android 12 应用安装白名单

一、功能概述

在Android 12.0系统中,实现APP应用安装白名单功能,主要是为了确保只有在白名单内的应用能够被安装。以下是对Android 12.0 APP应用安装白名单的详细解释:

二、核心代码与实现

2.1、IPackageManager.aidl添加接口:

首先,需要在IPackageManager.aidl文件中增加设置白名单和获取白名单的接口。这是实现应用安装白名单功能的基础。

2.2、PackageManagerService(PMS)实现接口:

在PackageManagerService.java中,实现上述接口的具体功能。这包括设置白名单、获取白名单以及在安装应用时判断应用是否在白名单中。

2.3、判断应用是否在白名单中:

在PMS的preparePackageLI方法中,添加逻辑以判断当前正在安装的应用是否在白名单中。如果应用在白名单中,则允许安装;否则,阻止安装。

三、app应用安装白名单核心代码

复制代码
frameworks/base/core/java/android/content/pm/IPackageManager.aidl
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

四、app应用安装白名单核心功能分析

首选需要在IPackageManager.aidl 日这个pms的aidl中增加白名单接口,实现设置白名单和获取白名单的接口,接下来在PMS中的安装app的方法中判断是否是白名单的app,然后确定是否让安装从而实现功能

4.1 IPackageManager.aidl添加接口供app调用

首先需要在增加pms的aidl中IPackageManager.aidl增加设置白名单和获取白名单接口

复制代码
diff --git a/frameworks/base/core/java/android/content/pm/IPackageManager.aidl b/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
 
old mode 100644
 
new mode 100755
 
index a369cc89a3..90fafe5a8f
 
--- a/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
 
+++ b/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
 
@@ -798,4 +798,7 @@ interface IPackageManager {
 
     */
     int restoreAppData(String sourceDir, String pkgName);
 
    /* @} */
 
+   
 
+       void setInstallPackageWhiteList(in List<String> packageNames);
 
+       List<String> getInstallPackageWhiteList();
 
 }

4.2 在PMS中实现设置和获取白名单的接口

复制代码
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 45289f2e39..6727b10e35 100755
 
--- a/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
 
+++ b/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
 
@@ -111,7 +111,13 @@ import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFile
 
 import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime;
 
 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
 
 import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
 
-
 
+import java.io.BufferedReader;
 
+import java.io.File;
 
+import java.io.FileInputStream;
 
+import java.io.FileOutputStream;
 
+import java.io.InputStreamReader;
 
+import java.io.LineNumberReader;
 
+import java.io.PrintWriter;
 
 import android.Manifest;
 
 import android.annotation.IntDef;
 
 import android.annotation.NonNull;
 
@@ -2141,7 +2147,16 @@ public class PackageManagerService extends PackageManagerServiceExAbs
 
             }
 
         }
 
     }
 
-
 
+       private List<String> installwhitepackageNames;
 
+           @Override
 
+    public void setInstallPackageWhiteList( List<String> packageNames) {
 
+               this.installwhitepackageNames=packageNames;
 
+    }
 
+       
 
+       @Override
 
