Android P版本。
第一步尝试:PMS增加扫描安装,【最终不符合需求】:
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4f09f6e..e6f2f19 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2652,6 +2652,14 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_SYSTEM,
0);
+ final File preloadAppDir = new File(Environment.getRootDirectory(), "preloadapp");
+ scanDirTracedLI(preloadAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM,
+ 0);
+
// Collect privileged vendor packages.
File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
测试如下:将ES文件管理器放到下面目录,上面代码修改之后,m services后替换services各组件,然后重启服务,之后能看到launcher中存在ES文件管理器,且能正常使用。
/system/preloadapp/cs/es-file-explorer-4-2-6-2-1.apk
替换services各组件命令:
adb root
adb remount
adb push X:\system\framework\oat\arm64\services.vdex /system/framework/oat/arm64/
adb push X:\system\framework\oat\arm64\services.odex /system/framework/oat/arm64/
adb push X:\system\framework\oat\arm64\services.art /system/framework/oat/arm64/
adb push X:\system\framework\services.jar.prof /system/framework/
adb push X:\system\framework\services.jar /system/framework/
adb shell sync
adb shell stop
adb shell start
结论:无法卸载,卸载需要使用SCAN_AS_PRIVILEGED,但测试高德地图车机版时,会出现
java.lang.UnsatisfiedLinkError异常:
08-27 09:42:30.441: W/System.err(3124): Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/system/preloadapp/AutoLite.apk"],nativeLibraryDirectories=[/data/app-lib/AutoLite, /system/lib64, /vendor/lib64]]] couldn't find "libdumpcrash.so"
第二步尝试:着手解决UnsatisfiedLinkError异常
根据网络上的解决方式,如:https://www.codeleading.com/a...,在预置apk的时候,通过LOCAL_PREBUILT_JNI_LIBS将apk解压缩出来的lib库都预置到/xxx/AutoLite/lib/arm下(此apk为高德地图车机版,官网下载下来的apk中只有armeabi-v7a的lib库)
测试结果:
08-26 17:19:22.733: W/System.err(3437): Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/vendor/app/AutoLite/AutoLite.apk"],nativeLibraryDirectories=[/vendor/app/AutoLite/lib/arm64, /system/lib64, /vendor/lib64, /system/lib64, /vendor/lib64]]] couldn't find "libdumpcrash.so"
上述log显示会到AutoLite/lib/arm64下面去寻找so,实际so都在AutoLite/lib/arm下面。
这块逻辑待查。
最终解决方案:
不同签名方式的apk,以不同方式预置到/system/preloadapp目录,同时准备一个shell脚本,在开机过程中将/system/preloadapp目录下的apks拷贝到/data/app,再解决掉开机过程中shell脚本的启动问题即可。
下面给出本地的修改,基于Android P方案完成:
查看apk签名方式:
ES文件管理器:
E:\AndroidSDK\build-tools\29.0.0\lib>java -jar apksigner.jar verify -v d:\downloads\es-file-explorer-4-2-6-2-1.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): false
Verified using v3 scheme (APK Signature Scheme v3): false
Number of signers: 1
高德地图车机版(罪魁祸首是也)
E:\AndroidSDK\build-tools\29.0.0\lib>java -jar apksigner.jar verify -v d:\downloads\Auto_V5.3.0.600050_release_signed.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false
Number of signers: 1
V1签名apk预置:
拷贝需要预置的apk到android/vendor/xxx/packages/apps/3rd-party/目录,如ES文件管理器,apk为EsFile.apk
修改:android/vendor/xxx/packages/apps/3rd-party/Android.mk
使用prebuilt的方式,将所需要的apk集成到/system/preloadapp下。
include $(CLEAR_VARS)
LOCAL_MODULE := EsFile
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_DEX_PREOPT := false
LOCAL_MODULE_PATH := $(TARGET_OUT)/preloadapp
include $(BUILD_PREBUILT)
V2签名apk预置:
拷贝需要预置的apk到android/vendor/xxx/packages/apps/3rd-party/目录,如高德地图车机版AutoLite.apk
修改:android/vendor/xxx/packages/apps/3rd-party/Android.mk
该apk会直接拷贝到/system/preloadapp目录,如有新增的apk,根据apk名字,新增一条$(shell cp $(LOCAL_PATH)/AutoLite.apk $(TARGET_OUT)/preloadapp/AutoLite)命令即可
$(info "copy V2 signed apks")
$(shell mkdir $(TARGET_OUT)/preloadapp/AutoLite)
$(shell cp $(LOCAL_PATH)/AutoLite.apk $(TARGET_OUT)/preloadapp/AutoLite)
/system/preloadapp下面的apk,在开机过程中,会由shell脚本copy_apps从/system/preloadapp拷贝到/data/app目录之后,由PMS进行安装处理。
新增apk集成到系统:
根据板卡配置,修改android/device/xxx/<board_type>/ja310_qh.mk,通过PRODUCT_PACKAGES += EsFile,将EsFile.apk编译到system.img
注意,V2签名的apk的copy脚本,是直接内置于EsFile.apk的编译目标定义部分之内的,客户可以根据自身需求,酌情进行修改。或者根据自己的目录规划进行调整,目的是将这类apk拷贝到/system/preloadapp目录即可,无须拘泥于特定拷贝方式。
copy_apps脚本:
该脚本作用是在开机过程中执行拷贝动作(条件满足时),将/system/preloadapp下的apk都拷贝至/data/app目录。
脚本路径:android/device/xxx/common/rootdir/etc/copy_apps.sh
脚本内容如下:
#!/system/bin/sh
if [ ! -f /data/app/did ]; then
chmod 777 /data/app/
cp -rf /system/preloadapp/* /data/app/
echo 1 > /data/app/did
chmod -R 777 /data/app/*
fi
脚本集成:
diff --git a/device.mk b/device.mk
PRODUCT_COPY_FILES += device/xxx/common/rootdir/etc/copy_apps.sh:system/bin/copy_apps.sh
copy_apps脚本启动:
在init.xxx.rc中配置copy_apps脚本启动方式:android/device/xxx/common/rootdir/etc/init.xxx.rc
init.xxx.rc修改之后,可以通过m bootimage编译boot.img后替换进行验证。
+on post-fs-data
+ start copy-apps
+
+
+#add for pre install apps
+service copy-apps /system/bin/copy_apps.sh
+ user system
+ group system
+ oneshot
+ disabled
脚本selinux权限验证:
android/device/xxx/sepolicy/common/copy_apps.te
type copy_apps, domain;
type copy_apps_exec, exec_type, file_type;
init_daemon_domain(copy_apps)
permissive copy_apps;
android/device/xxx/sepolicy/common/file_contexts
diff --git a/common/file_contexts b/common/file_contexts
+/system/bin/copy_apps.sh u:object_r:copy_apps_exec:s0
PMS中放开对/data/app的扫描处理:
revert掉commit 02cecae02901c86334e09b162c09a6e99187f171在PMS中的改动,这条改动限制了data/app下的apk安装,如下:
commit 02cecae02901c86334e09b162c09a6e99187f171
Author: Todd Kennedy <toddke@google.com>
Date: Fri Sep 8 14:27:16 2017 -0700
Don't install package if it's required to be known
During package scaning, we can require packages to be known. This
allows us to determine if an install was interrupted by checking
the previously known path with the current scanned path. However,
if the package wasn't known at all, we allowed the newly scanned
package to be installed. Instead, these completely unknown
packages should be removed as incomplete installs.
One side effect of the existing code is when new apps randomly
appear on /data/app, they will be installed. This is not behaviour
we want to support. Instead, applications should always be
installed through "adb install".
Change-Id: I3169482ab9ead252c0e91b415fa4da056abeed4a
Fixes: 65162907
Test: Manual
Test: cherry-pick ag/2863255
Test: adb install Foo.apk
Test: adb shell setprop fw.poke com.android.foo
Test: adb shell stop && adb shell start
Test: see entries in persistent package manager logs for removing app & data [adb shell dumpsys package messages]
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bafcad4..71d3d9a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11394,6 +11394,10 @@ public class PackageManagerService extends IPackageManager.Stub
+ " but expected at " + known.codePathString
+ "; ignoring.");
}
+ } else {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+ "Application package " + pkg.packageName
+ + " not found; ignoring.");
}
}
碰到的问题:
- UnsatisfiedLinkError异常,至今未能正向解决,这条道不通
shell脚本未能正常执行,adb shell下手动执行脚本时出现如下问题:
xxxxx:/system/bin # ./copy_apps.sh /system/bin/sh: ./copy_apps.sh: No such file or directory
这个是因为sh脚本格式问题,奶奶个腿儿,坑死人不偿命,百度一下,随处都是解决方案:https://blog.csdn.net/u013626...
- init.rc中无法启动shell脚本,这里碰到的问题就多了,先是init进程log跑着跑着没有了,后来发现是之前on init中write /proc/sys/kernel/printk "4 4 1 7"导致的,临时去掉这个,有log后,发现没有看到start service copy_apps的log,这里是因为启动service时机太早了,要找到data正常mount之后,且data/app目录生成之后再触发服务启动,但是又不能太晚,因为希望PMS启动的时候能扫描/data/app目录,所以可以看到最终的触发时机是on post-fs-data
鸣谢:
init.rc中启动shell脚本:https://blog.csdn.net/Sunxiao...
预装apk:https://www.codeleading.com/a...
预装apk:https://blog.csdn.net/a462533...
预装apk:https://www.jianshu.com/p/894...
预装apk:https://www.daimajiaoliu.com/...
预装apk:https://www.cnblogs.com/cengj...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。