diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index dc990afd729bd..d52e23732d8e5 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -30,6 +30,7 @@ import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import java.io.File; @@ -48,7 +49,9 @@ import java.util.stream.Collectors; class ApexManager { static final String TAG = "ApexManager"; private final IApexService mApexService; - private final Map mActivePackagesCache; + private final Object mLock = new Object(); + @GuardedBy("mLock") + private Map mActivePackagesCache; ApexManager() { try { @@ -57,31 +60,35 @@ class ApexManager { } catch (ServiceNotFoundException e) { throw new IllegalStateException("Required service apexservice not available"); } - mActivePackagesCache = populateActivePackagesCache(); } - @NonNull - private Map populateActivePackagesCache() { - try { - List list = new ArrayList<>(); - final ApexInfo[] activePkgs = mApexService.getActivePackages(); - for (ApexInfo ai : activePkgs) { - // 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.packagePath)).isDirectory()) { - break; - } - try { - list.add(PackageParser.generatePackageInfoFromApex( - new File(ai.packagePath), true /* collect certs */)); - } catch (PackageParserException pe) { - throw new IllegalStateException("Unable to parse: " + ai, pe); - } + private void populateActivePackagesCacheIfNeeded() { + synchronized (mLock) { + if (mActivePackagesCache != null) { + return; + } + try { + List list = new ArrayList<>(); + final ApexInfo[] activePkgs = mApexService.getActivePackages(); + for (ApexInfo ai : activePkgs) { + // 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.packagePath)).isDirectory()) { + break; + } + try { + list.add(PackageParser.generatePackageInfoFromApex( + new File(ai.packagePath), true /* collect certs */)); + } catch (PackageParserException pe) { + throw new IllegalStateException("Unable to parse: " + ai, pe); + } + } + mActivePackagesCache = list.stream().collect( + Collectors.toMap(p -> p.packageName, Function.identity())); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); + throw new RuntimeException(re); } - return list.stream().collect(Collectors.toMap(p -> p.packageName, Function.identity())); - } catch (RemoteException re) { - Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); - throw new RuntimeException(re); } } @@ -96,6 +103,7 @@ class ApexManager { * is not found. */ @Nullable PackageInfo getActivePackage(String packageName) { + populateActivePackagesCacheIfNeeded(); return mActivePackagesCache.get(packageName); } @@ -106,6 +114,7 @@ class ApexManager { * active package. */ Collection getActivePackages() { + populateActivePackagesCacheIfNeeded(); return mActivePackagesCache.values(); } @@ -217,7 +226,7 @@ class ApexManager { ipw.println("Active APEX packages:"); ipw.increaseIndent(); try { - populateActivePackagesCache(); + populateActivePackagesCacheIfNeeded(); for (PackageInfo pi : mActivePackagesCache.values()) { if (packageName != null && !packageName.equals(pi.packageName)) { continue; @@ -254,4 +263,8 @@ class ApexManager { ipw.println("Couldn't communicate with apexd."); } } + + public void onBootCompleted() { + populateActivePackagesCacheIfNeeded(); + } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index d501c4f76e75c..cced0f4a7eb25 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -209,8 +209,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements mStagingManager = new StagingManager(pm, this, am); } - private void setBootCompleted() { + private void onBootCompleted() { mBootCompleted = true; + // Tell APEX manager about it as well + mApexManager.onBootCompleted(); } boolean isBootCompleted() { @@ -223,7 +225,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - setBootCompleted(); + onBootCompleted(); mContext.unregisterReceiver(this); } }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));