Loading core/java/android/window/StartingWindowInfo.java +25 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,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 Loading libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading @@ -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) { Loading @@ -62,6 +65,7 @@ public class ShellInitImpl { legacySplitScreenOptional, splitScreenOptional, appPairsOptional, startingSurfaceOptional, fullscreenTaskListener, transitions, mainExecutor).mImpl; Loading @@ -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) { Loading @@ -85,6 +90,7 @@ public class ShellInitImpl { mFullscreenTaskListener = fullscreenTaskListener; mTransitions = transitions; mMainExecutor = mainExecutor; mStartingSurfaceOptional = startingSurfaceOptional; } private void init() { Loading @@ -93,6 +99,7 @@ public class ShellInitImpl { mShellTaskOrganizer.addListenerForType( mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN); mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface); // Register the shell organizer mShellTaskOrganizer.registerOrganizer(); Loading libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +23 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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 Loading @@ -162,6 +158,15 @@ public class ShellTaskOrganizer extends TaskOrganizer { super.createRootTask(displayId, windowingMode, cookie); } /** * @hide */ public void initStartingSurface(StartingSurface startingSurface) { synchronized (mLock) { mStartingSurface = startingSurface; } } /** * Adds a listener for a specific task id. */ Loading Loading @@ -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 Loading libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * 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); } libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +7 −117 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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 */); Loading Loading
core/java/android/window/StartingWindowInfo.java +25 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,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 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading @@ -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) { Loading @@ -62,6 +65,7 @@ public class ShellInitImpl { legacySplitScreenOptional, splitScreenOptional, appPairsOptional, startingSurfaceOptional, fullscreenTaskListener, transitions, mainExecutor).mImpl; Loading @@ -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) { Loading @@ -85,6 +90,7 @@ public class ShellInitImpl { mFullscreenTaskListener = fullscreenTaskListener; mTransitions = transitions; mMainExecutor = mainExecutor; mStartingSurfaceOptional = startingSurfaceOptional; } private void init() { Loading @@ -93,6 +99,7 @@ public class ShellInitImpl { mShellTaskOrganizer.addListenerForType( mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN); mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface); // Register the shell organizer mShellTaskOrganizer.registerOrganizer(); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +23 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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 Loading @@ -162,6 +158,15 @@ public class ShellTaskOrganizer extends TaskOrganizer { super.createRootTask(displayId, windowingMode, cookie); } /** * @hide */ public void initStartingSurface(StartingSurface startingSurface) { synchronized (mLock) { mStartingSurface = startingSurface; } } /** * Adds a listener for a specific task id. */ Loading Loading @@ -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 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * 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); }
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +7 −117 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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 */); Loading