学习日记 第二天 内置应用功能无法正常使用 需adb install

内置APP在安卓系统不可或缺,客户有时需要内置一些厂商商店等应用是通过adb install去测试以及验证功能,当要求我们内置时会遇到代码混淆以及各种限制导致应用功能失效,这种时候我们需要写一个脚本去实现开机自动install来替代。

一.使用PRODUCT_COPY_FILES

+# define check-product-copy-files
+# $(if $(filter-out $(TARGET_COPY_OUT_SYSTEM_OTHER)/%,$(2)), \
+#   $(if $(filter %.apk, $(2)),$(error \
+#      Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))) \
+# $(if $(filter true,$(BUILD_BROKEN_VINTF_PRODUCT_COPY_FILES)),, \
+#   $(if $(filter $(TARGET_COPY_OUT_SYSTEM)/etc/vintf/% \
+#                 $(TARGET_COPY_OUT_SYSTEM)/manifest.xml \
+#                 $(TARGET_COPY_OUT_SYSTEM)/compatibility_matrix.xml,$(2)), \
+#     $(error VINTF metadata found in PRODUCT_COPY_FILES: $(1), use vintf_fragments instead!)) \
+#   $(if $(filter $(TARGET_COPY_OUT_PRODUCT)/etc/vintf/%,$(2)), \
+#     $(error VINTF metadata found in PRODUCT_COPY_FILES: $(1), \
+#       use PRODUCT_MANIFEST_FILES / DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE / vintf_compatibility_matrix / vintf_fragments instead!)) \
+#   $(if $(filter $(TARGET_COPY_OUT_SYSTEM_EXT)/etc/vintf/%,$(2)), \
+#     $(error VINTF metadata found in PRODUCT_COPY_FILES: $(1), \
+#       use vintf_compatibility_matrix / vintf_fragments instead!)) \
+#   $(if $(filter $(TARGET_COPY_OUT_VENDOR)/etc/vintf/% \
+#                 $(TARGET_COPY_OUT_VENDOR)/manifest.xml \
+#                 $(TARGET_COPY_OUT_VENDOR)/compatibility_matrix.xml,$(2)), \
+#     $(error VINTF metadata found in PRODUCT_COPY_FILES: $(1), \
+#       use DEVICE_MANIFEST_FILE / DEVICE_MATRIX_FILE / vintf_compatibility_matrix / vintf_fragments instead!)) \
+#   $(if $(filter $(TARGET_COPY_OUT_ODM)/etc/vintf/% \
+#                 $(TARGET_COPY_OUT_ODM)/etc/manifest%,$(2)), \
+#     $(error VINTF metadata found in PRODUCT_COPY_FILES: $(1), \
+#       use ODM_MANIFEST_FILES / vintf_fragments instead!)) \
+# )
+# endef

需要跳过这一部分检查

+PRODUCT_COPY_FILES += \
+       device/rockchip/rk356x/rk3568_r/apps/xxxx/xxxx.apk:odm/other_persist-app/xxxx.apk

客户要求恢复出厂设置后我用的RK平台,我试过放置到对应路径下install,结果可卸载跟不可卸载功能是用不了的,因此我们要重新写一套。但目前先尝试copy跟install可不可行

因此我们在init阶段读取on property:sys.boot_completed=1

+    exec u:r:shell:s0  root  root -- /system/bin/pm install /odm/other_uninstall_back-app/xxxx.apk

本以为行得通,没想到客户要求用他们自己的Launcher,且他们的UI线程有点问题,应用install时如果不在他们的launcher主界面之后install是不会有新图标显示的,除非重启。为了减少扯皮步骤开始第二种方案。

二.脚本服务实现

diff --git a/device/rockchip/common/init.rk30board.rc b/device/rockchip/common/init.rk30board.rc
index f02c344b54..1d8b12aff5 100755
--- a/device/rockchip/common/init.rk30board.rc
+++ b/device/rockchip/common/init.rk30board.rc
@@ -425,3 +425,9 @@ service mcu_notify_service /system/bin/mcu_tool notify_power_on
     user root
     group root
     oneshot
+
+service install_service /system/bin/install_service.sh
+    class main
+    user root
+    oneshot
+    disabled
diff --git a/device/rockchip/common/sepolicy/private/file_contexts b/device/rockchip/common/sepolicy/private/file_contexts
index 9c6f73427c..904ee95bce 100644
--- a/device/rockchip/common/sepolicy/private/file_contexts
+++ b/device/rockchip/common/sepolicy/private/file_contexts
@@ -2,3 +2,5 @@
 /system/bin/move_widevine_data\.sh              u:object_r:move-widevine-data-sh_exec:s0
 
 /system/bin/can_init_bitrate\.sh                u:object_r:can_init_bitrate-sh_exec:s0
+
+/system/bin/install_service\.sh                u:object_r:install_service-sh_exec:s0
diff --git a/device/rockchip/common/sepolicy/private/install-service.te b/device/rockchip/common/sepolicy/private/install-service.te
new file mode 100644
index 0000000000..1c772d302a
--- /dev/null
+++ b/device/rockchip/common/sepolicy/private/install-service.te
@@ -0,0 +1,4 @@
+type install_service-sh, domain, coredomain;
+type install_service-sh_exec, exec_type, system_file_type, file_type;
+allow init install_service-sh_exec:file { getattr open read execute map };
+init_daemon_domain(install_service-sh);
\ No newline at end of file
diff --git a/device/rockchip/rk356x/init.rk356x.rc b/device/rockchip/rk356x/init.rk356x.rc
index a1222044cd..b55745abd3 100644
--- a/device/rockchip/rk356x/init.rk356x.rc
+++ b/device/rockchip/rk356x/init.rk356x.rc
@@ -11,10 +11,8 @@ on property:sys.boot_completed=1
 
     start can_init_bitrate
+    start install_service

 on boot
     chown system system /sys/class/thermal/thermal_zone0/policy
     chown system system /sys/class/thermal/thermal_zone1/policy
@@ -56,3 +54,9 @@ service can_init_bitrate /system/bin/can_init_bitrate.sh
     oneshot
     disabled
 
+service install_service /system/bin/install_service.sh
+    class main
+    user root
+    oneshot
+    disabled
+

需要注意的是oneshot执行一次,以及selinux权限相关

之后添加我们的不可卸载框架

