一、功能概述
在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;
+ }