• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.startingsurface.phone;
18 
19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
20 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
21 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
22 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
23 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
24 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
25 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
26 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
27 import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
28 import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
29 import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
30 import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
31 import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
32 
33 import static com.android.wm.shell.startingsurface.StartingWindowController.DEBUG_SPLASH_SCREEN;
34 import static com.android.wm.shell.startingsurface.StartingWindowController.DEBUG_TASK_SNAPSHOT;
35 
36 import android.util.Slog;
37 import android.window.StartingWindowInfo;
38 import android.window.TaskSnapshot;
39 
40 import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
41 
42 /**
43  * Algorithm for determining the type of a new starting window on handheld devices.
44  * At the moment also used on Android Auto.
45  */
46 public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgorithm {
47     private static final String TAG = PhoneStartingWindowTypeAlgorithm.class.getSimpleName();
48 
49     @Override
getSuggestedWindowType(StartingWindowInfo windowInfo)50     public int getSuggestedWindowType(StartingWindowInfo windowInfo) {
51         final int parameter = windowInfo.startingWindowTypeParameter;
52         final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0;
53         final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0;
54         final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
55         final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
56         final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
57         final boolean useEmptySplashScreen =
58                 (parameter & TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN) != 0;
59         final boolean legacySplashScreen =
60                 ((parameter & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN) != 0);
61         final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME;
62 
63         if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
64             Slog.d(TAG, "preferredStartingWindowType newTask:" + newTask
65                     + " taskSwitch:" + taskSwitch
66                     + " processRunning:" + processRunning
67                     + " allowTaskSnapshot:" + allowTaskSnapshot
68                     + " activityCreated:" + activityCreated
69                     + " useEmptySplashScreen:" + useEmptySplashScreen
70                     + " legacySplashScreen:" + legacySplashScreen
71                     + " topIsHome:" + topIsHome);
72         }
73 
74         final int visibleSplashScreenType = legacySplashScreen
75                 ? STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
76                 : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
77 
78         if (!topIsHome) {
79             if (!processRunning) {
80                 return useEmptySplashScreen
81                         ? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
82                         : visibleSplashScreenType;
83             }
84             if (newTask) {
85                 return useEmptySplashScreen
86                         ? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
87                         : visibleSplashScreenType;
88             }
89             if (taskSwitch && !activityCreated) {
90                 return visibleSplashScreenType;
91             }
92         }
93         if (taskSwitch && allowTaskSnapshot) {
94             if (isSnapshotCompatible(windowInfo)) {
95                 return STARTING_WINDOW_TYPE_SNAPSHOT;
96             }
97             if (!topIsHome) {
98                 return STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
99             }
100         }
101         return STARTING_WINDOW_TYPE_NONE;
102     }
103 
104 
105     /**
106      * Returns {@code true} if the task snapshot is compatible with this activity (at least the
107      * rotation must be the same).
108      */
isSnapshotCompatible(StartingWindowInfo windowInfo)109     private boolean isSnapshotCompatible(StartingWindowInfo windowInfo) {
110         final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
111         if (snapshot == null) {
112             if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
113                 Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
114             }
115             return false;
116         }
117         if (!snapshot.getTopActivityComponent().equals(windowInfo.taskInfo.topActivity)) {
118             if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
119                 Slog.d(TAG, "isSnapshotCompatible obsoleted snapshot "
120                         + windowInfo.taskInfo.topActivity);
121             }
122             return false;
123         }
124 
125         final int taskRotation = windowInfo.taskInfo.configuration
126                 .windowConfiguration.getRotation();
127         final int snapshotRotation = snapshot.getRotation();
128         if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
129             Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
130                     + " snapshot " + snapshotRotation);
131         }
132         return taskRotation == snapshotRotation;
133     }
134 }
135