Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af2f51f2 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Avoid token resource from being affected by derived resource

For example:
ActivityResources
 ActivityResource[0] by real activity
 ActivityResource[1] by Activity#createConfigurationContext

If the ResourcesKey for [0] and [1] use the same token identity for
creating the ResourcesKey, when updateResourcesForActivity iterates
ActivityResources to update:
 The first update for [0] is no problem.
 But when updating [1], the key finds the ResourcesImpl instance
 for [0]. And [1]'s override configuration applies to [0], which
 causes the problem.

By using token identity only for base resource (for token itself),
the derived resource can have its own ResourcesImpl, which avoids
affecting the base resource.

Bug: 413273054
Flag: android.content.res.ignore_non_public_config_diff_for_resources_key
Test: atest FrameworksCoreTests:ResourcesManagerTest# \
      testUpdateActivityResourcesOverrideWindowConfiguration
Change-Id: I1ac1b94b540deb2de69dcec5781fd29d51103ed7
parent d55f80cc
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -340,6 +340,9 @@ public class ResourcesManager {
        @Nullable
        public WeakReference<Resources> resources;

        /** Whether this resource is created for the token itself. */
        boolean isBaseResource;

        private ActivityResource() {}
    }

@@ -946,6 +949,9 @@ public class ResourcesManager {
        activityResource.overrideConfig.setTo(initialOverrideConfig);
        activityResource.overrideDisplayId = overrideDisplayId;
        activityResources.activityResources.add(activityResource);
        if (activityResources.activityResources.size() == 1) {
            activityResource.isBaseResource = true;
        }
        if (DEBUG) {
            Slog.d(TAG, "- creating new ref=" + resources);
            Slog.d(TAG, "- setting ref=" + resources + " with impl=" + impl);
@@ -1476,8 +1482,13 @@ public class ResourcesManager {
        // Ensure the new key keeps the expected override display instead of the new token display.
        displayId = overrideDisplayId != null ? overrideDisplayId : displayId;

        // Do not use token identify if it is a derived resource (isBaseResource == false) because
        // if the window configuration is different, the key for derived resource should not find
        // the ResourcesImpl instance of token resource.
        final int tokenIdentity = activityResource.isBaseResource
                ? System.identityHashCode(activityToken) : 0;
        // Create the new ResourcesKey with the rebased override config.
        final ResourcesKey newKey = new ResourcesKey(System.identityHashCode(activityToken),
        final ResourcesKey newKey = new ResourcesKey(tokenIdentity,
                oldKey.mResDir, oldKey.mSplitResDirs, oldKey.mOverlayPaths, oldKey.mLibDirs,
                displayId, rebasedOverrideConfig, oldKey.mCompatInfo, oldKey.mLoaders);

+29 −0
Original line number Diff line number Diff line
@@ -407,6 +407,35 @@ public class ResourcesManagerTest {
                resources2.getConfiguration().windowConfiguration);
    }

    @Test
    @SmallTest
    public void testUpdateActivityResourcesOverrideWindowConfiguration() {
        final Binder activity = new Binder();
        final Resources activityResources = mResourcesManager.createBaseTokenResources(
                activity, null, null, null, null, null, Display.DEFAULT_DISPLAY,
                null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
        final Configuration overrideConfig = new Configuration();
        overrideConfig.windowConfiguration.getBounds().set(0, 0, 500, 1000);
        // Simulate the usage of Activity#createConfigurationContext.
        final Resources overrideConfigResources = mResourcesManager.getResources(
                activity, null, null, null, null, null, Display.DEFAULT_DISPLAY,
                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
        // This is a key step to make the non-window configuration fields have the same value
        // (which were assigned from ResourcesManager#applyDisplayMetricsToConfiguration). And the
        // following update shouldn't create the ResourcesKey that finds the same ResourcesImpl.
        final Configuration newActivityOverrideConfig =
                new Configuration(overrideConfigResources.getConfiguration());
        newActivityOverrideConfig.windowConfiguration.getBounds().set(100, 200, 600, 1200);
        mResourcesManager.updateResourcesForActivity(activity, newActivityOverrideConfig,
                Display.DEFAULT_DISPLAY);

        // Verifies that the update applies the configuration to the correct ResourcesImpl.
        assertEquals(overrideConfig.windowConfiguration.getBounds(),
                overrideConfigResources.getConfiguration().windowConfiguration.getBounds());
        assertEquals(newActivityOverrideConfig.windowConfiguration.getBounds(),
                activityResources.getConfiguration().windowConfiguration.getBounds());
    }

    @Test
    @SmallTest
    @RequiresFlagsEnabled(Flags.FLAG_IGNORE_NON_PUBLIC_CONFIG_DIFF_FOR_RESOURCES_KEY)