Loading libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +58 −34 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.CAMERA_CONTROL_STATE_UPDATE; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_APPEARED; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_CLICKED; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; Loading @@ -31,7 +34,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.app.WindowConfiguration; import android.content.LocusId; Loading @@ -57,6 +59,11 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.wm.shell.common.ScreenshotUtils; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.compatui.CompatUIController; import com.android.wm.shell.compatui.api.CompatUIHandler; import com.android.wm.shell.compatui.api.CompatUIInfo; import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonClicked; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.startingsurface.StartingWindowController; import com.android.wm.shell.sysui.ShellCommandHandler; Loading @@ -75,8 +82,7 @@ import java.util.function.Consumer; * Unified task organizer for all components in the shell. * TODO(b/167582004): may consider consolidating this class and TaskOrganizer */ public class ShellTaskOrganizer extends TaskOrganizer implements CompatUIController.CompatUICallback { public class ShellTaskOrganizer extends TaskOrganizer { private static final String TAG = "ShellTaskOrganizer"; // Intentionally using negative numbers here so the positive numbers can be used Loading Loading @@ -194,12 +200,11 @@ public class ShellTaskOrganizer extends TaskOrganizer implements * In charge of showing compat UI. Can be {@code null} if the device doesn't support size * compat or if this isn't the main {@link ShellTaskOrganizer}. * * <p>NOTE: only the main {@link ShellTaskOrganizer} should have a {@link CompatUIController}, * and register itself as a {@link CompatUIController.CompatUICallback}. Subclasses should be * initialized with a {@code null} {@link CompatUIController}. * <p>NOTE: only the main {@link ShellTaskOrganizer} should have a {@link CompatUIHandler}, * Subclasses should be initialized with a {@code null} {@link CompatUIHandler}. */ @Nullable private final CompatUIController mCompatUI; private final CompatUIHandler mCompatUI; @NonNull private final ShellCommandHandler mShellCommandHandler; Loading @@ -223,7 +228,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements public ShellTaskOrganizer(ShellInit shellInit, ShellCommandHandler shellCommandHandler, @Nullable CompatUIController compatUI, @Nullable CompatUIHandler compatUI, Optional<UnfoldAnimationController> unfoldAnimationController, Optional<RecentTasksController> recentTasks, ShellExecutor mainExecutor) { Loading @@ -235,7 +240,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements protected ShellTaskOrganizer(ShellInit shellInit, ShellCommandHandler shellCommandHandler, ITaskOrganizerController taskOrganizerController, @Nullable CompatUIController compatUI, @Nullable CompatUIHandler compatUI, Optional<UnfoldAnimationController> unfoldAnimationController, Optional<RecentTasksController> recentTasks, ShellExecutor mainExecutor) { Loading @@ -252,7 +257,21 @@ public class ShellTaskOrganizer extends TaskOrganizer implements private void onInit() { mShellCommandHandler.addDumpCallback(this::dump, this); if (mCompatUI != null) { mCompatUI.setCompatUICallback(this); mCompatUI.setCallback(compatUIEvent -> { switch(compatUIEvent.getEventId()) { case SIZE_COMPAT_RESTART_BUTTON_APPEARED: onSizeCompatRestartButtonAppeared(compatUIEvent.asType()); break; case SIZE_COMPAT_RESTART_BUTTON_CLICKED: onSizeCompatRestartButtonClicked(compatUIEvent.asType()); break; case CAMERA_CONTROL_STATE_UPDATE: onCameraControlStateUpdated(compatUIEvent.asType()); break; default: } }); } registerOrganizer(); } Loading Loading @@ -727,8 +746,26 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } } @Override public void onSizeCompatRestartButtonAppeared(int taskId) { /** Reparents a child window surface to the task surface. */ public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc, SurfaceControl.Transaction t) { final TaskListener taskListener; synchronized (mLock) { taskListener = mTasks.contains(taskId) ? getTaskListener(mTasks.get(taskId).getTaskInfo()) : null; } if (taskListener == null) { ProtoLog.w(WM_SHELL_TASK_ORG, "Failed to find Task to reparent surface taskId=%d", taskId); return; } taskListener.reparentChildSurfaceToTask(taskId, sc, t); } @VisibleForTesting void onSizeCompatRestartButtonAppeared(@NonNull SizeCompatRestartButtonAppeared compatUIEvent) { final int taskId = compatUIEvent.getTaskId(); final TaskAppearedInfo info; synchronized (mLock) { info = mTasks.get(taskId); Loading @@ -740,8 +777,9 @@ public class ShellTaskOrganizer extends TaskOrganizer implements FrameworkStatsLog.SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED__EVENT__APPEARED); } @Override public void onSizeCompatRestartButtonClicked(int taskId) { @VisibleForTesting void onSizeCompatRestartButtonClicked(@NonNull SizeCompatRestartButtonClicked compatUIEvent) { final int taskId = compatUIEvent.getTaskId(); final TaskAppearedInfo info; synchronized (mLock) { info = mTasks.get(taskId); Loading @@ -754,8 +792,10 @@ public class ShellTaskOrganizer extends TaskOrganizer implements restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token); } @Override public void onCameraControlStateUpdated(int taskId, @CameraCompatControlState int state) { @VisibleForTesting void onCameraControlStateUpdated(@NonNull CameraControlStateUpdated compatUIEvent) { final int taskId = compatUIEvent.getTaskId(); final int state = compatUIEvent.getState(); final TaskAppearedInfo info; synchronized (mLock) { info = mTasks.get(taskId); Loading @@ -766,22 +806,6 @@ public class ShellTaskOrganizer extends TaskOrganizer implements updateCameraCompatControlState(info.getTaskInfo().token, state); } /** Reparents a child window surface to the task surface. */ public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc, SurfaceControl.Transaction t) { final TaskListener taskListener; synchronized (mLock) { taskListener = mTasks.contains(taskId) ? getTaskListener(mTasks.get(taskId).getTaskInfo()) : null; } if (taskListener == null) { ProtoLog.w(WM_SHELL_TASK_ORG, "Failed to find Task to reparent surface taskId=%d", taskId); return; } taskListener.reparentChildSurfaceToTask(taskId, sc, t); } private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info, int event) { Loading Loading @@ -810,10 +834,10 @@ public class ShellTaskOrganizer extends TaskOrganizer implements // on this Task if there is any. if (taskListener == null || !taskListener.supportCompatUI() || !taskInfo.appCompatTaskInfo.hasCompatUI() || !taskInfo.isVisible) { mCompatUI.onCompatInfoChanged(taskInfo, null /* taskListener */); mCompatUI.onCompatInfoChanged(new CompatUIInfo(taskInfo, null /* taskListener */)); return; } mCompatUI.onCompatInfoChanged(taskInfo, taskListener); mCompatUI.onCompatInfoChanged(new CompatUIInfo(taskInfo, taskListener)); } private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +19 −25 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -50,6 +49,10 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.DockStateReader; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.api.CompatUIEvent; import com.android.wm.shell.compatui.api.CompatUIHandler; import com.android.wm.shell.compatui.api.CompatUIInfo; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonClicked; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; Loading @@ -71,17 +74,7 @@ import java.util.function.Predicate; * activities are in compatibility mode. */ public class CompatUIController implements OnDisplaysChangedListener, DisplayImeController.ImePositionProcessor, KeyguardChangeListener { /** Callback for compat UI interaction. */ public interface CompatUICallback { /** Called when the size compat restart button appears. */ void onSizeCompatRestartButtonAppeared(int taskId); /** Called when the size compat restart button is clicked. */ void onSizeCompatRestartButtonClicked(int taskId); /** Called when the camera compat control state is updated. */ void onCameraControlStateUpdated(int taskId, @CameraCompatControlState int state); } DisplayImeController.ImePositionProcessor, KeyguardChangeListener, CompatUIHandler { private static final String TAG = "CompatUIController"; Loading Loading @@ -170,7 +163,7 @@ public class CompatUIController implements OnDisplaysChangedListener, private final Function<Integer, Integer> mDisappearTimeSupplier; @Nullable private CompatUICallback mCompatUICallback; private Consumer<CompatUIEvent> mCallback; // Indicates if the keyguard is currently showing, in which case compat UIs shouldn't // be shown. Loading Loading @@ -230,20 +223,21 @@ public class CompatUIController implements OnDisplaysChangedListener, mCompatUIShellCommandHandler.onInit(); } /** Sets the callback for Compat UI interactions. */ public void setCompatUICallback(@NonNull CompatUICallback compatUiCallback) { mCompatUICallback = compatUiCallback; /** Sets the callback for UI interactions. */ @Override public void setCallback(@Nullable Consumer<CompatUIEvent> callback) { mCallback = callback; } /** * Called when the Task info changed. Creates and updates the compat UI if there is an * activity in size compat, or removes the UI if there is no size compat activity. * * @param taskInfo {@link TaskInfo} task the activity is in. * @param taskListener listener to handle the Task Surface placement. * @param compatUIInfo {@link CompatUIInfo} encapsulates information about the task and listener */ public void onCompatInfoChanged(@NonNull TaskInfo taskInfo, @Nullable ShellTaskOrganizer.TaskListener taskListener) { public void onCompatInfoChanged(@NonNull CompatUIInfo compatUIInfo) { final TaskInfo taskInfo = compatUIInfo.getTaskInfo(); final ShellTaskOrganizer.TaskListener taskListener = compatUIInfo.getListener(); if (taskInfo != null && !taskInfo.appCompatTaskInfo.topActivityInSizeCompat) { mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId); } Loading Loading @@ -466,7 +460,7 @@ public class CompatUIController implements OnDisplaysChangedListener, CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { return new CompatUIWindowManager(context, taskInfo, mSyncQueue, mCompatUICallback, taskListener, taskInfo, mSyncQueue, mCallback, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), mCompatUIHintsState, mCompatUIConfiguration, this::onRestartButtonClicked); } Loading @@ -478,9 +472,9 @@ public class CompatUIController implements OnDisplaysChangedListener, taskInfoState.first)) { // We need to show the dialog mSetOfTaskIdsShowingRestartDialog.add(taskInfoState.first.taskId); onCompatInfoChanged(taskInfoState.first, taskInfoState.second); onCompatInfoChanged(new CompatUIInfo(taskInfoState.first, taskInfoState.second)); } else { mCompatUICallback.onSizeCompatRestartButtonClicked(taskInfoState.first.taskId); mCallback.accept(new SizeCompatRestartButtonClicked(taskInfoState.first.taskId)); } } Loading Loading @@ -575,13 +569,13 @@ public class CompatUIController implements OnDisplaysChangedListener, private void onRestartDialogCallback( Pair<TaskInfo, ShellTaskOrganizer.TaskListener> stateInfo) { mTaskIdToRestartDialogWindowManagerMap.remove(stateInfo.first.taskId); mCompatUICallback.onSizeCompatRestartButtonClicked(stateInfo.first.taskId); mCallback.accept(new SizeCompatRestartButtonClicked(stateInfo.first.taskId)); } private void onRestartDialogDismissCallback( Pair<TaskInfo, ShellTaskOrganizer.TaskListener> stateInfo) { mSetOfTaskIdsShowingRestartDialog.remove(stateInfo.first.taskId); onCompatInfoChanged(stateInfo.first, stateInfo.second); onCompatInfoChanged(new CompatUIInfo(stateInfo.first, stateInfo.second)); } private void createOrUpdateReachabilityEduLayout(@NonNull TaskInfo taskInfo, Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +20 −10 Original line number Diff line number Diff line Loading @@ -40,8 +40,10 @@ 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.CompatUIController.CompatUIHintsState; import com.android.wm.shell.compatui.api.CompatUIEvent; import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared; import java.util.function.Consumer; Loading @@ -50,10 +52,13 @@ import java.util.function.Consumer; */ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { private final CompatUICallback mCallback; @NonNull private final Consumer<CompatUIEvent> mCallback; @NonNull private final CompatUIConfiguration mCompatUIConfiguration; @NonNull private final Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartButtonClicked; // Remember the last reported states in case visibility changes due to keyguard or IME updates. Loading @@ -65,6 +70,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; @VisibleForTesting @NonNull CompatUIHintsState mCompatUIHintsState; @Nullable Loading @@ -73,11 +79,15 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { private final float mHideScmTolerance; CompatUIWindowManager(Context context, TaskInfo taskInfo, SyncTransactionQueue syncQueue, CompatUICallback callback, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, CompatUIHintsState compatUIHintsState, CompatUIConfiguration compatUIConfiguration, Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) { CompatUIWindowManager(@NonNull Context context, @NonNull TaskInfo taskInfo, @NonNull SyncTransactionQueue syncQueue, @NonNull Consumer<CompatUIEvent> callback, @Nullable ShellTaskOrganizer.TaskListener taskListener, @Nullable DisplayLayout displayLayout, @NonNull CompatUIHintsState compatUIHintsState, @NonNull CompatUIConfiguration compatUIConfiguration, @NonNull Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) { super(context, taskInfo, syncQueue, taskListener, displayLayout); mCallback = callback; mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat; Loading Loading @@ -122,7 +132,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { updateVisibilityOfViews(); if (mHasSizeCompat) { mCallback.onSizeCompatRestartButtonAppeared(mTaskId); mCallback.accept(new SizeCompatRestartButtonAppeared(mTaskId)); } return mLayout; Loading Loading @@ -177,7 +187,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { mCameraCompatControlState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED ? CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED : CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; mCallback.onCameraControlStateUpdated(mTaskId, mCameraCompatControlState); mCallback.accept(new CameraControlStateUpdated(mTaskId, mCameraCompatControlState)); mLayout.updateCameraTreatmentButton(mCameraCompatControlState); } Loading @@ -188,7 +198,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return; } mCameraCompatControlState = CAMERA_COMPAT_CONTROL_DISMISSED; mCallback.onCameraControlStateUpdated(mTaskId, CAMERA_COMPAT_CONTROL_DISMISSED); mCallback.accept(new CameraControlStateUpdated(mTaskId, CAMERA_COMPAT_CONTROL_DISMISSED)); mLayout.setCameraControlVisibility(/* show= */ false); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIEvent.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.api /** * Abstraction for all the possible Compat UI Component events. */ interface CompatUIEvent { /** * Unique event identifier */ val eventId: Int @Suppress("UNCHECKED_CAST") fun <T : CompatUIEvent> asType(): T? = this as? T fun <T : CompatUIEvent> asType(clazz: Class<T>): T? { return if (clazz.isInstance(this)) clazz.cast(this) else null } } No newline at end of file libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIHandler.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.api import java.util.function.Consumer /** * Abstraction for the objects responsible to handle all the CompatUI components and the * communication with the server. */ interface CompatUIHandler { /** * Invoked when a new model is coming from the server. */ fun onCompatInfoChanged(compatUIInfo: CompatUIInfo) /** * Optional reference to the object responsible to send {@link CompatUIEvent} */ fun setCallback(compatUIEventSender: Consumer<CompatUIEvent>?) } No newline at end of file Loading
libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +58 −34 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.CAMERA_CONTROL_STATE_UPDATE; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_APPEARED; import static com.android.wm.shell.compatui.impl.CompatUIEventsKt.SIZE_COMPAT_RESTART_BUTTON_CLICKED; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; Loading @@ -31,7 +34,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.app.WindowConfiguration; import android.content.LocusId; Loading @@ -57,6 +59,11 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.wm.shell.common.ScreenshotUtils; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.compatui.CompatUIController; import com.android.wm.shell.compatui.api.CompatUIHandler; import com.android.wm.shell.compatui.api.CompatUIInfo; import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonClicked; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.startingsurface.StartingWindowController; import com.android.wm.shell.sysui.ShellCommandHandler; Loading @@ -75,8 +82,7 @@ import java.util.function.Consumer; * Unified task organizer for all components in the shell. * TODO(b/167582004): may consider consolidating this class and TaskOrganizer */ public class ShellTaskOrganizer extends TaskOrganizer implements CompatUIController.CompatUICallback { public class ShellTaskOrganizer extends TaskOrganizer { private static final String TAG = "ShellTaskOrganizer"; // Intentionally using negative numbers here so the positive numbers can be used Loading Loading @@ -194,12 +200,11 @@ public class ShellTaskOrganizer extends TaskOrganizer implements * In charge of showing compat UI. Can be {@code null} if the device doesn't support size * compat or if this isn't the main {@link ShellTaskOrganizer}. * * <p>NOTE: only the main {@link ShellTaskOrganizer} should have a {@link CompatUIController}, * and register itself as a {@link CompatUIController.CompatUICallback}. Subclasses should be * initialized with a {@code null} {@link CompatUIController}. * <p>NOTE: only the main {@link ShellTaskOrganizer} should have a {@link CompatUIHandler}, * Subclasses should be initialized with a {@code null} {@link CompatUIHandler}. */ @Nullable private final CompatUIController mCompatUI; private final CompatUIHandler mCompatUI; @NonNull private final ShellCommandHandler mShellCommandHandler; Loading @@ -223,7 +228,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements public ShellTaskOrganizer(ShellInit shellInit, ShellCommandHandler shellCommandHandler, @Nullable CompatUIController compatUI, @Nullable CompatUIHandler compatUI, Optional<UnfoldAnimationController> unfoldAnimationController, Optional<RecentTasksController> recentTasks, ShellExecutor mainExecutor) { Loading @@ -235,7 +240,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements protected ShellTaskOrganizer(ShellInit shellInit, ShellCommandHandler shellCommandHandler, ITaskOrganizerController taskOrganizerController, @Nullable CompatUIController compatUI, @Nullable CompatUIHandler compatUI, Optional<UnfoldAnimationController> unfoldAnimationController, Optional<RecentTasksController> recentTasks, ShellExecutor mainExecutor) { Loading @@ -252,7 +257,21 @@ public class ShellTaskOrganizer extends TaskOrganizer implements private void onInit() { mShellCommandHandler.addDumpCallback(this::dump, this); if (mCompatUI != null) { mCompatUI.setCompatUICallback(this); mCompatUI.setCallback(compatUIEvent -> { switch(compatUIEvent.getEventId()) { case SIZE_COMPAT_RESTART_BUTTON_APPEARED: onSizeCompatRestartButtonAppeared(compatUIEvent.asType()); break; case SIZE_COMPAT_RESTART_BUTTON_CLICKED: onSizeCompatRestartButtonClicked(compatUIEvent.asType()); break; case CAMERA_CONTROL_STATE_UPDATE: onCameraControlStateUpdated(compatUIEvent.asType()); break; default: } }); } registerOrganizer(); } Loading Loading @@ -727,8 +746,26 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } } @Override public void onSizeCompatRestartButtonAppeared(int taskId) { /** Reparents a child window surface to the task surface. */ public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc, SurfaceControl.Transaction t) { final TaskListener taskListener; synchronized (mLock) { taskListener = mTasks.contains(taskId) ? getTaskListener(mTasks.get(taskId).getTaskInfo()) : null; } if (taskListener == null) { ProtoLog.w(WM_SHELL_TASK_ORG, "Failed to find Task to reparent surface taskId=%d", taskId); return; } taskListener.reparentChildSurfaceToTask(taskId, sc, t); } @VisibleForTesting void onSizeCompatRestartButtonAppeared(@NonNull SizeCompatRestartButtonAppeared compatUIEvent) { final int taskId = compatUIEvent.getTaskId(); final TaskAppearedInfo info; synchronized (mLock) { info = mTasks.get(taskId); Loading @@ -740,8 +777,9 @@ public class ShellTaskOrganizer extends TaskOrganizer implements FrameworkStatsLog.SIZE_COMPAT_RESTART_BUTTON_EVENT_REPORTED__EVENT__APPEARED); } @Override public void onSizeCompatRestartButtonClicked(int taskId) { @VisibleForTesting void onSizeCompatRestartButtonClicked(@NonNull SizeCompatRestartButtonClicked compatUIEvent) { final int taskId = compatUIEvent.getTaskId(); final TaskAppearedInfo info; synchronized (mLock) { info = mTasks.get(taskId); Loading @@ -754,8 +792,10 @@ public class ShellTaskOrganizer extends TaskOrganizer implements restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token); } @Override public void onCameraControlStateUpdated(int taskId, @CameraCompatControlState int state) { @VisibleForTesting void onCameraControlStateUpdated(@NonNull CameraControlStateUpdated compatUIEvent) { final int taskId = compatUIEvent.getTaskId(); final int state = compatUIEvent.getState(); final TaskAppearedInfo info; synchronized (mLock) { info = mTasks.get(taskId); Loading @@ -766,22 +806,6 @@ public class ShellTaskOrganizer extends TaskOrganizer implements updateCameraCompatControlState(info.getTaskInfo().token, state); } /** Reparents a child window surface to the task surface. */ public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc, SurfaceControl.Transaction t) { final TaskListener taskListener; synchronized (mLock) { taskListener = mTasks.contains(taskId) ? getTaskListener(mTasks.get(taskId).getTaskInfo()) : null; } if (taskListener == null) { ProtoLog.w(WM_SHELL_TASK_ORG, "Failed to find Task to reparent surface taskId=%d", taskId); return; } taskListener.reparentChildSurfaceToTask(taskId, sc, t); } private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info, int event) { Loading Loading @@ -810,10 +834,10 @@ public class ShellTaskOrganizer extends TaskOrganizer implements // on this Task if there is any. if (taskListener == null || !taskListener.supportCompatUI() || !taskInfo.appCompatTaskInfo.hasCompatUI() || !taskInfo.isVisible) { mCompatUI.onCompatInfoChanged(taskInfo, null /* taskListener */); mCompatUI.onCompatInfoChanged(new CompatUIInfo(taskInfo, null /* taskListener */)); return; } mCompatUI.onCompatInfoChanged(taskInfo, taskListener); mCompatUI.onCompatInfoChanged(new CompatUIInfo(taskInfo, taskListener)); } private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +19 −25 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.CameraCompatTaskInfo.CameraCompatControlState; import android.app.TaskInfo; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -50,6 +49,10 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.DockStateReader; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.api.CompatUIEvent; import com.android.wm.shell.compatui.api.CompatUIHandler; import com.android.wm.shell.compatui.api.CompatUIInfo; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonClicked; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; Loading @@ -71,17 +74,7 @@ import java.util.function.Predicate; * activities are in compatibility mode. */ public class CompatUIController implements OnDisplaysChangedListener, DisplayImeController.ImePositionProcessor, KeyguardChangeListener { /** Callback for compat UI interaction. */ public interface CompatUICallback { /** Called when the size compat restart button appears. */ void onSizeCompatRestartButtonAppeared(int taskId); /** Called when the size compat restart button is clicked. */ void onSizeCompatRestartButtonClicked(int taskId); /** Called when the camera compat control state is updated. */ void onCameraControlStateUpdated(int taskId, @CameraCompatControlState int state); } DisplayImeController.ImePositionProcessor, KeyguardChangeListener, CompatUIHandler { private static final String TAG = "CompatUIController"; Loading Loading @@ -170,7 +163,7 @@ public class CompatUIController implements OnDisplaysChangedListener, private final Function<Integer, Integer> mDisappearTimeSupplier; @Nullable private CompatUICallback mCompatUICallback; private Consumer<CompatUIEvent> mCallback; // Indicates if the keyguard is currently showing, in which case compat UIs shouldn't // be shown. Loading Loading @@ -230,20 +223,21 @@ public class CompatUIController implements OnDisplaysChangedListener, mCompatUIShellCommandHandler.onInit(); } /** Sets the callback for Compat UI interactions. */ public void setCompatUICallback(@NonNull CompatUICallback compatUiCallback) { mCompatUICallback = compatUiCallback; /** Sets the callback for UI interactions. */ @Override public void setCallback(@Nullable Consumer<CompatUIEvent> callback) { mCallback = callback; } /** * Called when the Task info changed. Creates and updates the compat UI if there is an * activity in size compat, or removes the UI if there is no size compat activity. * * @param taskInfo {@link TaskInfo} task the activity is in. * @param taskListener listener to handle the Task Surface placement. * @param compatUIInfo {@link CompatUIInfo} encapsulates information about the task and listener */ public void onCompatInfoChanged(@NonNull TaskInfo taskInfo, @Nullable ShellTaskOrganizer.TaskListener taskListener) { public void onCompatInfoChanged(@NonNull CompatUIInfo compatUIInfo) { final TaskInfo taskInfo = compatUIInfo.getTaskInfo(); final ShellTaskOrganizer.TaskListener taskListener = compatUIInfo.getListener(); if (taskInfo != null && !taskInfo.appCompatTaskInfo.topActivityInSizeCompat) { mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId); } Loading Loading @@ -466,7 +460,7 @@ public class CompatUIController implements OnDisplaysChangedListener, CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { return new CompatUIWindowManager(context, taskInfo, mSyncQueue, mCompatUICallback, taskListener, taskInfo, mSyncQueue, mCallback, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), mCompatUIHintsState, mCompatUIConfiguration, this::onRestartButtonClicked); } Loading @@ -478,9 +472,9 @@ public class CompatUIController implements OnDisplaysChangedListener, taskInfoState.first)) { // We need to show the dialog mSetOfTaskIdsShowingRestartDialog.add(taskInfoState.first.taskId); onCompatInfoChanged(taskInfoState.first, taskInfoState.second); onCompatInfoChanged(new CompatUIInfo(taskInfoState.first, taskInfoState.second)); } else { mCompatUICallback.onSizeCompatRestartButtonClicked(taskInfoState.first.taskId); mCallback.accept(new SizeCompatRestartButtonClicked(taskInfoState.first.taskId)); } } Loading Loading @@ -575,13 +569,13 @@ public class CompatUIController implements OnDisplaysChangedListener, private void onRestartDialogCallback( Pair<TaskInfo, ShellTaskOrganizer.TaskListener> stateInfo) { mTaskIdToRestartDialogWindowManagerMap.remove(stateInfo.first.taskId); mCompatUICallback.onSizeCompatRestartButtonClicked(stateInfo.first.taskId); mCallback.accept(new SizeCompatRestartButtonClicked(stateInfo.first.taskId)); } private void onRestartDialogDismissCallback( Pair<TaskInfo, ShellTaskOrganizer.TaskListener> stateInfo) { mSetOfTaskIdsShowingRestartDialog.remove(stateInfo.first.taskId); onCompatInfoChanged(stateInfo.first, stateInfo.second); onCompatInfoChanged(new CompatUIInfo(stateInfo.first, stateInfo.second)); } private void createOrUpdateReachabilityEduLayout(@NonNull TaskInfo taskInfo, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +20 −10 Original line number Diff line number Diff line Loading @@ -40,8 +40,10 @@ 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.CompatUIController.CompatUIHintsState; import com.android.wm.shell.compatui.api.CompatUIEvent; import com.android.wm.shell.compatui.impl.CompatUIEvents.CameraControlStateUpdated; import com.android.wm.shell.compatui.impl.CompatUIEvents.SizeCompatRestartButtonAppeared; import java.util.function.Consumer; Loading @@ -50,10 +52,13 @@ import java.util.function.Consumer; */ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { private final CompatUICallback mCallback; @NonNull private final Consumer<CompatUIEvent> mCallback; @NonNull private final CompatUIConfiguration mCompatUIConfiguration; @NonNull private final Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartButtonClicked; // Remember the last reported states in case visibility changes due to keyguard or IME updates. Loading @@ -65,6 +70,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; @VisibleForTesting @NonNull CompatUIHintsState mCompatUIHintsState; @Nullable Loading @@ -73,11 +79,15 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { private final float mHideScmTolerance; CompatUIWindowManager(Context context, TaskInfo taskInfo, SyncTransactionQueue syncQueue, CompatUICallback callback, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, CompatUIHintsState compatUIHintsState, CompatUIConfiguration compatUIConfiguration, Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) { CompatUIWindowManager(@NonNull Context context, @NonNull TaskInfo taskInfo, @NonNull SyncTransactionQueue syncQueue, @NonNull Consumer<CompatUIEvent> callback, @Nullable ShellTaskOrganizer.TaskListener taskListener, @Nullable DisplayLayout displayLayout, @NonNull CompatUIHintsState compatUIHintsState, @NonNull CompatUIConfiguration compatUIConfiguration, @NonNull Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) { super(context, taskInfo, syncQueue, taskListener, displayLayout); mCallback = callback; mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat; Loading Loading @@ -122,7 +132,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { updateVisibilityOfViews(); if (mHasSizeCompat) { mCallback.onSizeCompatRestartButtonAppeared(mTaskId); mCallback.accept(new SizeCompatRestartButtonAppeared(mTaskId)); } return mLayout; Loading Loading @@ -177,7 +187,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { mCameraCompatControlState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED ? CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED : CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; mCallback.onCameraControlStateUpdated(mTaskId, mCameraCompatControlState); mCallback.accept(new CameraControlStateUpdated(mTaskId, mCameraCompatControlState)); mLayout.updateCameraTreatmentButton(mCameraCompatControlState); } Loading @@ -188,7 +198,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return; } mCameraCompatControlState = CAMERA_COMPAT_CONTROL_DISMISSED; mCallback.onCameraControlStateUpdated(mTaskId, CAMERA_COMPAT_CONTROL_DISMISSED); mCallback.accept(new CameraControlStateUpdated(mTaskId, CAMERA_COMPAT_CONTROL_DISMISSED)); mLayout.setCameraControlVisibility(/* show= */ false); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIEvent.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.api /** * Abstraction for all the possible Compat UI Component events. */ interface CompatUIEvent { /** * Unique event identifier */ val eventId: Int @Suppress("UNCHECKED_CAST") fun <T : CompatUIEvent> asType(): T? = this as? T fun <T : CompatUIEvent> asType(clazz: Class<T>): T? { return if (clazz.isInstance(this)) clazz.cast(this) else null } } No newline at end of file
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIHandler.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.api import java.util.function.Consumer /** * Abstraction for the objects responsible to handle all the CompatUI components and the * communication with the server. */ interface CompatUIHandler { /** * Invoked when a new model is coming from the server. */ fun onCompatInfoChanged(compatUIInfo: CompatUIInfo) /** * Optional reference to the object responsible to send {@link CompatUIEvent} */ fun setCallback(compatUIEventSender: Consumer<CompatUIEvent>?) } No newline at end of file