Merge "Merge "Force Kids app to use LANDSCAPE when in REVERSE_LANDSCAPE" into tm-qpr-dev am: 4ad16867ee am: 2e27a9c9e7" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
81333e87d1
@@ -73,11 +73,17 @@ interface ITaskOrganizerController {
|
||||
|
||||
/**
|
||||
* Controls whether ignore orientation request logic in {@link
|
||||
* com.android.server.wm.DisplayArea} is disabled at runtime.
|
||||
* com.android.server.wm.DisplayArea} is disabled at runtime and how to optionally map some
|
||||
* requested orientations to others.
|
||||
*
|
||||
* @param isDisabled when {@code true}, the system always ignores the value of {@link
|
||||
* com.android.server.wm.DisplayArea#getIgnoreOrientationRequest} and app
|
||||
* requested orientation is respected.
|
||||
* @param fromOrientations The orientations we want to map to the correspondent orientations
|
||||
* in toOrientation.
|
||||
* @param toOrientations The orientations we map to the ones in fromOrientations at the same
|
||||
* index
|
||||
*/
|
||||
void setIsIgnoreOrientationRequestDisabled(boolean isDisabled);
|
||||
void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled,
|
||||
in int[] fromOrientations, in int[] toOrientations);
|
||||
}
|
||||
|
||||
@@ -267,17 +267,24 @@ public class TaskOrganizer extends WindowOrganizer {
|
||||
|
||||
/**
|
||||
* Controls whether ignore orientation request logic in {@link
|
||||
* com.android.server.wm.DisplayArea} is disabled at runtime.
|
||||
* com.android.server.wm.DisplayArea} is disabled at runtime and how to optionally map some
|
||||
* requested orientation to others.
|
||||
*
|
||||
* @param isDisabled when {@code true}, the system always ignores the value of {@link
|
||||
* com.android.server.wm.DisplayArea#getIgnoreOrientationRequest} and app
|
||||
* requested orientation is respected.
|
||||
* @param isIgnoreOrientationRequestDisabled when {@code true}, the system always ignores the
|
||||
* value of {@link com.android.server.wm.DisplayArea#getIgnoreOrientationRequest}
|
||||
* and app requested orientation is respected.
|
||||
* @param fromOrientations The orientations we want to map to the correspondent orientations
|
||||
* in toOrientation.
|
||||
* @param toOrientations The orientations we map to the ones in fromOrientations at the same
|
||||
* index
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
|
||||
public void setIsIgnoreOrientationRequestDisabled(boolean isDisabled) {
|
||||
public void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled,
|
||||
@Nullable int[] fromOrientations, @Nullable int[] toOrientations) {
|
||||
try {
|
||||
mTaskOrganizerController.setIsIgnoreOrientationRequestDisabled(isDisabled);
|
||||
mTaskOrganizerController.setOrientationRequestPolicy(isIgnoreOrientationRequestDisabled,
|
||||
fromOrientations, toOrientations);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
@@ -33,6 +35,7 @@ import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.view.Display;
|
||||
import android.view.InsetsSource;
|
||||
import android.view.InsetsState;
|
||||
import android.view.SurfaceControl;
|
||||
@@ -44,6 +47,7 @@ import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
@@ -80,6 +84,12 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
|
||||
private final DisplayController mDisplayController;
|
||||
private final DisplayInsetsController mDisplayInsetsController;
|
||||
|
||||
/**
|
||||
* The value of the {@link R.bool.config_reverseDefaultRotation} property which defines how
|
||||
* {@link Display#getRotation} values are mapped to screen orientations
|
||||
*/
|
||||
private final boolean mReverseDefaultRotationEnabled;
|
||||
|
||||
@VisibleForTesting
|
||||
ActivityManager.RunningTaskInfo mLaunchRootTask;
|
||||
@VisibleForTesting
|
||||
@@ -188,6 +198,8 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
|
||||
mDisplayInsetsController = displayInsetsController;
|
||||
mKidsModeSettingsObserver = kidsModeSettingsObserver;
|
||||
shellInit.addInitCallback(this::onInit, this);
|
||||
mReverseDefaultRotationEnabled = context.getResources().getBoolean(
|
||||
R.bool.config_reverseDefaultRotation);
|
||||
}
|
||||
|
||||
public KidsModeTaskOrganizer(
|
||||
@@ -211,6 +223,8 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
|
||||
mDisplayController = displayController;
|
||||
mDisplayInsetsController = displayInsetsController;
|
||||
shellInit.addInitCallback(this::onInit, this);
|
||||
mReverseDefaultRotationEnabled = context.getResources().getBoolean(
|
||||
R.bool.config_reverseDefaultRotation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,7 +308,14 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
|
||||
// Needed since many Kids apps aren't optimised to support both orientations and it will be
|
||||
// hard for kids to understand the app compat mode.
|
||||
// TODO(229961548): Remove ignoreOrientationRequest exception for Kids Mode once possible.
|
||||
setIsIgnoreOrientationRequestDisabled(true);
|
||||
if (mReverseDefaultRotationEnabled) {
|
||||
setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled */ true,
|
||||
/* fromOrientations */ new int[]{SCREEN_ORIENTATION_REVERSE_LANDSCAPE},
|
||||
/* toOrientations */ new int[]{SCREEN_ORIENTATION_LANDSCAPE});
|
||||
} else {
|
||||
setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled */ true,
|
||||
/* fromOrientations */ null, /* toOrientations */ null);
|
||||
}
|
||||
final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY);
|
||||
if (displayLayout != null) {
|
||||
mDisplayWidth = displayLayout.width();
|
||||
@@ -315,7 +336,8 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
|
||||
|
||||
@VisibleForTesting
|
||||
void disable() {
|
||||
setIsIgnoreOrientationRequestDisabled(false);
|
||||
setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled */ false,
|
||||
/* fromOrientations */ null, /* toOrientations */ null);
|
||||
mDisplayInsetsController.removeInsetsChangedListener(DEFAULT_DISPLAY,
|
||||
mOnInsetsChangedListener);
|
||||
mDisplayController.removeDisplayWindowListener(mOnDisplaysChangedListener);
|
||||
|
||||
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.verify;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -77,6 +78,7 @@ public class KidsModeTaskOrganizerTest extends ShellTestCase {
|
||||
@Mock private ShellInit mShellInit;
|
||||
@Mock private ShellCommandHandler mShellCommandHandler;
|
||||
@Mock private DisplayInsetsController mDisplayInsetsController;
|
||||
@Mock private Resources mResources;
|
||||
|
||||
KidsModeTaskOrganizer mOrganizer;
|
||||
|
||||
@@ -89,10 +91,12 @@ public class KidsModeTaskOrganizerTest extends ShellTestCase {
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
// NOTE: KidsModeTaskOrganizer should have a null CompatUIController.
|
||||
mOrganizer = spy(new KidsModeTaskOrganizer(mContext, mShellInit, mShellCommandHandler,
|
||||
mTaskOrganizerController, mSyncTransactionQueue, mDisplayController,
|
||||
mDisplayInsetsController, Optional.empty(), Optional.empty(), mObserver,
|
||||
mTestExecutor, mHandler));
|
||||
doReturn(mResources).when(mContext).getResources();
|
||||
final KidsModeTaskOrganizer kidsModeTaskOrganizer = new KidsModeTaskOrganizer(mContext,
|
||||
mShellInit, mShellCommandHandler, mTaskOrganizerController, mSyncTransactionQueue,
|
||||
mDisplayController, mDisplayInsetsController, Optional.empty(), Optional.empty(),
|
||||
mObserver, mTestExecutor, mHandler);
|
||||
mOrganizer = spy(kidsModeTaskOrganizer);
|
||||
doReturn(mTransaction).when(mOrganizer).getWindowContainerTransaction();
|
||||
doReturn(new InsetsState()).when(mDisplayController).getInsetsState(DEFAULT_DISPLAY);
|
||||
}
|
||||
@@ -112,6 +116,8 @@ public class KidsModeTaskOrganizerTest extends ShellTestCase {
|
||||
verify(mOrganizer, times(1)).registerOrganizer();
|
||||
verify(mOrganizer, times(1)).createRootTask(
|
||||
eq(DEFAULT_DISPLAY), eq(WINDOWING_MODE_FULLSCREEN), eq(mOrganizer.mCookie));
|
||||
verify(mOrganizer, times(1))
|
||||
.setOrientationRequestPolicy(eq(true), any(), any());
|
||||
|
||||
final ActivityManager.RunningTaskInfo rootTask = createTaskInfo(12,
|
||||
WINDOWING_MODE_FULLSCREEN, mOrganizer.mCookie);
|
||||
@@ -132,10 +138,11 @@ public class KidsModeTaskOrganizerTest extends ShellTestCase {
|
||||
doReturn(false).when(mObserver).isEnabled();
|
||||
mOrganizer.updateKidsModeState();
|
||||
|
||||
|
||||
verify(mOrganizer, times(1)).disable();
|
||||
verify(mOrganizer, times(1)).unregisterOrganizer();
|
||||
verify(mOrganizer, times(1)).deleteRootTask(rootTask.token);
|
||||
verify(mOrganizer, times(1))
|
||||
.setOrientationRequestPolicy(eq(false), any(), any());
|
||||
assertThat(mOrganizer.mLaunchRootLeash).isNull();
|
||||
assertThat(mOrganizer.mLaunchRootTask).isNull();
|
||||
}
|
||||
|
||||
@@ -447,6 +447,10 @@ final class LetterboxUiController {
|
||||
|
||||
@ScreenOrientation
|
||||
int overrideOrientationIfNeeded(@ScreenOrientation int candidate) {
|
||||
// In some cases (e.g. Kids app) we need to map the candidate orientation to some other
|
||||
// orientation.
|
||||
candidate = mActivityRecord.mWmService.mapOrientationRequest(candidate);
|
||||
|
||||
if (FALSE.equals(mBooleanPropertyAllowOrientationOverride)) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
@@ -1166,12 +1166,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsIgnoreOrientationRequestDisabled(boolean isDisabled) {
|
||||
enforceTaskPermission("setIsIgnoreOrientationRequestDisabled()");
|
||||
public void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled,
|
||||
@Nullable int[] fromOrientations, @Nullable int[] toOrientations) {
|
||||
enforceTaskPermission("setOrientationRequestPolicy()");
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
mService.mWindowManager.setIsIgnoreOrientationRequestDisabled(isDisabled);
|
||||
mService.mWindowManager
|
||||
.setOrientationRequestPolicy(isIgnoreOrientationRequestDisabled,
|
||||
fromOrientations, toOrientations);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
|
||||
@@ -237,6 +237,7 @@ import android.util.MergedConfiguration;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -594,6 +595,13 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
/** List of window currently causing non-system overlay windows to be hidden. */
|
||||
private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* In some cases (e.g. when {@link R.bool.config_reverseDefaultRotation} has value
|
||||
* {@value true}) we need to map some orientation to others. This {@link SparseIntArray}
|
||||
* contains the relation between the source orientation and the one to use.
|
||||
*/
|
||||
private final SparseIntArray mOrientationMapping = new SparseIntArray();
|
||||
|
||||
final AccessibilityController mAccessibilityController;
|
||||
private RecentsAnimationController mRecentsAnimationController;
|
||||
|
||||
@@ -4111,24 +4119,51 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
/**
|
||||
* Controls whether ignore orientation request logic in {@link DisplayArea} is disabled
|
||||
* at runtime.
|
||||
* at runtime and how to optionally map some requested orientations to others.
|
||||
*
|
||||
* <p>Note: this assumes that {@link #mGlobalLock} is held by the caller.
|
||||
*
|
||||
* @param isDisabled when {@code true}, the system always ignores the value of {@link
|
||||
* DisplayArea#getIgnoreOrientationRequest} and app requested orientation is
|
||||
* respected.
|
||||
* @param isIgnoreOrientationRequestDisabled when {@code true}, the system always ignores the
|
||||
* value of {@link DisplayArea#getIgnoreOrientationRequest} and app requested
|
||||
* orientation is respected.
|
||||
* @param fromOrientations The orientations we want to map to the correspondent orientations
|
||||
* in toOrientation.
|
||||
* @param toOrientations The orientations we map to the ones in fromOrientations at the same
|
||||
* index
|
||||
*/
|
||||
void setIsIgnoreOrientationRequestDisabled(boolean isDisabled) {
|
||||
if (isDisabled == mIsIgnoreOrientationRequestDisabled) {
|
||||
void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled,
|
||||
@Nullable int[] fromOrientations, @Nullable int[] toOrientations) {
|
||||
mOrientationMapping.clear();
|
||||
if (fromOrientations != null && toOrientations != null
|
||||
&& fromOrientations.length == toOrientations.length) {
|
||||
for (int i = 0; i < fromOrientations.length; i++) {
|
||||
mOrientationMapping.put(fromOrientations[i], toOrientations[i]);
|
||||
}
|
||||
}
|
||||
if (isIgnoreOrientationRequestDisabled == mIsIgnoreOrientationRequestDisabled) {
|
||||
return;
|
||||
}
|
||||
mIsIgnoreOrientationRequestDisabled = isDisabled;
|
||||
mIsIgnoreOrientationRequestDisabled = isIgnoreOrientationRequestDisabled;
|
||||
for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {
|
||||
mRoot.getChildAt(i).onIsIgnoreOrientationRequestDisabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link mIsIgnoreOrientationRequestDisabled} is {@value true} this method returns the
|
||||
* orientation to use in place of the one in input. It returns the same requestedOrientation in
|
||||
* input otherwise.
|
||||
*
|
||||
* @param requestedOrientation The orientation that can be mapped.
|
||||
* @return The orientation to use in place of requestedOrientation.
|
||||
*/
|
||||
int mapOrientationRequest(int requestedOrientation) {
|
||||
if (!mIsIgnoreOrientationRequestDisabled) {
|
||||
return requestedOrientation;
|
||||
}
|
||||
return mOrientationMapping.get(requestedOrientation, requestedOrientation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the system ignores the value of {@link DisplayArea#getIgnoreOrientationRequest} and
|
||||
* app requested orientation is respected.
|
||||
|
||||
@@ -55,6 +55,7 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.testing.PlatformCompatChangeRule;
|
||||
@@ -525,6 +526,16 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
|
||||
|
||||
// overrideOrientationIfNeeded
|
||||
|
||||
@Test
|
||||
public void testOverrideOrientationIfNeeded_mapInvokedOnRequest() throws Exception {
|
||||
mController = new LetterboxUiController(mWm, mActivity);
|
||||
spyOn(mWm);
|
||||
|
||||
mController.overrideOrientationIfNeeded(SCREEN_ORIENTATION_PORTRAIT);
|
||||
|
||||
verify(mWm).mapOrientationRequest(SCREEN_ORIENTATION_PORTRAIT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT})
|
||||
public void testOverrideOrientationIfNeeded_portraitOverrideEnabled_returnsPortrait()
|
||||
|
||||
@@ -116,6 +116,20 @@ public class WindowManagerServiceTests extends WindowTestsBase {
|
||||
InstrumentationRegistry.getInstrumentation().getUiAutomation(),
|
||||
ADD_TRUSTED_DISPLAY);
|
||||
|
||||
@Test
|
||||
public void testIsRequestedOrientationMapped() {
|
||||
mWm.setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled*/ true,
|
||||
/* fromOrientations */ new int[]{1}, /* toOrientations */ new int[]{2});
|
||||
assertThat(mWm.mapOrientationRequest(1)).isEqualTo(2);
|
||||
assertThat(mWm.mapOrientationRequest(3)).isEqualTo(3);
|
||||
|
||||
// Mapping disabled
|
||||
mWm.setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled*/ false,
|
||||
/* fromOrientations */ null, /* toOrientations */ null);
|
||||
assertThat(mWm.mapOrientationRequest(1)).isEqualTo(1);
|
||||
assertThat(mWm.mapOrientationRequest(3)).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddWindowToken() {
|
||||
IBinder token = mock(IBinder.class);
|
||||
|
||||
Reference in New Issue
Block a user