Rockchip平台Android应用预安装功能(基于Android13)

Rockchip平台Android应用预安装功能(基于Android13)

1. 预安装应用类型

Android上的应用预安装功能,主要是指配置产品时,根据厂商要求,将事先准备好的第三方应用预置进Android系统。预安装分为以下几种类型:

  1. 安装不可卸载应用
  2. 安装可永久卸载应用
  3. 安装卸载后恢复出厂设置后自动恢复的应用

2. 功能启用说明

2.1 配置和使用

在进行以下操作之前,首先需要输入命令 get_build_var TARGET_DEVICE_DIR 来找到对应的目标文件夹(比如 device/rockchip/rk3126c/)。

在目标文件夹下有三个文件夹,分别为:

  1. preinstall
  2. preinstall_del_forever
  3. preinstall_del

请将需要预置的应用放入对应的文件夹,注意apk文件名尽量使用英文,避免空格。

顺利的话,执行make之后会在$OUT/oem目录生成对应的文件夹:

  1. bundled_persist-app
  2. bundled_uninstall_gone-app
  3. bundled_uninstall_back-app

仍旧对应概述中的几种类型。在烧录后,系统会自动安装这些应用到对应目录。

注意:不支持带systemuid应用的预制,请使用Android原生方式编写mk文件。可参考vendor/rockchip/common/apps/RkDeviceTest/的集成方式。

2.2 编译结果

编译后配置文件将会输出到odm分区($OUT/oem/),增加后请确认烧写了odm.img来使其生效。

3. 预编译脚本

预置应用编译脚本通过下面脚本完成

ifneq ($(strip $(TARGET_PRODUCT)), )
    $(shell python device/rockchip/common/auto_generator.py $(TARGET_DEVICE_DIR) preinstall bundled_persist-app $(TARGET_ARCH))
    $(shell python device/rockchip/common/auto_generator.py $(TARGET_DEVICE_DIR) preinstall_del bundled_uninstall_back-app $(TARGET_ARCH))
    $(shell python device/rockchip/common/auto_generator.py $(TARGET_DEVICE_DIR) preinstall_del_forever bundled_uninstall_gone-app $(TARGET_ARCH))
    -include $(TARGET_DEVICE_DIR)/preinstall/preinstall.mk
    -include $(TARGET_DEVICE_DIR)/preinstall_del/preinstall.mk
    -include $(TARGET_DEVICE_DIR)/preinstall_del_forever/preinstall.mk
endif

可以看到预置应用的Android.mk主要通过auto_generator.py完成

#!/usr/bin/env python
import sys
import os
import re
import zipfile
import shutil
import logging
import string

templet = """include $(CLEAR_VARS)
LOCAL_MODULE := %s
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/%s
LOCAL_SRC_FILES := $(LOCAL_MODULE)$(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_DEX_PREOPT := false
LOCAL_ENFORCE_USES_LIBRARIES := false
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_JNI_SHARED_LIBRARIES_ABI := %s
MY_LOCAL_PREBUILT_JNI_LIBS := %s
MY_APP_LIB_PATH := $(TARGET_OUT_ODM)/%s/$(LOCAL_MODULE)/lib/$(LOCAL_JNI_SHARED_LIBRARIES_ABI)
ifneq ($(LOCAL_JNI_SHARED_LIBRARIES_ABI), None)
$(warning MY_APP_LIB_PATH=$(MY_APP_LIB_PATH))
LOCAL_POST_INSTALL_CMD := \
    mkdir -p $(MY_APP_LIB_PATH) \
    $(foreach lib, $(MY_LOCAL_PREBUILT_JNI_LIBS), ; cp -f $(LOCAL_PATH)/$(lib) $(MY_APP_LIB_PATH)/$(notdir $(lib)))
endif
include $(BUILD_PREBUILT)

"""

copy_app_templet = """LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_APK_NAME := %s
LOCAL_POST_PROCESS_COMMAND := $(shell mkdir -p $(TARGET_OUT_ODM)/%s/$(LOCAL_APK_NAME) && cp $(LOCAL_PATH)/$(LOCAL_APK_NAME).apk $(TARGET_OUT_ODM)/%s/$(LOCAL_APK_NAME)/)
"""

