Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +99 −33 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; import java.lang.ref.WeakReference; import java.util.ArrayList; Loading Loading @@ -74,8 +75,22 @@ public class CompatUIController implements OnDisplaysChangedListener, private final SparseArray<PerDisplayOnInsetsChangedListener> mOnInsetsChangedListeners = new SparseArray<>(0); /** The showing UIs by task id. */ private final SparseArray<CompatUIWindowManager> mActiveLayouts = new SparseArray<>(0); /** * The active Compat Control UI layouts by task id. * * <p>An active layout is a layout that is eligible to be shown for the associated task but * isn't necessarily shown at a given time. */ private final SparseArray<CompatUIWindowManager> mActiveCompatLayouts = new SparseArray<>(0); /** * The active Letterbox Education layout if there is one (there can be at most one active). * * <p>An active layout is a layout that is eligible to be shown for the associated task but * isn't necessarily shown at a given time. */ @Nullable private LetterboxEduWindowManager mActiveLetterboxEduLayout; /** Avoid creating display context frequently for non-default display. */ private final SparseArray<WeakReference<Context>> mDisplayContextCache = new SparseArray<>(0); Loading Loading @@ -135,14 +150,12 @@ public class CompatUIController implements OnDisplaysChangedListener, @Nullable ShellTaskOrganizer.TaskListener taskListener) { if (taskInfo.configuration == null || taskListener == null) { // Null token means the current foreground activity is not in compatibility mode. removeLayout(taskInfo.taskId); } else if (mActiveLayouts.contains(taskInfo.taskId)) { // UI already exists, update the UI layout. updateLayout(taskInfo, taskListener); } else { // Create a new compat UI. createLayout(taskInfo, taskListener); removeLayouts(taskInfo.taskId); return; } createOrUpdateCompatLayout(taskInfo, taskListener); createOrUpdateLetterboxEduLayout(taskInfo, taskListener); } @Override Loading @@ -159,7 +172,7 @@ public class CompatUIController implements OnDisplaysChangedListener, final List<Integer> toRemoveTaskIds = new ArrayList<>(); forAllLayoutsOnDisplay(displayId, layout -> toRemoveTaskIds.add(layout.getTaskId())); for (int i = toRemoveTaskIds.size() - 1; i >= 0; i--) { removeLayout(toRemoveTaskIds.get(i)); removeLayouts(toRemoveTaskIds.get(i)); } } Loading Loading @@ -218,26 +231,39 @@ public class CompatUIController implements OnDisplaysChangedListener, return mDisplaysWithIme.contains(displayId); } private void createLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { private void createOrUpdateCompatLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { CompatUIWindowManager layout = mActiveCompatLayouts.get(taskInfo.taskId); if (layout != null) { // UI already exists, update the UI layout. if (!layout.updateCompatInfo(taskInfo, taskListener, showOnDisplay(layout.getDisplayId()))) { // The layout is no longer eligible to be shown, remove from active layouts. mActiveCompatLayouts.remove(taskInfo.taskId); } return; } // Create a new UI layout. final Context context = getOrCreateDisplayContext(taskInfo.displayId); if (context == null) { Log.e(TAG, "Cannot get context for display " + taskInfo.displayId); return; } final CompatUIWindowManager compatUIWindowManager = createLayout(context, taskInfo, taskListener); mActiveLayouts.put(taskInfo.taskId, compatUIWindowManager); compatUIWindowManager.createLayout(showOnDisplay(taskInfo.displayId), taskInfo); layout = createCompatUiWindowManager(context, taskInfo, taskListener); if (layout.createLayout(showOnDisplay(taskInfo.displayId))) { // The new layout is eligible to be shown, add it the active layouts. mActiveCompatLayouts.put(taskInfo.taskId, layout); } } @VisibleForTesting CompatUIWindowManager createLayout(Context context, TaskInfo taskInfo, CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { final CompatUIWindowManager compatUIWindowManager = new CompatUIWindowManager(context, taskInfo.configuration, mSyncQueue, mCallback, taskInfo.taskId, taskListener, taskInfo, mSyncQueue, mCallback, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), mHasShownSizeCompatHint, mHasShownCameraCompatHint); // TODO(b/218304113): updates values only if hints are actually shown to the user. // Only show hints for the first time. if (taskInfo.topActivityInSizeCompat) { mHasShownSizeCompatHint = true; Loading @@ -248,19 +274,53 @@ public class CompatUIController implements OnDisplaysChangedListener, return compatUIWindowManager; } private void updateLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { final CompatUIWindowManager layout = mActiveLayouts.get(taskInfo.taskId); if (layout == null) { private void createOrUpdateLetterboxEduLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { if (mActiveLetterboxEduLayout != null && mActiveLetterboxEduLayout.getTaskId() == taskInfo.taskId) { // UI already exists, update the UI layout. if (!mActiveLetterboxEduLayout.updateCompatInfo(taskInfo, taskListener, showOnDisplay(mActiveLetterboxEduLayout.getDisplayId()))) { // The layout is no longer eligible to be shown, clear active layout. mActiveLetterboxEduLayout = null; } return; } // Create a new UI layout. final Context context = getOrCreateDisplayContext(taskInfo.displayId); if (context == null) { return; } layout.updateCompatInfo(taskInfo, taskListener, showOnDisplay(layout.getDisplayId())); LetterboxEduWindowManager newLayout = new LetterboxEduWindowManager(context, taskInfo, mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), this::onLetterboxEduDismissed); if (newLayout.createLayout(showOnDisplay(taskInfo.displayId))) { // The new layout is eligible to be shown, make it the active layout. if (mActiveLetterboxEduLayout != null) { // Release the previous layout since at most one can be active. // Since letterbox education is only shown once to the user, releasing the previous // layout is only a precaution. mActiveLetterboxEduLayout.release(); } mActiveLetterboxEduLayout = newLayout; } } private void onLetterboxEduDismissed() { mActiveLetterboxEduLayout = null; } private void removeLayout(int taskId) { final CompatUIWindowManager layout = mActiveLayouts.get(taskId); private void removeLayouts(int taskId) { final CompatUIWindowManager layout = mActiveCompatLayouts.get(taskId); if (layout != null) { layout.release(); mActiveLayouts.remove(taskId); mActiveCompatLayouts.remove(taskId); } if (mActiveLetterboxEduLayout != null && mActiveLetterboxEduLayout.getTaskId() == taskId) { mActiveLetterboxEduLayout.release(); mActiveLetterboxEduLayout = null; } } Loading @@ -278,28 +338,34 @@ public class CompatUIController implements OnDisplaysChangedListener, if (display != null) { context = mContext.createDisplayContext(display); mDisplayContextCache.put(displayId, new WeakReference<>(context)); } else { Log.e(TAG, "Cannot get context for display " + displayId); } } return context; } private void forAllLayoutsOnDisplay(int displayId, Consumer<CompatUIWindowManager> callback) { private void forAllLayoutsOnDisplay(int displayId, Consumer<CompatUIWindowManagerAbstract> callback) { forAllLayouts(layout -> layout.getDisplayId() == displayId, callback); } private void forAllLayouts(Consumer<CompatUIWindowManager> callback) { private void forAllLayouts(Consumer<CompatUIWindowManagerAbstract> callback) { forAllLayouts(layout -> true, callback); } private void forAllLayouts(Predicate<CompatUIWindowManager> condition, Consumer<CompatUIWindowManager> callback) { for (int i = 0; i < mActiveLayouts.size(); i++) { final int taskId = mActiveLayouts.keyAt(i); final CompatUIWindowManager layout = mActiveLayouts.get(taskId); private void forAllLayouts(Predicate<CompatUIWindowManagerAbstract> condition, Consumer<CompatUIWindowManagerAbstract> callback) { for (int i = 0; i < mActiveCompatLayouts.size(); i++) { final int taskId = mActiveCompatLayouts.keyAt(i); final CompatUIWindowManager layout = mActiveCompatLayouts.get(taskId); if (layout != null && condition.test(layout)) { callback.accept(layout); } } if (mActiveLetterboxEduLayout != null && condition.test(mActiveLetterboxEduLayout)) { callback.accept(mActiveLetterboxEduLayout); } } /** Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +20 −23 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import android.annotation.Nullable; import android.app.TaskInfo; import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; import android.util.Log; import android.view.LayoutInflater; Loading @@ -36,6 +35,8 @@ import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.CompatUIController.CompatUICallback; import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; /** * Window manager for the Size Compat restart button and Camera Compat control. Loading @@ -43,18 +44,19 @@ import com.android.wm.shell.common.SyncTransactionQueue; class CompatUIWindowManager extends CompatUIWindowManagerAbstract { /** * The Compat UI should be the topmost child of the Task in case there can be more than one * child. * The Compat UI should be below the Letterbox Education. */ private static final int Z_ORDER = Integer.MAX_VALUE; private static final int Z_ORDER = LetterboxEduWindowManager.Z_ORDER - 1; private final CompatUIController.CompatUICallback mCallback; private final CompatUICallback mCallback; // Remember the last reported states in case visibility changes due to keyguard or IME updates. @VisibleForTesting boolean mHasSizeCompat; @VisibleForTesting @CameraCompatControlState private int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; @VisibleForTesting boolean mShouldShowSizeCompatHint; Loading @@ -65,12 +67,14 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { @VisibleForTesting CompatUILayout mLayout; CompatUIWindowManager(Context context, Configuration taskConfig, SyncTransactionQueue syncQueue, CompatUIController.CompatUICallback callback, int taskId, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, CompatUIWindowManager(Context context, TaskInfo taskInfo, SyncTransactionQueue syncQueue, CompatUICallback callback, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, boolean hasShownSizeCompatHint, boolean hasShownCameraCompatHint) { super(context, taskConfig, syncQueue, taskId, taskListener, displayLayout); super(context, taskInfo, syncQueue, taskListener, displayLayout); mCallback = callback; mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; mShouldShowSizeCompatHint = !hasShownSizeCompatHint; mShouldShowCameraCompatHint = !hasShownCameraCompatHint; } Loading @@ -80,7 +84,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return Z_ORDER; } @Override protected @Nullable View getLayout() { return mLayout; Loading @@ -96,16 +99,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return mHasSizeCompat || shouldShowCameraControl(); } /** * Updates the internal state with respect to {@code taskInfo} and calls {@link * #createLayout(boolean)}. */ void createLayout(boolean canShow, TaskInfo taskInfo) { mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; createLayout(canShow); } @Override protected View createLayout() { mLayout = inflateLayout(); Loading @@ -127,19 +120,23 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { } @Override public void updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { final boolean prevHasSizeCompat = mHasSizeCompat; final int prevCameraCompatControlState = mCameraCompatControlState; mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; super.updateCompatInfo(taskInfo, taskListener, canShow); if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) { return false; } if (prevHasSizeCompat != mHasSizeCompat || prevCameraCompatControlState != mCameraCompatControlState) { updateVisibilityOfViews(); } return true; } /** Called when the restart button is clicked. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java +37 −20 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ import com.android.wm.shell.common.SyncTransactionQueue; * * <p>Holds view hierarchy of a root surface and helps to inflate and manage layout. */ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { protected final SyncTransactionQueue mSyncQueue; protected final int mDisplayId; Loading @@ -75,15 +75,15 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { @Nullable protected SurfaceControl mLeash; protected CompatUIWindowManagerAbstract(Context context, Configuration taskConfig, SyncTransactionQueue syncQueue, int taskId, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout) { super(taskConfig, null /* rootSurface */, null /* hostInputToken */); protected CompatUIWindowManagerAbstract(Context context, TaskInfo taskInfo, SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout) { super(taskInfo.configuration, null /* rootSurface */, null /* hostInputToken */); mContext = context; mSyncQueue = syncQueue; mTaskConfig = taskConfig; mTaskConfig = taskInfo.configuration; mDisplayId = mContext.getDisplayId(); mTaskId = taskId; mTaskId = taskInfo.taskId; mTaskListener = taskListener; mDisplayLayout = displayLayout; mStableBounds = new Rect(); Loading @@ -105,12 +105,18 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { * Inflates and inits the layout of this window manager on to the root surface if both {@code * canShow} and {@link #eligibleToShowLayout} are true. * * <p>Doesn't do anything if layout is not eligible to be shown. * * @param canShow whether the layout is allowed to be shown by the parent controller. * @return whether the layout is eligible to be shown. */ void createLayout(boolean canShow) { if (!canShow || !eligibleToShowLayout() || getLayout() != null) { // Wait until layout should be visible. return; protected boolean createLayout(boolean canShow) { if (!eligibleToShowLayout()) { return false; } if (!canShow || getLayout() != null) { // Wait until layout should be visible, or layout was already created. return true; } if (mViewHost != null) { Loading @@ -123,6 +129,8 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { mViewHost.setView(createLayout(), getWindowLayoutParams()); updateSurfacePosition(); return true; } /** Inflates and inits the layout of this window manager. */ Loading Loading @@ -174,9 +182,12 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { /** * Called when compat info changed. * * <p>The window manager is released if the layout is no longer eligible to be shown. * * @param canShow whether the layout is allowed to be shown by the parent controller. * @return whether the layout is eligible to be shown. */ void updateCompatInfo(TaskInfo taskInfo, protected boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; Loading @@ -186,12 +197,16 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { // Update configuration. setConfiguration(mTaskConfig); if (!eligibleToShowLayout()) { release(); return false; } View layout = getLayout(); if (layout == null || prevTaskListener != taskListener) { // TaskListener changed, recreate the layout for new surface parent. release(); createLayout(canShow); return; return createLayout(canShow); } boolean boundsUpdated = !mTaskConfig.windowConfiguration.getBounds().equals( Loading @@ -207,6 +222,8 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { // Update layout for RTL. layout.setLayoutDirection(mTaskConfig.getLayoutDirection()); } return true; } Loading Loading @@ -248,16 +265,16 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { mTaskListener.attachChildSurfaceToTask(mTaskId, b); } int getDisplayId() { public int getDisplayId() { return mDisplayId; } int getTaskId() { public int getTaskId() { return mTaskId; } /** Releases the surface control and tears down the view hierarchy. */ void release() { public void release() { // Hiding before releasing to avoid flickering when transitioning to the Home screen. View layout = getLayout(); if (layout != null) { Loading @@ -278,7 +295,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Re-layouts the view host and updates the surface position. */ void relayout() { public void relayout() { if (mViewHost == null) { return; } Loading Loading @@ -334,7 +351,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Gets the layout params. */ private WindowManager.LayoutParams getWindowLayoutParams() { protected WindowManager.LayoutParams getWindowLayoutParams() { View layout = getLayout(); if (layout == null) { return new WindowManager.LayoutParams(); Loading @@ -345,7 +362,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Gets the layout params given the width and height of the layout. */ private WindowManager.LayoutParams getWindowLayoutParams(int width, int height) { protected WindowManager.LayoutParams getWindowLayoutParams(int width, int height) { final WindowManager.LayoutParams winParams = new WindowManager.LayoutParams( // Cannot be wrap_content as this determines the actual window size width, height, Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java +13 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ class LetterboxEduDialogLayout extends FrameLayout { // 204 is simply 255 * 0.8. private static final int BACKGROUND_DIM_ALPHA = 204; private LetterboxEduWindowManager mWindowManager; public LetterboxEduDialogLayout(Context context) { this(context, null); } Loading @@ -52,6 +54,17 @@ class LetterboxEduDialogLayout extends FrameLayout { super(context, attrs, defStyleAttr, defStyleRes); } void inject(LetterboxEduWindowManager windowManager) { mWindowManager = windowManager; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); // Need to relayout after visibility changes since they affect size. mWindowManager.relayout(); } /** * Register a callback for the dismiss button and background dim. * Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java 0 → 100644 +150 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +99 −33 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; import java.lang.ref.WeakReference; import java.util.ArrayList; Loading Loading @@ -74,8 +75,22 @@ public class CompatUIController implements OnDisplaysChangedListener, private final SparseArray<PerDisplayOnInsetsChangedListener> mOnInsetsChangedListeners = new SparseArray<>(0); /** The showing UIs by task id. */ private final SparseArray<CompatUIWindowManager> mActiveLayouts = new SparseArray<>(0); /** * The active Compat Control UI layouts by task id. * * <p>An active layout is a layout that is eligible to be shown for the associated task but * isn't necessarily shown at a given time. */ private final SparseArray<CompatUIWindowManager> mActiveCompatLayouts = new SparseArray<>(0); /** * The active Letterbox Education layout if there is one (there can be at most one active). * * <p>An active layout is a layout that is eligible to be shown for the associated task but * isn't necessarily shown at a given time. */ @Nullable private LetterboxEduWindowManager mActiveLetterboxEduLayout; /** Avoid creating display context frequently for non-default display. */ private final SparseArray<WeakReference<Context>> mDisplayContextCache = new SparseArray<>(0); Loading Loading @@ -135,14 +150,12 @@ public class CompatUIController implements OnDisplaysChangedListener, @Nullable ShellTaskOrganizer.TaskListener taskListener) { if (taskInfo.configuration == null || taskListener == null) { // Null token means the current foreground activity is not in compatibility mode. removeLayout(taskInfo.taskId); } else if (mActiveLayouts.contains(taskInfo.taskId)) { // UI already exists, update the UI layout. updateLayout(taskInfo, taskListener); } else { // Create a new compat UI. createLayout(taskInfo, taskListener); removeLayouts(taskInfo.taskId); return; } createOrUpdateCompatLayout(taskInfo, taskListener); createOrUpdateLetterboxEduLayout(taskInfo, taskListener); } @Override Loading @@ -159,7 +172,7 @@ public class CompatUIController implements OnDisplaysChangedListener, final List<Integer> toRemoveTaskIds = new ArrayList<>(); forAllLayoutsOnDisplay(displayId, layout -> toRemoveTaskIds.add(layout.getTaskId())); for (int i = toRemoveTaskIds.size() - 1; i >= 0; i--) { removeLayout(toRemoveTaskIds.get(i)); removeLayouts(toRemoveTaskIds.get(i)); } } Loading Loading @@ -218,26 +231,39 @@ public class CompatUIController implements OnDisplaysChangedListener, return mDisplaysWithIme.contains(displayId); } private void createLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { private void createOrUpdateCompatLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { CompatUIWindowManager layout = mActiveCompatLayouts.get(taskInfo.taskId); if (layout != null) { // UI already exists, update the UI layout. if (!layout.updateCompatInfo(taskInfo, taskListener, showOnDisplay(layout.getDisplayId()))) { // The layout is no longer eligible to be shown, remove from active layouts. mActiveCompatLayouts.remove(taskInfo.taskId); } return; } // Create a new UI layout. final Context context = getOrCreateDisplayContext(taskInfo.displayId); if (context == null) { Log.e(TAG, "Cannot get context for display " + taskInfo.displayId); return; } final CompatUIWindowManager compatUIWindowManager = createLayout(context, taskInfo, taskListener); mActiveLayouts.put(taskInfo.taskId, compatUIWindowManager); compatUIWindowManager.createLayout(showOnDisplay(taskInfo.displayId), taskInfo); layout = createCompatUiWindowManager(context, taskInfo, taskListener); if (layout.createLayout(showOnDisplay(taskInfo.displayId))) { // The new layout is eligible to be shown, add it the active layouts. mActiveCompatLayouts.put(taskInfo.taskId, layout); } } @VisibleForTesting CompatUIWindowManager createLayout(Context context, TaskInfo taskInfo, CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { final CompatUIWindowManager compatUIWindowManager = new CompatUIWindowManager(context, taskInfo.configuration, mSyncQueue, mCallback, taskInfo.taskId, taskListener, taskInfo, mSyncQueue, mCallback, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), mHasShownSizeCompatHint, mHasShownCameraCompatHint); // TODO(b/218304113): updates values only if hints are actually shown to the user. // Only show hints for the first time. if (taskInfo.topActivityInSizeCompat) { mHasShownSizeCompatHint = true; Loading @@ -248,19 +274,53 @@ public class CompatUIController implements OnDisplaysChangedListener, return compatUIWindowManager; } private void updateLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { final CompatUIWindowManager layout = mActiveLayouts.get(taskInfo.taskId); if (layout == null) { private void createOrUpdateLetterboxEduLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { if (mActiveLetterboxEduLayout != null && mActiveLetterboxEduLayout.getTaskId() == taskInfo.taskId) { // UI already exists, update the UI layout. if (!mActiveLetterboxEduLayout.updateCompatInfo(taskInfo, taskListener, showOnDisplay(mActiveLetterboxEduLayout.getDisplayId()))) { // The layout is no longer eligible to be shown, clear active layout. mActiveLetterboxEduLayout = null; } return; } // Create a new UI layout. final Context context = getOrCreateDisplayContext(taskInfo.displayId); if (context == null) { return; } layout.updateCompatInfo(taskInfo, taskListener, showOnDisplay(layout.getDisplayId())); LetterboxEduWindowManager newLayout = new LetterboxEduWindowManager(context, taskInfo, mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), this::onLetterboxEduDismissed); if (newLayout.createLayout(showOnDisplay(taskInfo.displayId))) { // The new layout is eligible to be shown, make it the active layout. if (mActiveLetterboxEduLayout != null) { // Release the previous layout since at most one can be active. // Since letterbox education is only shown once to the user, releasing the previous // layout is only a precaution. mActiveLetterboxEduLayout.release(); } mActiveLetterboxEduLayout = newLayout; } } private void onLetterboxEduDismissed() { mActiveLetterboxEduLayout = null; } private void removeLayout(int taskId) { final CompatUIWindowManager layout = mActiveLayouts.get(taskId); private void removeLayouts(int taskId) { final CompatUIWindowManager layout = mActiveCompatLayouts.get(taskId); if (layout != null) { layout.release(); mActiveLayouts.remove(taskId); mActiveCompatLayouts.remove(taskId); } if (mActiveLetterboxEduLayout != null && mActiveLetterboxEduLayout.getTaskId() == taskId) { mActiveLetterboxEduLayout.release(); mActiveLetterboxEduLayout = null; } } Loading @@ -278,28 +338,34 @@ public class CompatUIController implements OnDisplaysChangedListener, if (display != null) { context = mContext.createDisplayContext(display); mDisplayContextCache.put(displayId, new WeakReference<>(context)); } else { Log.e(TAG, "Cannot get context for display " + displayId); } } return context; } private void forAllLayoutsOnDisplay(int displayId, Consumer<CompatUIWindowManager> callback) { private void forAllLayoutsOnDisplay(int displayId, Consumer<CompatUIWindowManagerAbstract> callback) { forAllLayouts(layout -> layout.getDisplayId() == displayId, callback); } private void forAllLayouts(Consumer<CompatUIWindowManager> callback) { private void forAllLayouts(Consumer<CompatUIWindowManagerAbstract> callback) { forAllLayouts(layout -> true, callback); } private void forAllLayouts(Predicate<CompatUIWindowManager> condition, Consumer<CompatUIWindowManager> callback) { for (int i = 0; i < mActiveLayouts.size(); i++) { final int taskId = mActiveLayouts.keyAt(i); final CompatUIWindowManager layout = mActiveLayouts.get(taskId); private void forAllLayouts(Predicate<CompatUIWindowManagerAbstract> condition, Consumer<CompatUIWindowManagerAbstract> callback) { for (int i = 0; i < mActiveCompatLayouts.size(); i++) { final int taskId = mActiveCompatLayouts.keyAt(i); final CompatUIWindowManager layout = mActiveCompatLayouts.get(taskId); if (layout != null && condition.test(layout)) { callback.accept(layout); } } if (mActiveLetterboxEduLayout != null && condition.test(mActiveLetterboxEduLayout)) { callback.accept(mActiveLetterboxEduLayout); } } /** Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +20 −23 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import android.annotation.Nullable; import android.app.TaskInfo; import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; import android.util.Log; import android.view.LayoutInflater; Loading @@ -36,6 +35,8 @@ import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.CompatUIController.CompatUICallback; import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; /** * Window manager for the Size Compat restart button and Camera Compat control. Loading @@ -43,18 +44,19 @@ import com.android.wm.shell.common.SyncTransactionQueue; class CompatUIWindowManager extends CompatUIWindowManagerAbstract { /** * The Compat UI should be the topmost child of the Task in case there can be more than one * child. * The Compat UI should be below the Letterbox Education. */ private static final int Z_ORDER = Integer.MAX_VALUE; private static final int Z_ORDER = LetterboxEduWindowManager.Z_ORDER - 1; private final CompatUIController.CompatUICallback mCallback; private final CompatUICallback mCallback; // Remember the last reported states in case visibility changes due to keyguard or IME updates. @VisibleForTesting boolean mHasSizeCompat; @VisibleForTesting @CameraCompatControlState private int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; @VisibleForTesting boolean mShouldShowSizeCompatHint; Loading @@ -65,12 +67,14 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { @VisibleForTesting CompatUILayout mLayout; CompatUIWindowManager(Context context, Configuration taskConfig, SyncTransactionQueue syncQueue, CompatUIController.CompatUICallback callback, int taskId, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, CompatUIWindowManager(Context context, TaskInfo taskInfo, SyncTransactionQueue syncQueue, CompatUICallback callback, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, boolean hasShownSizeCompatHint, boolean hasShownCameraCompatHint) { super(context, taskConfig, syncQueue, taskId, taskListener, displayLayout); super(context, taskInfo, syncQueue, taskListener, displayLayout); mCallback = callback; mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; mShouldShowSizeCompatHint = !hasShownSizeCompatHint; mShouldShowCameraCompatHint = !hasShownCameraCompatHint; } Loading @@ -80,7 +84,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return Z_ORDER; } @Override protected @Nullable View getLayout() { return mLayout; Loading @@ -96,16 +99,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return mHasSizeCompat || shouldShowCameraControl(); } /** * Updates the internal state with respect to {@code taskInfo} and calls {@link * #createLayout(boolean)}. */ void createLayout(boolean canShow, TaskInfo taskInfo) { mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; createLayout(canShow); } @Override protected View createLayout() { mLayout = inflateLayout(); Loading @@ -127,19 +120,23 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { } @Override public void updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { final boolean prevHasSizeCompat = mHasSizeCompat; final int prevCameraCompatControlState = mCameraCompatControlState; mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; super.updateCompatInfo(taskInfo, taskListener, canShow); if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) { return false; } if (prevHasSizeCompat != mHasSizeCompat || prevCameraCompatControlState != mCameraCompatControlState) { updateVisibilityOfViews(); } return true; } /** Called when the restart button is clicked. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java +37 −20 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ import com.android.wm.shell.common.SyncTransactionQueue; * * <p>Holds view hierarchy of a root surface and helps to inflate and manage layout. */ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { protected final SyncTransactionQueue mSyncQueue; protected final int mDisplayId; Loading @@ -75,15 +75,15 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { @Nullable protected SurfaceControl mLeash; protected CompatUIWindowManagerAbstract(Context context, Configuration taskConfig, SyncTransactionQueue syncQueue, int taskId, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout) { super(taskConfig, null /* rootSurface */, null /* hostInputToken */); protected CompatUIWindowManagerAbstract(Context context, TaskInfo taskInfo, SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout) { super(taskInfo.configuration, null /* rootSurface */, null /* hostInputToken */); mContext = context; mSyncQueue = syncQueue; mTaskConfig = taskConfig; mTaskConfig = taskInfo.configuration; mDisplayId = mContext.getDisplayId(); mTaskId = taskId; mTaskId = taskInfo.taskId; mTaskListener = taskListener; mDisplayLayout = displayLayout; mStableBounds = new Rect(); Loading @@ -105,12 +105,18 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { * Inflates and inits the layout of this window manager on to the root surface if both {@code * canShow} and {@link #eligibleToShowLayout} are true. * * <p>Doesn't do anything if layout is not eligible to be shown. * * @param canShow whether the layout is allowed to be shown by the parent controller. * @return whether the layout is eligible to be shown. */ void createLayout(boolean canShow) { if (!canShow || !eligibleToShowLayout() || getLayout() != null) { // Wait until layout should be visible. return; protected boolean createLayout(boolean canShow) { if (!eligibleToShowLayout()) { return false; } if (!canShow || getLayout() != null) { // Wait until layout should be visible, or layout was already created. return true; } if (mViewHost != null) { Loading @@ -123,6 +129,8 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { mViewHost.setView(createLayout(), getWindowLayoutParams()); updateSurfacePosition(); return true; } /** Inflates and inits the layout of this window manager. */ Loading Loading @@ -174,9 +182,12 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { /** * Called when compat info changed. * * <p>The window manager is released if the layout is no longer eligible to be shown. * * @param canShow whether the layout is allowed to be shown by the parent controller. * @return whether the layout is eligible to be shown. */ void updateCompatInfo(TaskInfo taskInfo, protected boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; Loading @@ -186,12 +197,16 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { // Update configuration. setConfiguration(mTaskConfig); if (!eligibleToShowLayout()) { release(); return false; } View layout = getLayout(); if (layout == null || prevTaskListener != taskListener) { // TaskListener changed, recreate the layout for new surface parent. release(); createLayout(canShow); return; return createLayout(canShow); } boolean boundsUpdated = !mTaskConfig.windowConfiguration.getBounds().equals( Loading @@ -207,6 +222,8 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { // Update layout for RTL. layout.setLayoutDirection(mTaskConfig.getLayoutDirection()); } return true; } Loading Loading @@ -248,16 +265,16 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { mTaskListener.attachChildSurfaceToTask(mTaskId, b); } int getDisplayId() { public int getDisplayId() { return mDisplayId; } int getTaskId() { public int getTaskId() { return mTaskId; } /** Releases the surface control and tears down the view hierarchy. */ void release() { public void release() { // Hiding before releasing to avoid flickering when transitioning to the Home screen. View layout = getLayout(); if (layout != null) { Loading @@ -278,7 +295,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Re-layouts the view host and updates the surface position. */ void relayout() { public void relayout() { if (mViewHost == null) { return; } Loading Loading @@ -334,7 +351,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Gets the layout params. */ private WindowManager.LayoutParams getWindowLayoutParams() { protected WindowManager.LayoutParams getWindowLayoutParams() { View layout = getLayout(); if (layout == null) { return new WindowManager.LayoutParams(); Loading @@ -345,7 +362,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Gets the layout params given the width and height of the layout. */ private WindowManager.LayoutParams getWindowLayoutParams(int width, int height) { protected WindowManager.LayoutParams getWindowLayoutParams(int width, int height) { final WindowManager.LayoutParams winParams = new WindowManager.LayoutParams( // Cannot be wrap_content as this determines the actual window size width, height, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java +13 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ class LetterboxEduDialogLayout extends FrameLayout { // 204 is simply 255 * 0.8. private static final int BACKGROUND_DIM_ALPHA = 204; private LetterboxEduWindowManager mWindowManager; public LetterboxEduDialogLayout(Context context) { this(context, null); } Loading @@ -52,6 +54,17 @@ class LetterboxEduDialogLayout extends FrameLayout { super(context, attrs, defStyleAttr, defStyleRes); } void inject(LetterboxEduWindowManager windowManager) { mWindowManager = windowManager; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); // Need to relayout after visibility changes since they affect size. mWindowManager.relayout(); } /** * Register a callback for the dismiss button and background dim. * Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java 0 → 100644 +150 −0 File added.Preview size limit exceeded, changes collapsed. Show changes