diff options
12 files changed, 332 insertions, 137 deletions
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java index 63b9e9befb77..d1c1e40d1578 100644 --- a/core/java/android/window/StartingWindowInfo.java +++ b/core/java/android/window/StartingWindowInfo.java @@ -35,6 +35,31 @@ import android.view.WindowManager; @TestApi public final class StartingWindowInfo implements Parcelable { /** + * Prefer nothing or not care the type of starting window. + * @hide + */ + public static final int STARTING_WINDOW_TYPE_NONE = 0; + /** + * Prefer splash screen starting window. + * @hide + */ + public static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 1; + /** + * Prefer snapshot starting window. + * @hide + */ + public static final int STARTING_WINDOW_TYPE_SNAPSHOT = 2; + /** + * @hide + */ + @IntDef(flag = true, prefix = "STARTING_WINDOW_TYPE_", value = { + STARTING_WINDOW_TYPE_NONE, + STARTING_WINDOW_TYPE_SPLASH_SCREEN, + STARTING_WINDOW_TYPE_SNAPSHOT + }) + public @interface StartingWindowType {} + + /** * The {@link TaskInfo} from this task. * @hide */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java index 7376d9898ab8..cc353dc991e3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java @@ -25,6 +25,7 @@ import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.transition.Transitions; import java.util.Optional; @@ -44,6 +45,7 @@ public class ShellInitImpl { private final FullscreenTaskListener mFullscreenTaskListener; private final ShellExecutor mMainExecutor; private final Transitions mTransitions; + private final Optional<StartingSurface> mStartingSurfaceOptional; private final InitImpl mImpl = new InitImpl(); @@ -53,6 +55,7 @@ public class ShellInitImpl { Optional<LegacySplitScreenController> legacySplitScreenOptional, Optional<SplitScreenController> splitScreenOptional, Optional<AppPairsController> appPairsOptional, + Optional<StartingSurface> startingSurfaceOptional, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, ShellExecutor mainExecutor) { @@ -62,6 +65,7 @@ public class ShellInitImpl { legacySplitScreenOptional, splitScreenOptional, appPairsOptional, + startingSurfaceOptional, fullscreenTaskListener, transitions, mainExecutor).mImpl; @@ -73,6 +77,7 @@ public class ShellInitImpl { Optional<LegacySplitScreenController> legacySplitScreenOptional, Optional<SplitScreenController> splitScreenOptional, Optional<AppPairsController> appPairsOptional, + Optional<StartingSurface> startingSurfaceOptional, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, ShellExecutor mainExecutor) { @@ -85,6 +90,7 @@ public class ShellInitImpl { mFullscreenTaskListener = fullscreenTaskListener; mTransitions = transitions; mMainExecutor = mainExecutor; + mStartingSurfaceOptional = startingSurfaceOptional; } private void init() { @@ -93,6 +99,7 @@ public class ShellInitImpl { mShellTaskOrganizer.addListenerForType( mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN); + mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface); // Register the shell organizer mShellTaskOrganizer.registerOrganizer(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index efc55c4fbe31..9ddeb2fc6e1e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -44,7 +44,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.sizecompatui.SizeCompatUIController; -import com.android.wm.shell.startingsurface.StartingSurfaceDrawer; +import com.android.wm.shell.startingsurface.StartingSurface; import java.io.PrintWriter; import java.util.ArrayList; @@ -110,7 +110,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>(); private final Object mLock = new Object(); - private final StartingSurfaceDrawer mStartingSurfaceDrawer; + private StartingSurface mStartingSurface; /** * In charge of showing size compat UI. Can be {@code null} if device doesn't support size @@ -120,23 +120,19 @@ public class ShellTaskOrganizer extends TaskOrganizer { private final SizeCompatUIController mSizeCompatUI; public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) { - this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */, - new StartingSurfaceDrawer(context, mainExecutor)); + this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */); } public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context, @Nullable SizeCompatUIController sizeCompatUI) { - this(null /* taskOrganizerController */, mainExecutor, context, sizeCompatUI, - new StartingSurfaceDrawer(context, mainExecutor)); + this(null /* taskOrganizerController */, mainExecutor, context, sizeCompatUI); } @VisibleForTesting ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController, ShellExecutor mainExecutor, - Context context, @Nullable SizeCompatUIController sizeCompatUI, - StartingSurfaceDrawer startingSurfaceDrawer) { + Context context, @Nullable SizeCompatUIController sizeCompatUI) { super(taskOrganizerController, mainExecutor); mSizeCompatUI = sizeCompatUI; - mStartingSurfaceDrawer = startingSurfaceDrawer; } @Override @@ -163,6 +159,15 @@ public class ShellTaskOrganizer extends TaskOrganizer { } /** + * @hide + */ + public void initStartingSurface(StartingSurface startingSurface) { + synchronized (mLock) { + mStartingSurface = startingSurface; + } + } + + /** * Adds a listener for a specific task id. */ public void addListenerForTaskId(TaskListener listener, int taskId) { @@ -254,17 +259,23 @@ public class ShellTaskOrganizer extends TaskOrganizer { @Override public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { - mStartingSurfaceDrawer.addStartingWindow(info, appToken); + if (mStartingSurface != null) { + mStartingSurface.addStartingWindow(info, appToken); + } } @Override public void removeStartingWindow(int taskId) { - mStartingSurfaceDrawer.removeStartingWindow(taskId); + if (mStartingSurface != null) { + mStartingSurface.removeStartingWindow(taskId); + } } @Override public void copySplashScreenView(int taskId) { - mStartingSurfaceDrawer.copySplashScreenView(taskId); + if (mStartingSurface != null) { + mStartingSurface.copySplashScreenView(taskId); + } } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java new file mode 100644 index 000000000000..2c4ceffcb8f5 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java @@ -0,0 +1,39 @@ +/* + * 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.os.IBinder; +import android.window.StartingWindowInfo; + +/** + * Interface to engage starting window feature. + */ +public interface StartingSurface { + /** + * Called when a task need a starting window. + */ + void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken); + /** + * Called when the content of a task is ready to show, starting window can be removed. + */ + void removeStartingWindow(int taskId); + /** + * Called when the Task wants to copy the splash screen. + * @param taskId + */ + void copySplashScreenView(int taskId); +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 5332291fd1bd..814407164750 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -16,15 +16,9 @@ package com.android.wm.shell.startingsurface; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.content.Context.CONTEXT_RESTRICTED; import static android.content.res.Configuration.EMPTY; import static android.view.Display.DEFAULT_DISPLAY; -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_TASK_SWITCH; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; @@ -37,7 +31,6 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.hardware.display.DisplayManager; import android.os.IBinder; -import android.os.RemoteException; import android.util.Slog; import android.util.SparseArray; import android.view.Display; @@ -46,7 +39,6 @@ import android.view.WindowManager; import android.window.SplashScreenView; import android.window.SplashScreenView.SplashScreenViewParcelable; import android.window.StartingWindowInfo; -import android.window.TaskOrganizer; import android.window.TaskSnapshot; import com.android.internal.R; @@ -56,19 +48,13 @@ import com.android.wm.shell.common.ShellExecutor; import java.util.function.Consumer; /** - * Implementation to draw the starting window to an application, and remove the starting window - * until the application displays its own window. - * - * When receive {@link TaskOrganizer#addStartingWindow} callback, use this class to create a - * starting window and attached to the Task, then when the Task want to remove the starting window, - * the TaskOrganizer will receive {@link TaskOrganizer#removeStartingWindow} callback then use this - * class to remove the starting window of the Task. + * A class which able to draw splash screen or snapshot as the starting window for a task. * @hide */ public class StartingSurfaceDrawer { static final String TAG = StartingSurfaceDrawer.class.getSimpleName(); - static final boolean DEBUG_SPLASH_SCREEN = false; - static final boolean DEBUG_TASK_SNAPSHOT = false; + static final boolean DEBUG_SPLASH_SCREEN = StartingWindowController.DEBUG_SPLASH_SCREEN; + static final boolean DEBUG_TASK_SNAPSHOT = StartingWindowController.DEBUG_TASK_SNAPSHOT; private final Context mContext; private final DisplayManager mDisplayManager; @@ -107,106 +93,10 @@ public class StartingSurfaceDrawer { return context.createDisplayContext(targetDisplay); } - private static class PreferredStartingTypeHelper { - private static final int STARTING_TYPE_NO = 0; - private static final int STARTING_TYPE_SPLASH_SCREEN = 1; - private static final int STARTING_TYPE_SNAPSHOT = 2; - - TaskSnapshot mSnapshot; - int mPreferredType; - - PreferredStartingTypeHelper(StartingWindowInfo taskInfo) { - final int parameter = taskInfo.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; - mPreferredType = preferredStartingWindowType(taskInfo, newTask, taskSwitch, - processRunning, allowTaskSnapshot, activityCreated); - } - - // reference from ActivityRecord#getStartingWindowType - private int preferredStartingWindowType(StartingWindowInfo windowInfo, - boolean newTask, boolean taskSwitch, boolean processRunning, - boolean allowTaskSnapshot, boolean activityCreated) { - if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { - Slog.d(TAG, "preferredStartingWindowType newTask " + newTask - + " taskSwitch " + taskSwitch - + " processRunning " + processRunning - + " allowTaskSnapshot " + allowTaskSnapshot - + " activityCreated " + activityCreated); - } - - if (newTask || !processRunning || (taskSwitch && !activityCreated)) { - return STARTING_TYPE_SPLASH_SCREEN; - } else if (taskSwitch && allowTaskSnapshot) { - final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId); - if (isSnapshotCompatible(windowInfo, snapshot)) { - return STARTING_TYPE_SNAPSHOT; - } - if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) { - return STARTING_TYPE_SPLASH_SCREEN; - } - return STARTING_TYPE_NO; - } else { - return STARTING_TYPE_NO; - } - } - - /** - * 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; - } - - 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; - } - - private TaskSnapshot getTaskSnapshot(int taskId) { - if (mSnapshot != null) { - return mSnapshot; - } - try { - mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId, - false/* isLowResolution */); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e); - return null; - } - return mSnapshot; - } - } - /** - * Called when a task need a starting window. + * Called when a task need a splash screen starting window. */ - public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { - final PreferredStartingTypeHelper helper = - new PreferredStartingTypeHelper(windowInfo); - if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SPLASH_SCREEN) { - addSplashScreenStartingWindow(windowInfo, appToken); - } else if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SNAPSHOT) { - final TaskSnapshot snapshot = helper.mSnapshot; - makeTaskSnapshotWindow(windowInfo, appToken, snapshot); - } - // If prefer don't show, then don't show! - } - - private void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { + public void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { final RunningTaskInfo taskInfo = windowInfo.taskInfo; final ActivityInfo activityInfo = taskInfo.topActivityInfo; if (activityInfo == null) { @@ -378,8 +268,8 @@ public class StartingSurfaceDrawer { /** * Called when a task need a snapshot starting window. */ - private void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, - IBinder appToken, TaskSnapshot snapshot) { + void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, IBinder appToken, + TaskSnapshot snapshot) { final int taskId = startingWindowInfo.taskInfo.taskId; final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken, snapshot, mMainExecutor, () -> removeWindowSynced(taskId) /* clearWindow */); 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 new file mode 100644 index 000000000000..73bf8ac90c29 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2020 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 static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +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_TASK_SWITCH; + +import android.app.ActivityTaskManager; +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Slog; +import android.window.StartingWindowInfo; +import android.window.TaskOrganizer; +import android.window.TaskSnapshot; + +import com.android.wm.shell.common.ShellExecutor; + +/** + * Implementation to draw the starting window to an application, and remove the starting window + * until the application displays its own window. + * + * When receive {@link TaskOrganizer#addStartingWindow} callback, use this class to create a + * starting window and attached to the Task, then when the Task want to remove the starting window, + * the TaskOrganizer will receive {@link TaskOrganizer#removeStartingWindow} callback then use this + * class to remove the starting window of the Task. + * @hide + */ +public class StartingWindowController { + private static final String TAG = StartingWindowController.class.getSimpleName(); + static final boolean DEBUG_SPLASH_SCREEN = false; + static final boolean DEBUG_TASK_SNAPSHOT = false; + + private final StartingSurfaceDrawer mStartingSurfaceDrawer; + private final StartingTypeChecker mStartingTypeChecker = new StartingTypeChecker(); + private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl(); + + public StartingWindowController(Context context, ShellExecutor mainExecutor) { + mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, mainExecutor); + } + + /** + * Provide the implementation for Shell Module. + */ + public StartingSurface asStartingSurface() { + return mImpl; + } + + private static class StartingTypeChecker { + TaskSnapshot mSnapshot; + + StartingTypeChecker() { } + + private void reset() { + mSnapshot = null; + } + + private @StartingWindowInfo.StartingWindowType int + estimateStartingWindowType(StartingWindowInfo windowInfo) { + reset(); + 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; + return estimateStartingWindowType(windowInfo, newTask, taskSwitch, + processRunning, allowTaskSnapshot, activityCreated); + } + + // reference from ActivityRecord#getStartingWindowType + private int estimateStartingWindowType(StartingWindowInfo windowInfo, + boolean newTask, boolean taskSwitch, boolean processRunning, + boolean allowTaskSnapshot, boolean activityCreated) { + if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { + Slog.d(TAG, "preferredStartingWindowType newTask " + newTask + + " taskSwitch " + taskSwitch + + " processRunning " + processRunning + + " allowTaskSnapshot " + allowTaskSnapshot + + " activityCreated " + activityCreated); + } + if (newTask || !processRunning || (taskSwitch && !activityCreated)) { + return STARTING_WINDOW_TYPE_SPLASH_SCREEN; + } + if (taskSwitch && allowTaskSnapshot) { + final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId); + 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; + } + + 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; + } + + private TaskSnapshot getTaskSnapshot(int taskId) { + if (mSnapshot != null) { + return mSnapshot; + } + try { + mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId, + false/* isLowResolution */); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e); + return null; + } + return mSnapshot; + } + } + + /** + * Called when a task need a starting window. + */ + void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { + final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo); + if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) { + mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken); + } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) { + final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot; + mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot); + } + // If prefer don't show, then don't show! + } + + void copySplashScreenView(int taskId) { + mStartingSurfaceDrawer.copySplashScreenView(taskId); + } + + /** + * Called when the content of a task is ready to show, starting window can be removed. + */ + void removeStartingWindow(int taskId) { + mStartingSurfaceDrawer.removeStartingWindow(taskId); + } + + private class StartingSurfaceImpl implements StartingSurface { + + @Override + public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) { + StartingWindowController.this.addStartingWindow(windowInfo, appToken); + } + + @Override + public void removeStartingWindow(int taskId) { + StartingWindowController.this.removeStartingWindow(taskId); + } + + @Override + public void copySplashScreenView(int taskId) { + StartingWindowController.this.copySplashScreenView(taskId); + } + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index a0e9f43218f2..06b492dcb409 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -53,7 +53,6 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.sizecompatui.SizeCompatUIController; -import com.android.wm.shell.startingsurface.StartingSurfaceDrawer; import org.junit.Before; import org.junit.Test; @@ -79,8 +78,6 @@ public class ShellTaskOrganizerTests { private Context mContext; @Mock private SizeCompatUIController mSizeCompatUI; - @Mock - private StartingSurfaceDrawer mStartingSurfaceDrawer; ShellTaskOrganizer mOrganizer; private final SyncTransactionQueue mSyncTransactionQueue = mock(SyncTransactionQueue.class); @@ -116,7 +113,7 @@ public class ShellTaskOrganizerTests { .when(mTaskOrganizerController).registerTaskOrganizer(any()); } catch (RemoteException e) {} mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mTestExecutor, mContext, - mSizeCompatUI, mStartingSurfaceDrawer)); + mSizeCompatUI)); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index de7d6c74bb06..b9af9ce8895d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -125,7 +125,7 @@ public class StartingSurfaceDrawerTests { final Handler mainLoop = new Handler(Looper.getMainLooper()); final StartingWindowInfo windowInfo = createWindowInfo(taskId, android.R.style.Theme); - mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder); + mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder); waitHandlerIdle(mainLoop); verify(mStartingSurfaceDrawer).postAddWindow( eq(taskId), eq(mBinder), any(), any(), any(), any()); @@ -143,7 +143,7 @@ public class StartingSurfaceDrawerTests { final Handler mainLoop = new Handler(Looper.getMainLooper()); final StartingWindowInfo windowInfo = createWindowInfo(taskId, 0); - mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder); + mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder); waitHandlerIdle(mainLoop); verify(mStartingSurfaceDrawer).postAddWindow( eq(taskId), eq(mBinder), any(), any(), any(), any()); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 19520df08757..9d00262436e5 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -115,7 +115,8 @@ public class SystemUIFactory { .setShellCommandHandler(mWMComponent.getShellCommandHandler()) .setAppPairs(mWMComponent.getAppPairs()) .setTaskViewFactory(mWMComponent.getTaskViewFactory()) - .setTransitions(mWMComponent.getTransitions()); + .setTransitions(mWMComponent.getTransitions()) + .setStartingSurface(mWMComponent.getStartingSurface()); } else { // TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option // is separating this logic into newly creating SystemUITestsFactory. @@ -129,7 +130,8 @@ public class SystemUIFactory { .setShellCommandHandler(Optional.ofNullable(null)) .setAppPairs(Optional.ofNullable(null)) .setTaskViewFactory(Optional.ofNullable(null)) - .setTransitions(Transitions.createEmptyForTesting()); + .setTransitions(Transitions.createEmptyForTesting()) + .setStartingSurface(Optional.ofNullable(null)); } mSysUIComponent = builder.build(); if (initializeComponents) { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index ffb8446f3e21..8f79de518419 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -33,6 +33,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.transition.RemoteTransitions; import java.util.Optional; @@ -88,6 +89,9 @@ public interface SysUIComponent { @BindsInstance Builder setTransitions(RemoteTransitions t); + @BindsInstance + Builder setStartingSurface(Optional<StartingSurface> s); + SysUIComponent build(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index f3726a37bb65..1b77d1c16639 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -32,6 +32,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.transition.RemoteTransitions; import java.util.Optional; @@ -98,4 +99,7 @@ public interface WMComponent { @WMSingleton RemoteTransitions getTransitions(); + + @WMSingleton + Optional<StartingSurface> getStartingSurface(); } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 4611fe03e157..8d3a0402f4c8 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -77,6 +77,8 @@ import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.sizecompatui.SizeCompatUIController; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.startingsurface.StartingSurface; +import com.android.wm.shell.startingsurface.StartingWindowController; import com.android.wm.shell.transition.RemoteTransitions; import com.android.wm.shell.transition.Transitions; @@ -448,6 +450,22 @@ public abstract class WMShellBaseModule { @BindsOptionalOf abstract AppPairsController optionalAppPairs(); + // Starting window + + @WMSingleton + @Provides + static Optional<StartingSurface> provideStartingSurface( + StartingWindowController startingWindowController) { + return Optional.of(startingWindowController.asStartingSurface()); + } + + @WMSingleton + @Provides + static StartingWindowController provideStartingWindowController(Context context, + @ShellMainThread ShellExecutor mainExecutor) { + return new StartingWindowController(context, mainExecutor); + } + // // Task view factory // @@ -479,6 +497,7 @@ public abstract class WMShellBaseModule { Optional<LegacySplitScreenController> legacySplitScreenOptional, Optional<SplitScreenController> splitScreenOptional, Optional<AppPairsController> appPairsOptional, + Optional<StartingSurface> startingSurface, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, @ShellMainThread ShellExecutor mainExecutor) { @@ -488,6 +507,7 @@ public abstract class WMShellBaseModule { legacySplitScreenOptional, splitScreenOptional, appPairsOptional, + startingSurface, fullscreenTaskListener, transitions, mainExecutor); |