blob: d49270d7f55780c28c15fe1f7b7e1cfda28c3f24 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Winson Chungbb348802017-01-30 12:01:45 -080019import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
Riddle Hsuaec55442019-03-12 17:25:35 +080020import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
Ruben Brunkf53497c2017-03-27 20:26:17 -070021import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080022import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
23import static android.app.ActivityOptions.ANIM_CUSTOM;
24import static android.app.ActivityOptions.ANIM_NONE;
25import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
26import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
27import static android.app.ActivityOptions.ANIM_SCALE_UP;
Ruben Brunkf53497c2017-03-27 20:26:17 -070028import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080029import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
30import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
31import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
32import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
Louis Chang477e93e2019-04-24 18:35:20 +080033import static android.app.ActivityOptions.ANIM_UNDEFINED;
Riddle Hsu16567132018-08-16 21:37:47 +080034import static android.app.ActivityTaskManager.INVALID_STACK_ID;
Vishnu Nair9ba31652018-11-13 14:34:05 -080035import static android.app.ActivityTaskManager.INVALID_TASK_ID;
Winson Chung59fda9e2017-01-20 16:14:51 -080036import static android.app.AppOpsManager.MODE_ALLOWED;
Winson Chungf4ac0632017-03-17 12:34:12 -070037import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
Vishnu Nair132ee832018-09-28 15:00:05 -070038import static android.app.WaitResult.INVALID_DELAY;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070039import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
40import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
41import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070042import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Riddle Hsu74826262019-04-17 14:57:42 +080043import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
Garfield Tane8d84ab2019-10-11 09:49:40 -070044import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -070045import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Garfield Tane8d84ab2019-10-11 09:49:40 -070046import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070047import static android.app.WindowConfiguration.activityTypeToString;
Ruben Brunkf53497c2017-03-27 20:26:17 -070048import static android.content.Intent.ACTION_MAIN;
49import static android.content.Intent.CATEGORY_HOME;
50import static android.content.Intent.CATEGORY_LAUNCHER;
Chilun2ef71f72018-11-16 17:57:15 +080051import static android.content.Intent.CATEGORY_SECONDARY_HOME;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080052import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Bryce Leeb7c9b802017-05-02 14:20:24 -070053import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY;
Andrii Kulian21713ac2016-10-12 22:05:05 -070054import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
55import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
56import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
57import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
Zak Cohen90e7116742017-01-29 12:59:23 -080058import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
Wale Ogunwale822e5122017-07-26 06:02:24 -070059import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
Garfield Tane8d84ab2019-10-11 09:49:40 -070060import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080061import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
62import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
Garfield Tane8d84ab2019-10-11 09:49:40 -070063import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080064import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020065import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
Chong Zhang87761972016-08-22 13:53:24 -070066import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080067import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
Garfield Tane8d84ab2019-10-11 09:49:40 -070068import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
69import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -080070import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
71import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
Garfield Tane8d84ab2019-10-11 09:49:40 -070072import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Charles He2bf28322017-10-12 22:24:49 +010073import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
74import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
75import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
76import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
Ruben Brunkf53497c2017-03-27 20:26:17 -070077import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
78import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
Wale Ogunwaledf241e92016-10-13 15:14:21 -070079import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Jorim Jaggicd13d332016-04-27 15:40:20 -070080import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -070081import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwaledf241e92016-10-13 15:14:21 -070082import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
Garfield Tane8d84ab2019-10-11 09:49:40 -070083import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
84import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -070085import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
86import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070087import static android.content.res.Configuration.EMPTY;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -070088import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
89import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu0a343c32018-12-21 00:40:48 +080090import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
Ruben Brunkf53497c2017-03-27 20:26:17 -070091import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
Zak Cohen90e7116742017-01-29 12:59:23 -080092import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
Garfield Tane8d84ab2019-10-11 09:49:40 -070093import static android.os.Build.VERSION_CODES.HONEYCOMB;
Zak Cohen90e7116742017-01-29 12:59:23 -080094import static android.os.Build.VERSION_CODES.O;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080095import static android.os.Process.SYSTEM_UID;
Garfield Tane8d84ab2019-10-11 09:49:40 -070096import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
97import static android.view.Display.COLOR_MODE_DEFAULT;
Issei Suzuki62356a22019-04-11 16:46:37 +020098import static android.view.Display.DEFAULT_DISPLAY;
Riddle Hsufd4a0502018-10-16 01:05:16 +080099import static android.view.Display.INVALID_DISPLAY;
Riddle Hsu61987bc2019-04-03 13:08:47 +0800100import static android.view.Surface.ROTATION_270;
101import static android.view.Surface.ROTATION_90;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700102import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
103import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
104import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
105import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
106import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
107import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
108import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700109import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700110import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
111import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700112import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700113import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
114import static android.view.WindowManager.TRANSIT_UNSET;
115import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
Riddle Hsu16567132018-08-16 21:37:47 +0800116
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800117import static com.android.server.am.ActivityRecordProto.APP_WINDOW_TOKEN;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800118import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
119import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
120import static com.android.server.am.ActivityRecordProto.PROC_ID;
121import static com.android.server.am.ActivityRecordProto.STATE;
122import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
123import static com.android.server.am.ActivityRecordProto.VISIBLE;
Issei Suzukif2f6c912019-11-08 11:24:18 +0100124import static com.android.server.am.ActivityRecordProto.VISIBLE_REQUESTED;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700125import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
126import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Hui Yu03d12402018-12-06 18:00:37 -0800127import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
Andrii Kulian79d67982019-08-19 11:56:16 -0700128import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700129import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800130import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
131import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
132import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800133import static com.android.server.wm.ActivityStack.ActivityState.RESTARTING_PROCESS;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800134import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Louis Changeadb22f2019-06-19 12:09:23 +0800135import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800136import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
137import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800138import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -0700139import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
Andrii Kulian79d67982019-08-19 11:56:16 -0700140import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
141import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
Wale Ogunwale59507092018-10-29 09:00:30 -0700142import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700143import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700144import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700145import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
146import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700147import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
148import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
149import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
Jorim Jaggi346702a2019-05-08 17:49:33 +0200150import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700151import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
Wale Ogunwale59507092018-10-29 09:00:30 -0700152import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
Andrii Kulian79d67982019-08-19 11:56:16 -0700153import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
154import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP;
Wale Ogunwale59507092018-10-29 09:00:30 -0700155import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700156import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700157import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700158import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
159import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700160import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
161import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
162import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700163import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
164import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
Wale Ogunwale59507092018-10-29 09:00:30 -0700165import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
166import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
167import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale59507092018-10-29 09:00:30 -0700168import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
169import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
Hui Yu03d12402018-12-06 18:00:37 -0800170import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
Louis Chang746c2242019-10-08 16:30:44 +0800171import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700172import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
173import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
Issei Suzukid4ee1cc2019-11-08 13:20:14 +0100174import static com.android.server.wm.AppWindowTokenProto.CLIENT_VISIBLE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700175import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
176import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
177import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
lumark9bca6b42019-10-17 18:35:22 +0800178import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700179import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
180import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
181import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
182import static com.android.server.wm.AppWindowTokenProto.NAME;
183import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
184import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700185import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
186import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
187import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
188import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
189import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
190import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
Issei Suzukif2f6c912019-11-08 11:24:18 +0100191import static com.android.server.wm.AppWindowTokenProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700192import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
193import static com.android.server.wm.IdentifierProto.HASH_CODE;
194import static com.android.server.wm.IdentifierProto.TITLE;
195import static com.android.server.wm.IdentifierProto.USER_ID;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200196import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700197import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
198import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
199import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200200import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
201import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800202import static com.android.server.wm.TaskPersister.DEBUG;
203import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
lumark9bca6b42019-10-17 18:35:22 +0800204import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
205import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
206import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700207import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
208import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
209import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800210import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700211import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
212import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700213import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
214import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700215import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700216
Ruben Brunkf53497c2017-03-27 20:26:17 -0700217import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
218import static org.xmlpull.v1.XmlPullParser.END_TAG;
219import static org.xmlpull.v1.XmlPullParser.START_TAG;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800220
Andrii Kulian057a6512019-07-15 16:15:51 -0700221import android.annotation.IntDef;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700222import android.annotation.NonNull;
Issei Suzuki74e1eb22018-12-20 17:42:52 +0100223import android.annotation.Nullable;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700224import android.annotation.Size;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700225import android.app.Activity;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700226import android.app.ActivityManager;
Craig Mautner21d24a22014-04-23 11:45:37 -0700227import android.app.ActivityManager.TaskDescription;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -0700228import android.app.ActivityOptions;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800229import android.app.PendingIntent;
Winson Chung709904f2017-04-25 11:00:48 -0700230import android.app.PictureInPictureParams;
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800231import android.app.ResultInfo;
Vishnu Nairbb9ab4b2018-12-13 10:29:46 -0800232import android.app.WaitResult.LaunchState;
Riddle Hsu16567132018-08-16 21:37:47 +0800233import android.app.servertransaction.ActivityConfigurationChangeItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800234import android.app.servertransaction.ActivityLifecycleItem;
235import android.app.servertransaction.ActivityRelaunchItem;
Andrii Kulian79d67982019-08-19 11:56:16 -0700236import android.app.servertransaction.ActivityResultItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800237import android.app.servertransaction.ClientTransaction;
238import android.app.servertransaction.ClientTransactionItem;
Andrii Kulian79d67982019-08-19 11:56:16 -0700239import android.app.servertransaction.DestroyActivityItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700240import android.app.servertransaction.MoveToDisplayItem;
241import android.app.servertransaction.MultiWindowModeChangeItem;
242import android.app.servertransaction.NewIntentItem;
Bryce Lee0bd8d422018-01-09 09:45:57 -0800243import android.app.servertransaction.PauseActivityItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700244import android.app.servertransaction.PipModeChangeItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800245import android.app.servertransaction.ResumeActivityItem;
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800246import android.app.servertransaction.StopActivityItem;
Andrii Kuliand70cdb92019-01-08 15:03:50 -0800247import android.app.servertransaction.TopResumedActivityChangeItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700248import android.app.servertransaction.WindowVisibilityItem;
Hui Yu03d12402018-12-06 18:00:37 -0800249import android.app.usage.UsageEvents.Event;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250import android.content.ComponentName;
251import android.content.Intent;
252import android.content.pm.ActivityInfo;
253import android.content.pm.ApplicationInfo;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -0700254import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255import android.content.res.Configuration;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700256import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257import android.graphics.Bitmap;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800258import android.graphics.GraphicBuffer;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700259import android.graphics.PixelFormat;
260import android.graphics.Point;
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700261import android.graphics.Rect;
Andrii Kulian79d67982019-08-19 11:56:16 -0700262import android.net.Uri;
Patrick Baumann78380272018-04-04 10:41:01 -0700263import android.os.Binder;
Bryce Lee39791592017-04-26 09:29:12 -0700264import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265import android.os.Bundle;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700266import android.os.Debug;
Dianne Hackbornbe707852011-11-11 14:32:10 -0800267import android.os.IBinder;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800268import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269import android.os.Process;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700270import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271import android.os.SystemClock;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700272import android.os.Trace;
273import android.os.UserHandle;
Bryce Lee8558ec72017-08-17 15:37:26 -0700274import android.os.storage.StorageManager;
Amith Yamasani0af6fa72016-01-17 15:36:19 -0800275import android.service.voice.IVoiceInteractionSession;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700276import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277import android.util.EventLog;
278import android.util.Log;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700279import android.util.MergedConfiguration;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700280import android.util.Slog;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700281import android.util.TimeUtils;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700282import android.util.proto.ProtoOutputStream;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800283import android.view.AppTransitionAnimationSpec;
Riddle Hsu61987bc2019-04-03 13:08:47 +0800284import android.view.DisplayCutout;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700285import android.view.DisplayInfo;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800286import android.view.IAppTransitionAnimationSpecsFuture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287import android.view.IApplicationToken;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700288import android.view.InputApplicationHandle;
289import android.view.RemoteAnimationAdapter;
290import android.view.RemoteAnimationDefinition;
lumark19a5d2e2019-10-11 16:19:30 +0800291import android.view.RemoteAnimationTarget;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700292import android.view.SurfaceControl;
293import android.view.SurfaceControl.Transaction;
294import android.view.WindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +0200295import android.view.WindowManager.LayoutParams;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700296import android.view.animation.Animation;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700297
lumark9bca6b42019-10-17 18:35:22 +0800298import com.android.internal.R;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800299import com.android.internal.annotations.VisibleForTesting;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800300import com.android.internal.app.ResolverActivity;
301import com.android.internal.content.ReferrerIntent;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700302import com.android.internal.util.ToBooleanFunction;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800303import com.android.internal.util.XmlUtils;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800304import com.android.internal.util.function.pooled.PooledConsumer;
305import com.android.internal.util.function.pooled.PooledFunction;
306import com.android.internal.util.function.pooled.PooledLambda;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700307import com.android.server.AttributeCache;
308import com.android.server.LocalServices;
Wale Ogunwale59507092018-10-29 09:00:30 -0700309import com.android.server.am.AppTimeTracker;
310import com.android.server.am.PendingIntentRecord;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700311import com.android.server.display.color.ColorDisplayService;
312import com.android.server.policy.WindowManagerPolicy;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200313import com.android.server.protolog.common.ProtoLog;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800314import com.android.server.uri.UriPermissionOwner;
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800315import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
Wale Ogunwale59507092018-10-29 09:00:30 -0700316import com.android.server.wm.ActivityStack.ActivityState;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700317import com.android.server.wm.WindowManagerService.H;
lumark19a5d2e2019-10-11 16:19:30 +0800318import com.android.server.wm.utils.InsetUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319
Andrii Kuliande93eff2019-07-12 12:21:27 -0700320import com.google.android.collect.Sets;
321
Jorim Jaggi02886a82016-12-06 09:10:06 -0800322import org.xmlpull.v1.XmlPullParser;
323import org.xmlpull.v1.XmlPullParserException;
324import org.xmlpull.v1.XmlSerializer;
325
Suprabh Shukla23593142015-11-03 17:31:15 -0800326import java.io.File;
Craig Mautner21d24a22014-04-23 11:45:37 -0700327import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328import java.io.PrintWriter;
329import java.lang.ref.WeakReference;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700330import java.util.ArrayDeque;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331import java.util.ArrayList;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800332import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333import java.util.HashSet;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700334import java.util.List;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700335import java.util.Objects;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800336import java.util.function.Consumer;
337import java.util.function.Function;
338import java.util.function.Predicate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339
340/**
341 * An entry in the history stack, representing an activity.
342 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700343final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
Wale Ogunwale98875612018-10-12 07:53:02 -0700344 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
Andrii Kulian79d67982019-08-19 11:56:16 -0700345 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
346 private static final String TAG_APP = TAG + POSTFIX_APP;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700347 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700348 private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
349 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
350 private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
351 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700352 private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700353 private static final String TAG_STATES = TAG + POSTFIX_STATES;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700354 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700355 private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
356 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700357 private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800358
Craig Mautner21d24a22014-04-23 11:45:37 -0700359 private static final String ATTR_ID = "id";
360 private static final String TAG_INTENT = "intent";
361 private static final String ATTR_USERID = "user_id";
362 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
363 private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700364 private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
Craig Mautner21d24a22014-04-23 11:45:37 -0700365 private static final String ATTR_RESOLVEDTYPE = "resolved_type";
366 private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
Dianne Hackborn337abb32014-09-24 12:44:29 -0700367 static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
Craig Mautner21d24a22014-04-23 11:45:37 -0700368
Andrii Kulian79d67982019-08-19 11:56:16 -0700369 // How many activities have to be scheduled to stop to force a stop pass.
370 private static final int MAX_STOPPING_TO_FORCE = 3;
371
Garfield Tane8d84ab2019-10-11 09:49:40 -0700372 private static final int STARTING_WINDOW_TYPE_NONE = 0;
373 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
374 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
375
376 /**
377 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
378 */
379 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Vishnu Nair19479df2019-10-30 08:03:15 -0700380 static final int INVALID_PID = -1;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700381
Wale Ogunwale196db712019-12-27 15:35:39 +0000382 // How long we wait until giving up on the last activity to pause. This
383 // is short because it directly impacts the responsiveness of starting the
384 // next activity.
385 private static final int PAUSE_TIMEOUT = 500;
386
387 // Ticks during which we check progress while waiting for an app to launch.
388 private static final int LAUNCH_TICK = 500;
389
390 // How long we wait for the activity to tell us it has stopped before
391 // giving up. This is a good amount of time because we really need this
392 // from the application in order to get its saved state. Once the stop
393 // is complete we may start destroying client resources triggering
394 // crashes if the UI thread was hung. We put this timeout one second behind
395 // the ANR timeout so these situations will generate ANR instead of
396 // Surface lost or other errors.
397 private static final int STOP_TIMEOUT = 11 * 1000;
398
399 // How long we wait until giving up on an activity telling us it has
400 // finished destroying itself.
401 private static final int DESTROY_TIMEOUT = 10 * 1000;
402
Garfield Tane8d84ab2019-10-11 09:49:40 -0700403 final ActivityTaskManagerService mAtmService;
Andrii Kulianeceebbf2019-06-26 17:36:51 -0700404 final ActivityInfo info; // activity info provided by developer in AndroidManifest
Garfield Tane8d84ab2019-10-11 09:49:40 -0700405 // Non-null only for application tokens.
406 // TODO: rename to mActivityToken
407 final ActivityRecord.Token appToken;
408 // Which user is this running for?
409 final int mUserId;
410 // The package implementing intent's component
411 // TODO: rename to mPackageName
412 final String packageName;
413 // the intent component, or target of an alias.
414 final ComponentName mActivityComponent;
415 // Has a wallpaper window as a background.
416 // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
417 // mOccludesParent field.
418 final boolean hasWallpaper;
419 // Input application handle used by the input dispatcher.
420 final InputApplicationHandle mInputApplicationHandle;
421
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800422 final int launchedFromPid; // always the pid who started the activity.
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700423 final int launchedFromUid; // always the uid who started the activity.
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800424 final String launchedFromPackage; // always the package who started the activity.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 final Intent intent; // the original intent that generated us
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 final String shortComponentName; // the short component name of the intent
427 final String resolvedType; // as per original caller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 final String processName; // process where this component wants to run
429 final String taskAffinity; // as per ActivityInfo.taskAffinity
430 final boolean stateNotNeeded; // As per ActivityInfo.flags
Louis Changd58cb672018-12-24 17:45:16 +0800431 @VisibleForTesting
432 int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800433 private final boolean componentSpecified; // did caller specify an explicit component?
Dianne Hackbornfb81d092015-08-03 17:14:46 -0700434 final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?
Craig Mautner86d67a42013-05-14 10:34:38 -0700435
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800436 private CharSequence nonLocalizedLabel; // the label information from the package mgr.
437 private int labelRes; // the label information from the package mgr.
438 private int icon; // resource identifier of activity's icon.
439 private int logo; // resource identifier of activity's logo.
440 private int theme; // resource identifier of activity's theme.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800441 private int windowFlags; // custom window flags for preview window.
Louis Changcdec0802019-11-11 11:45:07 +0800442 private Task task; // the task this is in.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800443 private long createTime = System.currentTimeMillis();
Andrii Kulian86e70fc2019-02-12 11:04:10 +0000444 long lastVisibleTime; // last time this activity became visible
445 long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
446 long pauseTime; // last time we started pausing the activity
447 long launchTickTime; // base time for launch tick messages
448 long topResumedStateLossTime; // last time we reported top resumed state loss to an activity
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700449 // Last configuration reported to the activity in the client process.
450 private MergedConfiguration mLastReportedConfiguration;
Andrii Kulianb047b8b2017-02-08 18:38:26 -0800451 private int mLastReportedDisplayId;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200452 boolean mLastReportedMultiWindowMode;
453 boolean mLastReportedPictureInPictureMode;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -0700454 CompatibilityInfo compat;// last used compatibility mode
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700455 ActivityRecord resultTo; // who started this entry, so will get our reply
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 final String resultWho; // additional identifier for use by resultTo.
457 final int requestCode; // code given by requester (resultTo)
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800458 ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
Dianne Hackborn85d558c2014-11-04 10:31:54 -0800460 ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
Louis Chang746c2242019-10-08 16:30:44 +0800461 Intent mLastNewIntent; // the last new intent we delivered to client
Dianne Hackborn7a2195c2012-03-19 17:38:00 -0700462 ActivityOptions pendingOptions; // most recently given options
George Mount6ba042b2014-07-28 11:12:28 -0700463 ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
Dianne Hackbornb5a380d2015-05-20 18:18:46 -0700464 AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
Wale Ogunwalec4e63a42018-10-02 13:19:54 -0700465 ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
Dianne Hackborn7e269642010-08-25 19:50:20 -0700466 UriPermissionOwner uriPermissions; // current special URI access perms.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700467 WindowProcessController app; // if non-null, hosting application
Bryce Lee7ace3952018-02-16 14:34:32 -0800468 private ActivityState mState; // current state we are in
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700469 private Bundle mIcicle; // last saved activity state
470 private PersistableBundle mPersistentState; // last persistently saved activity state
471 private boolean mHaveState = true; // Indicates whether the last saved state of activity is
472 // preserved. This starts out 'true', since the initial state
473 // of an activity is that we have everything, and we should
474 // never consider it lacking in state to be removed if it
475 // dies. After an activity is launched it follows the value
476 // of #mIcicle.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 boolean launchFailed; // set if a launched failed, to abort on 2nd try
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 boolean stopped; // is activity pause finished?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700479 boolean delayedResume; // not yet resumed because of stopped app switches?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 boolean finishing; // activity in pending finish list?
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800481 boolean deferRelaunchUntilPaused; // relaunch of activity is being deferred until pause is
482 // completed
483 boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 int configChangeFlags; // which config values have changed
Wale Ogunwaleec950642017-04-25 07:44:21 -0700485 private boolean keysPaused; // has key dispatching been paused for it?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 int launchMode; // the launch mode activity attribute.
Charles He2bf28322017-10-12 22:24:49 +0100487 int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
Issei Suzukif2f6c912019-11-08 11:24:18 +0100488 private boolean mVisible; // Should this token's windows be visible?
Jorim Jaggi241ae102016-11-02 21:57:33 -0700489 boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
490 // might hide this activity?
Issei Suzukid4ee1cc2019-11-08 13:20:14 +0100491 // True if the visible state of this token was forced to true due to a transferred starting
Garfield Tane8d84ab2019-10-11 09:49:40 -0700492 // window.
Issei Suzukif2f6c912019-11-08 11:24:18 +0100493 private boolean mVisibleSetFromTransferredStartingWindow;
494 // TODO: figure out how to consolidate with the same variable in ActivityRecord.
Wale Ogunwaleec950642017-04-25 07:44:21 -0700495 private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
496 // process that it is hidden.
Issei Suzukid4ee1cc2019-11-08 13:20:14 +0100497 private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false
Garfield Tane8d84ab2019-10-11 09:49:40 -0700498 // and reporting to the client that it is hidden.
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800499 boolean sleeping; // have we told the activity to sleep?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 boolean nowVisible; // is this activity's window visible?
Vishnu Nair9ba31652018-11-13 14:34:05 -0800501 boolean mDrawn; // is this activity's window drawn?
Andrii Kuliana39ae3e2018-05-31 12:43:54 -0700502 boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 boolean idle; // has the activity gone idle?
504 boolean hasBeenLaunched;// has this activity ever been launched?
505 boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
Daniel Sandler69a48172010-06-23 16:29:36 -0400506 boolean immersive; // immersive mode (don't interrupt if possible)
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400507 boolean forceNewConfig; // force re-create with new config next time
Winson Chungf7e03e12017-08-22 11:32:16 -0700508 boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the
509 // activity can enter picture in picture while pausing (only when switching to another task)
Winson Chung709904f2017-04-25 11:00:48 -0700510 PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();
511 // The PiP params used when deferring the entering of picture-in-picture.
Dianne Hackborn07981492013-01-28 11:36:23 -0800512 int launchCount; // count of launches since last state
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800513 long lastLaunchTime; // time of last launch of this activity
Ruben Brunke24b9a62016-02-16 21:38:24 -0800514 ComponentName requestedVrComponent; // the requested component for handling VR mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200516 boolean inHistory; // are we in the history stack?
Craig Mautnerde4ef022013-04-07 19:01:33 -0700517 final ActivityStackSupervisor mStackSupervisor;
Louis Chang149d5c82019-12-30 09:47:39 +0800518 final RootWindowContainer mRootWindowContainer;
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800519
520 static final int STARTING_WINDOW_NOT_SHOWN = 0;
521 static final int STARTING_WINDOW_SHOWN = 1;
522 static final int STARTING_WINDOW_REMOVED = 2;
523 int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800524 private boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800525
Garfield Tan2746ab52018-07-25 12:33:01 -0700526 // Marking the reason why this activity is being relaunched. Mainly used to track that this
527 // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
528 // pre-NYC apps that don't have a sense of being resized.
529 int mRelaunchReason = RELAUNCH_REASON_NONE;
530
Craig Mautner21d24a22014-04-23 11:45:37 -0700531 TaskDescription taskDescription; // the recents information for this activity
Craig Mautner2fbd7542014-03-21 09:34:07 -0700532
Filip Gruszczynski23493322015-07-29 17:02:59 -0700533 // These configurations are collected from application's resources based on size-sensitive
534 // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
535 // and drawable-sw400dp will be added to both as 400.
536 private int[] mVerticalSizeConfigurations;
537 private int[] mHorizontalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -0700538 private int[] mSmallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -0700539
Riddle Hsu61987bc2019-04-03 13:08:47 +0800540 /**
541 * The precomputed display insets for resolving configuration. It will be non-null if
542 * {@link #shouldUseSizeCompatMode} returns {@code true}.
543 */
544 private CompatDisplayInsets mCompatDisplayInsets;
545
Amith Yamasani0af6fa72016-01-17 15:36:19 -0800546 boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session
547 IVoiceInteractionSession voiceSession; // Voice interaction session for this activity
548
Garfield Tane8d84ab2019-10-11 09:49:40 -0700549 boolean mVoiceInteraction;
550
551 private int mPendingRelaunchCount;
552
553 // True if we are current in the process of removing this app token from the display
554 private boolean mRemovingFromDisplay = false;
555
Garfield Tane8d84ab2019-10-11 09:49:40 -0700556 private RemoteAnimationDefinition mRemoteAnimationDefinition;
557
558 private AnimatingActivityRegistry mAnimatingActivityRegistry;
559
560 private Task mLastParent;
561
Issei Suzukid4ee1cc2019-11-08 13:20:14 +0100562 // Have we told the window clients to show themselves?
563 private boolean mClientVisible;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700564
565 boolean firstWindowDrawn;
566 // Last drawn state we reported to the app token.
567 private boolean reportedDrawn;
568 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
569 new WindowState.UpdateReportedVisibilityResults();
570
Issei Suzuki2bcbd682019-11-08 13:20:14 +0100571 boolean mUseTransferredAnimation;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700572
573 /**
574 * @see #currentLaunchCanTurnScreenOn()
575 */
576 private boolean mCurrentLaunchCanTurnScreenOn = true;
577
578 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -0700579 * This leash is used to "freeze" the app surface in place after the state change, but before
580 * the animation is ready to start.
581 */
582 private SurfaceControl mTransitChangeLeash = null;
583
584 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
585 private boolean mLastSurfaceShowing = true;
586
587 private Letterbox mLetterbox;
588
589 /**
590 * The activity is opaque and fills the entire space of this task.
591 * @see WindowContainer#fillsParent()
592 */
593 private boolean mOccludesParent;
594
595 // The input dispatching timeout for this application token in nanoseconds.
596 long mInputDispatchingTimeoutNanos;
597
598 private boolean mShowWhenLocked;
599 private boolean mInheritShownWhenLocked;
600 private boolean mTurnScreenOn;
601
602 /** Have we been asked to have this token keep the screen frozen? */
603 private boolean mFreezingScreen;
604
605 // These are used for determining when all windows associated with
606 // an activity have been drawn, so they can be made visible together
607 // at the same time.
608 // initialize so that it doesn't match mTransactionSequence which is an int.
609 private long mLastTransactionSequence = Long.MIN_VALUE;
610 private int mNumInterestingWindows;
611 private int mNumDrawnWindows;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700612 boolean allDrawn;
613 private boolean mLastAllDrawn;
614
615 private boolean mLastContainsShowWhenLockedWindow;
616 private boolean mLastContainsDismissKeyguardWindow;
617
618 /**
619 * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
620 * to help AR know that the app is in the process of closing but hasn't yet started closing on
621 * the WM side.
622 */
623 private boolean mWillCloseOrEnterPip;
624
625 /**
626 * The scale to fit at least one side of the activity to its parent. If the activity uses
627 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
628 */
629 private float mSizeCompatScale = 1f;
630 /**
631 * The bounds in global coordinates for activity in size compatibility mode.
632 * @see ActivityRecord#hasSizeCompatBounds()
633 */
634 private Rect mSizeCompatBounds;
635
636 // activity is not displayed?
637 // TODO: rename to mNoDisplay
638 @VisibleForTesting
639 boolean noDisplay;
640 boolean mShowForAllUsers;
641 // TODO: Make this final
642 int mTargetSdk;
643
Issei Suzuki1669ea42019-11-06 14:20:59 +0100644 // Is this window's surface needed? This is almost like visible, except
645 // it will sometimes be true a little earlier: when the activity record has
Garfield Tane8d84ab2019-10-11 09:49:40 -0700646 // been shown, but is still waiting for its app transition to execute
647 // before making its windows shown.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100648 boolean mVisibleRequested;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700649
650 // Last visibility state we reported to the app token.
651 boolean reportedVisible;
652
Garfield Tane8d84ab2019-10-11 09:49:40 -0700653 boolean mDisablePreviewScreenshots;
654
655 // Information about an application starting window if displayed.
656 // Note: these are de-referenced before the starting window animates away.
657 StartingData mStartingData;
658 WindowState startingWindow;
659 WindowManagerPolicy.StartingSurface startingSurface;
660 boolean startingDisplayed;
661 boolean startingMoved;
662
663 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
664 boolean mIsExiting;
665
Garfield Tane8d84ab2019-10-11 09:49:40 -0700666 boolean mEnteringAnimation;
667
668 boolean mAppStopped;
669 // A hint to override the window specified rotation animation, or -1 to use the window specified
670 // value. We use this so that we can select the right animation in the cases of starting
671 // windows, where the app hasn't had time to set a value on the window.
672 int mRotationAnimationHint = -1;
673
674 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
675 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
676
Garfield Tane8d84ab2019-10-11 09:49:40 -0700677 private AppSaturationInfo mLastAppSaturationInfo;
678
679 private final ColorDisplayService.ColorTransformController mColorTransformController =
680 (matrix, translation) -> mWmService.mH.post(() -> {
681 synchronized (mWmService.mGlobalLock) {
682 if (mLastAppSaturationInfo == null) {
683 mLastAppSaturationInfo = new AppSaturationInfo();
684 }
685
686 mLastAppSaturationInfo.setSaturation(matrix, translation);
687 updateColorTransform();
688 }
689 });
690
Andrii Kulian21713ac2016-10-12 22:05:05 -0700691 /**
Garfield Tan0443b372019-01-04 15:00:13 -0800692 * Current sequencing integer of the configuration, for skipping old activity configurations.
693 */
694 private int mConfigurationSeq;
695
696 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800697 * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}
Andrii Kulian21713ac2016-10-12 22:05:05 -0700698 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700699 private final Configuration mTmpConfig = new Configuration();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700700 private final Rect mTmpBounds = new Rect();
Andrii Kulian21713ac2016-10-12 22:05:05 -0700701
Sunny Goyald40c3452019-03-20 12:46:55 -0700702 // Token for targeting this activity for assist purposes.
703 final Binder assistToken = new Binder();
704
Wale Ogunwale196db712019-12-27 15:35:39 +0000705 private final Runnable mPauseTimeoutRunnable = new Runnable() {
706 @Override
707 public void run() {
708 // We don't at this point know if the activity is fullscreen,
709 // so we need to be conservative and assume it isn't.
710 Slog.w(TAG, "Activity pause timeout for " + ActivityRecord.this);
711 synchronized (mAtmService.mGlobalLock) {
712 if (hasProcess()) {
713 mAtmService.logAppTooSlow(app, pauseTime, "pausing " + ActivityRecord.this);
714 }
715 activityPaused(true);
716 }
717 }
718 };
719
720 private final Runnable mLaunchTickRunnable = new Runnable() {
721 @Override
722 public void run() {
723 synchronized (mAtmService.mGlobalLock) {
724 if (continueLaunchTicking()) {
725 mAtmService.logAppTooSlow(
726 app, launchTickTime, "launching " + ActivityRecord.this);
727 }
728 }
729 }
730 };
731
732 private final Runnable mDestroyTimeoutRunnable = new Runnable() {
733 @Override
734 public void run() {
735 synchronized (mAtmService.mGlobalLock) {
736 Slog.w(TAG, "Activity destroy timeout for " + ActivityRecord.this);
737 destroyed("destroyTimeout");
738 }
739 }
740 };
741
742 private final Runnable mStopTimeoutRunnable = new Runnable() {
743 @Override
744 public void run() {
745 synchronized (mAtmService.mGlobalLock) {
746 Slog.w(TAG, "Activity stop timeout for " + ActivityRecord.this);
747 if (isInHistory()) {
748 activityStopped(null /*icicle*/, null /*persistentState*/, null /*description*/);
749 }
750 }
751 }
752 };
753
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800754 private static String startingWindowStateToString(int state) {
755 switch (state) {
756 case STARTING_WINDOW_NOT_SHOWN:
757 return "STARTING_WINDOW_NOT_SHOWN";
758 case STARTING_WINDOW_SHOWN:
759 return "STARTING_WINDOW_SHOWN";
760 case STARTING_WINDOW_REMOVED:
761 return "STARTING_WINDOW_REMOVED";
762 default:
763 return "unknown state=" + state;
764 }
765 }
766
Garfield Tane8d84ab2019-10-11 09:49:40 -0700767 @Override
768 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700769 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700770 pw.print(prefix); pw.print("packageName="); pw.print(packageName);
771 pw.print(" processName="); pw.println(processName);
772 pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
Craig Mautnere11f2b72013-04-01 12:37:17 -0700773 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800774 pw.print(" userId="); pw.println(mUserId);
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800775 pw.print(prefix); pw.print("app="); pw.println(app);
Hui Yu6d5c3b92019-10-22 15:35:53 -0700776 pw.print(prefix); pw.println(intent.toInsecureString());
Andrii Kulian39f27442019-06-26 19:09:19 -0700777 pw.print(prefix); pw.print("rootOfTask="); pw.print(isRootOfTask());
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700778 pw.print(" task="); pw.println(task);
779 pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800780 pw.print(prefix); pw.print("mActivityComponent=");
781 pw.println(mActivityComponent.flattenToShortString());
Andrii Kulianeceebbf2019-06-26 17:36:51 -0700782 if (info != null && info.applicationInfo != null) {
783 final ApplicationInfo appInfo = info.applicationInfo;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700784 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
785 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
786 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
787 }
788 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800789 if (appInfo.splitSourceDirs != null) {
790 pw.print(prefix); pw.print("splitDir=");
791 pw.println(Arrays.toString(appInfo.splitSourceDirs));
792 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800793 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700794 pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
795 pw.print(" componentSpecified="); pw.print(componentSpecified);
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700796 pw.print(" mActivityType="); pw.println(
797 activityTypeToString(getActivityType()));
Dianne Hackbornfb81d092015-08-03 17:14:46 -0700798 if (rootVoiceInteraction) {
799 pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
800 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800801 pw.print(prefix); pw.print("compat="); pw.print(compat);
802 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
803 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
804 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700805 pw.println(prefix + "mLastReportedConfigurations:");
806 mLastReportedConfiguration.dump(pw, prefix + " ");
807
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700808 pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
Evan Roskydfe3da72018-10-26 17:21:06 -0700809 if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
810 pw.println(prefix + "RequestedOverrideConfiguration="
811 + getRequestedOverrideConfiguration());
812 }
813 if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
814 pw.println(prefix + "ResolvedOverrideConfiguration="
815 + getResolvedOverrideConfiguration());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700816 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800817 if (!matchParentBounds()) {
818 pw.println(prefix + "bounds=" + getBounds());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700819 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700820 if (resultTo != null || resultWho != null) {
821 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
822 pw.print(" resultWho="); pw.print(resultWho);
823 pw.print(" resultCode="); pw.println(requestCode);
824 }
Craig Mautner29c58ca2014-10-14 16:17:06 -0700825 if (taskDescription != null) {
826 final String iconFilename = taskDescription.getIconFilename();
827 if (iconFilename != null || taskDescription.getLabel() != null ||
828 taskDescription.getPrimaryColor() != 0) {
829 pw.print(prefix); pw.print("taskDescription:");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700830 pw.print(" label=\""); pw.print(taskDescription.getLabel());
831 pw.print("\"");
Matthew Ng54bc9422017-10-02 17:16:28 -0700832 pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
833 ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
834 : "null");
835 pw.print(" iconResource="); pw.print(taskDescription.getIconResource());
836 pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200837 pw.print(" primaryColor=");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700838 pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700839 pw.print(prefix + " backgroundColor=");
Riddle Hsud8bdc452019-12-06 21:36:32 +0800840 pw.print(Integer.toHexString(taskDescription.getBackgroundColor()));
841 pw.print(" statusBarColor=");
842 pw.print(Integer.toHexString(taskDescription.getStatusBarColor()));
843 pw.print(" navigationBarColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200844 pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
Craig Mautner29c58ca2014-10-14 16:17:06 -0700845 }
Craig Mautner648f69b2014-09-18 14:16:26 -0700846 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700847 if (results != null) {
848 pw.print(prefix); pw.print("results="); pw.println(results);
849 }
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700850 if (pendingResults != null && pendingResults.size() > 0) {
851 pw.print(prefix); pw.println("Pending Results:");
852 for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
853 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
854 pw.print(prefix); pw.print(" - ");
855 if (pir == null) {
856 pw.println("null");
857 } else {
858 pw.println(pir);
859 pir.dump(pw, prefix + " ");
860 }
861 }
862 }
863 if (newIntents != null && newIntents.size() > 0) {
864 pw.print(prefix); pw.println("Pending New Intents:");
865 for (int i=0; i<newIntents.size(); i++) {
Craig Mautnerd2328952013-03-05 12:46:26 -0800866 Intent intent = newIntents.get(i);
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700867 pw.print(prefix); pw.print(" - ");
868 if (intent == null) {
869 pw.println("null");
870 } else {
Hui Yu6d5c3b92019-10-22 15:35:53 -0700871 pw.println(intent.toShortString(false, true, false, false));
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700872 }
873 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700874 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700875 if (pendingOptions != null) {
876 pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
877 }
Dianne Hackbornb5a380d2015-05-20 18:18:46 -0700878 if (appTimeTracker != null) {
879 appTimeTracker.dumpWithHeader(pw, prefix, false);
880 }
Dianne Hackborn7e269642010-08-25 19:50:20 -0700881 if (uriPermissions != null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700882 uriPermissions.dump(pw, prefix);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700883 }
884 pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
Dianne Hackborn07981492013-01-28 11:36:23 -0800885 pw.print(" launchCount="); pw.print(launchCount);
886 pw.print(" lastLaunchTime=");
887 if (lastLaunchTime == 0) pw.print("0");
888 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
889 pw.println();
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700890 pw.print(prefix); pw.print("mHaveState="); pw.print(mHaveState);
891 pw.print(" mIcicle="); pw.println(mIcicle);
Bryce Lee7ace3952018-02-16 14:34:32 -0800892 pw.print(prefix); pw.print("state="); pw.print(mState);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700893 pw.print(" stopped="); pw.print(stopped);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700894 pw.print(" delayedResume="); pw.print(delayedResume);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700895 pw.print(" finishing="); pw.println(finishing);
896 pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
897 pw.print(" inHistory="); pw.print(inHistory);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800898 pw.print(" sleeping="); pw.print(sleeping);
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800899 pw.print(" idle="); pw.print(idle);
900 pw.print(" mStartingWindowState=");
901 pw.println(startingWindowStateToString(mStartingWindowState));
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800902 pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
Dianne Hackbornff801ec2011-01-22 18:05:38 -0800903 pw.print(" noDisplay="); pw.print(noDisplay);
904 pw.print(" immersive="); pw.print(immersive);
905 pw.print(" launchMode="); pw.println(launchMode);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800906 pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400907 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700908 pw.print(prefix); pw.print("mActivityType=");
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700909 pw.println(activityTypeToString(getActivityType()));
Ruben Brunke24b9a62016-02-16 21:38:24 -0800910 if (requestedVrComponent != null) {
911 pw.print(prefix);
912 pw.print("requestedVrComponent=");
913 pw.println(requestedVrComponent);
914 }
Garfield Tane8d84ab2019-10-11 09:49:40 -0700915 super.dump(pw, prefix, dumpAll);
Riddle Hsud8bdc452019-12-06 21:36:32 +0800916 if (mVoiceInteraction) {
917 pw.println(prefix + "mVoiceInteraction=true");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700918 }
Riddle Hsud8bdc452019-12-06 21:36:32 +0800919 pw.print(prefix); pw.print("mOccludesParent="); pw.print(mOccludesParent);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700920 pw.print(" mOrientation="); pw.println(mOrientation);
Issei Suzuki1669ea42019-11-06 14:20:59 +0100921 pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
Riddle Hsud8bdc452019-12-06 21:36:32 +0800922 + " mVisible=" + mVisible + " mClientVisible=" + mClientVisible
Garfield Tane8d84ab2019-10-11 09:49:40 -0700923 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
924 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
925 if (paused) {
926 pw.print(prefix); pw.print("paused="); pw.println(paused);
927 }
928 if (mAppStopped) {
929 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
930 }
931 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
932 || allDrawn || mLastAllDrawn) {
933 pw.print(prefix); pw.print("mNumInterestingWindows=");
934 pw.print(mNumInterestingWindows);
935 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700936 pw.print(" allDrawn="); pw.print(allDrawn);
937 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
938 pw.println(")");
939 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -0800940 if (mStartingData != null || firstWindowDrawn || mIsExiting) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700941 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700942 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
943 pw.print(" mIsExiting="); pw.println(mIsExiting);
944 }
945 if (startingWindow != null || startingSurface != null
Issei Suzukif2f6c912019-11-08 11:24:18 +0100946 || startingDisplayed || startingMoved || mVisibleSetFromTransferredStartingWindow) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700947 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
948 pw.print(" startingSurface="); pw.print(startingSurface);
949 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
950 pw.print(" startingMoved="); pw.print(startingMoved);
951 pw.println(" mHiddenSetFromTransferredStartingWindow="
Issei Suzukif2f6c912019-11-08 11:24:18 +0100952 + mVisibleSetFromTransferredStartingWindow);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700953 }
954 if (!mFrozenBounds.isEmpty()) {
955 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
956 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
957 }
958 if (mPendingRelaunchCount != 0) {
959 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
960 }
961 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
962 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
963 + mSizeCompatBounds);
964 }
965 if (mRemovingFromDisplay) {
966 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
967 }
Jorim Jaggi9b5e3312019-03-01 18:08:00 +0100968 if (lastVisibleTime != 0 || nowVisible) {
Riddle Hsud8bdc452019-12-06 21:36:32 +0800969 pw.print(prefix); pw.print("nowVisible="); pw.print(nowVisible);
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700970 pw.print(" lastVisibleTime=");
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700971 if (lastVisibleTime == 0) pw.print("0");
972 else TimeUtils.formatDuration(lastVisibleTime, now, pw);
973 pw.println();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700974 }
Wale Ogunwaleec950642017-04-25 07:44:21 -0700975 if (mDeferHidingClient) {
976 pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
977 }
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800978 if (deferRelaunchUntilPaused || configChangeFlags != 0) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700979 pw.print(prefix); pw.print("deferRelaunchUntilPaused=");
980 pw.print(deferRelaunchUntilPaused);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700981 pw.print(" configChangeFlags=");
982 pw.println(Integer.toHexString(configChangeFlags));
983 }
Wale Ogunwalec4e63a42018-10-02 13:19:54 -0700984 if (mServiceConnectionsHolder != null) {
985 pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700986 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -0800987 if (info != null) {
988 pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
Winson Chung609e1e92017-05-08 10:52:12 -0700989 pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode
990 + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700991 if (info.supportsPictureInPicture()) {
992 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
Winson Chungf7e03e12017-08-22 11:32:16 -0700993 pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
994 + supportsEnterPipOnTaskSwitch);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700995 }
996 if (info.maxAspectRatio != 0) {
997 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
998 }
Adrian Roos917791e2018-11-28 16:30:44 +0100999 if (info.minAspectRatio != 0) {
1000 pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
1001 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -08001002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 }
1004
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001005 void setAppTimeTracker(AppTimeTracker att) {
1006 appTimeTracker = att;
1007 }
1008
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07001009 /** Update the saved state of an activity. */
1010 void setSavedState(@Nullable Bundle savedState) {
1011 mIcicle = savedState;
1012 mHaveState = mIcicle != null;
1013 }
1014
1015 /**
1016 * Get the actual Bundle instance of the saved state.
1017 * @see #hasSavedState() for checking if the record has saved state.
1018 */
1019 @Nullable Bundle getSavedState() {
1020 return mIcicle;
1021 }
1022
1023 /**
1024 * Check if the activity has saved state.
1025 * @return {@code true} if the client reported a non-empty saved state from last onStop(), or
1026 * if this record was just created and the client is yet to be launched and resumed.
1027 */
1028 boolean hasSavedState() {
1029 return mHaveState;
1030 }
1031
1032 /** @return The actual PersistableBundle instance of the saved persistent state. */
1033 @Nullable PersistableBundle getPersistentSavedState() {
1034 return mPersistentState;
1035 }
1036
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -07001037 void updateApplicationInfo(ApplicationInfo aInfo) {
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -07001038 info.applicationInfo = aInfo;
1039 }
1040
Andrii Kulian21713ac2016-10-12 22:05:05 -07001041 private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001042 return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
1043 }
1044
Andrii Kulian21713ac2016-10-12 22:05:05 -07001045 private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001046 return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
1047 }
1048
Andrii Kulian21713ac2016-10-12 22:05:05 -07001049 private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001050 return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
1051 }
1052
Filip Gruszczynski23493322015-07-29 17:02:59 -07001053 /**
1054 * The purpose of this method is to decide whether the activity needs to be relaunched upon
1055 * changing its size. In most cases the activities don't need to be relaunched, if the resize
1056 * is small, all the activity content has to do is relayout itself within new bounds. There are
1057 * cases however, where the activity's content would be completely changed in the new size and
1058 * the full relaunch is required.
1059 *
1060 * The activity will report to us vertical and horizontal thresholds after which a relaunch is
1061 * required. These thresholds are collected from the application resource qualifiers. For
1062 * example, if application has layout-w600dp resource directory, then it needs a relaunch when
1063 * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
1064 * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
1065 * of the threshold.
1066 */
1067 private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
1068 int secondDp) {
1069 if (thresholds == null) {
1070 return false;
1071 }
1072 for (int i = thresholds.length - 1; i >= 0; i--) {
1073 final int threshold = thresholds[i];
1074 if ((firstDp < threshold && secondDp >= threshold)
1075 || (firstDp >= threshold && secondDp < threshold)) {
1076 return true;
1077 }
1078 }
1079 return false;
1080 }
1081
Andrii Kulian21713ac2016-10-12 22:05:05 -07001082 void setSizeConfigurations(int[] horizontalSizeConfiguration,
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001083 int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001084 mHorizontalSizeConfigurations = horizontalSizeConfiguration;
1085 mVerticalSizeConfigurations = verticalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001086 mSmallestSizeConfigurations = smallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -07001087 }
1088
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001089 private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001090 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001091 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
1092 "Can't report activity moved to display - client not running, activityRecord="
1093 + this + ", displayId=" + displayId);
Wale Ogunwale22e25262016-02-01 10:32:02 -08001094 return;
1095 }
1096 try {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001097 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
1098 "Reporting activity moved to display" + ", activityRecord=" + this
1099 + ", displayId=" + displayId + ", config=" + config);
Chong Zhang6be533e2016-06-17 16:24:21 -07001100
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001101 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001102 MoveToDisplayItem.obtain(displayId, config));
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001103 } catch (RemoteException e) {
1104 // If process died, whatever.
1105 }
1106 }
1107
1108 private void scheduleConfigurationChanged(Configuration config) {
Wale Ogunwalef6733932018-06-27 05:14:34 -07001109 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001110 if (DEBUG_CONFIGURATION) Slog.w(TAG,
1111 "Can't report activity configuration update - client not running"
1112 + ", activityRecord=" + this);
1113 return;
1114 }
1115 try {
1116 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
1117 + config);
1118
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001119 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001120 ActivityConfigurationChangeItem.obtain(config));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001121 } catch (RemoteException e) {
1122 // If process died, whatever.
1123 }
1124 }
1125
Louis Chang3b21bdc2019-03-25 15:49:14 +08001126 boolean scheduleTopResumedActivityChanged(boolean onTop) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001127 if (!attachedToProcess()) {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001128 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001129 Slog.w(TAG, "Can't report activity position update - client not running"
1130 + ", activityRecord=" + this);
1131 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001132 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001133 }
1134 try {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001135 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001136 Slog.v(TAG, "Sending position change to " + this + ", onTop: " + onTop);
1137 }
1138
1139 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1140 TopResumedActivityChangeItem.obtain(onTop));
1141 } catch (RemoteException e) {
1142 // If process died, whatever.
Louis Chang3b21bdc2019-03-25 15:49:14 +08001143 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001144 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001145 return true;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001146 }
1147
Winson Chung5af42fc2017-03-24 17:11:33 -07001148 void updateMultiWindowMode() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001149 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001150 return;
1151 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001152
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001153 if (task.getStack().deferScheduleMultiWindowModeChanged()) {
1154 // Don't do anything if we are currently deferring multi-window mode change.
1155 return;
1156 }
1157
Winson Chung5af42fc2017-03-24 17:11:33 -07001158 // An activity is considered to be in multi-window mode if its task isn't fullscreen.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001159 final boolean inMultiWindowMode = inMultiWindowMode();
Winson Chung609e1e92017-05-08 10:52:12 -07001160 if (inMultiWindowMode != mLastReportedMultiWindowMode) {
1161 mLastReportedMultiWindowMode = inMultiWindowMode;
Winson Chung5af42fc2017-03-24 17:11:33 -07001162 scheduleMultiWindowModeChanged(getConfiguration());
1163 }
1164 }
1165
1166 private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001167 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001168 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001169 MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001170 } catch (Exception e) {
1171 // If process died, I don't care.
1172 }
1173 }
1174
Winson Chungab76bbc2017-08-14 13:33:51 -07001175 void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001176 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001177 return;
1178 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001179
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001180 final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
Winson Chungab76bbc2017-08-14 13:33:51 -07001181 if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001182 // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
Winson Chung059955f2018-08-08 16:10:20 -07001183 // update that here in order. Set the last reported MW state to the same as the PiP
1184 // state since we haven't yet actually resized the task (these callbacks need to
1185 // preceed the configuration change from the resiez.
1186 // TODO(110009072): Once we move these callbacks to the client, remove all logic related
1187 // to forcing the update of the picture-in-picture mode as a part of the PiP animation.
Winson Chung609e1e92017-05-08 10:52:12 -07001188 mLastReportedPictureInPictureMode = inPictureInPictureMode;
Winson Chung059955f2018-08-08 16:10:20 -07001189 mLastReportedMultiWindowMode = inPictureInPictureMode;
Evan Rosky1ac84462018-11-13 11:25:30 -08001190 final Configuration newConfig = new Configuration();
1191 if (targetStackBounds != null && !targetStackBounds.isEmpty()) {
Evan Rosky730f6e82018-12-03 17:40:11 -08001192 newConfig.setTo(task.getRequestedOverrideConfiguration());
1193 Rect outBounds = newConfig.windowConfiguration.getBounds();
1194 task.adjustForMinimalTaskDimensions(outBounds, outBounds);
1195 task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration());
Evan Rosky1ac84462018-11-13 11:25:30 -08001196 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001197 schedulePictureInPictureModeChanged(newConfig);
1198 scheduleMultiWindowModeChanged(newConfig);
1199 }
1200 }
1201
1202 private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001203 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001204 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001205 PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
Andrii Kulian446e8242017-10-26 15:17:29 -07001206 overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001207 } catch (Exception e) {
1208 // If process died, no one cares.
Filip Gruszczynskica664812015-12-04 12:43:36 -08001209 }
1210 }
1211
Louis Changcdec0802019-11-11 11:45:07 +08001212 Task getTask() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001213 return task;
1214 }
1215
Bryce Leeaf691c02017-03-20 14:20:22 -07001216 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001217 * Sets the Task on this activity for the purposes of re-use during launch where we will
1218 * re-use another activity instead of this one for the launch.
chaviw4ad54912018-05-30 11:05:44 -07001219 */
Louis Changcdec0802019-11-11 11:45:07 +08001220 void setTaskForReuse(Task task) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001221 this.task = task;
chaviw4ad54912018-05-30 11:05:44 -07001222 }
1223
Louis Changdc077272019-11-12 16:52:56 +08001224 ActivityStack getStack() {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001225 return task != null ? task.getStack() : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001226 }
1227
1228 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001229 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +08001230 final Task oldTask = oldParent != null ? (Task) oldParent : null;
1231 final Task newTask = newParent != null ? (Task) newParent : null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001232 this.task = newTask;
1233
1234 super.onParentChanged(newParent, oldParent);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001235
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001236 if (isPersistable()) {
1237 if (oldTask != null) {
1238 mAtmService.notifyTaskPersisterLocked(oldTask, false);
1239 }
1240 if (newTask != null) {
1241 mAtmService.notifyTaskPersisterLocked(newTask, false);
1242 }
1243 }
1244
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001245 if (oldParent == null && newParent != null) {
1246 // First time we are adding the activity to the system.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001247 mVoiceInteraction = newTask.voiceSession != null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001248 mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
lumarkbde15132019-12-18 22:29:43 +08001249
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001250 // TODO(b/36505427): Maybe this call should be moved inside
1251 // updateOverrideConfiguration()
1252 newTask.updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001253 // Make sure override configuration is up-to-date before using to create window
1254 // controller.
1255 updateSizeCompatMode();
1256 // When an activity is started directly into a split-screen fullscreen stack, we need to
1257 // update the initial multi-window modes so that the callbacks are scheduled correctly
1258 // when the user leaves that mode.
1259 mLastReportedMultiWindowMode = inMultiWindowMode();
1260 mLastReportedPictureInPictureMode = inPinnedWindowingMode();
1261 }
1262
Garfield Tane8d84ab2019-10-11 09:49:40 -07001263 // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
1264 // access visual elements like the {@link DisplayContent}. We must remove any associations
1265 // such as animations.
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001266 if (task == null) {
1267 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1268 // from this list so we do not participate in any future animations.
1269 if (getDisplayContent() != null) {
1270 getDisplayContent().mClosingApps.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001271 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001272 } else if (mLastParent != null && mLastParent.getStack() != null) {
1273 task.getStack().mExitingActivities.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001274 }
Louis Changdc077272019-11-12 16:52:56 +08001275 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001276
1277 // If we reparent, make sure to remove ourselves from the old animation registry.
1278 if (mAnimatingActivityRegistry != null) {
1279 mAnimatingActivityRegistry.notifyFinished(this);
1280 }
1281 mAnimatingActivityRegistry = stack != null
1282 ? stack.getAnimatingActivityRegistry()
1283 : null;
1284
1285 mLastParent = task;
1286
1287 updateColorTransform();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001288
1289 final ActivityStack oldStack = (oldTask != null) ? oldTask.getStack() : null;
1290 final ActivityStack newStack = (newTask != null) ? newTask.getStack() : null;
1291 // Inform old stack (if present) of activity removal and new stack (if set) of activity
1292 // addition.
1293 if (oldStack != newStack) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001294 if (oldStack != null) {
1295 oldStack.onActivityRemovedFromStack(this);
1296 }
1297 if (newStack != null) {
1298 newStack.onActivityAddedToStack(this);
1299 }
1300 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001301 }
1302
1303 private void updateColorTransform() {
1304 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
1305 getPendingTransaction().setColorTransform(mSurfaceControl,
1306 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
1307 mWmService.scheduleAnimationLocked();
1308 }
1309 }
1310
1311 @Override
1312 void onDisplayChanged(DisplayContent dc) {
1313 DisplayContent prevDc = mDisplayContent;
1314 super.onDisplayChanged(dc);
1315 if (prevDc == null || prevDc == mDisplayContent) {
1316 return;
1317 }
1318
1319 if (prevDc.mOpeningApps.remove(this)) {
1320 // Transfer opening transition to new display.
1321 mDisplayContent.mOpeningApps.add(this);
1322 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1323 mDisplayContent.executeAppTransition();
1324 }
1325
1326 if (prevDc.mChangingApps.remove(this)) {
1327 // This gets called *after* the ActivityRecord has been reparented to the new display.
1328 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1329 // so this token is now "frozen" while waiting for the animation to start on prevDc
1330 // (which will be cancelled since the window is no-longer a child). However, since this
1331 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1332 // so we need to cancel the change transition here.
1333 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1334 }
1335 prevDc.mClosingApps.remove(this);
1336
1337 if (prevDc.mFocusedApp == this) {
1338 prevDc.setFocusedApp(null);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001339 if (dc.getTopMostActivity() == this) {
1340 dc.setFocusedApp(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001341 }
1342 }
1343
1344 if (mLetterbox != null) {
1345 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1346 }
1347 }
1348
1349 void layoutLetterbox(WindowState winHint) {
1350 final WindowState w = findMainWindow();
1351 if (w == null || winHint != null && w != winHint) {
1352 return;
1353 }
1354 final boolean surfaceReady = w.isDrawnLw() // Regular case
1355 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1356 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1357 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
1358 if (needsLetterbox) {
1359 if (mLetterbox == null) {
1360 mLetterbox = new Letterbox(() -> makeChildSurface(null),
1361 mWmService.mTransactionFactory);
1362 mLetterbox.attachInput(w);
1363 }
1364 getPosition(mTmpPoint);
1365 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1366 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1367 // is also applied to the task).
1368 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
Louis Changcdec0802019-11-11 11:45:07 +08001369 ? task.getDisplayedBounds() : getStack().getDisplayedBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001370 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
1371 } else if (mLetterbox != null) {
1372 mLetterbox.hide();
1373 }
1374 }
1375
1376 void updateLetterboxSurface(WindowState winHint) {
1377 final WindowState w = findMainWindow();
1378 if (w != winHint && winHint != null && w != null) {
1379 return;
1380 }
1381 layoutLetterbox(winHint);
1382 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1383 mLetterbox.applySurfaceChanges(getPendingTransaction());
1384 }
1385 }
1386
1387 Rect getLetterboxInsets() {
1388 if (mLetterbox != null) {
1389 return mLetterbox.getInsets();
1390 } else {
1391 return new Rect();
1392 }
1393 }
1394
1395 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
1396 void getLetterboxInnerBounds(Rect outBounds) {
1397 if (mLetterbox != null) {
1398 outBounds.set(mLetterbox.getInnerFrame());
1399 } else {
1400 outBounds.setEmpty();
1401 }
1402 }
1403
1404 /**
1405 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
1406 * the given {@code rect}.
1407 */
1408 boolean isLetterboxOverlappingWith(Rect rect) {
1409 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
1410 }
1411
Dianne Hackbornbe707852011-11-11 14:32:10 -08001412 static class Token extends IApplicationToken.Stub {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001413 private WeakReference<ActivityRecord> weakActivity;
Steven Timotiusaf03df62017-07-18 16:56:43 -07001414 private final String name;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001415 private final String tokenString;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001416
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001417 Token(Intent intent) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07001418 name = intent.getComponent().flattenToShortString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001419 tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
1420 }
1421
1422 private void attach(ActivityRecord activity) {
1423 if (weakActivity != null) {
1424 throw new IllegalStateException("Already attached..." + this);
1425 }
1426 weakActivity = new WeakReference<>(activity);
Wale Ogunwale7d701172015-03-11 15:36:30 -07001427 }
1428
Charles Chen69362cd2019-03-29 15:18:45 +08001429 private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001430 if (token == null) {
1431 return null;
1432 }
1433 ActivityRecord r = token.weakActivity.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001434 if (r == null || r.getActivityStack() == null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001435 return null;
1436 }
1437 return r;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001438 }
1439
Craig Mautnerde4ef022013-04-07 19:01:33 -07001440 @Override
Dianne Hackbornbe707852011-11-11 14:32:10 -08001441 public String toString() {
1442 StringBuilder sb = new StringBuilder(128);
1443 sb.append("Token{");
1444 sb.append(Integer.toHexString(System.identityHashCode(this)));
1445 sb.append(' ');
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001446 if (weakActivity != null) {
1447 sb.append(weakActivity.get());
1448 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001449 sb.append('}');
1450 return sb.toString();
1451 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07001452
1453 @Override
1454 public String getName() {
1455 return name;
1456 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001457 }
1458
Charles Chen69362cd2019-03-29 15:18:45 +08001459 static @Nullable ActivityRecord forTokenLocked(IBinder token) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001460 try {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001461 return Token.tokenToActivityRecordLocked((Token)token);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001462 } catch (ClassCastException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08001463 Slog.w(TAG, "Bad activity token: " + token, e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001464 return null;
1465 }
1466 }
1467
Riddle Hsuff9e8282019-04-24 23:55:11 +08001468 static boolean isResolverActivity(String className) {
1469 return ResolverActivity.class.getName().equals(className);
1470 }
1471
Louis Chang6a9be162019-07-15 10:41:32 +08001472 boolean isResolverOrDelegateActivity() {
1473 return isResolverActivity(mActivityComponent.getClassName()) || Objects.equals(
1474 mActivityComponent, mAtmService.mStackSupervisor.getSystemChooserActivity());
Craig Mautnerac6f8432013-07-17 13:24:59 -07001475 }
1476
Patrick Baumann31426b22018-05-21 13:46:40 -07001477 boolean isResolverOrChildActivity() {
1478 if (!"android".equals(packageName)) {
1479 return false;
1480 }
1481 try {
1482 return ResolverActivity.class.isAssignableFrom(
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001483 Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
Patrick Baumann31426b22018-05-21 13:46:40 -07001484 } catch (ClassNotFoundException e) {
1485 return false;
1486 }
1487 }
1488
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001489 ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
1490 int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent,
1491 String _resolvedType, ActivityInfo aInfo, Configuration _configuration,
1492 ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
1493 boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
1494 ActivityOptions options, ActivityRecord sourceRecord) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001495 super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
1496 null /* displayContent */, false /* ownerCanManageAppTokens */);
1497
1498 mAtmService = _service;
1499 appToken = (Token) token;
1500 info = aInfo;
1501 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1502 packageName = info.applicationInfo.packageName;
1503 mInputApplicationHandle = new InputApplicationHandle(appToken);
1504 intent = _intent;
1505
1506 // If the class name in the intent doesn't match that of the target, this is probably an
1507 // alias. We have to create a new ComponentName object to keep track of the real activity
1508 // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
1509 if (info.targetActivity == null
1510 || (info.targetActivity.equals(intent.getComponent().getClassName())
1511 && (info.launchMode == LAUNCH_MULTIPLE
1512 || info.launchMode == LAUNCH_SINGLE_TOP))) {
1513 mActivityComponent = intent.getComponent();
1514 } else {
1515 mActivityComponent =
1516 new ComponentName(info.packageName, info.targetActivity);
1517 }
1518
1519 mTargetSdk = info.applicationInfo.targetSdkVersion;
1520 mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
1521 setOrientation(info.screenOrientation);
1522 mRotationAnimationHint = info.rotationAnimation;
1523
1524 mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
1525 mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
1526 mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
1527
1528 int realTheme = info.getThemeResource();
1529 if (realTheme == Resources.ID_NULL) {
1530 realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
1531 ? android.R.style.Theme : android.R.style.Theme_Holo;
1532 }
1533
1534 final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
1535 realTheme, com.android.internal.R.styleable.Window, mUserId);
1536
1537 if (ent != null) {
1538 mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
1539 hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
1540 noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
1541 } else {
1542 hasWallpaper = false;
1543 noDisplay = false;
1544 }
1545
1546 if (options != null) {
1547 mLaunchTaskBehind = options.getLaunchTaskBehind();
1548
1549 final int rotationAnimation = options.getRotationAnimationHint();
1550 // Only override manifest supplied option if set.
1551 if (rotationAnimation >= 0) {
1552 mRotationAnimationHint = rotationAnimation;
1553 }
1554 }
1555
1556 // Application tokens start out hidden.
Issei Suzukif2f6c912019-11-08 11:24:18 +01001557 setVisible(false);
Issei Suzuki1669ea42019-11-06 14:20:59 +01001558 mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001559
1560 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
1561 ColorDisplayService.ColorDisplayServiceInternal.class);
1562 cds.attachColorTransformController(packageName, mUserId,
1563 new WeakReference<>(mColorTransformController));
1564
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001565 appToken.attach(this);
1566
Louis Chang149d5c82019-12-30 09:47:39 +08001567 mRootWindowContainer = _service.mRootWindowContainer;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001568 launchedFromPid = _launchedFromPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 launchedFromUid = _launchedFromUid;
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001570 launchedFromPackage = _launchedFromPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 shortComponentName = _intent.getComponent().flattenToShortString();
1572 resolvedType = _resolvedType;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001573 componentSpecified = _componentSpecified;
Dianne Hackbornfb81d092015-08-03 17:14:46 -07001574 rootVoiceInteraction = _rootVoiceInteraction;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07001575 mLastReportedConfiguration = new MergedConfiguration(_configuration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 resultTo = _resultTo;
1577 resultWho = _resultWho;
1578 requestCode = _reqCode;
Bryce Lee7ace3952018-02-16 14:34:32 -08001579 setState(INITIALIZING, "ActivityRecord ctor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 launchFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 stopped = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001582 delayedResume = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 finishing = false;
Wale Ogunwalef81c1d12016-01-12 12:20:18 -08001584 deferRelaunchUntilPaused = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 keysPaused = false;
1586 inHistory = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 nowVisible = false;
Vishnu Nair9ba31652018-11-13 14:34:05 -08001588 mDrawn = false;
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01001589 mClientVisible = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 idle = false;
1591 hasBeenLaunched = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001592 mStackSupervisor = supervisor;
Robert Carr0f5d7532016-10-17 16:39:17 -07001593
Charles Chenf365d3a2019-11-14 17:22:05 +08001594 // b/35954083: Limit task affinity to uid to avoid various issues associated with sharing
1595 // affinity across uids.
1596 final String uid = Integer.toString(info.applicationInfo.uid);
1597 if (info.taskAffinity != null && !info.taskAffinity.startsWith(uid)) {
1598 info.taskAffinity = uid + ":" + info.taskAffinity;
1599 }
1600 taskAffinity = info.taskAffinity;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001601 stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001602 nonLocalizedLabel = aInfo.nonLocalizedLabel;
1603 labelRes = aInfo.labelRes;
1604 if (nonLocalizedLabel == null && labelRes == 0) {
1605 ApplicationInfo app = aInfo.applicationInfo;
1606 nonLocalizedLabel = app.nonLocalizedLabel;
1607 labelRes = app.labelRes;
1608 }
1609 icon = aInfo.getIconResource();
1610 logo = aInfo.getLogoResource();
1611 theme = aInfo.getThemeResource();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001612 if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
1613 windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
1614 }
1615 if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
1616 && (aInfo.applicationInfo.uid == SYSTEM_UID
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001617 || aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
1618 processName = _caller.mName;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001619 } else {
1620 processName = aInfo.processName;
1621 }
1622
1623 if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
1624 intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1625 }
1626
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001627 launchMode = aInfo.launchMode;
1628
Winson Chung83471632016-12-13 11:02:12 -08001629 setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001630
1631 immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
1632
1633 requestedVrComponent = (aInfo.requestedVrComponent == null) ?
1634 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
chaviw59b98852017-06-13 12:05:44 -07001635
Charles He2bf28322017-10-12 22:24:49 +01001636 lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
Andrii Kulianeceebbf2019-06-26 17:36:51 -07001637 if (info.applicationInfo.isPrivilegedApp()
1638 && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
Charles He2bf28322017-10-12 22:24:49 +01001639 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1640 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1641 }
1642
1643 if (options != null) {
1644 pendingOptions = options;
Charles He2bf28322017-10-12 22:24:49 +01001645 final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
1646 if (usageReport != null) {
1647 appTimeTracker = new AppTimeTracker(usageReport);
1648 }
1649 final boolean useLockTask = pendingOptions.getLockTaskMode();
1650 if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
1651 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
1652 }
Louis Changd58cb672018-12-24 17:45:16 +08001653 // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
1654 mHandoverLaunchDisplayId = options.getLaunchDisplayId();
Charles He2bf28322017-10-12 22:24:49 +01001655 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001656 }
1657
Garfield Tane8d84ab2019-10-11 09:49:40 -07001658 @Override
1659 ActivityRecord asActivityRecord() {
1660 // I am an activity record!
1661 return this;
1662 }
1663
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001664 @Override
1665 boolean hasActivity() {
1666 // I am an activity!
1667 return true;
1668 }
1669
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001670 void setProcess(WindowProcessController proc) {
Dianne Hackborn68a06332017-11-15 17:54:18 -08001671 app = proc;
1672 final ActivityRecord root = task != null ? task.getRootActivity() : null;
1673 if (root == this) {
1674 task.setRootProcess(proc);
1675 }
1676 }
1677
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001678 boolean hasProcess() {
1679 return app != null;
1680 }
1681
1682 boolean attachedToProcess() {
1683 return hasProcess() && app.hasThread();
1684 }
1685
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001686 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1687 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1688 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1689 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001690 // If the display is frozen, we won't do anything until the actual window is
1691 // displayed so there is no reason to put in the starting window.
1692 if (!okToDisplay()) {
Yunfan Chen48c0ed082018-12-05 18:15:35 -08001693 return false;
1694 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001695
1696 if (mStartingData != null) {
1697 return false;
1698 }
1699
1700 final WindowState mainWin = findMainWindow();
1701 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
1702 // App already has a visible window...why would you want a starting window?
1703 return false;
1704 }
1705
1706 final ActivityManager.TaskSnapshot snapshot =
Louis Changcdec0802019-11-11 11:45:07 +08001707 mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
Garfield Tane8d84ab2019-10-11 09:49:40 -07001708 false /* restoreFromDisk */, false /* reducedResolution */);
1709 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
1710 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
1711
1712 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
Riddle Hsu440f88b2019-11-06 22:17:35 +08001713 if (isActivityTypeHome()) {
1714 // The snapshot of home is only used once because it won't be updated while screen
1715 // is on (see {@link TaskSnapshotController#screenTurningOff}).
1716 mWmService.mTaskSnapshotController.removeSnapshotCache(task.mTaskId);
1717 // TODO(b/9684093): Use more general condition to specify the case.
1718 if (mDisplayContent.mAppTransition
1719 .getAppTransition() != WindowManager.TRANSIT_KEYGUARD_GOING_AWAY) {
1720 // Only use snapshot of home as starting window when unlocking.
1721 return false;
1722 }
1723 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001724 return createSnapshot(snapshot);
1725 }
1726
1727 // If this is a translucent window, then don't show a starting window -- the current
1728 // effect (a full-screen opaque starting window that fades away to the real contents
1729 // when it is ready) does not work for this.
1730 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
1731 if (theme != 0) {
1732 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
1733 com.android.internal.R.styleable.Window,
1734 mWmService.mCurrentUserId);
1735 if (ent == null) {
1736 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
1737 // see that.
1738 return false;
1739 }
1740 final boolean windowIsTranslucent = ent.array.getBoolean(
1741 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
1742 final boolean windowIsFloating = ent.array.getBoolean(
1743 com.android.internal.R.styleable.Window_windowIsFloating, false);
1744 final boolean windowShowWallpaper = ent.array.getBoolean(
1745 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
1746 final boolean windowDisableStarting = ent.array.getBoolean(
1747 com.android.internal.R.styleable.Window_windowDisablePreview, false);
1748 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
1749 windowIsTranslucent, windowIsFloating, windowShowWallpaper);
1750 if (windowIsTranslucent) {
1751 return false;
1752 }
1753 if (windowIsFloating || windowDisableStarting) {
1754 return false;
1755 }
1756 if (windowShowWallpaper) {
1757 if (getDisplayContent().mWallpaperController
1758 .getWallpaperTarget() == null) {
1759 // If this theme is requesting a wallpaper, and the wallpaper
1760 // is not currently visible, then this effectively serves as
1761 // an opaque window and our starting window transition animation
1762 // can still work. We just need to make sure the starting window
1763 // is also showing the wallpaper.
1764 windowFlags |= FLAG_SHOW_WALLPAPER;
1765 } else {
1766 return false;
1767 }
1768 }
1769 }
1770
1771 if (transferStartingWindow(transferFrom)) {
1772 return true;
1773 }
1774
1775 // There is no existing starting window, and we don't want to create a splash screen, so
1776 // that's it!
1777 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
1778 return false;
1779 }
1780
1781 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
1782 mStartingData = new SplashScreenStartingData(mWmService, pkg,
1783 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
1784 getMergedOverrideConfiguration());
1785 scheduleAddStartingWindow();
1786 return true;
1787 }
1788
1789 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
1790 if (snapshot == null) {
1791 return false;
1792 }
1793
1794 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
1795 mStartingData = new SnapshotStartingData(mWmService, snapshot);
1796 scheduleAddStartingWindow();
1797 return true;
1798 }
1799
1800 void scheduleAddStartingWindow() {
1801 // Note: we really want to do sendMessageAtFrontOfQueue() because we
1802 // want to process the message ASAP, before any other queued
1803 // messages.
1804 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
1805 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
1806 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
1807 }
1808 }
1809
1810 private class AddStartingWindow implements Runnable {
1811
1812 @Override
1813 public void run() {
1814 // Can be accessed without holding the global lock
1815 final StartingData startingData;
1816 synchronized (mWmService.mGlobalLock) {
1817 // There can only be one adding request, silly caller!
1818 mWmService.mAnimationHandler.removeCallbacks(this);
1819
1820 if (mStartingData == null) {
1821 // Animation has been canceled... do nothing.
1822 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1823 "startingData was nulled out before handling"
1824 + " mAddStartingWindow: %s", ActivityRecord.this);
1825 return;
1826 }
1827 startingData = mStartingData;
1828 }
1829
1830 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
1831 this, startingData);
1832
1833
1834 WindowManagerPolicy.StartingSurface surface = null;
1835 try {
1836 surface = startingData.createStartingSurface(ActivityRecord.this);
1837 } catch (Exception e) {
1838 Slog.w(TAG, "Exception when adding starting window", e);
1839 }
1840 if (surface != null) {
1841 boolean abort = false;
1842 synchronized (mWmService.mGlobalLock) {
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08001843 // If the window was successfully added, then we need to remove it.
1844 if (mStartingData == null) {
1845 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Aborted starting %s: startingData=%s",
1846 ActivityRecord.this, mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001847
1848 startingWindow = null;
1849 mStartingData = null;
1850 abort = true;
1851 } else {
1852 startingSurface = surface;
1853 }
1854 if (!abort) {
1855 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1856 "Added starting %s: startingWindow=%s startingView=%s",
1857 ActivityRecord.this, startingWindow, startingSurface);
1858 }
1859 }
1860 if (abort) {
1861 surface.remove();
1862 }
1863 } else {
1864 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
1865 ActivityRecord.this);
1866 }
1867 }
1868 }
1869
1870 private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
1871
1872 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
1873 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
1874 ActivityManager.TaskSnapshot snapshot) {
1875 if (getDisplayContent().mAppTransition.getAppTransition()
1876 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
1877 // TODO(b/34099271): Remove this statement to add back the starting window and figure
1878 // out why it causes flickering, the starting window appears over the thumbnail while
1879 // the docked from recents transition occurs
1880 return STARTING_WINDOW_TYPE_NONE;
1881 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
1882 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1883 } else if (taskSwitch && allowTaskSnapshot) {
Jorim Jaggi5cb681b2019-12-20 11:36:30 +00001884 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
Garfield Tane8d84ab2019-10-11 09:49:40 -07001885 : snapshotOrientationSameAsTask(snapshot) || fromRecents
1886 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1887 } else {
1888 return STARTING_WINDOW_TYPE_NONE;
1889 }
1890 }
1891
1892 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
1893 if (snapshot == null) {
1894 return false;
1895 }
Louis Changcdec0802019-11-11 11:45:07 +08001896 return task.getConfiguration().orientation == snapshot.getOrientation();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001897 }
1898
1899 void removeStartingWindow() {
1900 if (startingWindow == null) {
1901 if (mStartingData != null) {
1902 // Starting window has not been added yet, but it is scheduled to be added.
1903 // Go ahead and cancel the request.
1904 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
1905 mStartingData = null;
1906 }
1907 return;
1908 }
1909
1910 final WindowManagerPolicy.StartingSurface surface;
1911 if (mStartingData != null) {
1912 surface = startingSurface;
1913 mStartingData = null;
1914 startingSurface = null;
1915 startingWindow = null;
1916 startingDisplayed = false;
1917 if (surface == null) {
1918 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1919 "startingWindow was set but startingSurface==null, couldn't "
1920 + "remove");
1921
1922 return;
1923 }
1924 } else {
1925 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1926 "Tried to remove starting window but startingWindow was null: %s",
1927 this);
1928 return;
1929 }
1930
1931 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
1932 + " startingView=%s Callers=%s",
1933 this, startingWindow, startingSurface, Debug.getCallers(5));
1934
1935
1936 // Use the same thread to remove the window as we used to add it, as otherwise we end up
1937 // with things in the view hierarchy being called from different threads.
1938 mWmService.mAnimationHandler.post(() -> {
1939 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
1940 try {
1941 surface.remove();
1942 } catch (Exception e) {
1943 Slog.w(TAG_WM, "Exception when removing starting window", e);
1944 }
1945 });
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001946 }
1947
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001948 private void removeAppTokenFromDisplay() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001949 if (mWmService.mRoot == null) return;
Yunfan Chend4ef3012018-11-28 21:14:32 -08001950
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001951 final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001952 if (dc == null) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001953 Slog.w(TAG, "removeAppTokenFromDisplay: Attempted to remove token: "
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001954 + appToken + " from non-existing displayId=" + getDisplayId());
Bryce Lee7ace3952018-02-16 14:34:32 -08001955 return;
1956 }
Wale Ogunwalecc367f42017-02-01 08:12:14 -08001957 // Resume key dispatching if it is currently paused before we remove the container.
1958 resumeKeyDispatchingLocked();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001959 dc.removeAppToken(appToken.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 }
1961
Winson Chung30480042017-01-26 10:55:34 -08001962 /**
1963 * Reparents this activity into {@param newTask} at the provided {@param position}. The caller
1964 * should ensure that the {@param newTask} is not already the parent of this activity.
1965 */
Louis Changcdec0802019-11-11 11:45:07 +08001966 void reparent(Task newTask, int position, String reason) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001967 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001968 Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
1969 return;
1970 }
Louis Changcdec0802019-11-11 11:45:07 +08001971 final Task prevTask = task;
Winson Chung30480042017-01-26 10:55:34 -08001972 if (prevTask == newTask) {
1973 throw new IllegalArgumentException(reason + ": task=" + newTask
1974 + " is already the parent of r=" + this);
1975 }
1976
Winson Chung74666102017-02-22 17:49:24 -08001977 // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
1978 // the stacks in strange states. For now, we should use Task.reparent() to ensure that
1979 // the stack is left in an OK state.
1980 if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
1981 throw new IllegalArgumentException(reason + ": task=" + newTask
1982 + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
1983 + " r=" + this + " (" + prevTask.getStackId() + ")");
1984 }
1985
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001986 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
Garfield Tane8d84ab2019-10-11 09:49:40 -07001987 + " to task=%d at %d", this, task.mTaskId, position);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001988 reparent(newTask, position);
Winson Chung30480042017-01-26 10:55:34 -08001989 }
1990
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001991 private boolean isHomeIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07001992 return ACTION_MAIN.equals(intent.getAction())
Chilun2ef71f72018-11-16 17:57:15 +08001993 && (intent.hasCategory(CATEGORY_HOME)
1994 || intent.hasCategory(CATEGORY_SECONDARY_HOME))
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001995 && intent.getCategories().size() == 1
1996 && intent.getData() == null
1997 && intent.getType() == null;
1998 }
1999
Chong Zhangad24f962016-08-25 12:12:33 -07002000 static boolean isMainIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07002001 return ACTION_MAIN.equals(intent.getAction())
2002 && intent.hasCategory(CATEGORY_LAUNCHER)
Chong Zhangad24f962016-08-25 12:12:33 -07002003 && intent.getCategories().size() == 1
2004 && intent.getData() == null
2005 && intent.getType() == null;
2006 }
2007
Louis Chang6a9be162019-07-15 10:41:32 +08002008 @VisibleForTesting
2009 boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002010 if (uid == Process.myUid() || uid == 0) {
2011 // System process can launch home activity.
2012 return true;
2013 }
Winson Chung547afd22018-05-17 16:03:25 -07002014 // Allow the recents component to launch the home activity.
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07002015 final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
Winson Chung547afd22018-05-17 16:03:25 -07002016 if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
2017 return true;
2018 }
Louis Chang6a9be162019-07-15 10:41:32 +08002019 // Resolver or system chooser activity can launch home activity.
2020 return sourceRecord != null && sourceRecord.isResolverOrDelegateActivity();
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002021 }
2022
Winson Chung83471632016-12-13 11:02:12 -08002023 /**
2024 * @return whether the given package name can launch an assist activity.
2025 */
2026 private boolean canLaunchAssistActivity(String packageName) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002027 final ComponentName assistComponent =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002028 mAtmService.mActiveVoiceInteractionServiceComponent;
Winson Chung83471632016-12-13 11:02:12 -08002029 if (assistComponent != null) {
2030 return assistComponent.getPackageName().equals(packageName);
2031 }
2032 return false;
2033 }
2034
2035 private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
2036 ActivityOptions options, ActivityRecord sourceRecord) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002037 int activityType = ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002038 if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
Louis Chang6a9be162019-07-15 10:41:32 +08002039 && isHomeIntent(intent) && !isResolverOrDelegateActivity()) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002040 // This sure looks like a home activity!
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002041 activityType = ACTIVITY_TYPE_HOME;
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002042
2043 if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
2044 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
2045 // We only allow home activities to be resizeable if they explicitly requested it.
2046 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
2047 }
Andrii Kulian3b3fb662019-06-26 17:52:26 -07002048 } else if (mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07002049 info.applicationInfo.uid)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002050 activityType = ACTIVITY_TYPE_RECENTS;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07002051 } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
Winson Chung83471632016-12-13 11:02:12 -08002052 && canLaunchAssistActivity(launchedFromPackage)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002053 activityType = ACTIVITY_TYPE_ASSISTANT;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002054 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002055 setActivityType(activityType);
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002056 }
2057
Louis Changcdec0802019-11-11 11:45:07 +08002058 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002059 if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
Craig Mautnera228ae92014-07-09 05:44:55 -07002060 task.setTaskToAffiliateWith(taskToAffiliateWith);
2061 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002062 }
2063
Andrii Kulian02b7a832016-10-06 23:11:56 -07002064 /**
2065 * @return Stack value from current task, null if there is no task.
2066 */
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07002067 ActivityStack getActivityStack() {
2068 return task != null ? task.getStack() : null;
Andrii Kulian02b7a832016-10-06 23:11:56 -07002069 }
2070
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02002071 int getStackId() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002072 return getActivityStack() != null ? getActivityStack().mStackId : INVALID_STACK_ID;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08002073 }
2074
Louis Chang677921f2019-12-06 16:44:24 +08002075 DisplayContent getDisplay() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002076 final ActivityStack stack = getActivityStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002077 return stack != null ? stack.getDisplay() : null;
2078 }
2079
Garfield Tane8d84ab2019-10-11 09:49:40 -07002080 @Override
2081 boolean fillsParent() {
2082 return occludesParent();
2083 }
2084
2085 /** Returns true if this activity is opaque and fills the entire space of this task. */
2086 boolean occludesParent() {
2087 return mOccludesParent;
2088 }
2089
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002090 boolean setOccludesParent(boolean occludesParent) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002091 final boolean changed = occludesParent != mOccludesParent;
2092 mOccludesParent = occludesParent;
2093 setMainWindowOpaque(occludesParent);
2094 mWmService.mWindowPlacerLocked.requestTraversal();
2095
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08002096 if (changed && task != null && !occludesParent) {
2097 getActivityStack().convertActivityToTranslucent(this);
Riddle Hsued5789b2019-08-21 15:12:03 +08002098 }
2099 // Always ensure visibility if this activity doesn't occlude parent, so the
2100 // {@link #returningOptions} of the activity under this one can be applied in
2101 // {@link #handleAlreadyVisible()}.
2102 if (changed || !occludesParent) {
Louis Chang149d5c82019-12-30 09:47:39 +08002103 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Craig Mautner5eda9b32013-07-02 11:58:16 -07002104 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002105 return changed;
Craig Mautner4addfc52013-06-25 08:05:45 -07002106 }
2107
Garfield Tane8d84ab2019-10-11 09:49:40 -07002108 void setMainWindowOpaque(boolean isOpaque) {
2109 final WindowState win = findMainWindow();
2110 if (win == null) {
2111 return;
2112 }
2113 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2114 win.mWinAnimator.setOpaqueLocked(isOpaque);
2115 }
2116
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002117 void takeFromHistory() {
2118 if (inHistory) {
2119 inHistory = false;
2120 if (task != null && !finishing) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002121 task = null;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002122 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -07002123 clearOptionsLocked();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002124 }
2125 }
2126
2127 boolean isInHistory() {
2128 return inHistory;
2129 }
2130
Wale Ogunwale7d701172015-03-11 15:36:30 -07002131 boolean isInStackLocked() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002132 final ActivityStack stack = getActivityStack();
Andrii Kulian02b7a832016-10-06 23:11:56 -07002133 return stack != null && stack.isInStackLocked(this) != null;
Wale Ogunwale7d701172015-03-11 15:36:30 -07002134 }
2135
Craig Mautner21d24a22014-04-23 11:45:37 -07002136 boolean isPersistable() {
Ruben Brunkf53497c2017-03-27 20:26:17 -07002137 return (info.persistableMode == PERSIST_ROOT_ONLY ||
2138 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002139 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
Craig Mautner21d24a22014-04-23 11:45:37 -07002140 }
2141
Wale Ogunwale4cea0f52015-12-25 06:30:31 -08002142 boolean isFocusable() {
Louis Chang149d5c82019-12-30 09:47:39 +08002143 return mRootWindowContainer.isFocusable(this, isAlwaysFocusable());
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002144 }
2145
2146 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08002147 return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002148 }
2149
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07002150 /** @return whether this activity is non-resizeable or forced to be resizeable */
2151 boolean isNonResizableOrForcedResizable(int windowingMode) {
2152 if (windowingMode == WINDOWING_MODE_PINNED && info.supportsPictureInPicture()) {
2153 return false;
2154 }
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002155 return info.resizeMode != RESIZE_MODE_RESIZEABLE
Wale Ogunwale72a73e32016-10-13 12:16:39 -07002156 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Jorim Jaggicd13d332016-04-27 15:40:20 -07002157 }
2158
Winson Chunge6308042016-10-31 09:24:01 -07002159 /**
Winson Chungd3395382016-12-13 11:49:09 -08002160 * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
Winson Chunge6308042016-10-31 09:24:01 -07002161 */
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002162 boolean supportsPictureInPicture() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002163 return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
Winson Chungd3395382016-12-13 11:49:09 -08002164 && info.supportsPictureInPicture();
2165 }
2166
2167 /**
2168 * @return whether this activity supports split-screen multi-window and can be put in the docked
2169 * stack.
2170 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002171 @Override
2172 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08002173 // An activity can not be docked even if it is considered resizeable because it only
2174 // supports picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002175 return super.supportsSplitScreenWindowingMode()
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002176 && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002177 }
2178
2179 /**
2180 * @return whether this activity supports freeform multi-window and can be put in the freeform
2181 * stack.
2182 */
2183 boolean supportsFreeform() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002184 return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002185 }
2186
2187 /**
2188 * @return whether this activity supports non-PiP multi-window.
2189 */
2190 private boolean supportsResizeableMultiWindow() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002191 return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
Winson Chungd3395382016-12-13 11:49:09 -08002192 && (ActivityInfo.isResizeableMode(info.resizeMode)
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002193 || mAtmService.mForceResizableActivities);
Wale Ogunwaled26176f2016-01-25 20:04:04 -08002194 }
2195
Winson Chunge6308042016-10-31 09:24:01 -07002196 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002197 * Check whether this activity can be launched on the specified display.
Riddle Hsu16567132018-08-16 21:37:47 +08002198 *
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002199 * @param displayId Target display id.
Riddle Hsu16567132018-08-16 21:37:47 +08002200 * @return {@code true} if either it is the default display or this activity can be put on a
2201 * secondary screen.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002202 */
2203 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002204 return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
Riddle Hsu16567132018-08-16 21:37:47 +08002205 launchedFromUid, info);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002206 }
2207
2208 /**
Robert Carrc33658e2017-04-11 18:24:20 -07002209 * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
2210 * the activity has requested to enter PiP when it would otherwise be stopped.
2211 *
Winson Chung298f95b2017-08-10 15:57:18 -07002212 * @return whether this activity is currently allowed to enter PIP.
Winson Chunge6308042016-10-31 09:24:01 -07002213 */
Winson Chung298f95b2017-08-10 15:57:18 -07002214 boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
Wale Ogunwaleb9a0c992017-04-18 07:25:20 -07002215 if (!supportsPictureInPicture()) {
2216 return false;
2217 }
2218
Winson Chungf4ac0632017-03-17 12:34:12 -07002219 // Check app-ops and see if PiP is supported for this package
2220 if (!checkEnterPictureInPictureAppOpsState()) {
2221 return false;
2222 }
2223
Winson Chungf1bfee12017-03-24 17:11:33 -07002224 // Check to see if we are in VR mode, and disallow PiP if so
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002225 if (mAtmService.shouldDisableNonVrUiLocked()) {
Winson Chungf1bfee12017-03-24 17:11:33 -07002226 return false;
2227 }
2228
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002229 boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002230 boolean isCurrentAppLocked =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002231 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
Louis Chang677921f2019-12-06 16:44:24 +08002232 final DisplayContent display = getDisplay();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002233 boolean hasPinnedStack = display != null && display.hasPinnedStack();
Winson Chungbb348802017-01-30 12:01:45 -08002234 // Don't return early if !isNotLocked, since we want to throw an exception if the activity
2235 // is in an incorrect state
Winson Chunge581ebf2017-02-21 08:25:03 -08002236 boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
Robert Carrc33658e2017-04-11 18:24:20 -07002237
2238 // We don't allow auto-PiP when something else is already pipped.
2239 if (beforeStopping && hasPinnedStack) {
2240 return false;
2241 }
2242
Bryce Lee7ace3952018-02-16 14:34:32 -08002243 switch (mState) {
Winson Chungc2baac02017-01-11 13:34:47 -08002244 case RESUMED:
Winson Chunge581ebf2017-02-21 08:25:03 -08002245 // When visible, allow entering PiP if the app is not locked. If it is over the
2246 // keyguard, then we will prompt to unlock in the caller before entering PiP.
Robert Carrc33658e2017-04-11 18:24:20 -07002247 return !isCurrentAppLocked &&
Winson Chungf7e03e12017-08-22 11:32:16 -07002248 (supportsEnterPipOnTaskSwitch || !beforeStopping);
Winson Chungc2baac02017-01-11 13:34:47 -08002249 case PAUSING:
2250 case PAUSED:
Winson Chungbb348802017-01-30 12:01:45 -08002251 // When pausing, then only allow enter PiP as in the resume state, and in addition,
2252 // require that there is not an existing PiP activity and that the current system
2253 // state supports entering PiP
Winson Chunge581ebf2017-02-21 08:25:03 -08002254 return isNotLockedOrOnKeyguard && !hasPinnedStack
Winson Chungf7e03e12017-08-22 11:32:16 -07002255 && supportsEnterPipOnTaskSwitch;
Winson Chungc2baac02017-01-11 13:34:47 -08002256 case STOPPING:
2257 // When stopping in a valid state, then only allow enter PiP as in the pause state.
2258 // Otherwise, fall through to throw an exception if the caller is trying to enter
2259 // PiP in an invalid stopping state.
Winson Chungf7e03e12017-08-22 11:32:16 -07002260 if (supportsEnterPipOnTaskSwitch) {
Winson Chungf4ac0632017-03-17 12:34:12 -07002261 return isNotLockedOrOnKeyguard && !hasPinnedStack;
Winson Chungc2baac02017-01-11 13:34:47 -08002262 }
2263 default:
Winson Chung298f95b2017-08-10 15:57:18 -07002264 return false;
Winson Chungb5c41b72016-12-07 15:00:47 -08002265 }
Winson Chunge6308042016-10-31 09:24:01 -07002266 }
2267
Winson Chung59fda9e2017-01-20 16:14:51 -08002268 /**
Issei Suzuki2bcbd682019-11-08 13:20:14 +01002269 * Sets if this {@link ActivityRecord} is in the process of closing or entering PIP.
Garfield Tane8d84ab2019-10-11 09:49:40 -07002270 * {@link #mWillCloseOrEnterPip}}
2271 */
2272 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
2273 mWillCloseOrEnterPip = willCloseOrEnterPip;
2274 }
2275
2276 /**
Issei Suzuki2bcbd682019-11-08 13:20:14 +01002277 * Returns whether this {@link ActivityRecord} is considered closing. Conditions are either
Garfield Tane8d84ab2019-10-11 09:49:40 -07002278 * 1. Is this app animating and was requested to be hidden
2279 * 2. App is delayed closing since it might enter PIP.
2280 */
2281 boolean isClosingOrEnteringPip() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01002282 return (isAnimating(TRANSITION | PARENTS) && !mVisibleRequested) || mWillCloseOrEnterPip;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002283 }
2284 /**
Winson Chungf4ac0632017-03-17 12:34:12 -07002285 * @return Whether AppOps allows this package to enter picture-in-picture.
Winson Chung59fda9e2017-01-20 16:14:51 -08002286 */
Winson Chungf4ac0632017-03-17 12:34:12 -07002287 private boolean checkEnterPictureInPictureAppOpsState() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002288 return mAtmService.getAppOpsService().checkOperation(
Andrii Kulianeceebbf2019-06-26 17:36:51 -07002289 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
Winson Chung59fda9e2017-01-20 16:14:51 -08002290 }
2291
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002292 private boolean isAlwaysFocusable() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002293 return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
2294 }
2295
Louis Chang2104fd92019-11-04 15:43:53 +08002296 boolean windowsAreFocusable() {
2297 return windowsAreFocusable(false /* fromUserTouch */);
2298 }
2299
Garfield Tane8d84ab2019-10-11 09:49:40 -07002300 // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
2301 // focusable means resumeable. I guess with that in mind maybe we should rename the other
2302 // method to isResumeable() or something like that.
Louis Chang2104fd92019-11-04 15:43:53 +08002303 boolean windowsAreFocusable(boolean fromUserTouch) {
2304 if (!fromUserTouch && mTargetSdk < Build.VERSION_CODES.Q) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002305 final int pid = getPid();
2306 final ActivityRecord topFocusedAppOfMyProcess =
2307 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
2308 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
2309 // For the apps below Q, there can be only one app which has the focused window per
2310 // process, because legacy apps may not be ready for a multi-focus system.
2311 return false;
2312 }
2313 }
Louis Changa9c9d982019-11-11 11:20:19 +08002314 return (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable())
Louis Chang2453d062019-11-19 22:30:48 +08002315 && getDisplay() != null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002316 }
2317
Louis Chang2104fd92019-11-04 15:43:53 +08002318 /**
2319 * Move activity with its stack to front and make the stack focused.
2320 * @param reason the reason to move to top
2321 * @return {@code true} if the stack is focusable and has been moved to top or the activity
2322 * is not yet resumed while the stack is already on top, {@code false} otherwise.
2323 */
Louis Chang19443452018-10-09 12:10:21 +08002324 boolean moveFocusableActivityToTop(String reason) {
2325 if (!isFocusable()) {
2326 if (DEBUG_FOCUS) {
2327 Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
2328 }
2329 return false;
2330 }
2331
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002332 final ActivityStack stack = getActivityStack();
Louis Chang19443452018-10-09 12:10:21 +08002333 if (stack == null) {
2334 Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
2335 + this + " task=" + task);
2336 return false;
2337 }
2338
Louis Chang149d5c82019-12-30 09:47:39 +08002339 if (mRootWindowContainer.getTopResumedActivity() == this
lumarkd0b5c8f2019-09-29 11:30:37 +08002340 && getDisplayContent().mFocusedApp == this) {
Louis Chang19443452018-10-09 12:10:21 +08002341 if (DEBUG_FOCUS) {
2342 Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
2343 }
Louis Chang2104fd92019-11-04 15:43:53 +08002344 return !isState(RESUMED);
Louis Chang19443452018-10-09 12:10:21 +08002345 }
2346
2347 if (DEBUG_FOCUS) {
2348 Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
2349 }
2350
2351 stack.moveToFront(reason, task);
2352 // Report top activity change to tracking services and WM
Louis Chang149d5c82019-12-30 09:47:39 +08002353 if (mRootWindowContainer.getTopResumedActivity() == this) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002354 mAtmService.setResumedActivityUncheckLocked(this, reason);
Louis Chang19443452018-10-09 12:10:21 +08002355 }
2356 return true;
2357 }
Jorim Jaggife762342016-10-13 14:33:27 +02002358
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002359 void finishIfSubActivity(ActivityRecord parent, String otherResultWho, int otherRequestCode) {
2360 if (resultTo != parent
2361 || requestCode != otherRequestCode
2362 || !Objects.equals(resultWho, otherResultWho)) return;
2363
2364 finishIfPossible("request-sub", false /* oomAdj */);
2365 }
2366
Andrii Kuliande93eff2019-07-12 12:21:27 -07002367 /** Finish all activities in the task with the same affinity as this one. */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002368 boolean finishIfSameAffinity(ActivityRecord r) {
2369 // End search once we get to the activity that doesn't have the same affinity.
2370 if (!Objects.equals(r.taskAffinity, taskAffinity)) return true;
2371
2372 r.finishIfPossible("request-affinity", true /* oomAdj */);
2373 return false;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002374 }
2375
2376 /**
2377 * Sets the result for activity that started this one, clears the references to activities
2378 * started for result from this one, and clears new intents.
2379 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002380 private void finishActivityResults(int resultCode, Intent resultData) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002381 // Send the result if needed
2382 if (resultTo != null) {
2383 if (DEBUG_RESULTS) {
2384 Slog.v(TAG_RESULTS, "Adding result to " + resultTo
2385 + " who=" + resultWho + " req=" + requestCode
2386 + " res=" + resultCode + " data=" + resultData);
2387 }
2388 if (resultTo.mUserId != mUserId) {
2389 if (resultData != null) {
2390 resultData.prepareToLeaveUser(mUserId);
2391 }
2392 }
2393 if (info.applicationInfo.uid > 0) {
2394 mAtmService.mUgmInternal.grantUriPermissionFromIntent(info.applicationInfo.uid,
2395 resultTo.packageName, resultData,
2396 resultTo.getUriPermissionsLocked(), resultTo.mUserId);
2397 }
2398 resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
2399 resultTo = null;
2400 } else if (DEBUG_RESULTS) {
2401 Slog.v(TAG_RESULTS, "No result destination from " + this);
2402 }
2403
2404 // Make sure this HistoryRecord is not holding on to other resources,
2405 // because clients have remote IPC references to this object so we
2406 // can't assume that will go away and want to avoid circular IPC refs.
2407 results = null;
2408 pendingResults = null;
2409 newIntents = null;
2410 setSavedState(null /* savedState */);
2411 }
2412
Andrii Kulian057a6512019-07-15 16:15:51 -07002413 /** Activity finish request was not executed. */
2414 static final int FINISH_RESULT_CANCELLED = 0;
2415 /** Activity finish was requested, activity will be fully removed later. */
2416 static final int FINISH_RESULT_REQUESTED = 1;
2417 /** Activity finish was requested, activity was removed from history. */
2418 static final int FINISH_RESULT_REMOVED = 2;
2419
2420 /** Definition of possible results for activity finish request. */
2421 @IntDef(prefix = { "FINISH_RESULT_" }, value = {
2422 FINISH_RESULT_CANCELLED,
2423 FINISH_RESULT_REQUESTED,
2424 FINISH_RESULT_REMOVED,
2425 })
2426 @interface FinishRequest {}
2427
Andrii Kuliande93eff2019-07-12 12:21:27 -07002428 /**
Louis Chang7b03ad92019-08-21 12:32:33 +08002429 * See {@link #finishIfPossible(int, Intent, String, boolean)}
Andrii Kuliande93eff2019-07-12 12:21:27 -07002430 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002431 @FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
Louis Chang7b03ad92019-08-21 12:32:33 +08002432 return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason, oomAdj);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002433 }
2434
2435 /**
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002436 * Finish activity if possible. If activity was resumed - we must first pause it to make the
2437 * activity below resumed. Otherwise we will try to complete the request immediately by calling
2438 * {@link #completeFinishing(String)}.
Andrii Kulian057a6512019-07-15 16:15:51 -07002439 * @return One of {@link FinishRequest} values:
2440 * {@link #FINISH_RESULT_REMOVED} if this activity has been removed from the history list.
2441 * {@link #FINISH_RESULT_REQUESTED} if removal process was started, but it is still in the list
2442 * and will be removed from history later.
2443 * {@link #FINISH_RESULT_CANCELLED} if activity is already finishing or in invalid state and the
2444 * request to finish it was not ignored.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002445 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002446 @FinishRequest int finishIfPossible(int resultCode, Intent resultData, String reason,
Louis Chang7b03ad92019-08-21 12:32:33 +08002447 boolean oomAdj) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002448 if (DEBUG_RESULTS || DEBUG_STATES) {
2449 Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
2450 + ", data=" + resultData + ", reason=" + reason);
2451 }
2452
Andrii Kuliande93eff2019-07-12 12:21:27 -07002453 if (finishing) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002454 Slog.w(TAG, "Duplicate finish request for r=" + this);
2455 return FINISH_RESULT_CANCELLED;
2456 }
2457
2458 if (!isInStackLocked()) {
2459 Slog.w(TAG, "Finish request when not in stack for r=" + this);
2460 return FINISH_RESULT_CANCELLED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002461 }
2462
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002463 final ActivityStack stack = getActivityStack();
Riddle Hsucf920232019-10-04 19:05:36 +08002464 final boolean mayAdjustTop = (isState(RESUMED) || stack.mResumedActivity == null)
2465 && stack.isFocusedStackOnDisplay();
2466 final boolean shouldAdjustGlobalFocus = mayAdjustTop
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002467 // It must be checked before {@link #makeFinishingLocked} is called, because a stack
2468 // is not visible if it only contains finishing activities.
Louis Chang149d5c82019-12-30 09:47:39 +08002469 && mRootWindowContainer.isTopDisplayFocusedStack(stack);
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002470
Riddle Hsua0022cd2019-09-09 21:12:41 +08002471 mAtmService.deferWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002472 try {
2473 makeFinishingLocked();
Louis Changcdec0802019-11-11 11:45:07 +08002474 // Make a local reference to its task since this.task could be set to null once this
2475 // activity is destroyed and detached from task.
2476 final Task task = getTask();
Jeff Changd136e772019-11-05 20:33:52 +08002477 EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002478 task.mTaskId, shortComponentName, reason);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002479 ActivityRecord next = task.getActivityAbove(this);
2480 if (next != null) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002481 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2482 // If the caller asked that this activity (and all above it)
2483 // be cleared when the task is reset, don't lose that information,
2484 // but propagate it up to the next activity.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002485 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2486 }
2487 }
2488
2489 pauseKeyDispatchingLocked();
2490
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002491 // We are finishing the top focused activity and its stack has nothing to be focused so
2492 // the next focusable stack should be focused.
Riddle Hsucf920232019-10-04 19:05:36 +08002493 if (mayAdjustTop
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09002494 && (stack.topRunningActivity() == null || !stack.isFocusable())) {
Riddle Hsucf920232019-10-04 19:05:36 +08002495 if (shouldAdjustGlobalFocus) {
2496 // Move the entire hierarchy to top with updating global top resumed activity
2497 // and focused application if needed.
2498 stack.adjustFocusToNextFocusableStack("finish-top");
2499 } else {
2500 // Only move the next stack to top in its display.
Louis Chang677921f2019-12-06 16:44:24 +08002501 final DisplayContent display = stack.getDisplay();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002502 next = display.topRunningActivity();
Riddle Hsucf920232019-10-04 19:05:36 +08002503 if (next != null) {
Louis Chang2453d062019-11-19 22:30:48 +08002504 display.positionStackAtTop(next.getActivityStack(),
Riddle Hsucf920232019-10-04 19:05:36 +08002505 false /* includingParents */, "finish-display-top");
2506 }
2507 }
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002508 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002509
2510 finishActivityResults(resultCode, resultData);
2511
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002512 final boolean endTask = task.getActivityBelow(this) == null
2513 && !task.isClearingToReuseTask();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002514 final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002515 if (isState(RESUMED)) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002516 if (endTask) {
2517 mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
2518 task.getTaskInfo());
2519 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002520 // Prepare app close transition, but don't execute just yet. It is possible that
2521 // an activity that will be made resumed in place of this one will immediately
2522 // launch another new activity. In this case current closing transition will be
2523 // combined with open transition for the new activity.
2524 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
2525 Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
2526 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002527 getDisplay().mDisplayContent.prepareAppTransition(transit, false);
2528
2529 // When finishing the activity preemptively take the snapshot before the app window
2530 // is marked as hidden and any configuration changes take place
2531 if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002532 final ArraySet<Task> tasks = Sets.newArraySet(task);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002533 mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
2534 mAtmService.mWindowManager.mTaskSnapshotController
2535 .addSkipClosingAppSnapshotTasks(tasks);
2536 }
2537
2538 // Tell window manager to prepare for this one to be removed.
2539 setVisibility(false);
2540
2541 if (stack.mPausingActivity == null) {
2542 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + this);
2543 if (DEBUG_USER_LEAVING) {
2544 Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
2545 }
Louis Chang7b03ad92019-08-21 12:32:33 +08002546 stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
2547 null /* resuming */);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002548 }
2549
2550 if (endTask) {
2551 mAtmService.getLockTaskController().clearLockedTask(task);
2552 }
2553 } else if (!isState(PAUSING)) {
Issei Suzuki1669ea42019-11-06 14:20:59 +01002554 if (mVisibleRequested) {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002555 // Prepare and execute close transition.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002556 prepareActivityHideTransitionAnimation(transit);
2557 }
2558
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002559 final boolean removedActivity = completeFinishing("finishIfPossible") == null;
2560 // Performance optimization - only invoke OOM adjustment if the state changed to
2561 // 'STOPPING'. Otherwise it will not change the OOM scores.
2562 if (oomAdj && isState(STOPPING)) {
2563 mAtmService.updateOomAdj();
2564 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002565
2566 // The following code is an optimization. When the last non-task overlay activity
2567 // is removed from the task, we remove the entire task from the stack. However,
2568 // since that is done after the scheduled destroy callback from the activity, that
2569 // call to change the visibility of the task overlay activities would be out of
2570 // sync with the activity visibility being set for this finishing activity above.
2571 // In this case, we can set the visibility of all the task overlay activities when
2572 // we detect the last one is finishing to keep them in sync.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002573 if (task.onlyHasTaskOverlayActivities(false /* includeFinishing */)) {
2574 final PooledConsumer c = PooledLambda.obtainConsumer(
2575 ActivityRecord::prepareActivityHideTransitionAnimationIfOvarlay,
2576 PooledLambda.__(ActivityRecord.class), transit);
2577 task.forAllActivities(c);
2578 c.recycle();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002579 }
Andrii Kulian057a6512019-07-15 16:15:51 -07002580 return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002581 } else {
2582 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
2583 }
2584
Andrii Kulian057a6512019-07-15 16:15:51 -07002585 return FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002586 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +08002587 mAtmService.continueWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002588 }
2589 }
2590
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002591 private void prepareActivityHideTransitionAnimationIfOvarlay(int transit) {
2592 if (mTaskOverlay) {
2593 prepareActivityHideTransitionAnimation(transit);
2594 }
2595 }
2596
Andrii Kuliande93eff2019-07-12 12:21:27 -07002597 private void prepareActivityHideTransitionAnimation(int transit) {
2598 final DisplayContent dc = getDisplay().mDisplayContent;
2599 dc.prepareAppTransition(transit, false);
2600 setVisibility(false);
2601 dc.executeAppTransition();
2602 }
2603
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002604 /**
2605 * Complete activity finish request that was initiated earlier. If the activity is still
2606 * pausing we will wait for it to complete its transition. If the activity that should appear in
2607 * place of this one is not visible yet - we'll wait for it first. Otherwise - activity can be
2608 * destroyed right away.
2609 * @param reason Reason for finishing the activity.
2610 * @return Flag indicating whether the activity was removed from history.
2611 */
2612 ActivityRecord completeFinishing(String reason) {
2613 if (!finishing || isState(RESUMED)) {
2614 throw new IllegalArgumentException(
2615 "Activity must be finishing and not resumed to complete, r=" + this
2616 + ", finishing=" + finishing + ", state=" + mState);
2617 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002618
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002619 if (isState(PAUSING)) {
2620 // Activity is marked as finishing and will be processed once it completes.
2621 return this;
2622 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002623
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002624 boolean activityRemoved = false;
2625
2626 // If this activity is currently visible, and the resumed activity is not yet visible, then
2627 // hold off on finishing until the resumed one becomes visible.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002628 // The activity that we are finishing may be over the lock screen. In this case, we do not
2629 // want to consider activities that cannot be shown on the lock screen as running and should
2630 // proceed with finishing the activity if there is no valid next top running activity.
2631 // Note that if this finishing activity is floating task, we don't need to wait the
2632 // next activity resume and can destroy it directly.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002633 // TODO(b/137329632): find the next activity directly underneath this one, not just anywhere
2634 final ActivityRecord next = getDisplay().topRunningActivity(
2635 true /* considerKeyguardState */);
Issei Suzuki1669ea42019-11-06 14:20:59 +01002636 final boolean isVisible = mVisibleRequested || nowVisible;
lumark50b81542019-09-01 23:11:49 +08002637 // isNextNotYetVisible is to check if the next activity is invisible, or it has been
2638 // requested to be invisible but its windows haven't reported as invisible. If so, it
2639 // implied that the current finishing activity should be added into stopping list rather
2640 // than destroy immediately.
Issei Suzuki1669ea42019-11-06 14:20:59 +01002641 final boolean isNextNotYetVisible = next != null
2642 && (!next.nowVisible || !next.mVisibleRequested);
lumark50b81542019-09-01 23:11:49 +08002643 if (isVisible && isNextNotYetVisible) {
Andrii Kulian34acc142019-09-24 15:35:50 -07002644 // Add this activity to the list of stopping activities. It will be processed and
2645 // destroyed when the next activity reports idle.
Andrii Kulian79d67982019-08-19 11:56:16 -07002646 addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
2647 "completeFinishing");
Andrii Kulian79d67982019-08-19 11:56:16 -07002648 setState(STOPPING, "completeFinishing");
Andrii Kulian34acc142019-09-24 15:35:50 -07002649 } else if (addToFinishingAndWaitForIdle()) {
2650 // We added this activity to the finishing list and something else is becoming resumed.
2651 // The activity will complete finishing when the next activity reports idle. No need to
2652 // do anything else here.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002653 } else {
Andrii Kulian34acc142019-09-24 15:35:50 -07002654 // Not waiting for the next one to become visible, and nothing else will be resumed in
2655 // place of this activity - requesting destruction right away.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002656 activityRemoved = destroyIfPossible(reason);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002657 }
2658
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002659 return activityRemoved ? null : this;
2660 }
2661
2662 /**
2663 * Destroy and cleanup the activity both on client and server if possible. If activity is the
2664 * last one left on display with home stack and there is no other running activity - delay
2665 * destroying it until the next one starts.
2666 */
2667 boolean destroyIfPossible(String reason) {
2668 setState(FINISHING, "destroyIfPossible");
2669
2670 // Make sure the record is cleaned out of other places.
2671 mStackSupervisor.mStoppingActivities.remove(this);
2672 mStackSupervisor.mGoingToSleepActivities.remove(this);
2673
2674 final ActivityStack stack = getActivityStack();
Louis Chang677921f2019-12-06 16:44:24 +08002675 final DisplayContent display = getDisplay();
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002676 // TODO(b/137329632): Exclude current activity when looking for the next one with
Louis Chang677921f2019-12-06 16:44:24 +08002677 // DisplayContent#topRunningActivity().
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002678 final ActivityRecord next = display.topRunningActivity();
2679 final boolean isLastStackOverEmptyHome =
2680 next == null && stack.isFocusedStackOnDisplay() && display.getHomeStack() != null;
2681 if (isLastStackOverEmptyHome) {
2682 // Don't destroy activity immediately if this is the last activity on the display and
2683 // the display contains home stack. Although there is no next activity at the moment,
2684 // another home activity should be started later. Keep this activity alive until next
2685 // home activity is resumed. This way the user won't see a temporary black screen.
2686 addToFinishingAndWaitForIdle();
2687 return false;
2688 }
2689 makeFinishingLocked();
2690
Andrii Kulian79d67982019-08-19 11:56:16 -07002691 final boolean activityRemoved = destroyImmediately(true /* removeFromApp */,
2692 "finish-imm:" + reason);
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002693
2694 // If the display does not have running activity, the configuration may need to be
2695 // updated for restoring original orientation of the display.
2696 if (next == null) {
Louis Chang149d5c82019-12-30 09:47:39 +08002697 mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002698 false /* markFrozenIfConfigChanged */, true /* deferResume */);
2699 }
2700 if (activityRemoved) {
Louis Chang149d5c82019-12-30 09:47:39 +08002701 mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002702 }
2703
2704 if (DEBUG_CONTAINERS) {
2705 Slog.d(TAG_CONTAINERS, "destroyIfPossible: r=" + this + " destroy returned removed="
2706 + activityRemoved);
2707 }
2708
2709 return activityRemoved;
2710 }
2711
Andrii Kulian34acc142019-09-24 15:35:50 -07002712 /**
2713 * Add this activity to the list of finishing and trigger resuming of activities in focused
2714 * stacks.
2715 * @return {@code true} if some other activity is being resumed as a result of this call.
2716 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002717 @VisibleForTesting
Andrii Kulian34acc142019-09-24 15:35:50 -07002718 boolean addToFinishingAndWaitForIdle() {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002719 if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
2720 setState(FINISHING, "addToFinishingAndWaitForIdle");
Andrii Kulian34acc142019-09-24 15:35:50 -07002721 if (!mStackSupervisor.mFinishingActivities.contains(this)) {
2722 mStackSupervisor.mFinishingActivities.add(this);
2723 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002724 resumeKeyDispatchingLocked();
Louis Chang149d5c82019-12-30 09:47:39 +08002725 return mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002726 }
2727
Andrii Kulian79d67982019-08-19 11:56:16 -07002728 /**
2729 * Destroy the current CLIENT SIDE instance of an activity. This may be called both when
2730 * actually finishing an activity, or when performing a configuration switch where we destroy
2731 * the current client-side object but then create a new client-side object for this same
2732 * HistoryRecord.
2733 * Normally the server-side record will be removed when the client reports back after
2734 * destruction. If, however, at this point there is no client process attached, the record will
Andrii Kulianf49a58c2019-08-14 17:34:27 -07002735 * be removed immediately.
2736 *
2737 * @return {@code true} if activity was immediately removed from history, {@code false}
2738 * otherwise.
Andrii Kulian79d67982019-08-19 11:56:16 -07002739 */
2740 boolean destroyImmediately(boolean removeFromApp, String reason) {
2741 if (DEBUG_SWITCH || DEBUG_CLEANUP) {
2742 Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this
2743 + ", app=" + (hasProcess() ? app.mName : "(null)"));
2744 }
2745
2746 if (isState(DESTROYING, DESTROYED)) {
2747 if (DEBUG_STATES) {
2748 Slog.v(TAG_STATES, "activity " + this + " already destroying."
2749 + "skipping request with reason:" + reason);
2750 }
2751 return false;
2752 }
2753
Jeff Changd136e772019-11-05 20:33:52 +08002754 EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this),
2755 task.mTaskId, shortComponentName, reason);
Andrii Kulian79d67982019-08-19 11:56:16 -07002756
2757 boolean removedFromHistory = false;
2758
2759 cleanUp(false /* cleanServices */, false /* setState */);
2760
Riddle Hsu5477b572019-11-12 16:07:29 +08002761 if (hasProcess()) {
Andrii Kulian79d67982019-08-19 11:56:16 -07002762 if (removeFromApp) {
2763 app.removeActivity(this);
2764 if (!app.hasActivities()) {
2765 mAtmService.clearHeavyWeightProcessIfEquals(app);
2766 // Update any services we are bound to that might care about whether
2767 // their client may have activities.
2768 // No longer have activities, so update LRU list and oom adj.
2769 app.updateProcessInfo(true /* updateServiceConnectionActivities */,
2770 false /* activityChange */, true /* updateOomAdj */);
2771 }
2772 }
2773
2774 boolean skipDestroy = false;
2775
2776 try {
2777 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
2778 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2779 DestroyActivityItem.obtain(finishing, configChangeFlags));
2780 } catch (Exception e) {
2781 // We can just ignore exceptions here... if the process has crashed, our death
2782 // notification will clean things up.
2783 if (finishing) {
2784 removeFromHistory(reason + " exceptionInScheduleDestroy");
2785 removedFromHistory = true;
2786 skipDestroy = true;
2787 }
2788 }
2789
2790 nowVisible = false;
2791
2792 // If the activity is finishing, we need to wait on removing it from the list to give it
2793 // a chance to do its cleanup. During that time it may make calls back with its token
2794 // so we need to be able to find it on the list and so we don't want to remove it from
2795 // the list yet. Otherwise, we can just immediately put it in the destroyed state since
2796 // we are not removing it from the list.
2797 if (finishing && !skipDestroy) {
2798 if (DEBUG_STATES) {
2799 Slog.v(TAG_STATES, "Moving to DESTROYING: " + this + " (destroy requested)");
2800 }
2801 setState(DESTROYING,
2802 "destroyActivityLocked. finishing and not skipping destroy");
Wale Ogunwale196db712019-12-27 15:35:39 +00002803 mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT);
Andrii Kulian79d67982019-08-19 11:56:16 -07002804 } else {
2805 if (DEBUG_STATES) {
2806 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
2807 }
2808 setState(DESTROYED,
2809 "destroyActivityLocked. not finishing or skipping destroy");
2810 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
2811 app = null;
2812 }
2813 } else {
2814 // Remove this record from the history.
2815 if (finishing) {
2816 removeFromHistory(reason + " hadNoApp");
2817 removedFromHistory = true;
2818 } else {
2819 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (no app)");
2820 setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
2821 }
2822 }
2823
2824 configChangeFlags = 0;
2825
Andrii Kulian79d67982019-08-19 11:56:16 -07002826 return removedFromHistory;
2827 }
2828
2829 boolean safelyDestroy(String reason) {
2830 if (isDestroyable()) {
2831 if (DEBUG_SWITCH) {
2832 final ActivityStack stack = getActivityStack();
2833 Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState()
2834 + " resumed=" + stack.mResumedActivity
2835 + " pausing=" + stack.mPausingActivity
2836 + " for reason " + reason);
2837 }
2838 return destroyImmediately(true /* removeFromApp */, reason);
2839 }
2840 return false;
2841 }
2842
2843 /** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
2844 void removeFromHistory(String reason) {
2845 finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
2846 makeFinishingLocked();
2847 if (ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE) {
2848 Slog.i(TAG_ADD_REMOVE, "Removing activity " + this + " from stack callers="
2849 + Debug.getCallers(5));
2850 }
2851
2852 takeFromHistory();
Wale Ogunwale196db712019-12-27 15:35:39 +00002853 removeTimeouts();
Andrii Kulian79d67982019-08-19 11:56:16 -07002854 if (DEBUG_STATES) {
2855 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
2856 }
2857 setState(DESTROYED, "removeFromHistory");
2858 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
2859 app = null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002860 removeAppTokenFromDisplay();
Andrii Kulian79d67982019-08-19 11:56:16 -07002861
2862 cleanUpActivityServices();
2863 removeUriPermissionsLocked();
2864 }
2865
Wale Ogunwale7d701172015-03-11 15:36:30 -07002866 void makeFinishingLocked() {
Wale Ogunwalec981ad52017-06-13 11:40:06 -07002867 if (finishing) {
2868 return;
2869 }
2870 finishing = true;
2871 if (stopped) {
2872 clearOptionsLocked();
2873 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002874 }
2875
Andrii Kulian79d67982019-08-19 11:56:16 -07002876 /**
2877 * This method is to only be called from the client via binder when the activity is destroyed
2878 * AND finished.
2879 */
2880 void destroyed(String reason) {
Wale Ogunwale196db712019-12-27 15:35:39 +00002881 removeDestroyTimeout();
Andrii Kulian79d67982019-08-19 11:56:16 -07002882
2883 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + this);
2884
2885 if (!isState(DESTROYING, DESTROYED)) {
2886 throw new IllegalStateException(
2887 "Reported destroyed for activity that is not destroying: r=" + this);
2888 }
2889
2890 if (isInStackLocked()) {
2891 cleanUp(true /* cleanServices */, false /* setState */);
2892 removeFromHistory(reason);
2893 }
2894
Louis Chang149d5c82019-12-30 09:47:39 +08002895 mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kulian79d67982019-08-19 11:56:16 -07002896 }
2897
2898 /**
2899 * Perform the common clean-up of an activity record. This is called both as part of
2900 * destroyActivityLocked() (when destroying the client-side representation) and cleaning things
2901 * up as a result of its hosting processing going away, in which case there is no remaining
2902 * client-side state to destroy so only the cleanup here is needed.
2903 *
2904 * Note: Call before {@link #removeFromHistory(String)}.
2905 */
2906 void cleanUp(boolean cleanServices, boolean setState) {
2907 final ActivityStack stack = getActivityStack();
2908 stack.onActivityRemovedFromStack(this);
2909
2910 deferRelaunchUntilPaused = false;
2911 frozenBeforeDestroy = false;
2912
2913 if (setState) {
2914 setState(DESTROYED, "cleanUp");
2915 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this);
2916 app = null;
2917 }
2918
2919 // Inform supervisor the activity has been removed.
2920 mStackSupervisor.cleanupActivity(this);
2921
2922 // Remove any pending results.
2923 if (finishing && pendingResults != null) {
2924 for (WeakReference<PendingIntentRecord> apr : pendingResults) {
2925 PendingIntentRecord rec = apr.get();
2926 if (rec != null) {
2927 mAtmService.mPendingIntentController.cancelIntentSender(rec,
2928 false /* cleanActivity */);
2929 }
2930 }
2931 pendingResults = null;
2932 }
2933
2934 if (cleanServices) {
2935 cleanUpActivityServices();
2936 }
2937
2938 // Get rid of any pending idle timeouts.
Wale Ogunwale196db712019-12-27 15:35:39 +00002939 removeTimeouts();
Andrii Kulian79d67982019-08-19 11:56:16 -07002940 // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
2941 // manager so it can update its bookkeeping.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002942 clearRelaunching();
Andrii Kulian79d67982019-08-19 11:56:16 -07002943 }
2944
Garfield Tane8d84ab2019-10-11 09:49:40 -07002945 boolean isRelaunching() {
2946 return mPendingRelaunchCount > 0;
2947 }
2948
2949 boolean shouldFreezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002950 // For freeform windows, we can't freeze the bounds at the moment because this would make
2951 // the resizing unresponsive.
2952 if (task == null || task.inFreeformWindowingMode()) {
2953 return false;
2954 }
2955
2956 // We freeze the bounds while drag resizing to deal with the time between
2957 // the divider/drag handle being released, and the handling it's new
2958 // configuration. If we are relaunched outside of the drag resizing state,
2959 // we need to be careful not to do this.
Louis Changcdec0802019-11-11 11:45:07 +08002960 return task.isDragResizing();
Garfield Tane8d84ab2019-10-11 09:49:40 -07002961 }
2962
2963 void startRelaunching() {
2964 if (shouldFreezeBounds()) {
2965 freezeBounds();
2966 }
2967
2968 // In the process of tearing down before relaunching, the app will
2969 // try and clean up it's child surfaces. We need to prevent this from
2970 // happening, so we sever the children, transfering their ownership
2971 // from the client it-self to the parent surface (owned by us).
2972 detachChildren();
2973
2974 mPendingRelaunchCount++;
2975 }
2976
2977 /**
2978 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
2979 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
2980 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
2981 * with a queue.
2982 */
2983 private void freezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002984 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
2985
2986 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
2987 // We didn't call prepareFreezingBounds on the task, so use the current value.
2988 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
2989 } else {
2990 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
2991 }
2992 // Calling unset() to make it equal to Configuration.EMPTY.
2993 task.mPreparedFrozenMergedConfig.unset();
2994 }
2995
2996 void detachChildren() {
2997 SurfaceControl.openTransaction();
2998 for (int i = mChildren.size() - 1; i >= 0; i--) {
2999 final WindowState w = mChildren.get(i);
3000 w.mWinAnimator.detachChildren();
3001 }
3002 SurfaceControl.closeTransaction();
3003 }
3004
3005 void finishRelaunching() {
3006 unfreezeBounds();
3007
3008 if (mPendingRelaunchCount > 0) {
3009 mPendingRelaunchCount--;
3010 } else {
3011 // Update keyguard flags upon finishing relaunch.
3012 checkKeyguardFlagsChanged();
3013 }
3014 }
3015
3016 void clearRelaunching() {
3017 if (mPendingRelaunchCount == 0) {
3018 return;
3019 }
3020 unfreezeBounds();
3021 mPendingRelaunchCount = 0;
3022 }
3023
3024 /**
3025 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
3026 */
3027 private void unfreezeBounds() {
3028 if (mFrozenBounds.isEmpty()) {
3029 return;
3030 }
3031 mFrozenBounds.remove();
3032 if (!mFrozenMergedConfig.isEmpty()) {
3033 mFrozenMergedConfig.remove();
3034 }
3035 for (int i = mChildren.size() - 1; i >= 0; i--) {
3036 final WindowState win = mChildren.get(i);
3037 win.onUnfreezeBounds();
3038 }
3039 mWmService.mWindowPlacerLocked.performSurfacePlacement();
3040 }
3041
Andrii Kulian79d67982019-08-19 11:56:16 -07003042 /**
3043 * Perform clean-up of service connections in an activity record.
3044 */
3045 private void cleanUpActivityServices() {
3046 if (mServiceConnectionsHolder == null) {
3047 return;
3048 }
3049 // Throw away any services that have been bound by this activity.
3050 mServiceConnectionsHolder.disconnectActivityFromServices();
3051 }
3052
Garfield Tane8d84ab2019-10-11 09:49:40 -07003053 @Override
3054 void removeImmediately() {
3055 onRemovedFromDisplay();
3056 super.removeImmediately();
3057 }
3058
3059 @Override
3060 void removeIfPossible() {
3061 mIsExiting = false;
3062 removeAllWindowsIfPossible();
3063 removeImmediately();
3064 }
3065
3066 @Override
3067 boolean checkCompleteDeferredRemoval() {
3068 if (mIsExiting) {
3069 removeIfPossible();
3070 }
3071 return super.checkCompleteDeferredRemoval();
3072 }
3073
3074 void onRemovedFromDisplay() {
3075 if (mRemovingFromDisplay) {
3076 return;
3077 }
3078 mRemovingFromDisplay = true;
3079
3080 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
3081
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003082 commitVisibility(false /* visible */, true /* performLayout */);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003083
3084 getDisplayContent().mOpeningApps.remove(this);
3085 getDisplayContent().mChangingApps.remove(this);
3086 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
3087 mWmService.mTaskSnapshotController.onAppRemoved(this);
Riddle Hsufd66d4d2019-11-14 10:35:55 +08003088 mStackSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003089 waitingToShow = false;
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003090
3091 boolean delayed = isAnimating(TRANSITION | CHILDREN);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003092 if (getDisplayContent().mClosingApps.contains(this)) {
3093 delayed = true;
3094 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
3095 getDisplayContent().mClosingApps.add(this);
3096 delayed = true;
3097 }
3098
3099 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
3100 "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
lumark9bca6b42019-10-17 18:35:22 +08003101 getAnimation(), isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07003102
3103 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
3104 + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
3105
3106 if (mStartingData != null) {
3107 removeStartingWindow();
3108 }
3109
3110 // If this window was animating, then we need to ensure that the app transition notifies
3111 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
3112 // so add to that list now
lumark9bca6b42019-10-17 18:35:22 +08003113 if (isAnimating(TRANSITION)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003114 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
3115 }
3116
Louis Changdc077272019-11-12 16:52:56 +08003117 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003118 if (delayed && !isEmpty()) {
3119 // set the token aside because it has an active animation to be finished
3120 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3121 "removeAppToken make exiting: %s", this);
3122 if (stack != null) {
3123 stack.mExitingActivities.add(this);
3124 }
3125 mIsExiting = true;
3126 } else {
3127 // Make sure there is no animation running on this token, so any windows associated
3128 // with it will be removed as soon as their animations are complete
3129 cancelAnimation();
3130 if (stack != null) {
3131 stack.mExitingActivities.remove(this);
3132 }
3133 removeIfPossible();
3134 }
3135
Garfield Tane8d84ab2019-10-11 09:49:40 -07003136 stopFreezingScreen(true, true);
3137
3138 final DisplayContent dc = getDisplayContent();
3139 if (dc.mFocusedApp == this) {
3140 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
3141 "Removing focused app token:%s displayId=%d", this,
3142 dc.getDisplayId());
3143 dc.setFocusedApp(null);
3144 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3145 }
3146 if (mLetterbox != null) {
3147 mLetterbox.destroy();
3148 mLetterbox = null;
3149 }
3150
3151 if (!delayed) {
3152 updateReportedVisibilityLocked();
3153 }
3154
3155 // Reset the last saved PiP snap fraction on removal.
jorgegil@google.com62f735e2019-10-30 14:37:19 -07003156 mDisplayContent.mPinnedStackControllerLocked.resetReentryBounds(mActivityComponent);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003157
3158 mRemovingFromDisplay = false;
3159 }
3160
3161 /**
3162 * Returns true if the new child window we are adding to this token is considered greater than
3163 * the existing child window in this token in terms of z-order.
3164 */
3165 @Override
3166 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
3167 WindowState existingWindow) {
3168 final int type1 = newWindow.mAttrs.type;
3169 final int type2 = existingWindow.mAttrs.type;
3170
3171 // Base application windows should be z-ordered BELOW all other windows in the app token.
3172 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
3173 return false;
3174 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
3175 return true;
3176 }
3177
3178 // Starting windows should be z-ordered ABOVE all other windows in the app token.
3179 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
3180 return true;
3181 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
3182 return false;
3183 }
3184
3185 // Otherwise the new window is greater than the existing window.
3186 return true;
3187 }
3188
3189 /**
3190 * @return {@code true} if starting window is in app's hierarchy.
3191 */
3192 boolean hasStartingWindow() {
3193 if (startingDisplayed || mStartingData != null) {
3194 return true;
3195 }
3196 for (int i = mChildren.size() - 1; i >= 0; i--) {
3197 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
3198 return true;
3199 }
3200 }
3201 return false;
3202 }
3203
3204 boolean isLastWindow(WindowState win) {
3205 return mChildren.size() == 1 && mChildren.get(0) == win;
3206 }
3207
3208 @Override
3209 void addWindow(WindowState w) {
3210 super.addWindow(w);
3211
3212 boolean gotReplacementWindow = false;
3213 for (int i = mChildren.size() - 1; i >= 0; i--) {
3214 final WindowState candidate = mChildren.get(i);
3215 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
3216 }
3217
3218 // if we got a replacement window, reset the timeout to give drawing more time
3219 if (gotReplacementWindow) {
3220 mWmService.scheduleWindowReplacementTimeouts(this);
3221 }
3222 checkKeyguardFlagsChanged();
3223 }
3224
3225 @Override
3226 void removeChild(WindowState child) {
3227 if (!mChildren.contains(child)) {
3228 // This can be true when testing.
3229 return;
3230 }
3231 super.removeChild(child);
3232 checkKeyguardFlagsChanged();
3233 updateLetterboxSurface(child);
3234 }
3235
Garfield Tane8d84ab2019-10-11 09:49:40 -07003236 void onWindowReplacementTimeout() {
3237 for (int i = mChildren.size() - 1; i >= 0; --i) {
3238 (mChildren.get(i)).onWindowReplacementTimeout();
3239 }
3240 }
3241
3242 void setAppLayoutChanges(int changes, String reason) {
3243 if (!mChildren.isEmpty()) {
3244 final DisplayContent dc = getDisplayContent();
3245 dc.pendingLayoutChanges |= changes;
3246 if (DEBUG_LAYOUT_REPEATS) {
3247 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
3248 }
3249 }
3250 }
3251
3252 void removeReplacedWindowIfNeeded(WindowState replacement) {
3253 for (int i = mChildren.size() - 1; i >= 0; i--) {
3254 final WindowState win = mChildren.get(i);
3255 if (win.removeReplacedWindowIfNeeded(replacement)) {
3256 return;
3257 }
3258 }
3259 }
3260
3261 boolean transferStartingWindow(IBinder transferFrom) {
3262 final ActivityRecord fromActivity = getDisplayContent().getActivityRecord(transferFrom);
3263 if (fromActivity == null) {
3264 return false;
3265 }
3266
3267 final WindowState tStartingWindow = fromActivity.startingWindow;
3268 if (tStartingWindow != null && fromActivity.startingSurface != null) {
3269 // In this case, the starting icon has already been displayed, so start
3270 // letting windows get shown immediately without any more transitions.
3271 getDisplayContent().mSkipAppTransitionAnimation = true;
3272
3273 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
3274 + " from %s to %s", tStartingWindow, fromActivity, this);
3275
3276 final long origId = Binder.clearCallingIdentity();
3277 try {
3278 // Transfer the starting window over to the new token.
3279 mStartingData = fromActivity.mStartingData;
3280 startingSurface = fromActivity.startingSurface;
3281 startingDisplayed = fromActivity.startingDisplayed;
3282 fromActivity.startingDisplayed = false;
3283 startingWindow = tStartingWindow;
3284 reportedVisible = fromActivity.reportedVisible;
3285 fromActivity.mStartingData = null;
3286 fromActivity.startingSurface = null;
3287 fromActivity.startingWindow = null;
3288 fromActivity.startingMoved = true;
3289 tStartingWindow.mToken = this;
3290 tStartingWindow.mActivityRecord = this;
3291
3292 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3293 "Removing starting %s from %s", tStartingWindow, fromActivity);
3294 fromActivity.removeChild(tStartingWindow);
3295 fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
Issei Suzukif2f6c912019-11-08 11:24:18 +01003296 fromActivity.mVisibleSetFromTransferredStartingWindow = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003297 addWindow(tStartingWindow);
3298
3299 // Propagate other interesting state between the tokens. If the old token is displayed,
3300 // we should immediately force the new one to be displayed. If it is animating, we need
3301 // to move that animation to the new one.
3302 if (fromActivity.allDrawn) {
3303 allDrawn = true;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003304 }
3305 if (fromActivity.firstWindowDrawn) {
3306 firstWindowDrawn = true;
3307 }
Issei Suzukif2f6c912019-11-08 11:24:18 +01003308 if (fromActivity.isVisible()) {
3309 setVisible(true);
Issei Suzuki1669ea42019-11-06 14:20:59 +01003310 mVisibleRequested = true;
Issei Suzukif2f6c912019-11-08 11:24:18 +01003311 mVisibleSetFromTransferredStartingWindow = true;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003312 }
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01003313 setClientVisible(fromActivity.mClientVisible);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003314
3315 transferAnimation(fromActivity);
3316
3317 // When transferring an animation, we no longer need to apply an animation to the
3318 // the token we transfer the animation over. Thus, set this flag to indicate we've
3319 // transferred the animation.
3320 mUseTransferredAnimation = true;
3321
3322 mWmService.updateFocusedWindowLocked(
3323 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
3324 getDisplayContent().setLayoutNeeded();
3325 mWmService.mWindowPlacerLocked.performSurfacePlacement();
3326 } finally {
3327 Binder.restoreCallingIdentity(origId);
3328 }
3329 return true;
3330 } else if (fromActivity.mStartingData != null) {
3331 // The previous app was getting ready to show a
3332 // starting window, but hasn't yet done so. Steal it!
3333 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
3334 "Moving pending starting from %s to %s", fromActivity, this);
3335 mStartingData = fromActivity.mStartingData;
3336 fromActivity.mStartingData = null;
3337 fromActivity.startingMoved = true;
3338 scheduleAddStartingWindow();
3339 return true;
3340 }
3341
3342 // TODO: Transfer thumbnail
3343
3344 return false;
3345 }
3346
3347 /**
3348 * Tries to transfer the starting window from a token that's above ourselves in the task but
3349 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
3350 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
3351 * immediately finishes after, so we have to transfer T to M.
3352 */
3353 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003354 final PooledFunction p = PooledLambda.obtainFunction(ActivityRecord::transferStartingWindow,
3355 this, PooledLambda.__(ActivityRecord.class));
3356 task.forAllActivities(p);
3357 p.recycle();
3358 }
3359
3360 private boolean transferStartingWindow(ActivityRecord fromActivity) {
3361 if (fromActivity == this) return true;
3362
3363 return !fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003364 }
3365
3366 void checkKeyguardFlagsChanged() {
3367 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
3368 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
3369 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
3370 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
3371 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
3372 getDisplayContent().getDisplayId());
3373 }
3374 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
3375 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
3376 }
3377
3378 boolean containsDismissKeyguardWindow() {
3379 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
3380 // entirety of the relaunch.
3381 if (isRelaunching()) {
3382 return mLastContainsDismissKeyguardWindow;
3383 }
3384
3385 for (int i = mChildren.size() - 1; i >= 0; i--) {
3386 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
3387 return true;
3388 }
3389 }
3390 return false;
3391 }
3392
3393 boolean containsShowWhenLockedWindow() {
3394 // When we are relaunching, it is possible for us to be unfrozen before our previous
3395 // windows have been added back. Using the cached value ensures that our previous
3396 // showWhenLocked preference is honored until relaunching is complete.
3397 if (isRelaunching()) {
3398 return mLastContainsShowWhenLockedWindow;
3399 }
3400
3401 for (int i = mChildren.size() - 1; i >= 0; i--) {
3402 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
3403 return true;
3404 }
3405 }
3406
3407 return false;
3408 }
3409
3410 void setShowWhenLocked(boolean showWhenLocked) {
3411 mShowWhenLocked = showWhenLocked;
Louis Chang149d5c82019-12-30 09:47:39 +08003412 mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
Garfield Tane8d84ab2019-10-11 09:49:40 -07003413 0 /* configChanges */, false /* preserveWindows */);
3414 }
3415
3416 void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
3417 mInheritShownWhenLocked = inheritShowWhenLocked;
Louis Chang149d5c82019-12-30 09:47:39 +08003418 mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
Garfield Tane8d84ab2019-10-11 09:49:40 -07003419 0 /* configChanges */, false /* preserveWindows */);
3420 }
3421
3422 /**
3423 * @return {@code true} if the activity windowing mode is not
3424 * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
3425 * contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
3426 * activity has set {@link #mShowWhenLocked}, or b) if the activity has set
3427 * {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
3428 * conditions a) above.
3429 * Multi-windowing mode will be exited if {@code true} is returned.
3430 */
3431 boolean canShowWhenLocked() {
3432 if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
3433 return true;
3434 } else if (mInheritShownWhenLocked) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003435 final ActivityRecord r = task.getActivityBelow(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003436 return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
3437 || r.containsShowWhenLockedWindow());
3438 } else {
3439 return false;
3440 }
3441 }
3442
3443 /**
3444 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3445 * showing windows during transitions in case we have windows that have wide-color-gamut
3446 * color mode set to avoid jank in the middle of the transition.
3447 */
3448 boolean canShowWindows() {
lumark9bca6b42019-10-17 18:35:22 +08003449 return allDrawn && !(isAnimating() && hasNonDefaultColorWindow());
Garfield Tane8d84ab2019-10-11 09:49:40 -07003450 }
3451
3452 /**
3453 * @return true if we have a window that has a non-default color mode set; false otherwise.
3454 */
3455 private boolean hasNonDefaultColorWindow() {
3456 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3457 true /* topToBottom */);
3458 }
3459
Garfield Tane8d84ab2019-10-11 09:49:40 -07003460 WindowState getImeTargetBelowWindow(WindowState w) {
3461 final int index = mChildren.indexOf(w);
3462 if (index > 0) {
3463 final WindowState target = mChildren.get(index - 1);
3464 if (target.canBeImeTarget()) {
3465 return target;
3466 }
3467 }
3468 return null;
3469 }
3470
3471 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
3472 WindowState candidate = null;
3473 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
3474 final WindowState w = mChildren.get(i);
3475 if (w.mRemoved) {
3476 continue;
3477 }
3478 if (candidate == null) {
3479 candidate = w;
3480 }
3481 }
3482 return candidate;
3483 }
3484
3485 @Override
3486 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
3487 // For legacy reasons we process the TaskStack.mExitingActivities first in DisplayContent
3488 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
3489 // TODO: Investigate if we need to continue to do this or if we can just process them
3490 // in-order.
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003491 if (mIsExiting && !forAllWindowsUnchecked(WindowState::waitingForReplacement, true)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003492 return false;
3493 }
3494 return forAllWindowsUnchecked(callback, traverseTopToBottom);
3495 }
3496
Garfield Tane8d84ab2019-10-11 09:49:40 -07003497 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
3498 boolean traverseTopToBottom) {
3499 return super.forAllWindows(callback, traverseTopToBottom);
3500 }
3501
3502 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003503 boolean forAllActivities(
3504 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
lumark9bca6b42019-10-17 18:35:22 +08003505 return callback.apply(this);
3506 }
3507
3508 @Override
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08003509 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
3510 callback.accept(this);
3511 }
3512
3513 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003514 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
3515 WindowContainer boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08003516 return callback.test(this) ? this : null;
3517 }
3518
3519 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07003520 protected void setLayer(Transaction t, int layer) {
3521 if (!mSurfaceAnimator.hasLeash()) {
3522 t.setLayer(mSurfaceControl, layer);
3523 }
3524 }
3525
3526 @Override
3527 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
3528 if (!mSurfaceAnimator.hasLeash()) {
3529 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
3530 }
3531 }
3532
3533 @Override
3534 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
3535 if (!mSurfaceAnimator.hasLeash()) {
3536 t.reparent(mSurfaceControl, newParent);
3537 }
3538 }
3539
Louis Changcdec0802019-11-11 11:45:07 +08003540 void logStartActivity(int tag, Task task) {
Andrii Kulian79d67982019-08-19 11:56:16 -07003541 final Uri data = intent.getData();
3542 final String strData = data != null ? data.toSafeString() : null;
3543
3544 EventLog.writeEvent(tag,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07003545 mUserId, System.identityHashCode(this), task.mTaskId,
Andrii Kulian79d67982019-08-19 11:56:16 -07003546 shortComponentName, intent.getAction(),
3547 intent.getType(), strData, intent.getFlags());
3548 }
3549
Dianne Hackborn7e269642010-08-25 19:50:20 -07003550 UriPermissionOwner getUriPermissionsLocked() {
3551 if (uriPermissions == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003552 uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
Dianne Hackborn7e269642010-08-25 19:50:20 -07003553 }
3554 return uriPermissions;
3555 }
3556
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003557 void addResultLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 int requestCode, int resultCode,
3559 Intent resultData) {
3560 ActivityResult r = new ActivityResult(from, resultWho,
John Spurlock8a985d22014-02-25 09:40:05 -05003561 requestCode, resultCode, resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 if (results == null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003563 results = new ArrayList<ResultInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 }
3565 results.add(r);
3566 }
3567
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003568 void removeResultsLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 int requestCode) {
3570 if (results != null) {
3571 for (int i=results.size()-1; i>=0; i--) {
3572 ActivityResult r = (ActivityResult)results.get(i);
3573 if (r.mFrom != from) continue;
3574 if (r.mResultWho == null) {
3575 if (resultWho != null) continue;
3576 } else {
3577 if (!r.mResultWho.equals(resultWho)) continue;
3578 }
3579 if (r.mRequestCode != requestCode) continue;
3580
3581 results.remove(i);
3582 }
3583 }
3584 }
3585
Andrii Kulian79d67982019-08-19 11:56:16 -07003586 void sendResult(int callingUid, String resultWho, int requestCode, int resultCode,
3587 Intent data) {
3588 if (callingUid > 0) {
3589 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3590 data, getUriPermissionsLocked(), mUserId);
3591 }
3592
3593 if (DEBUG_RESULTS) {
3594 Slog.v(TAG, "Send activity result to " + this
3595 + " : who=" + resultWho + " req=" + requestCode
3596 + " res=" + resultCode + " data=" + data);
3597 }
3598 if (isState(RESUMED) && attachedToProcess()) {
3599 try {
3600 final ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3601 list.add(new ResultInfo(resultWho, requestCode, resultCode, data));
3602 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3603 ActivityResultItem.obtain(list));
3604 return;
3605 } catch (Exception e) {
3606 Slog.w(TAG, "Exception thrown sending result to " + this, e);
3607 }
3608 }
3609
3610 addResultLocked(null /* from */, resultWho, requestCode, resultCode, data);
3611 }
3612
Andrii Kulian21713ac2016-10-12 22:05:05 -07003613 private void addNewIntentLocked(ReferrerIntent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 if (newIntents == null) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003615 newIntents = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 }
3617 newIntents.add(intent);
3618 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07003619
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003620 final boolean isSleeping() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003621 final ActivityStack stack = getActivityStack();
3622 return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003623 }
3624
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003625 /**
3626 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3627 * method will be called at the proper time.
3628 */
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003629 final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
Dianne Hackborn514074f2013-02-11 10:52:46 -08003630 // The activity now gets access to the data associated with this Intent.
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003631 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3632 intent, getUriPermissionsLocked(), mUserId);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003633 final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
Craig Mautner86d67a42013-05-14 10:34:38 -07003634 boolean unsent = true;
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003635 final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
Wale Ogunwale826c7062016-09-13 08:25:54 -07003636
3637 // We want to immediately deliver the intent to the activity if:
Wale Ogunwale03f7e9e2016-09-22 09:04:09 -07003638 // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
3639 // the user to see the visual effects caused by the intent delivery now.
Wale Ogunwale826c7062016-09-13 08:25:54 -07003640 // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07003641 if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
3642 && attachedToProcess()) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003643 try {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003644 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
3645 ar.add(rintent);
Louis Changea203cd2019-07-01 12:39:31 +08003646 // Making sure the client state is RESUMED after transaction completed and doing
3647 // so only if activity is currently RESUMED. Otherwise, client may have extra
3648 // life-cycle calls to RESUMED (and PAUSED later).
Louis Chang92d16522019-02-27 12:56:18 +08003649 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Louis Changea203cd2019-07-01 12:39:31 +08003650 NewIntentItem.obtain(ar, mState == RESUMED));
Craig Mautner86d67a42013-05-14 10:34:38 -07003651 unsent = false;
Dianne Hackborn39792d22010-08-19 18:01:52 -07003652 } catch (RemoteException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003653 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003654 } catch (NullPointerException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003655 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003656 }
3657 }
Craig Mautner86d67a42013-05-14 10:34:38 -07003658 if (unsent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003659 addNewIntentLocked(rintent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003660 }
3661 }
3662
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003663 void updateOptionsLocked(ActivityOptions options) {
3664 if (options != null) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003665 if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003666 if (pendingOptions != null) {
3667 pendingOptions.abort();
3668 }
3669 pendingOptions = options;
3670 }
3671 }
3672
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003673 void applyOptionsLocked() {
George Mount2c92c972014-03-20 09:38:23 -07003674 if (pendingOptions != null
Ruben Brunkf53497c2017-03-27 20:26:17 -07003675 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003676 if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003677 applyOptionsLocked(pendingOptions, intent);
chaviw82a0ba82018-03-15 14:26:29 -07003678 if (task == null) {
3679 clearOptionsLocked(false /* withAbort */);
3680 } else {
3681 // This will clear the options for all the ActivityRecords for this Task.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003682 task.forAllActivities((r) -> {
3683 r.clearOptionsLocked(false /* withAbort */);
3684 });
chaviw82a0ba82018-03-15 14:26:29 -07003685 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003686 }
3687 }
3688
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003689 /**
3690 * Apply override app transition base on options & animation type.
3691 */
3692 void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
3693 final int animationType = pendingOptions.getAnimationType();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003694 final DisplayContent displayContent = getDisplayContent();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003695 switch (animationType) {
3696 case ANIM_CUSTOM:
3697 displayContent.mAppTransition.overridePendingAppTransition(
3698 pendingOptions.getPackageName(),
3699 pendingOptions.getCustomEnterResId(),
3700 pendingOptions.getCustomExitResId(),
3701 pendingOptions.getOnAnimationStartListener());
3702 break;
3703 case ANIM_CLIP_REVEAL:
3704 displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
3705 pendingOptions.getStartX(), pendingOptions.getStartY(),
3706 pendingOptions.getWidth(), pendingOptions.getHeight());
3707 if (intent.getSourceBounds() == null) {
3708 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3709 pendingOptions.getStartY(),
3710 pendingOptions.getStartX() + pendingOptions.getWidth(),
3711 pendingOptions.getStartY() + pendingOptions.getHeight()));
3712 }
3713 break;
3714 case ANIM_SCALE_UP:
3715 displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
3716 pendingOptions.getStartX(), pendingOptions.getStartY(),
3717 pendingOptions.getWidth(), pendingOptions.getHeight());
3718 if (intent.getSourceBounds() == null) {
3719 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3720 pendingOptions.getStartY(),
3721 pendingOptions.getStartX() + pendingOptions.getWidth(),
3722 pendingOptions.getStartY() + pendingOptions.getHeight()));
3723 }
3724 break;
3725 case ANIM_THUMBNAIL_SCALE_UP:
3726 case ANIM_THUMBNAIL_SCALE_DOWN:
3727 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
3728 final GraphicBuffer buffer = pendingOptions.getThumbnail();
3729 displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
3730 pendingOptions.getStartX(), pendingOptions.getStartY(),
3731 pendingOptions.getOnAnimationStartListener(),
3732 scaleUp);
3733 if (intent.getSourceBounds() == null && buffer != null) {
3734 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3735 pendingOptions.getStartY(),
3736 pendingOptions.getStartX() + buffer.getWidth(),
3737 pendingOptions.getStartY() + buffer.getHeight()));
3738 }
3739 break;
3740 case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
3741 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
3742 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
3743 final IAppTransitionAnimationSpecsFuture specsFuture =
3744 pendingOptions.getSpecsFuture();
3745 if (specsFuture != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003746 displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
3747 specsFuture, pendingOptions.getOnAnimationStartListener(),
3748 animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
3749 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
3750 && specs != null) {
3751 displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
3752 specs, pendingOptions.getOnAnimationStartListener(),
3753 pendingOptions.getAnimationFinishedListener(), false);
3754 } else {
3755 displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
3756 pendingOptions.getThumbnail(),
3757 pendingOptions.getStartX(), pendingOptions.getStartY(),
3758 pendingOptions.getWidth(), pendingOptions.getHeight(),
3759 pendingOptions.getOnAnimationStartListener(),
3760 (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
3761 if (intent.getSourceBounds() == null) {
3762 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3763 pendingOptions.getStartY(),
3764 pendingOptions.getStartX() + pendingOptions.getWidth(),
3765 pendingOptions.getStartY() + pendingOptions.getHeight()));
3766 }
3767 }
3768 break;
3769 case ANIM_OPEN_CROSS_PROFILE_APPS:
3770 displayContent.mAppTransition
3771 .overridePendingAppTransitionStartCrossProfileApps();
3772 break;
3773 case ANIM_REMOTE_ANIMATION:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003774 displayContent.mAppTransition.overridePendingAppTransitionRemote(
3775 pendingOptions.getRemoteAnimationAdapter());
3776 break;
3777 case ANIM_NONE:
Louis Chang477e93e2019-04-24 18:35:20 +08003778 case ANIM_UNDEFINED:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003779 break;
3780 default:
3781 Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
3782 break;
3783 }
3784 }
3785
Garfield Tane8d84ab2019-10-11 09:49:40 -07003786 void clearAllDrawn() {
3787 allDrawn = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003788 }
3789
3790 /**
3791 * Returns whether the drawn window states of this {@link ActivityRecord} has considered every
3792 * child {@link WindowState}. A child is considered if it has been passed into
3793 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
3794 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
3795 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
3796 *
3797 * @return {@code true} If all children have been considered, {@code false}.
3798 */
3799 private boolean allDrawnStatesConsidered() {
3800 for (int i = mChildren.size() - 1; i >= 0; --i) {
3801 final WindowState child = mChildren.get(i);
3802 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
3803 return false;
3804 }
3805 }
3806 return true;
3807 }
3808
3809 /**
3810 * Determines if the token has finished drawing. This should only be called from
3811 * {@link DisplayContent#applySurfaceChangesTransaction}
3812 */
3813 void updateAllDrawn() {
3814 if (!allDrawn) {
3815 // Number of drawn windows can be less when a window is being relaunched, wait for
3816 // all windows to be launched and drawn for this token be considered all drawn.
3817 final int numInteresting = mNumInterestingWindows;
3818
3819 // We must make sure that all present children have been considered (determined by
3820 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
3821 // drawn.
3822 if (numInteresting > 0 && allDrawnStatesConsidered()
3823 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
3824 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
3825 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
3826 allDrawn = true;
3827 // Force an additional layout pass where
3828 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
3829 if (mDisplayContent != null) {
3830 mDisplayContent.setLayoutNeeded();
3831 }
3832 mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
3833
3834 // Notify the pinned stack upon all windows drawn. If there was an animation in
3835 // progress then this signal will resume that animation.
Louis Changdc077272019-11-12 16:52:56 +08003836 final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003837 if (pinnedStack != null) {
3838 pinnedStack.onAllWindowsDrawn();
3839 }
3840 }
3841 }
3842 }
3843
Adam Powellcfbe9be2013-11-06 14:58:58 -08003844 ActivityOptions getOptionsForTargetActivityLocked() {
3845 return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
3846 }
3847
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003848 void clearOptionsLocked() {
chaviw82a0ba82018-03-15 14:26:29 -07003849 clearOptionsLocked(true /* withAbort */);
3850 }
3851
3852 void clearOptionsLocked(boolean withAbort) {
3853 if (withAbort && pendingOptions != null) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003854 pendingOptions.abort();
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003855 }
chaviw82a0ba82018-03-15 14:26:29 -07003856 pendingOptions = null;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003857 }
3858
Jorim Jaggi346702a2019-05-08 17:49:33 +02003859 ActivityOptions takeOptionsLocked(boolean fromClient) {
3860 if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
3861 + Debug.getCallers(6));
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003862 ActivityOptions opts = pendingOptions;
Jorim Jaggi346702a2019-05-08 17:49:33 +02003863
3864 // If we are trying to take activity options from the client, do not null it out if it's a
3865 // remote animation as the client doesn't need it ever. This is a workaround when client is
3866 // faster to take the options than we are to resume the next activity.
3867 // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
3868 // timing somehow
3869 if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
3870 pendingOptions = null;
3871 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003872 return opts;
3873 }
3874
Issei Suzuki1669ea42019-11-06 14:20:59 +01003875 boolean allowMoveToFront() {
3876 return pendingOptions == null || !pendingOptions.getAvoidMoveToFront();
3877 }
3878
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003879 void removeUriPermissionsLocked() {
Dianne Hackborn7e269642010-08-25 19:50:20 -07003880 if (uriPermissions != null) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003881 uriPermissions.removeUriPermissions();
Dianne Hackborn7e269642010-08-25 19:50:20 -07003882 uriPermissions = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003883 }
3884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885
3886 void pauseKeyDispatchingLocked() {
3887 if (!keysPaused) {
3888 keysPaused = true;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003889
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003890 if (getDisplayContent() != null) {
3891 getDisplayContent().getInputMonitor().pauseDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 }
3894 }
3895
3896 void resumeKeyDispatchingLocked() {
3897 if (keysPaused) {
3898 keysPaused = false;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003899
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003900 if (getDisplayContent() != null) {
3901 getDisplayContent().getInputMonitor().resumeDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903 }
3904 }
3905
Jorim Jaggie7d2b852017-08-28 17:55:15 +02003906 private void updateTaskDescription(CharSequence description) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07003907 task.lastDescription = description;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003908 }
3909
Wale Ogunwaleec950642017-04-25 07:44:21 -07003910 void setDeferHidingClient(boolean deferHidingClient) {
3911 if (mDeferHidingClient == deferHidingClient) {
3912 return;
3913 }
3914 mDeferHidingClient = deferHidingClient;
Issei Suzuki1669ea42019-11-06 14:20:59 +01003915 if (!mDeferHidingClient && !mVisibleRequested) {
Wale Ogunwaleec950642017-04-25 07:44:21 -07003916 // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
3917 // update the visibility.
3918 setVisibility(false);
3919 }
Wale Ogunwale89973222017-04-23 18:39:45 -07003920 }
3921
Garfield Tane8d84ab2019-10-11 09:49:40 -07003922 @Override
3923 boolean isVisible() {
3924 // If the activity isn't hidden then it is considered visible and there is no need to check
3925 // its children windows to see if they are visible.
Issei Suzukif2f6c912019-11-08 11:24:18 +01003926 return mVisible;
3927 }
3928
3929 void setVisible(boolean visible) {
3930 if (visible != mVisible) {
3931 mVisible = visible;
3932 scheduleAnimation();
3933 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07003934 }
3935
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003936 /**
3937 * Set visibility on this {@link ActivityRecord}
3938 *
3939 * <p class="note"><strong>Note: </strong>This function might not update the visibility of
3940 * this {@link ActivityRecord} immediately. In case we are preparing an app transition, we
3941 * delay changing the visibility of this {@link ActivityRecord} until we execute that
3942 * transition.</p>
3943 *
3944 * @param visible {@code true} if the {@link ActivityRecord} should become visible, otherwise
3945 * this should become invisible.
3946 */
Wale Ogunwaleec950642017-04-25 07:44:21 -07003947 void setVisibility(boolean visible) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003948 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003949 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
3950 + appToken);
3951 return;
3952 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01003953 if (visible) {
3954 mDeferHidingClient = false;
3955 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003956 setVisibility(visible, mDeferHidingClient);
Riddle Hsua0022cd2019-09-09 21:12:41 +08003957 mAtmService.addWindowLayoutReasons(
3958 ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
Bryce Lee2a3cc462017-10-27 10:57:35 -07003959 mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07003960 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
3961 }
3962
Issei Suzuki1669ea42019-11-06 14:20:59 +01003963 @VisibleForTesting
Garfield Tane8d84ab2019-10-11 09:49:40 -07003964 void setVisibility(boolean visible, boolean deferHidingClient) {
3965 final AppTransition appTransition = getDisplayContent().mAppTransition;
3966
3967 // Don't set visibility to false if we were already not visible. This prevents WM from
3968 // adding the app to the closing app list which doesn't make sense for something that is
3969 // already not visible. However, set visibility to true even if we are already visible.
3970 // This makes sure the app is added to the opening apps list so that the right
3971 // transition can be selected.
3972 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
3973 // concept of setting visibility...
Issei Suzuki1669ea42019-11-06 14:20:59 +01003974 if (!visible && !mVisibleRequested) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003975
3976 if (!deferHidingClient && mLastDeferHidingClient) {
3977 // We previously deferred telling the client to hide itself when visibility was
3978 // initially set to false. Now we would like it to hide, so go ahead and set it.
3979 mLastDeferHidingClient = deferHidingClient;
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01003980 setClientVisible(false);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003981 }
3982 return;
3983 }
3984
3985 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzukif2f6c912019-11-08 11:24:18 +01003986 "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
3987 appToken, visible, appTransition, isVisible(), mVisibleRequested,
Garfield Tane8d84ab2019-10-11 09:49:40 -07003988 Debug.getCallers(6));
3989
3990 final DisplayContent displayContent = getDisplayContent();
3991 displayContent.mOpeningApps.remove(this);
3992 displayContent.mClosingApps.remove(this);
3993 if (isInChangeTransition()) {
3994 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3995 }
3996 displayContent.mChangingApps.remove(this);
3997 waitingToShow = false;
Issei Suzuki1669ea42019-11-06 14:20:59 +01003998 mVisibleRequested = visible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003999 mLastDeferHidingClient = deferHidingClient;
4000
4001 if (!visible) {
4002 // If the app is dead while it was visible, we kept its dead window on screen.
4003 // Now that the app is going invisible, we can remove it. It will be restarted
4004 // if made visible again.
4005 removeDeadWindows();
4006 } else {
4007 if (!appTransition.isTransitionSet()
4008 && appTransition.isReady()) {
4009 // Add the app mOpeningApps if transition is unset but ready. This means
4010 // we're doing a screen freeze, and the unfreeze will wait for all opening
4011 // apps to be ready.
4012 displayContent.mOpeningApps.add(this);
4013 }
4014 startingMoved = false;
4015 // If the token is currently hidden (should be the common case), or has been
4016 // stopped, then we need to set up to wait for its windows to be ready.
Issei Suzukif2f6c912019-11-08 11:24:18 +01004017 if (!isVisible() || mAppStopped) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004018 clearAllDrawn();
4019
4020 // If the app was already visible, don't reset the waitingToShow state.
Issei Suzukif2f6c912019-11-08 11:24:18 +01004021 if (!isVisible()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004022 waitingToShow = true;
4023
4024 // If the client isn't hidden, we don't need to reset the drawing state.
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01004025 if (!isClientVisible()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004026 // Let's reset the draw state in order to prevent the starting window to be
4027 // immediately dismissed when the app still has the surface.
4028 forAllWindows(w -> {
4029 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
4030 w.mWinAnimator.resetDrawState();
4031
4032 // Force add to mResizingWindows, so that we are guaranteed to get
4033 // another reportDrawn callback.
4034 w.resetLastContentInsets();
4035 }
4036 }, true /* traverseTopToBottom */);
4037 }
4038 }
4039 }
4040
4041 // In the case where we are making an app visible but holding off for a transition,
4042 // we still need to tell the client to make its windows visible so they get drawn.
4043 // Otherwise, we will wait on performing the transition until all windows have been
4044 // drawn, they never will be, and we are sad.
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01004045 setClientVisible(true);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004046
4047 requestUpdateWallpaperIfNeeded();
4048
4049 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
4050 mAppStopped = false;
4051
4052 transferStartingWindowFromHiddenAboveTokenIfNeeded();
4053 }
4054
4055 // If we are preparing an app transition, then delay changing
4056 // the visibility of this token until we execute that transition.
lumark3b8bbc82019-12-02 16:22:08 +08004057 // Note that we ignore display frozen since we want the opening / closing transition type
4058 // can be updated correctly even display frozen, and it's safe since in applyAnimation will
4059 // still check DC#okToAnimate again if the transition animation is fine to apply.
4060 if (okToAnimate(true /* ignoreFrozen */) && appTransition.isTransitionSet()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004061 if (visible) {
4062 displayContent.mOpeningApps.add(this);
4063 mEnteringAnimation = true;
4064 } else {
4065 displayContent.mClosingApps.add(this);
4066 mEnteringAnimation = false;
4067 }
4068 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
4069 // We're launchingBehind, add the launching activity to mOpeningApps.
4070 final WindowState win = getDisplayContent().findFocusedWindow();
4071 if (win != null) {
4072 final ActivityRecord focusedActivity = win.mActivityRecord;
4073 if (focusedActivity != null) {
4074 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
4075 "TRANSIT_TASK_OPEN_BEHIND, adding %s to mOpeningApps",
4076 focusedActivity);
4077
4078 // Force animation to be loaded.
4079 displayContent.mOpeningApps.add(focusedActivity);
4080 }
4081 }
4082 }
4083 return;
4084 }
4085
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004086 commitVisibility(visible, true /* performLayout */);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004087 updateReportedVisibilityLocked();
4088 }
4089
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004090 @Override
4091 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
4092 boolean isVoiceInteraction) {
4093 if (mUseTransferredAnimation) {
4094 return false;
4095 }
4096 return super.applyAnimation(lp, transit, enter, isVoiceInteraction);
4097 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004098
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004099 /**
4100 * Update visibility to this {@link ActivityRecord}.
4101 *
4102 * <p class="note"><strong>Note: </strong> Unlike {@link #setVisibility}, this immediately
4103 * updates the visibility without starting an app transition. Since this function may start
4104 * animation on {@link WindowState} depending on app transition animation status, an app
4105 * transition animation must be started before calling this function if necessary.</p>
4106 *
4107 * @param visible {@code true} if this {@link ActivityRecord} should become visible, otherwise
4108 * this should become invisible.
4109 * @param performLayout if {@code true}, perform surface placement after committing visibility.
4110 */
4111 void commitVisibility(boolean visible, boolean performLayout) {
4112 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
Garfield Tane8d84ab2019-10-11 09:49:40 -07004113 // been set by the app now.
Issei Suzukif2f6c912019-11-08 11:24:18 +01004114 mVisibleSetFromTransferredStartingWindow = false;
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004115 if (visible == isVisible()) {
4116 return;
Garfield Tane8d84ab2019-10-11 09:49:40 -07004117 }
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004118
4119 final int windowsCount = mChildren.size();
4120 for (int i = 0; i < windowsCount; i++) {
4121 mChildren.get(i).onAppVisibilityChanged(visible, isAnimating(PARENTS));
4122 }
4123 setVisible(visible);
4124 mVisibleRequested = visible;
4125 if (!visible) {
4126 stopFreezingScreen(true, true);
4127 } else {
4128 // If we are being set visible, and the starting window is not yet displayed,
4129 // then make sure it doesn't get displayed.
4130 if (startingWindow != null && !startingWindow.isDrawnLw()) {
4131 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
4132 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
4133 }
4134 // We are becoming visible, so better freeze the screen with the windows that are
4135 // getting visible so we also wait for them.
4136 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
4137 }
4138 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
4139 "commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
4140 isVisible(), mVisibleRequested);
4141 final DisplayContent displayContent = getDisplayContent();
4142 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
4143 if (performLayout) {
4144 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4145 false /*updateInputWindows*/);
4146 mWmService.mWindowPlacerLocked.performSurfacePlacement();
4147 }
4148 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004149 mUseTransferredAnimation = false;
4150
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004151 postApplyAnimation(visible);
4152 }
4153
4154 /**
4155 * Post process after applying an app transition animation.
4156 *
4157 * <p class="note"><strong>Note: </strong> This function must be called after the animations
4158 * have been applied and {@link #commitVisibility}.</p>
4159 *
4160 * @param visible {@code true} if this {@link ActivityRecord} has become visible, otherwise
4161 * this has become invisible.
4162 */
4163 private void postApplyAnimation(boolean visible) {
4164 final boolean delayed = isAnimating(PARENTS | CHILDREN);
lumark9bca6b42019-10-17 18:35:22 +08004165 if (!delayed) {
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004166 // We aren't delayed anything, but exiting windows rely on the animation finished
4167 // callback being called in case the ActivityRecord was pretending to be delayed,
Garfield Tane8d84ab2019-10-11 09:49:40 -07004168 // which we might have done because we were in closing/opening apps list.
4169 onAnimationFinished();
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004170 if (visible) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004171 // The token was made immediately visible, there will be no entrance animation.
4172 // We need to inform the client the enter animation was finished.
4173 mEnteringAnimation = true;
4174 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
4175 token);
4176 }
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004177 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004178
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004179 // If we're becoming visible, immediately change client visibility as well. there seem
4180 // to be some edge cases where we change our visibility but client visibility never gets
4181 // updated.
4182 // If we're becoming invisible, update the client visibility if we are not running an
4183 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
4184 if (visible || !isAnimating(PARENTS)) {
4185 setClientVisible(visible);
4186 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004187
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004188 final DisplayContent displayContent = getDisplayContent();
4189 if (!displayContent.mClosingApps.contains(this)
4190 && !displayContent.mOpeningApps.contains(this)) {
4191 // The token is not closing nor opening, so even if there is an animation set, that
4192 // doesn't mean that it goes through the normal app transition cycle so we have
4193 // to inform the docked controller about visibility change.
4194 // TODO(multi-display): notify docked divider on all displays where visibility was
4195 // affected.
4196 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
Garfield Tane8d84ab2019-10-11 09:49:40 -07004197
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004198 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
4199 // will not be taken.
4200 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
4201 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004202
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004203 // If we are hidden but there is no delay needed we immediately
4204 // apply the Surface transaction so that the ActivityManager
4205 // can have some guarantee on the Surface state following
4206 // setting the visibility. This captures cases like dismissing
4207 // the docked or pinned stack where there is no app transition.
4208 //
4209 // In the case of a "Null" animation, there will be
4210 // no animation but there will still be a transition set.
4211 // We still need to delay hiding the surface such that it
4212 // can be synchronized with showing the next surface in the transition.
4213 if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
4214 SurfaceControl.openTransaction();
4215 try {
4216 forAllWindows(win -> {
4217 win.mWinAnimator.hide("immediately hidden"); }, true);
4218 } finally {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004219 SurfaceControl.closeTransaction();
4220 }
4221 }
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004222 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004223
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004224 /**
4225 * Check if visibility of this {@link ActivityRecord} should be updated as part of an app
4226 * transition.
4227 *
4228 * <p class="note><strong>Note:</strong> If the visibility of this {@link ActivityRecord} is
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004229 * already set to {@link #mVisible}, we don't need to update the visibility. So {@code false} is
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004230 * returned.</p>
4231 *
4232 * @param visible {@code true} if this {@link ActivityRecord} should become visible,
4233 * {@code false} if this should become invisible.
4234 * @return {@code true} if visibility of this {@link ActivityRecord} should be updated, and
4235 * an app transition animation should be run.
4236 */
4237 boolean shouldApplyAnimation(boolean visible) {
4238 // Allow for state update and animation to be applied if:
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004239 // * activity is transitioning visibility state
4240 // * or the activity was marked as hidden and is exiting before we had a chance to play the
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004241 // transition animation
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004242 // * or this is an opening app and windows are being replaced (e.g. freeform window to
4243 // normal window).
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004244 return isVisible() != visible || (!isVisible() && mIsExiting)
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004245 || (visible && forAllWindows(WindowState::waitingForReplacement, true));
Garfield Tane8d84ab2019-10-11 09:49:40 -07004246 }
4247
Garfield Tane8d84ab2019-10-11 09:49:40 -07004248 /**
4249 * See {@link Activity#setDisablePreviewScreenshots}.
4250 */
4251 void setDisablePreviewScreenshots(boolean disable) {
4252 mDisablePreviewScreenshots = disable;
4253 }
4254
4255 /**
4256 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
4257 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
4258 * we can't take a snapshot for other reasons, for example, if we have a secure window.
4259 *
4260 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
4261 * screenshot.
4262 */
4263 boolean shouldUseAppThemeSnapshot() {
4264 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
4265 true /* topToBottom */);
4266 }
4267
4268 /**
4269 * Sets whether the current launch can turn the screen on.
4270 * @see #currentLaunchCanTurnScreenOn()
4271 */
4272 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
4273 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
4274 }
4275
4276 /**
4277 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
4278 * relayouts from turning the screen back on. The screen should only turn on at most
4279 * once per activity resume.
4280 * <p>
4281 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
4282 * or {@link ActivityRecord#canTurnScreenOn} is set.
4283 *
4284 * @return {@code true} if the activity is ready to turn on the screen.
4285 */
4286 boolean currentLaunchCanTurnScreenOn() {
4287 return mCurrentLaunchCanTurnScreenOn;
4288 }
4289
Bryce Lee7ace3952018-02-16 14:34:32 -08004290 void setState(ActivityState state, String reason) {
4291 if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
4292 + " to:" + state + " reason:" + reason);
Bryce Lee6ff17072018-02-28 07:26:17 -08004293
Bryce Leeb0f993f2018-03-02 15:38:01 -08004294 if (state == mState) {
4295 // No need to do anything if state doesn't change.
4296 if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
4297 return;
4298 }
4299
Bryce Leeb0f993f2018-03-02 15:38:01 -08004300 mState = state;
4301
Louis Changcdec0802019-11-11 11:45:07 +08004302 if (task != null) {
4303 task.onActivityStateChanged(this, state, reason);
Bryce Leec4ab62a2018-03-05 14:19:26 -08004304 }
Robert Carr29daa922018-04-27 11:56:48 -07004305
Robert Carr9e1bf7c2018-05-31 15:39:07 -07004306 // The WindowManager interprets the app stopping signal as
4307 // an indication that the Surface will eventually be destroyed.
4308 // This however isn't necessarily true if we are going to sleep.
4309 if (state == STOPPING && !isSleeping()) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004310 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004311 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
4312 + appToken);
4313 return;
4314 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004315 detachChildren();
Robert Carr29daa922018-04-27 11:56:48 -07004316 }
Hui Yu03d12402018-12-06 18:00:37 -08004317
4318 if (state == RESUMED) {
4319 mAtmService.updateBatteryStats(this, true);
4320 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
4321 } else if (state == PAUSED) {
4322 mAtmService.updateBatteryStats(this, false);
4323 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
4324 } else if (state == STOPPED) {
4325 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
4326 } else if (state == DESTROYED) {
4327 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
4328 }
Bryce Lee7ace3952018-02-16 14:34:32 -08004329 }
4330
4331 ActivityState getState() {
4332 return mState;
4333 }
4334
4335 /**
4336 * Returns {@code true} if the Activity is in the specified state.
4337 */
4338 boolean isState(ActivityState state) {
4339 return state == mState;
4340 }
4341
4342 /**
4343 * Returns {@code true} if the Activity is in one of the specified states.
4344 */
4345 boolean isState(ActivityState state1, ActivityState state2) {
4346 return state1 == mState || state2 == mState;
4347 }
4348
4349 /**
4350 * Returns {@code true} if the Activity is in one of the specified states.
4351 */
4352 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3) {
4353 return state1 == mState || state2 == mState || state3 == mState;
4354 }
4355
4356 /**
4357 * Returns {@code true} if the Activity is in one of the specified states.
4358 */
4359 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4360 ActivityState state4) {
4361 return state1 == mState || state2 == mState || state3 == mState || state4 == mState;
4362 }
4363
Louis Changeadb22f2019-06-19 12:09:23 +08004364 /**
4365 * Returns {@code true} if the Activity is in one of the specified states.
4366 */
4367 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4368 ActivityState state4, ActivityState state5) {
4369 return state1 == mState || state2 == mState || state3 == mState || state4 == mState
4370 || state5 == mState;
4371 }
4372
Garfield Tane8d84ab2019-10-11 09:49:40 -07004373 void destroySurfaces() {
4374 destroySurfaces(false /*cleanupOnResume*/);
4375 }
4376
4377 /**
4378 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
4379 * the client has finished with them.
4380 *
4381 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
4382 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
4383 * others so that they are ready to be reused. If set to false (common case), destroy all
4384 * surfaces that's eligible, if the app is already stopped.
4385 */
4386 private void destroySurfaces(boolean cleanupOnResume) {
4387 boolean destroyedSomething = false;
4388
4389 // Copying to a different list as multiple children can be removed.
4390 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
4391 for (int i = children.size() - 1; i >= 0; i--) {
4392 final WindowState win = children.get(i);
4393 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
4394 }
4395 if (destroyedSomething) {
4396 final DisplayContent dc = getDisplayContent();
4397 dc.assignWindowLayers(true /*setLayoutNeeded*/);
4398 updateLetterboxSurface(null);
4399 }
4400 }
4401
Jorim Jaggibae01b12017-04-11 16:29:10 -07004402 void notifyAppResumed(boolean wasStopped) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004403 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004404 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
4405 + appToken);
4406 return;
4407 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004408 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
4409 wasStopped, this);
4410 mAppStopped = false;
4411 // Allow the window to turn the screen on once the app is resumed again.
4412 setCurrentLaunchCanTurnScreenOn(true);
4413 if (!wasStopped) {
4414 destroySurfaces(true /*cleanupOnResume*/);
4415 }
4416 }
4417
4418 /**
4419 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
4420 * keeping alive in case they were still being used.
4421 */
4422 void notifyAppStopped() {
4423 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
4424 mAppStopped = true;
4425 // Reset the last saved PiP snap fraction on app stop.
jorgegil@google.com62f735e2019-10-30 14:37:19 -07004426 mDisplayContent.mPinnedStackControllerLocked.resetReentryBounds(mActivityComponent);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004427 destroySurfaces();
4428 // Remove any starting window that was added for this app if they are still around.
4429 removeStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08004430 }
4431
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004432 /**
4433 * Suppress transition until the new activity becomes ready, otherwise the keyguard can appear
4434 * for a short amount of time before the new process with the new activity had the ability to
4435 * set its showWhenLocked flags.
4436 */
4437 void notifyUnknownVisibilityLaunchedForKeyguardTransition() {
Jorim Jaggi838c2452017-08-28 15:44:43 +02004438 // No display activities never add a window, so there is no point in waiting them for
4439 // relayout.
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004440 if (noDisplay || !mStackSupervisor.getKeyguardController().isKeyguardLocked()) {
4441 return;
Andrii Kulian21713ac2016-10-12 22:05:05 -07004442 }
4443
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004444 mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004445 }
4446
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004447 /** @return {@code true} if this activity should be made visible. */
4448 boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
Garfield Tan47e576c2019-01-28 10:26:23 -08004449 // Check whether activity should be visible without Keyguard influence
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004450 visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
4451 && okToShowLocked();
4452
4453 if (ignoringKeyguard) {
4454 return visibleIgnoringKeyguard;
4455 }
Garfield Tan47e576c2019-01-28 10:26:23 -08004456
4457 final ActivityStack stack = getActivityStack();
4458 if (stack == null) {
4459 return false;
4460 }
4461
Issei Suzuki62356a22019-04-11 16:46:37 +02004462 // Whether the activity is on the sleeping display.
4463 // TODO(b/129750406): This should be applied for the default display, too.
4464 final boolean isDisplaySleeping = getDisplay().isSleeping()
4465 && getDisplayId() != DEFAULT_DISPLAY;
Garfield Tan47e576c2019-01-28 10:26:23 -08004466 // Whether this activity is the top activity of this stack.
Wale Ogunwale21e06482019-11-18 05:14:15 -08004467 final boolean isTop = this == stack.getTopNonFinishingActivity();
Garfield Tan47e576c2019-01-28 10:26:23 -08004468 // Exclude the case where this is the top activity in a pinned stack.
4469 final boolean isTopNotPinnedStack = stack.isAttached()
4470 && stack.getDisplay().isTopNotPinnedStack(stack);
Issei Suzuki62356a22019-04-11 16:46:37 +02004471 // Now check whether it's really visible depending on Keyguard state, and update
4472 // {@link ActivityStack} internal states.
4473 final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
Garfield Tan47e576c2019-01-28 10:26:23 -08004474 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
Issei Suzuki62356a22019-04-11 16:46:37 +02004475 return visibleIgnoringDisplayStatus && !isDisplaySleeping;
Garfield Tan47e576c2019-01-28 10:26:23 -08004476 }
4477
4478 boolean shouldBeVisible() {
4479 final ActivityStack stack = getActivityStack();
4480 if (stack == null) {
4481 return false;
4482 }
4483
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004484 final boolean behindFullscreenActivity = stack.checkBehindFullscreenActivity(
4485 this, null /* handleBehindFullscreenActivity */);
4486 return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */);
Garfield Tan47e576c2019-01-28 10:26:23 -08004487 }
4488
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004489 void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004490 // This activity is not currently visible, but is running. Tell it to become visible.
Bryce Lee7ace3952018-02-16 14:34:32 -08004491 if (mState == RESUMED || this == starting) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004492 if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
Bryce Lee7ace3952018-02-16 14:34:32 -08004493 "Not making visible, r=" + this + " state=" + mState + " starting=" + starting);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004494 return;
4495 }
4496
4497 // If this activity is paused, tell it to now show its window.
4498 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
4499 "Making visible and scheduling visibility: " + this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004500 final ActivityStack stack = getActivityStack();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004501 try {
4502 if (stack.mTranslucentActivityWaiting != null) {
4503 updateOptionsLocked(returningOptions);
4504 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
4505 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01004506 setVisibility(true);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004507 sleeping = false;
Wale Ogunwale342fbe92018-10-09 08:44:10 -07004508 app.postPendingUiCleanMsg(true);
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004509 if (reportToClient) {
4510 makeClientVisible();
4511 } else {
4512 mClientVisibilityDeferred = true;
4513 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004514 // The activity may be waiting for stop, but that is no longer appropriate for it.
4515 mStackSupervisor.mStoppingActivities.remove(this);
4516 mStackSupervisor.mGoingToSleepActivities.remove(this);
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004517 } catch (Exception e) {
4518 // Just skip on any failure; we'll make it visible when it next restarts.
4519 Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
4520 }
4521 handleAlreadyVisible();
4522 }
Andrii Kulian0d595f32018-02-21 15:47:33 -08004523
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004524 /** Send visibility change message to the client and pause if needed. */
4525 void makeClientVisible() {
4526 mClientVisibilityDeferred = false;
4527 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004528 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004529 WindowVisibilityItem.obtain(true /* showWindow */));
Andrii Kulian6b321512019-01-23 06:37:00 +00004530 makeActiveIfNeeded(null /* activeActivity*/);
Louis Changeadb22f2019-06-19 12:09:23 +08004531 if (isState(STOPPING, STOPPED)) {
4532 // Set state to STARTED in order to have consistent state with client while
4533 // making an non-active activity visible from stopped.
4534 setState(STARTED, "makeClientVisible");
Louis Chang3d119a92019-04-22 10:45:37 +08004535 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004536 } catch (Exception e) {
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004537 Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004538 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004539 }
4540
Andrii Kulian79d67982019-08-19 11:56:16 -07004541 void makeInvisible() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01004542 if (!mVisibleRequested) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004543 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
4544 return;
4545 }
4546 // Now for any activities that aren't visible to the user, make sure they no longer are
4547 // keeping the screen frozen.
4548 if (DEBUG_VISIBILITY) {
4549 Slog.v(TAG_VISIBILITY, "Making invisible: " + this + ", state=" + getState());
4550 }
4551 try {
4552 final boolean canEnterPictureInPicture = checkEnterPictureInPictureState(
4553 "makeInvisible", true /* beforeStopping */);
4554 // Defer telling the client it is hidden if it can enter Pip and isn't current paused,
4555 // stopped or stopping. This gives it a chance to enter Pip in onPause().
4556 // TODO: There is still a question surrounding activities in multi-window mode that want
4557 // to enter Pip after they are paused, but are still visible. I they should be okay to
4558 // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and
4559 // the current contract for "auto-Pip" is that the app should enter it before onPause
4560 // returns. Just need to confirm this reasoning makes sense.
4561 final boolean deferHidingClient = canEnterPictureInPicture
4562 && !isState(STOPPING, STOPPED, PAUSED);
4563 setDeferHidingClient(deferHidingClient);
Issei Suzuki1669ea42019-11-06 14:20:59 +01004564 setVisibility(false);
Andrii Kulian79d67982019-08-19 11:56:16 -07004565
4566 switch (getState()) {
4567 case STOPPING:
4568 case STOPPED:
4569 if (attachedToProcess()) {
4570 if (DEBUG_VISIBILITY) {
4571 Slog.v(TAG_VISIBILITY, "Scheduling invisibility: " + this);
4572 }
4573 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
4574 appToken, WindowVisibilityItem.obtain(false /* showWindow */));
4575 }
4576
4577 // Reset the flag indicating that an app can enter picture-in-picture once the
4578 // activity is hidden
4579 supportsEnterPipOnTaskSwitch = false;
4580 break;
4581
4582 case INITIALIZING:
4583 case RESUMED:
4584 case PAUSING:
4585 case PAUSED:
4586 case STARTED:
4587 addToStopping(true /* scheduleIdle */,
4588 canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
4589 break;
4590
4591 default:
4592 break;
4593 }
4594 } catch (Exception e) {
4595 // Just skip on any failure; we'll make it visible when it next restarts.
4596 Slog.w(TAG, "Exception thrown making hidden: " + intent.getComponent(), e);
4597 }
4598 }
4599
Andrii Kulian6b321512019-01-23 06:37:00 +00004600 /**
4601 * Make activity resumed or paused if needed.
4602 * @param activeActivity an activity that is resumed or just completed pause action.
4603 * We won't change the state of this activity.
4604 */
4605 boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
4606 if (shouldResumeActivity(activeActivity)) {
4607 if (DEBUG_VISIBILITY) {
4608 Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this);
4609 }
4610 return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
4611 null /* options */);
4612 } else if (shouldPauseActivity(activeActivity)) {
4613 if (DEBUG_VISIBILITY) {
4614 Slog.v("TAG_VISIBILITY", "Pause visible activity, " + this);
4615 }
4616 // An activity must be in the {@link PAUSING} state for the system to validate
4617 // the move to {@link PAUSED}.
4618 setState(PAUSING, "makeVisibleIfNeeded");
4619 try {
4620 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
4621 PauseActivityItem.obtain(finishing, false /* userLeaving */,
4622 configChangeFlags, false /* dontReport */));
4623 } catch (Exception e) {
4624 Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
4625 }
4626 }
4627 return false;
4628 }
4629
4630 /**
4631 * Check if activity should be moved to PAUSED state. The activity:
4632 * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4633 * - should be non-focusable
4634 * - should not be currently pausing or paused
4635 * @param activeActivity the activity that is active or just completed pause action. We won't
4636 * resume if this activity is active.
4637 */
wilsonshiha96aac62019-11-18 14:53:34 +08004638 @VisibleForTesting
4639 boolean shouldPauseActivity(ActivityRecord activeActivity) {
4640 return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED)
4641 // We will only allow pausing if results is null, otherwise it will cause this
4642 // activity to resume before getting result
4643 && (results == null);
Andrii Kulian6b321512019-01-23 06:37:00 +00004644 }
4645
4646 /**
wilsonshihb5d8f8b2019-10-23 13:01:40 +08004647 * Check if activity should be moved to RESUMED state.
4648 * See {@link #shouldBeResumed(ActivityRecord)}
Andrii Kulian6b321512019-01-23 06:37:00 +00004649 * @param activeActivity the activity that is active or just completed pause action. We won't
4650 * resume if this activity is active.
4651 */
Andrii Kulian0c869cc2019-02-06 19:50:32 -08004652 @VisibleForTesting
4653 boolean shouldResumeActivity(ActivityRecord activeActivity) {
wilsonshihb5d8f8b2019-10-23 13:01:40 +08004654 return shouldBeResumed(activeActivity) && !isState(RESUMED);
4655 }
4656
4657 /**
4658 * Check if activity should be RESUMED now. The activity:
4659 * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4660 * - should be focusable
4661 */
4662 private boolean shouldBeResumed(ActivityRecord activeActivity) {
4663 return shouldMakeActive(activeActivity) && isFocusable()
4664 && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
4665 && canResumeByCompat();
Andrii Kulian6b321512019-01-23 06:37:00 +00004666 }
4667
4668 /**
4669 * Check if activity is eligible to be made active (resumed of paused). The activity:
4670 * - should be paused, stopped or stopping
Andrii Kulian996df0d2019-01-24 17:04:36 -08004671 * - should not be the currently active one or launching behind other tasks
Andrii Kulian6b321512019-01-23 06:37:00 +00004672 * - should be either the topmost in task, or right below the top activity that is finishing
4673 * If all of these conditions are not met at the same time, the activity cannot be made active.
4674 */
Andrii Kulianf2195362019-01-31 18:20:11 -08004675 @VisibleForTesting
4676 boolean shouldMakeActive(ActivityRecord activeActivity) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004677 // If the activity is stopped, stopping, cycle to an active state. We avoid doing
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004678 // this when there is an activity waiting to become translucent as the extra binder
4679 // calls will lead to noticeable jank. A later call to
Wale Ogunwale076c3b12019-11-20 12:17:22 -08004680 // ActivityStack#ensureActivitiesVisible will bring the activity to a proper
Andrii Kulian6b321512019-01-23 06:37:00 +00004681 // active state.
Louis Changeadb22f2019-06-19 12:09:23 +08004682 if (!isState(STARTED, RESUMED, PAUSED, STOPPED, STOPPING)
Andrii Kulian6b321512019-01-23 06:37:00 +00004683 || getActivityStack().mTranslucentActivityWaiting != null) {
4684 return false;
4685 }
4686
4687 if (this == activeActivity) {
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004688 return false;
4689 }
4690
Andrii Kulianf2195362019-01-31 18:20:11 -08004691 if (!mStackSupervisor.readyToResume()) {
4692 // Making active is currently deferred (e.g. because an activity launch is in progress).
4693 return false;
4694 }
4695
Andrii Kulian996df0d2019-01-24 17:04:36 -08004696 if (this.mLaunchTaskBehind) {
4697 // This activity is being launched from behind, which means that it's not intended to be
4698 // presented to user right now, even if it's set to be visible.
4699 return false;
4700 }
4701
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004702 // Check if position in task allows to become paused
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004703 if (!task.hasChild(this)) {
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004704 throw new IllegalStateException("Activity not found in its task");
4705 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004706 final ActivityRecord activityAbove = task.getActivityAbove(this);
4707 if (activityAbove == null) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004708 // It's the topmost activity in the task - should become resumed now
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004709 return true;
4710 }
4711 // Check if activity above is finishing now and this one becomes the topmost in task.
wilsonshiha96aac62019-11-18 14:53:34 +08004712 if (activityAbove.finishing) {
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004713 return true;
4714 }
4715 return false;
4716 }
4717
Louis Changcfe46212019-07-30 10:34:18 +08004718 void handleAlreadyVisible() {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004719 stopFreezingScreenLocked(false);
4720 try {
4721 if (returningOptions != null) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004722 app.getThread().scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
Andrii Kulian21713ac2016-10-12 22:05:05 -07004723 }
4724 } catch(RemoteException e) {
4725 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004726 }
4727
4728 static void activityResumedLocked(IBinder token) {
4729 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
4730 if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
Charles Chen69362cd2019-03-29 15:18:45 +08004731 if (r == null) {
4732 // If an app reports resumed after a long delay, the record on server side might have
4733 // been removed (e.g. destroy timeout), so the token could be null.
4734 return;
Andrii Kulian21713ac2016-10-12 22:05:05 -07004735 }
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004736 r.setSavedState(null /* savedState */);
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004737
Louis Chang677921f2019-12-06 16:44:24 +08004738 final DisplayContent display = r.getDisplay();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004739 if (display != null) {
4740 display.handleActivitySizeCompatModeIfNeeded(r);
4741 }
Riddle Hsu8419e4b2019-09-18 23:28:01 +08004742
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004743 r.getDisplayContent().mUnknownAppVisibilityController.notifyAppResumedFinished(r);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004744 }
4745
4746 /**
4747 * Once we know that we have asked an application to put an activity in the resumed state
4748 * (either by launching it or explicitly telling it), this function updates the rest of our
4749 * state to match that fact.
4750 */
4751 void completeResumeLocked() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01004752 final boolean wasVisible = mVisibleRequested;
4753 setVisibility(true);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004754 if (!wasVisible) {
4755 // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
4756 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
4757 }
4758 idle = false;
4759 results = null;
Louis Chang746c2242019-10-08 16:30:44 +08004760 if (newIntents != null && newIntents.size() > 0) {
4761 mLastNewIntent = newIntents.get(newIntents.size() - 1);
4762 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004763 newIntents = null;
4764 stopped = false;
4765
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07004766 if (isActivityTypeHome()) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004767 mStackSupervisor.updateHomeProcess(task.getBottomMostActivity().app);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004768 }
4769
4770 if (nowVisible) {
Louis Changa59937a2019-03-20 17:17:22 +08004771 mStackSupervisor.stopWaitingForActivityVisible(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004772 }
4773
4774 // Schedule an idle timeout in case the app doesn't do it for us.
4775 mStackSupervisor.scheduleIdleTimeoutLocked(this);
4776
4777 mStackSupervisor.reportResumedActivityLocked(this);
4778
4779 resumeKeyDispatchingLocked();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004780 final ActivityStack stack = getActivityStack();
Jorim Jaggifa9ed962018-01-25 00:16:49 +01004781 mStackSupervisor.mNoAnimActivities.clear();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004782
4783 // Mark the point when the activity is resuming
4784 // TODO: To be more accurate, the mark should be before the onCreate,
4785 // not after the onResume. But for subsequent starts, onResume is fine.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004786 if (hasProcess()) {
Wale Ogunwale86b74462018-07-02 08:42:43 -07004787 cpuTimeAtResume = app.getCpuTime();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004788 } else {
4789 cpuTimeAtResume = 0; // Couldn't get the cpu time of process
4790 }
4791
4792 returningOptions = null;
chaviw59b98852017-06-13 12:05:44 -07004793
4794 if (canTurnScreenOn()) {
4795 mStackSupervisor.wakeUp("turnScreenOnFlag");
4796 } else {
4797 // If the screen is going to turn on because the caller explicitly requested it and
4798 // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
4799 // pause and then resume again later, which will result in a double life-cycle event.
David Stevens9440dc82017-03-16 19:00:20 -07004800 stack.checkReadyForSleep();
chaviw59b98852017-06-13 12:05:44 -07004801 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004802 }
4803
Wale Ogunwale196db712019-12-27 15:35:39 +00004804 void activityPaused(boolean timeout) {
4805 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
4806 "Activity paused: token=" + appToken + ", timeout=" + timeout);
4807
4808 final ActivityStack stack = getStack();
4809
4810 if (stack != null) {
4811 removePauseTimeout();
4812
4813 if (stack.mPausingActivity == this) {
4814 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
4815 + (timeout ? " (due to timeout)" : " (pause complete)"));
4816 mAtmService.deferWindowLayout();
4817 try {
4818 stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
4819 } finally {
4820 mAtmService.continueWindowLayout();
4821 }
4822 return;
4823 } else {
4824 EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this),
4825 shortComponentName, stack.mPausingActivity != null
4826 ? stack.mPausingActivity.shortComponentName : "(none)");
4827 if (isState(PAUSING)) {
4828 setState(PAUSED, "activityPausedLocked");
4829 if (finishing) {
4830 if (DEBUG_PAUSE) Slog.v(TAG,
4831 "Executing finish of failed to pause activity: " + this);
4832 completeFinishing("activityPausedLocked");
4833 }
4834 }
4835 }
4836 }
4837
Louis Chang149d5c82019-12-30 09:47:39 +08004838 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwale196db712019-12-27 15:35:39 +00004839 }
4840
4841 /**
4842 * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
4843 * this directly impacts the responsiveness seen by the user.
4844 */
4845 void schedulePauseTimeout() {
4846 pauseTime = SystemClock.uptimeMillis();
4847 mAtmService.mH.postDelayed(mPauseTimeoutRunnable, PAUSE_TIMEOUT);
4848 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
4849 }
4850
4851 private void removePauseTimeout() {
4852 mAtmService.mH.removeCallbacks(mPauseTimeoutRunnable);
4853 }
4854
4855 private void removeDestroyTimeout() {
4856 mAtmService.mH.removeCallbacks(mDestroyTimeoutRunnable);
4857 }
4858
4859 private void removeStopTimeout() {
4860 mAtmService.mH.removeCallbacks(mStopTimeoutRunnable);
4861 }
4862
4863 void removeTimeouts() {
4864 mStackSupervisor.removeIdleTimeoutForActivity(this);
4865 removePauseTimeout();
4866 removeStopTimeout();
4867 removeDestroyTimeout();
4868 finishLaunchTickingLocked();
4869 }
4870
Andrii Kulian79d67982019-08-19 11:56:16 -07004871 void stopIfPossible() {
4872 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
4873 final ActivityStack stack = getActivityStack();
4874 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4875 || (info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0) {
4876 if (!finishing) {
4877 if (!stack.shouldSleepActivities()) {
4878 if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + this);
4879 if (finishIfPossible("stop-no-history", false /* oomAdj */)
4880 != FINISH_RESULT_CANCELLED) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004881 resumeKeyDispatchingLocked();
4882 return;
4883 }
4884 } else {
4885 if (DEBUG_STATES) {
4886 Slog.d(TAG_STATES, "Not finishing noHistory " + this
4887 + " on stop because we're just sleeping");
4888 }
4889 }
4890 }
4891 }
4892
4893 if (!attachedToProcess()) {
4894 return;
4895 }
Andrii Kulian79d67982019-08-19 11:56:16 -07004896 resumeKeyDispatchingLocked();
4897 try {
4898 stopped = false;
4899 if (DEBUG_STATES) {
4900 Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (stop requested)");
4901 }
4902 setState(STOPPING, "stopIfPossible");
4903 if (DEBUG_VISIBILITY) {
Issei Suzuki1669ea42019-11-06 14:20:59 +01004904 Slog.v(TAG_VISIBILITY, "Stopping visibleRequested="
4905 + mVisibleRequested + " for " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07004906 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01004907 if (!mVisibleRequested) {
4908 setVisibility(false);
Andrii Kulian79d67982019-08-19 11:56:16 -07004909 }
Jeff Changd136e772019-11-05 20:33:52 +08004910 EventLogTags.writeWmStopActivity(
Andrii Kulian79d67982019-08-19 11:56:16 -07004911 mUserId, System.identityHashCode(this), shortComponentName);
4912 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Issei Suzuki1669ea42019-11-06 14:20:59 +01004913 StopActivityItem.obtain(mVisibleRequested, configChangeFlags));
Andrii Kulian79d67982019-08-19 11:56:16 -07004914 if (stack.shouldSleepOrShutDownActivities()) {
4915 setSleeping(true);
4916 }
Wale Ogunwale196db712019-12-27 15:35:39 +00004917 mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
Andrii Kulian79d67982019-08-19 11:56:16 -07004918 } catch (Exception e) {
4919 // Maybe just ignore exceptions here... if the process has crashed, our death
4920 // notification will clean things up.
4921 Slog.w(TAG, "Exception thrown during pause", e);
4922 // Just in case, assume it to be stopped.
4923 stopped = true;
4924 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + this);
4925 setState(STOPPED, "stopIfPossible");
4926 if (deferRelaunchUntilPaused) {
4927 destroyImmediately(true /* removeFromApp */, "stop-except");
4928 }
4929 }
4930 }
4931
Wale Ogunwale196db712019-12-27 15:35:39 +00004932 void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState,
Andrii Kulian21713ac2016-10-12 22:05:05 -07004933 CharSequence description) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004934 final ActivityStack stack = getActivityStack();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004935 final boolean isStopping = mState == STOPPING;
4936 if (!isStopping && mState != RESTARTING_PROCESS) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004937 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
Wale Ogunwale196db712019-12-27 15:35:39 +00004938 removeStopTimeout();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004939 return;
4940 }
4941 if (newPersistentState != null) {
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004942 mPersistentState = newPersistentState;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004943 mAtmService.notifyTaskPersisterLocked(task, false);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004944 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08004945
Andrii Kulian21713ac2016-10-12 22:05:05 -07004946 if (newIcicle != null) {
4947 // If icicle is null, this is happening due to a timeout, so we haven't really saved
4948 // the state.
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004949 setSavedState(newIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004950 launchCount = 0;
Jorim Jaggie7d2b852017-08-28 17:55:15 +02004951 updateTaskDescription(description);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004952 }
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004953 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004954 if (!stopped) {
4955 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
Wale Ogunwale196db712019-12-27 15:35:39 +00004956 removeStopTimeout();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004957 stopped = true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004958 if (isStopping) {
4959 setState(STOPPED, "activityStoppedLocked");
4960 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004961
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004962 notifyAppStopped();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004963
Andrii Kulian21713ac2016-10-12 22:05:05 -07004964 if (finishing) {
4965 clearOptionsLocked();
4966 } else {
4967 if (deferRelaunchUntilPaused) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004968 destroyImmediately(true /* removeFromApp */, "stop-config");
Louis Chang149d5c82019-12-30 09:47:39 +08004969 mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004970 } else {
Louis Chang149d5c82019-12-30 09:47:39 +08004971 mRootWindowContainer.updatePreviousProcess(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004972 }
4973 }
4974 }
4975 }
4976
Andrii Kulian79d67982019-08-19 11:56:16 -07004977 void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
4978 if (!mStackSupervisor.mStoppingActivities.contains(this)) {
Jeff Changd136e772019-11-05 20:33:52 +08004979 EventLogTags.writeWmAddToStopping(mUserId, System.identityHashCode(this),
4980 shortComponentName, reason);
Andrii Kulian79d67982019-08-19 11:56:16 -07004981 mStackSupervisor.mStoppingActivities.add(this);
4982 }
4983
4984 final ActivityStack stack = getActivityStack();
4985 // If we already have a few activities waiting to stop, then give up on things going idle
4986 // and start clearing them out. Or if r is the last of activity of the last task the stack
4987 // will be empty and must be cleared immediately.
4988 boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
4989 || (isRootOfTask() && stack.getChildCount() <= 1);
4990 if (scheduleIdle || forceIdle) {
4991 if (DEBUG_PAUSE) {
4992 Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" + forceIdle
4993 + "immediate=" + !idleDelayed);
4994 }
4995 if (!idleDelayed) {
4996 mStackSupervisor.scheduleIdleLocked();
4997 } else {
4998 mStackSupervisor.scheduleIdleTimeoutLocked(this);
4999 }
5000 } else {
5001 stack.checkReadyForSleep();
5002 }
5003 }
5004
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005005 void startLaunchTickingLocked() {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06005006 if (Build.IS_USER) {
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005007 return;
5008 }
5009 if (launchTickTime == 0) {
5010 launchTickTime = SystemClock.uptimeMillis();
Wale Ogunwale196db712019-12-27 15:35:39 +00005011 continueLaunchTicking();
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005012 }
5013 }
5014
Wale Ogunwale196db712019-12-27 15:35:39 +00005015 private boolean continueLaunchTicking() {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005016 if (launchTickTime == 0) {
5017 return false;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005018 }
Wale Ogunwale7d701172015-03-11 15:36:30 -07005019
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005020 final ActivityStack stack = getActivityStack();
Wale Ogunwale7d701172015-03-11 15:36:30 -07005021 if (stack == null) {
5022 return false;
5023 }
5024
Andrii Kulian79d67982019-08-19 11:56:16 -07005025 stack.removeLaunchTickMessages();
Wale Ogunwale196db712019-12-27 15:35:39 +00005026 mAtmService.mH.postDelayed(mLaunchTickRunnable, LAUNCH_TICK);
Wale Ogunwale7d701172015-03-11 15:36:30 -07005027 return true;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005028 }
5029
Wale Ogunwale196db712019-12-27 15:35:39 +00005030 void removeLaunchTickRunnable() {
5031 mAtmService.mH.removeCallbacks(mLaunchTickRunnable);
5032 }
5033
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005034 void finishLaunchTickingLocked() {
5035 launchTickTime = 0;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005036 final ActivityStack stack = getActivityStack();
Andrii Kulian79d67982019-08-19 11:56:16 -07005037 if (stack == null) {
5038 return;
Wale Ogunwale7d701172015-03-11 15:36:30 -07005039 }
Andrii Kulian79d67982019-08-19 11:56:16 -07005040 stack.removeLaunchTickMessages();
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005041 }
5042
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005043 boolean mayFreezeScreenLocked() {
5044 return mayFreezeScreenLocked(app);
5045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005047 private boolean mayFreezeScreenLocked(WindowProcessController app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 // Only freeze the screen if this activity is currently attached to
5049 // an application, and that application is not blocked or unresponding.
5050 // In any other case, we can't count on getting the screen unfrozen,
5051 // so it is best to leave as-is.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005052 return hasProcess() && !app.isCrashing() && !app.isNotResponding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005054
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005055 void startFreezingScreenLocked(int configChanges) {
5056 startFreezingScreenLocked(app, configChanges);
5057 }
5058
5059 void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005060 if (mayFreezeScreenLocked(app)) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005061 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005062 Slog.w(TAG_WM,
5063 "Attempted to freeze screen with non-existing app token: " + appToken);
5064 return;
5065 }
5066
Evan Roskyb1e75f72019-04-26 20:23:26 -07005067 // Window configuration changes only effect windows, so don't require a screen freeze.
5068 int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005069 if (freezableConfigChanges == 0 && okToDisplay()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02005070 ProtoLog.v(WM_DEBUG_ORIENTATION, "Skipping set freeze of %s", appToken);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005071 return;
5072 }
5073
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005074 startFreezingScreen();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 }
5076 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005077
Garfield Tane8d84ab2019-10-11 09:49:40 -07005078 void startFreezingScreen() {
5079 ProtoLog.i(WM_DEBUG_ORIENTATION,
Issei Suzukif2f6c912019-11-08 11:24:18 +01005080 "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
5081 appToken, isVisible(), mFreezingScreen, mVisibleRequested,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005082 new RuntimeException().fillInStackTrace());
Issei Suzuki1669ea42019-11-06 14:20:59 +01005083 if (mVisibleRequested) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005084 if (!mFreezingScreen) {
5085 mFreezingScreen = true;
5086 mWmService.registerAppFreezeListener(this);
5087 mWmService.mAppsFreezingScreen++;
5088 if (mWmService.mAppsFreezingScreen == 1) {
5089 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
5090 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
5091 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
5092 }
5093 }
5094 final int count = mChildren.size();
5095 for (int i = 0; i < count; i++) {
5096 final WindowState w = mChildren.get(i);
5097 w.onStartFreezingScreen();
5098 }
5099 }
5100 }
5101
5102 boolean isFreezingScreen() {
5103 return mFreezingScreen;
5104 }
5105
5106 @Override
5107 public void onAppFreezeTimeout() {
5108 Slog.w(TAG_WM, "Force clearing freeze: " + this);
5109 stopFreezingScreen(true, true);
5110 }
5111
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005112 void stopFreezingScreenLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 if (force || frozenBeforeDestroy) {
5114 frozenBeforeDestroy = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005115 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005116 return;
5117 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02005118 ProtoLog.v(WM_DEBUG_ORIENTATION,
Issei Suzukif2f6c912019-11-08 11:24:18 +01005119 "Clear freezing of %s: visible=%b freezing=%b", appToken,
5120 isVisible(), isFreezingScreen());
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005121 stopFreezingScreen(true, force);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 }
5123 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005124
Garfield Tane8d84ab2019-10-11 09:49:40 -07005125 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
5126 if (!mFreezingScreen) {
5127 return;
5128 }
5129 ProtoLog.v(WM_DEBUG_ORIENTATION,
5130 "Clear freezing of %s force=%b", this, force);
5131 final int count = mChildren.size();
5132 boolean unfrozeWindows = false;
5133 for (int i = 0; i < count; i++) {
5134 final WindowState w = mChildren.get(i);
5135 unfrozeWindows |= w.onStopFreezingScreen();
5136 }
5137 if (force || unfrozeWindows) {
5138 ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
5139 mFreezingScreen = false;
5140 mWmService.unregisterAppFreezeListener(this);
5141 mWmService.mAppsFreezingScreen--;
5142 mWmService.mLastFinishedFreezeSource = this;
5143 }
5144 if (unfreezeSurfaceNow) {
5145 if (unfrozeWindows) {
5146 mWmService.mWindowPlacerLocked.performSurfacePlacement();
5147 }
5148 mWmService.stopFreezingDisplayLocked();
5149 }
5150 }
5151
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005152 void reportFullyDrawnLocked(boolean restoredFromBundle) {
Riddle Hsufd66d4d2019-11-14 10:35:55 +08005153 final TransitionInfoSnapshot info = mStackSupervisor
Yan Wangd47f90b2019-10-03 19:17:15 -07005154 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
Vishnu Nair132ee832018-09-28 15:00:05 -07005155 if (info != null) {
5156 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
Vishnu Nairbb9ab4b2018-12-13 10:29:46 -08005157 info.windowsFullyDrawnDelayMs, info.getLaunchState());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07005158 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07005159 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005160
Garfield Tane8d84ab2019-10-11 09:49:40 -07005161 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
5162 firstWindowDrawn = true;
5163
5164 // We now have a good window to show, remove dead placeholders
5165 removeDeadWindows();
5166
5167 if (startingWindow != null) {
5168 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
5169 + ": first real window is shown, no animation", win.mToken);
5170 // If this initial window is animating, stop it -- we will do an animation to reveal
5171 // it from behind the starting window, so there is no need for it to also be doing its
5172 // own stuff.
5173 win.cancelAnimation();
5174 }
5175 removeStartingWindow();
5176 updateReportedVisibilityLocked();
5177 }
5178
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005179 /** Called when the windows associated app window container are drawn. */
Yan Wangd47f90b2019-10-03 19:17:15 -07005180 void onWindowsDrawn(boolean drawn, long timestampNs) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005181 mDrawn = drawn;
5182 if (!drawn) {
5183 return;
5184 }
Riddle Hsufd66d4d2019-11-14 10:35:55 +08005185 final TransitionInfoSnapshot info = mStackSupervisor
5186 .getActivityMetricsLogger().notifyWindowsDrawn(this, timestampNs);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005187 final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
5188 final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
5189 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
5190 windowsDrawnDelayMs, launchState);
Riddle Hsuc48c8912019-10-31 13:34:27 +08005191 mStackSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005192 finishLaunchTickingLocked();
5193 if (task != null) {
5194 task.hasBeenVisible = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 }
5196 }
5197
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005198 /** Called when the windows associated app window container are visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005199 void onWindowsVisible() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005200 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005201 mStackSupervisor.stopWaitingForActivityVisible(this);
5202 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
5203 if (!nowVisible) {
5204 nowVisible = true;
5205 lastVisibleTime = SystemClock.uptimeMillis();
5206 mAtmService.scheduleAppGcsLocked();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005207 }
5208 }
5209
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005210 /** Called when the windows associated app window container are no longer visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005211 void onWindowsGone() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005212 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005213 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
5214 nowVisible = false;
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005215 }
5216
Garfield Tane8d84ab2019-10-11 09:49:40 -07005217 @Override
5218 void checkAppWindowsReadyToShow() {
5219 if (allDrawn == mLastAllDrawn) {
5220 return;
5221 }
5222
5223 mLastAllDrawn = allDrawn;
5224 if (!allDrawn) {
5225 return;
5226 }
5227
5228 // The token has now changed state to having all windows shown... what to do, what to do?
5229 if (mFreezingScreen) {
5230 showAllWindowsLocked();
5231 stopFreezingScreen(false, true);
5232 ProtoLog.i(WM_DEBUG_ORIENTATION,
5233 "Setting mOrientationChangeComplete=true because wtoken %s "
5234 + "numInteresting=%d numDrawn=%d",
5235 this, mNumInterestingWindows, mNumDrawnWindows);
5236 // This will set mOrientationChangeComplete and cause a pass through layout.
5237 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
5238 "checkAppWindowsReadyToShow: freezingScreen");
5239 } else {
5240 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
5241
5242 // We can now show all of the drawn windows!
5243 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
5244 showAllWindowsLocked();
5245 }
5246 }
5247 }
5248
5249 /**
5250 * This must be called while inside a transaction.
5251 */
5252 void showAllWindowsLocked() {
5253 forAllWindows(windowState -> {
5254 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
5255 windowState.performShowLocked();
5256 }, false /* traverseTopToBottom */);
5257 }
5258
5259 void updateReportedVisibilityLocked() {
5260 if (appToken == null) {
5261 return;
5262 }
5263
5264 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
5265 final int count = mChildren.size();
5266
5267 mReportedVisibilityResults.reset();
5268
5269 for (int i = 0; i < count; i++) {
5270 final WindowState win = mChildren.get(i);
5271 win.updateReportedVisibility(mReportedVisibilityResults);
5272 }
5273
5274 int numInteresting = mReportedVisibilityResults.numInteresting;
5275 int numVisible = mReportedVisibilityResults.numVisible;
5276 int numDrawn = mReportedVisibilityResults.numDrawn;
5277 boolean nowGone = mReportedVisibilityResults.nowGone;
5278
5279 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Issei Suzukif2f6c912019-11-08 11:24:18 +01005280 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && isVisible();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005281 if (!nowGone) {
5282 // If the app is not yet gone, then it can only become visible/drawn.
5283 if (!nowDrawn) {
5284 nowDrawn = reportedDrawn;
5285 }
5286 if (!nowVisible) {
5287 nowVisible = reportedVisible;
5288 }
5289 }
5290 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
5291 + numInteresting + " visible=" + numVisible);
5292 if (nowDrawn != reportedDrawn) {
5293 onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
5294 reportedDrawn = nowDrawn;
5295 }
5296 if (nowVisible != reportedVisible) {
5297 if (DEBUG_VISIBILITY) Slog.v(TAG,
5298 "Visibility changed in " + this + ": vis=" + nowVisible);
5299 reportedVisible = nowVisible;
5300 if (nowVisible) {
5301 onWindowsVisible();
5302 } else {
5303 onWindowsGone();
5304 }
5305 }
5306 }
5307
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005308 boolean isClientVisible() {
5309 return mClientVisible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005310 }
5311
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005312 void setClientVisible(boolean clientVisible) {
5313 if (mClientVisible == clientVisible || (!clientVisible && mDeferHidingClient)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005314 return;
5315 }
5316 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005317 "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005318 Debug.getCallers(5));
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005319 mClientVisible = clientVisible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005320 sendAppVisibilityToClients();
5321 }
5322
5323 /**
5324 * Updated this app token tracking states for interesting and drawn windows based on the window.
5325 *
5326 * @return Returns true if the input window is considered interesting and drawn while all the
5327 * windows in this app token where not considered drawn as of the last pass.
5328 */
5329 boolean updateDrawnWindowStates(WindowState w) {
5330 w.setDrawnStateEvaluated(true /*evaluated*/);
5331
5332 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
5333 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
5334 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
5335 }
5336
5337 if (allDrawn && !mFreezingScreen) {
5338 return false;
5339 }
5340
5341 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
5342 mLastTransactionSequence = mWmService.mTransactionSequence;
5343 mNumDrawnWindows = 0;
5344 startingDisplayed = false;
5345
5346 // There is the main base application window, even if it is exiting, wait for it
5347 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
5348 }
5349
5350 final WindowStateAnimator winAnimator = w.mWinAnimator;
5351
5352 boolean isInterestingAndDrawn = false;
5353
5354 if (!allDrawn && w.mightAffectAllDrawn()) {
5355 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5356 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
lumark9bca6b42019-10-17 18:35:22 +08005357 + ", isAnimationSet=" + isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005358 if (!w.isDrawnLw()) {
5359 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
5360 + " pv=" + w.isVisibleByPolicy()
5361 + " mDrawState=" + winAnimator.drawStateToString()
Issei Suzuki1669ea42019-11-06 14:20:59 +01005362 + " ph=" + w.isParentWindowHidden() + " th=" + mVisibleRequested
lumark9bca6b42019-10-17 18:35:22 +08005363 + " a=" + isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005364 }
5365 }
5366
5367 if (w != startingWindow) {
5368 if (w.isInteresting()) {
5369 // Add non-main window as interesting since the main app has already been added
5370 if (findMainWindow(false /* includeStartingApp */) != w) {
5371 mNumInterestingWindows++;
5372 }
5373 if (w.isDrawnLw()) {
5374 mNumDrawnWindows++;
5375
5376 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5377 Slog.v(TAG, "tokenMayBeDrawn: "
5378 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
5379 + " freezingScreen=" + mFreezingScreen
5380 + " mAppFreezing=" + w.mAppFreezing);
5381 }
5382
5383 isInterestingAndDrawn = true;
5384 }
5385 }
5386 } else if (w.isDrawnLw()) {
Riddle Hsufd66d4d2019-11-14 10:35:55 +08005387 // The starting window for this container is drawn.
5388 mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005389 startingDisplayed = true;
5390 }
5391 }
5392
5393 return isInterestingAndDrawn;
5394 }
5395
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005396 /**
5397 * Called when the key dispatching to a window associated with the app window container
5398 * timed-out.
5399 *
5400 * @param reason The reason for the key dispatching time out.
5401 * @param windowPid The pid of the window key dispatching timed out on.
5402 * @return True if input dispatching should be aborted.
5403 */
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005404 public boolean keyDispatchingTimedOut(String reason, int windowPid) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005405 ActivityRecord anrActivity;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005406 WindowProcessController anrApp;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005407 boolean windowFromSameProcessAsActivity;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005408 synchronized (mAtmService.mGlobalLock) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005409 anrActivity = getWaitingHistoryRecordLocked();
5410 anrApp = app;
Brian Carlstrom7b0f2e82017-03-31 00:24:18 -07005411 windowFromSameProcessAsActivity =
Vishnu Nair19479df2019-10-30 08:03:15 -07005412 !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005413 }
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005414
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005415 if (windowFromSameProcessAsActivity) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005416 return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07005417 anrActivity.shortComponentName, anrActivity.info.applicationInfo,
5418 shortComponentName, app, false, reason);
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005419 } else {
5420 // In this case another process added windows using this activity token. So, we call the
5421 // generic service input dispatch timed out method so that the right process is blamed.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005422 return mAtmService.mAmInternal.inputDispatchingTimedOut(
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005423 windowPid, false /* aboveSystem */, reason) < 0;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005424 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005425 }
5426
5427 private ActivityRecord getWaitingHistoryRecordLocked() {
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005428 // First find the real culprit... if this activity has stopped, then the key dispatching
riddle_hsudb46d6b2015-04-01 18:58:07 +08005429 // timeout should not be caused by this.
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005430 if (stopped) {
Louis Chang149d5c82019-12-30 09:47:39 +08005431 final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
riddle_hsudb46d6b2015-04-01 18:58:07 +08005432 // Try to use the one which is closest to top.
Bryce Leec4ab62a2018-03-05 14:19:26 -08005433 ActivityRecord r = stack.getResumedActivity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 if (r == null) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08005435 r = stack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005437 if (r != null) {
5438 return r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005439 }
5440 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005441 return this;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 }
5443
Chong Zhang87761972016-08-22 13:53:24 -07005444 /** Checks whether the activity should be shown for current user. */
5445 public boolean okToShowLocked() {
Bryce Lee8558ec72017-08-17 15:37:26 -07005446 // We cannot show activities when the device is locked and the application is not
5447 // encryption aware.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005448 if (!StorageManager.isUserKeyUnlocked(mUserId)
Bryce Lee8558ec72017-08-17 15:37:26 -07005449 && !info.applicationInfo.isEncryptionAware()) {
5450 return false;
5451 }
5452
Chong Zhang87761972016-08-22 13:53:24 -07005453 return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005454 || (mStackSupervisor.isCurrentProfileLocked(mUserId)
5455 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
Chong Zhang87761972016-08-22 13:53:24 -07005456 }
5457
Wale Ogunwalea38654f2019-11-17 20:37:15 -08005458 boolean canBeTopRunning() {
5459 return !finishing && okToShowLocked();
5460 }
5461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 /**
5463 * This method will return true if the activity is either visible, is becoming visible, is
5464 * currently pausing, or is resumed.
5465 */
5466 public boolean isInterestingToUserLocked() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01005467 return mVisibleRequested || nowVisible || mState == PAUSING || mState == RESUMED;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005468 }
5469
Wale Ogunwale3e997362016-09-06 10:37:56 -07005470 void setSleeping(boolean _sleeping) {
5471 setSleeping(_sleeping, false);
5472 }
5473
5474 void setSleeping(boolean _sleeping, boolean force) {
5475 if (!force && sleeping == _sleeping) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005476 return;
5477 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005478 if (attachedToProcess()) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005479 try {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005480 app.getThread().scheduleSleeping(appToken, _sleeping);
Craig Mautner0eea92c2013-05-16 13:35:39 -07005481 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
5482 mStackSupervisor.mGoingToSleepActivities.add(this);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005483 }
5484 sleeping = _sleeping;
5485 } catch (RemoteException e) {
Craig Mautner0eea92c2013-05-16 13:35:39 -07005486 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005487 }
5488 }
5489 }
Craig Mautnerf81b90872013-02-26 13:02:43 -08005490
Craig Mautnerd2328952013-03-05 12:46:26 -08005491 static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005492 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08005493 if (r == null || r.getParent() == null) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005494 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005495 }
Louis Changcdec0802019-11-11 11:45:07 +08005496 final Task task = r.task;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08005497 if (onlyRoot && r.compareTo(task.getRootActivity(
5498 false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)) > 0) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005499 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005500 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005501 return task.mTaskId;
Craig Mautnerd2328952013-03-05 12:46:26 -08005502 }
5503
5504 static ActivityRecord isInStackLocked(IBinder token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005505 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005506 return (r != null) ? r.getActivityStack().isInStackLocked(r) : null;
Craig Mautnerd2328952013-03-05 12:46:26 -08005507 }
5508
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005509 static ActivityStack getStackLocked(IBinder token) {
Craig Mautnerd2328952013-03-05 12:46:26 -08005510 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
5511 if (r != null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005512 return r.getActivityStack();
Craig Mautnerd2328952013-03-05 12:46:26 -08005513 }
5514 return null;
5515 }
5516
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005517 /**
Riddle Hsufd4a0502018-10-16 01:05:16 +08005518 * @return display id to which this record is attached,
5519 * {@link android.view.Display#INVALID_DISPLAY} if not attached.
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005520 */
5521 int getDisplayId() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005522 final ActivityStack stack = getActivityStack();
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005523 if (stack == null) {
Riddle Hsufd4a0502018-10-16 01:05:16 +08005524 return INVALID_DISPLAY;
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005525 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08005526 return stack.getDisplayId();
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005527 }
5528
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005529 final boolean isDestroyable() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005530 if (finishing || !hasProcess()) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005531 // This would be redundant.
5532 return false;
5533 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005534 final ActivityStack stack = getActivityStack();
Andrii Kulianf49a58c2019-08-14 17:34:27 -07005535 if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState
5536 || !stopped) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005537 // We're not ready for this kind of thing.
5538 return false;
5539 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01005540 if (mVisibleRequested) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005541 // The user would notice this!
5542 return false;
5543 }
5544 return true;
5545 }
5546
Winson Chung3bad5cc02014-08-19 17:44:32 -07005547 private static String createImageFilename(long createTime, int taskId) {
5548 return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
Ruben Brunkf53497c2017-03-27 20:26:17 -07005549 IMAGE_EXTENSION;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07005550 }
5551
Craig Mautner648f69b2014-09-18 14:16:26 -07005552 void setTaskDescription(TaskDescription _taskDescription) {
5553 Bitmap icon;
5554 if (_taskDescription.getIconFilename() == null &&
5555 (icon = _taskDescription.getIcon()) != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005556 final String iconFilename = createImageFilename(createTime, task.mTaskId);
5557 final File iconFile = new File(TaskPersister.getUserImagesDir(task.mUserId),
Winson Chungc8408b82017-01-25 17:58:56 -08005558 iconFilename);
Suprabh Shukla23593142015-11-03 17:31:15 -08005559 final String iconFilePath = iconFile.getAbsolutePath();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005560 mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
Suprabh Shukla23593142015-11-03 17:31:15 -08005561 _taskDescription.setIconFilename(iconFilePath);
Craig Mautner648f69b2014-09-18 14:16:26 -07005562 }
5563 taskDescription = _taskDescription;
5564 }
5565
Amith Yamasani0af6fa72016-01-17 15:36:19 -08005566 void setVoiceSessionLocked(IVoiceInteractionSession session) {
5567 voiceSession = session;
5568 pendingVoiceInteractionStart = false;
5569 }
5570
5571 void clearVoiceSessionLocked() {
5572 voiceSession = null;
5573 pendingVoiceInteractionStart = false;
5574 }
5575
Jorim Jaggi02886a82016-12-06 09:10:06 -08005576 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
Jorim Jaggi42befc62017-06-13 11:54:04 -07005577 showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
5578 }
5579
5580 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
5581 boolean fromRecents) {
Wale Ogunwale19866e22017-04-19 06:05:13 -07005582 if (mTaskOverlay) {
5583 // We don't show starting window for overlay activities.
5584 return;
5585 }
Sunny Goyald85bed52018-09-25 12:01:01 -07005586 if (pendingOptions != null
5587 && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
5588 // Don't show starting window when using shared element transition.
5589 return;
5590 }
Wale Ogunwale19866e22017-04-19 06:05:13 -07005591
Wale Ogunwale3b232392016-05-13 15:37:13 -07005592 final CompatibilityInfo compatInfo =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005593 mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005594 final boolean shown = addStartingWindow(packageName, theme,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005595 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
Jorim Jaggibae01b12017-04-11 16:29:10 -07005596 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
Jorim Jaggi70aa4d12017-05-15 00:05:54 +02005597 allowTaskSnapshot(),
Louis Changeadb22f2019-06-19 12:09:23 +08005598 mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
Jorim Jaggi42befc62017-06-13 11:54:04 -07005599 fromRecents);
Wale Ogunwale3b232392016-05-13 15:37:13 -07005600 if (shown) {
5601 mStartingWindowState = STARTING_WINDOW_SHOWN;
5602 }
5603 }
5604
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005605 /**
5606 * If any activities below the top running one are in the INITIALIZING state and they have a
5607 * starting window displayed then remove that starting window. It is possible that the activity
5608 * in this state will never resumed in which case that starting window will be orphaned.
5609 * <p>
5610 * It should only be called if this activity is behind other fullscreen activity.
5611 */
5612 void cancelInitializing() {
5613 if (mStartingWindowState == STARTING_WINDOW_SHOWN) {
5614 // Remove orphaned starting window.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005615 if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
5616 mStartingWindowState = STARTING_WINDOW_REMOVED;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005617 removeStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005618 }
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005619 if (isState(INITIALIZING) && !shouldBeVisible(
5620 true /* behindFullscreenActivity */, true /* ignoringKeyguard */)) {
5621 // Remove the unknown visibility record because an invisible activity shouldn't block
5622 // the keyguard transition.
5623 mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
5624 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005625 }
5626
Garfield Tane8d84ab2019-10-11 09:49:40 -07005627 void postWindowRemoveStartingWindowCleanup(WindowState win) {
5628 // TODO: Something smells about the code below...Is there a better way?
5629 if (startingWindow == win) {
5630 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
5631 removeStartingWindow();
5632 } else if (mChildren.size() == 0) {
5633 // If this is the last window and we had requested a starting transition window,
5634 // well there is no point now.
5635 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
5636 mStartingData = null;
Issei Suzukif2f6c912019-11-08 11:24:18 +01005637 if (mVisibleSetFromTransferredStartingWindow) {
5638 // We set the visible state to true for the token from a transferred starting
5639 // window. We now reset it back to false since the starting window was the last
5640 // window in the token.
5641 setVisible(false);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005642 }
5643 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
5644 // If this is the last window except for a starting transition window,
5645 // we need to get rid of the starting transition.
5646 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
5647 removeStartingWindow();
5648 }
5649 }
5650
5651 void removeDeadWindows() {
5652 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
5653 WindowState win = mChildren.get(winNdx);
5654 if (win.mAppDied) {
5655 ProtoLog.w(WM_DEBUG_ADD_REMOVE,
5656 "removeDeadWindows: %s", win);
5657 // Set mDestroying, we don't want any animation or delayed removal here.
5658 win.mDestroying = true;
5659 // Also removes child windows.
5660 win.removeIfPossible();
5661 }
5662 }
5663 }
5664
5665 boolean hasWindowsAlive() {
5666 for (int i = mChildren.size() - 1; i >= 0; i--) {
5667 // No need to loop through child windows as the answer should be the same as that of the
5668 // parent window.
5669 if (!(mChildren.get(i)).mAppDied) {
5670 return true;
5671 }
5672 }
5673 return false;
5674 }
5675
5676 void setWillReplaceWindows(boolean animate) {
5677 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5678 "Marking app token %s with replacing windows.", this);
5679
5680 for (int i = mChildren.size() - 1; i >= 0; i--) {
5681 final WindowState w = mChildren.get(i);
5682 w.setWillReplaceWindow(animate);
5683 }
5684 }
5685
5686 void setWillReplaceChildWindows() {
5687 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
5688 + " with replacing child windows.", this);
5689 for (int i = mChildren.size() - 1; i >= 0; i--) {
5690 final WindowState w = mChildren.get(i);
5691 w.setWillReplaceChildWindows();
5692 }
5693 }
5694
5695 void clearWillReplaceWindows() {
5696 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5697 "Resetting app token %s of replacing window marks.", this);
5698
5699 for (int i = mChildren.size() - 1; i >= 0; i--) {
5700 final WindowState w = mChildren.get(i);
5701 w.clearWillReplaceWindow();
5702 }
5703 }
5704
5705 void requestUpdateWallpaperIfNeeded() {
5706 for (int i = mChildren.size() - 1; i >= 0; i--) {
5707 final WindowState w = mChildren.get(i);
5708 w.requestUpdateWallpaperIfNeeded();
5709 }
5710 }
5711
5712 /**
5713 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
Riddle Hsu84bc3d72019-12-19 19:24:07 +08005714 * true and isn't fully transparent.
Garfield Tane8d84ab2019-10-11 09:49:40 -07005715 */
Riddle Hsu84bc3d72019-12-19 19:24:07 +08005716 WindowState getTopFullscreenOpaqueWindow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005717 for (int i = mChildren.size() - 1; i >= 0; i--) {
5718 final WindowState win = mChildren.get(i);
Riddle Hsu84bc3d72019-12-19 19:24:07 +08005719 if (win != null && win.mAttrs.isFullscreen() && !win.isFullyTransparent()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005720 return win;
5721 }
5722 }
5723 return null;
5724 }
5725
5726 WindowState findMainWindow() {
5727 return findMainWindow(true);
5728 }
5729
5730 /**
5731 * Finds the main window that either has type base application or application starting if
5732 * requested.
5733 *
5734 * @param includeStartingApp Allow to search application-starting windows to also be returned.
5735 * @return The main window of type base application or application starting if requested.
5736 */
5737 WindowState findMainWindow(boolean includeStartingApp) {
5738 WindowState candidate = null;
5739 for (int j = mChildren.size() - 1; j >= 0; --j) {
5740 final WindowState win = mChildren.get(j);
5741 final int type = win.mAttrs.type;
5742 // No need to loop through child window as base application and starting types can't be
5743 // child windows.
5744 if (type == TYPE_BASE_APPLICATION
5745 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
5746 // In cases where there are multiple windows, we prefer the non-exiting window. This
5747 // happens for example when replacing windows during an activity relaunch. When
5748 // constructing the animation, we want the new window, not the exiting one.
5749 if (win.mAnimatingExit) {
5750 candidate = win;
5751 } else {
5752 return win;
5753 }
5754 }
5755 }
5756 return candidate;
5757 }
5758
5759 SurfaceControl getAppAnimationLayer() {
5760 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
5761 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
5762 : ANIMATION_LAYER_STANDARD);
5763 }
5764
5765 @Override
5766 boolean needsZBoost() {
5767 return mNeedsZBoost || super.needsZBoost();
5768 }
5769
5770 @Override
5771 public SurfaceControl getAnimationLeashParent() {
5772 // For transitions in the pinned stack (menu activity) we just let them occur as a child
5773 // of the pinned stack.
5774 // All normal app transitions take place in an animation layer which is below the pinned
5775 // stack but may be above the parent stacks of the given animating apps by default. When
5776 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
5777 // stack, i.e. the hierarchy of the surfaces is unchanged.
5778 if (inPinnedWindowingMode()) {
5779 return getStack().getSurfaceControl();
5780 } else if (WindowManagerService.sHierarchicalAnimations) {
5781 return super.getAnimationLeashParent();
5782 } else {
5783 return getAppAnimationLayer();
5784 }
5785 }
5786
Garfield Tane8d84ab2019-10-11 09:49:40 -07005787 @VisibleForTesting
5788 boolean shouldAnimate(int transit) {
lumark19a5d2e2019-10-11 16:19:30 +08005789 if (task != null && !task.shouldAnimate()) {
5790 return false;
5791 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005792 final boolean isSplitScreenPrimary =
5793 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
5794 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
5795
Garfield Tane8d84ab2019-10-11 09:49:40 -07005796 // We animate always if it's not split screen primary, and only some special cases in split
5797 // screen primary because it causes issues with stack clipping when we run an un-minimize
5798 // animation at the same time.
5799 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
5800 }
5801
lumark19a5d2e2019-10-11 16:19:30 +08005802 @Override
5803 boolean isChangingAppTransition() {
Louis Changcdec0802019-11-11 11:45:07 +08005804 return task != null ? task.isChangingAppTransition() : super.isChangingAppTransition();
lumark19a5d2e2019-10-11 16:19:30 +08005805 }
5806
Garfield Tane8d84ab2019-10-11 09:49:40 -07005807 /**
5808 * Creates a layer to apply crop to an animation.
5809 */
5810 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
5811 ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
5812 final SurfaceControl.Builder builder = makeAnimationLeash()
5813 .setParent(getAnimationLeashParent())
5814 .setName(getSurfaceControl() + " - animation-bounds");
5815 final SurfaceControl boundsLayer = builder.build();
5816 t.show(boundsLayer);
5817 return boundsLayer;
5818 }
5819
Garfield Tane8d84ab2019-10-11 09:49:40 -07005820 @Override
5821 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
5822 return mAnimatingActivityRegistry != null
5823 && mAnimatingActivityRegistry.notifyAboutToFinish(
5824 this, endDeferFinishCallback);
5825 }
5826
5827 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
5828 if (mWmService.mDisableTransitionAnimation
5829 || !isVisible()
5830 || getDisplayContent().mAppTransition.isTransitionSet()
5831 || getSurfaceControl() == null) {
5832 return false;
5833 }
5834 // Only do an animation into and out-of freeform mode for now. Other mode
5835 // transition animations are currently handled by system-ui.
5836 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
5837 }
5838
lumark9bca6b42019-10-17 18:35:22 +08005839 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07005840 boolean isWaitingForTransitionStart() {
5841 final DisplayContent dc = getDisplayContent();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005842 return dc.mAppTransition.isTransitionSet()
5843 && (dc.mOpeningApps.contains(this)
5844 || dc.mClosingApps.contains(this)
5845 || dc.mChangingApps.contains(this));
5846 }
5847
5848 /**
5849 * Initializes a change transition. Because the app is visible already, there is a small period
5850 * of time where the user can see the app content/window update before the transition starts.
5851 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
5852 * "freezes" the location/crop until the transition starts.
5853 * <p>
5854 * Here's a walk-through of the process:
5855 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
5856 * 2. Set the temporary leash's position/crop to the current state.
5857 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
5858 * 4. Once the transition is ready, it will reparent the app to the animation leash.
5859 * 5. Detach the interim-change-leash.
5860 */
5861 private void initializeChangeTransition(Rect startBounds) {
5862 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
5863 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
5864 mDisplayContent.mChangingApps.add(this);
5865 mTransitStartRect.set(startBounds);
5866
5867 final SurfaceControl.Builder builder = makeAnimationLeash()
5868 .setParent(getAnimationLeashParent())
5869 .setName(getSurfaceControl() + " - interim-change-leash");
5870 mTransitChangeLeash = builder.build();
5871 Transaction t = getPendingTransaction();
5872 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
5873 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
5874 t.show(mTransitChangeLeash);
5875 t.reparent(getSurfaceControl(), mTransitChangeLeash);
5876 onAnimationLeashCreated(t, mTransitChangeLeash);
5877
5878 // Skip creating snapshot if this transition is controlled by a remote animator which
5879 // doesn't need it.
5880 ArraySet<Integer> activityTypes = new ArraySet<>();
5881 activityTypes.add(getActivityType());
5882 RemoteAnimationAdapter adapter =
5883 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
5884 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
5885 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
5886 return;
5887 }
5888
Garfield Tane8d84ab2019-10-11 09:49:40 -07005889 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
5890 SurfaceControl.ScreenshotGraphicBuffer snapshot =
5891 mWmService.mTaskSnapshotController.createTaskSnapshot(
5892 task, 1 /* scaleFraction */);
5893 if (snapshot != null) {
lumarkbc0032a2019-11-01 21:38:13 +08005894 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory, t, this,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005895 snapshot.getGraphicBuffer(), true /* relative */);
5896 }
5897 }
5898 }
5899
5900 @Override
5901 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
5902 // The leash is parented to the animation layer. We need to preserve the z-order by using
5903 // the prefix order index, but we boost if necessary.
5904 int layer = 0;
5905 if (!inPinnedWindowingMode()) {
5906 layer = getPrefixOrderIndex();
5907 } else {
5908 // Pinned stacks have animations take place within themselves rather than an animation
5909 // layer so we need to preserve the order relative to the stack (e.g. the order of our
5910 // task/parent).
5911 layer = getParent().getPrefixOrderIndex();
5912 }
5913
5914 if (mNeedsZBoost) {
5915 layer += Z_BOOST_BASE;
5916 }
5917 if (!mNeedsAnimationBoundsLayer) {
5918 t.setLayer(leash, layer);
5919 }
5920
5921 final DisplayContent dc = getDisplayContent();
5922 dc.assignStackOrdering();
5923
5924 if (leash == mTransitChangeLeash) {
5925 // This is a temporary state so skip any animation notifications
5926 return;
5927 } else if (mTransitChangeLeash != null) {
5928 // unparent mTransitChangeLeash for clean-up
5929 clearChangeLeash(t, false /* cancel */);
5930 }
5931
5932 if (mAnimatingActivityRegistry != null) {
5933 mAnimatingActivityRegistry.notifyStarting(this);
5934 }
5935
5936 // If the animation needs to be cropped then an animation bounds layer is created as a child
5937 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
5938 if (mNeedsAnimationBoundsLayer) {
5939 mTmpRect.setEmpty();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005940 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
5941 getTransit(), task)) {
5942 task.getBounds(mTmpRect);
5943 } else {
Louis Changdc077272019-11-12 16:52:56 +08005944 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005945 if (stack == null) {
5946 return;
5947 }
5948 // Set clip rect to stack bounds.
5949 stack.getBounds(mTmpRect);
5950 }
5951 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
5952
5953 // Crop to stack bounds.
5954 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
5955 t.setLayer(mAnimationBoundsLayer, layer);
5956
5957 // Reparent leash to animation bounds layer.
5958 t.reparent(leash, mAnimationBoundsLayer);
5959 }
5960 }
5961
5962 @Override
5963 void prepareSurfaces() {
Issei Suzukif2f6c912019-11-08 11:24:18 +01005964 final boolean show = isVisible() || isAnimating();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005965
5966 if (mSurfaceControl != null) {
5967 if (show && !mLastSurfaceShowing) {
5968 getPendingTransaction().show(mSurfaceControl);
5969 } else if (!show && mLastSurfaceShowing) {
5970 getPendingTransaction().hide(mSurfaceControl);
5971 }
5972 }
5973 if (mThumbnail != null) {
5974 mThumbnail.setShowing(getPendingTransaction(), show);
5975 }
5976 mLastSurfaceShowing = show;
5977 super.prepareSurfaces();
5978 }
5979
5980 /**
5981 * @return Whether our {@link #getSurfaceControl} is currently showing.
5982 */
5983 boolean isSurfaceShowing() {
5984 return mLastSurfaceShowing;
5985 }
5986
5987 boolean isInChangeTransition() {
5988 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
5989 }
5990
5991 void attachThumbnailAnimation() {
lumark9bca6b42019-10-17 18:35:22 +08005992 if (!isAnimating()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005993 return;
5994 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005995 final GraphicBuffer thumbnailHeader =
Louis Changcdec0802019-11-11 11:45:07 +08005996 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005997 if (thumbnailHeader == null) {
Louis Changcdec0802019-11-11 11:45:07 +08005998 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005999 return;
6000 }
6001 clearThumbnail();
lumarkbc0032a2019-11-01 21:38:13 +08006002 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
6003 getPendingTransaction(), this, thumbnailHeader);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006004 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
6005 }
6006
6007 /**
6008 * Attaches a surface with a thumbnail for the
6009 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
6010 */
6011 void attachCrossProfileAppsThumbnailAnimation() {
lumark9bca6b42019-10-17 18:35:22 +08006012 if (!isAnimating()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006013 return;
6014 }
6015 clearThumbnail();
6016
6017 final WindowState win = findMainWindow();
6018 if (win == null) {
6019 return;
6020 }
6021 final Rect frame = win.getFrameLw();
Louis Changcdec0802019-11-11 11:45:07 +08006022 final int thumbnailDrawableRes = task.mUserId == mWmService.mCurrentUserId
Garfield Tane8d84ab2019-10-11 09:49:40 -07006023 ? R.drawable.ic_account_circle
6024 : R.drawable.ic_corp_badge;
6025 final GraphicBuffer thumbnail =
6026 getDisplayContent().mAppTransition
6027 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
6028 if (thumbnail == null) {
6029 return;
6030 }
lumarkbc0032a2019-11-01 21:38:13 +08006031 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
Garfield Tane8d84ab2019-10-11 09:49:40 -07006032 getPendingTransaction(), this, thumbnail);
6033 final Animation animation =
6034 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
6035 win.getFrameLw());
6036 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
6037 frame.top));
6038 }
6039
6040 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
6041 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
6042
6043 // If this is a multi-window scenario, we use the windows frame as
6044 // destination of the thumbnail header animation. If this is a full screen
6045 // window scenario, we use the whole display as the target.
6046 WindowState win = findMainWindow();
6047 Rect appRect = win != null ? win.getContentFrameLw() :
6048 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
6049 final Rect insets = win != null ? win.getContentInsets() : null;
6050 final Configuration displayConfig = mDisplayContent.getConfiguration();
6051 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Louis Changcdec0802019-11-11 11:45:07 +08006052 appRect, insets, thumbnailHeader, task, displayConfig.uiMode,
Garfield Tane8d84ab2019-10-11 09:49:40 -07006053 displayConfig.orientation);
6054 }
6055
6056 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006057 public void onAnimationLeashLost(Transaction t) {
6058 super.onAnimationLeashLost(t);
6059 if (mAnimationBoundsLayer != null) {
6060 t.remove(mAnimationBoundsLayer);
6061 mAnimationBoundsLayer = null;
6062 }
6063
6064 if (mAnimatingActivityRegistry != null) {
6065 mAnimatingActivityRegistry.notifyFinished(this);
6066 }
6067 }
6068
6069 @Override
6070 protected void onAnimationFinished() {
6071 super.onAnimationFinished();
6072
Issei Suzuki2bcbd682019-11-08 13:20:14 +01006073 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished");
Garfield Tane8d84ab2019-10-11 09:49:40 -07006074 mTransit = TRANSIT_UNSET;
6075 mTransitFlags = 0;
6076 mNeedsZBoost = false;
6077 mNeedsAnimationBoundsLayer = false;
6078
6079 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
Issei Suzuki2bcbd682019-11-08 13:20:14 +01006080 "ActivityRecord");
Garfield Tane8d84ab2019-10-11 09:49:40 -07006081
6082 clearThumbnail();
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01006083 setClientVisible(isVisible() || mVisibleRequested);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006084
6085 getDisplayContent().computeImeTargetIfNeeded(this);
6086
6087 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
6088 + ": reportedVisible=" + reportedVisible
6089 + " okToDisplay=" + okToDisplay()
6090 + " okToAnimate=" + okToAnimate()
6091 + " startingDisplayed=" + startingDisplayed);
6092
6093 // clean up thumbnail window
6094 if (mThumbnail != null) {
6095 mThumbnail.destroy();
6096 mThumbnail = null;
6097 }
6098
6099 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
6100 // traverse the copy.
6101 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
6102 children.forEach(WindowState::onExitAnimationDone);
6103
6104 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
6105 scheduleAnimation();
6106
Louis Chang149d5c82019-12-30 09:47:39 +08006107 if (mAtmService.mRootWindowContainer.allResumedActivitiesIdle()
Garfield Tane8d84ab2019-10-11 09:49:40 -07006108 || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
6109 // If all activities are already idle or there is an activity that must be
6110 // stopped immediately after visible, then we now need to make sure we perform
6111 // the full stop of this activity. This is because we won't do that while they are still
6112 // waiting for the animation to finish.
6113 if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
6114 mAtmService.mStackSupervisor.scheduleIdleLocked();
6115 }
6116 } else {
6117 // Instead of doing the full stop routine here, let's just hide any activities
6118 // we now can, and let them stop when the normal idle happens.
6119 mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
6120 false /* remove */, true /* processPausingActivities */);
6121 }
6122 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
6123 }
6124
6125 /**
6126 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
6127 * to another leash.
6128 */
6129 private void clearChangeLeash(Transaction t, boolean cancel) {
6130 if (mTransitChangeLeash == null) {
6131 return;
6132 }
6133 if (cancel) {
6134 clearThumbnail();
6135 SurfaceControl sc = getSurfaceControl();
6136 SurfaceControl parentSc = getParentSurfaceControl();
6137 // Don't reparent if surface is getting destroyed
6138 if (parentSc != null && sc != null) {
6139 t.reparent(sc, getParentSurfaceControl());
6140 }
6141 }
6142 t.hide(mTransitChangeLeash);
6143 t.remove(mTransitChangeLeash);
6144 mTransitChangeLeash = null;
6145 if (cancel) {
6146 onAnimationLeashLost(t);
6147 }
6148 }
6149
6150 void clearAnimatingFlags() {
6151 boolean wallpaperMightChange = false;
6152 for (int i = mChildren.size() - 1; i >= 0; i--) {
6153 final WindowState win = mChildren.get(i);
6154 wallpaperMightChange |= win.clearAnimatingFlags();
6155 }
6156 if (wallpaperMightChange) {
6157 requestUpdateWallpaperIfNeeded();
6158 }
6159 }
6160
Garfield Tane8d84ab2019-10-11 09:49:40 -07006161 @Override
6162 void cancelAnimation() {
6163 cancelAnimationOnly();
6164 clearThumbnail();
6165 clearChangeLeash(getPendingTransaction(), true /* cancel */);
6166 }
6167
6168 /**
6169 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
6170 * or interim leashes.
6171 * <p>
6172 * Used when canceling in preparation for starting a new animation.
6173 */
6174 void cancelAnimationOnly() {
6175 super.cancelAnimation();
6176 }
6177
6178 @VisibleForTesting
lumarkbc0032a2019-11-01 21:38:13 +08006179 WindowContainerThumbnail getThumbnail() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006180 return mThumbnail;
6181 }
6182
6183 private void clearThumbnail() {
6184 if (mThumbnail == null) {
6185 return;
6186 }
6187 mThumbnail.destroy();
6188 mThumbnail = null;
6189 }
6190
6191 public int getTransit() {
6192 return mTransit;
6193 }
6194
6195 int getTransitFlags() {
6196 return mTransitFlags;
6197 }
6198
6199 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
6200 mRemoteAnimationDefinition = definition;
Winson Chung10fc25d2019-12-10 14:13:56 -08006201 if (definition != null) {
6202 definition.linkToDeath(this::unregisterRemoteAnimations);
6203 }
6204 }
6205
6206 void unregisterRemoteAnimations() {
6207 mRemoteAnimationDefinition = null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07006208 }
6209
6210 RemoteAnimationDefinition getRemoteAnimationDefinition() {
6211 return mRemoteAnimationDefinition;
6212 }
6213
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006214 void setRequestedOrientation(int requestedOrientation) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006215 setOrientation(requestedOrientation, mayFreezeScreenLocked());
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006216 mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07006217 task.mTaskId, requestedOrientation);
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006218 }
6219
Garfield Tan90b04282018-12-11 14:04:42 -08006220 private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
Evan Rosky730f6e82018-12-03 17:40:11 -08006221 final IBinder binder =
6222 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006223 setOrientation(requestedOrientation, binder, this);
Garfield Tan36a69ad2019-01-16 17:08:23 -08006224
6225 // Push the new configuration to the requested app in case where it's not pushed, e.g. when
6226 // the request is handled at task level with letterbox.
6227 if (!getMergedOverrideConfiguration().equals(
6228 mLastReportedConfiguration.getMergedConfiguration())) {
6229 ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
6230 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08006231 }
6232
Garfield Tane8d84ab2019-10-11 09:49:40 -07006233 void reportDescendantOrientationChangeIfNeeded() {
6234 // Orientation request is exposed only when we're visible. Therefore visibility change
6235 // will change requested orientation. Notify upward the hierarchy ladder to adjust
6236 // configuration. This is important to cases where activities with incompatible
6237 // orientations launch, or user goes back from an activity of bi-orientation to an
6238 // activity with specified orientation.
6239 if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
6240 return;
6241 }
6242
6243 final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
6244 onDescendantOrientationChanged(freezeToken, this);
6245 }
6246
6247 /**
6248 * We override because this class doesn't want its children affecting its reported orientation
6249 * in anyway.
6250 */
6251 @Override
6252 int getOrientation(int candidate) {
6253 if (candidate == SCREEN_ORIENTATION_BEHIND) {
6254 // Allow app to specify orientation regardless of its visibility state if the current
6255 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
6256 // wants us to use the orientation of the app behind it.
6257 return mOrientation;
6258 }
6259
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08006260 // The {@link ActivityRecord} should only specify an orientation when it is not closing.
6261 // Allowing closing {@link ActivityRecord} to participate can lead to an Activity in another
6262 // task being started in the wrong orientation during the transition.
6263 if (!getDisplayContent().mClosingApps.contains(this)
Garfield Tane8d84ab2019-10-11 09:49:40 -07006264 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
6265 return mOrientation;
6266 }
6267
6268 return SCREEN_ORIENTATION_UNSET;
6269 }
6270
6271 /** Returns the app's preferred orientation regardless of its currently visibility state. */
6272 int getRequestedOrientation() {
6273 return mOrientation;
6274 }
6275
Bryce Leea163b762017-01-24 11:05:01 -08006276 /**
6277 * Set the last reported global configuration to the client. Should be called whenever a new
6278 * global configuration is sent to the client for this activity.
6279 */
6280 void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006281 mLastReportedConfiguration.setGlobalConfiguration(config);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006282 }
6283
Bryce Leea163b762017-01-24 11:05:01 -08006284 /**
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006285 * Set the last reported configuration to the client. Should be called whenever
Bryce Leea163b762017-01-24 11:05:01 -08006286 * a new merged configuration is sent to the client for this activity.
6287 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006288 void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006289 setLastReportedConfiguration(config.getGlobalConfiguration(),
6290 config.getOverrideConfiguration());
Bryce Leea163b762017-01-24 11:05:01 -08006291 }
6292
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07006293 private void setLastReportedConfiguration(Configuration global, Configuration override) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006294 mLastReportedConfiguration.setConfiguration(global, override);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006295 }
6296
Riddle Hsu0a343c32018-12-21 00:40:48 +08006297 /**
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006298 * @return {@code true} if this activity is in size compatibility mode that uses the different
6299 * density or bounds from its parent.
6300 */
6301 boolean inSizeCompatMode() {
Evan Rosky72f084d2019-09-11 17:05:16 -07006302 if (mCompatDisplayInsets == null || !shouldUseSizeCompatMode()) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006303 return false;
6304 }
Riddle Hsu359c84d2019-12-10 17:49:52 +08006305 final Rect appBounds = getConfiguration().windowConfiguration.getAppBounds();
6306 if (appBounds == null) {
6307 // The app bounds hasn't been computed yet.
Riddle Hsu04164182019-03-07 18:03:27 +08006308 return false;
6309 }
6310
6311 final Configuration parentConfig = getParent().getConfiguration();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006312 // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
6313 // fields should be changed with density and bounds, so here only compares the most
6314 // significant field.
Riddle Hsu359c84d2019-12-10 17:49:52 +08006315 if (parentConfig.densityDpi != getConfiguration().densityDpi) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006316 return true;
6317 }
Riddle Hsu04164182019-03-07 18:03:27 +08006318
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006319 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
Riddle Hsu359c84d2019-12-10 17:49:52 +08006320 final int appWidth = appBounds.width();
6321 final int appHeight = appBounds.height();
Riddle Hsuaec55442019-03-12 17:25:35 +08006322 final int parentAppWidth = parentAppBounds.width();
6323 final int parentAppHeight = parentAppBounds.height();
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006324 if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
6325 // Matched the parent bounds.
6326 return false;
6327 }
6328 if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
6329 // Both sides are smaller than the parent.
6330 return true;
6331 }
Riddle Hsuaec55442019-03-12 17:25:35 +08006332 if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
Riddle Hsu04164182019-03-07 18:03:27 +08006333 // One side is larger than the parent.
6334 return true;
6335 }
6336
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006337 // The rest of the condition is that only one side is smaller than the parent, but it still
6338 // needs to exclude the cases where the size is limited by the fixed aspect ratio.
6339 if (info.maxAspectRatio > 0) {
Riddle Hsu359c84d2019-12-10 17:49:52 +08006340 final float aspectRatio =
6341 (float) Math.max(appWidth, appHeight) / Math.min(appWidth, appHeight);
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006342 if (aspectRatio >= info.maxAspectRatio) {
6343 // The current size has reached the max aspect ratio.
6344 return false;
Riddle Hsuaec55442019-03-12 17:25:35 +08006345 }
6346 }
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006347 if (info.minAspectRatio > 0) {
6348 // The activity should have at least the min aspect ratio, so this checks if the parent
6349 // still has available space to provide larger aspect ratio.
6350 final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
6351 / Math.min(parentAppWidth, parentAppHeight);
6352 if (parentAspectRatio <= info.minAspectRatio) {
6353 // The long side has reached the parent.
6354 return false;
6355 }
6356 }
6357 return true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006358 }
6359
6360 /**
Riddle Hsu0a343c32018-12-21 00:40:48 +08006361 * Indicates the activity will keep the bounds and screen configuration when it was first
6362 * launched, no matter how its parent changes.
6363 *
6364 * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
6365 * aspect ratio.
6366 */
Riddle Hsu74826262019-04-17 14:57:42 +08006367 boolean shouldUseSizeCompatMode() {
Riddle Hsu0a343c32018-12-21 00:40:48 +08006368 return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
6369 // The configuration of non-standard type should be enforced by system.
6370 && isActivityTypeStandard()
6371 && !mAtmService.mForceResizableActivities;
6372 }
6373
Garfield Tane8d84ab2019-10-11 09:49:40 -07006374 boolean hasSizeCompatBounds() {
6375 return mSizeCompatBounds != null;
6376 }
6377
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006378 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006379 private void updateSizeCompatMode() {
6380 if (mCompatDisplayInsets != null || !shouldUseSizeCompatMode()) {
6381 // The override configuration is set only once in size compatibility mode.
6382 return;
6383 }
6384 final Configuration parentConfig = getParent().getConfiguration();
6385 if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
6386 // Don't compute when launching in fullscreen and the fixed orientation is not the
6387 // current orientation. It is more accurately to compute the override bounds from
6388 // the updated configuration after the fixed orientation is applied.
6389 return;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006390 }
Riddle Hsu74826262019-04-17 14:57:42 +08006391
Evan Rosky72f084d2019-09-11 17:05:16 -07006392 Configuration overrideConfig = getRequestedOverrideConfiguration();
6393 final Configuration fullConfig = getConfiguration();
6394
6395 // Ensure the screen related fields are set. It is used to prevent activity relaunch
6396 // when moving between displays. For screenWidthDp and screenWidthDp, because they
6397 // are relative to bounds and density, they will be calculated in
Louis Changcdec0802019-11-11 11:45:07 +08006398 // {@link Task#computeConfigResourceOverrides} and the result will also be
Evan Rosky72f084d2019-09-11 17:05:16 -07006399 // relatively fixed.
6400 overrideConfig.colorMode = fullConfig.colorMode;
6401 overrideConfig.densityDpi = fullConfig.densityDpi;
Evan Rosky72f084d2019-09-11 17:05:16 -07006402 // The smallest screen width is the short side of screen bounds. Because the bounds
6403 // and density won't be changed, smallestScreenWidthDp is also fixed.
6404 overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
6405 if (info.isFixedOrientation()) {
6406 // lock rotation too. When in size-compat, onConfigurationChanged will watch for and
6407 // apply runtime rotation changes.
6408 overrideConfig.windowConfiguration.setRotation(
6409 fullConfig.windowConfiguration.getRotation());
6410 }
6411
6412 // The role of CompatDisplayInsets is like the override bounds.
Louis Chang677921f2019-12-06 16:44:24 +08006413 final DisplayContent display = getDisplay();
Evan Rosky72f084d2019-09-11 17:05:16 -07006414 if (display != null) {
6415 mCompatDisplayInsets = new CompatDisplayInsets(display.mDisplayContent,
6416 getWindowConfiguration().getBounds(),
6417 getWindowConfiguration().tasksAreFloating());
6418 }
6419 }
6420
6421 private void clearSizeCompatMode() {
6422 mCompatDisplayInsets = null;
6423 onRequestedOverrideConfigurationChanged(EMPTY);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006424 }
6425
Garfield Tan0443b372019-01-04 15:00:13 -08006426 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006427 public boolean matchParentBounds() {
6428 if (super.matchParentBounds()) {
6429 return true;
6430 }
6431 // An activity in size compatibility mode may have override bounds which equals to its
6432 // parent bounds, so the exact bounds should also be checked.
6433 final WindowContainer parent = getParent();
6434 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
6435 }
6436
6437 @Override
6438 float getSizeCompatScale() {
6439 return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
6440 }
6441
6442 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006443 void resolveOverrideConfiguration(Configuration newParentConfiguration) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006444 Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu74826262019-04-17 14:57:42 +08006445 if (mCompatDisplayInsets != null) {
Riddle Hsu04164182019-03-07 18:03:27 +08006446 resolveSizeCompatModeConfiguration(newParentConfiguration);
6447 } else {
6448 super.resolveOverrideConfiguration(newParentConfiguration);
Garfield Tan966c0412019-11-19 11:34:27 -08006449 // We ignore activities' requested orientation in multi-window modes. Task level may
6450 // take them into consideration when calculating bounds.
6451 if (getParent() != null && getParent().inMultiWindowMode()) {
6452 resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
6453 }
Evan Rosky72f084d2019-09-11 17:05:16 -07006454 applyAspectRatio(resolvedConfig.windowConfiguration.getBounds(),
6455 newParentConfiguration.windowConfiguration.getAppBounds(),
6456 newParentConfiguration.windowConfiguration.getBounds());
Riddle Hsu74826262019-04-17 14:57:42 +08006457 // If the activity has override bounds, the relative configuration (e.g. screen size,
6458 // layout) needs to be resolved according to the bounds.
Evan Rosky72f084d2019-09-11 17:05:16 -07006459 if (task != null && !resolvedConfig.windowConfiguration.getBounds().isEmpty()) {
Riddle Hsu04164182019-03-07 18:03:27 +08006460 task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
Riddle Hsu61987bc2019-04-03 13:08:47 +08006461 newParentConfiguration);
Riddle Hsu04164182019-03-07 18:03:27 +08006462 }
6463 }
Garfield Tan0443b372019-01-04 15:00:13 -08006464
6465 // Assign configuration sequence number into hierarchy because there is a different way than
6466 // ensureActivityConfiguration() in this class that uses configuration in WindowState during
6467 // layout traversals.
6468 mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
6469 getResolvedOverrideConfiguration().seq = mConfigurationSeq;
Riddle Hsu04164182019-03-07 18:03:27 +08006470 }
Riddle Hsu0a343c32018-12-21 00:40:48 +08006471
Riddle Hsu74826262019-04-17 14:57:42 +08006472 /**
6473 * Resolves consistent screen configuration for orientation and rotation changes without
6474 * inheriting the parent bounds.
6475 */
Riddle Hsu04164182019-03-07 18:03:27 +08006476 private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006477 super.resolveOverrideConfiguration(newParentConfiguration);
Riddle Hsu0a343c32018-12-21 00:40:48 +08006478 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu04164182019-03-07 18:03:27 +08006479 final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
Riddle Hsu0a343c32018-12-21 00:40:48 +08006480
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006481 Rect parentBounds = new Rect(newParentConfiguration.windowConfiguration.getBounds());
Riddle Hsu0a343c32018-12-21 00:40:48 +08006482
Evan Rosky72f084d2019-09-11 17:05:16 -07006483 int orientation = getRequestedConfigurationOrientation();
6484 if (orientation == ORIENTATION_UNDEFINED) {
6485 orientation = newParentConfiguration.orientation;
6486 }
6487 int rotation = resolvedConfig.windowConfiguration.getRotation();
6488 if (rotation == ROTATION_UNDEFINED) {
6489 rotation = newParentConfiguration.windowConfiguration.getRotation();
6490 }
6491
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006492 // Use compat insets to lock width and height. We should not use the parent width and height
6493 // because apps in compat mode should have a constant width and height. The compat insets
6494 // are locked when the app is first launched and are never changed after that, so we can
6495 // rely on them to contain the original and unchanging width and height of the app.
6496 final Rect compatDisplayBounds = mTmpBounds;
Evan Rosky72f084d2019-09-11 17:05:16 -07006497 mCompatDisplayInsets.getDisplayBoundsByRotation(compatDisplayBounds, rotation);
6498 final Rect containingAppBounds = new Rect();
6499 mCompatDisplayInsets.getFrameByOrientation(containingAppBounds, orientation);
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006500
Evan Rosky72f084d2019-09-11 17:05:16 -07006501 // Center containingAppBounds horizontally and aligned to top of parent. Both
6502 // are usually the same unless the app was frozen with an orientation letterbox.
6503 int left = compatDisplayBounds.left + compatDisplayBounds.width() / 2
6504 - containingAppBounds.width() / 2;
6505 resolvedBounds.set(left, compatDisplayBounds.top, left + containingAppBounds.width(),
6506 compatDisplayBounds.top + containingAppBounds.height());
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006507
Evan Rosky72f084d2019-09-11 17:05:16 -07006508 if (rotation != ROTATION_UNDEFINED) {
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006509 // Ensure the parent and container bounds won't overlap with insets.
Louis Changcdec0802019-11-11 11:45:07 +08006510 Task.intersectWithInsetsIfFits(containingAppBounds, compatDisplayBounds,
Evan Rosky72f084d2019-09-11 17:05:16 -07006511 mCompatDisplayInsets.mNonDecorInsets[rotation]);
Louis Changcdec0802019-11-11 11:45:07 +08006512 Task.intersectWithInsetsIfFits(parentBounds, compatDisplayBounds,
Evan Rosky72f084d2019-09-11 17:05:16 -07006513 mCompatDisplayInsets.mNonDecorInsets[rotation]);
Riddle Hsu74826262019-04-17 14:57:42 +08006514 }
6515
Evan Rosky72f084d2019-09-11 17:05:16 -07006516 applyAspectRatio(resolvedBounds, containingAppBounds, compatDisplayBounds);
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006517
6518 // Center horizontally in parent and align to top of parent - this is a UX choice
Evan Rosky72f084d2019-09-11 17:05:16 -07006519 left = parentBounds.left + parentBounds.width() / 2 - resolvedBounds.width() / 2;
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006520 resolvedBounds.set(left, parentBounds.top, left + resolvedBounds.width(),
6521 parentBounds.top + resolvedBounds.height());
6522
6523 // We want to get as much of the app on the screen even if insets cover it. This is because
6524 // insets change but an app's bounds are more permanent after launch. After computing insets
6525 // and horizontally centering resolvedBounds, the resolvedBounds may end up outside parent
6526 // bounds. This is okay only if the resolvedBounds exceed their parent on the bottom and
6527 // right, because that is clipped when the final bounds are computed. To reach this state,
6528 // we first try and push the app as much inside the parent towards the top and left (the
6529 // min). The app may then end up outside the parent by going too far left and top, so we
6530 // push it back into the parent by taking the max with parent left and top.
6531 Rect fullParentBounds = newParentConfiguration.windowConfiguration.getBounds();
6532 resolvedBounds.offsetTo(Math.max(fullParentBounds.left,
6533 Math.min(fullParentBounds.right - resolvedBounds.width(), resolvedBounds.left)),
6534 Math.max(fullParentBounds.top,
6535 Math.min(fullParentBounds.bottom - resolvedBounds.height(),
6536 resolvedBounds.top)));
6537
6538 // Use resolvedBounds to compute other override configurations such as appBounds
Riddle Hsu74826262019-04-17 14:57:42 +08006539 task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
6540 mCompatDisplayInsets);
Riddle Hsuca928562019-11-22 01:04:14 +08006541 // Use current screen layout as source because the size of app is independent to parent.
6542 resolvedConfig.screenLayout = Task.computeScreenLayoutOverride(
6543 getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
6544 resolvedConfig.screenHeightDp);
Riddle Hsu74826262019-04-17 14:57:42 +08006545
Riddle Hsu04164182019-03-07 18:03:27 +08006546 // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
6547 // the parent bounds appropriately.
6548 if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
6549 resolvedConfig.orientation = newParentConfiguration.orientation;
Riddle Hsu0a343c32018-12-21 00:40:48 +08006550 }
Garfield Tan0443b372019-01-04 15:00:13 -08006551 }
6552
6553 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006554 public Rect getBounds() {
6555 if (mSizeCompatBounds != null) {
6556 return mSizeCompatBounds;
6557 }
6558 return super.getBounds();
6559 }
6560
6561 @Override
6562 Rect getDisplayedBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006563 if (task != null) {
6564 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
6565 if (!overrideDisplayedBounds.isEmpty()) {
6566 return overrideDisplayedBounds;
6567 }
6568 }
6569 return getBounds();
6570 }
6571
6572 @VisibleForTesting
lumark19a5d2e2019-10-11 16:19:30 +08006573 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006574 Rect getAnimationBounds(int appStackClipMode) {
6575 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
6576 // Using the stack bounds here effectively applies the clipping before animation.
6577 return getStack().getBounds();
6578 }
6579 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
6580 // included in the animation.
Louis Changcdec0802019-11-11 11:45:07 +08006581 return task != null ? task.getBounds() : getBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006582 }
6583
6584 /**
6585 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
6586 * region which is available to application.
6587 */
6588 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
6589 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
6590 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
6591 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
6592 final Rect appBounds = getWindowConfiguration().getAppBounds();
6593 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
6594 final float contentW = contentBounds.width();
6595 final float contentH = contentBounds.height();
6596 final float viewportW = viewportBounds.width();
6597 final float viewportH = viewportBounds.height();
6598 // Only allow to scale down.
6599 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
6600 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
6601 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
6602 + viewportBounds.left;
6603
6604 if (mSizeCompatBounds == null) {
6605 mSizeCompatBounds = new Rect();
6606 }
6607 mSizeCompatBounds.set(contentBounds);
6608 mSizeCompatBounds.offsetTo(0, 0);
6609 mSizeCompatBounds.scale(mSizeCompatScale);
6610 // Ensure to align the top with the parent.
6611 mSizeCompatBounds.top = parentBounds.top;
6612 // The decor inset is included in height.
6613 mSizeCompatBounds.bottom += viewportBounds.top;
6614 mSizeCompatBounds.left += offsetX;
6615 mSizeCompatBounds.right += offsetX;
6616 }
6617
6618 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006619 public void onConfigurationChanged(Configuration newParentConfig) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006620 if (mCompatDisplayInsets != null) {
6621 Configuration overrideConfig = getRequestedOverrideConfiguration();
6622 // Adapt to changes in orientation locking. The app is still non-resizable, but
6623 // it can change which orientation is fixed. If the fixed orientation changes,
6624 // update the rotation used on the "compat" display
6625 boolean wasFixedOrient =
6626 overrideConfig.windowConfiguration.getRotation() != ROTATION_UNDEFINED;
6627 int requestedOrient = getRequestedConfigurationOrientation();
6628 if (requestedOrient != ORIENTATION_UNDEFINED
6629 && requestedOrient != getConfiguration().orientation
6630 // The task orientation depends on the top activity orientation, so it
6631 // should match. If it doesn't, just wait until it does.
6632 && requestedOrient == getParent().getConfiguration().orientation
6633 && (overrideConfig.windowConfiguration.getRotation()
6634 != getParent().getWindowConfiguration().getRotation())) {
6635 overrideConfig.windowConfiguration.setRotation(
6636 getParent().getWindowConfiguration().getRotation());
6637 onRequestedOverrideConfigurationChanged(overrideConfig);
6638 return;
6639 } else if (wasFixedOrient && requestedOrient == ORIENTATION_UNDEFINED
6640 && (overrideConfig.windowConfiguration.getRotation()
6641 != ROTATION_UNDEFINED)) {
6642 overrideConfig.windowConfiguration.setRotation(ROTATION_UNDEFINED);
6643 onRequestedOverrideConfigurationChanged(overrideConfig);
6644 return;
6645 }
6646 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07006647 final int prevWinMode = getWindowingMode();
6648 mTmpPrevBounds.set(getBounds());
Garfield Tan0443b372019-01-04 15:00:13 -08006649 super.onConfigurationChanged(newParentConfig);
6650
Garfield Tane8d84ab2019-10-11 09:49:40 -07006651 final Rect overrideBounds = getResolvedOverrideBounds();
6652 if (task != null && !overrideBounds.isEmpty()
6653 // If the changes come from change-listener, the incoming parent configuration is
6654 // still the old one. Make sure their orientations are the same to reduce computing
6655 // the compatibility bounds for the intermediate state.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02006656 && (task.getConfiguration().orientation == newParentConfig.orientation)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006657 final Rect taskBounds = task.getBounds();
6658 // Since we only center the activity horizontally, if only the fixed height is smaller
6659 // than its container, the override bounds don't need to take effect.
6660 if ((overrideBounds.width() != taskBounds.width()
6661 || overrideBounds.height() > taskBounds.height())) {
6662 calculateCompatBoundsTransformation(newParentConfig);
6663 updateSurfacePosition();
6664 } else if (mSizeCompatBounds != null) {
6665 mSizeCompatBounds = null;
6666 mSizeCompatScale = 1f;
6667 updateSurfacePosition();
6668 }
Evan Rosky72f084d2019-09-11 17:05:16 -07006669 } else if (overrideBounds.isEmpty()) {
6670 mSizeCompatBounds = null;
6671 mSizeCompatScale = 1f;
6672 updateSurfacePosition();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006673 }
6674
Hongwei Wange75e1912019-11-07 16:00:32 -08006675 final int newWinMode = getWindowingMode();
6676 if ((prevWinMode != newWinMode) && (mDisplayContent != null)
6677 && shouldStartChangeTransition(prevWinMode, newWinMode)) {
6678 initializeChangeTransition(mTmpPrevBounds);
6679 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07006680
Garfield Tan0443b372019-01-04 15:00:13 -08006681 // Configuration's equality doesn't consider seq so if only seq number changes in resolved
6682 // override configuration. Therefore ConfigurationContainer doesn't change merged override
6683 // configuration, but it's used to push configuration changes so explicitly update that.
6684 if (getMergedOverrideConfiguration().seq != getResolvedOverrideConfiguration().seq) {
6685 onMergedOverrideConfigurationChanged();
6686 }
6687
Louis Chang677921f2019-12-06 16:44:24 +08006688 final DisplayContent display = getDisplay();
Riddle Hsuaec55442019-03-12 17:25:35 +08006689 if (display == null) {
6690 return;
6691 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01006692 if (mVisibleRequested) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006693 // It may toggle the UI for user to restart the size compatibility mode activity.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006694 display.handleActivitySizeCompatModeIfNeeded(this);
Evan Rosky72f084d2019-09-11 17:05:16 -07006695 } else if (mCompatDisplayInsets != null) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006696 // The override changes can only be obtained from display, because we don't have the
6697 // difference of full configuration in each hierarchy.
Riddle Hsu7f704b52019-12-10 23:10:45 +08006698 final int displayChanges = display.getCurrentOverrideConfigurationChanges();
Riddle Hsuaec55442019-03-12 17:25:35 +08006699 final int orientationChanges = CONFIG_WINDOW_CONFIGURATION
6700 | CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION;
6701 final boolean hasNonOrienSizeChanged = hasResizeChange(displayChanges)
6702 // Filter out the case of simple orientation change.
6703 && (displayChanges & orientationChanges) != orientationChanges;
6704 // For background activity that uses size compatibility mode, if the size or density of
6705 // the display is changed, then reset the override configuration and kill the activity's
6706 // process if its process state is not important to user.
6707 if (hasNonOrienSizeChanged || (displayChanges & ActivityInfo.CONFIG_DENSITY) != 0) {
6708 restartProcessIfVisible();
6709 }
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006710 }
Garfield Tan0443b372019-01-04 15:00:13 -08006711 }
6712
Hongwei Wange75e1912019-11-07 16:00:32 -08006713 void savePinnedStackBounds() {
6714 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
6715 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
Louis Changdc077272019-11-12 16:52:56 +08006716 final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
Hongwei Wange75e1912019-11-07 16:00:32 -08006717 if (pinnedStack == null) return;
6718 final Rect stackBounds;
6719 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
6720 // We are animating the bounds, use the pre-animation bounds to save the snap
6721 // fraction
6722 stackBounds = pinnedStack.mPreAnimationBounds;
6723 } else {
6724 // We skip the animation if the fullscreen configuration is not compatible, so
6725 // use the current bounds to calculate the saved snap fraction instead
6726 // (see PinnedActivityStack.skipResizeAnimation())
6727 stackBounds = mTmpRect;
6728 pinnedStack.getBounds(stackBounds);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006729 }
jorgegil@google.com62f735e2019-10-30 14:37:19 -07006730 mDisplayContent.mPinnedStackControllerLocked.saveReentryBounds(
Hongwei Wange75e1912019-11-07 16:00:32 -08006731 mActivityComponent, stackBounds);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006732 }
6733
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006734 /** Returns true if the configuration is compatible with this activity. */
Wale Ogunwale42f07d92017-05-01 21:32:58 -07006735 boolean isConfigurationCompatible(Configuration config) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006736 final int orientation = getRequestedOrientation();
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006737 if (isFixedOrientationPortrait(orientation)
6738 && config.orientation != ORIENTATION_PORTRAIT) {
6739 return false;
6740 }
6741 if (isFixedOrientationLandscape(orientation)
6742 && config.orientation != ORIENTATION_LANDSCAPE) {
6743 return false;
6744 }
6745 return true;
6746 }
6747
Bryce Lee7566d762017-03-30 09:34:15 -07006748 /**
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006749 * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
6750 * made to outBounds.
Bryce Lee7566d762017-03-30 09:34:15 -07006751 */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006752 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006753 private void applyAspectRatio(Rect outBounds, Rect containingAppBounds,
6754 Rect containingBounds) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006755 final float maxAspectRatio = info.maxAspectRatio;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006756 final ActivityStack stack = getActivityStack();
Adrian Roos917791e2018-11-28 16:30:44 +01006757 final float minAspectRatio = info.minAspectRatio;
6758
Evan Rosky72f084d2019-09-11 17:05:16 -07006759 if (task == null || stack == null || (inMultiWindowMode() && !shouldUseSizeCompatMode())
Adrian Roos917791e2018-11-28 16:30:44 +01006760 || (maxAspectRatio == 0 && minAspectRatio == 0)
Bryce Leee5ab4502017-07-11 08:58:05 -07006761 || isInVrUiMode(getConfiguration())) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006762 // We don't enforce aspect ratio if the activity task is in multiwindow unless it
6763 // is in size-compat mode. We also don't set it if we are in VR mode.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006764 return;
6765 }
6766
Riddle Hsu74826262019-04-17 14:57:42 +08006767 final int containingAppWidth = containingAppBounds.width();
6768 final int containingAppHeight = containingAppBounds.height();
Adrian Roos917791e2018-11-28 16:30:44 +01006769 final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
6770 / (float) Math.min(containingAppWidth, containingAppHeight);
Bryce Lee7566d762017-03-30 09:34:15 -07006771
Adrian Roos917791e2018-11-28 16:30:44 +01006772 int activityWidth = containingAppWidth;
6773 int activityHeight = containingAppHeight;
6774
6775 if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
6776 if (containingAppWidth < containingAppHeight) {
6777 // Width is the shorter side, so we use that to figure-out what the max. height
6778 // should be given the aspect ratio.
6779 activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
6780 } else {
6781 // Height is the shorter side, so we use that to figure-out what the max. width
6782 // should be given the aspect ratio.
6783 activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
6784 }
Tiger Huang3d2b8982019-01-29 22:56:48 +08006785 } else if (containingRatio < minAspectRatio) {
6786 boolean adjustWidth;
6787 switch (getRequestedConfigurationOrientation()) {
6788 case ORIENTATION_LANDSCAPE:
6789 // Width should be the longer side for this landscape app, so we use the width
6790 // to figure-out what the max. height should be given the aspect ratio.
6791 adjustWidth = false;
6792 break;
6793 case ORIENTATION_PORTRAIT:
6794 // Height should be the longer side for this portrait app, so we use the height
6795 // to figure-out what the max. width should be given the aspect ratio.
6796 adjustWidth = true;
6797 break;
6798 default:
6799 // This app doesn't have a preferred orientation, so we keep the length of the
6800 // longer side, and use it to figure-out the length of the shorter side.
6801 if (containingAppWidth < containingAppHeight) {
6802 // Width is the shorter side, so we use the height to figure-out what the
6803 // max. width should be given the aspect ratio.
6804 adjustWidth = true;
6805 } else {
6806 // Height is the shorter side, so we use the width to figure-out what the
6807 // max. height should be given the aspect ratio.
6808 adjustWidth = false;
6809 }
6810 break;
6811 }
6812 if (adjustWidth) {
Adrian Roos917791e2018-11-28 16:30:44 +01006813 activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
6814 } else {
Adrian Roos917791e2018-11-28 16:30:44 +01006815 activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
6816 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006817 }
6818
Adrian Roos917791e2018-11-28 16:30:44 +01006819 if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006820 // The display matches or is less than the activity aspect ratio, so nothing else to do.
6821 return;
6822 }
6823
6824 // Compute configuration based on max supported width and height.
Adrian Roos24be34d2018-05-28 18:55:38 +02006825 // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
Louis Changcdec0802019-11-11 11:45:07 +08006826 // away later in {@link Task#computeConfigResourceOverrides()}. Otherwise, the app
Adrian Roos24be34d2018-05-28 18:55:38 +02006827 // bounds would end up too small.
Evan Rosky72f084d2019-09-11 17:05:16 -07006828 outBounds.set(containingBounds.left, containingBounds.top,
6829 activityWidth + containingAppBounds.left,
Riddle Hsu74826262019-04-17 14:57:42 +08006830 activityHeight + containingAppBounds.top);
Andrii Kulian3a1619d2017-07-07 14:38:09 -07006831 }
6832
Riddle Hsu16567132018-08-16 21:37:47 +08006833 /**
6834 * @return {@code true} if this activity was reparented to another display but
6835 * {@link #ensureActivityConfiguration} is not called.
6836 */
6837 boolean shouldUpdateConfigForDisplayChanged() {
6838 return mLastReportedDisplayId != getDisplayId();
6839 }
6840
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006841 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
6842 return ensureActivityConfiguration(globalChanges, preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006843 false /* ignoreVisibility */);
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006844 }
6845
Andrii Kulian21713ac2016-10-12 22:05:05 -07006846 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006847 * Make sure the given activity matches the current configuration. Ensures the HistoryRecord
6848 * is updated with the correct configuration and all other bookkeeping is handled.
6849 *
6850 * @param globalChanges The changes to the global configuration.
6851 * @param preserveWindow If the activity window should be preserved on screen if the activity
6852 * is relaunched.
Riddle Hsu609a8e22019-06-27 16:46:29 -06006853 * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
6854 * (stopped state). This is useful for the case where we know the
6855 * activity will be visible soon and we want to ensure its configuration
6856 * before we make it visible.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006857 * @return False if the activity was relaunched and true if it wasn't relaunched because we
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006858 * can't or the app handles the specific configuration that is changing.
Andrii Kulian21713ac2016-10-12 22:05:05 -07006859 */
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006860 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006861 boolean ignoreVisibility) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006862 final ActivityStack stack = getActivityStack();
Andrii Kulian21713ac2016-10-12 22:05:05 -07006863 if (stack.mConfigWillChange) {
6864 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6865 "Skipping config check (will change): " + this);
6866 return true;
6867 }
6868
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006869 // We don't worry about activities that are finishing.
6870 if (finishing) {
6871 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6872 "Configuration doesn't matter in finishing " + this);
6873 stopFreezingScreenLocked(false);
6874 return true;
6875 }
6876
Riddle Hsu609a8e22019-06-27 16:46:29 -06006877 if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006878 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006879 "Skipping config check invisible: " + this);
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006880 return true;
6881 }
6882
Andrii Kulian21713ac2016-10-12 22:05:05 -07006883 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6884 "Ensuring correct configuration: " + this);
6885
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006886 final int newDisplayId = getDisplayId();
6887 final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
6888 if (displayChanged) {
6889 mLastReportedDisplayId = newDisplayId;
6890 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006891 // TODO(b/36505427): Is there a better place to do this?
Evan Rosky72f084d2019-09-11 17:05:16 -07006892 updateSizeCompatMode();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006893
Winson Chungbdc646f2017-02-13 12:12:22 -08006894 // Short circuit: if the two full configurations are equal (the common case), then there is
6895 // nothing to do. We test the full configuration instead of the global and merged override
6896 // configurations because there are cases (like moving a task to the pinned stack) where
6897 // the combine configurations are equal, but would otherwise differ in the override config
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006898 mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
6899 if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006900 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006901 "Configuration & display unchanged in " + this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006902 return true;
6903 }
6904
6905 // Okay we now are going to make this activity have the new config.
6906 // But then we need to figure out how it needs to deal with that.
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006907
6908 // Find changes between last reported merged configuration and the current one. This is used
6909 // to decide whether to relaunch an activity or just report a configuration change.
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006910 final int changes = getConfigurationChanges(mTmpConfig);
Ruben Brunkf64af332017-03-22 22:03:25 -07006911
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006912 // Update last reported values.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006913 final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
Bryce Lee8104e7a2017-08-17 09:16:03 -07006914
Andrii Kulianbeadacc2019-05-20 12:18:01 +00006915 setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006916
Bryce Lee7ace3952018-02-16 14:34:32 -08006917 if (mState == INITIALIZING) {
Andrii Kulianb372da62018-01-18 10:46:24 -08006918 // No need to relaunch or schedule new config for activity that hasn't been launched
6919 // yet. We do, however, return after applying the config to activity record, so that
6920 // it will use it for launch transaction.
6921 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6922 "Skipping config check for initializing activity: " + this);
6923 return true;
6924 }
6925
Andrii Kulian21713ac2016-10-12 22:05:05 -07006926 if (changes == 0 && !forceNewConfig) {
6927 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6928 "Configuration no differences in " + this);
6929 // There are no significant differences, so we won't relaunch but should still deliver
6930 // the new configuration to the client process.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006931 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006932 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006933 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006934 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006935 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07006936 return true;
6937 }
6938
6939 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006940 "Configuration changes for " + this + ", allChanges="
Andrii Kulian21713ac2016-10-12 22:05:05 -07006941 + Configuration.configurationDiffToString(changes));
6942
6943 // If the activity isn't currently running, just leave the new configuration and it will
6944 // pick that up next time it starts.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006945 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006946 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6947 "Configuration doesn't matter not running " + this);
6948 stopFreezingScreenLocked(false);
6949 forceNewConfig = false;
6950 return true;
6951 }
6952
6953 // Figure out how to handle the changes between the configurations.
6954 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6955 "Checking to restart " + info.name + ": changed=0x"
6956 + Integer.toHexString(changes) + ", handles=0x"
6957 + Integer.toHexString(info.getRealConfigChanged())
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006958 + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006959
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006960 if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006961 // Aha, the activity isn't handling the change, so DIE DIE DIE.
6962 configChangeFlags |= changes;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006963 startFreezingScreenLocked(globalChanges);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006964 forceNewConfig = false;
6965 preserveWindow &= isResizeOnlyChange(changes);
Garfield Tan2746ab52018-07-25 12:33:01 -07006966 final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
6967 if (hasResizeChange) {
Louis Changcdec0802019-11-11 11:45:07 +08006968 final boolean isDragResizing = task.isDragResizing();
Garfield Tan2746ab52018-07-25 12:33:01 -07006969 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
6970 : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
6971 } else {
6972 mRelaunchReason = RELAUNCH_REASON_NONE;
6973 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006974 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006975 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6976 "Config is destroying non-running " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07006977 destroyImmediately(true /* removeFromApp */, "config");
Bryce Lee7ace3952018-02-16 14:34:32 -08006978 } else if (mState == PAUSING) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006979 // A little annoying: we are waiting for this activity to finish pausing. Let's not
6980 // do anything now, but just flag that it needs to be restarted when done pausing.
6981 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6982 "Config is skipping already pausing " + this);
6983 deferRelaunchUntilPaused = true;
6984 preserveWindowOnDeferredRelaunch = preserveWindow;
6985 return true;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006986 } else {
6987 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006988 "Config is relaunching " + this);
Issei Suzuki1669ea42019-11-06 14:20:59 +01006989 if (DEBUG_STATES && !mVisibleRequested) {
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006990 Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
6991 + " called by " + Debug.getCallers(4));
6992 }
6993 relaunchActivityLocked(preserveWindow);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006994 }
6995
6996 // All done... tell the caller we weren't able to keep this activity around.
6997 return false;
6998 }
6999
7000 // Default case: the activity can handle this new configuration, so hand it over.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007001 // NOTE: We only forward the override configuration as the system level configuration
Andrii Kulian21713ac2016-10-12 22:05:05 -07007002 // changes is always sent to all processes when they happen so it can just use whatever
7003 // system level configuration it last got.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08007004 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007005 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08007006 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007007 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08007008 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07007009 stopFreezingScreenLocked(false);
7010
7011 return true;
7012 }
7013
Zak Cohen90e7116742017-01-29 12:59:23 -08007014 /**
7015 * When assessing a configuration change, decide if the changes flags and the new configurations
7016 * should cause the Activity to relaunch.
Ruben Brunkf64af332017-03-22 22:03:25 -07007017 *
7018 * @param changes the changes due to the given configuration.
7019 * @param changesConfig the configuration that was used to calculate the given changes via a
7020 * call to getConfigurationChanges.
Zak Cohen90e7116742017-01-29 12:59:23 -08007021 */
Ruben Brunkf64af332017-03-22 22:03:25 -07007022 private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
Zak Cohen90e7116742017-01-29 12:59:23 -08007023 int configChanged = info.getRealConfigChanged();
Ruben Brunkf64af332017-03-22 22:03:25 -07007024 boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
Zak Cohen90e7116742017-01-29 12:59:23 -08007025
7026 // Override for apps targeting pre-O sdks
7027 // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
7028 // to the config change.
7029 // For O and later, apps will be required to add configChanges="uimode" to their manifest.
Andrii Kulianeceebbf2019-06-26 17:36:51 -07007030 if (info.applicationInfo.targetSdkVersion < O
Zak Cohen90e7116742017-01-29 12:59:23 -08007031 && requestedVrComponent != null
Ruben Brunkf64af332017-03-22 22:03:25 -07007032 && onlyVrUiModeChanged) {
Zak Cohen90e7116742017-01-29 12:59:23 -08007033 configChanged |= CONFIG_UI_MODE;
7034 }
7035
7036 return (changes&(~configChanged)) != 0;
7037 }
7038
Ruben Brunkf64af332017-03-22 22:03:25 -07007039 /**
7040 * Returns true if the configuration change is solely due to the UI mode switching into or out
7041 * of UI_MODE_TYPE_VR_HEADSET.
7042 */
7043 private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
7044 final Configuration currentConfig = getConfiguration();
Ruben Brunkf53497c2017-03-27 20:26:17 -07007045 return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
Ruben Brunkf64af332017-03-22 22:03:25 -07007046 != isInVrUiMode(lastReportedConfig));
7047 }
7048
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007049 private int getConfigurationChanges(Configuration lastReportedConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07007050 // Determine what has changed. May be nothing, if this is a config that has come back from
7051 // the app after going idle. In that case we just want to leave the official config object
7052 // now in the activity and do nothing else.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007053 final Configuration currentConfig = getConfiguration();
7054 int changes = lastReportedConfig.diff(currentConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007055 // We don't want to use size changes if they don't cross boundaries that are important to
7056 // the app.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007057 if ((changes & CONFIG_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08007058 final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
7059 currentConfig.screenWidthDp)
7060 || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
7061 currentConfig.screenHeightDp);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007062 if (!crosses) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007063 changes &= ~CONFIG_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07007064 }
7065 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007066 if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08007067 final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
7068 final int newSmallest = currentConfig.smallestScreenWidthDp;
7069 if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007070 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07007071 }
7072 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07007073 // We don't want window configuration to cause relaunches.
7074 if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
7075 changes &= ~CONFIG_WINDOW_CONFIGURATION;
7076 }
Bryce Lee600dadd2017-07-25 10:48:42 -07007077
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007078 return changes;
Andrii Kulian21713ac2016-10-12 22:05:05 -07007079 }
7080
7081 private static boolean isResizeOnlyChange(int change) {
7082 return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
7083 | CONFIG_SCREEN_LAYOUT)) == 0;
7084 }
7085
Garfield Tan2746ab52018-07-25 12:33:01 -07007086 private static boolean hasResizeChange(int change) {
7087 return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
7088 | CONFIG_SCREEN_LAYOUT)) != 0;
7089 }
7090
wilsonshihb5d8f8b2019-10-23 13:01:40 +08007091 void relaunchActivityLocked(boolean preserveWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007092 if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07007093 configChangeFlags = 0;
7094 return;
7095 }
7096
wilsonshihb5d8f8b2019-10-23 13:01:40 +08007097 final boolean andResume = shouldBeResumed(null /*activeActivity*/);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007098 List<ResultInfo> pendingResults = null;
7099 List<ReferrerIntent> pendingNewIntents = null;
7100 if (andResume) {
7101 pendingResults = results;
7102 pendingNewIntents = newIntents;
7103 }
7104 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
7105 "Relaunching: " + this + " with results=" + pendingResults
7106 + " newIntents=" + pendingNewIntents + " andResume=" + andResume
7107 + " preserveWindow=" + preserveWindow);
Jeff Changd136e772019-11-05 20:33:52 +08007108 if (andResume) {
7109 EventLogTags.writeWmRelaunchResumeActivity(mUserId, System.identityHashCode(this),
7110 task.mTaskId, shortComponentName);
7111 } else {
7112 EventLogTags.writeWmRelaunchActivity(mUserId, System.identityHashCode(this),
7113 task.mTaskId, shortComponentName);
7114 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07007115
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007116 startFreezingScreenLocked(0);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007117
Andrii Kulian21713ac2016-10-12 22:05:05 -07007118 try {
7119 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
7120 "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
7121 + " callers=" + Debug.getCallers(6));
7122 forceNewConfig = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007123 startRelaunching();
Andrii Kulianb372da62018-01-18 10:46:24 -08007124 final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
7125 pendingNewIntents, configChangeFlags,
Andrii Kulianbeadacc2019-05-20 12:18:01 +00007126 new MergedConfiguration(mAtmService.getGlobalConfiguration(),
Andrii Kulianb372da62018-01-18 10:46:24 -08007127 getMergedOverrideConfiguration()),
7128 preserveWindow);
7129 final ActivityLifecycleItem lifecycleItem;
7130 if (andResume) {
lumark588a3e82018-07-20 18:53:54 +08007131 lifecycleItem = ResumeActivityItem.obtain(
Wale Ogunwale3a256e62018-12-06 14:41:18 -08007132 getDisplay().mDisplayContent.isNextTransitionForward());
Andrii Kulianb372da62018-01-18 10:46:24 -08007133 } else {
Bryce Lee1d0d5142018-04-12 10:35:07 -07007134 lifecycleItem = PauseActivityItem.obtain();
Andrii Kulianb372da62018-01-18 10:46:24 -08007135 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007136 final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
Andrii Kulianb372da62018-01-18 10:46:24 -08007137 transaction.addCallback(callbackItem);
7138 transaction.setLifecycleStateRequest(lifecycleItem);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007139 mAtmService.getLifecycleManager().scheduleTransaction(transaction);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007140 // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
Andrii Kulianb372da62018-01-18 10:46:24 -08007141 // request resume if this activity is currently resumed, which implies we aren't
Andrii Kulian21713ac2016-10-12 22:05:05 -07007142 // sleeping.
7143 } catch (RemoteException e) {
7144 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
7145 }
7146
7147 if (andResume) {
7148 if (DEBUG_STATES) {
7149 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
7150 }
7151 results = null;
7152 newIntents = null;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007153 mAtmService.getAppWarningsLocked().onResumeActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007154 } else {
Wale Ogunwale196db712019-12-27 15:35:39 +00007155 removePauseTimeout();
Bryce Lee7ace3952018-02-16 14:34:32 -08007156 setState(PAUSED, "relaunchActivityLocked");
Andrii Kulian21713ac2016-10-12 22:05:05 -07007157 }
7158
7159 configChangeFlags = 0;
7160 deferRelaunchUntilPaused = false;
7161 preserveWindowOnDeferredRelaunch = false;
7162 }
7163
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007164 /**
7165 * Request the process of the activity to restart with its saved state (from
7166 * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
7167 * the override configuration. Note if the activity is in background, the process will be killed
7168 * directly with keeping its record.
7169 */
7170 void restartProcessIfVisible() {
7171 Slog.i(TAG, "Request to restart process of " + this);
7172
Riddle Hsuaec55442019-03-12 17:25:35 +08007173 // Reset the existing override configuration so it can be updated according to the latest
7174 // configuration.
Evan Rosky72f084d2019-09-11 17:05:16 -07007175 clearSizeCompatMode();
Issei Suzuki1669ea42019-11-06 14:20:59 +01007176 if (mVisibleRequested) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007177 // Configuration will be ensured when becoming visible, so if it is already visible,
7178 // then the manual update is needed.
Evan Rosky72f084d2019-09-11 17:05:16 -07007179 updateSizeCompatMode();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007180 }
7181
7182 if (!attachedToProcess()) {
7183 return;
7184 }
7185
7186 // The restarting state avoids removing this record when process is died.
7187 setState(RESTARTING_PROCESS, "restartActivityProcess");
7188
Issei Suzuki1669ea42019-11-06 14:20:59 +01007189 if (!mVisibleRequested || mHaveState) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007190 // Kill its process immediately because the activity should be in background.
7191 // The activity state will be update to {@link #DESTROYED} in
Andrii Kulian79d67982019-08-19 11:56:16 -07007192 // {@link ActivityStack#cleanUp} when handling process died.
Riddle Hsuaec55442019-03-12 17:25:35 +08007193 mAtmService.mH.post(() -> {
7194 final WindowProcessController wpc;
7195 synchronized (mAtmService.mGlobalLock) {
7196 if (!hasProcess()
7197 || app.getReportedProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
7198 return;
7199 }
7200 wpc = app;
7201 }
7202 mAtmService.mAmInternal.killProcess(wpc.mName, wpc.mUid, "resetConfig");
7203 });
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007204 return;
7205 }
7206
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007207 if (getParent() != null) {
7208 startFreezingScreen();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007209 }
7210 // The process will be killed until the activity reports stopped with saved state (see
7211 // {@link ActivityTaskManagerService.activityStopped}).
7212 try {
7213 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
7214 StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */));
7215 } catch (RemoteException e) {
7216 Slog.w(TAG, "Exception thrown during restart " + this, e);
7217 }
7218 mStackSupervisor.scheduleRestartTimeout(this);
7219 }
7220
Riddle Hsu32dbdca2019-05-17 23:10:16 -06007221 boolean isProcessRunning() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007222 WindowProcessController proc = app;
Jorim Jaggi02886a82016-12-06 09:10:06 -08007223 if (proc == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007224 proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
Jorim Jaggi02886a82016-12-06 09:10:06 -08007225 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007226 return proc != null && proc.hasThread();
Jorim Jaggi02886a82016-12-06 09:10:06 -08007227 }
7228
Jorim Jaggibae01b12017-04-11 16:29:10 -07007229 /**
7230 * @return Whether a task snapshot starting window may be shown.
7231 */
7232 private boolean allowTaskSnapshot() {
7233 if (newIntents == null) {
7234 return true;
7235 }
7236
Louis Chang746c2242019-10-08 16:30:44 +08007237 // Restrict task snapshot starting window to launcher start, or is same as the last
7238 // delivered intent, or there is no intent at all (eg. task being brought to front). If
7239 // the intent is something else, likely the app is going to show some specific page or
7240 // view, instead of what's left last time.
Jorim Jaggibae01b12017-04-11 16:29:10 -07007241 for (int i = newIntents.size() - 1; i >= 0; i--) {
7242 final Intent intent = newIntents.get(i);
Louis Chang746c2242019-10-08 16:30:44 +08007243 if (intent == null || ActivityRecord.isMainIntent(intent)) {
7244 continue;
7245 }
7246
7247 final boolean sameIntent = mLastNewIntent != null ? mLastNewIntent.filterEquals(intent)
7248 : this.intent.filterEquals(intent);
7249 if (!sameIntent || intent.getExtras() != null) {
Jorim Jaggibae01b12017-04-11 16:29:10 -07007250 return false;
7251 }
7252 }
7253 return true;
7254 }
7255
Bryce Leeb7c9b802017-05-02 14:20:24 -07007256 /**
7257 * Returns {@code true} if the associated activity has the no history flag set on it.
7258 * {@code false} otherwise.
7259 */
7260 boolean isNoHistory() {
7261 return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
7262 || (info.flags & FLAG_NO_HISTORY) != 0;
7263 }
7264
Craig Mautner21d24a22014-04-23 11:45:37 -07007265 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
7266 out.attribute(null, ATTR_ID, String.valueOf(createTime));
7267 out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
7268 if (launchedFromPackage != null) {
7269 out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
7270 }
7271 if (resolvedType != null) {
7272 out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
7273 }
7274 out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007275 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
Winson Chung2cb86c72014-06-25 12:03:30 -07007276
Craig Mautner21d24a22014-04-23 11:45:37 -07007277 if (taskDescription != null) {
Craig Mautner648f69b2014-09-18 14:16:26 -07007278 taskDescription.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007279 }
7280
7281 out.startTag(null, TAG_INTENT);
7282 intent.saveToXml(out);
7283 out.endTag(null, TAG_INTENT);
7284
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007285 if (isPersistable() && mPersistentState != null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007286 out.startTag(null, TAG_PERSISTABLEBUNDLE);
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007287 mPersistentState.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007288 out.endTag(null, TAG_PERSISTABLEBUNDLE);
7289 }
7290 }
7291
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07007292 static ActivityRecord restoreFromXml(XmlPullParser in,
7293 ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
Craig Mautner21d24a22014-04-23 11:45:37 -07007294 Intent intent = null;
7295 PersistableBundle persistentState = null;
7296 int launchedFromUid = 0;
7297 String launchedFromPackage = null;
7298 String resolvedType = null;
7299 boolean componentSpecified = false;
7300 int userId = 0;
Craig Mautner21d24a22014-04-23 11:45:37 -07007301 long createTime = -1;
7302 final int outerDepth = in.getDepth();
Winson Chung2cb86c72014-06-25 12:03:30 -07007303 TaskDescription taskDescription = new TaskDescription();
Craig Mautner21d24a22014-04-23 11:45:37 -07007304
7305 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
7306 final String attrName = in.getAttributeName(attrNdx);
7307 final String attrValue = in.getAttributeValue(attrNdx);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007308 if (DEBUG) Slog.d(TaskPersister.TAG,
Wale Ogunwale18795a22014-12-03 11:38:33 -08007309 "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007310 if (ATTR_ID.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01007311 createTime = Long.parseLong(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007312 } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007313 launchedFromUid = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007314 } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
7315 launchedFromPackage = attrValue;
7316 } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
7317 resolvedType = attrValue;
7318 } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
Tobias Thiererb0800dc2016-04-21 17:51:41 +01007319 componentSpecified = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007320 } else if (ATTR_USERID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007321 userId = Integer.parseInt(attrValue);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007322 } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
Craig Mautner648f69b2014-09-18 14:16:26 -07007323 taskDescription.restoreFromXml(attrName, attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007324 } else {
7325 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
7326 }
7327 }
7328
7329 int event;
Ruben Brunkf53497c2017-03-27 20:26:17 -07007330 while (((event = in.next()) != END_DOCUMENT) &&
7331 (event != END_TAG || in.getDepth() >= outerDepth)) {
7332 if (event == START_TAG) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007333 final String name = in.getName();
Ruben Brunkf53497c2017-03-27 20:26:17 -07007334 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007335 Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
Craig Mautner21d24a22014-04-23 11:45:37 -07007336 if (TAG_INTENT.equals(name)) {
7337 intent = Intent.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007338 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007339 Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007340 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
7341 persistentState = PersistableBundle.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007342 if (DEBUG) Slog.d(TaskPersister.TAG,
Craig Mautner21d24a22014-04-23 11:45:37 -07007343 "ActivityRecord: persistentState=" + persistentState);
7344 } else {
7345 Slog.w(TAG, "restoreActivity: unexpected name=" + name);
7346 XmlUtils.skipCurrentTag(in);
7347 }
7348 }
7349 }
7350
7351 if (intent == null) {
Craig Mautnere0129b32014-05-25 16:41:09 -07007352 throw new XmlPullParserException("restoreActivity error intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007353 }
7354
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007355 final ActivityTaskManagerService service = stackSupervisor.mService;
Craig Mautner21d24a22014-04-23 11:45:37 -07007356 final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
Patrick Baumann78380272018-04-04 10:41:01 -07007357 userId, Binder.getCallingUid());
Craig Mautnere0129b32014-05-25 16:41:09 -07007358 if (aInfo == null) {
Craig Mautner77b04262014-06-27 15:22:12 -07007359 throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
7360 " resolvedType=" + resolvedType);
Craig Mautnere0129b32014-05-25 16:41:09 -07007361 }
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007362 final ActivityRecord r = new ActivityRecord(service, null /* caller */,
Andrii Kulianfb1bf692017-01-17 11:17:34 -08007363 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
Wale Ogunwalef6733932018-06-27 05:14:34 -07007364 aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
Andrii Kulianfb1bf692017-01-17 11:17:34 -08007365 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07007366 stackSupervisor, null /* options */, null /* sourceRecord */);
Craig Mautner21d24a22014-04-23 11:45:37 -07007367
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007368 r.mPersistentState = persistentState;
Winson Chung2cb86c72014-06-25 12:03:30 -07007369 r.taskDescription = taskDescription;
Craig Mautner21d24a22014-04-23 11:45:37 -07007370 r.createTime = createTime;
7371
7372 return r;
7373 }
7374
Zak Cohen90e7116742017-01-29 12:59:23 -08007375 private static boolean isInVrUiMode(Configuration config) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07007376 return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
Zak Cohen90e7116742017-01-29 12:59:23 -08007377 }
7378
David Stevens82ea6cb2017-03-03 16:18:50 -08007379 int getUid() {
7380 return info.applicationInfo.uid;
7381 }
7382
Wale Ogunwalea38654f2019-11-17 20:37:15 -08007383 boolean isUid(int uid) {
7384 return info.applicationInfo.uid == uid;
7385 }
7386
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007387 int getPid() {
7388 return app != null ? app.getPid() : 0;
chaviw59b98852017-06-13 12:05:44 -07007389 }
7390
7391 /**
7392 * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
Garfield Tane8d84ab2019-10-11 09:49:40 -07007393 * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007394 * should be visible depending on Keyguard state
chaviw59b98852017-06-13 12:05:44 -07007395 *
7396 * @return true if the screen can be turned on, false otherwise.
7397 */
7398 boolean canTurnScreenOn() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007399 if (!getTurnScreenOnFlag()) {
7400 return false;
7401 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007402 final ActivityStack stack = getActivityStack();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007403 return stack != null &&
chaviw59b98852017-06-13 12:05:44 -07007404 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
7405 }
7406
Garfield Tane8d84ab2019-10-11 09:49:40 -07007407 void setTurnScreenOn(boolean turnScreenOn) {
7408 mTurnScreenOn = turnScreenOn;
7409 }
7410
7411 boolean getTurnScreenOnFlag() {
7412 return mTurnScreenOn;
7413 }
7414
Louis Chang77ce34d2019-01-03 15:45:12 +08007415 /**
7416 * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
7417 * process are allowed to be resumed.
7418 *
7419 * @return true if this activity can be resumed.
7420 */
7421 boolean canResumeByCompat() {
7422 return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
7423 }
7424
chaviw59b98852017-06-13 12:05:44 -07007425 boolean isTopRunningActivity() {
Louis Chang149d5c82019-12-30 09:47:39 +08007426 return mRootWindowContainer.topRunningActivity() == this;
chaviw59b98852017-06-13 12:05:44 -07007427 }
7428
Andrii Kulian52d255c2018-07-13 11:32:19 -07007429 /**
7430 * @return {@code true} if this is the resumed activity on its current display, {@code false}
7431 * otherwise.
7432 */
7433 boolean isResumedActivityOnDisplay() {
Louis Chang677921f2019-12-06 16:44:24 +08007434 final DisplayContent display = getDisplay();
Andrii Kulian52d255c2018-07-13 11:32:19 -07007435 return display != null && this == display.getResumedActivity();
7436 }
7437
Andrii Kulian39f27442019-06-26 19:09:19 -07007438
7439 /**
7440 * Check if this is the root of the task - first activity that is not finishing, starting from
7441 * the bottom of the task. If all activities are finishing - then this method will return
7442 * {@code true} if the activity is at the bottom.
7443 *
7444 * NOTE: This is different from 'effective root' - an activity that defines the task identity.
7445 */
7446 boolean isRootOfTask() {
7447 if (task == null) {
7448 return false;
7449 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08007450 final ActivityRecord rootActivity = task.getRootActivity(true);
7451 return this == rootActivity;
Andrii Kulian39f27442019-06-26 19:09:19 -07007452 }
7453
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08007454 void setTaskOverlay(boolean taskOverlay) {
7455 mTaskOverlay = taskOverlay;
7456 setAlwaysOnTop(mTaskOverlay);
7457 }
7458
7459 boolean isTaskOverlay() {
7460 return mTaskOverlay;
7461 }
7462
Craig Mautnerf81b90872013-02-26 13:02:43 -08007463 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007465 if (stringName != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07007466 return stringName + " t" + (task == null ? INVALID_TASK_ID : task.mTaskId) +
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007467 (finishing ? " f}" : "") + (mIsExiting ? " mIsExiting=" : "") + "}";
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007468 }
7469 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn30d71892010-12-11 10:37:55 -08007470 sb.append("ActivityRecord{");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007471 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornb12e1352012-09-26 11:39:20 -07007472 sb.append(" u");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007473 sb.append(mUserId);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007474 sb.append(' ');
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007475 sb.append(intent.getComponent().flattenToShortString());
Craig Mautnerf81b90872013-02-26 13:02:43 -08007476 stringName = sb.toString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007477 return stringName;
Steven Timotius4346f0a2017-09-12 11:07:21 -07007478 }
7479
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007480 /**
7481 * Write all fields to an {@code ActivityRecordProto}. This assumes the
7482 * {@code ActivityRecordProto} is the outer-most proto data.
7483 */
Jeffrey Huangcb782852019-12-05 11:28:11 -08007484 void dumpDebug(ProtoOutputStream proto) {
7485 dumpDebug(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
Steven Timotius4346f0a2017-09-12 11:07:21 -07007486 writeIdentifierToProto(proto, IDENTIFIER);
Bryce Lee7ace3952018-02-16 14:34:32 -08007487 proto.write(STATE, mState.toString());
Issei Suzukif2f6c912019-11-08 11:24:18 +01007488 proto.write(VISIBLE_REQUESTED, mVisibleRequested);
Andrii Kulian39f27442019-06-26 19:09:19 -07007489 proto.write(FRONT_OF_TASK, isRootOfTask());
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007490 if (hasProcess()) {
7491 proto.write(PROC_ID, app.getPid());
Steven Timotius4346f0a2017-09-12 11:07:21 -07007492 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007493 proto.write(TRANSLUCENT, !occludesParent());
Issei Suzukif2f6c912019-11-08 11:24:18 +01007494 proto.write(VISIBLE, mVisible);
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007495 }
7496
Jeffrey Huangcb782852019-12-05 11:28:11 -08007497 public void dumpDebug(ProtoOutputStream proto, long fieldId) {
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007498 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08007499 dumpDebug(proto);
Steven Timotius4346f0a2017-09-12 11:07:21 -07007500 proto.end(token);
7501 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007502
7503 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -07007504 * Copied from old AppWindowToken.
7505 */
7506 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08007507 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Garfield Tane8d84ab2019-10-11 09:49:40 -07007508 @WindowTraceLogLevel int logLevel) {
7509 // Critical log level logs only visible elements to mitigate performance overheard
7510 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
7511 return;
7512 }
7513
7514 final long token = proto.start(fieldId);
7515 writeNameToProto(proto, NAME);
Jeffrey Huangcb782852019-12-05 11:28:11 -08007516 super.dumpDebug(proto, WINDOW_TOKEN, logLevel);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007517 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
7518 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
lumark9bca6b42019-10-17 18:35:22 +08007519 proto.write(IS_ANIMATING, isAnimating());
Garfield Tane8d84ab2019-10-11 09:49:40 -07007520 if (mThumbnail != null){
Jeffrey Huangcb782852019-12-05 11:28:11 -08007521 mThumbnail.dumpDebug(proto, THUMBNAIL);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007522 }
7523 proto.write(FILLS_PARENT, mOccludesParent);
7524 proto.write(APP_STOPPED, mAppStopped);
Issei Suzukif2f6c912019-11-08 11:24:18 +01007525 proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED, mVisibleRequested);
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01007526 proto.write(CLIENT_VISIBLE, mClientVisible);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007527 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
7528 proto.write(REPORTED_DRAWN, reportedDrawn);
7529 proto.write(REPORTED_VISIBLE, reportedVisible);
7530 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
7531 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
7532 proto.write(ALL_DRAWN, allDrawn);
7533 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007534 if (startingWindow != null) {
7535 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
7536 }
7537 proto.write(STARTING_DISPLAYED, startingDisplayed);
7538 proto.write(STARTING_MOVED, startingMoved);
Issei Suzukif2f6c912019-11-08 11:24:18 +01007539 proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW,
7540 mVisibleSetFromTransferredStartingWindow);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007541 for (Rect bounds : mFrozenBounds) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08007542 bounds.dumpDebug(proto, FROZEN_BOUNDS);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007543 }
Issei Suzukif2f6c912019-11-08 11:24:18 +01007544 proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE, mVisible);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007545 proto.end(token);
7546 }
7547
7548 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
7549 if (appToken != null) {
7550 proto.write(fieldId, appToken.getName());
7551 }
7552 }
7553
7554 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
7555 final long token = proto.start(fieldId);
7556 proto.write(HASH_CODE, System.identityHashCode(this));
7557 proto.write(USER_ID, mUserId);
7558 proto.write(TITLE, intent.getComponent().flattenToShortString());
7559 proto.end(token);
7560 }
7561
7562 /**
Riddle Hsu61987bc2019-04-03 13:08:47 +08007563 * The precomputed insets of the display in each rotation. This is used to make the size
7564 * compatibility mode activity compute the configuration without relying on its current display.
7565 */
7566 static class CompatDisplayInsets {
Evan Rosky72f084d2019-09-11 17:05:16 -07007567 private final int mDisplayWidth;
7568 private final int mDisplayHeight;
7569 private final int mWidth;
7570 private final int mHeight;
Riddle Hsu61987bc2019-04-03 13:08:47 +08007571
Riddle Hsu74826262019-04-17 14:57:42 +08007572 /**
7573 * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
7574 * is used to compute the appBounds.
7575 */
Riddle Hsu61987bc2019-04-03 13:08:47 +08007576 final Rect[] mNonDecorInsets = new Rect[4];
7577 /**
7578 * The stableInsets for each rotation. Includes the status bar inset and the
7579 * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
7580 * {@link Configuration#screenHeightDp}.
7581 */
7582 final Rect[] mStableInsets = new Rect[4];
7583
Evan Rosky72f084d2019-09-11 17:05:16 -07007584 /**
Louis Changcdec0802019-11-11 11:45:07 +08007585 * Sets bounds to {@link Task} bounds. For apps in freeform, the task bounds are the
Evan Rosky72f084d2019-09-11 17:05:16 -07007586 * parent bounds from the app's perspective. No insets because within a window.
7587 */
7588 CompatDisplayInsets(DisplayContent display, Rect activityBounds, boolean isFloating) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08007589 mDisplayWidth = display.mBaseDisplayWidth;
7590 mDisplayHeight = display.mBaseDisplayHeight;
Evan Rosky72f084d2019-09-11 17:05:16 -07007591 mWidth = activityBounds.width();
7592 mHeight = activityBounds.height();
7593 if (isFloating) {
7594 Rect emptyRect = new Rect();
7595 for (int rotation = 0; rotation < 4; rotation++) {
7596 mNonDecorInsets[rotation] = emptyRect;
7597 mStableInsets[rotation] = emptyRect;
7598 }
7599 return;
7600 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007601 final DisplayPolicy policy = display.getDisplayPolicy();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007602 for (int rotation = 0; rotation < 4; rotation++) {
7603 mNonDecorInsets[rotation] = new Rect();
7604 mStableInsets[rotation] = new Rect();
7605 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7606 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
7607 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
Riddle Hsu74826262019-04-17 14:57:42 +08007608 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
7609 .getDisplayCutout();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007610 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
7611 mStableInsets[rotation].set(mNonDecorInsets[rotation]);
7612 policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
7613 }
7614 }
7615
Riddle Hsu74826262019-04-17 14:57:42 +08007616 void getDisplayBoundsByRotation(Rect outBounds, int rotation) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08007617 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7618 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
7619 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
7620 outBounds.set(0, 0, dw, dh);
7621 }
Riddle Hsu74826262019-04-17 14:57:42 +08007622
Evan Rosky72f084d2019-09-11 17:05:16 -07007623 void getFrameByOrientation(Rect outBounds, int orientation) {
7624 final int longSide = Math.max(mWidth, mHeight);
7625 final int shortSide = Math.min(mWidth, mHeight);
Riddle Hsu74826262019-04-17 14:57:42 +08007626 final boolean isLandscape = orientation == ORIENTATION_LANDSCAPE;
7627 outBounds.set(0, 0, isLandscape ? longSide : shortSide,
7628 isLandscape ? shortSide : longSide);
7629 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007630 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07007631
7632 private static class AppSaturationInfo {
7633 float[] mMatrix = new float[9];
7634 float[] mTranslation = new float[3];
7635
7636 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
7637 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
7638 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
7639 }
7640 }
lumark19a5d2e2019-10-11 16:19:30 +08007641
7642 @Override
7643 RemoteAnimationTarget createRemoteAnimationTarget(
7644 RemoteAnimationController.RemoteAnimationRecord record) {
lumark19a5d2e2019-10-11 16:19:30 +08007645 final WindowState mainWindow = findMainWindow();
7646 if (task == null || mainWindow == null) {
7647 return null;
7648 }
7649 final Rect insets = new Rect();
7650 mainWindow.getContentInsets(insets);
7651 InsetUtils.addInsets(insets, getLetterboxInsets());
7652 return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
7653 record.mAdapter.mCapturedLeash, !task.fillsParent(),
7654 mainWindow.mWinAnimator.mLastClipRect, insets,
7655 getPrefixOrderIndex(), record.mAdapter.mPosition,
7656 record.mAdapter.mStackBounds, task.getWindowConfiguration(),
7657 false /*isNotInRecents*/,
7658 record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
7659 record.mStartBounds);
7660 }
7661
7662 @Override
7663 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
7664 Rect outSurfaceInsets) {
7665 final WindowState win = findMainWindow();
7666 if (win == null) {
7667 return;
7668 }
7669 win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
7670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671}