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

Commit 8efbbe75 authored by Andrii Kulian's avatar Andrii Kulian
Browse files

Don't override activity display adjustments with app config

When process configuration was applied on the client side it
accidentally applied an override to display adjustments in resources
for all ResourceImpl objects. This resulted in resources of
activities having incorrect display adjustments and reporting
incorrect display size.

This CL fixes the issue by updating the applied config with the
activity override. It also removes
ResourcesManager#applyNonDefaultDisplayMetricsToConfiguration, which
is no longer needed on the client side since the server-side is fully
multi-display aware.

Bug: 148639826
Test: ActivityThreadTest#testHandleConfigurationChangedDoesntOverrideActivityConfig
Test: AppConfigurationTests#testDisplaySizeInSplitScreen
Change-Id: Ib3ee007bcccd11451556b66274de4257cba082d4
parent df8bb003
Loading
Loading
Loading
Loading
+7 −40
Original line number Diff line number Diff line
@@ -250,28 +250,6 @@ public class ResourcesManager {
        return dm;
    }

    private static void applyNonDefaultDisplayMetricsToConfiguration(
            @NonNull DisplayMetrics dm, @NonNull Configuration config) {
        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
        config.densityDpi = dm.densityDpi;
        config.screenWidthDp = (int) (dm.widthPixels / dm.density);
        config.screenHeightDp = (int) (dm.heightPixels / dm.density);
        int sl = Configuration.resetScreenLayout(config.screenLayout);
        if (dm.widthPixels > dm.heightPixels) {
            config.orientation = Configuration.ORIENTATION_LANDSCAPE;
            config.screenLayout = Configuration.reduceScreenLayout(sl,
                    config.screenWidthDp, config.screenHeightDp);
        } else {
            config.orientation = Configuration.ORIENTATION_PORTRAIT;
            config.screenLayout = Configuration.reduceScreenLayout(sl,
                    config.screenHeightDp, config.screenWidthDp);
        }
        config.smallestScreenWidthDp = Math.min(config.screenWidthDp, config.screenHeightDp);
        config.compatScreenWidthDp = config.screenWidthDp;
        config.compatScreenHeightDp = config.screenHeightDp;
        config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
    }

    public boolean applyCompatConfigurationLocked(int displayDensity,
            @NonNull Configuration compatConfiguration) {
        if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
@@ -519,17 +497,11 @@ public class ResourcesManager {

    private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) {
        Configuration config;
        final boolean isDefaultDisplay = (key.mDisplayId == Display.DEFAULT_DISPLAY);
        final boolean hasOverrideConfig = key.hasOverrideConfiguration();
        if (!isDefaultDisplay || hasOverrideConfig) {
            config = new Configuration(getConfiguration());
            if (!isDefaultDisplay) {
                applyNonDefaultDisplayMetricsToConfiguration(dm, config);
            }
        if (hasOverrideConfig) {
            config = new Configuration(getConfiguration());
            config.updateFrom(key.mOverrideConfiguration);
            if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration);
            }
        } else {
            config = getConfiguration();
        }
@@ -1110,8 +1082,6 @@ public class ResourcesManager {
                    + resourcesImpl + " config to: " + config);
        }
        int displayId = key.mDisplayId;
        final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
        tmpConfig.setTo(config);

        // Get new DisplayMetrics based on the DisplayAdjustments given to the ResourcesImpl. Update
        // a copy if the CompatibilityInfo changed, because the ResourcesImpl object will handle the
@@ -1121,15 +1091,12 @@ public class ResourcesManager {
            daj = new DisplayAdjustments(daj);
            daj.setCompatibilityInfo(compat);
        }
        daj.setConfiguration(config);
        DisplayMetrics dm = getDisplayMetrics(displayId, daj);
        if (displayId != Display.DEFAULT_DISPLAY) {
            applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
        }

        if (hasOverrideConfiguration) {
        tmpConfig.setTo(config);
        if (key.hasOverrideConfiguration()) {
            tmpConfig.updateFrom(key.mOverrideConfiguration);
        }
        daj.setConfiguration(tmpConfig);
        DisplayMetrics dm = getDisplayMetrics(displayId, daj);
        resourcesImpl.updateConfiguration(tmpConfig, dm, compat);
    }

+55 −0
Original line number Diff line number Diff line
@@ -40,7 +40,10 @@ import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.StopActivityItem;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.view.Display;
import android.view.View;
@@ -306,6 +309,58 @@ public class ActivityThreadTest {
        assertEquals(400, activity.mConfig.smallestScreenWidthDp);
    }

    @Test
    public void testHandleConfigurationChangedDoesntOverrideActivityConfig() {
        final TestActivity activity = mActivityTestRule.launchActivity(new Intent());

        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            final Configuration oldActivityConfig =
                    new Configuration(activity.getResources().getConfiguration());
            final DisplayMetrics oldActivityMetrics = new DisplayMetrics();
            activity.getDisplay().getMetrics(oldActivityMetrics);
            final Resources oldAppResources = activity.getApplication().getResources();
            final Configuration oldAppConfig =
                    new Configuration(oldAppResources.getConfiguration());
            final DisplayMetrics oldApplicationMetrics = new DisplayMetrics();
            oldApplicationMetrics.setTo(oldAppResources.getDisplayMetrics());
            assertEquals("Process config must match the top activity config by default",
                    0, oldActivityConfig.diffPublicOnly(oldAppConfig));
            assertEquals("Process config must match the top activity config by default",
                    oldActivityMetrics, oldApplicationMetrics);

            // Update the application configuration separately from activity config
            final Configuration newAppConfig = new Configuration(oldAppConfig);
            newAppConfig.densityDpi += 100;
            newAppConfig.screenHeightDp += 100;
            final Rect newBounds = new Rect(newAppConfig.windowConfiguration.getAppBounds());
            newBounds.bottom += 100;
            newAppConfig.windowConfiguration.setAppBounds(newBounds);
            newAppConfig.windowConfiguration.setBounds(newBounds);
            newAppConfig.seq++;

            final ActivityThread activityThread = activity.getActivityThread();
            activityThread.handleConfigurationChanged(newAppConfig);

            // Verify that application config update was applied, but didn't change activity config.
            assertEquals("Activity config must not change if the process config changes",
                    oldActivityConfig, activity.getResources().getConfiguration());

            final DisplayMetrics newActivityMetrics = new DisplayMetrics();
            activity.getDisplay().getMetrics(newActivityMetrics);
            assertEquals("Activity display size must not change if the process config changes",
                    oldActivityMetrics, newActivityMetrics);
            final Resources newAppResources = activity.getApplication().getResources();
            assertEquals("Application config must be updated",
                    newAppConfig, newAppResources.getConfiguration());
            final DisplayMetrics newApplicationMetrics = new DisplayMetrics();
            newApplicationMetrics.setTo(newAppResources.getDisplayMetrics());
            assertNotEquals("Application display size must be updated after config update",
                    oldApplicationMetrics, newApplicationMetrics);
            assertNotEquals("Application display size must be updated after config update",
                    newActivityMetrics, newApplicationMetrics);
        });
    }

    @Test
    public void testResumeAfterNewIntent() {
        final Activity activity = mActivityTestRule.launchActivity(new Intent());