Loading core/java/android/app/ActivityThread.java +76 −18 Original line number Diff line number Diff line Loading @@ -245,7 +245,7 @@ public final class ActivityThread { boolean mSomeActivitiesChanged = false; boolean mUpdatingSystemConfig = false; // These can be accessed by multiple threads; mPackages is the lock. // These can be accessed by multiple threads; mResourcesManager is the lock. // XXX For now we keep around information about all packages we have // seen, not removing entries from this map. // NOTE: The activity and window managers need to call in to Loading @@ -254,12 +254,13 @@ public final class ActivityThread { // holds their own lock. Thus you MUST NEVER call back into the activity manager // or window manager or anything that depends on them while holding this lock. // These LoadedApk are only valid for the userId that we're running as. final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<String, WeakReference<LoadedApk>>(); final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<String, WeakReference<LoadedApk>>(); final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<ActivityClientRecord>(); @GuardedBy("mResourcesManager") final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<>(); @GuardedBy("mResourcesManager") final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>(); @GuardedBy("mResourcesManager") final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<>(); @GuardedBy("mResourcesManager") Configuration mPendingConfiguration = null; // Because we merge activity relaunch operations we can't depend on the ordering provided by // the handler messages. We need to introduce secondary ordering mechanism, which will allow Loading Loading @@ -904,6 +905,10 @@ public final class ActivityThread { sendMessage(H.CONFIGURATION_CHANGED, config); } public void scheduleApplicationInfoChanged(ApplicationInfo ai) { sendMessage(H.APPLICATION_INFO_CHANGED, ai); } public void updateTimeZone() { TimeZone.setDefault(null); } Loading Loading @@ -1448,6 +1453,7 @@ public final class ActivityThread { public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153; public static final int LOCAL_VOICE_INTERACTION_STARTED = 154; public static final int ATTACH_AGENT = 155; public static final int APPLICATION_INFO_CHANGED = 156; String codeToString(int code) { if (DEBUG_MESSAGES) { Loading Loading @@ -1505,6 +1511,7 @@ public final class ActivityThread { case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED"; case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED"; case ATTACH_AGENT: return "ATTACH_AGENT"; case APPLICATION_INFO_CHANGED: return "APPLICATION_INFO_CHANGED"; } } return Integer.toString(code); Loading Loading @@ -1636,8 +1643,11 @@ public final class ActivityThread { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged"); mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi; mUpdatingSystemConfig = true; try { handleConfigurationChanged((Configuration) msg.obj, null); } finally { mUpdatingSystemConfig = false; } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case CLEAN_UP_CONTEXT: Loading Loading @@ -1763,6 +1773,14 @@ public final class ActivityThread { case ATTACH_AGENT: handleAttachAgent((String) msg.obj); break; case APPLICATION_INFO_CHANGED: mUpdatingSystemConfig = true; try { handleApplicationInfoChanged((ApplicationInfo) msg.obj); } finally { mUpdatingSystemConfig = false; } break; } Object obj = msg.obj; if (obj instanceof SomeArgs) { Loading Loading @@ -3500,10 +3518,11 @@ public final class ActivityThread { } r.activity.performResume(); synchronized (mResourcesManager) { // If there is a pending local relaunch that was requested when the activity was // paused, it will put the activity into paused state when it finally happens. // Since the activity resumed before being relaunched, we don't want that to happen, // so we need to clear the request to relaunch paused. // Since the activity resumed before being relaunched, we don't want that to // happen, so we need to clear the request to relaunch paused. for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) { final ActivityClientRecord relaunching = mRelaunchingActivities.get(i); if (relaunching.token == r.token Loading @@ -3511,6 +3530,7 @@ public final class ActivityThread { relaunching.startsNotResumed = false; } } } EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(), r.activity.getComponentName().getClassName(), reason); Loading Loading @@ -4898,6 +4918,44 @@ public final class ActivityThread { } } void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) { synchronized (mResourcesManager) { // Update all affected loaded packages with new package information WeakReference<LoadedApk> ref = mPackages.get(ai.packageName); LoadedApk apk = ref != null ? ref.get() : null; if (apk != null) { apk.updateApplicationInfo(ai, null); } ref = mResourcePackages.get(ai.packageName); apk = ref != null ? ref.get() : null; if (apk != null) { apk.updateApplicationInfo(ai, null); } // Update all affected Resources objects to use new ResourcesImpl mResourcesManager.applyNewResourceDirsLocked(ai.sourceDir, ai.resourceDirs); } ApplicationPackageManager.configurationChanged(); // Trigger a regular Configuration change event, only with a different assetsSeq number // so that we actually call through to all components. Configuration newConfig = new Configuration(); newConfig.unset(); newConfig.assetsSeq = mConfiguration.assetsSeq + 1; handleConfigurationChanged(newConfig, null); // Schedule all activities to reload for (final Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) { final Activity activity = entry.getValue().activity; if (!activity.mFinished) { requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false, false); } } } static void freeTextLayoutCachesIfNeeded(int configDiff) { if (configDiff != 0) { // Ask text layout engine to free its caches if there is a locale change Loading core/java/android/app/IActivityManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -601,6 +601,8 @@ interface IActivityManager { */ ActivityManager.TaskSnapshot getTaskSnapshot(int taskId); void scheduleApplicationInfoChanged(in List<String> packageNames, int userId); // WARNING: when these transactions are updated, check if they are any callers on the native // side. If so, make sure they are using the correct transaction ids and arguments. // If a transaction which will also be used on the native side is being inserted, add it Loading core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -152,4 +152,5 @@ oneway interface IApplicationThread { IVoiceInteractor voiceInteractor); void handleTrustStorageUpdate(); void attachAgent(String path); void scheduleApplicationInfoChanged(in ApplicationInfo ai); } core/java/android/app/ResourcesManager.java +67 −26 Original line number Diff line number Diff line Loading @@ -916,6 +916,45 @@ public class ResourcesManager { } } redirectResourcesToNewImplLocked(updatedResourceKeys); } } // TODO(adamlesinski): Make this accept more than just overlay directories. final void applyNewResourceDirsLocked(@NonNull final String baseCodePath, @NonNull final String[] newResourceDirs) { try { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#applyNewResourceDirsLocked"); final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>(); final int implCount = mResourceImpls.size(); for (int i = 0; i < implCount; i++) { final ResourcesKey key = mResourceImpls.keyAt(i); final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i); final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null; if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) { updatedResourceKeys.put(impl, new ResourcesKey( key.mResDir, key.mSplitResDirs, newResourceDirs, key.mLibDirs, key.mDisplayId, key.mOverrideConfiguration, key.mCompatInfo)); } } invalidatePath("/"); redirectResourcesToNewImplLocked(updatedResourceKeys); } finally { Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } } private void redirectResourcesToNewImplLocked( @NonNull final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys) { // Bail early if there is no work to do. if (updatedResourceKeys.isEmpty()) { return; Loading @@ -924,13 +963,14 @@ public class ResourcesManager { // Update any references to ResourcesImpl that require reloading. final int resourcesCount = mResourceReferences.size(); for (int i = 0; i < resourcesCount; i++) { final Resources r = mResourceReferences.get(i).get(); final WeakReference<Resources> ref = mResourceReferences.get(i); final Resources r = ref != null ? ref.get() : null; if (r != null) { final ResourcesKey key = updatedResourceKeys.get(r.getImpl()); if (key != null) { final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key); if (impl == null) { throw new Resources.NotFoundException("failed to load " + libAsset); throw new Resources.NotFoundException("failed to redirect ResourcesImpl"); } r.setImpl(impl); } Loading @@ -941,13 +981,15 @@ public class ResourcesManager { for (ActivityResources activityResources : mActivityResourceReferences.values()) { final int resCount = activityResources.activityResources.size(); for (int i = 0; i < resCount; i++) { final Resources r = activityResources.activityResources.get(i).get(); final WeakReference<Resources> ref = activityResources.activityResources.get(i); final Resources r = ref != null ? ref.get() : null; if (r != null) { final ResourcesKey key = updatedResourceKeys.get(r.getImpl()); if (key != null) { final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key); if (impl == null) { throw new Resources.NotFoundException("failed to load " + libAsset); throw new Resources.NotFoundException( "failed to redirect ResourcesImpl"); } r.setImpl(impl); } Loading @@ -956,4 +998,3 @@ public class ResourcesManager { } } } } core/java/android/content/pm/ActivityInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,14 @@ public class ActivityInfo extends ComponentInfo * {@link android.R.attr#configChanges} attribute. */ public static final int CONFIG_LAYOUT_DIRECTION = 0x2000; /** * Bit in {@link #configChanges} that indicates that the activity * can itself handle asset path changes. Set from the {@link android.R.attr#configChanges} * attribute. This is not a core resource configuration, but a higher-level value, so its * constant starts at the high bits. * @hide We do not want apps handling this yet, but we do need some kind of bit for diffs. */ public static final int CONFIG_ASSETS_PATHS = 0x80000000; /** * Bit in {@link #configChanges} that indicates that the activity * can itself handle changes to the font scaling factor. Set from the Loading Loading
core/java/android/app/ActivityThread.java +76 −18 Original line number Diff line number Diff line Loading @@ -245,7 +245,7 @@ public final class ActivityThread { boolean mSomeActivitiesChanged = false; boolean mUpdatingSystemConfig = false; // These can be accessed by multiple threads; mPackages is the lock. // These can be accessed by multiple threads; mResourcesManager is the lock. // XXX For now we keep around information about all packages we have // seen, not removing entries from this map. // NOTE: The activity and window managers need to call in to Loading @@ -254,12 +254,13 @@ public final class ActivityThread { // holds their own lock. Thus you MUST NEVER call back into the activity manager // or window manager or anything that depends on them while holding this lock. // These LoadedApk are only valid for the userId that we're running as. final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<String, WeakReference<LoadedApk>>(); final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<String, WeakReference<LoadedApk>>(); final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<ActivityClientRecord>(); @GuardedBy("mResourcesManager") final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<>(); @GuardedBy("mResourcesManager") final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>(); @GuardedBy("mResourcesManager") final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<>(); @GuardedBy("mResourcesManager") Configuration mPendingConfiguration = null; // Because we merge activity relaunch operations we can't depend on the ordering provided by // the handler messages. We need to introduce secondary ordering mechanism, which will allow Loading Loading @@ -904,6 +905,10 @@ public final class ActivityThread { sendMessage(H.CONFIGURATION_CHANGED, config); } public void scheduleApplicationInfoChanged(ApplicationInfo ai) { sendMessage(H.APPLICATION_INFO_CHANGED, ai); } public void updateTimeZone() { TimeZone.setDefault(null); } Loading Loading @@ -1448,6 +1453,7 @@ public final class ActivityThread { public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153; public static final int LOCAL_VOICE_INTERACTION_STARTED = 154; public static final int ATTACH_AGENT = 155; public static final int APPLICATION_INFO_CHANGED = 156; String codeToString(int code) { if (DEBUG_MESSAGES) { Loading Loading @@ -1505,6 +1511,7 @@ public final class ActivityThread { case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED"; case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED"; case ATTACH_AGENT: return "ATTACH_AGENT"; case APPLICATION_INFO_CHANGED: return "APPLICATION_INFO_CHANGED"; } } return Integer.toString(code); Loading Loading @@ -1636,8 +1643,11 @@ public final class ActivityThread { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged"); mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi; mUpdatingSystemConfig = true; try { handleConfigurationChanged((Configuration) msg.obj, null); } finally { mUpdatingSystemConfig = false; } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case CLEAN_UP_CONTEXT: Loading Loading @@ -1763,6 +1773,14 @@ public final class ActivityThread { case ATTACH_AGENT: handleAttachAgent((String) msg.obj); break; case APPLICATION_INFO_CHANGED: mUpdatingSystemConfig = true; try { handleApplicationInfoChanged((ApplicationInfo) msg.obj); } finally { mUpdatingSystemConfig = false; } break; } Object obj = msg.obj; if (obj instanceof SomeArgs) { Loading Loading @@ -3500,10 +3518,11 @@ public final class ActivityThread { } r.activity.performResume(); synchronized (mResourcesManager) { // If there is a pending local relaunch that was requested when the activity was // paused, it will put the activity into paused state when it finally happens. // Since the activity resumed before being relaunched, we don't want that to happen, // so we need to clear the request to relaunch paused. // Since the activity resumed before being relaunched, we don't want that to // happen, so we need to clear the request to relaunch paused. for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) { final ActivityClientRecord relaunching = mRelaunchingActivities.get(i); if (relaunching.token == r.token Loading @@ -3511,6 +3530,7 @@ public final class ActivityThread { relaunching.startsNotResumed = false; } } } EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(), r.activity.getComponentName().getClassName(), reason); Loading Loading @@ -4898,6 +4918,44 @@ public final class ActivityThread { } } void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) { synchronized (mResourcesManager) { // Update all affected loaded packages with new package information WeakReference<LoadedApk> ref = mPackages.get(ai.packageName); LoadedApk apk = ref != null ? ref.get() : null; if (apk != null) { apk.updateApplicationInfo(ai, null); } ref = mResourcePackages.get(ai.packageName); apk = ref != null ? ref.get() : null; if (apk != null) { apk.updateApplicationInfo(ai, null); } // Update all affected Resources objects to use new ResourcesImpl mResourcesManager.applyNewResourceDirsLocked(ai.sourceDir, ai.resourceDirs); } ApplicationPackageManager.configurationChanged(); // Trigger a regular Configuration change event, only with a different assetsSeq number // so that we actually call through to all components. Configuration newConfig = new Configuration(); newConfig.unset(); newConfig.assetsSeq = mConfiguration.assetsSeq + 1; handleConfigurationChanged(newConfig, null); // Schedule all activities to reload for (final Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) { final Activity activity = entry.getValue().activity; if (!activity.mFinished) { requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false, false); } } } static void freeTextLayoutCachesIfNeeded(int configDiff) { if (configDiff != 0) { // Ask text layout engine to free its caches if there is a locale change Loading
core/java/android/app/IActivityManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -601,6 +601,8 @@ interface IActivityManager { */ ActivityManager.TaskSnapshot getTaskSnapshot(int taskId); void scheduleApplicationInfoChanged(in List<String> packageNames, int userId); // WARNING: when these transactions are updated, check if they are any callers on the native // side. If so, make sure they are using the correct transaction ids and arguments. // If a transaction which will also be used on the native side is being inserted, add it Loading
core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -152,4 +152,5 @@ oneway interface IApplicationThread { IVoiceInteractor voiceInteractor); void handleTrustStorageUpdate(); void attachAgent(String path); void scheduleApplicationInfoChanged(in ApplicationInfo ai); }
core/java/android/app/ResourcesManager.java +67 −26 Original line number Diff line number Diff line Loading @@ -916,6 +916,45 @@ public class ResourcesManager { } } redirectResourcesToNewImplLocked(updatedResourceKeys); } } // TODO(adamlesinski): Make this accept more than just overlay directories. final void applyNewResourceDirsLocked(@NonNull final String baseCodePath, @NonNull final String[] newResourceDirs) { try { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#applyNewResourceDirsLocked"); final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>(); final int implCount = mResourceImpls.size(); for (int i = 0; i < implCount; i++) { final ResourcesKey key = mResourceImpls.keyAt(i); final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i); final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null; if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) { updatedResourceKeys.put(impl, new ResourcesKey( key.mResDir, key.mSplitResDirs, newResourceDirs, key.mLibDirs, key.mDisplayId, key.mOverrideConfiguration, key.mCompatInfo)); } } invalidatePath("/"); redirectResourcesToNewImplLocked(updatedResourceKeys); } finally { Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } } private void redirectResourcesToNewImplLocked( @NonNull final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys) { // Bail early if there is no work to do. if (updatedResourceKeys.isEmpty()) { return; Loading @@ -924,13 +963,14 @@ public class ResourcesManager { // Update any references to ResourcesImpl that require reloading. final int resourcesCount = mResourceReferences.size(); for (int i = 0; i < resourcesCount; i++) { final Resources r = mResourceReferences.get(i).get(); final WeakReference<Resources> ref = mResourceReferences.get(i); final Resources r = ref != null ? ref.get() : null; if (r != null) { final ResourcesKey key = updatedResourceKeys.get(r.getImpl()); if (key != null) { final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key); if (impl == null) { throw new Resources.NotFoundException("failed to load " + libAsset); throw new Resources.NotFoundException("failed to redirect ResourcesImpl"); } r.setImpl(impl); } Loading @@ -941,13 +981,15 @@ public class ResourcesManager { for (ActivityResources activityResources : mActivityResourceReferences.values()) { final int resCount = activityResources.activityResources.size(); for (int i = 0; i < resCount; i++) { final Resources r = activityResources.activityResources.get(i).get(); final WeakReference<Resources> ref = activityResources.activityResources.get(i); final Resources r = ref != null ? ref.get() : null; if (r != null) { final ResourcesKey key = updatedResourceKeys.get(r.getImpl()); if (key != null) { final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key); if (impl == null) { throw new Resources.NotFoundException("failed to load " + libAsset); throw new Resources.NotFoundException( "failed to redirect ResourcesImpl"); } r.setImpl(impl); } Loading @@ -956,4 +998,3 @@ public class ResourcesManager { } } } }
core/java/android/content/pm/ActivityInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,14 @@ public class ActivityInfo extends ComponentInfo * {@link android.R.attr#configChanges} attribute. */ public static final int CONFIG_LAYOUT_DIRECTION = 0x2000; /** * Bit in {@link #configChanges} that indicates that the activity * can itself handle asset path changes. Set from the {@link android.R.attr#configChanges} * attribute. This is not a core resource configuration, but a higher-level value, so its * constant starts at the high bits. * @hide We do not want apps handling this yet, but we do need some kind of bit for diffs. */ public static final int CONFIG_ASSETS_PATHS = 0x80000000; /** * Bit in {@link #configChanges} that indicates that the activity * can itself handle changes to the font scaling factor. Set from the Loading