Merge "Per-app compat treatment for setRequestedOrientation loops." into tm-qpr-dev am: 300cd48c7a am: ead0f1a138
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20838889 Change-Id: I00c50dfe4b723e55eea6374dfbbadf56533ef18c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -1065,6 +1065,19 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface SizeChangesSupportMode {}
|
||||
|
||||
/**
|
||||
* This change id enables compat policy that ignores app requested orientation in
|
||||
* response to an app calling {@link android.app.Activity#setRequestedOrientation}. See
|
||||
* com.android.server.wm.LetterboxUiController#shouldIgnoreRequestedOrientation for
|
||||
* details.
|
||||
* @hide
|
||||
*/
|
||||
@ChangeId
|
||||
@Overridable
|
||||
@Disabled
|
||||
public static final long OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION =
|
||||
254631730L; // buganizer id
|
||||
|
||||
/**
|
||||
* This change id forces the packages it is applied to never have Display API sandboxing
|
||||
* applied for a letterbox or SCM activity. The Display APIs will continue to provide
|
||||
|
||||
@@ -813,6 +813,45 @@ public interface WindowManager extends ViewManager {
|
||||
int SCREENSHOT_VENDOR_GESTURE = 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activity level {@link android.content.pm.PackageManager.Property PackageManager
|
||||
* .Property} for an app to inform the system that the activity can be opted-in or opted-out
|
||||
* from the compatibility treatment that avoids {@link
|
||||
* android.app.Activity#setRequestedOrientation} loops. The loop can be trigerred by
|
||||
* ignoreRequestedOrientation display setting enabled on the device or by the landscape natural
|
||||
* orientation of the device.
|
||||
*
|
||||
* <p>The treatment is disabled by default but device manufacturers can enable the treatment
|
||||
* using their discretion to improve display compatibility.
|
||||
*
|
||||
* <p>With this property set to {@code true}, the system could ignore {@link
|
||||
* android.app.Activity#setRequestedOrientation} call from an app if one of the following
|
||||
* conditions are true:
|
||||
* <ul>
|
||||
* <li>Activity is relaunching due to the previous {@link
|
||||
* android.app.Activity#setRequestedOrientation} call.
|
||||
* <li>Camera compatibility force rotation treatment is active for the package.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Setting this property to {@code false} informs the system that the activity must be
|
||||
* opted-out from the compatibility treatment even if the device manufacturer has opted the app
|
||||
* into the treatment.
|
||||
*
|
||||
* <p><b>Syntax:</b>
|
||||
* <pre>
|
||||
* <activity>
|
||||
* <property
|
||||
* android:name="android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION"
|
||||
* android:value="true|false"/>
|
||||
* </activity>
|
||||
* </pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
// TODO(b/263984287): Make this public API.
|
||||
String PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION =
|
||||
"android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION";
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -5360,6 +5360,11 @@
|
||||
If given value is outside of this range, the option 0 (top) is assummed. -->
|
||||
<integer name="config_letterboxDefaultPositionForTabletopModeReachability">0</integer>
|
||||
|
||||
<!-- Whether should ignore app requested orientation in response to an app
|
||||
calling Activity#setRequestedOrientation. See
|
||||
LetterboxUiController#shouldIgnoreRequestedOrientation for details. -->
|
||||
<bool name="config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled">false</bool>
|
||||
|
||||
<!-- Whether displaying letterbox education is enabled for letterboxed fullscreen apps. -->
|
||||
<bool name="config_letterboxIsEducationEnabled">false</bool>
|
||||
|
||||
|
||||
@@ -4430,6 +4430,7 @@
|
||||
<java-symbol type="integer" name="config_letterboxDefaultPositionForVerticalReachability" />
|
||||
<java-symbol type="integer" name="config_letterboxDefaultPositionForBookModeReachability" />
|
||||
<java-symbol type="integer" name="config_letterboxDefaultPositionForTabletopModeReachability" />
|
||||
<java-symbol type="bool" name="config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled" />
|
||||
<java-symbol type="bool" name="config_letterboxIsEducationEnabled" />
|
||||
<java-symbol type="dimen" name="config_letterboxDefaultMinAspectRatioForUnresizableApps" />
|
||||
<java-symbol type="bool" name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled" />
|
||||
|
||||
@@ -1451,8 +1451,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
updatePictureInPictureMode(null, false);
|
||||
} else {
|
||||
mLastReportedMultiWindowMode = inMultiWindowMode;
|
||||
ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS,
|
||||
false /* ignoreVisibility */);
|
||||
ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3981,6 +3980,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
void finishRelaunching() {
|
||||
mLetterboxUiController.setRelauchingAfterRequestedOrientationChanged(false);
|
||||
mTaskSupervisor.getActivityMetricsLogger().notifyActivityRelaunched(this);
|
||||
|
||||
if (mPendingRelaunchCount > 0) {
|
||||
@@ -7724,13 +7724,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
void setRequestedOrientation(int requestedOrientation) {
|
||||
if (mLetterboxUiController.shouldIgnoreRequestedOrientation(requestedOrientation)) {
|
||||
return;
|
||||
}
|
||||
setOrientation(requestedOrientation, this);
|
||||
|
||||
// Push the new configuration to the requested app in case where it's not pushed, e.g. when
|
||||
// the request is handled at task level with letterbox.
|
||||
if (!getMergedOverrideConfiguration().equals(
|
||||
mLastReportedConfiguration.getMergedConfiguration())) {
|
||||
ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
|
||||
ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */,
|
||||
false /* ignoreVisibility */, true /* isRequestedOrientationChanged */);
|
||||
}
|
||||
|
||||
mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
|
||||
@@ -9060,7 +9064,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
|
||||
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
|
||||
return ensureActivityConfiguration(globalChanges, preserveWindow,
|
||||
false /* ignoreVisibility */);
|
||||
false /* ignoreVisibility */, false /* isRequestedOrientationChanged */);
|
||||
}
|
||||
|
||||
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
|
||||
boolean ignoreVisibility) {
|
||||
return ensureActivityConfiguration(globalChanges, preserveWindow, ignoreVisibility,
|
||||
false /* isRequestedOrientationChanged */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9074,11 +9084,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
* (stopped state). This is useful for the case where we know the
|
||||
* activity will be visible soon and we want to ensure its configuration
|
||||
* before we make it visible.
|
||||
* @param isRequestedOrientationChanged whether this is triggered in response to an app calling
|
||||
* {@link android.app.Activity#setRequestedOrientation}.
|
||||
* @return False if the activity was relaunched and true if it wasn't relaunched because we
|
||||
* can't or the app handles the specific configuration that is changing.
|
||||
*/
|
||||
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
|
||||
boolean ignoreVisibility) {
|
||||
boolean ignoreVisibility, boolean isRequestedOrientationChanged) {
|
||||
final Task rootTask = getRootTask();
|
||||
if (rootTask.mConfigWillChange) {
|
||||
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Skipping config check "
|
||||
@@ -9202,6 +9214,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
} else {
|
||||
mRelaunchReason = RELAUNCH_REASON_NONE;
|
||||
}
|
||||
if (isRequestedOrientationChanged) {
|
||||
mLetterboxUiController.setRelauchingAfterRequestedOrientationChanged(true);
|
||||
}
|
||||
if (mState == PAUSING) {
|
||||
// A little annoying: we are waiting for this activity to finish pausing. Let's not
|
||||
// do anything now, but just flag that it needs to be restarted when done pausing.
|
||||
|
||||
@@ -287,7 +287,7 @@ final class DisplayRotationCompatPolicy {
|
||||
* <li>The activity has fixed orientation but not "locked" or "nosensor" one.
|
||||
* </ul>
|
||||
*/
|
||||
private boolean isTreatmentEnabledForActivity(@Nullable ActivityRecord activity) {
|
||||
boolean isTreatmentEnabledForActivity(@Nullable ActivityRecord activity) {
|
||||
return activity != null && !activity.inMultiWindowMode()
|
||||
&& activity.getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED
|
||||
// "locked" and "nosensor" values are often used by camera apps that can't
|
||||
|
||||
@@ -222,6 +222,11 @@ final class LetterboxConfiguration {
|
||||
// See RefreshCallbackItem for context.
|
||||
private boolean mIsCameraCompatRefreshCycleThroughStopEnabled = true;
|
||||
|
||||
// Whether should ignore app requested orientation in response to an app
|
||||
// calling Activity#setRequestedOrientation. See
|
||||
// LetterboxUiController#shouldIgnoreRequestedOrientation for details.
|
||||
private final boolean mIsPolicyForIgnoringRequestedOrientationEnabled;
|
||||
|
||||
LetterboxConfiguration(Context systemUiContext) {
|
||||
this(systemUiContext, new LetterboxConfigurationPersister(systemUiContext,
|
||||
() -> readLetterboxHorizontalReachabilityPositionFromConfig(systemUiContext,
|
||||
@@ -274,10 +279,13 @@ final class LetterboxConfiguration {
|
||||
R.bool.config_letterboxIsEnabledForTranslucentActivities);
|
||||
mIsCameraCompatTreatmentEnabled = mContext.getResources().getBoolean(
|
||||
R.bool.config_isWindowManagerCameraCompatTreatmentEnabled);
|
||||
mIsCompatFakeFocusEnabled = mContext.getResources().getBoolean(
|
||||
R.bool.config_isCompatFakeFocusEnabled);
|
||||
mIsPolicyForIgnoringRequestedOrientationEnabled = mContext.getResources().getBoolean(
|
||||
R.bool.config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled);
|
||||
|
||||
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
|
||||
mLetterboxConfigurationPersister.start();
|
||||
mIsCompatFakeFocusEnabled = mContext.getResources()
|
||||
.getBoolean(R.bool.config_isCompatFakeFocusEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1034,6 +1042,15 @@ final class LetterboxConfiguration {
|
||||
mIsCompatFakeFocusEnabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether should ignore app requested orientation in response to an app calling
|
||||
* {@link android.app.Activity#setRequestedOrientation}. See {@link
|
||||
* LetterboxUiController#shouldIgnoreRequestedOrientation} for details.
|
||||
*/
|
||||
boolean isPolicyForIgnoringRequestedOrientationEnabled() {
|
||||
return mIsPolicyForIgnoringRequestedOrientationEnabled;
|
||||
}
|
||||
|
||||
/** Whether camera compatibility treatment is enabled. */
|
||||
boolean isCameraCompatTreatmentEnabled(boolean checkDeviceConfig) {
|
||||
return mIsCameraCompatTreatmentEnabled
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.content.pm.ActivityInfo.screenOrientationToString;
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
|
||||
import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
|
||||
|
||||
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
|
||||
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
|
||||
@@ -55,6 +58,8 @@ import static com.android.server.wm.LetterboxConfiguration.letterboxBackgroundTy
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager.TaskDescription;
|
||||
import android.content.pm.ActivityInfo.ScreenOrientation;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
@@ -74,6 +79,7 @@ import com.android.internal.statusbar.LetterboxDetails;
|
||||
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
/** Controls behaviour of the letterbox UI for {@link mActivityRecord}. */
|
||||
// TODO(b/185262487): Improve test coverage of this class. Parts of it are tested in
|
||||
@@ -131,12 +137,37 @@ final class LetterboxUiController {
|
||||
// DisplayRotationCompatPolicy.
|
||||
private boolean mIsRefreshAfterRotationRequested;
|
||||
|
||||
@Nullable
|
||||
private final Boolean mBooleanPropertyIgnoreRequestedOrientation;
|
||||
|
||||
private boolean mIsRelauchingAfterRequestedOrientationChanged;
|
||||
|
||||
LetterboxUiController(WindowManagerService wmService, ActivityRecord activityRecord) {
|
||||
mLetterboxConfiguration = wmService.mLetterboxConfiguration;
|
||||
// Given activityRecord may not be fully constructed since LetterboxUiController
|
||||
// is created in its constructor. It shouldn't be used in this constructor but it's safe
|
||||
// to use it after since controller is only used in ActivityRecord.
|
||||
mActivityRecord = activityRecord;
|
||||
|
||||
PackageManager packageManager = wmService.mContext.getPackageManager();
|
||||
mBooleanPropertyIgnoreRequestedOrientation =
|
||||
readComponentProperty(packageManager, mActivityRecord.packageName,
|
||||
mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled,
|
||||
PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Boolean readComponentProperty(PackageManager packageManager, String packageName,
|
||||
BooleanSupplier gatingCondition, String propertyName) {
|
||||
if (!gatingCondition.getAsBoolean()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return packageManager.getProperty(propertyName, packageName).getBoolean();
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// No such property name.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Cleans up {@link Letterbox} if it exists.*/
|
||||
@@ -153,6 +184,72 @@ final class LetterboxUiController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether should ignore app requested orientation in response to an app
|
||||
* calling {@link android.app.Activity#setRequestedOrientation}.
|
||||
*
|
||||
* <p>This is needed to avoid getting into {@link android.app.Activity#setRequestedOrientation}
|
||||
* loop when {@link DisplayContent#getIgnoreOrientationRequest} is enabled or device has
|
||||
* landscape natural orientation which app developers don't expect. For example, the loop can
|
||||
* look like this:
|
||||
* <ol>
|
||||
* <li>App sets default orientation to "unspecified" at runtime
|
||||
* <li>App requests to "portrait" after checking some condition (e.g. display rotation).
|
||||
* <li>(2) leads to fullscreen -> letterboxed bounds change and activity relaunch because
|
||||
* app can't handle the corresponding config changes.
|
||||
* <li>Loop goes back to (1)
|
||||
* </ol>
|
||||
*
|
||||
* <p>This treatment is enabled when the following conditions are met:
|
||||
* <ul>
|
||||
* <li>Flag gating the treatment is enabled
|
||||
* <li>Opt-out component property isn't enabled
|
||||
* <li>Opt-in component property or per-app override are enabled
|
||||
* <li>Activity is relaunched after {@link android.app.Activity#setRequestedOrientation}
|
||||
* call from an app or camera compat force rotation treatment is active for the activity.
|
||||
* </ul>
|
||||
*/
|
||||
boolean shouldIgnoreRequestedOrientation(@ScreenOrientation int requestedOrientation) {
|
||||
if (!mLetterboxConfiguration.isPolicyForIgnoringRequestedOrientationEnabled()) {
|
||||
return false;
|
||||
}
|
||||
if (Boolean.FALSE.equals(mBooleanPropertyIgnoreRequestedOrientation)) {
|
||||
return false;
|
||||
}
|
||||
if (!Boolean.TRUE.equals(mBooleanPropertyIgnoreRequestedOrientation)
|
||||
&& !mActivityRecord.info.isChangeEnabled(
|
||||
OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION)) {
|
||||
return false;
|
||||
}
|
||||
if (mIsRelauchingAfterRequestedOrientationChanged) {
|
||||
Slog.w(TAG, "Ignoring orientation update to "
|
||||
+ screenOrientationToString(requestedOrientation)
|
||||
+ " due to relaunching after setRequestedOrientation for " + mActivityRecord);
|
||||
return true;
|
||||
}
|
||||
DisplayContent displayContent = mActivityRecord.mDisplayContent;
|
||||
if (displayContent == null) {
|
||||
return false;
|
||||
}
|
||||
if (displayContent.mDisplayRotationCompatPolicy != null
|
||||
&& displayContent.mDisplayRotationCompatPolicy
|
||||
.isTreatmentEnabledForActivity(mActivityRecord)) {
|
||||
Slog.w(TAG, "Ignoring orientation update to "
|
||||
+ screenOrientationToString(requestedOrientation)
|
||||
+ " due to camera compat treatment for " + mActivityRecord);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether an activity is relaunching after the app has called {@link
|
||||
* android.app.Activity#setRequestedOrientation}.
|
||||
*/
|
||||
void setRelauchingAfterRequestedOrientationChanged(boolean isRelaunching) {
|
||||
mIsRelauchingAfterRequestedOrientationChanged = isRelaunching;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether activity "refresh" was requested but not finished in {@link #activityResumedLocked}
|
||||
* following the camera compat force rotation in {@link DisplayRotationCompatPolicy}.
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
|
||||
import android.compat.testing.PlatformCompatChangeRule;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.Property;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Test class for {@link LetterboxUiControllerTest}.
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* atest WmTests:LetterboxUiControllerTest
|
||||
*/
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(WindowTestRunner.class)
|
||||
public class LetterboxUiControllerTest extends WindowTestsBase {
|
||||
|
||||
@Rule
|
||||
public TestRule compatChangeRule = new PlatformCompatChangeRule();
|
||||
|
||||
private ActivityRecord mActivity;
|
||||
private DisplayContent mDisplayContent;
|
||||
private LetterboxUiController mController;
|
||||
private LetterboxConfiguration mLetterboxConfiguration;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mActivity = setUpActivityWithComponent();
|
||||
|
||||
mLetterboxConfiguration = mWm.mLetterboxConfiguration;
|
||||
spyOn(mLetterboxConfiguration);
|
||||
|
||||
mController = new LetterboxUiController(mWm, mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION})
|
||||
public void testShouldIgnoreRequestedOrientation_activityRelaunching_returnsTrue() {
|
||||
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
|
||||
|
||||
assertTrue(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION})
|
||||
public void testShouldIgnoreRequestedOrientation_cameraCompatTreatment_returnsTrue() {
|
||||
doReturn(true).when(mLetterboxConfiguration).isCameraCompatTreatmentEnabled(anyBoolean());
|
||||
|
||||
// Recreate DisplayContent with DisplayRotationCompatPolicy
|
||||
mActivity = setUpActivityWithComponent();
|
||||
mController = new LetterboxUiController(mWm, mActivity);
|
||||
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
|
||||
mController.setRelauchingAfterRequestedOrientationChanged(false);
|
||||
|
||||
spyOn(mDisplayContent.mDisplayRotationCompatPolicy);
|
||||
doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy)
|
||||
.isTreatmentEnabledForActivity(eq(mActivity));
|
||||
|
||||
assertTrue(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldIgnoreRequestedOrientation_overrideDisabled_returnsFalse() {
|
||||
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
|
||||
|
||||
assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldIgnoreRequestedOrientation_propertyIsTrue_returnsTrue()
|
||||
throws Exception {
|
||||
doReturn(true).when(mLetterboxConfiguration)
|
||||
.isPolicyForIgnoringRequestedOrientationEnabled();
|
||||
mockThatProperty(PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION, /* value */ true);
|
||||
mController = new LetterboxUiController(mWm, mActivity);
|
||||
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
|
||||
|
||||
assertTrue(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION})
|
||||
public void testShouldIgnoreRequestedOrientation_propertyIsFalseAndOverride_returnsFalse()
|
||||
throws Exception {
|
||||
doReturn(true).when(mLetterboxConfiguration)
|
||||
.isPolicyForIgnoringRequestedOrientationEnabled();
|
||||
mockThatProperty(PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION, /* value */ false);
|
||||
|
||||
mController = new LetterboxUiController(mWm, mActivity);
|
||||
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
|
||||
|
||||
assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION})
|
||||
public void testShouldIgnoreRequestedOrientation_flagIsDisabled_returnsFalse() {
|
||||
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
|
||||
doReturn(false).when(mLetterboxConfiguration)
|
||||
.isPolicyForIgnoringRequestedOrientationEnabled();
|
||||
|
||||
assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
|
||||
}
|
||||
|
||||
private void mockThatProperty(String propertyName, boolean value) throws Exception {
|
||||
Property property = new Property(propertyName, /* value */ value, /* packageName */ "",
|
||||
/* className */ "");
|
||||
PackageManager pm = mWm.mContext.getPackageManager();
|
||||
spyOn(pm);
|
||||
doReturn(property).when(pm).getProperty(eq(propertyName), anyString());
|
||||
}
|
||||
|
||||
private void prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch() {
|
||||
doReturn(true).when(mLetterboxConfiguration)
|
||||
.isPolicyForIgnoringRequestedOrientationEnabled();
|
||||
mController.setRelauchingAfterRequestedOrientationChanged(true);
|
||||
}
|
||||
|
||||
private ActivityRecord setUpActivityWithComponent() {
|
||||
mDisplayContent = new TestDisplayContent
|
||||
.Builder(mAtm, /* dw */ 1000, /* dh */ 2000).build();
|
||||
Task task = new TaskBuilder(mSupervisor).setDisplay(mDisplayContent).build();
|
||||
final ActivityRecord activity = new ActivityBuilder(mAtm)
|
||||
.setOnTop(true)
|
||||
.setTask(task)
|
||||
// Set the component to be that of the test class in order to enable compat changes
|
||||
.setComponent(ComponentName.createRelative(mContext,
|
||||
com.android.server.wm.LetterboxUiControllerTest.class.getName()))
|
||||
.build();
|
||||
return activity;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user