Loading core/java/android/window/ITaskOrganizerController.aidl +8 −2 Original line number Diff line number Diff line Loading @@ -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); } core/java/android/window/TaskOrganizer.java +13 −6 Original line number Diff line number Diff line Loading @@ -270,17 +270,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(); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java +24 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -43,6 +46,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; Loading Loading @@ -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 Loading Loading @@ -168,6 +178,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( Loading @@ -191,6 +203,8 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { mDisplayController = displayController; mDisplayInsetsController = displayInsetsController; shellInit.addInitCallback(this::onInit, this); mReverseDefaultRotationEnabled = context.getResources().getBoolean( R.bool.config_reverseDefaultRotation); } /** Loading Loading @@ -274,7 +288,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(); Loading @@ -295,7 +316,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); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java +12 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); } Loading @@ -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); Loading @@ -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(); } Loading services/core/java/com/android/server/wm/LetterboxUiController.java +4 −0 Original line number Diff line number Diff line Loading @@ -455,6 +455,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; } Loading Loading
core/java/android/window/ITaskOrganizerController.aidl +8 −2 Original line number Diff line number Diff line Loading @@ -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); }
core/java/android/window/TaskOrganizer.java +13 −6 Original line number Diff line number Diff line Loading @@ -270,17 +270,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(); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java +24 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -43,6 +46,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; Loading Loading @@ -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 Loading Loading @@ -168,6 +178,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( Loading @@ -191,6 +203,8 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { mDisplayController = displayController; mDisplayInsetsController = displayInsetsController; shellInit.addInitCallback(this::onInit, this); mReverseDefaultRotationEnabled = context.getResources().getBoolean( R.bool.config_reverseDefaultRotation); } /** Loading Loading @@ -274,7 +288,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(); Loading @@ -295,7 +316,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); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java +12 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); } Loading @@ -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); Loading @@ -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(); } Loading
services/core/java/com/android/server/wm/LetterboxUiController.java +4 −0 Original line number Diff line number Diff line Loading @@ -455,6 +455,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; } Loading