前情提要

关于预装APK相关知识可参考

Android 源码编译如何确定模块安装的位置

Android O、P、Q 版本如何预装 APK

遇到问题

当我按照 Android O、P、Q 版本如何预装 APK 一文将 PMS 中 patch 回退,并在 Android.mk 中指定

LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) 输出到 data/app 目录下,编译后apk也确实位于

data/app/中,而且 userdata.img 大小也明显变大了,但是当烧写完成后,开机并不能正常启动,而是

自动进入了 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会没了,因为我们

预装app就在 data 分区下,恢复出厂将 data 分区格式化了,所以 app 没了,而且系统能正常开机了。那么看来问题

就在 data 分区上了,难道 AndroidQ 不允许将apk预装到 data 分区了吗?

解决办法

跳过 data 分区下 app 目录加密策略读取和设置即可

system/extras/libfscrypt/fscrypt_init_extensions.cpp

@@ -88,7 +88,7 @@ int fscrypt_set_directory_policy(const char* dir)"media","data", "user", "user_de","apex", "preloads", "app-staging",
-        "gsi",
+        "gsi","app",};std::string prefix = "/data/";for (const auto& d: directories_to_exclude) {if ((prefix + d) == dir) {LOG(INFO) << "Not setting policy on " << dir;return 0;}}return set_system_de_policy_on(dir);

分析过程

由上面的问题现象开始定位到 data 分区,问了朋友后说可能和分区格式有关系,userdata 改成f2sf才能内置东西,

于是照着 Android 如何将 data 分区格式由 ext4 转为 f2fs 一文修改后重新编译,烧写后发现问题依旧,还是提示

一样的问题,回厂进入系统后 adb shell 查看 data 分区格式确实已经变成 f2fs 了,这么说和 ext4、f2fs 没关系,但

如果需要过 GMS 的话,确实需要修改 data 格式为 f2fs。

好吧,看来这条路走不通了。那就只能启用终极奥义,看串口Log了,乘着硬件小哥飞串口线的时间,我们

先来把系统的串口 Log 打开。

kernel-4.9/kernel/printk/printk.c

