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

Commit 2e97644b authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Distinguish window configuration for different tokens" into main

parents 96b10744 7b262506
Loading
Loading
Loading
Loading
+80 −21
Original line number Diff line number Diff line
@@ -795,13 +795,19 @@ public class ResourcesManager {
     * Finds a cached ResourcesImpl object that matches the given ResourcesKey.
     *
     * @param key The key to match.
     * @return a ResourcesImpl if the key matches a cache entry, null otherwise.
     * @return a pair of key and ResourcesImpl if the key matches a cache entry, null otherwise.
     */
    private @Nullable ResourcesImpl findResourcesImplForKeyLocked(@NonNull ResourcesKey key) {
        WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.get(key);
        ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
    @Nullable
    private Pair<ResourcesKey, ResourcesImpl> findResourcesImplPairForKeyLocked(
            @NonNull ResourcesKey key) {
        final int index = mResourceImpls.indexOfKey(key);
        if (index < 0) {
            return null;
        }
        final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(index);
        final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
        if (impl != null && impl.getAssets().isUpToDate()) {
            return impl;
            return new Pair<>(mResourceImpls.keyAt(index), impl);
        }
        return null;
    }
@@ -823,15 +829,29 @@ public class ResourcesManager {
     */
    private @Nullable ResourcesImpl findOrCreateResourcesImplForKeyLocked(
            @NonNull ResourcesKey key, @Nullable ApkAssetsSupplier apkSupplier) {
        ResourcesImpl impl = findResourcesImplForKeyLocked(key);
        final Pair<ResourcesKey, ResourcesImpl> pair =
                findOrCreateResourcesImplPairForKeyLocked(key, apkSupplier);
        return pair != null ? pair.second : null;
    }

    /**
     * Returns a pair consisting of the key (the instance may be different from the given one if
     * it matches an existing ResourcesImpl) and ResourcesImpl object matching the key.
     */
    @Nullable
    private Pair<ResourcesKey, ResourcesImpl> findOrCreateResourcesImplPairForKeyLocked(
            @NonNull ResourcesKey key, @Nullable ApkAssetsSupplier apkSupplier) {
        final Pair<ResourcesKey, ResourcesImpl> pair = findResourcesImplPairForKeyLocked(key);
        ResourcesImpl impl = pair != null ? pair.second : null;
        // ResourcesImpl also need to be recreated if its shared library hash is not up-to-date.
        if (impl == null || impl.getAppliedSharedLibsHash() != mSharedLibAssetsMap.size()) {
            impl = createResourcesImpl(key, apkSupplier);
            if (impl != null) {
                mResourceImpls.put(key, new WeakReference<>(impl));
                return new Pair<>(key, impl);
            }
        }
        return impl;
        return pair;
    }

    /**
@@ -990,6 +1010,7 @@ public class ResourcesManager {
            Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
                    "ResourcesManager#createBaseActivityResources");
            final ResourcesKey key = new ResourcesKey(
                    System.identityHashCode(token),
                    resDir,
                    splitResDirs,
                    combinedOverlayPaths(legacyOverlayDirs, overlayPaths),
@@ -1248,6 +1269,7 @@ public class ResourcesManager {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#getResources");
            final ResourcesKey key = new ResourcesKey(
                    System.identityHashCode(activityToken),
                    resDir,
                    splitResDirs,
                    combinedOverlayPaths(legacyOverlayDirs, overlayPaths),
@@ -1352,16 +1374,18 @@ public class ResourcesManager {
                        continue;
                    }

                    final ResourcesKey newKey = rebaseActivityOverrideConfig(activityResource,
                            overrideConfig, displayId);
                    final ResourcesKey newKey = rebaseActivityOverrideConfig(activityToken,
                            activityResource, overrideConfig, displayId);
                    if (newKey == null) {
                        continue;
                    }

                    // TODO(b/173090263): Improve the performance of AssetManager & ResourcesImpl
                    // constructions.
                    final ResourcesImpl resourcesImpl =
                            findOrCreateResourcesImplForKeyLocked(newKey);
                    final Pair<ResourcesKey, ResourcesImpl> implPair =
                            findOrCreateResourcesImplPairForKeyLocked(
                                    newKey, null /* apkSupplier */);
                    final ResourcesImpl resourcesImpl = implPair != null ? implPair.second : null;
                    if (resourcesImpl == null) {
                        continue;
                    }
@@ -1369,15 +1393,26 @@ public class ResourcesManager {
                        // Set the ResourcesImpl, updating it for all users of this Resources
                        // object.
                        resources.setImpl(resourcesImpl);
                    } else if (android.content.res.Flags
                            .ignoreNonPublicConfigDiffForResourcesKey()) {
                    }
                    // Even if the new key matches an existing ResourcesImpl, the window
                    // configuration of the new key and the existing key can be different, e.g.
                    // only position change. So retrieve the existing key to check.
                    final ResourcesKey currentKey = implPair.first;
                    final boolean isReusedResImpl =
                            android.content.res.Flags.ignoreNonPublicConfigDiffForResourcesKey()
                                    && currentKey != null && currentKey != newKey;
                    if (isReusedResImpl) {
                        // If the ResourcesImpl is reused, also update fields not related to
                        // resources in case the app accesses WindowConfiguration, e.g. rotation.
                        final Configuration resConfig = resourcesImpl.getConfiguration();
                        resConfig.windowConfiguration.updateFrom(
                                newKey.mOverrideConfiguration.windowConfiguration);
                        if (newKey.mOverrideConfiguration.seq != 0) {
                            resConfig.seq = newKey.mOverrideConfiguration.seq;
                        // Note that the content of window configuration won't affect the result of
                        // ResourcesKey#equals/hashCode for the reused case.
                        if (updateWindowConfiguration(currentKey.mOverrideConfiguration,
                                newKey.mOverrideConfiguration)) {
                            updateWindowConfiguration(resourcesImpl.getConfiguration(),
                                    newKey.mOverrideConfiguration);
                            updateWindowConfiguration(
                                    resourcesImpl.getDisplayAdjustments().getConfiguration(),
                                    newKey.mOverrideConfiguration);
                        }
                    }
                }
@@ -1392,7 +1427,8 @@ public class ResourcesManager {
     * that an Activity's Resources should be set to.
     */
    @Nullable
    private ResourcesKey rebaseActivityOverrideConfig(@NonNull ActivityResource activityResource,
    private ResourcesKey rebaseActivityOverrideConfig(@NonNull IBinder activityToken,
            @NonNull ActivityResource activityResource,
            @Nullable Configuration newOverrideConfig, int displayId) {
        final Resources resources = activityResource.resources.get();
        if (resources == null) {
@@ -1442,8 +1478,8 @@ public class ResourcesManager {
        displayId = overrideDisplayId != null ? overrideDisplayId : displayId;

        // Create the new ResourcesKey with the rebased override config.
        final ResourcesKey newKey = new ResourcesKey(oldKey.mResDir,
                oldKey.mSplitResDirs, oldKey.mOverlayPaths, oldKey.mLibDirs,
        final ResourcesKey newKey = new ResourcesKey(System.identityHashCode(activityToken),
                oldKey.mResDir, oldKey.mSplitResDirs, oldKey.mOverlayPaths, oldKey.mLibDirs,
                displayId, rebasedOverrideConfig, oldKey.mCompatInfo, oldKey.mLoaders);

        if (DEBUG) {
@@ -1454,6 +1490,25 @@ public class ResourcesManager {
        return newKey;
    }

    /**
     * Updates the window configuration of the destination configuration from the source
     * configuration.
     *
     * @param destConfig The destination configuration to update.
     * @param srcConfig The source configuration which will update to the destination configuration.
     * @return true if the destination configuration is changed.
     */
    private static boolean updateWindowConfiguration(@NonNull Configuration destConfig,
            @NonNull Configuration srcConfig) {
        final int changes = destConfig.windowConfiguration.updateFrom(
                srcConfig.windowConfiguration);
        if (changes != 0 && srcConfig.seq != 0) {
            destConfig.seq = srcConfig.seq;
        }
        return changes != 0;
    }


    @RavenwoodThrow(reason = "AppInfo update not supported")
    public void appendPendingAppInfoUpdate(@NonNull String[] oldSourceDirs,
            @NonNull ApplicationInfo appInfo) {
@@ -1608,6 +1663,7 @@ public class ResourcesManager {

                    if (!Arrays.equals(newLibAssets, key.mLibDirs)) {
                        updatedResourceKeys.put(impl, new ResourcesKey(
                                key.mTokenIdentity,
                                key.mResDir,
                                key.mSplitResDirs,
                                key.mOverlayPaths,
@@ -1680,6 +1736,7 @@ public class ResourcesManager {

        @NonNull ResourcesKey collectedKey() {
            return new ResourcesKey(
                    originalKey == null ? 0 : originalKey.mTokenIdentity,
                    originalKey == null ? null : originalKey.mResDir,
                    originalKey == null ? null : originalKey.mSplitResDirs,
                    orderedOverlays.toArray(new String[0]), orderedLibs.toArray(new String[0]),
@@ -1764,6 +1821,7 @@ public class ResourcesManager {
                        || key.mResDir.equals(baseCodePath)
                        || ArrayUtils.contains(oldSourceDirs, key.mResDir)) {
                    updatedResourceKeys.put(impl, new ResourcesKey(
                            key.mTokenIdentity,
                            baseCodePath,
                            copiedSplitDirs,
                            copiedResourceDirs,
@@ -1927,6 +1985,7 @@ public class ResourcesManager {
                }

                final ResourcesKey newKey = new ResourcesKey(
                        oldKey.mTokenIdentity,
                        oldKey.mResDir,
                        oldKey.mSplitResDirs,
                        oldKey.mOverlayPaths,
+24 −11
Original line number Diff line number Diff line
@@ -31,6 +31,14 @@ import java.util.Objects;
/** @hide */
@RavenwoodKeepWholeClass
public final class ResourcesKey {
    /**
     * The identity hash of owner Activity/WindowTokenClient's token. It can be zero for global
     * resources. If the token identity is set, it means that different
     * {@link Configuration#windowConfiguration} of {@link #mOverrideConfiguration} cannot be
     * shared for different tokens.
     */
    public final int mTokenIdentity;

    @Nullable
    @UnsupportedAppUsage
    public final String mResDir;
@@ -67,7 +75,8 @@ public final class ResourcesKey {

    private final int mHash;

    public ResourcesKey(@Nullable String resDir,
    public ResourcesKey(int tokenIdentity,
            @Nullable String resDir,
            @Nullable String[] splitResDirs,
            @Nullable String[] overlayPaths,
            @Nullable String[] libDirs,
@@ -75,6 +84,7 @@ public final class ResourcesKey {
            @Nullable Configuration overrideConfig,
            @Nullable CompatibilityInfo compatInfo,
            @Nullable ResourcesLoader[] loader) {
        mTokenIdentity = tokenIdentity;
        mResDir = resDir;
        mSplitResDirs = splitResDirs;
        mOverlayPaths = overlayPaths;
@@ -105,8 +115,8 @@ public final class ResourcesKey {
            int displayId,
            @Nullable Configuration overrideConfig,
            @Nullable CompatibilityInfo compatInfo) {
        this(resDir, splitResDirs, overlayPaths, libDirs, displayId, overrideConfig, compatInfo,
                null);
        this(0 /* tokenIdentity */, resDir, splitResDirs, overlayPaths, libDirs, displayId,
                overrideConfig, compatInfo, null /* loader */);
    }

    public boolean hasOverrideConfiguration() {
@@ -166,9 +176,12 @@ public final class ResourcesKey {
            return false;
        }
        if (android.content.res.Flags.ignoreNonPublicConfigDiffForResourcesKey()) {
            // Different tokens need to have their own ResourcesImpl instances to store different
            // window configurations.
            final boolean ignoreWindowConfig = mTokenIdentity == peer.mTokenIdentity;
            // Do not compare the configuration fields that won't affect resources.
            if (mOverrideConfiguration.diff(peer.mOverrideConfiguration,
                    true /* compareUndefined */, true /* publicOnly */) != 0) {
                    true /* compareUndefined */, ignoreWindowConfig /* publicOnly */) != 0) {
                return false;
            }
        } else if (!Objects.equals(mOverrideConfiguration, peer.mOverrideConfiguration)) {
+18 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.content.res;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
@@ -377,16 +378,33 @@ public class ResourcesManagerTest {
    @SmallTest
    public void testUpdateResourcesForActivityUpdateWindowConfiguration() {
        final Binder activity = new Binder();
        final Binder activity2 = new Binder();
        final Configuration overrideConfig = new Configuration();
        final Resources resources = mResourcesManager.getResources(
                activity, APP_ONE_RES_DIR, null, null, null, null, Display.DEFAULT_DISPLAY,
                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
        final Resources resources2 = mResourcesManager.getResources(
                activity2, APP_ONE_RES_DIR, null, null, null, null, Display.DEFAULT_DISPLAY,
                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
        overrideConfig.windowConfiguration.getBounds().set(100, 100, 600, 1200);
        mResourcesManager.updateResourcesForActivity(activity, overrideConfig,
                Display.DEFAULT_DISPLAY);

        assertEquals(overrideConfig.windowConfiguration,
                resources.getConfiguration().windowConfiguration);
        assertEquals(overrideConfig.windowConfiguration,
                resources.getDisplayAdjustments().getConfiguration().windowConfiguration);
        assertNotEquals(resources.getConfiguration().windowConfiguration,
                resources2.getConfiguration().windowConfiguration);

        overrideConfig.windowConfiguration.getBounds().offset(10, 10);
        mResourcesManager.updateResourcesForActivity(activity2, overrideConfig,
                Display.DEFAULT_DISPLAY);

        assertEquals(overrideConfig.windowConfiguration,
                resources2.getConfiguration().windowConfiguration);
        assertNotEquals(resources.getConfiguration().windowConfiguration,
                resources2.getConfiguration().windowConfiguration);
    }

    @Test