Loading services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java +7 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,13 @@ class AppCompatAspectRatioOverrides { && cameraPolicy.isTreatmentEnabledForActivity(mActivityRecord)); } /** * Returns the value of the user aspect ratio override property. If unset, return {@code true}. */ boolean getAllowUserAspectRatioOverridePropertyValue() { return !mAllowUserAspectRatioOverrideOptProp.isFalse(); } @VisibleForTesting int getUserMinAspectRatioOverrideCode() { try { Loading services/core/java/com/android/server/wm/AppCompatController.java +9 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ class AppCompatController { @NonNull private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy; @NonNull private final DesktopAppCompatAspectRatioPolicy mDesktopAppCompatAspectRatioPolicy; @NonNull private final AppCompatOverrides mAppCompatOverrides; @NonNull private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery; Loading @@ -63,6 +65,8 @@ class AppCompatController { wmService.mAppCompatConfiguration); mAppCompatLetterboxPolicy = new AppCompatLetterboxPolicy(mActivityRecord, wmService.mAppCompatConfiguration); mDesktopAppCompatAspectRatioPolicy = new DesktopAppCompatAspectRatioPolicy(activityRecord, mAppCompatOverrides, mTransparentPolicy, wmService.mAppCompatConfiguration); } @NonNull Loading @@ -80,6 +84,11 @@ class AppCompatController { return mAppCompatAspectRatioPolicy; } @NonNull DesktopAppCompatAspectRatioPolicy getDesktopAppCompatAspectRatioPolicy() { return mDesktopAppCompatAspectRatioPolicy; } @NonNull AppCompatOverrides getAppCompatOverrides() { return mAppCompatOverrides; Loading services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java 0 → 100644 +294 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static com.android.server.wm.AppCompatConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; import android.annotation.NonNull; import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.graphics.Rect; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; // TODO(b/359217664): Consider refactoring into AppCompatAspectRatioPolicy. /** * Encapsulate app compat aspect ratio policy logic specific for desktop windowing initial bounds * calculation. */ public class DesktopAppCompatAspectRatioPolicy { @NonNull private final AppCompatOverrides mAppCompatOverrides; @NonNull private final AppCompatConfiguration mAppCompatConfiguration; @NonNull private final ActivityRecord mActivityRecord; @NonNull private final TransparentPolicy mTransparentPolicy; DesktopAppCompatAspectRatioPolicy(@NonNull ActivityRecord activityRecord, @NonNull AppCompatOverrides appCompatOverrides, @NonNull TransparentPolicy transparentPolicy, @NonNull AppCompatConfiguration appCompatConfiguration) { mActivityRecord = activityRecord; mAppCompatOverrides = appCompatOverrides; mTransparentPolicy = transparentPolicy; mAppCompatConfiguration = appCompatConfiguration; } /** * Calculates the final aspect ratio of an launching activity based on the task it will be * launched in. Takes into account any min or max aspect ratio constraints. */ float calculateAspectRatio(@NonNull Task task) { final float maxAspectRatio = getMaxAspectRatio(); final float minAspectRatio = getMinAspectRatio(task); float desiredAspectRatio = 0; desiredAspectRatio = getDesiredAspectRatio(task); if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) { desiredAspectRatio = maxAspectRatio; } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) { desiredAspectRatio = minAspectRatio; } return desiredAspectRatio; } /** * Returns the aspect ratio desired by the system for current activity, not taking into account * any min or max aspect ratio constraints. */ @VisibleForTesting float getDesiredAspectRatio(@NonNull Task task) { final float letterboxAspectRatioOverride = getFixedOrientationLetterboxAspectRatio(task); // Aspect ratio as suggested by the system. Apps requested mix/max aspect ratio will // be respected in #calculateAspectRatio. if (isDefaultMultiWindowLetterboxAspectRatioDesired(task)) { return DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; } else if (letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { return letterboxAspectRatioOverride; } return AppCompatUtils.computeAspectRatio(task.getDisplayArea().getBounds()); } /** * Determines the letterbox aspect ratio for an application based on its orientation and * resizability. */ private float getFixedOrientationLetterboxAspectRatio(@NonNull Task task) { return mActivityRecord.shouldCreateCompatDisplayInsets() ? getDefaultMinAspectRatioForUnresizableApps(task) : getDefaultMinAspectRatio(task); } /** * Calculates the aspect ratio of the available display area when an app enters split-screen on * a given device, taking into account any dividers and insets. */ private float getSplitScreenAspectRatio(@NonNull Task task) { // Getting the same aspect ratio that apps get in split screen. final DisplayArea displayArea = task.getDisplayArea(); final int dividerWindowWidth = mActivityRecord.mWmService.mContext.getResources().getDimensionPixelSize( R.dimen.docked_stack_divider_thickness); final int dividerInsets = mActivityRecord.mWmService.mContext.getResources().getDimensionPixelSize( R.dimen.docked_stack_divider_insets); final int dividerSize = dividerWindowWidth - dividerInsets * 2; final Rect bounds = new Rect(displayArea.getWindowConfiguration().getAppBounds()); if (bounds.width() >= bounds.height()) { bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0); bounds.right = bounds.centerX(); } else { bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2); bounds.bottom = bounds.centerY(); } return AppCompatUtils.computeAspectRatio(bounds); } /** * Returns the minimum aspect ratio for unresizable apps as determined by the system. */ private float getDefaultMinAspectRatioForUnresizableApps(@NonNull Task task) { if (!mAppCompatConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled()) { return mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps() > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps() : getDefaultMinAspectRatio(task); } return getSplitScreenAspectRatio(task); } /** * Returns the default minimum aspect ratio for apps as determined by the system. */ private float getDefaultMinAspectRatio(@NonNull Task task) { if (!mAppCompatConfiguration.getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox()) { return mAppCompatConfiguration.getFixedOrientationLetterboxAspectRatio(); } return getDisplayAreaMinAspectRatio(task); } /** * Calculates the aspect ratio of the available display area. */ private float getDisplayAreaMinAspectRatio(@NonNull Task task) { final DisplayArea displayArea = task.getDisplayArea(); final Rect bounds = new Rect(displayArea.getWindowConfiguration().getAppBounds()); return AppCompatUtils.computeAspectRatio(bounds); } /** * Returns {@code true} if the default aspect ratio for a letterboxed app in multi-window mode * should be used. */ private boolean isDefaultMultiWindowLetterboxAspectRatioDesired(@NonNull Task task) { final DisplayContent dc = task.mDisplayContent; final int windowingMode = task.getDisplayArea().getWindowingMode(); return WindowConfiguration.inMultiWindowMode(windowingMode) && !dc.getIgnoreOrientationRequest(); } /** * Returns the min aspect ratio of this activity. */ private float getMinAspectRatio(@NonNull Task task) { if (mTransparentPolicy.isRunning()) { return mTransparentPolicy.getInheritedMinAspectRatio(); } final ActivityInfo info = mActivityRecord.info; if (info.applicationInfo == null) { return info.getMinAspectRatio(); } final AppCompatAspectRatioOverrides aspectRatioOverrides = mAppCompatOverrides.getAppCompatAspectRatioOverrides(); if (shouldApplyUserMinAspectRatioOverride(task)) { return aspectRatioOverrides.getUserMinAspectRatio(); } if (!aspectRatioOverrides.shouldOverrideMinAspectRatio() && !mAppCompatOverrides.getAppCompatCameraOverrides() .shouldOverrideMinAspectRatioForCamera()) { return info.getMinAspectRatio(); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY) && !ActivityInfo.isFixedOrientationPortrait( mActivityRecord.getOverrideOrientation())) { return info.getMinAspectRatio(); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN) && isFullscreenPortrait(task)) { return info.getMinAspectRatio(); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN)) { return Math.max(aspectRatioOverrides.getSplitScreenAspectRatio(), info.getMinAspectRatio()); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_LARGE)) { return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE, info.getMinAspectRatio()); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_MEDIUM)) { return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE, info.getMinAspectRatio()); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_SMALL)) { return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE, info.getMinAspectRatio()); } return info.getMinAspectRatio(); } /** * Returns the max aspect ratio of this activity. */ private float getMaxAspectRatio() { if (mTransparentPolicy.isRunning()) { return mTransparentPolicy.getInheritedMaxAspectRatio(); } return mActivityRecord.info.getMaxAspectRatio(); } /** * Whether an applications minimum aspect ratio has been overridden. */ boolean hasMinAspectRatioOverride(@NonNull Task task) { return mActivityRecord.info.getMinAspectRatio() < getMinAspectRatio(task); } /** * Whether we should apply the user aspect ratio override to the min aspect ratio for the * current app. */ private boolean shouldApplyUserMinAspectRatioOverride(@NonNull Task task) { if (!shouldEnableUserAspectRatioSettings(task)) { return false; } final int userAspectRatioCode = mAppCompatOverrides.getAppCompatAspectRatioOverrides() .getUserMinAspectRatioOverrideCode(); return userAspectRatioCode != USER_MIN_ASPECT_RATIO_UNSET && userAspectRatioCode != USER_MIN_ASPECT_RATIO_APP_DEFAULT && userAspectRatioCode != USER_MIN_ASPECT_RATIO_FULLSCREEN; } /** * Whether we should enable users to resize the current app. */ private boolean shouldEnableUserAspectRatioSettings(@NonNull Task task) { // We use mBooleanPropertyAllowUserAspectRatioOverride to allow apps to opt-out which has // effect only if explicitly false. If mBooleanPropertyAllowUserAspectRatioOverride is null, // the current app doesn't opt-out so the first part of the predicate is true. return mAppCompatOverrides.getAppCompatAspectRatioOverrides() .getAllowUserAspectRatioOverridePropertyValue() && mAppCompatConfiguration.isUserAppAspectRatioSettingsEnabled() && task.mDisplayContent.getIgnoreOrientationRequest(); } /** * Returns {@code true} if the task window is portrait and fullscreen. */ private boolean isFullscreenPortrait(@NonNull Task task) { return task.getConfiguration().orientation == ORIENTATION_PORTRAIT && task.getWindowConfiguration().getWindowingMode() == WINDOWING_MODE_FULLSCREEN; } } services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java +16 −9 Original line number Diff line number Diff line Loading @@ -31,10 +31,10 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import android.app.WindowConfiguration; import android.app.WindowConfiguration.WindowingMode; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.UserMinAspectRatio; import android.content.res.Configuration; import android.graphics.Rect; import android.view.Surface; Loading Loading @@ -176,10 +176,14 @@ class AppCompatActivityRobot { return mActivityStack.getFromTop(fromTop); } void setTaskWindowingMode(@WindowConfiguration.WindowingMode int windowingMode) { void setTaskWindowingMode(@WindowingMode int windowingMode) { mTaskStack.top().setWindowingMode(windowingMode); } void setTaskDisplayAreaWindowingMode(@WindowingMode int windowingMode) { mTaskStack.top().getDisplayArea().setWindowingMode(windowingMode); } void setLetterboxedForFixedOrientationAndAspectRatio(boolean enabled) { doReturn(enabled).when(mActivityStack.top().mAppCompatController .getAppCompatAspectRatioPolicy()).isLetterboxedForFixedOrientationAndAspectRatio(); Loading Loading @@ -222,10 +226,14 @@ class AppCompatActivityRobot { .getAppCompatAspectRatioOverrides()).shouldApplyUserFullscreenOverride(); } void setGetUserMinAspectRatioOverrideCode(@PackageManager.UserMinAspectRatio int orientation) { doReturn(orientation).when(mActivityStack.top() .mAppCompatController.getAppCompatAspectRatioOverrides()) .getUserMinAspectRatioOverrideCode(); void setGetUserMinAspectRatioOverrideCode(@UserMinAspectRatio int overrideCode) { doReturn(overrideCode).when(mActivityStack.top().mAppCompatController .getAppCompatAspectRatioOverrides()).getUserMinAspectRatioOverrideCode(); } void setGetUserMinAspectRatioOverrideValue(float overrideValue) { doReturn(overrideValue).when(mActivityStack.top().mAppCompatController .getAppCompatAspectRatioOverrides()).getUserMinAspectRatio(); } void setIgnoreOrientationRequest(boolean enabled) { Loading @@ -233,8 +241,7 @@ class AppCompatActivityRobot { } void setTopTaskInMultiWindowMode(boolean inMultiWindowMode) { doReturn(inMultiWindowMode).when(mTaskStack.top()) .inMultiWindowMode(); doReturn(inMultiWindowMode).when(mTaskStack.top()).inMultiWindowMode(); } void setTopActivityAsEmbedded(boolean embedded) { Loading services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java +5 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,11 @@ class AppCompatConfigurationRobot { doReturn(enabled).when(mAppCompatConfiguration).isCameraCompatTreatmentEnabled(); } void enableSplitScreenAspectRatioForUnresizableApps(boolean enabled) { doReturn(enabled).when(mAppCompatConfiguration) .getIsSplitScreenAspectRatioForUnresizableAppsEnabled(); } void enableCameraCompatTreatmentAtBuildTime(boolean enabled) { doReturn(enabled).when(mAppCompatConfiguration) .isCameraCompatTreatmentEnabledAtBuildTime(); Loading Loading
services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java +7 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,13 @@ class AppCompatAspectRatioOverrides { && cameraPolicy.isTreatmentEnabledForActivity(mActivityRecord)); } /** * Returns the value of the user aspect ratio override property. If unset, return {@code true}. */ boolean getAllowUserAspectRatioOverridePropertyValue() { return !mAllowUserAspectRatioOverrideOptProp.isFalse(); } @VisibleForTesting int getUserMinAspectRatioOverrideCode() { try { Loading
services/core/java/com/android/server/wm/AppCompatController.java +9 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ class AppCompatController { @NonNull private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy; @NonNull private final DesktopAppCompatAspectRatioPolicy mDesktopAppCompatAspectRatioPolicy; @NonNull private final AppCompatOverrides mAppCompatOverrides; @NonNull private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery; Loading @@ -63,6 +65,8 @@ class AppCompatController { wmService.mAppCompatConfiguration); mAppCompatLetterboxPolicy = new AppCompatLetterboxPolicy(mActivityRecord, wmService.mAppCompatConfiguration); mDesktopAppCompatAspectRatioPolicy = new DesktopAppCompatAspectRatioPolicy(activityRecord, mAppCompatOverrides, mTransparentPolicy, wmService.mAppCompatConfiguration); } @NonNull Loading @@ -80,6 +84,11 @@ class AppCompatController { return mAppCompatAspectRatioPolicy; } @NonNull DesktopAppCompatAspectRatioPolicy getDesktopAppCompatAspectRatioPolicy() { return mDesktopAppCompatAspectRatioPolicy; } @NonNull AppCompatOverrides getAppCompatOverrides() { return mAppCompatOverrides; Loading
services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java 0 → 100644 +294 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static com.android.server.wm.AppCompatConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; import android.annotation.NonNull; import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.graphics.Rect; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; // TODO(b/359217664): Consider refactoring into AppCompatAspectRatioPolicy. /** * Encapsulate app compat aspect ratio policy logic specific for desktop windowing initial bounds * calculation. */ public class DesktopAppCompatAspectRatioPolicy { @NonNull private final AppCompatOverrides mAppCompatOverrides; @NonNull private final AppCompatConfiguration mAppCompatConfiguration; @NonNull private final ActivityRecord mActivityRecord; @NonNull private final TransparentPolicy mTransparentPolicy; DesktopAppCompatAspectRatioPolicy(@NonNull ActivityRecord activityRecord, @NonNull AppCompatOverrides appCompatOverrides, @NonNull TransparentPolicy transparentPolicy, @NonNull AppCompatConfiguration appCompatConfiguration) { mActivityRecord = activityRecord; mAppCompatOverrides = appCompatOverrides; mTransparentPolicy = transparentPolicy; mAppCompatConfiguration = appCompatConfiguration; } /** * Calculates the final aspect ratio of an launching activity based on the task it will be * launched in. Takes into account any min or max aspect ratio constraints. */ float calculateAspectRatio(@NonNull Task task) { final float maxAspectRatio = getMaxAspectRatio(); final float minAspectRatio = getMinAspectRatio(task); float desiredAspectRatio = 0; desiredAspectRatio = getDesiredAspectRatio(task); if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) { desiredAspectRatio = maxAspectRatio; } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) { desiredAspectRatio = minAspectRatio; } return desiredAspectRatio; } /** * Returns the aspect ratio desired by the system for current activity, not taking into account * any min or max aspect ratio constraints. */ @VisibleForTesting float getDesiredAspectRatio(@NonNull Task task) { final float letterboxAspectRatioOverride = getFixedOrientationLetterboxAspectRatio(task); // Aspect ratio as suggested by the system. Apps requested mix/max aspect ratio will // be respected in #calculateAspectRatio. if (isDefaultMultiWindowLetterboxAspectRatioDesired(task)) { return DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; } else if (letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { return letterboxAspectRatioOverride; } return AppCompatUtils.computeAspectRatio(task.getDisplayArea().getBounds()); } /** * Determines the letterbox aspect ratio for an application based on its orientation and * resizability. */ private float getFixedOrientationLetterboxAspectRatio(@NonNull Task task) { return mActivityRecord.shouldCreateCompatDisplayInsets() ? getDefaultMinAspectRatioForUnresizableApps(task) : getDefaultMinAspectRatio(task); } /** * Calculates the aspect ratio of the available display area when an app enters split-screen on * a given device, taking into account any dividers and insets. */ private float getSplitScreenAspectRatio(@NonNull Task task) { // Getting the same aspect ratio that apps get in split screen. final DisplayArea displayArea = task.getDisplayArea(); final int dividerWindowWidth = mActivityRecord.mWmService.mContext.getResources().getDimensionPixelSize( R.dimen.docked_stack_divider_thickness); final int dividerInsets = mActivityRecord.mWmService.mContext.getResources().getDimensionPixelSize( R.dimen.docked_stack_divider_insets); final int dividerSize = dividerWindowWidth - dividerInsets * 2; final Rect bounds = new Rect(displayArea.getWindowConfiguration().getAppBounds()); if (bounds.width() >= bounds.height()) { bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0); bounds.right = bounds.centerX(); } else { bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2); bounds.bottom = bounds.centerY(); } return AppCompatUtils.computeAspectRatio(bounds); } /** * Returns the minimum aspect ratio for unresizable apps as determined by the system. */ private float getDefaultMinAspectRatioForUnresizableApps(@NonNull Task task) { if (!mAppCompatConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled()) { return mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps() > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps() : getDefaultMinAspectRatio(task); } return getSplitScreenAspectRatio(task); } /** * Returns the default minimum aspect ratio for apps as determined by the system. */ private float getDefaultMinAspectRatio(@NonNull Task task) { if (!mAppCompatConfiguration.getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox()) { return mAppCompatConfiguration.getFixedOrientationLetterboxAspectRatio(); } return getDisplayAreaMinAspectRatio(task); } /** * Calculates the aspect ratio of the available display area. */ private float getDisplayAreaMinAspectRatio(@NonNull Task task) { final DisplayArea displayArea = task.getDisplayArea(); final Rect bounds = new Rect(displayArea.getWindowConfiguration().getAppBounds()); return AppCompatUtils.computeAspectRatio(bounds); } /** * Returns {@code true} if the default aspect ratio for a letterboxed app in multi-window mode * should be used. */ private boolean isDefaultMultiWindowLetterboxAspectRatioDesired(@NonNull Task task) { final DisplayContent dc = task.mDisplayContent; final int windowingMode = task.getDisplayArea().getWindowingMode(); return WindowConfiguration.inMultiWindowMode(windowingMode) && !dc.getIgnoreOrientationRequest(); } /** * Returns the min aspect ratio of this activity. */ private float getMinAspectRatio(@NonNull Task task) { if (mTransparentPolicy.isRunning()) { return mTransparentPolicy.getInheritedMinAspectRatio(); } final ActivityInfo info = mActivityRecord.info; if (info.applicationInfo == null) { return info.getMinAspectRatio(); } final AppCompatAspectRatioOverrides aspectRatioOverrides = mAppCompatOverrides.getAppCompatAspectRatioOverrides(); if (shouldApplyUserMinAspectRatioOverride(task)) { return aspectRatioOverrides.getUserMinAspectRatio(); } if (!aspectRatioOverrides.shouldOverrideMinAspectRatio() && !mAppCompatOverrides.getAppCompatCameraOverrides() .shouldOverrideMinAspectRatioForCamera()) { return info.getMinAspectRatio(); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY) && !ActivityInfo.isFixedOrientationPortrait( mActivityRecord.getOverrideOrientation())) { return info.getMinAspectRatio(); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN) && isFullscreenPortrait(task)) { return info.getMinAspectRatio(); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN)) { return Math.max(aspectRatioOverrides.getSplitScreenAspectRatio(), info.getMinAspectRatio()); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_LARGE)) { return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE, info.getMinAspectRatio()); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_MEDIUM)) { return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE, info.getMinAspectRatio()); } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_SMALL)) { return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE, info.getMinAspectRatio()); } return info.getMinAspectRatio(); } /** * Returns the max aspect ratio of this activity. */ private float getMaxAspectRatio() { if (mTransparentPolicy.isRunning()) { return mTransparentPolicy.getInheritedMaxAspectRatio(); } return mActivityRecord.info.getMaxAspectRatio(); } /** * Whether an applications minimum aspect ratio has been overridden. */ boolean hasMinAspectRatioOverride(@NonNull Task task) { return mActivityRecord.info.getMinAspectRatio() < getMinAspectRatio(task); } /** * Whether we should apply the user aspect ratio override to the min aspect ratio for the * current app. */ private boolean shouldApplyUserMinAspectRatioOverride(@NonNull Task task) { if (!shouldEnableUserAspectRatioSettings(task)) { return false; } final int userAspectRatioCode = mAppCompatOverrides.getAppCompatAspectRatioOverrides() .getUserMinAspectRatioOverrideCode(); return userAspectRatioCode != USER_MIN_ASPECT_RATIO_UNSET && userAspectRatioCode != USER_MIN_ASPECT_RATIO_APP_DEFAULT && userAspectRatioCode != USER_MIN_ASPECT_RATIO_FULLSCREEN; } /** * Whether we should enable users to resize the current app. */ private boolean shouldEnableUserAspectRatioSettings(@NonNull Task task) { // We use mBooleanPropertyAllowUserAspectRatioOverride to allow apps to opt-out which has // effect only if explicitly false. If mBooleanPropertyAllowUserAspectRatioOverride is null, // the current app doesn't opt-out so the first part of the predicate is true. return mAppCompatOverrides.getAppCompatAspectRatioOverrides() .getAllowUserAspectRatioOverridePropertyValue() && mAppCompatConfiguration.isUserAppAspectRatioSettingsEnabled() && task.mDisplayContent.getIgnoreOrientationRequest(); } /** * Returns {@code true} if the task window is portrait and fullscreen. */ private boolean isFullscreenPortrait(@NonNull Task task) { return task.getConfiguration().orientation == ORIENTATION_PORTRAIT && task.getWindowConfiguration().getWindowingMode() == WINDOWING_MODE_FULLSCREEN; } }
services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java +16 −9 Original line number Diff line number Diff line Loading @@ -31,10 +31,10 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import android.app.WindowConfiguration; import android.app.WindowConfiguration.WindowingMode; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.UserMinAspectRatio; import android.content.res.Configuration; import android.graphics.Rect; import android.view.Surface; Loading Loading @@ -176,10 +176,14 @@ class AppCompatActivityRobot { return mActivityStack.getFromTop(fromTop); } void setTaskWindowingMode(@WindowConfiguration.WindowingMode int windowingMode) { void setTaskWindowingMode(@WindowingMode int windowingMode) { mTaskStack.top().setWindowingMode(windowingMode); } void setTaskDisplayAreaWindowingMode(@WindowingMode int windowingMode) { mTaskStack.top().getDisplayArea().setWindowingMode(windowingMode); } void setLetterboxedForFixedOrientationAndAspectRatio(boolean enabled) { doReturn(enabled).when(mActivityStack.top().mAppCompatController .getAppCompatAspectRatioPolicy()).isLetterboxedForFixedOrientationAndAspectRatio(); Loading Loading @@ -222,10 +226,14 @@ class AppCompatActivityRobot { .getAppCompatAspectRatioOverrides()).shouldApplyUserFullscreenOverride(); } void setGetUserMinAspectRatioOverrideCode(@PackageManager.UserMinAspectRatio int orientation) { doReturn(orientation).when(mActivityStack.top() .mAppCompatController.getAppCompatAspectRatioOverrides()) .getUserMinAspectRatioOverrideCode(); void setGetUserMinAspectRatioOverrideCode(@UserMinAspectRatio int overrideCode) { doReturn(overrideCode).when(mActivityStack.top().mAppCompatController .getAppCompatAspectRatioOverrides()).getUserMinAspectRatioOverrideCode(); } void setGetUserMinAspectRatioOverrideValue(float overrideValue) { doReturn(overrideValue).when(mActivityStack.top().mAppCompatController .getAppCompatAspectRatioOverrides()).getUserMinAspectRatio(); } void setIgnoreOrientationRequest(boolean enabled) { Loading @@ -233,8 +241,7 @@ class AppCompatActivityRobot { } void setTopTaskInMultiWindowMode(boolean inMultiWindowMode) { doReturn(inMultiWindowMode).when(mTaskStack.top()) .inMultiWindowMode(); doReturn(inMultiWindowMode).when(mTaskStack.top()).inMultiWindowMode(); } void setTopActivityAsEmbedded(boolean embedded) { Loading
services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java +5 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,11 @@ class AppCompatConfigurationRobot { doReturn(enabled).when(mAppCompatConfiguration).isCameraCompatTreatmentEnabled(); } void enableSplitScreenAspectRatioForUnresizableApps(boolean enabled) { doReturn(enabled).when(mAppCompatConfiguration) .getIsSplitScreenAspectRatioForUnresizableAppsEnabled(); } void enableCameraCompatTreatmentAtBuildTime(boolean enabled) { doReturn(enabled).when(mAppCompatConfiguration) .isCameraCompatTreatmentEnabledAtBuildTime(); Loading