[RK3288][Android6.0] 调试笔记 --- 系统自带预置第三方APK方法

来源:互联网 发布:淘宝女装店背景图 编辑:程序博客网 时间:2024/05/16 07:29

Platform: RK3288
OS: Android 6.0
Kernel: 3.10.92

Rockchip默认提供了机制来预置第三方APK, 方法很简单:
1. 在device/rockchip/rk3288创建preinstall目录(如果要可卸载,那就创建preinstall_del目录)
2. 将你要预安装的APK放进此目录即可

下面看下实现原理过程:
device/rockchip/common/device.mk中有:

ifneq ($(strip $(TARGET_DEVICE)), )    TARGET_DEVICE_DIR=$(shell test -d device && find device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk')    TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(TARGET_DEVICE_DIR)))    $(shell python device/rockchip/common/auto_generator.py $(TARGET_DEVICE_DIR) system_app)    $(shell python device/rockchip/common/auto_generator.py $(TARGET_DEVICE_DIR) preinstall)    $(shell python device/rockchip/common/auto_generator.py $(TARGET_DEVICE_DIR) preinstall_del)    -include $(TARGET_DEVICE_DIR)/system_app/preinstall.mk    -include $(TARGET_DEVICE_DIR)/preinstall/preinstall.mk    -include $(TARGET_DEVICE_DIR)/preinstall_del/preinstall.mkendif

auto_generator.py是个python脚本,用于生成Android.mk和preinstall.mk文件,

def main(argv):    preinstall_dir = os.path.join(argv[1] + '/' + argv[2])    if os.path.exists(preinstall_dir):        #Use to define modules for install        makefile_path = preinstall_dir + '/Android.mk'        #Use to include modules        include_path = preinstall_dir + '/preinstall.mk'        if os.path.exists(makefile_path):            os.remove(makefile_path)        if os.path.exists(include_path):            os.remove(include_path)        makefile = file(makefile_path, 'w')        includefile = file(include_path, 'w')        makefile.write("LOCAL_PATH := $(my-dir)\n\n")        for root, dirs, files in os.walk(preinstall_dir):            for file_name in files:                p = re.compile(r'\S*(?=.apk\b)')                found = p.search(file_name)                if found:                    makefile.write(templet %(found.group(), argv[2]))                    includefile.write('PRODUCT_PACKAGES += %s\n' %found.group())        makefile.close()        includefile.close()

Android.mk用于制定编译规则,如我在preinstall目录下放了个AVSourceTester.apk,那么生成的文件内容是

LOCAL_PATH := $(my-dir)include $(CLEAR_VARS)LOCAL_MODULE := AVSourceTesterLOCAL_MODULE_CLASS := APPSLOCAL_MODULE_PATH := $(TARGET_OUT)/preinstallLOCAL_SRC_FILES := $(LOCAL_MODULE)$(COMMON_ANDROID_PACKAGE_SUFFIX)LOCAL_CERTIFICATE := PRESIGNEDLOCAL_DEX_PREOPT := falseLOCAL_MODULE_TAGS := optionalLOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)include $(BUILD_PREBUILT)

preinstall.mk内容如下:
PRODUCT_PACKAGES += AVSourceTester

编译系统之后,生成路径是
out/target/product/rk3288/system/preinstall/AVSourceTester/AVSourceTester.apk

系统开机之后会调用copyDirectory()@PackageManagerService.java

  File preinstallAppDir = new File(Environment.getRootDirectory(), "preinstall");            File preinstallAppDelDir = new File(Environment.getRootDirectory(),                    "preinstall_del");            if ((!SystemProperties.getBoolean("persist.sys.preinstalled", false)) &&                (!"trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt", null)))) {                // mPreInstallObserver = new AppDirObserver(                // mPreinstallAppDir.getPath(), OBSERVER_EVENTS, false);                // mPreInstallObserver.startWatching();                if (preinstallAppDir.exists()) {                    // scanDirLI(mPreinstallAppDir, 0, scanMode, 0);                    copyPackagesToAppInstallDir(preinstallAppDir);                }                // mPreInstallDelObserver = new AppDirObserver(                // mPreinstallAppDelDir.getPath(), OBSERVER_EVENTS, false);                // mPreInstallDelObserver.startWatching();                if (preinstallAppDelDir.exists()) {                    copyPackagesToAppInstallDir(preinstallAppDelDir);                    deletePreinstallDir(preinstallAppDelDir);                }                SystemProperties.set("persist.sys.preinstalled", "1");            }//$_rockchip_$_modify_end

关键函数是copyPackagesToAppInstallDir(),它会把preinstall目录下的安装文件copy到安装目录。
这样安装就成功了。

安装preinstall和preinstall_del的区别在于后者在安装完之后会删除系统目录下的apk,因此要是做了恢复出厂设置或者卸载动作,那就不能恢复了。

删除函数是deletePreinstallDir(),通过init中的ctl命令实现。

    private void deletePreinstallDir(File dir) {        String[] files = dir.list();        if (files != null) {            Slog.d(TAG, "Ready to cleanup preinstall");            SystemProperties.set("ctl.start", "preinst_clr");        }    }

不过在source code中并没有找到preinst_clr这个service,可以在init.rc中自己添加下,
参考的是 Nu3001/device_rockchip_rksdk

service preinst_clr /system/bin/preinstall_cleanup.sh    disabled    oneshot

preinstall_cleanup.sh这个文件默认是有的,本质是直接删除apk。

#!/system/bin/shlog -t PackageManager "Start to clean up /system/preinstall_del/"mount -o rw,remount -t ext4 /systemrm system/preinstall_del/*.*mount -o ro,remount -t ext4 /system
阅读全文
1 0