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

Commit 06e0f4d7 authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Let WindowProcessController apply app specific config" into main

parents c9a621a0 b026b57e
Loading
Loading
Loading
Loading
+10 −82
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
import static android.app.WindowConfiguration.isFloating;
import static android.app.admin.DevicePolicyResources.Drawables.Source.PROFILE_SWITCH_ANIMATION;
import static android.app.admin.DevicePolicyResources.Drawables.Style.OUTLINE;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
@@ -343,7 +342,6 @@ import android.service.contentcapture.ActivityEvent;
import android.service.dreams.DreamActivity;
import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.MergedConfiguration;
@@ -8687,7 +8685,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
        }
        applySizeOverrideIfNeeded(newParentConfiguration, parentWindowingMode, resolvedConfig);
        applySizeOverrideIfNeeded(newParentConfiguration, resolvedConfig);
        mResolveConfigHint.resetTmpOverrides();
        logAppCompatState();
@@ -8710,85 +8708,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     * TODO: Consider integrate this with computeConfigByResolveHint()
     */
    private void applySizeOverrideIfNeeded(Configuration newParentConfiguration,
            int parentWindowingMode, Configuration inOutConfig) {
        if (mDisplayContent == null) {
            return;
        }
        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
        int rotation = newParentConfiguration.windowConfiguration.getRotation();
        if (rotation == ROTATION_UNDEFINED && !isFixedRotationTransforming()) {
            rotation = mDisplayContent.getRotation();
        }
        if (!mOptOutEdgeToEdge && (!mResolveConfigHint.mUseOverrideInsetsForConfig
                || getCompatDisplayInsets() != null
                || (isFloating(parentWindowingMode)
                        // Check the requested windowing mode of activity as well in case it is
                        // switching between PiP and fullscreen.
                        && (inOutConfig.windowConfiguration.getWindowingMode()
                                == WINDOWING_MODE_UNDEFINED
                                || isFloating(inOutConfig.windowConfiguration.getWindowingMode())))
                || rotation == ROTATION_UNDEFINED)) {
            // If the insets configuration decoupled logic is not enabled for the app, or the app
            // already has a compat override, or the context doesn't contain enough info to
            // calculate the override, skip the override.
            return;
        }
        // Make sure the orientation related fields will be updated by the override insets, because
        // fixed rotation has assigned the fields from display's configuration.
        if (hasFixedRotationTransform()) {
            inOutConfig.windowConfiguration.setAppBounds(null);
            inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
            inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
            inOutConfig.smallestScreenWidthDp = Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
            inOutConfig.orientation = ORIENTATION_UNDEFINED;
        }
        // Override starts here.
        final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
        final int dw = rotated ? mDisplayContent.mBaseDisplayHeight
                : mDisplayContent.mBaseDisplayWidth;
        final int dh = rotated ? mDisplayContent.mBaseDisplayWidth
                : mDisplayContent.mBaseDisplayHeight;
        final Rect nonDecorInsets = mDisplayContent.getDisplayPolicy()
                .getDecorInsetsInfo(rotation, dw, dh).mOverrideNonDecorInsets;
        // This should be the only place override the configuration for ActivityRecord. Override
        // the value if not calculated yet.
        Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
        if (outAppBounds == null || outAppBounds.isEmpty()) {
            inOutConfig.windowConfiguration.setAppBounds(parentBounds);
            outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
            outAppBounds.inset(nonDecorInsets);
        }
        float density = inOutConfig.densityDpi;
        if (density == Configuration.DENSITY_DPI_UNDEFINED) {
            density = newParentConfiguration.densityDpi;
        }
        density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
        if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
            inOutConfig.screenWidthDp = (int) (outAppBounds.width() / density + 0.5f);
        }
        if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
            inOutConfig.screenHeightDp = (int) (outAppBounds.height() / density + 0.5f);
        }
        if (inOutConfig.smallestScreenWidthDp
                == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
                && parentWindowingMode == WINDOWING_MODE_FULLSCREEN) {
            // For the case of PIP transition and multi-window environment, the
            // smallestScreenWidthDp is handled already. Override only if the app is in
            // fullscreen.
            final DisplayInfo info = new DisplayInfo(mDisplayContent.getDisplayInfo());
            mDisplayContent.computeSizeRanges(info, rotated, dw, dh,
                    mDisplayContent.getDisplayMetrics().density,
                    inOutConfig, true /* overrideConfig */);
        }
        // It's possible that screen size will be considered in different orientation with or
        // without considering the system bar insets. Override orientation as well.
        if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
            inOutConfig.orientation =
                    (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
                            ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
        }
            Configuration inOutConfig) {
        applySizeOverride(
                mDisplayContent,
                info.applicationInfo,
                newParentConfiguration,
                inOutConfig,
                mOptOutEdgeToEdge,
                hasFixedRotationTransform(),
                getCompatDisplayInsets() != null);
    }
    private void computeConfigByResolveHint(@NonNull Configuration resolvedConfig,
+125 −2
Original line number Diff line number Diff line
@@ -22,14 +22,23 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
import static android.app.WindowConfiguration.isFloating;
import static android.app.WindowConfiguration.windowingModeToString;
import static android.app.WindowConfigurationProto.WINDOWING_MODE;
import static android.content.ConfigurationProto.WINDOW_CONFIGURATION;
import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION;
import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION;
@@ -38,11 +47,14 @@ import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGU
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.app.WindowConfiguration;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.LocaleList;
import android.util.DisplayMetrics;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;

import com.android.internal.annotations.VisibleForTesting;

@@ -523,6 +535,116 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
        return getActivityType() == ACTIVITY_TYPE_ASSISTANT;
    }

    /**
     * @see ActivityRecord#applySizeOverrideIfNeeded
     */
    public static boolean applySizeOverride(DisplayContent displayContent, ApplicationInfo appInfo,
            Configuration newParentConfiguration, Configuration inOutConfig,
            boolean optOutEdgeToEdge, boolean hasFixedRotationTransform,
            boolean hasCompatDisplayInsets) {
        if (displayContent == null) {
            return false;
        }
        final boolean useOverrideInsetsForConfig =
                displayContent.mWmService.mFlags.mInsetsDecoupledConfiguration
                        ? !appInfo.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)
                                && !appInfo.isChangeEnabled(
                                        OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION)
                        : appInfo.isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION);
        if (newParentConfiguration == null) {
            newParentConfiguration = displayContent.getConfiguration();
        }
        final int parentWindowingMode =
                newParentConfiguration.windowConfiguration.getWindowingMode();
        final boolean isFloating = isFloating(parentWindowingMode)
                // Check the requested windowing mode of activity as well in case it is
                // switching between PiP and fullscreen.
                && (inOutConfig.windowConfiguration.getWindowingMode() == WINDOWING_MODE_UNDEFINED
                        || isFloating(inOutConfig.windowConfiguration.getWindowingMode()));
        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
        int rotation = newParentConfiguration.windowConfiguration.getRotation();
        if (rotation == ROTATION_UNDEFINED && !hasFixedRotationTransform) {
            rotation = displayContent.getRotation();
        }
        if (!optOutEdgeToEdge && (!useOverrideInsetsForConfig
                || hasCompatDisplayInsets
                || isFloating
                || rotation == ROTATION_UNDEFINED)) {
            // If the insets configuration decoupled logic is not enabled for the app, or the app
            // already has a compat override, or the context doesn't contain enough info to
            // calculate the override, skip the override.
            return false;
        }
        // Make sure the orientation related fields will be updated by the override insets, because
        // fixed rotation has assigned the fields from display's configuration.
        if (hasFixedRotationTransform) {
            inOutConfig.windowConfiguration.setAppBounds(null);
            inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
            inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
            inOutConfig.smallestScreenWidthDp = Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
            inOutConfig.orientation = ORIENTATION_UNDEFINED;
        }

        // Override starts here.
        final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
        final int dw = rotated
                ? displayContent.mBaseDisplayHeight
                : displayContent.mBaseDisplayWidth;
        final int dh = rotated
                ? displayContent.mBaseDisplayWidth
                : displayContent.mBaseDisplayHeight;
        final Rect nonDecorFrame = displayContent.getDisplayPolicy()
                .getDecorInsetsInfo(rotation, dw, dh).mOverrideNonDecorFrame;
        // This should be the only place override the configuration for ActivityRecord. Override
        // the value if not calculated yet.
        Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
        if (outAppBounds == null || outAppBounds.isEmpty()) {
            inOutConfig.windowConfiguration.setAppBounds(parentBounds);
            outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
            outAppBounds.intersect(nonDecorFrame);
        }
        float density = inOutConfig.densityDpi;
        if (density == Configuration.DENSITY_DPI_UNDEFINED) {
            density = newParentConfiguration.densityDpi;
        }
        density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
        if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
            inOutConfig.screenWidthDp = (int) (outAppBounds.width() / density + 0.5f);
        }
        if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
            inOutConfig.screenHeightDp = (int) (outAppBounds.height() / density + 0.5f);
        }
        if (inOutConfig.smallestScreenWidthDp == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
                && parentWindowingMode == WINDOWING_MODE_FULLSCREEN) {
            // For the case of PIP transition and multi-window environment, the
            // smallestScreenWidthDp is handled already. Override only if the app is in
            // fullscreen.
            final DisplayInfo info = new DisplayInfo(displayContent.getDisplayInfo());
            displayContent.computeSizeRanges(info, rotated, dw, dh,
                    displayContent.getDisplayMetrics().density,
                    inOutConfig, true /* overrideConfig */);
        }

        // It's possible that screen size will be considered in different orientation with or
        // without considering the system bar insets. Override orientation as well.
        if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
            inOutConfig.orientation =
                    (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
                            ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
        }
        return true;
    }

    /**
     * Gives the derived class a chance to apply the app-specific configuration.
     *
     * @param inOutConfig the configuration as the requested configuration.
     * @return true if any of the given configuration has been updated.
     */
    public boolean onApplyAppSpecificConfig(Configuration inOutConfig) {
        return false;
    }

    /**
     * Applies app-specific nightMode and {@link LocaleList} on requested configuration.
     * @return true if any of the requested configuration has been updated.
@@ -530,16 +652,17 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
    public boolean applyAppSpecificConfig(Integer nightMode, LocaleList locales,
            @Configuration.GrammaticalGender Integer gender) {
        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
        boolean changed = onApplyAppSpecificConfig(mRequestsTmpConfig);
        boolean newNightModeSet = (nightMode != null) && setOverrideNightMode(mRequestsTmpConfig,
                nightMode);
        boolean newLocalesSet = (locales != null) && setOverrideLocales(mRequestsTmpConfig,
                locales);
        boolean newGenderSet = setOverrideGender(mRequestsTmpConfig,
                gender == null ? Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED : gender);
        if (newNightModeSet || newLocalesSet || newGenderSet) {
        if (changed || newNightModeSet || newLocalesSet || newGenderSet) {
            onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
        }
        return newNightModeSet || newLocalesSet || newGenderSet;
        return changed || newNightModeSet || newLocalesSet || newGenderSet;
    }

    /**
+19 −0
Original line number Diff line number Diff line
@@ -1580,6 +1580,25 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        unregisterActivityConfigurationListener();
    }

    @Override
    public boolean onApplyAppSpecificConfig(Configuration inOutConfig) {
        if (mConfigActivityRecord != null) {
            // Let the activity decide whether to apply the size override.
            return false;
        }
        final DisplayContent displayContent = mAtm.mWindowManager != null
                ? mAtm.mWindowManager.getDefaultDisplayContentLocked()
                : null;
        return applySizeOverride(
                displayContent,
                mInfo,
                null /* newParentConfiguration */,
                inOutConfig,
                false /* optOutEdgeToEdge */,
                false /* hasFixedRotationTransform */,
                false /* hasCompatDisplayInsets */);
    }

    @Override
    public void onConfigurationChanged(Configuration newGlobalConfig) {
        super.onConfigurationChanged(newGlobalConfig);