def main(argv):
    preinstall_dir = os.path.join(argv[1],argv[2])
    if os.path.exists(preinstall_dir):
        #Use to include modules
        isfound = 'not_found_lib'
        include_path = preinstall_dir + '/preinstall.mk'
        android_path = preinstall_dir + '/Android.mk'
        target_arch = argv[4]

        if os.path.exists(include_path):
            os.remove(include_path)
        if os.path.exists(android_path):
            os.remove(android_path)

        includefile = file(include_path, 'w')
        androidfile = file(android_path, 'w')

        androidfile.write("include $(call all-subdir-makefiles)\n\n")

        MY_LOCAL_PREBUILT_JNI_LIBS = '\\' + '\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:
                    include_apk_path = preinstall_dir + '/' + found.group()
                    makefile_path = include_apk_path + '/Android.mk'
                    apk = preinstall_dir + '/' + found.group() + '.apk'
                    try:
                        zfile = zipfile.ZipFile(apk,'r')
                    except:
                        if os.path.exists(include_apk_path):
                            shutil.rmtree(include_apk_path)
                        os.makedirs(include_apk_path)
                        apkpath = preinstall_dir + '/' + found.group() + '/'
                        shutil.move(apk,apkpath)
                        makefile = file(makefile_path,'w')
                        makefile.write("LOCAL_PATH := $(my-dir)\n\n")
                        makefile.write(templet % (found.group(),argv[3],'None',MY_LOCAL_PREBUILT_JNI_LIBS,argv[3]))
                        continue
                    for lib_name in zfile.namelist():
                        include_apklib_path = include_apk_path + '/lib' + '/arm'
                        if os.path.exists(include_apk_path):
                            shutil.rmtree(include_apk_path)
                        os.makedirs(include_apklib_path)
                        makefile = file(makefile_path,'w')
                        makefile.write("LOCAL_PATH := $(my-dir)\n\n")
                        apkpath = preinstall_dir + '/' + found.group() + '/'
                    if target_arch == 'arm64':
                        for lib_name in zfile.namelist():
                            lib = re.compile(r'\A(lib/arm64-v8a/)+?')
                            find_name = 'lib/arm64-v8a/'
                            if lib_name.find(find_name) == -1:
                                continue
                            libfound = lib.search(lib_name)
                            if libfound:
                                isfound = 'arm64-v8a'
                                data = zfile.read(lib_name)
                                string = lib_name.split(libfound.group())
                                libfile = include_apklib_path + '/' + string[1]
                                MY_LOCAL_PREBUILT_JNI_LIBS += '\t' + 'lib/arm64' + '/' + string[1] + '\\' + '\n'
                                if (os.path.isdir(libfile)):
                                    continue
                                else:
                                    includelib = file(libfile, 'w')
                                    includelib.write(data)
                        try:
                            if cmp(isfound, 'not_found_lib'):
                                include_apklib_path_arm64 = include_apk_path + '/lib/arm64'
                                os.rename(include_apklib_path, include_apklib_path_arm64)
                        except Exception as e:
                            logging.warning('rename dir faild for:' + e)
                    if not cmp(isfound,'not_found_lib'):
                        for lib_name in zfile.namelist():
                            lib = re.compile(r'\A(lib/armeabi-v7a/)+?')
                            find_name = 'lib/armeabi-v7a/'
                            #if not cmp(lib_name,find_name):
                            #    continue
                            if lib_name.find(find_name) == -1:
                                continue
                            libfound = lib.search(lib_name)
                            if libfound:
                                isfound = 'armeabi-v7a'
                                data = zfile.read(lib_name)
                                string = lib_name.split(libfound.group())
                                libfile = include_apklib_path + '/' + string[1]
                                MY_LOCAL_PREBUILT_JNI_LIBS += '\t' + 'lib/arm' + '/' + string[1] + '\\' + '\n'
                                if(os.path.isdir(libfile)):
                                    continue
                                else:
                                    includelib = file(libfile,'w')
                                    includelib.write(data)
                    if not cmp(isfound,'not_found_lib'):
                        for lib_name in zfile.namelist():
                            lib = re.compile(r'\A(lib/armeabi/)+?')
                            find_name = 'lib/armeabi/'
                            #if not cmp(lib_name,find_name):
                            #    continue
                            if lib_name.find(find_name) == -1:
                                continue
                            libfound = lib.search(lib_name)
                            if libfound:
                                data = zfile.read(lib_name)
                                string = lib_name.split(libfound.group())
                                libfile = include_apklib_path + '/' + string[1]
                                MY_LOCAL_PREBUILT_JNI_LIBS += '\t' + 'lib/arm' + '/' + string[1] + '\\' + '\n'
                                if(os.path.isdir(libfile)):
				        continue
				else:
                                    includelib = file(libfile,'w')
                                    includelib.write(data)
                    tmp_jni_libs = '\\' + '\n'
                    if not cmp(MY_LOCAL_PREBUILT_JNI_LIBS,tmp_jni_libs):
                        nolibpath = preinstall_dir + '/' + found.group() + '/lib'
                        shutil.rmtree(nolibpath)
                        makefile.write(templet % (found.group(),argv[3],'None',MY_LOCAL_PREBUILT_JNI_LIBS,argv[3]))
                    else:
                        if isfound == 'arm64-v8a':
                            makefile.write(templet % (found.group(),argv[3], 'arm64', MY_LOCAL_PREBUILT_JNI_LIBS,argv[3]))
                        else:
                            makefile.write(templet % (found.group(),argv[3],'arm',MY_LOCAL_PREBUILT_JNI_LIBS,argv[3]))
                    shutil.move(apk,apkpath)
                    isfound = 'not_found_lib'
                    MY_LOCAL_PREBUILT_JNI_LIBS = '\\' + '\n'
                    makefile.close()
            break
        for root, dirs,files in os.walk(preinstall_dir):
            for dir_file in dirs:
                includefile.write('PRODUCT_PACKAGES += %s\n' %dir_file)
            break
        includefile.close()