+    public List<String> getInstallPackageWhiteList(){
 
+               return this.installwhitepackageNames;
 
+    }
 
     private void notifyInstallObserver(String packageName) {
 
         Pair<PackageInstalledInfo, IPackageInstallObserver2> pair =
 
                 mNoKillInstallObservers.remove(packageName);

通过上述在PackageManagerService.java的代码中,增加实现安装app白名单的接口来实现自定义服务中,通过调用接口来实现对安装白名单数据的传递,来实现控制app白名单内的app安装.

4.3PackageManagerService关于安装app白名单功能实现分析

PMS的 preparePackageLl()负责对app的安装功能做相关的管理,可以先看相关代码然后在这里进行安装app的时候判断app是否在白名单列表中决定是否安装

复制代码
@GuardedBy("mInstallLock")
      private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
              throws PrepareFailure {
          final int installFlags = args.installFlags;
          final File tmpPackageFile = new File(args.getCodePath());
          final boolean onExternal = args.volumeUuid != null;
          final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
          final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
          final boolean virtualPreload =
                  ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
          @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
          if (args.move != null) {
              // moving a complete application; perform an initial scan on the new install location
              scanFlags |= SCAN_INITIAL;
          }
          if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
              scanFlags |= SCAN_DONT_KILL_APP;
          }
          if (instantApp) {
              scanFlags |= SCAN_AS_INSTANT_APP;
          }
          if (fullApp) {
              scanFlags |= SCAN_AS_FULL_APP;
          }
          if (virtualPreload) {
              scanFlags |= SCAN_AS_VIRTUAL_PRELOAD;
          }
  
          if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
  
          // Sanity check
          if (instantApp && onExternal) {
              Slog.i(TAG, "Incompatible ephemeral install; external=" + onExternal);
              throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
          }
  
          // Retrieve PackageSettings and parse package
          @ParseFlags final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
                  | PackageParser.PARSE_ENFORCE_CODE
                  | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
  
          Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
          ParsedPackage parsedPackage;
          try (PackageParser2 pp = new PackageParser2(mSeparateProcesses, false, mMetrics, null,
                  mPackageParserCallback)) {
              parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
              AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
          } catch (PackageParserException e) {
              throw new PrepareFailure("Failed parse during installPackageLI", e);
          } finally {
              Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
          }
  
          // Instant apps have several additional install-time checks.
          if (instantApp) {
              if (parsedPackage.getTargetSdkVersion() < Build.VERSION_CODES.O) {
                  Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName()
                                  + " does not target at least O");
                  throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                          "Instant app package must target at least O");
              }
              if (parsedPackage.getSharedUserId() != null) {
                  Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName()
                          + " may not declare sharedUserId.");
                  throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                          "Instant app package may not declare a sharedUserId");
              }
          }
  
          if (parsedPackage.isStaticSharedLibrary()) {
              // Static shared libraries have synthetic package names
              renameStaticSharedLibraryPackage(parsedPackage);
  
              // No static shared libs on external storage
              if (onExternal) {
                  Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
                  throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                          "Packages declaring static-shared libs cannot be updated");
              }
          }
  
          String pkgName = res.name = parsedPackage.getPackageName();
          if (parsedPackage.isTestOnly()) {
              if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
                  throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
              }
          }
  
          try {
              // either use what we've been given or parse directly from the APK
              if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {
                  parsedPackage.setSigningDetails(args.signingDetails);
              } else {
                  parsedPackage.setSigningDetails(
                          ParsingPackageUtils.getSigningDetails(parsedPackage, false /* skipVerify */));
              }
          } catch (PackageParserException e) {
              throw new PrepareFailure("Failed collect during installPackageLI", e);
          }
  
		  .....
      }

通过对PMS的安装流程分析,可以得知在app静默安装,手动安装,等等无论是pm安装或者是 代码安装 都会走preparePackageLl所以在这里添加判断包名是否在白名单即可然后在白名单内的app可以安装,不在白名单内的app就不能安装,具体实现如下:

复制代码
@@ -17482,7 +17497,13 @@ public class PackageManagerService extends PackageManagerServiceExAbs
 
 @GuardedBy("mInstallLock")
    private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
            throws PrepareFailure {     
         try (PackageParser2 pp = new PackageParser2(mSeparateProcesses, false, mMetrics, null,
                  mPackageParserCallback)) {
              parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
              AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
          } catch (PackageParserException e) {
              throw new PrepareFailure("Failed parse during installPackageLI", e);
          } finally {
              Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
          }
 
 
-
 
+               if(!isWhiteListApp(parsedPackage.getPackageName())){
 
+            Log.d("TAG","--isWhiteListApp--");
 
+                       
 
+                       throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
 
+                    "app is not in the whitelist. packageName");
 
+           
 
+        }
 
         if (instantApp && pkg.mSigningDetails.signatureSchemeVersion
 
                 < SignatureSchemeVersion.SIGNING_BLOCK_V2) {
 
             Slog.w(TAG, "Instant app package " + pkg.packageName
 
@@ -18039,7 +18060,21 @@ public class PackageManagerService extends PackageManagerServiceExAbs
 
             }
 
         }
 
     }
 
+    private boolean isWhiteListApp(String packagename){
 
 
 
+               if(this.installwhitepackageNames ==null || this.installwhitepackageNames.size()==0){
 
+                       return true;
 
+               }
 
+               
 
+        Iterator<String> it = this.installwhitepackageNames.iterator();
 
+        while (it.hasNext()) {
 
+            String whitelistItem = it.next();
 
+            if (whitelistItem.equals(packagename)) {
 
+                return true;
 
+            }
 
+        }
 
+        return false;
 
+    }
相关推荐
chlk1231 小时前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
阿巴斯甜1 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
舒一笑2 小时前
Ubuntu系统安装CodeX出现问题
linux·后端
Kapaseker2 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
改一下配置文件2 小时前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
xq95273 小时前
Andorid Google 登录接入文档
android
黄林晴4 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
深紫色的三北六号12 小时前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash16 小时前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
冬奇Lab17 小时前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读