前情提要
遇到问题
当然是和之前一样啦,开机并不能正常启动,而是
自动进入了 recovery 界面,且界面显示
Can't load Android system. You'r data may be corrupt.If you continue to get this message, you may
need to perform a factory data reset and erase all user data stored on this devices.
按照提示我进行了恢复出厂操作,恢复出厂后能正常开机。但是预装的app没了,很明显预装app会没了。
按照之前 Q 版本的经验去修改代码后,问题依旧,还是不能正常开机,这就离谱,难道谷歌把这个地方给
堵死了???这还能难倒我么,上才艺。
解决办法
跳过 data 分区下 app 目录加密策略读取和设置即可
system/core/init/util.cpp
java
@@ -88,7 +88,7 @@ static FscryptAction FscryptInferAction(const std::string& dir)
// Special case various directories that must not be encrypted,
// often because their subdirectories must be encrypted.
// This isn't a nice way to do this, see b/26641735
std::vector<std::string> directories_to_exclude = {
"lost+found", "system_ce", "system_de", "misc_ce", "misc_de",
"vendor_ce", "vendor_de", "media", "data", "user",
- "user_de", "apex", "preloads", "app-staging", "gsi",
+ "user_de", "apex", "preloads", "app-staging", "gsi", "app",
};
for (const auto& d : directories_to_exclude) {
if ((prefix + d) == dir) {
return FscryptAction::kNone;
}
}
跳过 init.rc 中 /data/app 节点加密
system/core/rootdir/init.rc
java
+++ b/alps/system/core/rootdir/init.rc
@@ -658,7 +658,7 @@ on post-fs-data
mkdir /data/app-ephemeral 0771 system system encryption=Require
mkdir /data/app-asec 0700 root root encryption=Require
mkdir /data/app-lib 0771 system system encryption=Require
- mkdir /data/app 0771 system system encryption=Require
+ mkdir /data/app 0771 system system encryption=None
mkdir /data/property 0700 root root encryption=Require
mkdir /data/tombstones 0771 system system encryption=Require
mkdir /data/vendor/tombstones 0771 root root
分析过程
当然要打开串口 Log 记录呀,它又不是那么简单的。R 版本的串口打开修改地方如下
kernel-4.19\drivers\misc\mediatek\mtprintk\mtk_printk_ctrl.c
java
@@ -43,7 +43,7 @@ module_param_named(disable_uart, printk_ctrl, int, 0644);
bool mt_get_uartlog_status(void)
{
if (printk_ctrl == 1)
- return false;
+ return true;
else if ((printk_ctrl == 0) || (printk_ctrl == 2))
return true;
return true;
@@ -53,7 +53,7 @@ void mt_disable_uart(void)
{
/* uart print not always enable */
if (printk_ctrl != 2)
- printk_ctrl = 1;
+ printk_ctrl = 0;
}
EXPORT_SYMBOL_GPL(mt_disable_uart);
vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/mt_boot.c
java
@@ -1345,7 +1345,7 @@ int boot_linux_fdt(void *kernel, unsigned *tags,
#endif
cmdline_append("mtk_printk_ctrl.disable_uart=0");
else
- cmdline_append("mtk_printk_ctrl.disable_uart=1");
+ cmdline_append("mtk_printk_ctrl.disable_uart=0");
break;
case BUILD_TYPE_USERDEBUG:
@@ -1355,13 +1355,13 @@ int boot_linux_fdt(void *kernel, unsigned *tags,
#else
(is_meta_log_disable() == 1))
#endif
- cmdline_append("mtk_printk_ctrl.disable_uart=1 slub_debug=O");
+ cmdline_append("mtk_printk_ctrl.disable_uart=0 slub_debug=O");
#ifdef LOG_STORE_SUPPORT
else if (boot_ftrace && g_boot_arg->log_dynamic_switch == 0)
#else
else if (boot_ftrace)
#endif
- cmdline_append("mtk_printk_ctrl.disable_uart=1 slub_debug=-");
+ cmdline_append("mtk_printk_ctrl.disable_uart=0 slub_debug=-");
else
cmdline_append("mtk_printk_ctrl.disable_uart=0");
break;
@@ -1369,7 +1369,7 @@ int boot_linux_fdt(void *kernel, unsigned *tags,
case BUILD_TYPE_ENG:
if ((g_boot_mode == META_BOOT) && is_meta_log_disable &&
(is_meta_log_disable() == 1))
- cmdline_append("mtk_printk_ctrl.disable_uart=1 slub_debug=O");
+ cmdline_append("mtk_printk_ctrl.disable_uart=0 slub_debug=O");
else
cmdline_append("mtk_printk_ctrl.disable_uart=0 ddebug_query=\"file *mediatek* +p ; file *gpu* =_\"");
break;
重新编译烧写开机得到如下串口日志
java
[ 13.654157] <4>.(4)[1:init]init 21: [13623][0]Switched to default mount namespace
[ 13.655223] <4>.(4)[1:init]init 21: [13624][0]Not setting encryption policy on: /data/apex
[ 13.663218] <4>.(4)[1:init]init 21: [13632][0]Not setting encryption policy on: /data/app-staging
[ 13.666087] <4>.(4)[1:init]init 21: [13635][0]starting service 'apexd'...
) failed: No such file or directory
[ 13.677980] <4>.(4)[1:init]init 25: [13644][0]Encryption policy of /data/misc set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2
d input file '/data/misc/recovery/ro.build.fingerprint': open() failed: No such file or directory
ata/misc/recovery/proc/version': open() failed: No such file or directory
[ 13.692959] <7>.(7)[456:apexd]apexd: Scanning /system/apex for preinstalled data
[ 13.698614] <1>.(1)[456:apexd]apexd: Scanning /system_ext/apex for preinstalled data
[ 13.699725] <1>.(1)[456:apexd]apexd: ... does not exist. Skipping
path.utils.link]=[stopped]13507 [init.svc_debug_pid.mtk.plpath.utils.link]=[]13507 [dev.mnt.blk.data]=[dm-7]13509 [init.svc.apexd]=[running]13639 [ro.boottime.apexd]=[13638876462]13640 [init.svc_debug_pid.apexd]=[456]13641 Done
[ 13.700519] <1>.(1)[456:apexd]apexd: Scanning /product/apex for preinstalled data
[ 13.706583] <1>.(1)[456:apexd]apexd: ... does not exist. Skipping
[ 13.707396] <1>.(1)[456:apexd]apexd: Scanning /vendor/apex for preinstalled data
[ 13.708382] <1>.(1)[456:apexd]apexd: ... does not exist. Skipping
[ 13.709166] <1>.(1)[456:apexd]apexd: Populating APEX database from mounts...
[ 13.710720] <1>.(1)[456:apexd]apexd: 0 packages restored.
[ 13.711617] <1>.(1)[456:apexd]apexd: Marking APEXd as starting
[ 13.730259] <3>.(3)[1:init]init 25: [13698][0]Encryption policy of /data/local set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2
[ 13.745616] <1>.(1)[456:apexd]EXT4-fs (loop6): mounted filesystem without journal. Opts: (null)
[ 13.758344] <3>.(3)[1:init]init 25: [13727][0]Not setting encryption policy on: /data/preloads
[ 13.762309] <3>.(3)[1:init]init 25: [13730][0]Encryption policy of /data/vendor set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2
[ 13.764161] <3>.(3)[1:init]init 25: [13733][0]Not setting encryption policy on: /data/vendor_ce
[ 13.766555] <3>.(3)[1:init]init 25: [13735][0]Not setting encryption policy on: /data/vendor_de
[ 13.773079] <3>.(3)[1:init]init 25: [13742][0]Not setting encryption policy on: /data/data
[ 13.776787] <1>.(1)[456:apexd]EXT4-fs (loop7): mounted filesystem without journal. Opts: (null)
[ 13.777475] <3>.(3)[1:init]init 21: [13745][0]Encryption policy of /data/app-private set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2
[ 13.781923] <0>.(0)[1:init]init 21: [13749][0]Encryption policy of /data/app-ephemeral set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2
[ 13.785340] <0>.(0)[1:init]init 21: [13753][0]Encryption policy of /data/app-asec set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2
[ 13.788729] <0>.(0)[1:init]init 21: [13756][0]Encryption policy of /data/app-lib set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2
[ 13.790485] <0>.(0)[1:init]init 21: [13759][0]Inferred action different from explicit one, expected 0 but got 2
[ 13.792434] <0>.(0)[1:init]init 21: [13759][0]Failed to set encryption policy of /data/app to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2: Directory not empty
:s0 tclass=file permissive=1
[ 13.800279] <2>.(2)[1:init]ls 21: [13759][0]executing ls failed: No such file or directory
[ 13.800313] <2>.(1)[462:init]logwrapper 21: executing ls failed: No such file or directory
[ 13.800321] <2>.(1)[462:init]logwrapper 21:
[ 13.805673] <2>.(2)[1:init]ls 21: [13759][0]ls terminated by exit(255)
[ 13.806716] <2>.(2)[1:init]init: 1 output lines suppressed due to ratelimiting
[ 13.807641] <2>.(2)[1:init]init 25: [13759][0]ls -laZ /data/app returned failure: 255
[ 13.808723] <2>.(2)[1:init]init 25: [13759][0]Setting d27f72eaf61213e463b2a9ec48dae65d policy on /data/app failed!
[ 13.809210] <0>.(0)[456:apexd]EXT4-fs (loop8): mounted filesystem without journal. Opts: (null)
[ 13.810098] <2>.(2)[1:init]init 25: [13759][0]Rebooting into recovery
和原来还是一样的配方,错误提示
Failed to set encryption policy of /data/app to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2: Directory not empty
R 版本上谷歌对 libfscrypt 这块进行了重构,代码移到了 system/core/init/util.cpp 中
现在来看下整体的流程,切入点从 init.rc 开始
mkdir /data/app 0771 system system encryption=Require
相比较 Q 版本的 init.rc R 多出了 encryption=Require 属性,就是这个属性决定了 boot
阶段需要检查文件加密情况。mkdir 指令应该调用 builtins 中 do_mkdir(args) 方法
system\core\init\builtins.cpp
java
// mkdir <path> [mode] [owner] [group] [<option> ...]
static Result<void> do_mkdir(const BuiltinArguments& args) {
auto options = ParseMkdir(args.args);
if (!options.ok()) return options.error();
return make_dir_with_options(*options);
}
static Result<void> make_dir_with_options(const MkdirOptions& options) {
std::string ref_basename;
if (options.ref_option == "ref") {
ref_basename = fscrypt_key_ref;
} else if (options.ref_option == "per_boot_ref") {
ref_basename = fscrypt_key_per_boot_ref;
} else {
return Error() << "Unknown key option: '" << options.ref_option << "'";
}
struct stat mstat;
if (lstat(options.target.c_str(), &mstat) != 0) {
if (errno != ENOENT) {
return ErrnoError() << "lstat() failed on " << options.target;
}
if (!make_dir(options.target, options.mode)) {
return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << options.target;
}
if (lstat(options.target.c_str(), &mstat) != 0) {
return ErrnoError() << "lstat() failed on new " << options.target;
}
}
if (!S_ISDIR(mstat.st_mode)) {
return Error() << "Not a directory on " << options.target;
}
bool needs_chmod = (mstat.st_mode & ~S_IFMT) != options.mode;
if ((options.uid != static_cast<uid_t>(-1) && options.uid != mstat.st_uid) ||
(options.gid != static_cast<gid_t>(-1) && options.gid != mstat.st_gid)) {
if (lchown(options.target.c_str(), options.uid, options.gid) == -1) {
return ErrnoError() << "lchown failed on " << options.target;
}
// chown may have cleared S_ISUID and S_ISGID, chmod again
needs_chmod = true;
}
if (needs_chmod) {
if (fchmodat(AT_FDCWD, options.target.c_str(), options.mode, AT_SYMLINK_NOFOLLOW) == -1) {
return ErrnoError() << "fchmodat() failed on " << options.target;
}
}
if (fscrypt_is_native()) {
if (!FscryptSetDirectoryPolicy(ref_basename, options.fscrypt_action, options.target)) {
return reboot_into_recovery(
{"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target});
}
}
return {};
}
可以看到其中调用 ParseMkdir(args.args) 获取 options,然后根据 options 创建文件夹,
如果过程中没遇到问题,则 return {} 可以看到出问题的时候进入 recovery 界面,应该是走的
reboot_into_recovery( {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target})
那么来看下 FscryptSetDirectoryPolicy() 方法是如何判断的
system\core\init\fscrypt_init_extensions.cpp
java
bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
const std::string& dir) {
if (action == FscryptAction::kNone) {
return true;
}
if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
return true;
}
if (action == FscryptAction::kDeleteIfNecessary) {
LOG(ERROR) << "Setting policy failed, deleting: " << dir;
delete_dir_contents(dir);
return SetPolicyOn(ref_basename, dir);
}
return false;
}
可以看到要想不进入 recovery 界面,action 为 FscryptAction::kNone 即可,也就是跳过
action 的取值 options.fscrypt_action,回到 builtins.cpp 中关注 auto options = ParseMkdir(args.args);
system\core\init\util.cpp
java
Result<MkdirOptions> ParseMkdir(const std::vector<std::string>& args) {
mode_t mode = 0755;
Result<uid_t> uid = -1;
Result<gid_t> gid = -1;
//第一次赋值 fscrypt_action,FscryptInferAction() 和之前一样有白名单可跳过
FscryptAction fscrypt_inferred_action = FscryptInferAction(args[1]);
FscryptAction fscrypt_action = fscrypt_inferred_action;
std::string ref_option = "ref";
bool set_option_encryption = false;
bool set_option_key = false;
for (size_t i = 2; i < args.size(); i++) {
switch (i) {
case 2:
mode = std::strtoul(args[2].c_str(), 0, 8);
break;
case 3:
uid = DecodeUid(args[3]);
if (!uid.ok()) {
return Error()
<< "Unable to decode UID for '" << args[3] << "': " << uid.error();
}
break;
case 4:
gid = DecodeUid(args[4]);
if (!gid.ok()) {
return Error()
<< "Unable to decode GID for '" << args[4] << "': " << gid.error();
}
break;
default:
auto parts = android::base::Split(args[i], "=");
if (parts.size() != 2) {
return Error() << "Can't parse option: '" << args[i] << "'";
}
auto optname = parts[0];
auto optval = parts[1];
//第二次赋值 fscrypt_action,根据 optval 值再次判断
//这里增加 log 打印后发现 optname = encryption optval = Require/None 在init.rc中配置
if (optname == "encryption") {
if (set_option_encryption) {
return Error() << "Duplicated option: '" << optname << "'";
}
if (optval == "Require") {
fscrypt_action = FscryptAction::kRequire;
} else if (optval == "None") {
fscrypt_action = FscryptAction::kNone;
} else if (optval == "Attempt") {
fscrypt_action = FscryptAction::kAttempt;
} else if (optval == "DeleteIfNecessary") {
fscrypt_action = FscryptAction::kDeleteIfNecessary;
} else {
return Error() << "Unknown encryption option: '" << optval << "'";
}
set_option_encryption = true;
} else if (optname == "key") {
if (set_option_key) {
return Error() << "Duplicated option: '" << optname << "'";
}
if (optval == "ref" || optval == "per_boot_ref") {
ref_option = optval;
} else {
return Error() << "Unknown key option: '" << optval << "'";
}
set_option_key = true;
} else {
return Error() << "Unknown option: '" << args[i] << "'";
}
}
}
if (set_option_key && fscrypt_action == FscryptAction::kNone) {
return Error() << "Key option set but encryption action is none";
}
const std::string prefix = "/data/";
if (StartsWith(args[1], prefix) &&
args[1].find_first_of('/', prefix.size()) == std::string::npos) {
if (!set_option_encryption) {
LOG(WARNING) << "Top-level directory needs encryption action, eg mkdir " << args[1]
<< " <mode> <uid> <gid> encryption=Require";
}
if (fscrypt_action == FscryptAction::kNone) {
LOG(INFO) << "Not setting encryption policy on: " << args[1];
}
}
if (fscrypt_action != fscrypt_inferred_action) {
LOG(WARNING) << "Inferred action different from explicit one, expected "
<< static_cast<int>(fscrypt_inferred_action) << " but got "
<< static_cast<int>(fscrypt_action);
}
//构建 options 返回
return MkdirOptions{args[1], mode, *uid, *gid, fscrypt_action, ref_option};
}
static FscryptAction FscryptInferAction(const std::string& dir) {
const std::string prefix = "/data/";
if (!android::base::StartsWith(dir, prefix)) {
return FscryptAction::kNone;
}
// Special-case /data/media/obb per b/64566063
if (dir == "/data/media/obb") {
// Try to set policy on this directory, but if it is non-empty this may fail.
return FscryptAction::kAttempt;
}
// Only set policy on first level /data directories
// To make this less restrictive, consider using a policy file.
// However this is overkill for as long as the policy is simply
// to apply a global policy to all /data folders created via makedir
if (dir.find_first_of('/', prefix.size()) != std::string::npos) {
return FscryptAction::kNone;
}
// Special case various directories that must not be encrypted,
// often because their subdirectories must be encrypted.
// This isn't a nice way to do this, see b/26641735
std::vector<std::string> directories_to_exclude = {
"lost+found", "system_ce", "system_de", "misc_ce", "misc_de",
"vendor_ce", "vendor_de", "media", "data", "user",
"user_de", "apex", "preloads", "app-staging", "gsi",
};
//在 directories_to_exclude 集合中则跳过
for (const auto& d : directories_to_exclude) {
if ((prefix + d) == dir) {
return FscryptAction::kNone;
}
}
// Empty these directories if policy setting fails.
std::vector<std::string> wipe_on_failure = {
"rollback", "rollback-observer", // b/139193659
"connsyslog", "debuglogger", "ramdump",
"mdlog", "log_temp", "aee_exp", "mdl",
};
for (const auto& d : wipe_on_failure) {
if ((prefix + d) == dir) {
return FscryptAction::kDeleteIfNecessary;
}
}
return FscryptAction::kRequire;
}
可以看到这样正常的流程就走完了,接下来看下错误的流程
回到 fscrypt_init_extensions.cpp 中
java
bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
const std::string& dir) {
if (action == FscryptAction::kNone) {
return true;
}
if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
return true;
}
if (action == FscryptAction::kDeleteIfNecessary) {
LOG(ERROR) << "Setting policy failed, deleting: " << dir;
delete_dir_contents(dir);
return SetPolicyOn(ref_basename, dir);
}
return false;
}
static bool SetPolicyOn(const std::string& ref_basename, const std::string& dir) {
EncryptionPolicy policy;
if (!LookupPolicy(ref_basename, &policy)) return false;
if (!EnsurePolicyOrLog(policy, dir)) return false;
return true;
}
static bool EnsurePolicyOrLog(const EncryptionPolicy& policy, const std::string& dir) {
if (!EnsurePolicy(policy, dir)) {
std::string ref_hex;
BytesToHex(policy.key_raw_ref, &ref_hex);
LOG(ERROR) << "Setting " << ref_hex << " policy on " << dir << " failed!";
return false;
}
return true;
}
最终调用到 system\extras\libfscrypt\fscrypt.cpp
java
bool EnsurePolicy(const EncryptionPolicy& policy, const std::string& directory) {
union {
fscrypt_policy_v1 v1;
fscrypt_policy_v2 v2;
} kern_policy;
memset(&kern_policy, 0, sizeof(kern_policy));
switch (policy.options.version) {
case 1:
if (policy.key_raw_ref.size() != FSCRYPT_KEY_DESCRIPTOR_SIZE) {
LOG(ERROR) << "Invalid key descriptor length for v1 policy: "
<< policy.key_raw_ref.size();
return false;
}
// Careful: FSCRYPT_POLICY_V1 is actually 0 in the API, so make sure
// to use it here instead of a literal 1.
kern_policy.v1.version = FSCRYPT_POLICY_V1;
kern_policy.v1.contents_encryption_mode = policy.options.contents_mode;
kern_policy.v1.filenames_encryption_mode = policy.options.filenames_mode;
kern_policy.v1.flags = policy.options.flags;
policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v1.master_key_descriptor),
FSCRYPT_KEY_DESCRIPTOR_SIZE);
break;
case 2:
if (policy.key_raw_ref.size() != FSCRYPT_KEY_IDENTIFIER_SIZE) {
LOG(ERROR) << "Invalid key identifier length for v2 policy: "
<< policy.key_raw_ref.size();
return false;
}
kern_policy.v2.version = FSCRYPT_POLICY_V2;
kern_policy.v2.contents_encryption_mode = policy.options.contents_mode;
kern_policy.v2.filenames_encryption_mode = policy.options.filenames_mode;
kern_policy.v2.flags = policy.options.flags;
policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v2.master_key_identifier),
FSCRYPT_KEY_IDENTIFIER_SIZE);
break;
default:
LOG(ERROR) << "Invalid encryption policy version: " << policy.options.version;
return false;
}
android::base::unique_fd fd(open(directory.c_str(), O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
if (fd == -1) {
PLOG(ERROR) << "Failed to open directory " << directory;
return false;
}
bool already_encrypted = fscrypt_is_encrypted(fd);
// FS_IOC_SET_ENCRYPTION_POLICY will set the policy if the directory is
// unencrypted; otherwise it will verify that the existing policy matches.
// Setting the policy will fail if the directory is already nonempty.
if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, &kern_policy) != 0) {
std::string reason;
switch (errno) {
case EEXIST:
reason = "The directory already has a different encryption policy.";
break;
default:
reason = strerror(errno);
break;
}
LOG(ERROR) << "Failed to set encryption policy of " << directory << " to "
<< PolicyDebugString(policy) << ": " << reason;
if (errno == ENOTEMPTY) {
log_ls(directory.c_str());
}
return false;
}
if (already_encrypted) {
LOG(INFO) << "Verified that " << directory << " has the encryption policy "
<< PolicyDebugString(policy);
} else {
LOG(INFO) << "Encryption policy of " << directory << " set to "
<< PolicyDebugString(policy);
}
return true;
}
重新编译烧写后成功开机的log,可以看到打印了跳过 /data/app/ 相关
java
[ 14.186668] <0>.(0)[1:init]init 16: [14155][0]ccz ParseMkdir encryption policy on: /data/app-lib
[ 14.187866] <0>.(0)[1:init]init 16: [14155][0]ccz ParseMkdir encryption optname: encryption
[ 14.189007] <0>.(0)[1:init]init 19: [14155][0]ccz ParseMkdir encryption optval: Require
[ 14.191729] <0>.(0)[1:init]init 19: [14155][0]Encryption policy of /data/app-lib set to ef2067add1858706a84cc01d25260ea5 v2 modes 1/4 flags 0x2
[ 14.193467] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption policy on: /data/app
[ 14.194557] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption optname: encryption
[ 14.195651] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption optval: None
[ 14.196637] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption hook:
[ 14.197555] <0>.(0)[1:init]init 19: [14162][0]Not setting encryption policy on: /data/app
[ 14.198574] <5>.(5)[317:init]init 16: [14167][200]ReapLogT PropSet [apexd.status]=[starting]13967 Done
[ 14.198737] <0>.(0)[1:init]init 19: [14167][0]ccz ParseMkdir encryption policy on: /data/property
[ 14.200913] <0>.(0)[1:init]init 19: [14167][0]ccz ParseMkdir encryption optname: encryption
[ 14.201996] <0>.(0)[1:init]init 25: [14167][0]ccz ParseMkdir encryption optval: Require
[ 14.204488] <0>.(0)[1:init]init 25: [14167][0]Encryption policy of /data/property set to ef2067add1858706a84cc01d25260ea5 v2 modes 1/4 flags 0x2
[ 14.206220] <0>.(0)[1:init]init 25: [14175][0]ccz ParseMkdir encryption policy on: /data/tombstones
[ 14.207437] <0>.(0)[1:init]init 25: [14175][0]ccz ParseMkdir encryption optname: encryption
[ 14.208516] <0>.(0)[1:init]init 25: [14175][0]ccz ParseMkdir encryption optval: Require
[ 14.211116] <0>.(0)[1:init]init 25: [14175][0]Encryption policy of /data/tombstones set to ef2067add1858706a84cc01d25260ea5 v2 modes 1/4 flags 0x2
[ 14.212936] <0>.(0)[1:init]init 25: [14181][0]ccz ParseMkdir encryption policy on: /data/vendor/tombstones
[ 14.215671] <0>.(0)[1:init]init 25: [14184][0]ccz ParseMkdir encryption policy on: /data/vendor/tombstones/wifi
关于 init.rc 启动可以参考下面