Loading services/core/java/com/android/server/pm/ApexManager.java +185 −123 Original line number Diff line number Diff line Loading @@ -16,22 +16,22 @@ package com.android.server.pm; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.apex.ApexInfo; import android.apex.ApexInfoList; import android.apex.ApexSessionInfo; import android.apex.ApexSessionParams; import android.apex.IApexService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.parsing.PackageInfoWithoutStateUtils; import android.os.Environment; import android.os.RemoteException; import android.os.ServiceManager; Loading @@ -44,8 +44,9 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.server.pm.parsing.PackageParser2; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.utils.TimingsTraceAndSlog; Loading @@ -61,7 +62,9 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; /** Loading @@ -72,7 +75,7 @@ public abstract class ApexManager { private static final String TAG = "ApexManager"; static final int MATCH_ACTIVE_PACKAGE = 1 << 0; public static final int MATCH_ACTIVE_PACKAGE = 1 << 0; static final int MATCH_FACTORY_PACKAGE = 1 << 1; private static final Singleton<ApexManager> sApexManagerSingleton = Loading Loading @@ -139,7 +142,14 @@ public abstract class ApexManager { */ public abstract List<ActiveApexInfo> getActiveApexInfos(); abstract void systemReady(Context context); /** * Called by package manager service to scan apex package files when device boots up. * * @param packageParser The package parser which supports caches. * @param executorService An executor to support parallel package parsing. */ abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService); /** * Retrieves information about an APEX package. Loading @@ -154,7 +164,7 @@ public abstract class ApexManager { * is not found. */ @Nullable abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags); public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags); /** * Retrieves information about all active APEX packages. Loading Loading @@ -188,6 +198,27 @@ public abstract class ApexManager { */ abstract boolean isApexPackage(String packageName); /** * Whether the APEX package is pre-installed or not. * * @param packageInfo the package to check * @return {@code true} if this package is pre-installed, {@code false} otherwise. */ public static boolean isFactory(@NonNull PackageInfo packageInfo) { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } /** * Returns the active apex package's name that contains the (apk) package. * * @param containedPackage The (apk) package that might be in a apex * @return the apex package's name of {@code null} if the {@code containedPackage} is not inside * any apex. */ @Nullable public abstract String getActiveApexPackageNameContainingPackage( @NonNull AndroidPackage containedPackage); /** * Retrieves information about an apexd staged session i.e. the internal state used by apexd to * track the different states of a session. Loading Loading @@ -342,7 +373,7 @@ public abstract class ApexManager { * difference between {@code packageName} and {@code apexModuleName}. */ @GuardedBy("mLock") private Map<String, List<String>> mApksInApex = new ArrayMap<>(); private ArrayMap<String, List<String>> mApksInApex = new ArrayMap<>(); @GuardedBy("mLock") private List<PackageInfo> mAllPackagesCache; Loading @@ -357,7 +388,7 @@ public abstract class ApexManager { * the apk container to {@code apexModuleName} of the apex-payload inside. */ @GuardedBy("mLock") private Map<String, String> mPackageNameToApexModuleName; private ArrayMap<String, String> mPackageNameToApexModuleName; ApexManagerImpl(IApexService apexService) { mApexService = apexService; Loading @@ -373,16 +404,6 @@ public abstract class ApexManager { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0; } /** * Whether the APEX package is pre-installed or not. * * @param packageInfo the package to check * @return {@code true} if this package is pre-installed, {@code false} otherwise. */ private static boolean isFactory(PackageInfo packageInfo) { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } @Override public List<ActiveApexInfo> getActiveApexInfos() { final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", Loading Loading @@ -411,77 +432,63 @@ public abstract class ApexManager { } @Override void systemReady(Context context) { context.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Post populateAllPackagesCacheIfNeeded to a background thread, since it's // expensive to run it in broadcast handler thread. BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded()); context.unregisterReceiver(this); void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanApexPackagesTraced"); try { synchronized (mLock) { scanApexPackagesInternalLocked(packageParser, executorService); } }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } private void populatePackageNameToApexModuleNameIfNeeded() { synchronized (mLock) { if (mPackageNameToApexModuleName != null) { return; } @GuardedBy("mLock") private void scanApexPackagesInternalLocked(PackageParser2 packageParser, ExecutorService executorService) { final ApexInfo[] allPkgs; try { mAllPackagesCache = new ArrayList<>(); mPackageNameToApexModuleName = new ArrayMap<>(); final ApexInfo[] allPkgs = mApexService.getAllPackages(); for (int i = 0; i < allPkgs.length; i++) { ApexInfo ai = allPkgs[i]; PackageParser.PackageLite pkgLite; try { File apexFile = new File(ai.modulePath); pkgLite = PackageParser.parsePackageLite(apexFile, 0); } catch (PackageParser.PackageParserException pe) { throw new IllegalStateException("Unable to parse: " + ai.modulePath, pe); } mPackageNameToApexModuleName.put(pkgLite.packageName, ai.moduleName); } allPkgs = mApexService.getAllPackages(); } catch (RemoteException re) { Slog.e(TAG, "Unable to retrieve packages from apexservice: ", re); Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); throw new RuntimeException(re); } } } private void populateAllPackagesCacheIfNeeded() { synchronized (mLock) { if (mAllPackagesCache != null) { if (allPkgs.length == 0) { return; } try { mAllPackagesCache = new ArrayList<>(); HashSet<String> activePackagesSet = new HashSet<>(); HashSet<String> factoryPackagesSet = new HashSet<>(); final ApexInfo[] allPkgs = mApexService.getAllPackages(); for (ApexInfo ai : allPkgs) { // If the device is using flattened APEX, don't report any APEX // packages since they won't be managed or updated by PackageManager. if ((new File(ai.modulePath)).isDirectory()) { break; } int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_SIGNATURES; PackageParser.Package pkg; try { ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>(); ParallelPackageParser parallelPackageParser = new ParallelPackageParser(packageParser, executorService); for (ApexInfo ai : allPkgs) { File apexFile = new File(ai.modulePath); PackageParser pp = new PackageParser(); pkg = pp.parsePackage(apexFile, flags, false); PackageParser.collectCertificates(pkg, false); } catch (PackageParser.PackageParserException pe) { throw new IllegalStateException("Unable to parse: " + ai, pe); parallelPackageParser.submit(apexFile, flags); parsingApexInfo.put(apexFile, ai); } final PackageInfo packageInfo = PackageParser.generatePackageInfo(pkg, ai, flags); HashSet<String> activePackagesSet = new HashSet<>(); HashSet<String> factoryPackagesSet = new HashSet<>(); // Process results one by one for (int i = 0; i < parsingApexInfo.size(); i++) { ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); Throwable throwable = parseResult.throwable; ApexInfo ai = parsingApexInfo.get(parseResult.scanFile); if (throwable == null) { final PackageInfo packageInfo = PackageInfoWithoutStateUtils.generate( parseResult.parsedPackage, ai, flags); if (packageInfo == null) { throw new IllegalStateException("Unable to generate package info: " + ai.modulePath); } mAllPackagesCache.add(packageInfo); mPackageNameToApexModuleName.put(packageInfo.packageName, ai.moduleName); if (ai.isActive) { if (activePackagesSet.contains(packageInfo.packageName)) { throw new IllegalStateException( Loading @@ -498,17 +505,21 @@ public abstract class ApexManager { } factoryPackagesSet.add(packageInfo.packageName); } } } catch (RemoteException re) { Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); throw new RuntimeException(re); } else if (throwable instanceof PackageParser.PackageParserException) { throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); } else { throw new IllegalStateException("Unexpected exception occurred while parsing " + ai.modulePath, throwable); } } } @Override @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) { populateAllPackagesCacheIfNeeded(); @Nullable public PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) { Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0; boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0; for (PackageInfo packageInfo: mAllPackagesCache) { Loading @@ -525,7 +536,8 @@ public abstract class ApexManager { @Override List<PackageInfo> getActivePackages() { populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); return mAllPackagesCache .stream() .filter(item -> isActive(item)) Loading @@ -534,7 +546,8 @@ public abstract class ApexManager { @Override List<PackageInfo> getFactoryPackages() { populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); return mAllPackagesCache .stream() .filter(item -> isFactory(item)) Loading @@ -543,7 +556,8 @@ public abstract class ApexManager { @Override List<PackageInfo> getInactivePackages() { populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); return mAllPackagesCache .stream() .filter(item -> !isActive(item)) Loading @@ -553,7 +567,8 @@ public abstract class ApexManager { @Override boolean isApexPackage(String packageName) { if (!isApexSupported()) return false; populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); for (PackageInfo packageInfo : mAllPackagesCache) { if (packageInfo.packageName.equals(packageName)) { return true; Loading @@ -562,6 +577,36 @@ public abstract class ApexManager { return false; } @Override @Nullable public String getActiveApexPackageNameContainingPackage( @NonNull AndroidPackage containedPackage) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); Objects.requireNonNull(containedPackage); synchronized (mLock) { int numApksInApex = mApksInApex.size(); for (int apkInApexNum = 0; apkInApexNum < numApksInApex; apkInApexNum++) { if (mApksInApex.valueAt(apkInApexNum).contains( containedPackage.getPackageName())) { String apexModuleName = mApksInApex.keyAt(apkInApexNum); int numApexPkgs = mPackageNameToApexModuleName.size(); for (int apexPkgNum = 0; apexPkgNum < numApexPkgs; apexPkgNum++) { if (mPackageNameToApexModuleName.valueAt(apexPkgNum).equals( apexModuleName)) { return mPackageNameToApexModuleName.keyAt(apexPkgNum); } } } } } return null; } @Override @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) { try { Loading Loading @@ -684,8 +729,9 @@ public abstract class ApexManager { @Override List<String> getApksInApex(String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); String moduleName = mPackageNameToApexModuleName.get(apexPackageName); if (moduleName == null) { return Collections.emptyList(); Loading @@ -697,17 +743,19 @@ public abstract class ApexManager { @Override @Nullable public String getApexModuleNameForPackageName(String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); return mPackageNameToApexModuleName.get(apexPackageName); } } @Override public long snapshotCeData(int userId, int rollbackId, String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); String apexModuleName; synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); apexModuleName = mPackageNameToApexModuleName.get(apexPackageName); } if (apexModuleName == null) { Loading @@ -724,9 +772,10 @@ public abstract class ApexManager { @Override public boolean restoreCeData(int userId, int rollbackId, String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); String apexModuleName; synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); apexModuleName = mPackageNameToApexModuleName.get(apexPackageName); } if (apexModuleName == null) { Loading Loading @@ -797,15 +846,7 @@ public abstract class ApexManager { void dump(PrintWriter pw, @Nullable String packageName) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); try { populateAllPackagesCacheIfNeeded(); ipw.println(); ipw.println("Active APEX packages:"); dumpFromPackagesCache(getActivePackages(), packageName, ipw); ipw.println("Inactive APEX packages:"); dumpFromPackagesCache(getInactivePackages(), packageName, ipw); ipw.println("Factory APEX packages:"); dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); ipw.increaseIndent(); ipw.println("APEX session state:"); ipw.increaseIndent(); final ApexSessionInfo[] sessions = mApexService.getSessions(); Loading Loading @@ -834,6 +875,17 @@ public abstract class ApexManager { ipw.decreaseIndent(); } ipw.decreaseIndent(); ipw.println(); if (mAllPackagesCache == null) { ipw.println("APEX packages have not been scanned"); return; } ipw.println("Active APEX packages:"); dumpFromPackagesCache(getActivePackages(), packageName, ipw); ipw.println("Inactive APEX packages:"); dumpFromPackagesCache(getInactivePackages(), packageName, ipw); ipw.println("Factory APEX packages:"); dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); } catch (RemoteException e) { ipw.println("Couldn't communicate with apexd."); } Loading Loading @@ -879,12 +931,13 @@ public abstract class ApexManager { } @Override void systemReady(Context context) { void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService) { // No-op } @Override PackageInfo getPackageInfo(String packageName, int flags) { public PackageInfo getPackageInfo(String packageName, int flags) { return null; } Loading @@ -908,6 +961,15 @@ public abstract class ApexManager { return false; } @Override @Nullable public String getActiveApexPackageNameContainingPackage( @NonNull AndroidPackage containedPackage) { Objects.requireNonNull(containedPackage); return null; } @Override ApexSessionInfo getStagedSessionInfo(int sessionId) { throw new UnsupportedOperationException(); Loading services/core/java/com/android/server/pm/PackageManagerService.java +3 −1 Original line number Diff line number Diff line Loading @@ -2900,6 +2900,9 @@ public class PackageManagerService extends IPackageManager.Stub mMetrics, mCacheDir, mPackageParserCallback); ExecutorService executorService = ParallelPackageParser.makeExecutorService(); // Prepare apex package info before scanning APKs, these information are needed when // scanning apk in apex. mApexManager.scanApexPackagesTraced(packageParser, executorService); // Collect vendor/product/system_ext overlay packages. (Do this before scanning // any apps.) // For security and version matching reason, only consider overlay packages if they Loading Loading @@ -20696,7 +20699,6 @@ public class PackageManagerService extends IPackageManager.Stub storage.registerListener(mStorageListener); mInstallerService.systemReady(); mApexManager.systemReady(mContext); mPackageDexOptimizer.systemReady(); mInjector.getStorageManagerInternal().addExternalStoragePolicy( services/core/java/com/android/server/pm/permission/PermissionManagerService.java +12 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED; import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED; import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE; import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS; Loading Loading @@ -130,6 +131,7 @@ import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemConfig; import com.android.server.Watchdog; import com.android.server.pm.ApexManager; import com.android.server.pm.PackageManagerServiceUtils; import com.android.server.pm.PackageSetting; import com.android.server.pm.SharedUserSetting; Loading Loading @@ -3317,8 +3319,16 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged() && !platformPackage && platformPermission) { if (!hasPrivappWhitelistEntry(perm, pkg)) { // Only report violations for apps on system image if (!mSystemReady && !pkgSetting.getPkgState().isUpdatedSystemApp()) { ApexManager apexMgr = ApexManager.getInstance(); String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(pkg); // Only enforce whitelist this on boot if (!mSystemReady // Updated system apps do not need to be whitelisted && !pkgSetting.getPkgState().isUpdatedSystemApp() // Apps that are in updated apexs' do not need to be whitelisted && (apexContainingPkg == null || apexMgr.isFactory( apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE)))) { // it's only a reportable violation if the permission isn't explicitly denied ArraySet<String> deniedPermissions = null; if (pkg.isVendor()) { Loading services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +23 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/pm/ApexManager.java +185 −123 Original line number Diff line number Diff line Loading @@ -16,22 +16,22 @@ package com.android.server.pm; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.apex.ApexInfo; import android.apex.ApexInfoList; import android.apex.ApexSessionInfo; import android.apex.ApexSessionParams; import android.apex.IApexService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.parsing.PackageInfoWithoutStateUtils; import android.os.Environment; import android.os.RemoteException; import android.os.ServiceManager; Loading @@ -44,8 +44,9 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.server.pm.parsing.PackageParser2; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.utils.TimingsTraceAndSlog; Loading @@ -61,7 +62,9 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; /** Loading @@ -72,7 +75,7 @@ public abstract class ApexManager { private static final String TAG = "ApexManager"; static final int MATCH_ACTIVE_PACKAGE = 1 << 0; public static final int MATCH_ACTIVE_PACKAGE = 1 << 0; static final int MATCH_FACTORY_PACKAGE = 1 << 1; private static final Singleton<ApexManager> sApexManagerSingleton = Loading Loading @@ -139,7 +142,14 @@ public abstract class ApexManager { */ public abstract List<ActiveApexInfo> getActiveApexInfos(); abstract void systemReady(Context context); /** * Called by package manager service to scan apex package files when device boots up. * * @param packageParser The package parser which supports caches. * @param executorService An executor to support parallel package parsing. */ abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService); /** * Retrieves information about an APEX package. Loading @@ -154,7 +164,7 @@ public abstract class ApexManager { * is not found. */ @Nullable abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags); public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags); /** * Retrieves information about all active APEX packages. Loading Loading @@ -188,6 +198,27 @@ public abstract class ApexManager { */ abstract boolean isApexPackage(String packageName); /** * Whether the APEX package is pre-installed or not. * * @param packageInfo the package to check * @return {@code true} if this package is pre-installed, {@code false} otherwise. */ public static boolean isFactory(@NonNull PackageInfo packageInfo) { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } /** * Returns the active apex package's name that contains the (apk) package. * * @param containedPackage The (apk) package that might be in a apex * @return the apex package's name of {@code null} if the {@code containedPackage} is not inside * any apex. */ @Nullable public abstract String getActiveApexPackageNameContainingPackage( @NonNull AndroidPackage containedPackage); /** * Retrieves information about an apexd staged session i.e. the internal state used by apexd to * track the different states of a session. Loading Loading @@ -342,7 +373,7 @@ public abstract class ApexManager { * difference between {@code packageName} and {@code apexModuleName}. */ @GuardedBy("mLock") private Map<String, List<String>> mApksInApex = new ArrayMap<>(); private ArrayMap<String, List<String>> mApksInApex = new ArrayMap<>(); @GuardedBy("mLock") private List<PackageInfo> mAllPackagesCache; Loading @@ -357,7 +388,7 @@ public abstract class ApexManager { * the apk container to {@code apexModuleName} of the apex-payload inside. */ @GuardedBy("mLock") private Map<String, String> mPackageNameToApexModuleName; private ArrayMap<String, String> mPackageNameToApexModuleName; ApexManagerImpl(IApexService apexService) { mApexService = apexService; Loading @@ -373,16 +404,6 @@ public abstract class ApexManager { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0; } /** * Whether the APEX package is pre-installed or not. * * @param packageInfo the package to check * @return {@code true} if this package is pre-installed, {@code false} otherwise. */ private static boolean isFactory(PackageInfo packageInfo) { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } @Override public List<ActiveApexInfo> getActiveApexInfos() { final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", Loading Loading @@ -411,77 +432,63 @@ public abstract class ApexManager { } @Override void systemReady(Context context) { context.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Post populateAllPackagesCacheIfNeeded to a background thread, since it's // expensive to run it in broadcast handler thread. BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded()); context.unregisterReceiver(this); void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanApexPackagesTraced"); try { synchronized (mLock) { scanApexPackagesInternalLocked(packageParser, executorService); } }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } private void populatePackageNameToApexModuleNameIfNeeded() { synchronized (mLock) { if (mPackageNameToApexModuleName != null) { return; } @GuardedBy("mLock") private void scanApexPackagesInternalLocked(PackageParser2 packageParser, ExecutorService executorService) { final ApexInfo[] allPkgs; try { mAllPackagesCache = new ArrayList<>(); mPackageNameToApexModuleName = new ArrayMap<>(); final ApexInfo[] allPkgs = mApexService.getAllPackages(); for (int i = 0; i < allPkgs.length; i++) { ApexInfo ai = allPkgs[i]; PackageParser.PackageLite pkgLite; try { File apexFile = new File(ai.modulePath); pkgLite = PackageParser.parsePackageLite(apexFile, 0); } catch (PackageParser.PackageParserException pe) { throw new IllegalStateException("Unable to parse: " + ai.modulePath, pe); } mPackageNameToApexModuleName.put(pkgLite.packageName, ai.moduleName); } allPkgs = mApexService.getAllPackages(); } catch (RemoteException re) { Slog.e(TAG, "Unable to retrieve packages from apexservice: ", re); Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); throw new RuntimeException(re); } } } private void populateAllPackagesCacheIfNeeded() { synchronized (mLock) { if (mAllPackagesCache != null) { if (allPkgs.length == 0) { return; } try { mAllPackagesCache = new ArrayList<>(); HashSet<String> activePackagesSet = new HashSet<>(); HashSet<String> factoryPackagesSet = new HashSet<>(); final ApexInfo[] allPkgs = mApexService.getAllPackages(); for (ApexInfo ai : allPkgs) { // If the device is using flattened APEX, don't report any APEX // packages since they won't be managed or updated by PackageManager. if ((new File(ai.modulePath)).isDirectory()) { break; } int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_SIGNATURES; PackageParser.Package pkg; try { ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>(); ParallelPackageParser parallelPackageParser = new ParallelPackageParser(packageParser, executorService); for (ApexInfo ai : allPkgs) { File apexFile = new File(ai.modulePath); PackageParser pp = new PackageParser(); pkg = pp.parsePackage(apexFile, flags, false); PackageParser.collectCertificates(pkg, false); } catch (PackageParser.PackageParserException pe) { throw new IllegalStateException("Unable to parse: " + ai, pe); parallelPackageParser.submit(apexFile, flags); parsingApexInfo.put(apexFile, ai); } final PackageInfo packageInfo = PackageParser.generatePackageInfo(pkg, ai, flags); HashSet<String> activePackagesSet = new HashSet<>(); HashSet<String> factoryPackagesSet = new HashSet<>(); // Process results one by one for (int i = 0; i < parsingApexInfo.size(); i++) { ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); Throwable throwable = parseResult.throwable; ApexInfo ai = parsingApexInfo.get(parseResult.scanFile); if (throwable == null) { final PackageInfo packageInfo = PackageInfoWithoutStateUtils.generate( parseResult.parsedPackage, ai, flags); if (packageInfo == null) { throw new IllegalStateException("Unable to generate package info: " + ai.modulePath); } mAllPackagesCache.add(packageInfo); mPackageNameToApexModuleName.put(packageInfo.packageName, ai.moduleName); if (ai.isActive) { if (activePackagesSet.contains(packageInfo.packageName)) { throw new IllegalStateException( Loading @@ -498,17 +505,21 @@ public abstract class ApexManager { } factoryPackagesSet.add(packageInfo.packageName); } } } catch (RemoteException re) { Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); throw new RuntimeException(re); } else if (throwable instanceof PackageParser.PackageParserException) { throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); } else { throw new IllegalStateException("Unexpected exception occurred while parsing " + ai.modulePath, throwable); } } } @Override @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) { populateAllPackagesCacheIfNeeded(); @Nullable public PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) { Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0; boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0; for (PackageInfo packageInfo: mAllPackagesCache) { Loading @@ -525,7 +536,8 @@ public abstract class ApexManager { @Override List<PackageInfo> getActivePackages() { populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); return mAllPackagesCache .stream() .filter(item -> isActive(item)) Loading @@ -534,7 +546,8 @@ public abstract class ApexManager { @Override List<PackageInfo> getFactoryPackages() { populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); return mAllPackagesCache .stream() .filter(item -> isFactory(item)) Loading @@ -543,7 +556,8 @@ public abstract class ApexManager { @Override List<PackageInfo> getInactivePackages() { populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); return mAllPackagesCache .stream() .filter(item -> !isActive(item)) Loading @@ -553,7 +567,8 @@ public abstract class ApexManager { @Override boolean isApexPackage(String packageName) { if (!isApexSupported()) return false; populateAllPackagesCacheIfNeeded(); Preconditions.checkState(mAllPackagesCache != null, "APEX packages have not been scanned"); for (PackageInfo packageInfo : mAllPackagesCache) { if (packageInfo.packageName.equals(packageName)) { return true; Loading @@ -562,6 +577,36 @@ public abstract class ApexManager { return false; } @Override @Nullable public String getActiveApexPackageNameContainingPackage( @NonNull AndroidPackage containedPackage) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); Objects.requireNonNull(containedPackage); synchronized (mLock) { int numApksInApex = mApksInApex.size(); for (int apkInApexNum = 0; apkInApexNum < numApksInApex; apkInApexNum++) { if (mApksInApex.valueAt(apkInApexNum).contains( containedPackage.getPackageName())) { String apexModuleName = mApksInApex.keyAt(apkInApexNum); int numApexPkgs = mPackageNameToApexModuleName.size(); for (int apexPkgNum = 0; apexPkgNum < numApexPkgs; apexPkgNum++) { if (mPackageNameToApexModuleName.valueAt(apexPkgNum).equals( apexModuleName)) { return mPackageNameToApexModuleName.keyAt(apexPkgNum); } } } } } return null; } @Override @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) { try { Loading Loading @@ -684,8 +729,9 @@ public abstract class ApexManager { @Override List<String> getApksInApex(String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); String moduleName = mPackageNameToApexModuleName.get(apexPackageName); if (moduleName == null) { return Collections.emptyList(); Loading @@ -697,17 +743,19 @@ public abstract class ApexManager { @Override @Nullable public String getApexModuleNameForPackageName(String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); return mPackageNameToApexModuleName.get(apexPackageName); } } @Override public long snapshotCeData(int userId, int rollbackId, String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); String apexModuleName; synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); apexModuleName = mPackageNameToApexModuleName.get(apexPackageName); } if (apexModuleName == null) { Loading @@ -724,9 +772,10 @@ public abstract class ApexManager { @Override public boolean restoreCeData(int userId, int rollbackId, String apexPackageName) { populatePackageNameToApexModuleNameIfNeeded(); String apexModuleName; synchronized (mLock) { Preconditions.checkState(mPackageNameToApexModuleName != null, "APEX packages have not been scanned"); apexModuleName = mPackageNameToApexModuleName.get(apexPackageName); } if (apexModuleName == null) { Loading Loading @@ -797,15 +846,7 @@ public abstract class ApexManager { void dump(PrintWriter pw, @Nullable String packageName) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); try { populateAllPackagesCacheIfNeeded(); ipw.println(); ipw.println("Active APEX packages:"); dumpFromPackagesCache(getActivePackages(), packageName, ipw); ipw.println("Inactive APEX packages:"); dumpFromPackagesCache(getInactivePackages(), packageName, ipw); ipw.println("Factory APEX packages:"); dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); ipw.increaseIndent(); ipw.println("APEX session state:"); ipw.increaseIndent(); final ApexSessionInfo[] sessions = mApexService.getSessions(); Loading Loading @@ -834,6 +875,17 @@ public abstract class ApexManager { ipw.decreaseIndent(); } ipw.decreaseIndent(); ipw.println(); if (mAllPackagesCache == null) { ipw.println("APEX packages have not been scanned"); return; } ipw.println("Active APEX packages:"); dumpFromPackagesCache(getActivePackages(), packageName, ipw); ipw.println("Inactive APEX packages:"); dumpFromPackagesCache(getInactivePackages(), packageName, ipw); ipw.println("Factory APEX packages:"); dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); } catch (RemoteException e) { ipw.println("Couldn't communicate with apexd."); } Loading Loading @@ -879,12 +931,13 @@ public abstract class ApexManager { } @Override void systemReady(Context context) { void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService) { // No-op } @Override PackageInfo getPackageInfo(String packageName, int flags) { public PackageInfo getPackageInfo(String packageName, int flags) { return null; } Loading @@ -908,6 +961,15 @@ public abstract class ApexManager { return false; } @Override @Nullable public String getActiveApexPackageNameContainingPackage( @NonNull AndroidPackage containedPackage) { Objects.requireNonNull(containedPackage); return null; } @Override ApexSessionInfo getStagedSessionInfo(int sessionId) { throw new UnsupportedOperationException(); Loading
services/core/java/com/android/server/pm/PackageManagerService.java +3 −1 Original line number Diff line number Diff line Loading @@ -2900,6 +2900,9 @@ public class PackageManagerService extends IPackageManager.Stub mMetrics, mCacheDir, mPackageParserCallback); ExecutorService executorService = ParallelPackageParser.makeExecutorService(); // Prepare apex package info before scanning APKs, these information are needed when // scanning apk in apex. mApexManager.scanApexPackagesTraced(packageParser, executorService); // Collect vendor/product/system_ext overlay packages. (Do this before scanning // any apps.) // For security and version matching reason, only consider overlay packages if they Loading Loading @@ -20696,7 +20699,6 @@ public class PackageManagerService extends IPackageManager.Stub storage.registerListener(mStorageListener); mInstallerService.systemReady(); mApexManager.systemReady(mContext); mPackageDexOptimizer.systemReady(); mInjector.getStorageManagerInternal().addExternalStoragePolicy(
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +12 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED; import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED; import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE; import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS; Loading Loading @@ -130,6 +131,7 @@ import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemConfig; import com.android.server.Watchdog; import com.android.server.pm.ApexManager; import com.android.server.pm.PackageManagerServiceUtils; import com.android.server.pm.PackageSetting; import com.android.server.pm.SharedUserSetting; Loading Loading @@ -3317,8 +3319,16 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged() && !platformPackage && platformPermission) { if (!hasPrivappWhitelistEntry(perm, pkg)) { // Only report violations for apps on system image if (!mSystemReady && !pkgSetting.getPkgState().isUpdatedSystemApp()) { ApexManager apexMgr = ApexManager.getInstance(); String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(pkg); // Only enforce whitelist this on boot if (!mSystemReady // Updated system apps do not need to be whitelisted && !pkgSetting.getPkgState().isUpdatedSystemApp() // Apps that are in updated apexs' do not need to be whitelisted && (apexContainingPkg == null || apexMgr.isFactory( apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE)))) { // it's only a reportable violation if the permission isn't explicitly denied ArraySet<String> deniedPermissions = null; if (pkg.isVendor()) { Loading
services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +23 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes