• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.server.wm;
18 
19 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
20 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
21 import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
22 import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
23 import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
24 import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
25 import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
26 
27 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
28 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
29 
30 import android.annotation.NonNull;
31 import android.annotation.Nullable;
32 import android.content.pm.ApplicationInfo;
33 import android.content.res.CompatibilityInfo;
34 import android.content.res.Configuration;
35 import android.os.SystemProperties;
36 import android.util.Slog;
37 import android.window.TaskSnapshot;
38 
39 import com.android.server.policy.WindowManagerPolicy.StartingSurface;
40 
41 import java.util.function.Supplier;
42 
43 /**
44  * Managing to create and release a starting window surface.
45  */
46 public class StartingSurfaceController {
47     private static final String TAG = TAG_WITH_CLASS_NAME
48             ? StartingSurfaceController.class.getSimpleName() : TAG_WM;
49     /** Set to {@code true} to enable shell starting surface drawer. */
50     static final boolean DEBUG_ENABLE_SHELL_DRAWER =
51             SystemProperties.getBoolean("persist.debug.shell_starting_surface", true);
52     private final WindowManagerService mService;
53     private final SplashScreenExceptionList mSplashScreenExceptionsList;
54 
StartingSurfaceController(WindowManagerService wm)55     public StartingSurfaceController(WindowManagerService wm) {
56         mService = wm;
57         mSplashScreenExceptionsList = new SplashScreenExceptionList(wm.mContext.getMainExecutor());
58     }
59 
createSplashScreenStartingSurface(ActivityRecord activity, String packageName, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId)60     StartingSurface createSplashScreenStartingSurface(ActivityRecord activity, String packageName,
61             int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
62             int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) {
63         if (!DEBUG_ENABLE_SHELL_DRAWER) {
64             return mService.mPolicy.addSplashScreen(activity.token, activity.mUserId, packageName,
65                     theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
66                     overrideConfig, displayId);
67         }
68 
69         synchronized (mService.mGlobalLock) {
70             final Task task = activity.getTask();
71             if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow(
72                     task, activity, theme, null /* taskSnapshot */)) {
73                 return new ShellStartingSurface(task);
74             }
75         }
76         return null;
77     }
78 
79     /**
80      * @see SplashScreenExceptionList#isException(String, int, Supplier)
81      */
isExceptionApp(@onNull String packageName, int targetSdk, @Nullable Supplier<ApplicationInfo> infoProvider)82     boolean isExceptionApp(@NonNull String packageName, int targetSdk,
83             @Nullable Supplier<ApplicationInfo> infoProvider) {
84         return mSplashScreenExceptionsList.isException(packageName, targetSdk, infoProvider);
85     }
86 
makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch, boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated, boolean useEmpty, boolean useLegacy)87     int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
88             boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
89             boolean useEmpty, boolean useLegacy) {
90         int parameter = 0;
91         if (newTask) {
92             parameter |= TYPE_PARAMETER_NEW_TASK;
93         }
94         if (taskSwitch) {
95             parameter |= TYPE_PARAMETER_TASK_SWITCH;
96         }
97         if (processRunning) {
98             parameter |= TYPE_PARAMETER_PROCESS_RUNNING;
99         }
100         if (allowTaskSnapshot) {
101             parameter |= TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
102         }
103         if (activityCreated) {
104             parameter |= TYPE_PARAMETER_ACTIVITY_CREATED;
105         }
106         if (useEmpty) {
107             parameter |= TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
108         }
109         if (useLegacy) {
110             parameter |= TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
111         }
112         return parameter;
113     }
114 
createTaskSnapshotSurface(ActivityRecord activity, TaskSnapshot taskSnapshot)115     StartingSurface createTaskSnapshotSurface(ActivityRecord activity, TaskSnapshot taskSnapshot) {
116         final WindowState topFullscreenOpaqueWindow;
117         final Task task;
118         synchronized (mService.mGlobalLock) {
119             final WindowState mainWindow = activity.findMainWindow();
120             task = activity.getTask();
121             if (task == null) {
122                 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
123                         + activity);
124                 return null;
125             }
126             final ActivityRecord topFullscreenActivity =
127                     activity.getTask().getTopFullscreenActivity();
128             if (topFullscreenActivity == null) {
129                 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
130                         + task);
131                 return null;
132             }
133             topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
134             if (mainWindow == null || topFullscreenOpaqueWindow == null) {
135                 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
136                         + activity);
137                 return null;
138             }
139             if (topFullscreenActivity.getWindowConfiguration().getRotation()
140                     != taskSnapshot.getRotation()
141                     // Use normal rotation to avoid flickering of IME window in old orientation.
142                     && !taskSnapshot.hasImeSurface()) {
143                 // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible
144                 // that the activity will be updated to the same rotation as the snapshot. Since
145                 // the transition is not started yet, fixed rotation transform needs to be applied
146                 // earlier to make the snapshot show in a rotated container.
147                 activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
148                         topFullscreenActivity, false /* checkOpening */);
149             }
150             if (DEBUG_ENABLE_SHELL_DRAWER) {
151                 mService.mAtmService.mTaskOrganizerController.addStartingWindow(task,
152                         activity, 0 /* launchTheme */, taskSnapshot);
153                 return new ShellStartingSurface(task);
154             }
155         }
156         return mService.mTaskSnapshotController.createStartingSurface(activity, taskSnapshot);
157     }
158 
159 
160     private final class ShellStartingSurface implements StartingSurface {
161         private final Task mTask;
162 
ShellStartingSurface(Task task)163         ShellStartingSurface(Task task) {
164             mTask = task;
165         }
166 
167         @Override
remove(boolean animate)168         public void remove(boolean animate) {
169             synchronized (mService.mGlobalLock) {
170                 mService.mAtmService.mTaskOrganizerController.removeStartingWindow(mTask, animate);
171             }
172         }
173     }
174 }
175