1.原始方案:
1.创建 “/system/third_app”文件夹
2. 预置第三方APP的Android.mk 中 LOCAL_MODULE_PATH = “/system/third_app”
3. PKMS 源码中添加 copy 代码:
(1): isFirstBoot() 判断第一次开机之后;
(2):scanDirLI() 扫描app之前
(3): copy 的路径是 “/system/third_app” ---> "/data/app"
----:question : PKMS 扫描/system/app 和 /data/app 下的应用的区别在于调用scaDirLI()时,/system/app 会传下去“PackageParser.PARSE_IS_SYSTEM” 的parseFlag 而/data/app 传下去的parseFlag 是null
-----: 直接调用FileUtils.copyFile 进行copy
缺点:
1.copy到data/app下会有两份apk,占空间;
2.采用异步copy ,如果很大的apk ,则调用到扫描/data/app时 ,还没copy 完成;
优点:
1.恢复出场设置后,third_app 是在/system 下的,仍然会扫描重新安装
*优化思路*
1.PKMS 2 个成员变量
1.1 PKMS.mSettings :维护/data/system/package.xml 文件,最后扫描的结果存放在 PKMS.mSettings.mPackage<PackageSettings> 这个arrayList 数组中;
1.2 PKMS.mPackages :维护记录当前PKMS 动态pkg 的信息,保存在PKMS.mPackages<PackageParser.package> 这个arrayList 数组中;
2. /system/app 或者/system/priv-app 为什么不可以被删除?
因为 PKMS 调用scanDirLI 扫描“/system/app” 和 “/system/priv-app” 这两个路径时,下发了SYSTEM_APP的parserFlag,此flag表示此APP 为系统APP ,删除时会检查此flag,有此flag不可以删除;
3. 定制APP ,必须放在/system 下面:
scanDirLI 时如果下发SYSTEM_APP,不能删除;
scanDirLI 时如果不下发SYSTEM_APP,则生成的lib库文件 和dex 文件都在/system 路径下,要访问此路径,必须是system_app ,不然没有权限(APP 获取自己的数据存储路径,写的时候selinux denied)
4. lib ,dex 文件路径
4.1 lib 库
PKMS.scanDirLI -->PKMS.scanPackageDirtyLI() --> PKMS.setNativeLibraryPaths() 函数确当lib 库路径 , 很重要的逻辑:如果扫描的是一个apk文件,就会pkg 的lib_path = /data/app-lib/<packagename>/lib , 如果传下去的是以“packagename”命名的文件夹,文件夹下有此pakcage,就会直接在“/system/app/<packagename>”下生成/lib/XXX.so 文件
4.2 dex 文件
(预编译的问题 :
1.正常情况是开机扫描,copy pkg 的dex 文件 到/data/dalvik-cache ----> 耗时;
2.在BoardConfig.mk 中开启 WITH_DEXPREOPT := true 这个宏,会直接在/system/third_app/<packagename>/oat/ 下生成dex 文件,然后进行拷贝到/data/dalvik-cache 时 selinux 异常 , 部分不拷贝到/data/dalvik 下面 , 异常 ... ..
解决方法: /system/third_app/ 下APP 的Android.mk 上 LOCAL_DEX_PREOPT = false)
PKMS.scanDirLI -->PKMS.scanPackageDirtyLI() -->PackageDexOptimizer.performDexOpt -->Installer -->Installd.dexopt ,逻辑和lib 库一样,传下去的是apk位置,就在/data/dalvik-cache/ 下 生成dex 文件;
5. PKMS 扫描/system/third_app时,传下去的是apk源文件的位置,而不是apk所在文件夹的位置
1.增加PKMS.mVendorSettings 负责维护/data/system/custom-packages.xml ,此文件记录所有PKMS维护的pkg 中标记为vendor 的pkg,存放在PKMS.mSettings<VendorPackageSettings>;
2.增加PKMS.mVendorPackage<PackageParser.package>, 记录PKMS 中/system/third_app/下app 的信息
3.PKMS 初始化时,scanDirLI “/system/third_app” 时 ,传下区的parserFlag = VendorPackage (在PackageParser.java 中添加)
4.PKMS 流程中,所有对mSetting.mPackages 和PKMS.mPackages 进行更新时,同时对mVendorSetting.mPackages 和PKMS.mVendorPackages 进行更新
6.删除apk 处理
/system/third_app 下是非system app ,所以可以走正常的删除流程,但是:
1.removePackageDataLI 函数中进行删除源文件时,检查Vendor_app 的flag ,如果是则不进行源文件的删除,删除lib库,oat文件 等等;
2.PKMS.mVendorSetting.mVendorPackages<vendroPackageSetting> 对象中,mIntallStatus 变量设置为false ,表示被删除;
3.PKMS.scanDirLI 扫描/system/third_app 时,监听mIntallStatus ,false 则不扫描;
4. PKMS 扫描完会同步PKMS.mPackage -> PKMS.mSettings -> /data/system/package.xml 上。
7.最后的结果
1./systen/third_app 中的apk 可以正常卸载;
2.恢复出场设置后,/system/third_app 重新安装;
*****
应用放在/system/third_app/<PackageName>/XXXX.apk
则扫描时 生成的lib库文件 和 dex 文件的路径就在/system/third_app/<PackageName>/lib/**** 和 /system/third_app/<PackageName>/oat/**** 都是在/system 下面,但是scanDirLI时 没有传SYSTEM_APP 的 parser_flag,所以系统不认为其为system_app ,这个app 的进程就无法访问/system 下的文件。
所以处理方法为,创建lib 和 dex 文件时,扫描的是直接为XXXX.apk 文件 ,而不是system/third_app/<PackageName>/ 这个目录,这样生成的lib 库 和 dex 文件 就不在/system 下 ,而是在/data 下