@@ -75,7 +75,7 @@ module_param_named(disable_uart, printk_disable_uart, int, 0644);bool mt_get_uartlog_status(void){if (printk_disable_uart == 1)
-               return false;
+               return true;//false;else if ((printk_disable_uart == 0) || (printk_disable_uart == 2))return true;return true;
@@ -94,7 +94,7 @@ void mt_disable_uart(void){/* uart print not always enable */if ((mt_need_uart_console != 1) && (printk_disable_uart != 2))
-               printk_disable_uart = 1;
+               printk_disable_uart = 0;}void mt_enable_uart(void){

vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/mt_boot.c

@@ -1233,7 +1233,7 @@ int boot_linux_fdt(void *kernel, unsigned *tags,#endifcmdline_append("printk.disable_uart=0");else
-                               cmdline_append("printk.disable_uart=1");
+                               cmdline_append("printk.disable_uart=0");break;case BUILD_TYPE_USERDEBUG:
@@ -1243,13 +1243,13 @@ int boot_linux_fdt(void *kernel, unsigned *tags,#else(is_meta_log_disable() == 1))#endif
-                               cmdline_append("printk.disable_uart=1 slub_debug=O");
+                               cmdline_append("printk.disable_uart=0 slub_debug=O");#ifdef LOG_STORE_SUPPORTelse if (boot_ftrace && g_boot_arg->log_dynamic_switch == 0)#elseelse if (boot_ftrace)#endif
-                               cmdline_append("printk.disable_uart=1 slub_debug=-");
+                               cmdline_append("printk.disable_uart=0 slub_debug=-");elsecmdline_append("printk.disable_uart=0");break;
@@ -1257,7 +1257,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("printk.disable_uart=1 slub_debug=O");
+                               cmdline_append("printk.disable_uart=0 slub_debug=O");elsecmdline_append("printk.disable_uart=0 ddebug_query=\"file *mediatek* +p ; file *gpu* =_\"");break;

重新编译烧写开机得到如下串口日志

[   21.147710] <2>.(2)[1:init]init 15: Setting policy on /data/vendor
[   21.148630] <2>.(2)[1:init]init 15: Policy for /data/vendor set to 579af1fc730f2e34 modes 1/4
[   21.151349] <2>.(2)[1:init]init 19: ReapLogF PropSet [apexd.status]=[ready]21.147147 Done
[   21.152406] <2>.(2)[1:init]init 15: Not setting policy on /data/vendor_ce
[   21.154164] <2>.(2)[1:init]init 15: Not setting policy on /data/vendor_de
[   21.159953] <2>.(2)[1:init]init 3: Not setting policy on /data/data
[   21.162020] <2>.(2)[1:init]init 3: Setting policy on /data/app-private
[   21.163054] <2>.(2)[1:init]init 3: Policy for /data/app-private set to 579af1fc730f2e34 modes 1/4
[   21.165331] <2>.(2)[1:init]init 3: Setting policy on /data/app-ephemeral
[   21.166299] <2>.(2)[1:init]init 3: Policy for /data/app-ephemeral set to 579af1fc730f2e34 modes 1/4
[   21.169022] <2>.(2)[1:init]init 3: Setting policy on /data/app-asec
[   21.169960] <2>.(2)[1:init]init 3: Policy for /data/app-asec set to 579af1fc730f2e34 modes 1/4
[   21.172106] <2>.(2)[1:init]init 3: Setting policy on /data/app-lib
[   21.173001] <2>.(2)[1:init]init 3: Policy for /data/app-lib set to 579af1fc730f2e34 modes 1/4
[   21.176232] <2>.(2)[1:init]init 15: Setting policy on /data/app
[   21.177618] <2>.(2)[1:init]init 15: Failed to get encryption policy for /data/app: No data available
[   21.202980] <3>.(3)[384:logd.auditd]type=1400 audit(1262304028.716:5): avc: denied { associate } for comm="init" name="boot_boost" scontext=u:object_r:proc_perfmgr:s0 tcontext=u:object_r:proc:s0 tclass=filesystem permissive=1
[   21.205523] <3>.(3)[384:logd.auditd]type=1400 audit(1262304029.180:6): avc: denied { dac_override } for comm="ls" capability=1 scontext=u:r:toolbox:s0 tcontext=u:r:toolbox:s0 tclass=capability permissive=1
[   21.205797] <3>.(2)[1:init]init 15: Setting 579af1fc policy on /data/app failed!
[   21.205825] <3>.(2)[1:init]init 15: Rebooting into recovery
[   21.209288] <3>.(2)[1:init]init 15: Received sys.powerctl='reboot,recovery' from pid: 1 (/system/bin/init)
[   21.209678] <3>.(2)[1:init]init 3: ReapLogF PropSet [sys.powerctl]=[reboot,recovery]21.206530 Done
[   21.209689] <3>.(2)[1:init]init 15: Clear action queue and start shutdown trigger
[   21.209819] <3>.(2)[1:init]init 15: processing action (shutdown_done) from (<Builtin Action>:0)
[   21.209851] <3>.(2)[1:init]init 15: Reboot start, reason: reboot,recovery, rebootTarget: recovery
[   21.215330] <3>.(3)[384:logd.auditd]type=1400 audit(1262304029.180:6): avc: denied { dac_override } for comm="ls" capability=1 scontext=u:r:toolbox:s0 tcontext=u:r:toolbox:s0 tclass=capability permissive=1
[   21.217674] <3>.(3)[384:logd.auditd]type=1400 audit(1262304029.180:7): avc: denied { read } for comm="ls" name="app" dev="mmcblk0p36" ino=6 scontext=u:r:toolbox:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=1
[   21.220472] <3>.(3)[384:logd.auditd]type=1400 audit(1262304029.180:7): avc: denied { read } for comm="ls" name="app" dev="mmcblk0p36" ino=6 scontext=u:r:toolbox:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=1
[   21.223103] <3>.(3)[384:logd.auditd]type=1400 audit(1262304029.180:8): avc: denied { open } for comm="ls" path="/data/app" dev="mmcblk0p36" ino=6 scontext=u:r:toolbox:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=1
[   21.244124] <2>.(2)[1:init]init 3: ReapLogF PropSet [persist.sys.boot.reason]=[recovery]21.207330 Done
[   21.245320] <2>.(2)[1:init]init 15: Shutdown timeout: 6000 ms
[   21.246820] <2>.(2)[1:init]init 19: starting service 'blank_screen'...
[   21.251021] <2>.(2)[1:init]init 19: starting service 'light-hal-2-0'...
[   21.254702] <2>.(2)[1:init]init 19: terminating init services

找到其中关键日志 Rebooting into recovery,往上看到 Setting 579af1fc policy on /data/app failed!

嗯,和 data 相关的东西出现了。Failed to get encryption policy for /data/app: No data available

通过搜索 Failed to get encryption policy 找到文件 system/extras/libfscrypt/fscrypt.cpp


static bool fscrypt_policy_get(const char *directory, char *policy,size_t policy_length,int contents_encryption_mode,int filenames_encryption_mode) {....fscrypt_policy fp;memset(&fp, 0, sizeof(fscrypt_policy));if (ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &fp) != 0) {PLOG(ERROR) << "Failed to get encryption policy for " << directory;close(fd);log_ls(directory);return false;}close(fd);if ((fp.version != 0)|| (fp.contents_encryption_mode != contents_encryption_mode)|| (fp.filenames_encryption_mode != filenames_encryption_mode)|| (fp.flags !=fscrypt_get_policy_flags(filenames_encryption_mode))) {LOG(ERROR) << "Failed to find matching encryption policy for " << directory;return false;}memcpy(policy, fp.master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE);return true;
}

应该就是在这里打印的,简单看了下源码,和设置文件加密解密策略有关,开始看到了日志中

Rebooting into recovery 附近一堆 avc: denied,以为和 SELinux 权限有关系,就先挨个把权限都给

补上了,再次编译后开机,呵呵,还是一样的问题,不过日志中已经没有 avc: denied 相关字眼。再仔细品一品

串口日志,既然问题出在读取 /data/app encryption policy 上,那么是不是跳过 /data/app 就行了呢。

回到源码中看下调用流程

fscrypt_policy_get(fscrypt_policy_check()fscrypt_policy_get()

然鹅 fscrypt_policy_get() 的调用在 system/extras/libfscrypt/fscrypt_init_extensions.cpp

看到 fscrypt_set_directory_policy() 调用了 fscrypt_policy_get() ,在之前进行了 for 循环判断,如果

传递的文件目录在 vector 中则跳过读取检查,这正是我们所需要的,直接在 vector 中添加 app 目录。


int fscrypt_set_directory_policy(const char* dir)
{if (!dir || strncmp(dir, "/data/", 6)) {return 0;}// Special-case /data/media/obb per b/64566063if (strcmp(dir, "/data/media/obb") == 0) {// Try to set policy on this directory, but if it is non-empty this may fail.set_system_de_policy_on(dir);return 0;}// 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 makedirif (strchr(dir + 6, '/')) {return 0;}// 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/26641735std::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","app",};std::string prefix = "/data/";for (const auto& d: directories_to_exclude) {if ((prefix + d) == dir) {LOG(INFO) << "Not setting policy on " << dir;return 0;}}return set_system_de_policy_on(dir);
}static int set_system_de_policy_on(char const* dir) {std::string ref_filename = std::string("/data") + fscrypt_key_ref;std::string policy;if (!android::base::ReadFileToString(ref_filename, &policy)) {LOG(ERROR) << "Unable to read system policy to set on " << dir;return -1;}auto type_filename = std::string("/data") + fscrypt_key_mode;std::string modestring;if (!android::base::ReadFileToString(type_filename, &modestring)) {LOG(ERROR) << "Cannot read mode";}std::vector<std::string> modes = android::base::Split(modestring, ":");if (modes.size() < 1 || modes.size() > 2) {LOG(ERROR) << "Invalid encryption mode string: " << modestring;return -1;}LOG(INFO) << "Setting policy on " << dir;int result = fscrypt_policy_ensure(dir, policy.c_str(), policy.length(),modes[0].c_str(),modes.size() >= 2 ?modes[1].c_str() : "aes-256-cts");if (result) {LOG(ERROR) << android::base::StringPrintf("Setting %02x%02x%02x%02x policy on %s failed!",policy[0], policy[1], policy[2], policy[3], dir);return -1;}return 0;
}

重新编译烧写后成功开机的log,可以看到打印了跳过 /data/app/ 相关

[    7.101127] <0>.(0)[1:init]init 19: Not setting policy on /data/vendor_de
[    7.106596] <0>.(0)[1:init]init 19: Not setting policy on /data/data
[    7.109088] <0>.(0)[1:init]init 19: Setting policy on /data/app-private
[    7.110129] <0>.(0)[1:init]init 19: Policy for /data/app-private set to e2d0272afa66497a modes 1/4
[    7.112834] <0>.(0)[1:init]init 19: Setting policy on /data/app-ephemeral[    7.124062] <0>.(0)[1:init]init 3: Not setting policy on /data/app
[    7.126336] <0>.(0)[1:init]init 3: Setting policy on /data/property
[    7.127449] <0>.(0)[1:init]init 3: Found policy e2d0272afa66497a at /data/property which matches expected value

可能还存在的问题

我在 userdebug 版本下测试,烧写完成后第一次开机启动正常,app 都存在,再次重启后发现 data 下的 app 被卸载了,抓到对应的日志


2020-06-24 16:23:22.767 1144-1144/system_process V/PackageManager: reconcileAppsData for null u0 0x1 migrateAppData=true
2020-06-24 16:23:22.771 1144-1144/system_process W/PackageManager: Destroying /data/user_de/0/cn.cpe.contacts due to: com.android.server.pm.PackageManagerException: Package cn.cpe.contact is unknown
2020-06-24 16:23:22.780 1144-1144/system_process W/PackageManager: Destroying /data/user_de/0/cn.cpe.broswer due to: com.android.server.pm.PackageManagerException: Package cn.cpe.brosweris unknown
2020-06-24 16:23:22.944 1144-1144/system_process V/PackageManager: reconcileAppsData finished 31 packages
2020-06-24 16:23:23.068 1144-1144/system_process E/PackageManager: There should probably be a verifier, but, none were found
2020-06-24 16:23:25.260 1144-1144/system_process W/PackageManager: Destroying orphaned/data/app/CeContact
2020-06-24 16:23:25.270 1144-1144/system_process W/PackageManager: Destroying orphaned/data/app/CeBroswerPackageManager: System package cn.cpe.contact no longer exists; it's data will be wiped
2020-06-30 15:23:16.505 1126-1126/system_process W/PackageManager: System package cn.cpe.broswer no longer exists; it's data will be wiped

PackageManager 中重启后进行了再次检查

我在 user 版本下验证并未出现这个现象,所以就不再深究了,感兴趣的可以去找 PackageManagerService 对应位置分析

androidQ(10.0) 预装集成apk到data分区相关推荐

  1. 安卓10 linux内核,AndroidQ(10.0) 内核版本增加linux编译用户信息

    版本对比 O 版本设置界面中内核信息 Q 版本设置界面中内核信息 解决办法 frameworks\base\packages\SettingsLib\src\com\android\settingsl ...

  2. androidQ(10.0) 读取蓝牙设备当前电量并显示

    效果图 华为手机顶部状态栏 我们客制化后最终效果 实现步骤 1.获取蓝牙设备连接成功后的电量值 2.跟踪蓝牙图标显示流程 3.制作蓝牙带电量图标 4.获取电量后显示对应电量值图标 文件修改清单 ven ...

  3. AndroidQ(10.0) 预制客供壁纸和铃声

    预制客供壁纸 之前这个功能在 6.0 上修改过,已经是三年前了,之前壁纸选择还集成在 Launcher3 中,当时参考这篇 https://blog.csdn.net/jspping/article/ ...

  4. AndroidQ(10.0) 手机锁屏炫酷充电动画————html方案

    效果图 知识储备 1.WebView加载html,并通过JS传值 在网上随便搜索找到了这个炫酷的充电动画,可惜是css实现的,想在Android中使用那只能 通过 WebView 来加载了,要传递当前 ...

  5. AndroidQ(10.0) MTK平台添加新分区

    65 平台增加一个新分区,用于保存特殊数据,修改文件列表如下 modified: build/make/core/Makefilemodified: build/make/core/config.mk ...

  6. AndroidQ(10.0) 手机锁屏炫酷充电动画————lottie方案

    效果图 知识储备 1.Lottie动画使用指南 Lottie开源动画库介绍与使用示例 Android Lottie动画初探 Lottie动画免费下载网站 2.SystemUI 中引入AAR库编译 因为 ...

  7. android 10.0 禁止安装apk

    连接usb调试adb logcat | grep START 点击应用获取到包名后,去到对应路径对想要屏蔽的apk做判断,如果系统识别到pkgname1里的包名后返回无法安装报错 frameworks ...

  8. AndroidQ(10.0) Settings DatePick bug修改

    问题现象 上图展示的很清楚,在系统->日期和时间选项页面中,点击日期 Preference,左边的上一月显示都透出来了 修改历程 一开始觉得是 DatePick 系统控件出问题了吧,自己新建了a ...

  9. android11.0(R) data分区节点加密控制分析

    前情提要 androidQ(10.0) 预装集成apk到data分区 Android O.P.Q 版本如何预装 APK 遇到问题 当然是和之前一样啦,开机并不能正常启动,而是 自动进入了 recove ...

  10. Android 1.5 -10.0 都有哪些新特性?

    点击上方"开发者技术前线",选择"星标" 13:21 在看 真爱 本文部分整理 公众号 终端研发部 作者:嘟嘟呢 https://blog.csdn.net/u ...

最新文章

  1. jq修改iframe html代码,jQuery控制iFrame(实例代码)
  2. 成功者都在用的“成功咒语”
  3. 企业SpringBoot 教程(五)springboot整合beatlsql
  4. oracle cube 交叉分组,oracle的ROLLUP跟CUBE语句分组(转)
  5. iPhone/iPad/Android UI尺寸规范 手机尺寸
  6. 网易免费邮箱服务器,网易免费邮箱重新免费开放 POP3/SMTP 服务
  7. JScript服务器运行,jscript模拟的“控制台”程序Web服务器教程
  8. 技能分享:扩展名怎么修改?
  9. BPMN 2.0规范
  10. MySQL 系统自带的数据库有哪些?每个数据库的作用是什么?
  11. 计算机专业需要物理力学,读经典物理学和量子力学所想到的计算机哲学
  12. 用老虎机小例子理解Multi-armed Bandit Learning
  13. 银行卡信用卡号校验查询API接口
  14. 用于Transformer的6种注意力的数学原理和代码实现
  15. 汉语言专家级C1,汉语言文学专业审核(文科生均可参考)
  16. 力扣刷题之二叉树的层序遍历
  17. Unity Universal RP asset not assigned
  18. 再生龙制作u盘启动linux,再生龙制作U盘启动盘教程 | 楚盟博客
  19. Insar 课程学习
  20. python求三个数的最大值编程_python 判断三个数字中的最大值实例代码

热门文章

  1. idea导入项目出现乱码
  2. [裴礼文数学分析中的典型问题与方法习题参考解答]4.4.9
  3. Ubuntu18.04安装WPS
  4. nnie svp算法代码解读
  5. 黑科技神器-uTools,必须下载
  6. 京东商城java笔试_京东java笔试
  7. Mac投屏软件推荐duet
  8. 光猫(吉比特h2-2)超级用户名与密码
  9. 聚类算法之密度聚类方法
  10. 顺序表的基本操作(C语言实现,简单易懂!)