if __name__=="__main__":
  main(sys.argv)

最终生成的Android.mk脚本如下:

LOCAL_PATH := $(my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := MySysManager
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/bundled_persist-app
LOCAL_SRC_FILES := $(LOCAL_MODULE)$(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_DEX_PREOPT := false
LOCAL_ENFORCE_USES_LIBRARIES := false
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_JNI_SHARED_LIBRARIES_ABI := None
MY_LOCAL_PREBUILT_JNI_LIBS := \

MY_APP_LIB_PATH := $(TARGET_OUT_ODM)/bundled_persist-app/$(LOCAL_MODULE)/lib/$(LOCAL_JNI_SHARED_LIBRARIES_ABI)
ifneq ($(LOCAL_JNI_SHARED_LIBRARIES_ABI), None)
$(warning MY_APP_LIB_PATH=$(MY_APP_LIB_PATH))
LOCAL_POST_INSTALL_CMD :=     mkdir -p $(MY_APP_LIB_PATH)     $(foreach lib, $(MY_LOCAL_PREBUILT_JNI_LIBS), ; cp -f $(LOCAL_PATH)/$(lib) $(MY_APP_LIB_PATH)/$(notdir $(lib)))
endif
include $(BUILD_PREBUILT)

PackageManagerService对预安装应用的处理

//PackageManagerService.java
 public static final String BUNDLED_PERSIST_DIR = "/odm/bundled_persist-app";

    public static final String BUNDLED_UNINSTALL_GONE_DIR = "/odm/bundled_uninstall_gone-app";

//Environment.java
private static final File DIR_PREBUNDLED_UNINSTALL_BACK_ROOT = getDirectory(
            ENV_PREBUNDLED_UNINSTALL_BACK_ROOT, "/odm/bundled_uninstall_back-app");
    private static final File DIR_PREBUNDLED_UNINSTALL_GONE_ROOT = getDirectory(
            ENV_PREBUNDLED_UNINSTALL_GONE_ROOT, "/odm/bundled_uninstall_gone-app");

//InitAppsHelper.java
 public void preinstallThirdPartyAPK(PackageParser2 packageParser, ExecutorService executorService,int scanFlags){
        preinstallPrebundledpersist(packageParser,executorService,scanFlags);
        preinstallPrebundledUninstallBack(packageParser,executorService,scanFlags);
        preinstallPrebundledUninstallGone(packageParser,executorService,scanFlags);
    }

    private void preinstallPrebundledpersist(PackageParser2 packageParser, ExecutorService executorService,int scanFlags){
        scanDirTracedLI(new File(mPm.BUNDLED_PERSIST_DIR),null,
                    mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR
                    | ParsingPackageUtils.PARSE_IS_PREINSTALL,
                    scanFlags | mPm.SCAN_AS_PREINSTALL
                    | SCAN_AS_SYSTEM,
                    packageParser, executorService);
    }

    private void preinstallPrebundledUninstallBack(PackageParser2 packageParser, ExecutorService executorService,int scanFlags){
        scanDirTracedLI(Environment.getPrebundledUninstallBackDirectory(),null,
                    mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_IS_PREBUNDLED_DIR,
                    scanFlags | mPm.SCAN_AS_PREBUNDLED_DIR,
                    packageParser, executorService);
    }

    private void preinstallPrebundledUninstallGone(PackageParser2 packageParser, ExecutorService executorService,int scanFlags){
        scanDirTracedLI(Environment.getPrebundledUninstallGoneDirectory(),null,
                    mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_IS_PREBUNDLED_DIR,
                    scanFlags | mPm.SCAN_AS_PREBUNDLED_DIR,
                    packageParser, executorService);
    }

需要进一步了解预安装应用相关流程,请查看preinstallPrebundled相关代码流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/286701.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Axure医疗-住院板块,住院患者原型预览,新增医护人员原型预览,新增病房原型预览,选择床位原型预览,主治医生原型预览,主治医生医嘱原型预览

目录 一.医疗项目原型图-----住院板块 1.1 住院板块原型预览 1.2 新增住院患者原型预览 1.3 新增医护人员原型预览 1.4 新增病房原型预览 1.5 选择床位原型预览 1.6 主治医生原型预览 1.7 主治医生医嘱原型预览 1.8 主治医生查看患者报告原型预览 1.9 护士原型预…

008、所有权

所有权可以说是Rust中最为独特的一个功能了。正是所有权概念和相关工具的引入,Rust才能够在没有垃圾回收机制的前提下保障内存安全。 因此,正确地了解所有权概念及其在Rust中的实现方式,对于所有Rust开发者来讲都是十分重要的。在本文中&…

「Vue3面试系列」Vue3 所采用的 Composition Api 与 Vue2 使用的 Options Api 有什么不同?

文章目录 开始之前正文一、Options Api二、Composition Api三、对比逻辑组织Options APICompostion API 逻辑复用 小结 开始之前 Composition API 可以说是Vue3的最大特点,那么为什么要推出Composition Api,解决了什么问题? 通常使用Vue2开…

Model::unguard()的作用

这是在生成假数据时碰见的,浅查了一下 Model::unguard() 是 Laravel 框架中的一个方法,它的作用是取消对 Eloquent 模型的属性赋值的安全性保护。 在默认情况下,Laravel 的 Eloquent 模型会对属性赋值做一些安全性检查,例如防止…

Vue Cli inspect

Vue Cli inspect vue-cli-service inspect:可以使用 vue-cli-service inspect 来审查一个 Vue CLI 项目的 webpack config 使用方法: 1、输出在控制台:vue-cli-service inspect 2、输在在文件中:vue-cli-service inspect -->…

频谱论文:空间频率插值的无线电地图 Space-Frequency-Interpolated Radio Map

#频谱# K. Sato, K. Suto, K. Inage, K. Adachi and T. Fujii, "Space-Frequency-Interpolated Radio Map," in IEEE Transactions on Vehicular Technology, vol. 70, no. 1, pp. 714-725, Jan. 2021, doi: 10.1109/TVT.2021.3049894. 东京理科大学&#xff0…

Flink实时电商数仓(十)

common模块回顾 app BaseApp: 作为其他子模块中使用Flink - StreamAPI的父类,实现了StreamAPI中的通用逻辑,在其他子模块中只需编写关于数据处理的核心逻辑。BaseSQLApp: 作为其他子模块中使用Flink- SQLAPI的父类。在里面设置了使用SQL API的环境、并行…

桌面天气预报软件 Weather Widget free mac特点介绍

Weather Widget free for Mac多种吸引人的小部件设计可供选择,可以随时了解天气!还可以在Dock和菜单栏中为您提供简短的天气预报或当前状况的概述。 Weather Widget free for Mac软件介绍 始终在桌面上使用时尚的天气小部件来随时了解天气!多…

jenkins +jmeter 报告乱码解决

问题:生产报告会乱码的问题,一般是有编码格式引起的。我遇到的问题是,jmeter需要读取csv的数据作为参数。但是我们并不知道csv保存是什么编码格式,有可能不是utf-8的编码格式,所以会导致中文乱码的问题 解决方案&#…

安装Unity详细教程(如何获取免费个人版许可证)

文章目录 下载Unity Hub安装Unity Hub登录获取免费个人版许可证安装Unity编辑器卸载Unity编辑器 下载Unity Hub 首先,我们需要到Unity的官网下载Unity Hub:Unity CN 我们可以在Unity Hub上管理我们的编辑器版本和项目文件。 安装Unity Hub 然后安装Un…

kubeadm创建k8s集群

kubeadm来快速的搭建一个k8s集群: 二进制搭建适合大集群,50台以上。 kubeadm更适合中下企业的业务集群。 部署框架 master192.168.10.10dockerkubelet kubeadm kubectl flannelnode1192.168.10.20dockerkubelet kubeadm kubectl flannelnode2192.168.1…

selenium实现UI自动化

1.selenium简介 selenium是支持web浏览器自动化的一系列工具和库的综合项目。具有支持linux、windows等多个平台,支持Firefox、chrome等多种主流浏览器;支持Java、Python等多种语言。 主要包括的三大工具有: WebDriver(rc 1.0)、…

JavaScript:作用域变量回收

JavaScript:作用域&变量回收 局部作用域函数作用域块作用域 全局作用域作用域链变量在浏览器模型中的位置浏览器模型全局变量的产生情况直接赋值全局对象与var全局对象的区别 垃圾回收机制引用计数法标记清除法 闭包变量提升&函数提升 作用域规定了变量能够…

k8s基础架构

k8s基础架构 创建pod流程 (1)用户通过kubectl向api-server发起创建pod请求; (2)apiserver通过对应的kubeconfig进行认证,认证通过后将yaml中的po信息存到etcd; (3)Contr…

图像分割-漫水填充法 floodFill

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 本文的C#版本请访问:图像分割-漫水填充法 floodFill (C#)-CSDN博客 FloodFill方法是一种图像处理算法&#…

软件测试/测试开发丨Vuetify框架的使用

介绍 Vuetify 是一个基于 Vue.js 精心打造 UI 组件库,整套 UI 设计为 Material 风格。能够让没有任何设计技能的开发者创造出时尚的 Material 风格界面。 为什么要使用Vuetify框架 所有组件遵从 Material Design 设计规范,UI 体验非常优秀&#xff0c…

计算机毕业设计-----ssm+mysql实现的JavaWeb酒店管理系统

项目介绍 本项目为基于ssmmysql实现的JavaWeb酒店管理系统; 主要功能包括: 管理员登录,收入统计,客房管理,商品管理,客房预订,住宿登记,财务统计,旅客管理,接待对象管理等功能。 环境需要 1.运行环境:最好是java jdk 1.8,我们在这个平台上…

UDS诊断(ISO14229-1) 22服务

文章目录 功能简介应用场景请求和响应1、请求2、子功能3、肯定响应4、否定响应 报文示例常用 DIDUDS中常用 NRC参考 功能简介 22服务,即 ReadDataByIdentifier(按标识符读取数据)服务,该服务允许客户端请求读取服务器中通过一个或…

数据结构初阶之栈和队列(C语言版)

数据结构初阶之栈和队列(C语言版) ✍栈♈栈的结构设计♈栈的各个接口的实现👺StackInit(初始化)👺push(入栈)👺pop(出栈)👺获取栈顶元素👺获取栈中…

案例081:基于微信小程序的移动平台的远程在线诊疗系统

文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…