diff options
Diffstat (limited to 'libs')
4 files changed, 199 insertions, 103 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index e3362870cdf0..cb7afc77a65b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -15,18 +15,10 @@ */ package com.android.wm.shell.startingsurface; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN; -import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN; -import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED; -import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT; -import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK; -import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING; -import static android.window.StartingWindowInfo.TYPE_PARAMETER_SAME_PACKAGE; -import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; @@ -68,27 +60,24 @@ import java.util.function.BiConsumer; */ public class StartingWindowController implements RemoteCallable<StartingWindowController> { private static final String TAG = StartingWindowController.class.getSimpleName(); + // TODO b/183150443 Keep this flag open for a while, several things might need to adjust. - static final boolean DEBUG_SPLASH_SCREEN = true; - static final boolean DEBUG_TASK_SNAPSHOT = false; + public static final boolean DEBUG_SPLASH_SCREEN = true; + public static final boolean DEBUG_TASK_SNAPSHOT = false; private final StartingSurfaceDrawer mStartingSurfaceDrawer; - private final StartingTypeChecker mStartingTypeChecker = new StartingTypeChecker(); + private final StartingWindowTypeAlgorithm mStartingWindowTypeAlgorithm; private BiConsumer<Integer, Integer> mTaskLaunchingCallback; private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl(); private final Context mContext; private final ShellExecutor mSplashScreenExecutor; - // For Car Launcher - public StartingWindowController(Context context, ShellExecutor splashScreenExecutor) { - this(context, splashScreenExecutor, new TransactionPool()); - } - public StartingWindowController(Context context, ShellExecutor splashScreenExecutor, - TransactionPool pool) { + StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, TransactionPool pool) { mContext = context; mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor, pool); + mStartingWindowTypeAlgorithm = startingWindowTypeAlgorithm; mSplashScreenExecutor = splashScreenExecutor; } @@ -109,90 +98,6 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo return mSplashScreenExecutor; } - private static class StartingTypeChecker { - - private @StartingWindowInfo.StartingWindowType int - estimateStartingWindowType(StartingWindowInfo windowInfo) { - final int parameter = windowInfo.startingWindowTypeParameter; - final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0; - final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0; - final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0; - final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0; - final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0; - final boolean samePackage = (parameter & TYPE_PARAMETER_SAME_PACKAGE) != 0; - return estimateStartingWindowType(windowInfo, newTask, taskSwitch, - processRunning, allowTaskSnapshot, activityCreated, samePackage); - } - - // reference from ActivityRecord#getStartingWindowType - private int estimateStartingWindowType(StartingWindowInfo windowInfo, - boolean newTask, boolean taskSwitch, boolean processRunning, - boolean allowTaskSnapshot, boolean activityCreated, boolean samePackage) { - if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { - Slog.d(TAG, "preferredStartingWindowType newTask " + newTask - + " taskSwitch " + taskSwitch - + " processRunning " + processRunning - + " allowTaskSnapshot " + allowTaskSnapshot - + " activityCreated " + activityCreated - + " samePackage " + samePackage); - } - if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) { - if (!processRunning) { - return STARTING_WINDOW_TYPE_SPLASH_SCREEN; - } - if (newTask) { - if (samePackage) { - return STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN; - } else { - return STARTING_WINDOW_TYPE_SPLASH_SCREEN; - } - } - if (taskSwitch && !activityCreated) { - return STARTING_WINDOW_TYPE_SPLASH_SCREEN; - } - } - if (taskSwitch && allowTaskSnapshot) { - final TaskSnapshot snapshot = windowInfo.mTaskSnapshot; - if (isSnapshotCompatible(windowInfo, snapshot)) { - return STARTING_WINDOW_TYPE_SNAPSHOT; - } - if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) { - return STARTING_WINDOW_TYPE_SPLASH_SCREEN; - } - } - return STARTING_WINDOW_TYPE_NONE; - } - - /** - * Returns {@code true} if the task snapshot is compatible with this activity (at least the - * rotation must be the same). - */ - private boolean isSnapshotCompatible(StartingWindowInfo windowInfo, TaskSnapshot snapshot) { - if (snapshot == null) { - if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { - Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId); - } - return false; - } - if (!snapshot.getTopActivityComponent().equals(windowInfo.taskInfo.topActivity)) { - if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { - Slog.d(TAG, "isSnapshotCompatible obsoleted snapshot " - + windowInfo.taskInfo.topActivity); - } - return false; - } - - final int taskRotation = windowInfo.taskInfo.configuration - .windowConfiguration.getRotation(); - final int snapshotRotation = snapshot.getRotation(); - if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { - Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation - + " snapshot " + snapshotRotation); - } - return taskRotation == snapshotRotation; - } - } - /* * Registers the starting window listener. * @@ -212,7 +117,8 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { mSplashScreenExecutor.execute(() -> { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addStartingWindow"); - final int suggestionType = mStartingTypeChecker.estimateStartingWindowType( + + final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType( windowInfo); final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo; if (mTaskLaunchingCallback != null && shouldSendToListener(suggestionType)) { @@ -228,8 +134,10 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo final TaskSnapshot snapshot = windowInfo.mTaskSnapshot; mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot); + } else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ { + // Don't add a staring window. } - // If prefer don't show, then don't show! + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowTypeAlgorithm.java new file mode 100644 index 000000000000..de221ed4cea7 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowTypeAlgorithm.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 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.startingsurface; + +import android.window.StartingWindowInfo; + +/** + * Used by {@link StartingWindowController} for determining the type of a new starting window. + */ +public interface StartingWindowTypeAlgorithm { + /** + * @return suggested type for the given window. + */ + @StartingWindowInfo.StartingWindowType + int getSuggestedWindowType(StartingWindowInfo windowInfo); +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java new file mode 100644 index 000000000000..9948e7d1f9c4 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2021 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.startingsurface.phone; + +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN; +import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE; +import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT; +import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN; +import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED; +import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT; +import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK; +import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING; +import static android.window.StartingWindowInfo.TYPE_PARAMETER_SAME_PACKAGE; +import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH; + +import static com.android.wm.shell.startingsurface.StartingWindowController.DEBUG_SPLASH_SCREEN; +import static com.android.wm.shell.startingsurface.StartingWindowController.DEBUG_TASK_SNAPSHOT; + +import android.util.Slog; +import android.window.StartingWindowInfo; +import android.window.TaskSnapshot; + +import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm; + +/** + * Algorithm for determining the type of a new starting window on handheld devices. + * At the moment also used on Android Auto. + */ +public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgorithm { + private static final String TAG = PhoneStartingWindowTypeAlgorithm.class.getSimpleName(); + + @Override + public int getSuggestedWindowType(StartingWindowInfo windowInfo) { + final int parameter = windowInfo.startingWindowTypeParameter; + final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0; + final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0; + final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0; + final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0; + final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0; + final boolean samePackage = (parameter & TYPE_PARAMETER_SAME_PACKAGE) != 0; + final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME; + + if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { + Slog.d(TAG, "preferredStartingWindowType newTask " + newTask + + " taskSwitch " + taskSwitch + + " processRunning " + processRunning + + " allowTaskSnapshot " + allowTaskSnapshot + + " activityCreated " + activityCreated + + " samePackage " + samePackage + + " topIsHome " + topIsHome); + } + if (!topIsHome) { + if (!processRunning) { + return STARTING_WINDOW_TYPE_SPLASH_SCREEN; + } + if (newTask) { + if (samePackage) { + return STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN; + } else { + return STARTING_WINDOW_TYPE_SPLASH_SCREEN; + } + } + if (taskSwitch && !activityCreated) { + return STARTING_WINDOW_TYPE_SPLASH_SCREEN; + } + } + if (taskSwitch && allowTaskSnapshot) { + if (isSnapshotCompatible(windowInfo)) { + return STARTING_WINDOW_TYPE_SNAPSHOT; + } + if (!topIsHome) { + return STARTING_WINDOW_TYPE_SPLASH_SCREEN; + } + } + return STARTING_WINDOW_TYPE_NONE; + } + + + /** + * Returns {@code true} if the task snapshot is compatible with this activity (at least the + * rotation must be the same). + */ + private boolean isSnapshotCompatible(StartingWindowInfo windowInfo) { + final TaskSnapshot snapshot = windowInfo.mTaskSnapshot; + if (snapshot == null) { + if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { + Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId); + } + return false; + } + if (!snapshot.getTopActivityComponent().equals(windowInfo.taskInfo.topActivity)) { + if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { + Slog.d(TAG, "isSnapshotCompatible obsoleted snapshot " + + windowInfo.taskInfo.topActivity); + } + return false; + } + + final int taskRotation = windowInfo.taskInfo.configuration + .windowConfiguration.getRotation(); + final int snapshotRotation = snapshot.getRotation(); + if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { + Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation + + " snapshot " + snapshotRotation); + } + return taskRotation == snapshotRotation; + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/tv/TvStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/tv/TvStartingWindowTypeAlgorithm.java new file mode 100644 index 000000000000..6e7dec590308 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/tv/TvStartingWindowTypeAlgorithm.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 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.startingsurface.tv; + +import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN; + +import android.window.StartingWindowInfo; + +import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm; + +/** + * Algorithm for determining the type of a new starting window on Android TV. + * For now we always show empty splash screens on Android TV. + */ +public class TvStartingWindowTypeAlgorithm implements StartingWindowTypeAlgorithm { + @Override + public int getSuggestedWindowType(StartingWindowInfo windowInfo) { + // For now we want to always show empty splash screens on TV. + return STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN; + } +} |