1.预置可卸载APK,恢复出厂设置以后不可以恢复,将apk预置到data/app目录下
android o 版本以后google 加入了patch,不允许预置apk到data/app目录下,只允许使用adb install 的方式来安装apk到data/app目录下,需要将
其roll back 回以前的版本,然后用下列方法可以完成预置:
https://android.googlesource.com/platform/frameworks/base/+/02cecae02901c86334e09b162c09a6e99187f171%5E%21/services/core/java/com/
android/server/pm/PackageManagerService.java
不能翻墙的可以直接删除下面的代码
+ " but expected at " + known.codePathString
+ "; ignoring.");
}
- } else {
+ } /*else {
throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
"Application package " + pkg.packageName
+ " not found; ignoring.");
- }
+ }*/
}
(1)在 packages/apps 下面以需要预置的 APK 名字创建文件夹,以预置一个名为Test的APK为例
(2)将 Test.apk 放到 packages/apps/Test 下面
(3)在 packages/apps/Test 下面创建文件 Android.mk,文件内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
# LOCAL_PRIVILEGED_MODULE := true
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
(4)打开文件 device\mediatek\common\device.mk
将 Test 添加到 PRODUCT_PACKAGES 里面。
PRODUCT_PACKAGES += Test
(5)重新 build 整个工程
注意:这个比不能卸载的多了一句
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
将 Test 添加到 PRODUCT_PACKAGES 里面。
PRODUCT_PACKAGES += Test
注意:这里发现了几个问题
这样编译出来的app正常情况会在data/app目录下,并打包到userdata.img,可以通过查看userdata.img的大小来判断,然后烧录,发现app并没有安装成功,发现有下面的错误log
2010-01-01 08:00:30.708 801-801/system_process I/PackageManager: /data/app/Test changed; collecting certs
2010-01-01 08:00:30.762 801-801/system_process W/PackageManager: Failed to scan /data/app/Test: Failed to collect certificates from /data/app/Test/Test.apk
2010-01-01 08:00:30.762 801-801/system_process W/PackageManager: Deleting invalid package at /data/app/Test
签名不对,这个apk采用的是v1签名,于是我去对比了原始的apk和编译到out目录下的,发现确实不一样,查看out目录apk签名,发现多了下面这句:
JAR signature META-INF/CERT.SF indicates the APK is signed using APK Signature Scheme v2 but no such signature was found. Signature stripped?
难道是必须要用v2签名?于是我把apk改成v2的签名,但还是不行,错误如下:
JAR signature META-INF/OSGSERVI.SF indicates the APK is signed using APK Signature Scheme v2 but no such signature was found. Signature stripped?
没办法,我试着把原始的apk直接拷到data/app,然后用make userdataimage-nodeps -j64进行打包,重新烧录,发现这时没有问题
于是我把mk文件改成直接拷贝的方式:
LOCAL_PATH := $(call my-dir)
LOCAL_MODULE := Test.apk
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)/Test
LOCAL_SRC_FILES := Test.apk
include $(BUILD_PREBUILT)
这时好了,没有任何问题。当然也可以在其它mk文件添加下面的代码
$(shell mkdir -p $(TARGET_OUT_DATA_APPS)/app/Test)
$(shell cp $(LOCAL_PATH)/Test.apk $(TARGET_OUT_DATA_APPS)/app/Test)
2.预置APK使得用户可以卸载,并且恢复出厂设置时能够恢复,将apk预置到vendor/operator/app目录下
如果apk是v1签名方式,按照如下方式预置:
(1)在 vendor\mediatek\proprietary\packages\3rd-party下面以需要预置的 APK 名字创建文件夹,以预置一个名为Wechat.apk为例
(2) 将Wechat.apk 放入vendor\mediatek\proprietary\packages\3rd-party\Wechat下面
(3)在vendor\mediatek\proprietary\packages\3rd-party\Wechat 下面创建文件 Android.mk,文件内容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Wechat
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := Wechat.apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/operator/app
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_OWNER := mtk
include $(BUILD_PREBUILT)
(4)打开文件device\mediatek\common\device.mk
将 Wechat 添加到 PRODUCT_PACKAGES 里面。
PRODUCT_PACKAGES += Wechat
(5)然后重新build整个工程
注意:需要确保MTK_CTA_SET宏是打开的,会定义属性值persist.vendor.pms_removable=1,MTK_CTA_SET和这个属性值不是强相关的,可以分离,然
后在/vendor/mediatek/proprietary/frameworks/base/data/etc/pms_sysapp_removable_vendor_list.txt这个白名单文件中加入需要卸载的apk的
包名
如果是apk是V2签名方式:
(1)在任意一个apk的目录下(Xunfei)的Android.mk的文件中添加如下内容:
$(shell mkdir $(TARGET_OUT)/vendor/operator/app/Facebook)
$(shell cp $(LOCAL_PATH)/Facebook.apk $(TARGET_OUT)/vendor/operator/app/Facebook)
(2)将该Facebook.apk放入任意一个apk目录中,比如放入Xunfei这个目录中
(3)打开文件device\mediatek\common\device.mk
将 Facebook 添加到 PRODUCT_PACKAGES 里面。
PRODUCT_PACKAGES += Facebook
(4)然后重新build整个工程
注意:
(1)需要确保MTK_CTA_SET宏是打开的,会定义属性值persist.vendor.pms_removable=1,MTK_CTA_SET和这个属性值不是强相关的,可以分离,然后
在/vendor/mediatek/proprietary/frameworks/base/data/etc/pms_sysapp_removable_vendor_list.txt这个白名单文件中加入需要卸载的apk的包
名
(2)这种方式预置facebook,facebook可以成功预置进手机,但是点击手机的时候会报出avc:denied,selinux权限异常的情况,可以通过在相应的te文
件中加入allow语句
3.预置APK使得用户可以卸载,并且恢复出厂设置时能够恢复,将apk预置到system/app目录下
(1) 在 packages/apps 下面以需要预置的 APK 名字创建文件夹,以预置一个名为Test的APK为例
(2) 将 Test.apk 放到 packages/apps/Test 下面
(3) 在 packages/apps/Test 下面创建文件 Android.mk,文件内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
(4) 打开文件 device\mediatek\common\device.mk
将 Test 添加到 PRODUCT_PACKAGES 里面。
PRODUCT_PACKAGES += Test
(5) 重新 build 整个工程
注意:
(1)需要确保MTK_CTA_SET宏是打开的,会定义属性值persist.vendor.pms_removable=1,MTK_CTA_SET和这个属性值不是强相关的,可以分离,然后
在/vendor/mediatek/proprietary/frameworks/base/data/etc/pms_sysapp_removable_system_list.txt这个白名单文件中加入需要卸载的apk的包
名
(2)同时需要把so文件放到对应的system/lib下面,这里为什么要放到system/lib目录下面?我试过放在app的lib/arm目录下面,但是会报找不到so库的错误,程序直接崩溃,只有放在vendor/operator/app才会这样,放到vendor/app目录的app就没问题。通过测试发现这种拷贝的方式有一个很大的问题,就是当app版本升级后,机器重启会恢复到原来的版本,所以不要使用这种方式。可以把每一个so库当做module来处理,当然也可以通过拷贝的方式来
include $(CLEAR_VARS)
LOCAL_MODULE := libleds_jni
LOCAL_SRC_FILES := $(LIB_DIR)/libleds_jni.so
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_OWNER := mtk
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_SUFFIX = .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/lib/
include $(BUILD_PREBUILT)
$(shell mkdir -p $(PRODUCT_OUT)/system/lib)
$(shell cp $(LOCAL_PATH)/lib/armeabi-v7a/libgpio_jni.so $(PRODUCT_OUT)/system/lib)
4.预置APK使得用户可以卸载,并且恢复出厂设置时能够恢复,将apk预置到vendor/app目录下
写法和vendor/operator/app一样,但是会出现找不到so的错误,可以看到会从3个地方找so库。
libnativeloader: classloader namespace configured for unbundled vendor apk. library_path=/vendor/app/Test/lib/arm64:/vendor/app/Test/Test.apk!/lib/arm64-v8a:/vendor/lib64
所以做法有三种:
a)可以把so提取取出来,然后编译到Test/lib/arm64,这种写法的好处就是不用管系统是32位还是64位的,如果是32位的会编译成lib/arm64,64位的则会编译成lib/arm64
LOCAL_PREBUILT_JNI_LIBS := \
libgdinamapv4sdk752.so \
libgdinamapv4sdk752ex.so \
libJNI_GaussisanBlur.so \
libStDualCam.so
b)我的apk里面明明是有lib/arm64-v8a文件夹的,但是就是找不到库,也没看到报avc的错误
c)放到系统的vendor/lib64文件夹
include $(CLEAR_VARS)
LOCAL_MODULE := libleds_jni
LOCAL_SRC_FILES := $(LIB_DIR)/libleds_jni.so
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_OWNER := mtk
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_SUFFIX = .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib64
include $(BUILD_PREBUILT)
内置好了并成功安装之后:
这里发现了一个问题,当app升级之后,重启机器,发现app不见了,写到pms_sysapp_removable_system_list.txt,privapp-permissions-mediatek.xml的app都会这样,反复打log,发现在PackageManagerService.java里面做了处理,可以做如下修改
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
// M:operator app also is removable and not system flag
- if ((!sPmsExt.isRemovableSysApp(ps.name))) {
+ //modify by jueme for vendor app can install at 20201109
+ //if ((!sPmsExt.isRemovableSysApp(ps.name))) {
continue;
- }
+ //}
+ //modify end
}
- final boolean scanSystemPartition = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0)
+ //modify by jueme for vendor app can install at 20201109
+ //final boolean scanSystemPartition = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0)
// M:operator app also is removable and not system flag
- || sPmsExt.isRemovableSysApp(pkg.packageName);
+ //|| sPmsExt.isRemovableSysApp(pkg.packageName);
+ final boolean scanSystemPartition = (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0;
+ //modify end
之后还有个奇怪的问题,当把预制的app卸载后然后重新安装时,发现PackageManager奔溃,错误信息如下
2020-11-09 17:16:19.650 659-963/system_process E/AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: PackageManager
java.lang.NullPointerException: Attempt to get length of null array
at com.mediatek.server.pm.PmsExtImpl.updatePackageSettings(PmsExtImpl.java:539)
at com.android.server.pm.PackageManagerService.updateSettingsInternalLI(PackageManagerService.java:17123)
at com.android.server.pm.PackageManagerService.updateSettingsLI(PackageManagerService.java:17057)
at com.android.server.pm.PackageManagerService.installNewPackageLIF(PackageManagerService.java:16468)
at com.android.server.pm.PackageManagerService.installPackageLI(PackageManagerService.java:17680)
at com.android.server.pm.PackageManagerService.installPackageTracedLI(PackageManagerService.java:17168)
at com.android.server.pm.PackageManagerService.access$3500(PackageManagerService.java:416)
at com.android.server.pm.PackageManagerService$9.run(PackageManagerService.java:15048)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.os.HandlerThread.run(HandlerThread.java:65)
at com.android.server.ServiceThread.run(ServiceThread.java:44)
于是加了一个为null的判断
/// M: Removable system app support
- sPmsExt.updatePackageSettings(userId, pkgName, pkg, ps, allUsers,
- installerPackageName);
+
+ //add by jueme for vendor app uninstall,then install NullPointerException at 20201109
+ if(allUsers!=null){
+ sPmsExt.updatePackageSettings(userId, pkgName, pkg, ps, allUsers,
+ installerPackageName);
+ }
+ //add end
fota升级时,发现在pms_sysapp_removable_vendor_list.txt和pms_sysapp_removable_system_list.txt里面的app不能安装,恢复出厂设置可以复原,这个问题困扰了我好久,各种排查问题,一开始以为是MTK平台的问题。但是发现只要不在pms_sysapp_removable_vendor_list和pms_sysapp_removable_system_list里面的应用就可以成功安装,于是去看代码。处理这些txt都是在PmsExtImpl.java。在PackageManagerService.java的scanPackageInternalLI方法里面
/// M: Skip an uninstalled system or vendor app
if (sPmsExt.needSkipScanning(pkg, updatedPkg, ps, scanFile))
return null;
可以看到这里做了判断
@Override
public boolean needSkipScanning(PackageParser.Package pkg,
PackageSetting updatedPkg, PackageSetting ps, File scanFile) {
if (!mPms.isFirstBoot() &&
(isRemovableSysApp(pkg.packageName) || locationIsOperator(scanFile)) &&
(ps == null && updatedPkg == null)) {
if (mPms.isUpgrade()) {
if (isRemovableSysApp(pkg.packageName)
&& !sRemovableSystemAppSetBak.contains(pkg.packageName)) {
Slog.d(TAG, "New added removable sys app by OTA:" + pkg.packageName);
return false;
}
if (locationIsOperator(scanFile)
&& sUpgradeOperAppSet.contains(pkg.packageName)
&& !sUpgradeOperAppSetBak.contains(pkg.packageName)) {
Slog.d(TAG, "New added operator app by OTA:" + pkg.packageName);
return false;
}
}
Slog.d(TAG, "Skip scanning uninstalled sys package " + pkg.packageName);
return true;
} else if (ps == null && updatedPkg != null) {
Slog.d(TAG, "Skip scanning uninstalled package: " + pkg.packageName);
return true;
}
return false;
}
如果返回true,就被忽略