diff --git a/frameworks/base/core/java/android/content/pm/PackageParser.java b/frameworks/base/core/java/android/content/pm/PackageParser.java
index 427fe2820b..0adadf65b4 100644
--- a/frameworks/base/core/java/android/content/pm/PackageParser.java
+++ b/frameworks/base/core/java/android/content/pm/PackageParser.java
@@ -130,6 +130,9 @@ import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
+import java.io.BufferedReader;
+import java.io.FileReader;
+
 /**
  * Parser for package files (APKs) on disk. This supports apps packaged either
  * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
@@ -214,6 +217,17 @@ public class PackageParser {
     public static final String METADATA_ACTIVITY_WINDOW_LAYOUT_AFFINITY =
             "android.activity_window_layout_affinity";
 
+    /**
+     * Profile file path
+     */
+    private static final String PROFILE_FILE_PATH = "/data/local/config/";
+
+    /**
+     * Profile file name
+     */
+    private static final String PROFILE_FILE_PATH_NAME = "NoDeleteApplist";
+
+
     /**
      * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
      * @hide
@@ -2489,10 +2503,52 @@ public class PackageParser {
         if (pkg.applicationInfo.usesCompatibilityMode()) {
             adjustPackageToBeUnresizeableAndUnpipable(pkg);
         }
+        if (isProfileNoDeleteApp(pkg.packageName)) {
+            Slog.w(TAG, "parser not removing packages " );
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        }
 
         return pkg;
     }
 
+    /**
+     * profile no delete app file
+     * @param pkgName
+     * @return
+     */
+    private boolean isProfileNoDeleteApp(String pkgName) {
+        final File systemDir;
+        final File blackListFile;
+        final ArrayList<String> blackListApps = new ArrayList<String>();
+        systemDir = new File(PROFILE_FILE_PATH);
+        blackListFile = new File(systemDir, PROFILE_FILE_PATH_NAME);
+        if (!blackListFile.exists()) {
+            return false;
+        }
+        try {
+            blackListApps.clear();
+            BufferedReader br = new BufferedReader(new FileReader(blackListFile));
+            String line = br.readLine();
+            while (line != null) {
+                blackListApps.add(line);
+                line = br.readLine();
+            }
+            br.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }
+        Iterator<String> it = blackListApps.iterator();
+        while (it.hasNext()) {
+            String blacklistItem = it.next();
+            if (pkgName.equals(blacklistItem)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
     /**
      * Returns {@code true} if both the property name and value are empty or if the given system
      * property is set to the specified value. Properties can be one or more, and if properties are
diff --git a/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java b/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
index 22c73d2f77..e9dcbdfb99 100644
--- a/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -450,6 +450,10 @@ import java.util.function.Supplier;
 import android.app.smdt.SmdtManagerNew;
 import java.lang.reflect.Method;
 
+import java.io.BufferedReader;
+import java.io.FileReader;
+import android.widget.Toast;
+
 /**
  * Keep track of all those APKs everywhere.
  * <p>
@@ -809,6 +813,16 @@ public class PackageManagerService extends IPackageManager.Stub
      */
     boolean mPromoteSystemApps;
 
+    /**
+     * Profile file path
+     */
+    private static final String PROFILE_FILE_PATH = "/data/local/config/";
+
+    /**
+     * Profile file name
+     */
+    private static final String PROFILE_FILE_PATH_NAME = "NoDeleteApplist";
+
     private final PackageManagerInternal mPmInternal;
 
 
@@ -3189,6 +3203,9 @@ public class PackageManagerService extends IPackageManager.Stub
                     if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                         continue;
                     }
+                    if (isProfileNoDeleteApp(ps.name)) {
+                        continue;
+                    }
 
                     /*
                      * If the package is scanned, it's not erased.
@@ -9167,6 +9184,9 @@ public class PackageManagerService extends IPackageManager.Stub
                 // Ignore entries which are not packages
                 continue;
             }
+            if (!isPackage && !isProfileNoDeleteApp(file.getAbsolutePath())) {
+                continue;
+            }
             if (file.getAbsolutePath().contains(BUNDLED_UNINSTALL_GONE_DIR)) {
                 if (list != null && list.size() > 0) {
                     final boolean isdeleteApk = isDeleteApk(file,parseFlags,list);
@@ -10458,6 +10478,10 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @GuardedBy("mInstallLock")
     void removeCodePathLI(File codePath) {
+        if (isProfileNoDeleteApp(codePath.getAbsolutePath())) {
+            Slog.w(TAG, "profile app file removeCodePathLI error");
+            return;
+        }
         if (codePath.isDirectory()) {
             File codePathParent = codePath.getParentFile();
             try {
@@ -12741,6 +12765,9 @@ public class PackageManagerService extends IPackageManager.Stub
     }
 
     private void removePackageLI(AndroidPackage pkg, boolean chatty) {
+        if (isProfileNoDeleteApp(pkg.getPackageName())) {
+            return;
+        }
         // Remove the parent package setting
         PackageSetting ps = getPackageSetting(pkg.getPackageName());
         if (ps != null) {
@@ -18739,6 +18766,43 @@ public class PackageManagerService extends IPackageManager.Stub
         return mKeepUninstalledPackages != null && mKeepUninstalledPackages.contains(packageName);
     }
 
+    /**
+     * profile no delete app file
+     * @param pkgName
+     * @return
+     */
+    private boolean isProfileNoDeleteApp(String pkgName) {
+        final File systemDir;
+        final File blackListFile;
+        final ArrayList<String> blackListApps = new ArrayList<String>();
+        systemDir = new File(PROFILE_FILE_PATH);
+        blackListFile = new File(systemDir, PROFILE_FILE_PATH_NAME);
+        if (!blackListFile.exists()) {
+            return false;
+        }
+        try {
+            blackListApps.clear();
+            BufferedReader br = new BufferedReader(new FileReader(blackListFile));
+            String line = br.readLine();
+            while (line != null) {
+                blackListApps.add(line);
+                line = br.readLine();
+            }
+            br.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }
+        Iterator<String> it = blackListApps.iterator();
+        while (it.hasNext()) {
+            String blacklistItem = it.next();
+            if (pkgName.contains(blacklistItem)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      *  This method is an internal method that could be get invoked either
      *  to delete an installed package or to clean up a failed installation.
@@ -18765,6 +18829,12 @@ public class PackageManagerService extends IPackageManager.Stub
             return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
         }
 
+        if (isProfileNoDeleteApp(packageName)) {
+            Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
+            Toast.makeText(mContext, "该应用无法删除", Toast.LENGTH_SHORT).show();
+            return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
+        }
+
                boolean canUninstall = true;
                //xlr add for uninstall black/white list 22.6.16 start
         SmdtManagerNew smdtManagerNew = SmdtManagerNew.getInstance(mContext);
@@ -19085,6 +19155,9 @@ public class PackageManagerService extends IPackageManager.Stub
     private void removePackageDataLIF(final PackageSetting deletedPs, int[] allUserHandles,
             PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
         String packageName = deletedPs.name;
+        if (isProfileNoDeleteApp(packageName)) {
+            return;
+        }
         if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs);
         // Retrieve object to delete permissions for shared user later on
         final AndroidPackage deletedPkg = deletedPs.pkg;
@@ -19222,6 +19295,10 @@ public class PackageManagerService extends IPackageManager.Stub
             int[] allUserHandles, int flags, @Nullable PackageRemovedInfo outInfo,
             boolean writeSettings)
             throws SystemDeleteException {
+        if (isProfileNoDeleteApp(deletedPs.name)) {
+            Slog.w(TAG, "deleteSystemPackageLIF packageName =  " + deletedPs.name);
+            return;
+        }
         final boolean applyUserRestrictions =
                 (allUserHandles != null) && outInfo != null && (outInfo.origUsers != null);
         final AndroidPackage deletedPkg = deletedPs.pkg;
diff --git a/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java b/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
index c3a930339e..96d7519541 100755
--- a/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -338,6 +338,8 @@ import java.util.Objects;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
 
 /**
  * An entry in the history stack, representing an activity.
@@ -5387,10 +5389,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
         //Launcher is drawn completed,box can exit bootanim
         //if ("box".equals(SystemProperties.get("ro.target.product"))){
-            if(shortComponentName!=null && !shortComponentName.contains(".FallbackHome")
-                && !"1".equals(SystemProperties.get("service.bootanim.exit"))){
-                    stopBootanim();
+        if(shortComponentName!=null && !shortComponentName.contains(".FallbackHome")
+            && !"1".equals(SystemProperties.get("service.bootanim.exit"))){
+                if ("true".equals(SystemProperties.get("persist.sys.firstboot"))) {
+                    Log.e("xx","install appstore");
+                SystemProperties.set("ctl.start","install_service");
+                try{
+                    Thread.sleep(5000);
+                } catch (InterruptedException e) {
+                    Log.e("xx","线程被中断");
+                }
             }
+                stopBootanim();
+        }
         //}

实现是通过包名写进一个文件,如果识别到就不可删除。我们把内置的包名也写进脚本里吧

diff --git a/vendor/rockchip/common/bin/Android.mk b/vendor/rockchip/common/bin/Android.mk
index 06f79be443..7aaef01264 100644
--- a/vendor/rockchip/common/bin/Android.mk
+++ b/vendor/rockchip/common/bin/Android.mk
@@ -53,4 +53,12 @@ LOCAL_MODULE_STEM := $(LOCAL_MODULE)
 LOCAL_SRC_FILES := $(TARGET_ARCH)/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
+###############################################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := install_service.sh
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_STEM := $(LOCAL_MODULE)
+LOCAL_SRC_FILES := $(TARGET_ARCH)/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
 
diff --git a/vendor/rockchip/common/bin/arm64/install_service.sh b/vendor/rockchip/common/bin/arm64/install_service.sh
new file mode 100644
index 0000000000..82637f4f4a
--- /dev/null
+++ b/vendor/rockchip/common/bin/arm64/install_service.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+mkdir /data/local/config/
+chmod 775 /data/local/config/
+echo "com.bbk.appstore" > /data/local/config/NoDeleteApplist
+pm install -r /odm/other_persist-app/AppStore/AppStore.apk
\ No newline at end of file
diff --git a/vendor/rockchip/common/bin/bin.mk b/vendor/rockchip/common/bin/bin.mk
index c8981bfb67..017a6c2651 100644
--- a/vendor/rockchip/common/bin/bin.mk
+++ b/vendor/rockchip/common/bin/bin.mk
@@ -22,5 +22,6 @@ PRODUCT_PACKAGES += \
 
 ifneq ($(filter rk356x, $(TARGET_BOARD_PLATFORM)), )
 PRODUCT_PACKAGES += \
-    can_init_bitrate.sh
+    can_init_bitrate.sh \
+    install_service.sh

在这里,理应就大功告成了。既在开机动画停止前install,保证在客户launcher显示前我们就安装好了。但是init阶段太早了,导致pms还没起来就进行了脚本操作。因此还是不成功,我们换个时间来进行脚本操作。

diff --git a/device/rockchip/rk356x/init.rk356x.rc b/device/rockchip/rk356x/init.rk356x.rc
index b55745abd3..a1ec2b65ab 100644
--- a/device/rockchip/rk356x/init.rk356x.rc
+++ b/device/rockchip/rk356x/init.rk356x.rc
@@ -11,7 +11,6 @@ on property:sys.boot_completed=1
 
     start can_init_bitrate
-    start install_service
 
 on boot
     chown system system /sys/class/thermal/thermal_zone0/policy
diff --git a/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java b/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
index 96d7519541..501e9626ca 100755
--- a/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5391,15 +5391,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
         //if ("box".equals(SystemProperties.get("ro.target.product"))){
         if(shortComponentName!=null && !shortComponentName.contains(".FallbackHome")
             && !"1".equals(SystemProperties.get("service.bootanim.exit"))){
-                if ("true".equals(SystemProperties.get("persist.sys.firstboot"))) {
-                    Log.e("xx","install appstore");
-                SystemProperties.set("ctl.start","install_service");
-                try{
-                    Thread.sleep(5000);
-                } catch (InterruptedException e) {
-                    Log.e("xx","线程被中断");
-                }
-            }
                 stopBootanim();
         }
         //}
diff --git a/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java b/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
index 6d98bfbc10..c76e6a4dd0 100644
--- a/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3423,6 +3423,9 @@ public class WindowManagerService extends IWindowManager.Stub
 
     private void performEnableScreen() {
         synchronized (mGlobalLock) {
+            if ("true".equals(SystemProperties.get("persist.sys.firstboot"))) {
+                SystemProperties.set("ctl.start","install_service");
+            }
             ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b"
                             + " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b"
                             + " mSystemBooted=%b mOnlyCore=%b. %s", mDisplayEnabled,

最终我们放弃了init阶段去执行脚本,而且在wms中通过属性来启动脚本。这里是绘制屏幕的功能,上层该启动的服务应该都起来了,经过测试OK!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值