diff options
| author | 2021-06-29 20:36:15 +0000 | |
|---|---|---|
| committer | 2021-06-29 20:36:15 +0000 | |
| commit | 8d440c0566910525b6bd92ebc1ccaec392df6f40 (patch) | |
| tree | 4799fbecbe34101426fb09368c7f91b2a887f440 | |
| parent | 4e395b98212bea2458cfeab6d863508db23c9ca5 (diff) | |
| parent | cb5a80ea57b51fcde117dea253c546dbba9f27f1 (diff) | |
Merge changes from topic "revert-15058002-SNQUARIDWJ" into sc-dev
* changes:
Revert^2 "Deprecate Context#createApplicationContext"
Revert "Version LoadedApk cache using base code path"
Revert "Apply overlay changes with config change"
19 files changed, 319 insertions, 593 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 4182ac3e572d..034ad8e83fd3 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -36,6 +36,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; import android.app.backup.BackupAgent; @@ -61,6 +62,7 @@ import android.content.ContentCaptureOptions; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; +import android.content.Context.CreatePackageOptions; import android.content.IContentProvider; import android.content.IIntentReceiver; import android.content.Intent; @@ -71,6 +73,7 @@ import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionInfo; @@ -218,8 +221,6 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.net.InetAddress; @@ -230,7 +231,6 @@ import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -419,16 +419,6 @@ public final class ActivityThread extends ClientTransactionHandler @GuardedBy("mResourcesManager") @UnsupportedAppUsage final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>(); - - @GuardedBy("mResourcesManager") - private final ArrayMap<List<String>, WeakReference<LoadedApk>> mPackageNonAMS = - new ArrayMap<>(); - @GuardedBy("mResourcesManager") - private final ArrayMap<List<String>, WeakReference<LoadedApk>> mResourcePackagesNonAMS = - new ArrayMap<>(); - @GuardedBy("mResourcesManager") - private final ReferenceQueue<LoadedApk> mPackageRefQueue = new ReferenceQueue<>(); - @GuardedBy("mResourcesManager") final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<>(); @GuardedBy("mResourcesManager") @@ -1182,7 +1172,6 @@ public final class ActivityThread extends ClientTransactionHandler } public void scheduleApplicationInfoChanged(ApplicationInfo ai) { - mResourcesManager.updatePendingAppInfoUpdates(ai); mH.removeMessages(H.APPLICATION_INFO_CHANGED, ai); sendMessage(H.APPLICATION_INFO_CHANGED, ai); } @@ -2385,281 +2374,72 @@ public final class ActivityThread extends ClientTransactionHandler return mH; } - /** - * If {@code retainReferences} is false, prunes all {@link LoadedApk} representing any of the - * specified packages from the package caches. - * - * @return whether the cache contains a loaded apk representing any of the specified packages - */ - private boolean clearCachedApks() { - synchronized (mResourcesManager) { - Reference<? extends LoadedApk> enqueuedRef = mPackageRefQueue.poll(); - if (enqueuedRef == null) { - return false; - } - - final HashSet<Reference<? extends LoadedApk>> deadReferences = new HashSet<>(); - for (; enqueuedRef != null; enqueuedRef = mPackageRefQueue.poll()) { - deadReferences.add(enqueuedRef); - } - - return cleanWeakMapValues(mPackages, deadReferences) - || cleanWeakMapValues(mResourcePackages, deadReferences) - || cleanWeakMapValues(mPackageNonAMS, deadReferences) - || cleanWeakMapValues(mResourcePackages, deadReferences); - } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, + @CreatePackageOptions int flags) { + return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId()); } - private static <K> boolean cleanWeakMapValues(ArrayMap<K, WeakReference<LoadedApk>> map, - HashSet<Reference<? extends LoadedApk>> deadReferences) { - boolean hasPkgInfo = false; - for (int i = map.size() - 1; i >= 0; i--) { - if (deadReferences.contains(map.valueAt(i))) { - map.removeAt(i); - hasPkgInfo = true; - } - } - return hasPkgInfo; + public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, + @CreatePackageOptions int flags, @UserIdInt int userId) { + return getPackageInfo(packageName, compatInfo, flags, userId, 0 /* packageFlags */); } - /** - * Retrieves the previously cached {@link LoadedApk} that was created/updated with the most - * recent {@link ApplicationInfo} sent from the activity manager service. - */ - @Nullable - private LoadedApk peekLatestCachedApkFromAMS(@NonNull String packageName, boolean includeCode) { + public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, + @CreatePackageOptions int flags, @UserIdInt int userId, + @ApplicationInfoFlags int packageFlags) { + final boolean differentUser = (UserHandle.myUserId() != userId); + ApplicationInfo ai = PackageManager.getApplicationInfoAsUserCached( + packageName, + packageFlags | PackageManager.GET_SHARED_LIBRARY_FILES + | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, + (userId < 0) ? UserHandle.myUserId() : userId); synchronized (mResourcesManager) { WeakReference<LoadedApk> ref; - if (includeCode) { - return ((ref = mPackages.get(packageName)) != null) ? ref.get() : null; + if (differentUser) { + // Caching not supported across users + ref = null; + } else if ((flags & Context.CONTEXT_INCLUDE_CODE) != 0) { + ref = mPackages.get(packageName); } else { - return ((ref = mResourcePackages.get(packageName)) != null) ? ref.get() : null; - } - } - } - - /** - * Updates the previously cached {@link LoadedApk} that was created/updated using an - * {@link ApplicationInfo} sent from activity manager service. - * - * If {@code appInfo} is null, the most up-to-date {@link ApplicationInfo} will be fetched and - * used to update the cached package; otherwise, the specified app info will be used. - */ - private boolean updateLatestCachedApkFromAMS(@NonNull String packageName, - @Nullable ApplicationInfo appInfo, boolean updateActivityRecords) { - final LoadedApk[] loadedPackages = new LoadedApk[]{ - peekLatestCachedApkFromAMS(packageName, true), - peekLatestCachedApkFromAMS(packageName, false) - }; - - try { - if (appInfo == null) { - appInfo = sPackageManager.getApplicationInfo( - packageName, PackageManager.GET_SHARED_LIBRARY_FILES, - UserHandle.myUserId()); - } - } catch (RemoteException e) { - Slog.v(TAG, "Failed to get most recent app info for '" + packageName + "'", e); - return false; - } - - boolean hasPackage = false; - final String[] oldResDirs = new String[loadedPackages.length]; - for (int i = loadedPackages.length - 1; i >= 0; i--) { - final LoadedApk loadedPackage = loadedPackages[i]; - if (loadedPackage == null) { - continue; + ref = mResourcePackages.get(packageName); } - // If the package is being updated, yet it still has a valid LoadedApk object, the - // package was updated with PACKAGE_REMOVED_DONT_KILL. Adjust it's internal references - // to the application info and resources. - hasPackage = true; - if (updateActivityRecords && mActivities.size() > 0) { - for (ActivityClientRecord ar : mActivities.values()) { - if (ar.activityInfo.applicationInfo.packageName.equals(packageName)) { - ar.activityInfo.applicationInfo = appInfo; - ar.packageInfo = loadedPackage; - } + LoadedApk packageInfo = ref != null ? ref.get() : null; + if (ai != null && packageInfo != null) { + if (!isLoadedApkResourceDirsUpToDate(packageInfo, ai)) { + List<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths(this, ai, oldPaths); + packageInfo.updateApplicationInfo(ai, oldPaths); } - } - - updateLoadedApk(loadedPackage, appInfo); - oldResDirs[i] = loadedPackage.getResDir(); - } - if (hasPackage) { - synchronized (mResourcesManager) { - mResourcesManager.applyNewResourceDirs(appInfo, oldResDirs); - } - } - return hasPackage; - } - - private static List<String> makeNonAMSKey(@NonNull ApplicationInfo appInfo) { - final List<String> paths = new ArrayList<>(); - paths.add(appInfo.sourceDir); - if (appInfo.resourceDirs != null) { - for (String path : appInfo.resourceDirs) { - paths.add(path); - } - } - return paths; - } - - /** - * Retrieves the previously cached {@link LoadedApk}. - * - * If {@code isAppInfoFromAMS} is true, then {@code appInfo} will be used to update the paths - * of the previously cached {@link LoadedApk} that was created/updated using an - * {@link ApplicationInfo} sent from activity manager service. - */ - @Nullable - private LoadedApk retrieveCachedApk(@NonNull ApplicationInfo appInfo, boolean includeCode, - boolean isAppInfoFromAMS) { - if (UserHandle.myUserId() != UserHandle.getUserId(appInfo.uid)) { - // Caching not supported across users. - return null; - } - - if (isAppInfoFromAMS) { - LoadedApk loadedPackage = peekLatestCachedApkFromAMS(appInfo.packageName, includeCode); - if (loadedPackage != null) { - updateLoadedApk(loadedPackage, appInfo); - } - return loadedPackage; - } - - synchronized (mResourcesManager) { - WeakReference<LoadedApk> ref; - if (includeCode) { - return ((ref = mPackageNonAMS.get(makeNonAMSKey(appInfo))) != null) - ? ref.get() : null; - } else { - return ((ref = mResourcePackagesNonAMS.get(makeNonAMSKey(appInfo))) != null) - ? ref.get() : null; - } - } - } - - private static boolean isLoadedApkResourceDirsUpToDate(LoadedApk loadedApk, - ApplicationInfo appInfo) { - boolean baseDirsUpToDate = loadedApk.getResDir().equals(appInfo.sourceDir); - boolean resourceDirsUpToDate = Arrays.equals( - ArrayUtils.defeatNullable(appInfo.resourceDirs), - ArrayUtils.defeatNullable(loadedApk.getOverlayDirs())); - boolean overlayPathsUpToDate = Arrays.equals( - ArrayUtils.defeatNullable(appInfo.overlayPaths), - ArrayUtils.defeatNullable(loadedApk.getOverlayPaths())); - - return (loadedApk.mResources == null || loadedApk.mResources.getAssets().isUpToDate()) - && baseDirsUpToDate && resourceDirsUpToDate && overlayPathsUpToDate; - } - private void updateLoadedApk(@NonNull LoadedApk loadedPackage, - @NonNull ApplicationInfo appInfo) { - if (isLoadedApkResourceDirsUpToDate(loadedPackage, appInfo)) { - return; - } - - final List<String> oldPaths = new ArrayList<>(); - LoadedApk.makePaths(this, appInfo, oldPaths); - loadedPackage.updateApplicationInfo(appInfo, oldPaths); - } - - @Nullable - private LoadedApk createLoadedPackage(@NonNull ApplicationInfo appInfo, - @Nullable CompatibilityInfo compatInfo, @Nullable ClassLoader baseLoader, - boolean securityViolation, boolean includeCode, boolean registerPackage, - boolean isAppInfoFromAMS) { - final LoadedApk packageInfo = - new LoadedApk(this, appInfo, compatInfo, baseLoader, - securityViolation, includeCode - && (appInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); - - if (mSystemThread && "android".equals(appInfo.packageName)) { - packageInfo.installSystemApplicationInfo(appInfo, - getSystemContext().mPackageInfo.getClassLoader()); - } - - if (UserHandle.myUserId() != UserHandle.getUserId(appInfo.uid)) { - // Caching not supported across users - return packageInfo; - } - - synchronized (mResourcesManager) { - if (includeCode) { - if (isAppInfoFromAMS) { - mPackages.put(appInfo.packageName, - new WeakReference<>(packageInfo, mPackageRefQueue)); - } else { - mPackageNonAMS.put(makeNonAMSKey(appInfo), - new WeakReference<>(packageInfo, mPackageRefQueue)); - } - } else { - if (isAppInfoFromAMS) { - mResourcePackages.put(appInfo.packageName, - new WeakReference<>(packageInfo, mPackageRefQueue)); - } else { - mResourcePackagesNonAMS.put(makeNonAMSKey(appInfo), - new WeakReference<>(packageInfo, mPackageRefQueue)); + if (packageInfo.isSecurityViolation() + && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) { + throw new SecurityException( + "Requesting code from " + packageName + + " to be run in process " + + mBoundApplication.processName + + "/" + mBoundApplication.appInfo.uid); } + return packageInfo; } - return packageInfo; } - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, - int flags) { - return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId()); - } - public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, - int flags, int userId) { - final ApplicationInfo ai = PackageManager.getApplicationInfoAsUserCached( - packageName, - PackageManager.GET_SHARED_LIBRARY_FILES - | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, - (userId < 0) ? UserHandle.myUserId() : userId); - LoadedApk packageInfo = null; if (ai != null) { - packageInfo = retrieveCachedApk(ai, - (flags & Context.CONTEXT_INCLUDE_CODE) != 0, - false); - } - - if (packageInfo != null) { - if (packageInfo.isSecurityViolation() - && (flags & Context.CONTEXT_IGNORE_SECURITY) == 0) { - throw new SecurityException( - "Requesting code from " + packageName - + " to be run in process " - + mBoundApplication.processName - + "/" + mBoundApplication.appInfo.uid); - } - return packageInfo; + return getPackageInfo(ai, compatInfo, flags); } - return ai == null ? null : getPackageInfo(ai, compatInfo, flags, false); + return null; } - /** - * @deprecated Use {@link #getPackageInfo(ApplicationInfo, CompatibilityInfo, int, boolean)} - * instead. - */ - @Deprecated @UnsupportedAppUsage(trackingBug = 171933273) public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo, - int flags) { - return getPackageInfo(ai, compatInfo, flags, true); - } - - public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo, - @Context.CreatePackageOptions int flags, boolean isAppInfoFromAMS) { + @CreatePackageOptions int flags) { boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; boolean securityViolation = includeCode && ai.uid != 0 - && ai.uid != Process.SYSTEM_UID && (mBoundApplication == null - || !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)); + && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null + ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid) + : true); boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0; if ((flags&(Context.CONTEXT_INCLUDE_CODE |Context.CONTEXT_IGNORE_SECURITY)) @@ -2669,47 +2449,107 @@ public final class ActivityThread extends ClientTransactionHandler + " (with uid " + ai.uid + ")"; if (mBoundApplication != null) { msg = msg + " to be run in process " - + mBoundApplication.processName + " (with uid " - + mBoundApplication.appInfo.uid + ")"; + + mBoundApplication.processName + " (with uid " + + mBoundApplication.appInfo.uid + ")"; } throw new SecurityException(msg); } } return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode, - registerPackage, isAppInfoFromAMS); + registerPackage); } @Override @UnsupportedAppUsage public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) { - return getPackageInfo(ai, compatInfo, null, false, true, false, true); + return getPackageInfo(ai, compatInfo, null, false, true, false); } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) { synchronized (mResourcesManager) { - return peekLatestCachedApkFromAMS(packageName, includeCode); + WeakReference<LoadedApk> ref; + if (includeCode) { + ref = mPackages.get(packageName); + } else { + ref = mResourcePackages.get(packageName); + } + return ref != null ? ref.get() : null; } } private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, - boolean registerPackage, boolean isAppInfoFromAMS) { - LoadedApk packageInfo = retrieveCachedApk(aInfo, includeCode, - isAppInfoFromAMS); - if (packageInfo != null) { + boolean registerPackage) { + final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid)); + synchronized (mResourcesManager) { + WeakReference<LoadedApk> ref; + if (differentUser) { + // Caching not supported across users + ref = null; + } else if (includeCode) { + ref = mPackages.get(aInfo.packageName); + } else { + ref = mResourcePackages.get(aInfo.packageName); + } + + LoadedApk packageInfo = ref != null ? ref.get() : null; + + if (packageInfo != null) { + if (!isLoadedApkResourceDirsUpToDate(packageInfo, aInfo)) { + List<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths(this, aInfo, oldPaths); + packageInfo.updateApplicationInfo(aInfo, oldPaths); + } + + return packageInfo; + } + + if (localLOGV) { + Slog.v(TAG, (includeCode ? "Loading code package " + : "Loading resource-only package ") + aInfo.packageName + + " (in " + (mBoundApplication != null + ? mBoundApplication.processName : null) + + ")"); + } + + packageInfo = + new LoadedApk(this, aInfo, compatInfo, baseLoader, + securityViolation, includeCode + && (aInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); + + if (mSystemThread && "android".equals(aInfo.packageName)) { + packageInfo.installSystemApplicationInfo(aInfo, + getSystemContext().mPackageInfo.getClassLoader()); + } + + if (differentUser) { + // Caching not supported across users + } else if (includeCode) { + mPackages.put(aInfo.packageName, + new WeakReference<LoadedApk>(packageInfo)); + } else { + mResourcePackages.put(aInfo.packageName, + new WeakReference<LoadedApk>(packageInfo)); + } + return packageInfo; } - if (localLOGV) { - Slog.v(TAG, (includeCode ? "Loading code package " - : "Loading resource-only package ") + aInfo.packageName - + " (in " + (mBoundApplication != null - ? mBoundApplication.processName : null) - + ")"); - } - return createLoadedPackage(aInfo, compatInfo, baseLoader, - securityViolation, includeCode, registerPackage, isAppInfoFromAMS); + } + + private static boolean isLoadedApkResourceDirsUpToDate(LoadedApk loadedApk, + ApplicationInfo appInfo) { + Resources packageResources = loadedApk.mResources; + boolean resourceDirsUpToDate = Arrays.equals( + ArrayUtils.defeatNullable(appInfo.resourceDirs), + ArrayUtils.defeatNullable(loadedApk.getOverlayDirs())); + boolean overlayPathsUpToDate = Arrays.equals( + ArrayUtils.defeatNullable(appInfo.overlayPaths), + ArrayUtils.defeatNullable(loadedApk.getOverlayPaths())); + + return (packageResources == null || packageResources.getAssets().isUpToDate()) + && resourceDirsUpToDate && overlayPathsUpToDate; } @UnsupportedAppUsage @@ -3671,7 +3511,7 @@ public final class ActivityThread extends ClientTransactionHandler ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, - Context.CONTEXT_INCLUDE_CODE, true); + Context.CONTEXT_INCLUDE_CODE); } ComponentName component = r.intent.getComponent(); @@ -6154,10 +5994,40 @@ public final class ActivityThread extends ClientTransactionHandler @VisibleForTesting(visibility = PACKAGE) public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) { - // Updates triggered by package installation go through a package update receiver. Here we - // try to capture ApplicationInfo changes that are caused by other sources, such as - // overlays. That means we want to be as conservative about code changes as possible. - updateLatestCachedApkFromAMS(ai.packageName, ai, false); + // Updates triggered by package installation go through a package update + // receiver. Here we try to capture ApplicationInfo changes that are + // caused by other sources, such as overlays. That means we want to be as conservative + // about code changes as possible. Take the diff of the old ApplicationInfo and the new + // to see if anything needs to change. + LoadedApk apk; + LoadedApk resApk; + // Update all affected loaded packages with new package information + synchronized (mResourcesManager) { + WeakReference<LoadedApk> ref = mPackages.get(ai.packageName); + apk = ref != null ? ref.get() : null; + ref = mResourcePackages.get(ai.packageName); + resApk = ref != null ? ref.get() : null; + } + + final String[] oldResDirs = new String[2]; + + if (apk != null) { + oldResDirs[0] = apk.getResDir(); + final ArrayList<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths); + apk.updateApplicationInfo(ai, oldPaths); + } + if (resApk != null) { + oldResDirs[1] = resApk.getResDir(); + final ArrayList<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths(this, resApk.getApplicationInfo(), oldPaths); + resApk.updateApplicationInfo(ai, oldPaths); + } + + synchronized (mResourcesManager) { + // Update all affected Resources objects to use new ResourcesImpl + mResourcesManager.applyNewResourceDirs(ai, oldResDirs); + } } /** @@ -6334,7 +6204,29 @@ public final class ActivityThread extends ClientTransactionHandler case ApplicationThreadConstants.PACKAGE_REMOVED: case ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL: { - hasPkgInfo = clearCachedApks(); + final boolean killApp = cmd == ApplicationThreadConstants.PACKAGE_REMOVED; + if (packages == null) { + break; + } + synchronized (mResourcesManager) { + for (int i = packages.length - 1; i >= 0; i--) { + if (!hasPkgInfo) { + WeakReference<LoadedApk> ref = mPackages.get(packages[i]); + if (ref != null && ref.get() != null) { + hasPkgInfo = true; + } else { + ref = mResourcePackages.get(packages[i]); + if (ref != null && ref.get() != null) { + hasPkgInfo = true; + } + } + } + if (killApp) { + mPackages.remove(packages[i]); + mResourcePackages.remove(packages[i]); + } + } + } break; } case ApplicationThreadConstants.PACKAGE_REPLACED: @@ -6342,19 +6234,68 @@ public final class ActivityThread extends ClientTransactionHandler if (packages == null) { break; } - final List<String> packagesHandled = new ArrayList<>(); - for (int i = packages.length - 1; i >= 0; i--) { - final String packageName = packages[i]; - if (updateLatestCachedApkFromAMS(packageName, null, true)) { - hasPkgInfo = true; - packagesHandled.add(packageName); + + List<String> packagesHandled = new ArrayList<>(); + + synchronized (mResourcesManager) { + for (int i = packages.length - 1; i >= 0; i--) { + String packageName = packages[i]; + WeakReference<LoadedApk> ref = mPackages.get(packageName); + LoadedApk pkgInfo = ref != null ? ref.get() : null; + if (pkgInfo != null) { + hasPkgInfo = true; + } else { + ref = mResourcePackages.get(packageName); + pkgInfo = ref != null ? ref.get() : null; + if (pkgInfo != null) { + hasPkgInfo = true; + } + } + // If the package is being replaced, yet it still has a valid + // LoadedApk object, the package was updated with _DONT_KILL. + // Adjust it's internal references to the application info and + // resources. + if (pkgInfo != null) { + packagesHandled.add(packageName); + try { + final ApplicationInfo aInfo = + sPackageManager.getApplicationInfo( + packageName, + PackageManager.GET_SHARED_LIBRARY_FILES, + UserHandle.myUserId()); + + if (mActivities.size() > 0) { + for (ActivityClientRecord ar : mActivities.values()) { + if (ar.activityInfo.applicationInfo.packageName + .equals(packageName)) { + ar.activityInfo.applicationInfo = aInfo; + ar.packageInfo = pkgInfo; + } + } + } + + final String[] oldResDirs = { pkgInfo.getResDir() }; + + final ArrayList<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths(this, pkgInfo.getApplicationInfo(), oldPaths); + pkgInfo.updateApplicationInfo(aInfo, oldPaths); + + synchronized (mResourcesManager) { + // Update affected Resources objects to use new ResourcesImpl + mResourcesManager.applyNewResourceDirs(aInfo, oldResDirs); + } + } catch (RemoteException e) { + } + } } } + try { getPackageManager().notifyPackagesReplacedReceived( packagesHandled.toArray(new String[0])); } catch (RemoteException ignored) { } + break; } } @@ -6913,7 +6854,7 @@ public final class ActivityThread extends ClientTransactionHandler ii.copyTo(instrApp); instrApp.initForUser(UserHandle.myUserId()); final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, - appContext.getClassLoader(), false, true, false, true); + appContext.getClassLoader(), false, true, false); // The test context's op package name == the target app's op package name, because // the app ops manager checks the op package name against the real calling UID, diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index d24196813387..16b6ea5bcf42 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -48,6 +48,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetManager; import android.content.res.CompatResources; @@ -2461,7 +2462,7 @@ class ContextImpl extends Context { public Context createApplicationContext(ApplicationInfo application, int flags) throws NameNotFoundException { LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(), - flags | CONTEXT_REGISTER_PACKAGE, false); + flags | CONTEXT_REGISTER_PACKAGE); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY, mAttributionSource.getAttributionTag(), @@ -2493,6 +2494,13 @@ class ContextImpl extends Context { @Override public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) throws NameNotFoundException { + return createPackageContextAsUser(packageName, flags, user, 0 /* packageFlags */); + } + + @Override + public Context createPackageContextAsUser( + @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user, + @ApplicationInfoFlags int packageFlags) throws PackageManager.NameNotFoundException { if (packageName.equals("system") || packageName.equals("android")) { // The system resources are loaded in every application, so we can safely copy // the context without reloading Resources. @@ -2503,7 +2511,7 @@ class ContextImpl extends Context { } LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), - flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier()); + flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier(), packageFlags); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams, mAttributionSource.getAttributionTag(), diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 6454d2027f58..506dfe09f3fa 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -6344,10 +6344,11 @@ public class Notification implements Parcelable ApplicationInfo applicationInfo = n.extras.getParcelable( EXTRA_BUILDER_APPLICATION_INFO); Context builderContext; - if (applicationInfo != null) { + if (applicationInfo != null && applicationInfo.packageName != null) { try { - builderContext = context.createApplicationContext(applicationInfo, - Context.CONTEXT_RESTRICTED); + builderContext = context.createPackageContextAsUser(applicationInfo.packageName, + Context.CONTEXT_RESTRICTED, + UserHandle.getUserHandleForUid(applicationInfo.uid)); } catch (NameNotFoundException e) { Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found"); builderContext = context; // try with our context diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index dfd1e2b61fae..e469b1fde2e5 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -98,12 +98,6 @@ public class ResourcesManager { private int mResDisplayId = DEFAULT_DISPLAY; /** - * ApplicationInfo changes that need to be applied to Resources when the next configuration - * change occurs. - */ - private ArrayList<ApplicationInfo> mPendingAppInfoUpdates; - - /** * A mapping of ResourceImpls and their configurations. These are heavy weight objects * which should be reused as much as possible. */ @@ -994,7 +988,7 @@ public class ResourcesManager { * @param classLoader The classloader to use for the Resources object. * If null, {@link ClassLoader#getSystemClassLoader()} is used. * @return A Resources object that gets updated when - * {@link #applyConfigurationToResources(Configuration, CompatibilityInfo)} + * {@link #applyConfigurationToResourcesLocked(Configuration, CompatibilityInfo)} * is called. */ @Nullable @@ -1121,8 +1115,8 @@ public class ResourcesManager { /** * Updates an Activity's Resources object with overrideConfig. The Resources object * that was previously returned by {@link #getResources(IBinder, String, String[], String[], - * String[], String[], Integer, Configuration, CompatibilityInfo, ClassLoader, List)} is still - * valid and will have the updated configuration. + * String[], Integer, Configuration, CompatibilityInfo, ClassLoader, List)} is still valid and + * will have the updated configuration. * * @param activityToken The Activity token. * @param overrideConfig The configuration override to update. @@ -1273,22 +1267,6 @@ public class ResourcesManager { return newKey; } - public void updatePendingAppInfoUpdates(@NonNull ApplicationInfo appInfo) { - synchronized (mLock) { - if (mPendingAppInfoUpdates == null) { - mPendingAppInfoUpdates = new ArrayList<>(); - } - // Clear previous app info changes for the package to prevent multiple ResourcesImpl - // recreations when only the last recreation will be used. - for (int i = mPendingAppInfoUpdates.size() - 1; i >= 0; i--) { - if (appInfo.sourceDir.equals(mPendingAppInfoUpdates.get(i).sourceDir)) { - mPendingAppInfoUpdates.remove(i); - } - } - mPendingAppInfoUpdates.add(appInfo); - } - } - public final boolean applyConfigurationToResources(@NonNull Configuration config, @Nullable CompatibilityInfo compat) { return applyConfigurationToResources(config, compat, null /* adjustments */); @@ -1302,18 +1280,7 @@ public class ResourcesManager { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#applyConfigurationToResources"); - final boolean assetsUpdated = mPendingAppInfoUpdates != null - && config.assetsSeq > mResConfiguration.assetsSeq; - if (assetsUpdated) { - for (int i = 0, n = mPendingAppInfoUpdates.size(); i < n; i++) { - final ApplicationInfo appInfo = mPendingAppInfoUpdates.get(i); - applyNewResourceDirs(appInfo, new String[]{appInfo.sourceDir}); - } - mPendingAppInfoUpdates = null; - } - - if (!assetsUpdated && !mResConfiguration.isOtherSeqNewer(config) - && compat == null) { + if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) { if (DEBUG || DEBUG_CONFIGURATION) { Slog.v(TAG, "Skipping new config: curSeq=" + mResConfiguration.seq + ", newSeq=" + config.seq); @@ -1353,7 +1320,7 @@ public class ResourcesManager { } } - return assetsUpdated || changes != 0; + return changes != 0; } finally { Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index ba3fc1e55c54..3b11a19f9acc 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -37,6 +37,7 @@ import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Parcelable; +import android.os.UserHandle; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; @@ -718,9 +719,10 @@ public class AppWidgetHostView extends FrameLayout { protected Context getRemoteContext() { try { // Return if cloned successfully, otherwise default - Context newContext = mContext.createApplicationContext( - mInfo.providerInfo.applicationInfo, - Context.CONTEXT_RESTRICTED); + final ApplicationInfo info = mInfo.providerInfo.applicationInfo; + Context newContext = mContext.createPackageContextAsUser(info.packageName, + Context.CONTEXT_RESTRICTED, + UserHandle.getUserHandleForUid(info.uid)); if (mColorResources != null) { mColorResources.apply(newContext); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index c02dcfd3d681..9c60f431b06e 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -46,6 +46,7 @@ import android.app.time.TimeManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.res.AssetManager; import android.content.res.ColorStateList; import android.content.res.Configuration; @@ -6268,6 +6269,23 @@ public abstract class Context { } /** + * Similar to {@link #createPackageContextAsUser(String, int, UserHandle)}, but also allows + * specifying the flags used to retrieve the {@link ApplicationInfo} of the package. + * + * @hide + */ + @NonNull + public Context createPackageContextAsUser( + @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user, + @ApplicationInfoFlags int packageFlags) + throws PackageManager.NameNotFoundException { + if (Build.IS_ENG) { + throw new IllegalStateException("createPackageContextAsUser not overridden!"); + } + return this; + } + + /** * Similar to {@link #createPackageContext(String, int)}, but for the own package with a * different {@link UserHandle}. For example, {@link #getContentResolver()} * will open any {@link Uri} as the given user. @@ -6286,10 +6304,18 @@ public abstract class Context { /** * Creates a context given an {@link android.content.pm.ApplicationInfo}. * + * @deprecated use {@link #createPackageContextAsUser(String, int, UserHandle, int)} + * If an application caches an ApplicationInfo and uses it to call this method, + * the app will not get the most recent version of Runtime Resource Overlays for + * that application. To make things worse, the LoadedApk stored in + * {@code ActivityThread#mResourcePackages} is updated using the old ApplicationInfo + * causing further uses of the cached LoadedApk to return outdated information. + * * @hide */ @SuppressWarnings("HiddenAbstractMethod") @UnsupportedAppUsage + @Deprecated public abstract Context createApplicationContext(ApplicationInfo application, @CreatePackageOptions int flags) throws PackageManager.NameNotFoundException; diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 6324d0ecb0e0..cf0dc8c92ea1 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -1009,6 +1009,14 @@ public class ContextWrapper extends Context { /** @hide */ @Override + public Context createPackageContextAsUser(String packageName, int flags, UserHandle user, + int packageFlags) + throws PackageManager.NameNotFoundException { + return mBase.createPackageContextAsUser(packageName, flags, user, packageFlags); + } + + /** @hide */ + @Override public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { return mBase.createContextAsUser(user, flags); } diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 8e4a68e52697..863d71f6f793 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -434,11 +434,8 @@ public class StatusBarNotification implements Parcelable { public Context getPackageContext(Context context) { if (mContext == null) { try { - ApplicationInfo ai = context.getPackageManager() - .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, - getUserId()); - mContext = context.createApplicationContext(ai, - Context.CONTEXT_RESTRICTED); + mContext = context.createPackageContextAsUser(pkg, Context.CONTEXT_RESTRICTED, user, + PackageManager.MATCH_UNINSTALLED_PACKAGES); } catch (PackageManager.NameNotFoundException e) { mContext = null; } diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index cf6807e41e8a..8d27cded6338 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -33,6 +33,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.Trace; +import android.os.UserHandle; import android.util.AndroidRuntimeException; import android.util.ArraySet; import android.util.Log; @@ -467,9 +468,12 @@ public final class WebViewFactory { sTimestamps.mCreateContextStart = SystemClock.uptimeMillis(); try { // Construct an app context to load the Java code into the current app. - Context webViewContext = initialApplication.createApplicationContext( - ai, - Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); + Context webViewContext = initialApplication.createPackageContextAsUser( + ai.packageName, + Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY, + UserHandle.getUserHandleForUid(ai.uid), + PackageManager.MATCH_UNINSTALLED_PACKAGES + | PackageManager.MATCH_DEBUG_TRIAGED_MISSING); sPackageInfo = newPackageInfo; return webViewContext; } finally { diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index e827f0a31bfd..8a044fd06dd5 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -5831,8 +5831,9 @@ public class RemoteViews implements Parcelable, Filter { return context; } try { - return context.createApplicationContext(mApplication, - Context.CONTEXT_RESTRICTED); + return context.createPackageContextAsUser(mApplication.packageName, + Context.CONTEXT_RESTRICTED, + UserHandle.getUserHandleForUid(mApplication.uid)); } catch (NameNotFoundException e) { Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found"); } diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index 8fae80d602d9..93e4a294a2cb 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -121,8 +121,6 @@ java_genrule { ":FrameworksCoreTests_keyset_splat_api", ":FrameworksCoreTests_locales", ":FrameworksCoreTests_overlay_config", - ":FrameworksCoreTests_res_version_after", - ":FrameworksCoreTests_res_version_before", ":FrameworksCoreTests_version_1", ":FrameworksCoreTests_version_1_diff", ":FrameworksCoreTests_version_1_nosys", diff --git a/core/tests/coretests/apks/res_upgrade/Android.bp b/core/tests/coretests/apks/res_upgrade/Android.bp deleted file mode 100644 index c58614f2c946..000000000000 --- a/core/tests/coretests/apks/res_upgrade/Android.bp +++ /dev/null @@ -1,22 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -android_test_helper_app { - name: "FrameworksCoreTests_res_version_before", - defaults: ["FrameworksCoreTests_apks_defaults"], - resource_dirs: ["res_before"], - certificate: ":FrameworksCoreTests_unit_test_cert", -} - -android_test_helper_app { - name: "FrameworksCoreTests_res_version_after", - defaults: ["FrameworksCoreTests_apks_defaults"], - resource_dirs: ["res_after"], - certificate: ":FrameworksCoreTests_unit_test_cert", -} diff --git a/core/tests/coretests/apks/res_upgrade/AndroidManifest.xml b/core/tests/coretests/apks/res_upgrade/AndroidManifest.xml deleted file mode 100644 index 1c607c9fd249..000000000000 --- a/core/tests/coretests/apks/res_upgrade/AndroidManifest.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2021 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.frameworks.coretests.res_version"> - <application android:hasCode="false"/> -</manifest> diff --git a/core/tests/coretests/apks/res_upgrade/res_after/values/values.xml b/core/tests/coretests/apks/res_upgrade/res_after/values/values.xml deleted file mode 100644 index db4fd54c7aee..000000000000 --- a/core/tests/coretests/apks/res_upgrade/res_after/values/values.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ Copyright (C) 2021 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> - -<resources> - <string name="version">after</string> - <public type="string" name="version" id="0x7f010000"/> -</resources> diff --git a/core/tests/coretests/apks/res_upgrade/res_before/values/values.xml b/core/tests/coretests/apks/res_upgrade/res_before/values/values.xml deleted file mode 100644 index 63fc79020e3f..000000000000 --- a/core/tests/coretests/apks/res_upgrade/res_before/values/values.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ Copyright (C) 2021 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> - -<resources> - <string name="version">before</string> - <public type="string" name="version" id="0x7f010000"/> -</resources> diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java index 8488a84dbe01..d1776fb7e5c1 100644 --- a/core/tests/coretests/src/android/content/ContextTest.java +++ b/core/tests/coretests/src/android/content/ContextTest.java @@ -25,23 +25,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.app.ActivityThread; -import android.app.PendingIntent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInstaller; -import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.PixelFormat; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.inputmethodservice.InputMethodService; import android.media.ImageReader; -import android.os.FileUtils; import android.os.UserHandle; import android.view.Display; @@ -50,20 +42,12 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.compatibility.common.util.ShellIdentityUtils; -import com.android.frameworks.coretests.R; - import org.junit.Test; import org.junit.runner.RunWith; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.TimeUnit; - /** - * Build/Install/Run: - * atest FrameworksCoreTests:ContextTest + * Build/Install/Run: + * atest FrameworksCoreTests:ContextTest */ @SmallTest @RunWith(AndroidJUnit4.class) @@ -232,132 +216,6 @@ public class ContextTest { assertFalse(context.isUiContext()); } - private static class TestReceiver extends BroadcastReceiver implements AutoCloseable { - private static final String INTENT_ACTION = "com.android.server.pm.test.test_app.action"; - private final ArrayBlockingQueue<Intent> mResults = new ArrayBlockingQueue<>(1); - - public IntentSender makeIntentSender() { - return PendingIntent.getBroadcast(getContext(), 0, new Intent(INTENT_ACTION), - PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED) - .getIntentSender(); - } - - public void waitForIntent() throws InterruptedException { - assertNotNull(mResults.poll(30, TimeUnit.SECONDS)); - } - - @Override - public void onReceive(Context context, Intent intent) { - mResults.add(intent); - } - - public void register() { - getContext().registerReceiver(this, new IntentFilter(INTENT_ACTION)); - } - - @Override - public void close() throws Exception { - getContext().unregisterReceiver(this); - } - - private Context getContext() { - return InstrumentationRegistry.getInstrumentation().getContext(); - } - } - - @Test - public void applicationContextBeforeAndAfterUpgrade() throws Exception { - final Context context = InstrumentationRegistry.getInstrumentation().getContext(); - final String testPackageName = "com.android.frameworks.coretests.res_version"; - try { - final PackageManager pm = context.getPackageManager(); - final int versionRes = 0x7f010000; - - final Context appContext = ApplicationProvider.getApplicationContext(); - installApk(appContext, R.raw.res_version_before); - - ApplicationInfo info = pm.getApplicationInfo(testPackageName, 0); - final Context beforeContext = appContext.createApplicationContext(info, 0); - assertEquals("before", beforeContext.getResources().getString(versionRes)); - - installApk(appContext, R.raw.res_version_after); - - info = pm.getApplicationInfo(testPackageName, 0); - final Context afterContext = appContext.createApplicationContext(info, 0); - assertEquals("before", beforeContext.createConfigurationContext(Configuration.EMPTY) - .getResources().getString(versionRes)); - assertEquals("after", afterContext.createConfigurationContext(Configuration.EMPTY) - .getResources().getString(versionRes)); - assertNotEquals(beforeContext.getPackageResourcePath(), - afterContext.getPackageResourcePath()); - } finally { - uninstallPackage(context, testPackageName); - } - } - - @Test - public void packageContextBeforeAndAfterUpgrade() throws Exception { - final Context context = InstrumentationRegistry.getInstrumentation().getContext(); - final String testPackageName = "com.android.frameworks.coretests.res_version"; - try { - final int versionRes = 0x7f010000; - final Context appContext = ApplicationProvider.getApplicationContext(); - installApk(appContext, R.raw.res_version_before); - - final Context beforeContext = appContext.createPackageContext(testPackageName, 0); - assertEquals("before", beforeContext.getResources().getString(versionRes)); - - installApk(appContext, R.raw.res_version_after); - - final Context afterContext = appContext.createPackageContext(testPackageName, 0); - assertEquals("before", beforeContext.createConfigurationContext(Configuration.EMPTY) - .getResources().getString(versionRes)); - assertEquals("after", afterContext.createConfigurationContext(Configuration.EMPTY) - .getResources().getString(versionRes)); - assertNotEquals(beforeContext.getPackageResourcePath(), - afterContext.getPackageResourcePath()); - } finally { - uninstallPackage(context, testPackageName); - } - } - - private void installApk(Context context, int rawApkResId) throws Exception { - final PackageManager pm = context.getPackageManager(); - final PackageInstaller pi = pm.getPackageInstaller(); - final PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - final int sessionId = pi.createSession(params); - - try (PackageInstaller.Session session = pi.openSession(sessionId)) { - // Copy the apk to the install session. - final Resources resources = context.getResources(); - try (InputStream is = resources.openRawResource(rawApkResId); - OutputStream sessionOs = session.openWrite("base", 0, -1)) { - FileUtils.copy(is, sessionOs); - } - - // Wait for the installation to finish - try (TestReceiver receiver = new TestReceiver()) { - receiver.register(); - ShellIdentityUtils.invokeMethodWithShellPermissions(session, - (s) -> { - s.commit(receiver.makeIntentSender()); - return true; - }); - receiver.waitForIntent(); - } - } - } - - private void uninstallPackage(Context context, String packageName) throws Exception { - try (TestReceiver receiver = new TestReceiver()) { - receiver.register(); - final PackageInstaller pi = context.getPackageManager().getPackageInstaller(); - pi.uninstall(packageName, receiver.makeIntentSender()); - receiver.waitForIntent(); - } - } - private Context createUiContext() { final Context appContext = ApplicationProvider.getApplicationContext(); final DisplayManager displayManager = appContext.getSystemService(DisplayManager.class); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java index 2b35bcd9a3ea..c90833c5b8f2 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java @@ -345,7 +345,7 @@ public class PluginInstanceManager<T extends Plugin> { // Create our own ClassLoader so we can use our own code as the parent. ClassLoader classLoader = mManager.getClassLoader(info); Context pluginContext = new PluginContextWrapper( - mContext.createApplicationContext(info, 0), classLoader); + mContext.createPackageContext(pkg, 0), classLoader); Class<?> pluginClass = Class.forName(cls, true, classLoader); // TODO: Only create the plugin before version check if we need it for // legacy version check. diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index fd9a53695e6c..7c5d09c3c5ce 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -4691,10 +4691,10 @@ public final class ProcessList { final ApplicationInfo ai = AppGlobals.getPackageManager() .getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId); if (ai != null) { + app.getThread().scheduleApplicationInfoChanged(ai); if (ai.packageName.equals(app.info.packageName)) { app.info = ai; } - app.getThread().scheduleApplicationInfoChanged(ai); targetProcesses.add(app.getWindowProcessController()); } } catch (RemoteException e) { @@ -4705,7 +4705,8 @@ public final class ProcessList { }); } - mService.mActivityTaskManager.updateAssetConfiguration(targetProcesses, updateFrameworkRes); + mService.mActivityTaskManager.updateAssetConfiguration( + updateFrameworkRes ? null : targetProcesses); } @GuardedBy("mService") diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 569c11be01e7..2bf78e9b1a2c 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4158,21 +4158,21 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /** * Update the asset configuration and increase the assets sequence number. - * @param processes the processes that needs to update the asset configuration + * @param processes the processes that needs to update the asset configuration, if none + * updates the global configuration for all processes. */ - public void updateAssetConfiguration(List<WindowProcessController> processes, - boolean updateFrameworkRes) { + public void updateAssetConfiguration(List<WindowProcessController> processes) { synchronized (mGlobalLock) { final int assetSeq = increaseAssetConfigurationSeq(); - if (updateFrameworkRes) { + // Update the global configuration if the no target processes + if (processes == null) { Configuration newConfig = new Configuration(); newConfig.assetsSeq = assetSeq; updateConfiguration(newConfig); + return; } - // Always update the override of every process so the asset sequence of the process is - // always greater than or equal to the global configuration. for (int i = processes.size() - 1; i >= 0; i--) { final WindowProcessController wpc = processes.get(i); wpc.updateAssetConfiguration(assetSeq); |