blob: fcdb3b065ae6d10e14c322449f8bba6f26f2d24b [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;
124import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
125import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700126import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
127import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Hui Yu03d12402018-12-06 18:00:37 -0800128import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
Andrii Kulian79d67982019-08-19 11:56:16 -0700129import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700130import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800131import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
132import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
133import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800134import static com.android.server.wm.ActivityStack.ActivityState.RESTARTING_PROCESS;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800135import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Louis Changeadb22f2019-06-19 12:09:23 +0800136import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800137import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
138import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800139import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -0700140import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
Andrii Kulian79d67982019-08-19 11:56:16 -0700141import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
142import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
Wale Ogunwale59507092018-10-29 09:00:30 -0700143import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700144import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700145import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700146import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
147import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700148import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
149import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
150import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
Jorim Jaggi346702a2019-05-08 17:49:33 +0200151import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700152import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
Wale Ogunwale59507092018-10-29 09:00:30 -0700153import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
Andrii Kulian79d67982019-08-19 11:56:16 -0700154import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
155import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP;
Wale Ogunwale59507092018-10-29 09:00:30 -0700156import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700157import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700158import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700159import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
160import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700161import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
162import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
163import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700164import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
165import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
Wale Ogunwale59507092018-10-29 09:00:30 -0700166import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
167import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
168import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale59507092018-10-29 09:00:30 -0700169import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
170import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
Hui Yu03d12402018-12-06 18:00:37 -0800171import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
Louis Chang746c2242019-10-08 16:30:44 +0800172import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700173import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
174import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
Issei Suzukie63eac72019-11-14 15:59:15 +0100175import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700176import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
177import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
178import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
Issei Suzuki430a1112019-11-14 16:20:52 +0100179import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100180import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
lumark9bca6b42019-10-17 18:35:22 +0800181import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700182import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
183import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
184import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
185import static com.android.server.wm.AppWindowTokenProto.NAME;
186import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
187import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700188import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
189import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
190import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
191import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
192import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
193import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
194import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
195import static com.android.server.wm.IdentifierProto.HASH_CODE;
196import static com.android.server.wm.IdentifierProto.TITLE;
197import static com.android.server.wm.IdentifierProto.USER_ID;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200198import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700199import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
200import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
201import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200202import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
203import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800204import static com.android.server.wm.TaskPersister.DEBUG;
205import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
lumark9bca6b42019-10-17 18:35:22 +0800206import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
207import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
208import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700209import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
210import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
211import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800212import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700213import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
214import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700215import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
216import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700217import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700218
Ruben Brunkf53497c2017-03-27 20:26:17 -0700219import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
220import static org.xmlpull.v1.XmlPullParser.END_TAG;
221import static org.xmlpull.v1.XmlPullParser.START_TAG;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800222
Andrii Kulian057a6512019-07-15 16:15:51 -0700223import android.annotation.IntDef;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700224import android.annotation.NonNull;
Issei Suzuki74e1eb22018-12-20 17:42:52 +0100225import android.annotation.Nullable;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700226import android.annotation.Size;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700227import android.app.Activity;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700228import android.app.ActivityManager;
Craig Mautner21d24a22014-04-23 11:45:37 -0700229import android.app.ActivityManager.TaskDescription;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -0700230import android.app.ActivityOptions;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800231import android.app.PendingIntent;
Winson Chung709904f2017-04-25 11:00:48 -0700232import android.app.PictureInPictureParams;
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800233import android.app.ResultInfo;
Vishnu Nairbb9ab4b2018-12-13 10:29:46 -0800234import android.app.WaitResult.LaunchState;
Riddle Hsu16567132018-08-16 21:37:47 +0800235import android.app.servertransaction.ActivityConfigurationChangeItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800236import android.app.servertransaction.ActivityLifecycleItem;
237import android.app.servertransaction.ActivityRelaunchItem;
Andrii Kulian79d67982019-08-19 11:56:16 -0700238import android.app.servertransaction.ActivityResultItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800239import android.app.servertransaction.ClientTransaction;
240import android.app.servertransaction.ClientTransactionItem;
Andrii Kulian79d67982019-08-19 11:56:16 -0700241import android.app.servertransaction.DestroyActivityItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700242import android.app.servertransaction.MoveToDisplayItem;
243import android.app.servertransaction.MultiWindowModeChangeItem;
244import android.app.servertransaction.NewIntentItem;
Bryce Lee0bd8d422018-01-09 09:45:57 -0800245import android.app.servertransaction.PauseActivityItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700246import android.app.servertransaction.PipModeChangeItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800247import android.app.servertransaction.ResumeActivityItem;
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800248import android.app.servertransaction.StopActivityItem;
Andrii Kuliand70cdb92019-01-08 15:03:50 -0800249import android.app.servertransaction.TopResumedActivityChangeItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700250import android.app.servertransaction.WindowVisibilityItem;
Hui Yu03d12402018-12-06 18:00:37 -0800251import android.app.usage.UsageEvents.Event;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252import android.content.ComponentName;
253import android.content.Intent;
254import android.content.pm.ActivityInfo;
255import android.content.pm.ApplicationInfo;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -0700256import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257import android.content.res.Configuration;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700258import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259import android.graphics.Bitmap;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800260import android.graphics.GraphicBuffer;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700261import android.graphics.PixelFormat;
262import android.graphics.Point;
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700263import android.graphics.Rect;
Andrii Kulian79d67982019-08-19 11:56:16 -0700264import android.net.Uri;
Patrick Baumann78380272018-04-04 10:41:01 -0700265import android.os.Binder;
Bryce Lee39791592017-04-26 09:29:12 -0700266import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267import android.os.Bundle;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700268import android.os.Debug;
Dianne Hackbornbe707852011-11-11 14:32:10 -0800269import android.os.IBinder;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800270import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271import android.os.Process;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700272import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273import android.os.SystemClock;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700274import android.os.Trace;
275import android.os.UserHandle;
Bryce Lee8558ec72017-08-17 15:37:26 -0700276import android.os.storage.StorageManager;
Amith Yamasani0af6fa72016-01-17 15:36:19 -0800277import android.service.voice.IVoiceInteractionSession;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700278import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279import android.util.EventLog;
280import android.util.Log;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700281import android.util.MergedConfiguration;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700282import android.util.Slog;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700283import android.util.TimeUtils;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700284import android.util.proto.ProtoOutputStream;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800285import android.view.AppTransitionAnimationSpec;
Riddle Hsu61987bc2019-04-03 13:08:47 +0800286import android.view.DisplayCutout;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700287import android.view.DisplayInfo;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800288import android.view.IAppTransitionAnimationSpecsFuture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289import android.view.IApplicationToken;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700290import android.view.InputApplicationHandle;
291import android.view.RemoteAnimationAdapter;
292import android.view.RemoteAnimationDefinition;
lumark19a5d2e2019-10-11 16:19:30 +0800293import android.view.RemoteAnimationTarget;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700294import android.view.SurfaceControl;
295import android.view.SurfaceControl.Transaction;
296import android.view.WindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +0200297import android.view.WindowManager.LayoutParams;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700298import android.view.animation.Animation;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700299
lumark9bca6b42019-10-17 18:35:22 +0800300import com.android.internal.R;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800301import com.android.internal.annotations.VisibleForTesting;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800302import com.android.internal.app.ResolverActivity;
303import com.android.internal.content.ReferrerIntent;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700304import com.android.internal.util.ToBooleanFunction;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800305import com.android.internal.util.XmlUtils;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700306import com.android.server.AttributeCache;
307import com.android.server.LocalServices;
Wale Ogunwale59507092018-10-29 09:00:30 -0700308import com.android.server.am.AppTimeTracker;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700309import com.android.server.am.EventLogTags;
Wale Ogunwale59507092018-10-29 09:00:30 -0700310import 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;
Wale Ogunwale59507092018-10-29 09:00:30 -0700315import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
316import 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336
337/**
338 * An entry in the history stack, representing an activity.
339 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700340final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
Wale Ogunwale98875612018-10-12 07:53:02 -0700341 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
Andrii Kulian79d67982019-08-19 11:56:16 -0700342 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
343 private static final String TAG_APP = TAG + POSTFIX_APP;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700344 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700345 private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
346 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
347 private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
348 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700349 private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700350 private static final String TAG_STATES = TAG + POSTFIX_STATES;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700351 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700352 private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
353 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700354 private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800355
Craig Mautner21d24a22014-04-23 11:45:37 -0700356 private static final String ATTR_ID = "id";
357 private static final String TAG_INTENT = "intent";
358 private static final String ATTR_USERID = "user_id";
359 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
360 private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700361 private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
Craig Mautner21d24a22014-04-23 11:45:37 -0700362 private static final String ATTR_RESOLVEDTYPE = "resolved_type";
363 private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
Dianne Hackborn337abb32014-09-24 12:44:29 -0700364 static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
Craig Mautner21d24a22014-04-23 11:45:37 -0700365
Andrii Kulian79d67982019-08-19 11:56:16 -0700366 // How many activities have to be scheduled to stop to force a stop pass.
367 private static final int MAX_STOPPING_TO_FORCE = 3;
368
Garfield Tane8d84ab2019-10-11 09:49:40 -0700369 private static final int STARTING_WINDOW_TYPE_NONE = 0;
370 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
371 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
372
373 /**
374 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
375 */
376 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Vishnu Nair19479df2019-10-30 08:03:15 -0700377 static final int INVALID_PID = -1;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700378
379 final ActivityTaskManagerService mAtmService;
Andrii Kulianeceebbf2019-06-26 17:36:51 -0700380 final ActivityInfo info; // activity info provided by developer in AndroidManifest
Garfield Tane8d84ab2019-10-11 09:49:40 -0700381 // Non-null only for application tokens.
382 // TODO: rename to mActivityToken
383 final ActivityRecord.Token appToken;
384 // Which user is this running for?
385 final int mUserId;
386 // The package implementing intent's component
387 // TODO: rename to mPackageName
388 final String packageName;
389 // the intent component, or target of an alias.
390 final ComponentName mActivityComponent;
391 // Has a wallpaper window as a background.
392 // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
393 // mOccludesParent field.
394 final boolean hasWallpaper;
395 // Input application handle used by the input dispatcher.
396 final InputApplicationHandle mInputApplicationHandle;
397
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800398 final int launchedFromPid; // always the pid who started the activity.
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700399 final int launchedFromUid; // always the uid who started the activity.
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800400 final String launchedFromPackage; // always the package who started the activity.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 final Intent intent; // the original intent that generated us
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 final String shortComponentName; // the short component name of the intent
403 final String resolvedType; // as per original caller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 final String processName; // process where this component wants to run
405 final String taskAffinity; // as per ActivityInfo.taskAffinity
406 final boolean stateNotNeeded; // As per ActivityInfo.flags
Louis Changd58cb672018-12-24 17:45:16 +0800407 @VisibleForTesting
408 int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800409 private final boolean componentSpecified; // did caller specify an explicit component?
Dianne Hackbornfb81d092015-08-03 17:14:46 -0700410 final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?
Craig Mautner86d67a42013-05-14 10:34:38 -0700411
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800412 private CharSequence nonLocalizedLabel; // the label information from the package mgr.
413 private int labelRes; // the label information from the package mgr.
414 private int icon; // resource identifier of activity's icon.
415 private int logo; // resource identifier of activity's logo.
416 private int theme; // resource identifier of activity's theme.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800417 private int windowFlags; // custom window flags for preview window.
Louis Changcdec0802019-11-11 11:45:07 +0800418 private Task task; // the task this is in.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800419 private long createTime = System.currentTimeMillis();
Andrii Kulian86e70fc2019-02-12 11:04:10 +0000420 long lastVisibleTime; // last time this activity became visible
421 long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
422 long pauseTime; // last time we started pausing the activity
423 long launchTickTime; // base time for launch tick messages
424 long topResumedStateLossTime; // last time we reported top resumed state loss to an activity
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700425 // Last configuration reported to the activity in the client process.
426 private MergedConfiguration mLastReportedConfiguration;
Andrii Kulianb047b8b2017-02-08 18:38:26 -0800427 private int mLastReportedDisplayId;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200428 boolean mLastReportedMultiWindowMode;
429 boolean mLastReportedPictureInPictureMode;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -0700430 CompatibilityInfo compat;// last used compatibility mode
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700431 ActivityRecord resultTo; // who started this entry, so will get our reply
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 final String resultWho; // additional identifier for use by resultTo.
433 final int requestCode; // code given by requester (resultTo)
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800434 ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
Dianne Hackborn85d558c2014-11-04 10:31:54 -0800436 ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
Louis Chang746c2242019-10-08 16:30:44 +0800437 Intent mLastNewIntent; // the last new intent we delivered to client
Dianne Hackborn7a2195c2012-03-19 17:38:00 -0700438 ActivityOptions pendingOptions; // most recently given options
George Mount6ba042b2014-07-28 11:12:28 -0700439 ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
Dianne Hackbornb5a380d2015-05-20 18:18:46 -0700440 AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
Wale Ogunwalec4e63a42018-10-02 13:19:54 -0700441 ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
Dianne Hackborn7e269642010-08-25 19:50:20 -0700442 UriPermissionOwner uriPermissions; // current special URI access perms.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700443 WindowProcessController app; // if non-null, hosting application
Bryce Lee7ace3952018-02-16 14:34:32 -0800444 private ActivityState mState; // current state we are in
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700445 private Bundle mIcicle; // last saved activity state
446 private PersistableBundle mPersistentState; // last persistently saved activity state
447 private boolean mHaveState = true; // Indicates whether the last saved state of activity is
448 // preserved. This starts out 'true', since the initial state
449 // of an activity is that we have everything, and we should
450 // never consider it lacking in state to be removed if it
451 // dies. After an activity is launched it follows the value
452 // of #mIcicle.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 boolean launchFailed; // set if a launched failed, to abort on 2nd try
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 boolean stopped; // is activity pause finished?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700455 boolean delayedResume; // not yet resumed because of stopped app switches?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 boolean finishing; // activity in pending finish list?
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800457 boolean deferRelaunchUntilPaused; // relaunch of activity is being deferred until pause is
458 // completed
459 boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 int configChangeFlags; // which config values have changed
Wale Ogunwaleec950642017-04-25 07:44:21 -0700461 private boolean keysPaused; // has key dispatching been paused for it?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 int launchMode; // the launch mode activity attribute.
Charles He2bf28322017-10-12 22:24:49 +0100463 int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
Issei Suzuki430a1112019-11-14 16:20:52 +0100464 boolean visible; // does this activity's window need to be shown?
Jorim Jaggi241ae102016-11-02 21:57:33 -0700465 boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
466 // might hide this activity?
Issei Suzukie63eac72019-11-14 15:59:15 +0100467 // True if the hidden state of this token was forced to false due to a transferred starting
Garfield Tane8d84ab2019-10-11 09:49:40 -0700468 // window.
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100469 private boolean mHiddenSetFromTransferredStartingWindow;
470 // TODO: figureout how to consolidate with the same variable in ActivityRecord.
Wale Ogunwaleec950642017-04-25 07:44:21 -0700471 private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
472 // process that it is hidden.
Issei Suzukie63eac72019-11-14 15:59:15 +0100473 private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true
Garfield Tane8d84ab2019-10-11 09:49:40 -0700474 // and reporting to the client that it is hidden.
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800475 boolean sleeping; // have we told the activity to sleep?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 boolean nowVisible; // is this activity's window visible?
Vishnu Nair9ba31652018-11-13 14:34:05 -0800477 boolean mDrawn; // is this activity's window drawn?
Andrii Kuliana39ae3e2018-05-31 12:43:54 -0700478 boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 boolean idle; // has the activity gone idle?
480 boolean hasBeenLaunched;// has this activity ever been launched?
481 boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
Daniel Sandler69a48172010-06-23 16:29:36 -0400482 boolean immersive; // immersive mode (don't interrupt if possible)
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400483 boolean forceNewConfig; // force re-create with new config next time
Winson Chungf7e03e12017-08-22 11:32:16 -0700484 boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the
485 // activity can enter picture in picture while pausing (only when switching to another task)
Winson Chung709904f2017-04-25 11:00:48 -0700486 PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();
487 // The PiP params used when deferring the entering of picture-in-picture.
Dianne Hackborn07981492013-01-28 11:36:23 -0800488 int launchCount; // count of launches since last state
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800489 long lastLaunchTime; // time of last launch of this activity
Ruben Brunke24b9a62016-02-16 21:38:24 -0800490 ComponentName requestedVrComponent; // the requested component for handling VR mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200492 boolean inHistory; // are we in the history stack?
Craig Mautnerde4ef022013-04-07 19:01:33 -0700493 final ActivityStackSupervisor mStackSupervisor;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800494 final RootActivityContainer mRootActivityContainer;
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800495
496 static final int STARTING_WINDOW_NOT_SHOWN = 0;
497 static final int STARTING_WINDOW_SHOWN = 1;
498 static final int STARTING_WINDOW_REMOVED = 2;
499 int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
Wale Ogunwale3b232392016-05-13 15:37:13 -0700500 boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800501
Garfield Tan2746ab52018-07-25 12:33:01 -0700502 // Marking the reason why this activity is being relaunched. Mainly used to track that this
503 // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
504 // pre-NYC apps that don't have a sense of being resized.
505 int mRelaunchReason = RELAUNCH_REASON_NONE;
506
Craig Mautner21d24a22014-04-23 11:45:37 -0700507 TaskDescription taskDescription; // the recents information for this activity
Craig Mautner2fbd7542014-03-21 09:34:07 -0700508
Filip Gruszczynski23493322015-07-29 17:02:59 -0700509 // These configurations are collected from application's resources based on size-sensitive
510 // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
511 // and drawable-sw400dp will be added to both as 400.
512 private int[] mVerticalSizeConfigurations;
513 private int[] mHorizontalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -0700514 private int[] mSmallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -0700515
Riddle Hsu61987bc2019-04-03 13:08:47 +0800516 /**
517 * The precomputed display insets for resolving configuration. It will be non-null if
518 * {@link #shouldUseSizeCompatMode} returns {@code true}.
519 */
520 private CompatDisplayInsets mCompatDisplayInsets;
521
Amith Yamasani0af6fa72016-01-17 15:36:19 -0800522 boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session
523 IVoiceInteractionSession voiceSession; // Voice interaction session for this activity
524
Garfield Tane8d84ab2019-10-11 09:49:40 -0700525 boolean mVoiceInteraction;
526
527 private int mPendingRelaunchCount;
528
529 // True if we are current in the process of removing this app token from the display
530 private boolean mRemovingFromDisplay = false;
531
Garfield Tane8d84ab2019-10-11 09:49:40 -0700532 private RemoteAnimationDefinition mRemoteAnimationDefinition;
533
534 private AnimatingActivityRegistry mAnimatingActivityRegistry;
535
536 private Task mLastParent;
537
Issei Suzukie63eac72019-11-14 15:59:15 +0100538 // Have we told the window clients to hide themselves?
539 private boolean mClientHidden;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700540
541 boolean firstWindowDrawn;
542 // Last drawn state we reported to the app token.
543 private boolean reportedDrawn;
544 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
545 new WindowState.UpdateReportedVisibilityResults();
546
547 private boolean mUseTransferredAnimation;
548
549 /**
550 * @see #currentLaunchCanTurnScreenOn()
551 */
552 private boolean mCurrentLaunchCanTurnScreenOn = true;
553
554 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -0700555 * This leash is used to "freeze" the app surface in place after the state change, but before
556 * the animation is ready to start.
557 */
558 private SurfaceControl mTransitChangeLeash = null;
559
560 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
561 private boolean mLastSurfaceShowing = true;
562
563 private Letterbox mLetterbox;
564
565 /**
566 * The activity is opaque and fills the entire space of this task.
567 * @see WindowContainer#fillsParent()
568 */
569 private boolean mOccludesParent;
570
571 // The input dispatching timeout for this application token in nanoseconds.
572 long mInputDispatchingTimeoutNanos;
573
574 private boolean mShowWhenLocked;
575 private boolean mInheritShownWhenLocked;
576 private boolean mTurnScreenOn;
577
578 /** Have we been asked to have this token keep the screen frozen? */
579 private boolean mFreezingScreen;
580
581 // These are used for determining when all windows associated with
582 // an activity have been drawn, so they can be made visible together
583 // at the same time.
584 // initialize so that it doesn't match mTransactionSequence which is an int.
585 private long mLastTransactionSequence = Long.MIN_VALUE;
586 private int mNumInterestingWindows;
587 private int mNumDrawnWindows;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700588 boolean allDrawn;
589 private boolean mLastAllDrawn;
590
591 private boolean mLastContainsShowWhenLockedWindow;
592 private boolean mLastContainsDismissKeyguardWindow;
593
594 /**
595 * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
596 * to help AR know that the app is in the process of closing but hasn't yet started closing on
597 * the WM side.
598 */
599 private boolean mWillCloseOrEnterPip;
600
601 /**
602 * The scale to fit at least one side of the activity to its parent. If the activity uses
603 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
604 */
605 private float mSizeCompatScale = 1f;
606 /**
607 * The bounds in global coordinates for activity in size compatibility mode.
608 * @see ActivityRecord#hasSizeCompatBounds()
609 */
610 private Rect mSizeCompatBounds;
611
612 // activity is not displayed?
613 // TODO: rename to mNoDisplay
614 @VisibleForTesting
615 boolean noDisplay;
616 boolean mShowForAllUsers;
617 // TODO: Make this final
618 int mTargetSdk;
619
620 // Set to true when this app creates a surface while in the middle of an animation. In that
621 // case do not clear allDrawn until the animation completes.
622 boolean deferClearAllDrawn;
623
Issei Suzuki430a1112019-11-14 16:20:52 +0100624 // Is this window's surface needed? This is almost like hidden, except
625 // it will sometimes be true a little earlier: when the token has
Garfield Tane8d84ab2019-10-11 09:49:40 -0700626 // been shown, but is still waiting for its app transition to execute
627 // before making its windows shown.
Issei Suzuki430a1112019-11-14 16:20:52 +0100628 boolean hiddenRequested;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700629
630 // Last visibility state we reported to the app token.
631 boolean reportedVisible;
632
Garfield Tane8d84ab2019-10-11 09:49:40 -0700633 boolean mDisablePreviewScreenshots;
634
635 // Information about an application starting window if displayed.
636 // Note: these are de-referenced before the starting window animates away.
637 StartingData mStartingData;
638 WindowState startingWindow;
639 WindowManagerPolicy.StartingSurface startingSurface;
640 boolean startingDisplayed;
641 boolean startingMoved;
642
643 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
644 boolean mIsExiting;
645
Garfield Tane8d84ab2019-10-11 09:49:40 -0700646 boolean mEnteringAnimation;
647
648 boolean mAppStopped;
649 // A hint to override the window specified rotation animation, or -1 to use the window specified
650 // value. We use this so that we can select the right animation in the cases of starting
651 // windows, where the app hasn't had time to set a value on the window.
652 int mRotationAnimationHint = -1;
653
654 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
655 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
656
Garfield Tane8d84ab2019-10-11 09:49:40 -0700657 private AppSaturationInfo mLastAppSaturationInfo;
658
659 private final ColorDisplayService.ColorTransformController mColorTransformController =
660 (matrix, translation) -> mWmService.mH.post(() -> {
661 synchronized (mWmService.mGlobalLock) {
662 if (mLastAppSaturationInfo == null) {
663 mLastAppSaturationInfo = new AppSaturationInfo();
664 }
665
666 mLastAppSaturationInfo.setSaturation(matrix, translation);
667 updateColorTransform();
668 }
669 });
670
Andrii Kulian21713ac2016-10-12 22:05:05 -0700671 /**
Garfield Tan0443b372019-01-04 15:00:13 -0800672 * Current sequencing integer of the configuration, for skipping old activity configurations.
673 */
674 private int mConfigurationSeq;
675
676 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800677 * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}
Andrii Kulian21713ac2016-10-12 22:05:05 -0700678 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700679 private final Configuration mTmpConfig = new Configuration();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700680 private final Rect mTmpBounds = new Rect();
Andrii Kulian21713ac2016-10-12 22:05:05 -0700681
Sunny Goyald40c3452019-03-20 12:46:55 -0700682 // Token for targeting this activity for assist purposes.
683 final Binder assistToken = new Binder();
684
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800685 private static String startingWindowStateToString(int state) {
686 switch (state) {
687 case STARTING_WINDOW_NOT_SHOWN:
688 return "STARTING_WINDOW_NOT_SHOWN";
689 case STARTING_WINDOW_SHOWN:
690 return "STARTING_WINDOW_SHOWN";
691 case STARTING_WINDOW_REMOVED:
692 return "STARTING_WINDOW_REMOVED";
693 default:
694 return "unknown state=" + state;
695 }
696 }
697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698 void dump(PrintWriter pw, String prefix) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700699 }
700
701 /**
702 * Copied from old AppWindowToken.
703 */
704 @Override
705 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700706 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700707 pw.print(prefix); pw.print("packageName="); pw.print(packageName);
708 pw.print(" processName="); pw.println(processName);
709 pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
Craig Mautnere11f2b72013-04-01 12:37:17 -0700710 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800711 pw.print(" userId="); pw.println(mUserId);
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800712 pw.print(prefix); pw.print("app="); pw.println(app);
Hui Yu6d5c3b92019-10-22 15:35:53 -0700713 pw.print(prefix); pw.println(intent.toInsecureString());
Andrii Kulian39f27442019-06-26 19:09:19 -0700714 pw.print(prefix); pw.print("rootOfTask="); pw.print(isRootOfTask());
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700715 pw.print(" task="); pw.println(task);
716 pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800717 pw.print(prefix); pw.print("mActivityComponent=");
718 pw.println(mActivityComponent.flattenToShortString());
Andrii Kulianeceebbf2019-06-26 17:36:51 -0700719 if (info != null && info.applicationInfo != null) {
720 final ApplicationInfo appInfo = info.applicationInfo;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700721 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
722 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
723 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
724 }
725 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800726 if (appInfo.splitSourceDirs != null) {
727 pw.print(prefix); pw.print("splitDir=");
728 pw.println(Arrays.toString(appInfo.splitSourceDirs));
729 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800730 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700731 pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
732 pw.print(" componentSpecified="); pw.print(componentSpecified);
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700733 pw.print(" mActivityType="); pw.println(
734 activityTypeToString(getActivityType()));
Dianne Hackbornfb81d092015-08-03 17:14:46 -0700735 if (rootVoiceInteraction) {
736 pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
737 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800738 pw.print(prefix); pw.print("compat="); pw.print(compat);
739 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
740 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
741 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700742 pw.println(prefix + "mLastReportedConfigurations:");
743 mLastReportedConfiguration.dump(pw, prefix + " ");
744
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700745 pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
Evan Roskydfe3da72018-10-26 17:21:06 -0700746 if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
747 pw.println(prefix + "RequestedOverrideConfiguration="
748 + getRequestedOverrideConfiguration());
749 }
750 if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
751 pw.println(prefix + "ResolvedOverrideConfiguration="
752 + getResolvedOverrideConfiguration());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700753 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800754 if (!matchParentBounds()) {
755 pw.println(prefix + "bounds=" + getBounds());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700756 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700757 if (resultTo != null || resultWho != null) {
758 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
759 pw.print(" resultWho="); pw.print(resultWho);
760 pw.print(" resultCode="); pw.println(requestCode);
761 }
Craig Mautner29c58ca2014-10-14 16:17:06 -0700762 if (taskDescription != null) {
763 final String iconFilename = taskDescription.getIconFilename();
764 if (iconFilename != null || taskDescription.getLabel() != null ||
765 taskDescription.getPrimaryColor() != 0) {
766 pw.print(prefix); pw.print("taskDescription:");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700767 pw.print(" label=\""); pw.print(taskDescription.getLabel());
768 pw.print("\"");
Matthew Ng54bc9422017-10-02 17:16:28 -0700769 pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
770 ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
771 : "null");
772 pw.print(" iconResource="); pw.print(taskDescription.getIconResource());
773 pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200774 pw.print(" primaryColor=");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700775 pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700776 pw.print(prefix + " backgroundColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200777 pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700778 pw.print(prefix + " statusBarColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200779 pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700780 pw.print(prefix + " navigationBarColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200781 pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
Craig Mautner29c58ca2014-10-14 16:17:06 -0700782 }
Craig Mautner648f69b2014-09-18 14:16:26 -0700783 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700784 if (results != null) {
785 pw.print(prefix); pw.print("results="); pw.println(results);
786 }
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700787 if (pendingResults != null && pendingResults.size() > 0) {
788 pw.print(prefix); pw.println("Pending Results:");
789 for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
790 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
791 pw.print(prefix); pw.print(" - ");
792 if (pir == null) {
793 pw.println("null");
794 } else {
795 pw.println(pir);
796 pir.dump(pw, prefix + " ");
797 }
798 }
799 }
800 if (newIntents != null && newIntents.size() > 0) {
801 pw.print(prefix); pw.println("Pending New Intents:");
802 for (int i=0; i<newIntents.size(); i++) {
Craig Mautnerd2328952013-03-05 12:46:26 -0800803 Intent intent = newIntents.get(i);
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700804 pw.print(prefix); pw.print(" - ");
805 if (intent == null) {
806 pw.println("null");
807 } else {
Hui Yu6d5c3b92019-10-22 15:35:53 -0700808 pw.println(intent.toShortString(false, true, false, false));
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700809 }
810 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700811 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700812 if (pendingOptions != null) {
813 pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
814 }
Dianne Hackbornb5a380d2015-05-20 18:18:46 -0700815 if (appTimeTracker != null) {
816 appTimeTracker.dumpWithHeader(pw, prefix, false);
817 }
Dianne Hackborn7e269642010-08-25 19:50:20 -0700818 if (uriPermissions != null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700819 uriPermissions.dump(pw, prefix);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700820 }
821 pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
Dianne Hackborn07981492013-01-28 11:36:23 -0800822 pw.print(" launchCount="); pw.print(launchCount);
823 pw.print(" lastLaunchTime=");
824 if (lastLaunchTime == 0) pw.print("0");
825 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
826 pw.println();
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700827 pw.print(prefix); pw.print("mHaveState="); pw.print(mHaveState);
828 pw.print(" mIcicle="); pw.println(mIcicle);
Bryce Lee7ace3952018-02-16 14:34:32 -0800829 pw.print(prefix); pw.print("state="); pw.print(mState);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700830 pw.print(" stopped="); pw.print(stopped);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700831 pw.print(" delayedResume="); pw.print(delayedResume);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700832 pw.print(" finishing="); pw.println(finishing);
833 pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
834 pw.print(" inHistory="); pw.print(inHistory);
Issei Suzuki430a1112019-11-14 16:20:52 +0100835 pw.print(" visible="); pw.print(visible);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800836 pw.print(" sleeping="); pw.print(sleeping);
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800837 pw.print(" idle="); pw.print(idle);
838 pw.print(" mStartingWindowState=");
839 pw.println(startingWindowStateToString(mStartingWindowState));
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800840 pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
Dianne Hackbornff801ec2011-01-22 18:05:38 -0800841 pw.print(" noDisplay="); pw.print(noDisplay);
842 pw.print(" immersive="); pw.print(immersive);
843 pw.print(" launchMode="); pw.println(launchMode);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800844 pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400845 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700846 pw.print(prefix); pw.print("mActivityType=");
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700847 pw.println(activityTypeToString(getActivityType()));
Ruben Brunke24b9a62016-02-16 21:38:24 -0800848 if (requestedVrComponent != null) {
849 pw.print(prefix);
850 pw.print("requestedVrComponent=");
851 pw.println(requestedVrComponent);
852 }
Garfield Tane8d84ab2019-10-11 09:49:40 -0700853 super.dump(pw, prefix, dumpAll);
854 if (appToken != null) {
855 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
856 }
857 pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
858 pw.print(" mOrientation="); pw.println(mOrientation);
Issei Suzuki430a1112019-11-14 16:20:52 +0100859 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
Garfield Tane8d84ab2019-10-11 09:49:40 -0700860 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
861 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
862 if (paused) {
863 pw.print(prefix); pw.print("paused="); pw.println(paused);
864 }
865 if (mAppStopped) {
866 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
867 }
868 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
869 || allDrawn || mLastAllDrawn) {
870 pw.print(prefix); pw.print("mNumInterestingWindows=");
871 pw.print(mNumInterestingWindows);
872 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700873 pw.print(" allDrawn="); pw.print(allDrawn);
874 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
875 pw.println(")");
876 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -0800877 if (mStartingData != null || firstWindowDrawn || mIsExiting) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700878 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700879 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
880 pw.print(" mIsExiting="); pw.println(mIsExiting);
881 }
882 if (startingWindow != null || startingSurface != null
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100883 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700884 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
885 pw.print(" startingSurface="); pw.print(startingSurface);
886 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
887 pw.print(" startingMoved="); pw.print(startingMoved);
888 pw.println(" mHiddenSetFromTransferredStartingWindow="
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100889 + mHiddenSetFromTransferredStartingWindow);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700890 }
891 if (!mFrozenBounds.isEmpty()) {
892 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
893 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
894 }
895 if (mPendingRelaunchCount != 0) {
896 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
897 }
898 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
899 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
900 + mSizeCompatBounds);
901 }
902 if (mRemovingFromDisplay) {
903 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
904 }
Jorim Jaggi9b5e3312019-03-01 18:08:00 +0100905 if (lastVisibleTime != 0 || nowVisible) {
906 pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700907 pw.print(" lastVisibleTime=");
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700908 if (lastVisibleTime == 0) pw.print("0");
909 else TimeUtils.formatDuration(lastVisibleTime, now, pw);
910 pw.println();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700911 }
Wale Ogunwaleec950642017-04-25 07:44:21 -0700912 if (mDeferHidingClient) {
913 pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
914 }
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800915 if (deferRelaunchUntilPaused || configChangeFlags != 0) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700916 pw.print(prefix); pw.print("deferRelaunchUntilPaused=");
917 pw.print(deferRelaunchUntilPaused);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700918 pw.print(" configChangeFlags=");
919 pw.println(Integer.toHexString(configChangeFlags));
920 }
Wale Ogunwalec4e63a42018-10-02 13:19:54 -0700921 if (mServiceConnectionsHolder != null) {
922 pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700923 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -0800924 if (info != null) {
925 pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
Winson Chung609e1e92017-05-08 10:52:12 -0700926 pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode
927 + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700928 if (info.supportsPictureInPicture()) {
929 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
Winson Chungf7e03e12017-08-22 11:32:16 -0700930 pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
931 + supportsEnterPipOnTaskSwitch);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700932 }
933 if (info.maxAspectRatio != 0) {
934 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
935 }
Adrian Roos917791e2018-11-28 16:30:44 +0100936 if (info.minAspectRatio != 0) {
937 pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
938 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -0800939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 }
941
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700942 /** Update the saved state of an activity. */
943 void setSavedState(@Nullable Bundle savedState) {
944 mIcicle = savedState;
945 mHaveState = mIcicle != null;
946 }
947
948 /**
949 * Get the actual Bundle instance of the saved state.
950 * @see #hasSavedState() for checking if the record has saved state.
951 */
952 @Nullable Bundle getSavedState() {
953 return mIcicle;
954 }
955
956 /**
957 * Check if the activity has saved state.
958 * @return {@code true} if the client reported a non-empty saved state from last onStop(), or
959 * if this record was just created and the client is yet to be launched and resumed.
960 */
961 boolean hasSavedState() {
962 return mHaveState;
963 }
964
965 /** @return The actual PersistableBundle instance of the saved persistent state. */
966 @Nullable PersistableBundle getPersistentSavedState() {
967 return mPersistentState;
968 }
969
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -0700970 void updateApplicationInfo(ApplicationInfo aInfo) {
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -0700971 info.applicationInfo = aInfo;
972 }
973
Andrii Kulian21713ac2016-10-12 22:05:05 -0700974 private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -0700975 return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
976 }
977
Andrii Kulian21713ac2016-10-12 22:05:05 -0700978 private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -0700979 return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
980 }
981
Andrii Kulian21713ac2016-10-12 22:05:05 -0700982 private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -0700983 return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
984 }
985
Filip Gruszczynski23493322015-07-29 17:02:59 -0700986 /**
987 * The purpose of this method is to decide whether the activity needs to be relaunched upon
988 * changing its size. In most cases the activities don't need to be relaunched, if the resize
989 * is small, all the activity content has to do is relayout itself within new bounds. There are
990 * cases however, where the activity's content would be completely changed in the new size and
991 * the full relaunch is required.
992 *
993 * The activity will report to us vertical and horizontal thresholds after which a relaunch is
994 * required. These thresholds are collected from the application resource qualifiers. For
995 * example, if application has layout-w600dp resource directory, then it needs a relaunch when
996 * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
997 * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
998 * of the threshold.
999 */
1000 private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
1001 int secondDp) {
1002 if (thresholds == null) {
1003 return false;
1004 }
1005 for (int i = thresholds.length - 1; i >= 0; i--) {
1006 final int threshold = thresholds[i];
1007 if ((firstDp < threshold && secondDp >= threshold)
1008 || (firstDp >= threshold && secondDp < threshold)) {
1009 return true;
1010 }
1011 }
1012 return false;
1013 }
1014
Andrii Kulian21713ac2016-10-12 22:05:05 -07001015 void setSizeConfigurations(int[] horizontalSizeConfiguration,
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001016 int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001017 mHorizontalSizeConfigurations = horizontalSizeConfiguration;
1018 mVerticalSizeConfigurations = verticalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001019 mSmallestSizeConfigurations = smallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -07001020 }
1021
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001022 private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001023 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001024 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
1025 "Can't report activity moved to display - client not running, activityRecord="
1026 + this + ", displayId=" + displayId);
Wale Ogunwale22e25262016-02-01 10:32:02 -08001027 return;
1028 }
1029 try {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001030 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
1031 "Reporting activity moved to display" + ", activityRecord=" + this
1032 + ", displayId=" + displayId + ", config=" + config);
Chong Zhang6be533e2016-06-17 16:24:21 -07001033
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001034 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001035 MoveToDisplayItem.obtain(displayId, config));
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001036 } catch (RemoteException e) {
1037 // If process died, whatever.
1038 }
1039 }
1040
1041 private void scheduleConfigurationChanged(Configuration config) {
Wale Ogunwalef6733932018-06-27 05:14:34 -07001042 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001043 if (DEBUG_CONFIGURATION) Slog.w(TAG,
1044 "Can't report activity configuration update - client not running"
1045 + ", activityRecord=" + this);
1046 return;
1047 }
1048 try {
1049 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
1050 + config);
1051
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001052 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001053 ActivityConfigurationChangeItem.obtain(config));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001054 } catch (RemoteException e) {
1055 // If process died, whatever.
1056 }
1057 }
1058
Louis Chang3b21bdc2019-03-25 15:49:14 +08001059 boolean scheduleTopResumedActivityChanged(boolean onTop) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001060 if (!attachedToProcess()) {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001061 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001062 Slog.w(TAG, "Can't report activity position update - client not running"
1063 + ", activityRecord=" + this);
1064 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001065 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001066 }
1067 try {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001068 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001069 Slog.v(TAG, "Sending position change to " + this + ", onTop: " + onTop);
1070 }
1071
1072 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1073 TopResumedActivityChangeItem.obtain(onTop));
1074 } catch (RemoteException e) {
1075 // If process died, whatever.
Louis Chang3b21bdc2019-03-25 15:49:14 +08001076 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001077 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001078 return true;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001079 }
1080
Winson Chung5af42fc2017-03-24 17:11:33 -07001081 void updateMultiWindowMode() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001082 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001083 return;
1084 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001085
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001086 if (task.getStack().deferScheduleMultiWindowModeChanged()) {
1087 // Don't do anything if we are currently deferring multi-window mode change.
1088 return;
1089 }
1090
Winson Chung5af42fc2017-03-24 17:11:33 -07001091 // An activity is considered to be in multi-window mode if its task isn't fullscreen.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001092 final boolean inMultiWindowMode = inMultiWindowMode();
Winson Chung609e1e92017-05-08 10:52:12 -07001093 if (inMultiWindowMode != mLastReportedMultiWindowMode) {
1094 mLastReportedMultiWindowMode = inMultiWindowMode;
Winson Chung5af42fc2017-03-24 17:11:33 -07001095 scheduleMultiWindowModeChanged(getConfiguration());
1096 }
1097 }
1098
1099 private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001100 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001101 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001102 MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001103 } catch (Exception e) {
1104 // If process died, I don't care.
1105 }
1106 }
1107
Winson Chungab76bbc2017-08-14 13:33:51 -07001108 void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001109 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001110 return;
1111 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001112
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001113 final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
Winson Chungab76bbc2017-08-14 13:33:51 -07001114 if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001115 // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
Winson Chung059955f2018-08-08 16:10:20 -07001116 // update that here in order. Set the last reported MW state to the same as the PiP
1117 // state since we haven't yet actually resized the task (these callbacks need to
1118 // preceed the configuration change from the resiez.
1119 // TODO(110009072): Once we move these callbacks to the client, remove all logic related
1120 // to forcing the update of the picture-in-picture mode as a part of the PiP animation.
Winson Chung609e1e92017-05-08 10:52:12 -07001121 mLastReportedPictureInPictureMode = inPictureInPictureMode;
Winson Chung059955f2018-08-08 16:10:20 -07001122 mLastReportedMultiWindowMode = inPictureInPictureMode;
Evan Rosky1ac84462018-11-13 11:25:30 -08001123 final Configuration newConfig = new Configuration();
1124 if (targetStackBounds != null && !targetStackBounds.isEmpty()) {
Evan Rosky730f6e82018-12-03 17:40:11 -08001125 newConfig.setTo(task.getRequestedOverrideConfiguration());
1126 Rect outBounds = newConfig.windowConfiguration.getBounds();
1127 task.adjustForMinimalTaskDimensions(outBounds, outBounds);
1128 task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration());
Evan Rosky1ac84462018-11-13 11:25:30 -08001129 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001130 schedulePictureInPictureModeChanged(newConfig);
1131 scheduleMultiWindowModeChanged(newConfig);
1132 }
1133 }
1134
1135 private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001136 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001137 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001138 PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
Andrii Kulian446e8242017-10-26 15:17:29 -07001139 overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001140 } catch (Exception e) {
1141 // If process died, no one cares.
Filip Gruszczynskica664812015-12-04 12:43:36 -08001142 }
1143 }
1144
Louis Changcdec0802019-11-11 11:45:07 +08001145 Task getTask() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001146 return task;
1147 }
1148
Bryce Leeaf691c02017-03-20 14:20:22 -07001149 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001150 * Sets the Task on this activity for the purposes of re-use during launch where we will
1151 * re-use another activity instead of this one for the launch.
chaviw4ad54912018-05-30 11:05:44 -07001152 */
Louis Changcdec0802019-11-11 11:45:07 +08001153 void setTaskForReuse(Task task) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001154 this.task = task;
chaviw4ad54912018-05-30 11:05:44 -07001155 }
1156
Louis Changdc077272019-11-12 16:52:56 +08001157 ActivityStack getStack() {
Louis Changcdec0802019-11-11 11:45:07 +08001158 return task != null ? task.getTaskStack() : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001159 }
1160
1161 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001162 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +08001163 final Task oldTask = oldParent != null ? (Task) oldParent : null;
1164 final Task newTask = newParent != null ? (Task) newParent : null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001165 this.task = newTask;
1166
1167 super.onParentChanged(newParent, oldParent);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001168
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001169 if (oldParent == null && newParent != null) {
1170 // First time we are adding the activity to the system.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001171 mVoiceInteraction = newTask.voiceSession != null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001172 mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
1173 onDisplayChanged(task.getDisplayContent());
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001174 // TODO(b/36505427): Maybe this call should be moved inside
1175 // updateOverrideConfiguration()
1176 newTask.updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001177 // Make sure override configuration is up-to-date before using to create window
1178 // controller.
1179 updateSizeCompatMode();
1180 // When an activity is started directly into a split-screen fullscreen stack, we need to
1181 // update the initial multi-window modes so that the callbacks are scheduled correctly
1182 // when the user leaves that mode.
1183 mLastReportedMultiWindowMode = inMultiWindowMode();
1184 mLastReportedPictureInPictureMode = inPinnedWindowingMode();
1185 }
1186
Garfield Tane8d84ab2019-10-11 09:49:40 -07001187 // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
1188 // access visual elements like the {@link DisplayContent}. We must remove any associations
1189 // such as animations.
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001190 if (task == null) {
1191 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1192 // from this list so we do not participate in any future animations.
1193 if (getDisplayContent() != null) {
1194 getDisplayContent().mClosingApps.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001195 }
Wale Ogunwale8577a052019-10-26 23:22:34 -07001196 } else if (mLastParent != null && mLastParent.getTaskStack() != null) {
1197 task.getTaskStack().mExitingActivities.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001198 }
Louis Changdc077272019-11-12 16:52:56 +08001199 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001200
1201 // If we reparent, make sure to remove ourselves from the old animation registry.
1202 if (mAnimatingActivityRegistry != null) {
1203 mAnimatingActivityRegistry.notifyFinished(this);
1204 }
1205 mAnimatingActivityRegistry = stack != null
1206 ? stack.getAnimatingActivityRegistry()
1207 : null;
1208
1209 mLastParent = task;
1210
1211 updateColorTransform();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001212
1213 final ActivityStack oldStack = (oldTask != null) ? oldTask.getStack() : null;
1214 final ActivityStack newStack = (newTask != null) ? newTask.getStack() : null;
1215 // Inform old stack (if present) of activity removal and new stack (if set) of activity
1216 // addition.
1217 if (oldStack != newStack) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001218 if (oldStack != null) {
1219 oldStack.onActivityRemovedFromStack(this);
1220 }
1221 if (newStack != null) {
1222 newStack.onActivityAddedToStack(this);
1223 }
1224 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001225 }
1226
1227 private void updateColorTransform() {
1228 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
1229 getPendingTransaction().setColorTransform(mSurfaceControl,
1230 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
1231 mWmService.scheduleAnimationLocked();
1232 }
1233 }
1234
1235 @Override
1236 void onDisplayChanged(DisplayContent dc) {
1237 DisplayContent prevDc = mDisplayContent;
1238 super.onDisplayChanged(dc);
1239 if (prevDc == null || prevDc == mDisplayContent) {
1240 return;
1241 }
1242
1243 if (prevDc.mOpeningApps.remove(this)) {
1244 // Transfer opening transition to new display.
1245 mDisplayContent.mOpeningApps.add(this);
1246 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1247 mDisplayContent.executeAppTransition();
1248 }
1249
1250 if (prevDc.mChangingApps.remove(this)) {
1251 // This gets called *after* the ActivityRecord has been reparented to the new display.
1252 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1253 // so this token is now "frozen" while waiting for the animation to start on prevDc
1254 // (which will be cancelled since the window is no-longer a child). However, since this
1255 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1256 // so we need to cancel the change transition here.
1257 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1258 }
1259 prevDc.mClosingApps.remove(this);
1260
1261 if (prevDc.mFocusedApp == this) {
1262 prevDc.setFocusedApp(null);
Louis Changdc077272019-11-12 16:52:56 +08001263 final ActivityStack stack = dc.getTopStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001264 if (stack != null) {
1265 final Task task = stack.getTopChild();
1266 if (task != null && task.getTopChild() == this) {
1267 dc.setFocusedApp(this);
1268 }
1269 }
1270 }
1271
1272 if (mLetterbox != null) {
1273 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1274 }
1275 }
1276
1277 void layoutLetterbox(WindowState winHint) {
1278 final WindowState w = findMainWindow();
1279 if (w == null || winHint != null && w != winHint) {
1280 return;
1281 }
1282 final boolean surfaceReady = w.isDrawnLw() // Regular case
1283 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1284 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1285 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
1286 if (needsLetterbox) {
1287 if (mLetterbox == null) {
1288 mLetterbox = new Letterbox(() -> makeChildSurface(null),
1289 mWmService.mTransactionFactory);
1290 mLetterbox.attachInput(w);
1291 }
1292 getPosition(mTmpPoint);
1293 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1294 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1295 // is also applied to the task).
1296 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
Louis Changcdec0802019-11-11 11:45:07 +08001297 ? task.getDisplayedBounds() : getStack().getDisplayedBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001298 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
1299 } else if (mLetterbox != null) {
1300 mLetterbox.hide();
1301 }
1302 }
1303
1304 void updateLetterboxSurface(WindowState winHint) {
1305 final WindowState w = findMainWindow();
1306 if (w != winHint && winHint != null && w != null) {
1307 return;
1308 }
1309 layoutLetterbox(winHint);
1310 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1311 mLetterbox.applySurfaceChanges(getPendingTransaction());
1312 }
1313 }
1314
1315 Rect getLetterboxInsets() {
1316 if (mLetterbox != null) {
1317 return mLetterbox.getInsets();
1318 } else {
1319 return new Rect();
1320 }
1321 }
1322
1323 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
1324 void getLetterboxInnerBounds(Rect outBounds) {
1325 if (mLetterbox != null) {
1326 outBounds.set(mLetterbox.getInnerFrame());
1327 } else {
1328 outBounds.setEmpty();
1329 }
1330 }
1331
1332 /**
1333 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
1334 * the given {@code rect}.
1335 */
1336 boolean isLetterboxOverlappingWith(Rect rect) {
1337 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
1338 }
1339
Dianne Hackbornbe707852011-11-11 14:32:10 -08001340 static class Token extends IApplicationToken.Stub {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001341 private WeakReference<ActivityRecord> weakActivity;
Steven Timotiusaf03df62017-07-18 16:56:43 -07001342 private final String name;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001343 private final String tokenString;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001344
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001345 Token(Intent intent) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07001346 name = intent.getComponent().flattenToShortString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001347 tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
1348 }
1349
1350 private void attach(ActivityRecord activity) {
1351 if (weakActivity != null) {
1352 throw new IllegalStateException("Already attached..." + this);
1353 }
1354 weakActivity = new WeakReference<>(activity);
Wale Ogunwale7d701172015-03-11 15:36:30 -07001355 }
1356
Charles Chen69362cd2019-03-29 15:18:45 +08001357 private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001358 if (token == null) {
1359 return null;
1360 }
1361 ActivityRecord r = token.weakActivity.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001362 if (r == null || r.getActivityStack() == null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001363 return null;
1364 }
1365 return r;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001366 }
1367
Craig Mautnerde4ef022013-04-07 19:01:33 -07001368 @Override
Dianne Hackbornbe707852011-11-11 14:32:10 -08001369 public String toString() {
1370 StringBuilder sb = new StringBuilder(128);
1371 sb.append("Token{");
1372 sb.append(Integer.toHexString(System.identityHashCode(this)));
1373 sb.append(' ');
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001374 if (weakActivity != null) {
1375 sb.append(weakActivity.get());
1376 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001377 sb.append('}');
1378 return sb.toString();
1379 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07001380
1381 @Override
1382 public String getName() {
1383 return name;
1384 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001385 }
1386
Charles Chen69362cd2019-03-29 15:18:45 +08001387 static @Nullable ActivityRecord forTokenLocked(IBinder token) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001388 try {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001389 return Token.tokenToActivityRecordLocked((Token)token);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001390 } catch (ClassCastException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08001391 Slog.w(TAG, "Bad activity token: " + token, e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001392 return null;
1393 }
1394 }
1395
Riddle Hsuff9e8282019-04-24 23:55:11 +08001396 static boolean isResolverActivity(String className) {
1397 return ResolverActivity.class.getName().equals(className);
1398 }
1399
Louis Chang6a9be162019-07-15 10:41:32 +08001400 boolean isResolverOrDelegateActivity() {
1401 return isResolverActivity(mActivityComponent.getClassName()) || Objects.equals(
1402 mActivityComponent, mAtmService.mStackSupervisor.getSystemChooserActivity());
Craig Mautnerac6f8432013-07-17 13:24:59 -07001403 }
1404
Patrick Baumann31426b22018-05-21 13:46:40 -07001405 boolean isResolverOrChildActivity() {
1406 if (!"android".equals(packageName)) {
1407 return false;
1408 }
1409 try {
1410 return ResolverActivity.class.isAssignableFrom(
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001411 Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
Patrick Baumann31426b22018-05-21 13:46:40 -07001412 } catch (ClassNotFoundException e) {
1413 return false;
1414 }
1415 }
1416
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001417 ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
1418 int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent,
1419 String _resolvedType, ActivityInfo aInfo, Configuration _configuration,
1420 ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
1421 boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
1422 ActivityOptions options, ActivityRecord sourceRecord) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001423 super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
1424 null /* displayContent */, false /* ownerCanManageAppTokens */);
1425
1426 mAtmService = _service;
1427 appToken = (Token) token;
1428 info = aInfo;
1429 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1430 packageName = info.applicationInfo.packageName;
1431 mInputApplicationHandle = new InputApplicationHandle(appToken);
1432 intent = _intent;
1433
1434 // If the class name in the intent doesn't match that of the target, this is probably an
1435 // alias. We have to create a new ComponentName object to keep track of the real activity
1436 // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
1437 if (info.targetActivity == null
1438 || (info.targetActivity.equals(intent.getComponent().getClassName())
1439 && (info.launchMode == LAUNCH_MULTIPLE
1440 || info.launchMode == LAUNCH_SINGLE_TOP))) {
1441 mActivityComponent = intent.getComponent();
1442 } else {
1443 mActivityComponent =
1444 new ComponentName(info.packageName, info.targetActivity);
1445 }
1446
1447 mTargetSdk = info.applicationInfo.targetSdkVersion;
1448 mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
1449 setOrientation(info.screenOrientation);
1450 mRotationAnimationHint = info.rotationAnimation;
1451
1452 mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
1453 mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
1454 mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
1455
1456 int realTheme = info.getThemeResource();
1457 if (realTheme == Resources.ID_NULL) {
1458 realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
1459 ? android.R.style.Theme : android.R.style.Theme_Holo;
1460 }
1461
1462 final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
1463 realTheme, com.android.internal.R.styleable.Window, mUserId);
1464
1465 if (ent != null) {
1466 mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
1467 hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
1468 noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
1469 } else {
1470 hasWallpaper = false;
1471 noDisplay = false;
1472 }
1473
1474 if (options != null) {
1475 mLaunchTaskBehind = options.getLaunchTaskBehind();
1476
1477 final int rotationAnimation = options.getRotationAnimationHint();
1478 // Only override manifest supplied option if set.
1479 if (rotationAnimation >= 0) {
1480 mRotationAnimationHint = rotationAnimation;
1481 }
1482 }
1483
1484 // Application tokens start out hidden.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01001485 setHidden(true);
Issei Suzuki430a1112019-11-14 16:20:52 +01001486 hiddenRequested = true;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001487
1488 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
1489 ColorDisplayService.ColorDisplayServiceInternal.class);
1490 cds.attachColorTransformController(packageName, mUserId,
1491 new WeakReference<>(mColorTransformController));
1492
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001493 appToken.attach(this);
1494
Wale Ogunwaled32da472018-11-16 07:19:28 -08001495 mRootActivityContainer = _service.mRootActivityContainer;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001496 launchedFromPid = _launchedFromPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 launchedFromUid = _launchedFromUid;
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001498 launchedFromPackage = _launchedFromPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 shortComponentName = _intent.getComponent().flattenToShortString();
1500 resolvedType = _resolvedType;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001501 componentSpecified = _componentSpecified;
Dianne Hackbornfb81d092015-08-03 17:14:46 -07001502 rootVoiceInteraction = _rootVoiceInteraction;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07001503 mLastReportedConfiguration = new MergedConfiguration(_configuration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 resultTo = _resultTo;
1505 resultWho = _resultWho;
1506 requestCode = _reqCode;
Bryce Lee7ace3952018-02-16 14:34:32 -08001507 setState(INITIALIZING, "ActivityRecord ctor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 launchFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 stopped = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001510 delayedResume = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 finishing = false;
Wale Ogunwalef81c1d12016-01-12 12:20:18 -08001512 deferRelaunchUntilPaused = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 keysPaused = false;
1514 inHistory = false;
Issei Suzuki430a1112019-11-14 16:20:52 +01001515 visible = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 nowVisible = false;
Vishnu Nair9ba31652018-11-13 14:34:05 -08001517 mDrawn = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 idle = false;
1519 hasBeenLaunched = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001520 mStackSupervisor = supervisor;
Robert Carr0f5d7532016-10-17 16:39:17 -07001521
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001522 taskAffinity = aInfo.taskAffinity;
1523 stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001524 nonLocalizedLabel = aInfo.nonLocalizedLabel;
1525 labelRes = aInfo.labelRes;
1526 if (nonLocalizedLabel == null && labelRes == 0) {
1527 ApplicationInfo app = aInfo.applicationInfo;
1528 nonLocalizedLabel = app.nonLocalizedLabel;
1529 labelRes = app.labelRes;
1530 }
1531 icon = aInfo.getIconResource();
1532 logo = aInfo.getLogoResource();
1533 theme = aInfo.getThemeResource();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001534 if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
1535 windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
1536 }
1537 if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
1538 && (aInfo.applicationInfo.uid == SYSTEM_UID
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001539 || aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
1540 processName = _caller.mName;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001541 } else {
1542 processName = aInfo.processName;
1543 }
1544
1545 if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
1546 intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1547 }
1548
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001549 launchMode = aInfo.launchMode;
1550
Winson Chung83471632016-12-13 11:02:12 -08001551 setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001552
1553 immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
1554
1555 requestedVrComponent = (aInfo.requestedVrComponent == null) ?
1556 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
chaviw59b98852017-06-13 12:05:44 -07001557
Charles He2bf28322017-10-12 22:24:49 +01001558 lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
Andrii Kulianeceebbf2019-06-26 17:36:51 -07001559 if (info.applicationInfo.isPrivilegedApp()
1560 && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
Charles He2bf28322017-10-12 22:24:49 +01001561 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1562 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1563 }
1564
1565 if (options != null) {
1566 pendingOptions = options;
Charles He2bf28322017-10-12 22:24:49 +01001567 final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
1568 if (usageReport != null) {
1569 appTimeTracker = new AppTimeTracker(usageReport);
1570 }
1571 final boolean useLockTask = pendingOptions.getLockTaskMode();
1572 if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
1573 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
1574 }
Louis Changd58cb672018-12-24 17:45:16 +08001575 // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
1576 mHandoverLaunchDisplayId = options.getLaunchDisplayId();
Charles He2bf28322017-10-12 22:24:49 +01001577 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001578 }
1579
Garfield Tane8d84ab2019-10-11 09:49:40 -07001580 @Override
1581 ActivityRecord asActivityRecord() {
1582 // I am an activity record!
1583 return this;
1584 }
1585
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001586 void setProcess(WindowProcessController proc) {
Dianne Hackborn68a06332017-11-15 17:54:18 -08001587 app = proc;
1588 final ActivityRecord root = task != null ? task.getRootActivity() : null;
1589 if (root == this) {
1590 task.setRootProcess(proc);
1591 }
1592 }
1593
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001594 boolean hasProcess() {
1595 return app != null;
1596 }
1597
1598 boolean attachedToProcess() {
1599 return hasProcess() && app.hasThread();
1600 }
1601
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001602 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1603 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1604 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1605 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001606 // If the display is frozen, we won't do anything until the actual window is
1607 // displayed so there is no reason to put in the starting window.
1608 if (!okToDisplay()) {
Yunfan Chen48c0ed082018-12-05 18:15:35 -08001609 return false;
1610 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001611
1612 if (mStartingData != null) {
1613 return false;
1614 }
1615
1616 final WindowState mainWin = findMainWindow();
1617 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
1618 // App already has a visible window...why would you want a starting window?
1619 return false;
1620 }
1621
1622 final ActivityManager.TaskSnapshot snapshot =
Louis Changcdec0802019-11-11 11:45:07 +08001623 mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
Garfield Tane8d84ab2019-10-11 09:49:40 -07001624 false /* restoreFromDisk */, false /* reducedResolution */);
1625 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
1626 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
1627
1628 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
1629 return createSnapshot(snapshot);
1630 }
1631
1632 // If this is a translucent window, then don't show a starting window -- the current
1633 // effect (a full-screen opaque starting window that fades away to the real contents
1634 // when it is ready) does not work for this.
1635 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
1636 if (theme != 0) {
1637 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
1638 com.android.internal.R.styleable.Window,
1639 mWmService.mCurrentUserId);
1640 if (ent == null) {
1641 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
1642 // see that.
1643 return false;
1644 }
1645 final boolean windowIsTranslucent = ent.array.getBoolean(
1646 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
1647 final boolean windowIsFloating = ent.array.getBoolean(
1648 com.android.internal.R.styleable.Window_windowIsFloating, false);
1649 final boolean windowShowWallpaper = ent.array.getBoolean(
1650 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
1651 final boolean windowDisableStarting = ent.array.getBoolean(
1652 com.android.internal.R.styleable.Window_windowDisablePreview, false);
1653 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
1654 windowIsTranslucent, windowIsFloating, windowShowWallpaper);
1655 if (windowIsTranslucent) {
1656 return false;
1657 }
1658 if (windowIsFloating || windowDisableStarting) {
1659 return false;
1660 }
1661 if (windowShowWallpaper) {
1662 if (getDisplayContent().mWallpaperController
1663 .getWallpaperTarget() == null) {
1664 // If this theme is requesting a wallpaper, and the wallpaper
1665 // is not currently visible, then this effectively serves as
1666 // an opaque window and our starting window transition animation
1667 // can still work. We just need to make sure the starting window
1668 // is also showing the wallpaper.
1669 windowFlags |= FLAG_SHOW_WALLPAPER;
1670 } else {
1671 return false;
1672 }
1673 }
1674 }
1675
1676 if (transferStartingWindow(transferFrom)) {
1677 return true;
1678 }
1679
1680 // There is no existing starting window, and we don't want to create a splash screen, so
1681 // that's it!
1682 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
1683 return false;
1684 }
1685
1686 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
1687 mStartingData = new SplashScreenStartingData(mWmService, pkg,
1688 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
1689 getMergedOverrideConfiguration());
1690 scheduleAddStartingWindow();
1691 return true;
1692 }
1693
1694 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
1695 if (snapshot == null) {
1696 return false;
1697 }
1698
1699 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
1700 mStartingData = new SnapshotStartingData(mWmService, snapshot);
1701 scheduleAddStartingWindow();
1702 return true;
1703 }
1704
1705 void scheduleAddStartingWindow() {
1706 // Note: we really want to do sendMessageAtFrontOfQueue() because we
1707 // want to process the message ASAP, before any other queued
1708 // messages.
1709 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
1710 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
1711 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
1712 }
1713 }
1714
1715 private class AddStartingWindow implements Runnable {
1716
1717 @Override
1718 public void run() {
1719 // Can be accessed without holding the global lock
1720 final StartingData startingData;
1721 synchronized (mWmService.mGlobalLock) {
1722 // There can only be one adding request, silly caller!
1723 mWmService.mAnimationHandler.removeCallbacks(this);
1724
1725 if (mStartingData == null) {
1726 // Animation has been canceled... do nothing.
1727 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1728 "startingData was nulled out before handling"
1729 + " mAddStartingWindow: %s", ActivityRecord.this);
1730 return;
1731 }
1732 startingData = mStartingData;
1733 }
1734
1735 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
1736 this, startingData);
1737
1738
1739 WindowManagerPolicy.StartingSurface surface = null;
1740 try {
1741 surface = startingData.createStartingSurface(ActivityRecord.this);
1742 } catch (Exception e) {
1743 Slog.w(TAG, "Exception when adding starting window", e);
1744 }
1745 if (surface != null) {
1746 boolean abort = false;
1747 synchronized (mWmService.mGlobalLock) {
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08001748 // If the window was successfully added, then we need to remove it.
1749 if (mStartingData == null) {
1750 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Aborted starting %s: startingData=%s",
1751 ActivityRecord.this, mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001752
1753 startingWindow = null;
1754 mStartingData = null;
1755 abort = true;
1756 } else {
1757 startingSurface = surface;
1758 }
1759 if (!abort) {
1760 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1761 "Added starting %s: startingWindow=%s startingView=%s",
1762 ActivityRecord.this, startingWindow, startingSurface);
1763 }
1764 }
1765 if (abort) {
1766 surface.remove();
1767 }
1768 } else {
1769 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
1770 ActivityRecord.this);
1771 }
1772 }
1773 }
1774
1775 private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
1776
1777 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
1778 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
1779 ActivityManager.TaskSnapshot snapshot) {
1780 if (getDisplayContent().mAppTransition.getAppTransition()
1781 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
1782 // TODO(b/34099271): Remove this statement to add back the starting window and figure
1783 // out why it causes flickering, the starting window appears over the thumbnail while
1784 // the docked from recents transition occurs
1785 return STARTING_WINDOW_TYPE_NONE;
1786 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
1787 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1788 } else if (taskSwitch && allowTaskSnapshot) {
1789 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
1790 // For low RAM devices, we use the splash screen starting window instead of the
1791 // task snapshot starting window.
1792 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1793 }
Jay Aliomer8b2671b2019-10-24 13:18:06 -04001794 return snapshot == null ? STARTING_WINDOW_TYPE_SPLASH_SCREEN
Garfield Tane8d84ab2019-10-11 09:49:40 -07001795 : snapshotOrientationSameAsTask(snapshot) || fromRecents
1796 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1797 } else {
1798 return STARTING_WINDOW_TYPE_NONE;
1799 }
1800 }
1801
1802 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
1803 if (snapshot == null) {
1804 return false;
1805 }
Louis Changcdec0802019-11-11 11:45:07 +08001806 return task.getConfiguration().orientation == snapshot.getOrientation();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001807 }
1808
1809 void removeStartingWindow() {
1810 if (startingWindow == null) {
1811 if (mStartingData != null) {
1812 // Starting window has not been added yet, but it is scheduled to be added.
1813 // Go ahead and cancel the request.
1814 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
1815 mStartingData = null;
1816 }
1817 return;
1818 }
1819
1820 final WindowManagerPolicy.StartingSurface surface;
1821 if (mStartingData != null) {
1822 surface = startingSurface;
1823 mStartingData = null;
1824 startingSurface = null;
1825 startingWindow = null;
1826 startingDisplayed = false;
1827 if (surface == null) {
1828 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1829 "startingWindow was set but startingSurface==null, couldn't "
1830 + "remove");
1831
1832 return;
1833 }
1834 } else {
1835 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1836 "Tried to remove starting window but startingWindow was null: %s",
1837 this);
1838 return;
1839 }
1840
1841 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
1842 + " startingView=%s Callers=%s",
1843 this, startingWindow, startingSurface, Debug.getCallers(5));
1844
1845
1846 // Use the same thread to remove the window as we used to add it, as otherwise we end up
1847 // with things in the view hierarchy being called from different threads.
1848 mWmService.mAnimationHandler.post(() -> {
1849 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
1850 try {
1851 surface.remove();
1852 } catch (Exception e) {
1853 Slog.w(TAG_WM, "Exception when removing starting window", e);
1854 }
1855 });
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001856 }
1857
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001858 private void removeAppTokenFromDisplay() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001859 if (mWmService.mRoot == null) return;
Yunfan Chend4ef3012018-11-28 21:14:32 -08001860
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001861 final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001862 if (dc == null) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001863 Slog.w(TAG, "removeAppTokenFromDisplay: Attempted to remove token: "
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001864 + appToken + " from non-existing displayId=" + getDisplayId());
Bryce Lee7ace3952018-02-16 14:34:32 -08001865 return;
1866 }
Wale Ogunwalecc367f42017-02-01 08:12:14 -08001867 // Resume key dispatching if it is currently paused before we remove the container.
1868 resumeKeyDispatchingLocked();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001869 dc.removeAppToken(appToken.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 }
1871
Winson Chung30480042017-01-26 10:55:34 -08001872 /**
1873 * Reparents this activity into {@param newTask} at the provided {@param position}. The caller
1874 * should ensure that the {@param newTask} is not already the parent of this activity.
1875 */
Louis Changcdec0802019-11-11 11:45:07 +08001876 void reparent(Task newTask, int position, String reason) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001877 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001878 Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
1879 return;
1880 }
Louis Changcdec0802019-11-11 11:45:07 +08001881 final Task prevTask = task;
Winson Chung30480042017-01-26 10:55:34 -08001882 if (prevTask == newTask) {
1883 throw new IllegalArgumentException(reason + ": task=" + newTask
1884 + " is already the parent of r=" + this);
1885 }
1886
Winson Chung74666102017-02-22 17:49:24 -08001887 // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
1888 // the stacks in strange states. For now, we should use Task.reparent() to ensure that
1889 // the stack is left in an OK state.
1890 if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
1891 throw new IllegalArgumentException(reason + ": task=" + newTask
1892 + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
1893 + " r=" + this + " (" + prevTask.getStackId() + ")");
1894 }
1895
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001896 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
Garfield Tane8d84ab2019-10-11 09:49:40 -07001897 + " to task=%d at %d", this, task.mTaskId, position);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001898 reparent(newTask, position);
Winson Chung30480042017-01-26 10:55:34 -08001899 }
1900
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001901 private boolean isHomeIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07001902 return ACTION_MAIN.equals(intent.getAction())
Chilun2ef71f72018-11-16 17:57:15 +08001903 && (intent.hasCategory(CATEGORY_HOME)
1904 || intent.hasCategory(CATEGORY_SECONDARY_HOME))
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001905 && intent.getCategories().size() == 1
1906 && intent.getData() == null
1907 && intent.getType() == null;
1908 }
1909
Chong Zhangad24f962016-08-25 12:12:33 -07001910 static boolean isMainIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07001911 return ACTION_MAIN.equals(intent.getAction())
1912 && intent.hasCategory(CATEGORY_LAUNCHER)
Chong Zhangad24f962016-08-25 12:12:33 -07001913 && intent.getCategories().size() == 1
1914 && intent.getData() == null
1915 && intent.getType() == null;
1916 }
1917
Louis Chang6a9be162019-07-15 10:41:32 +08001918 @VisibleForTesting
1919 boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001920 if (uid == Process.myUid() || uid == 0) {
1921 // System process can launch home activity.
1922 return true;
1923 }
Winson Chung547afd22018-05-17 16:03:25 -07001924 // Allow the recents component to launch the home activity.
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07001925 final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
Winson Chung547afd22018-05-17 16:03:25 -07001926 if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
1927 return true;
1928 }
Louis Chang6a9be162019-07-15 10:41:32 +08001929 // Resolver or system chooser activity can launch home activity.
1930 return sourceRecord != null && sourceRecord.isResolverOrDelegateActivity();
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001931 }
1932
Winson Chung83471632016-12-13 11:02:12 -08001933 /**
1934 * @return whether the given package name can launch an assist activity.
1935 */
1936 private boolean canLaunchAssistActivity(String packageName) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001937 final ComponentName assistComponent =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001938 mAtmService.mActiveVoiceInteractionServiceComponent;
Winson Chung83471632016-12-13 11:02:12 -08001939 if (assistComponent != null) {
1940 return assistComponent.getPackageName().equals(packageName);
1941 }
1942 return false;
1943 }
1944
1945 private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
1946 ActivityOptions options, ActivityRecord sourceRecord) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001947 int activityType = ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001948 if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
Louis Chang6a9be162019-07-15 10:41:32 +08001949 && isHomeIntent(intent) && !isResolverOrDelegateActivity()) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001950 // This sure looks like a home activity!
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001951 activityType = ACTIVITY_TYPE_HOME;
Wale Ogunwaledf241e92016-10-13 15:14:21 -07001952
1953 if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
1954 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
1955 // We only allow home activities to be resizeable if they explicitly requested it.
1956 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
1957 }
Andrii Kulian3b3fb662019-06-26 17:52:26 -07001958 } else if (mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07001959 info.applicationInfo.uid)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001960 activityType = ACTIVITY_TYPE_RECENTS;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001961 } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
Winson Chung83471632016-12-13 11:02:12 -08001962 && canLaunchAssistActivity(launchedFromPackage)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001963 activityType = ACTIVITY_TYPE_ASSISTANT;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001964 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001965 setActivityType(activityType);
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001966 }
1967
Louis Changcdec0802019-11-11 11:45:07 +08001968 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001969 if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
Craig Mautnera228ae92014-07-09 05:44:55 -07001970 task.setTaskToAffiliateWith(taskToAffiliateWith);
1971 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07001972 }
1973
Andrii Kulian02b7a832016-10-06 23:11:56 -07001974 /**
1975 * @return Stack value from current task, null if there is no task.
1976 */
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001977 ActivityStack getActivityStack() {
1978 return task != null ? task.getStack() : null;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001979 }
1980
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001981 int getStackId() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001982 return getActivityStack() != null ? getActivityStack().mStackId : INVALID_STACK_ID;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001983 }
1984
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001985 ActivityDisplay getDisplay() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001986 final ActivityStack stack = getActivityStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001987 return stack != null ? stack.getDisplay() : null;
1988 }
1989
Garfield Tane8d84ab2019-10-11 09:49:40 -07001990 @Override
1991 boolean fillsParent() {
1992 return occludesParent();
1993 }
1994
1995 /** Returns true if this activity is opaque and fills the entire space of this task. */
1996 boolean occludesParent() {
1997 return mOccludesParent;
1998 }
1999
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002000 boolean setOccludesParent(boolean occludesParent) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002001 final boolean changed = occludesParent != mOccludesParent;
2002 mOccludesParent = occludesParent;
2003 setMainWindowOpaque(occludesParent);
2004 mWmService.mWindowPlacerLocked.requestTraversal();
2005
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08002006 if (changed && task != null && !occludesParent) {
2007 getActivityStack().convertActivityToTranslucent(this);
Riddle Hsued5789b2019-08-21 15:12:03 +08002008 }
2009 // Always ensure visibility if this activity doesn't occlude parent, so the
2010 // {@link #returningOptions} of the activity under this one can be applied in
2011 // {@link #handleAlreadyVisible()}.
2012 if (changed || !occludesParent) {
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002013 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Craig Mautner5eda9b32013-07-02 11:58:16 -07002014 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002015 return changed;
Craig Mautner4addfc52013-06-25 08:05:45 -07002016 }
2017
Garfield Tane8d84ab2019-10-11 09:49:40 -07002018 void setMainWindowOpaque(boolean isOpaque) {
2019 final WindowState win = findMainWindow();
2020 if (win == null) {
2021 return;
2022 }
2023 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2024 win.mWinAnimator.setOpaqueLocked(isOpaque);
2025 }
2026
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002027 void takeFromHistory() {
2028 if (inHistory) {
2029 inHistory = false;
2030 if (task != null && !finishing) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002031 task = null;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002032 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -07002033 clearOptionsLocked();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002034 }
2035 }
2036
2037 boolean isInHistory() {
2038 return inHistory;
2039 }
2040
Wale Ogunwale7d701172015-03-11 15:36:30 -07002041 boolean isInStackLocked() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002042 final ActivityStack stack = getActivityStack();
Andrii Kulian02b7a832016-10-06 23:11:56 -07002043 return stack != null && stack.isInStackLocked(this) != null;
Wale Ogunwale7d701172015-03-11 15:36:30 -07002044 }
2045
Craig Mautner21d24a22014-04-23 11:45:37 -07002046 boolean isPersistable() {
Ruben Brunkf53497c2017-03-27 20:26:17 -07002047 return (info.persistableMode == PERSIST_ROOT_ONLY ||
2048 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002049 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
Craig Mautner21d24a22014-04-23 11:45:37 -07002050 }
2051
Wale Ogunwale4cea0f52015-12-25 06:30:31 -08002052 boolean isFocusable() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08002053 return mRootActivityContainer.isFocusable(this, isAlwaysFocusable());
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002054 }
2055
2056 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08002057 return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002058 }
2059
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07002060 /** @return whether this activity is non-resizeable or forced to be resizeable */
2061 boolean isNonResizableOrForcedResizable(int windowingMode) {
2062 if (windowingMode == WINDOWING_MODE_PINNED && info.supportsPictureInPicture()) {
2063 return false;
2064 }
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002065 return info.resizeMode != RESIZE_MODE_RESIZEABLE
Wale Ogunwale72a73e32016-10-13 12:16:39 -07002066 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Jorim Jaggicd13d332016-04-27 15:40:20 -07002067 }
2068
Winson Chunge6308042016-10-31 09:24:01 -07002069 /**
Winson Chungd3395382016-12-13 11:49:09 -08002070 * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
Winson Chunge6308042016-10-31 09:24:01 -07002071 */
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002072 boolean supportsPictureInPicture() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002073 return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
Winson Chungd3395382016-12-13 11:49:09 -08002074 && info.supportsPictureInPicture();
2075 }
2076
2077 /**
2078 * @return whether this activity supports split-screen multi-window and can be put in the docked
2079 * stack.
2080 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002081 @Override
2082 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08002083 // An activity can not be docked even if it is considered resizeable because it only
2084 // supports picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002085 return super.supportsSplitScreenWindowingMode()
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002086 && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002087 }
2088
2089 /**
2090 * @return whether this activity supports freeform multi-window and can be put in the freeform
2091 * stack.
2092 */
2093 boolean supportsFreeform() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002094 return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002095 }
2096
2097 /**
2098 * @return whether this activity supports non-PiP multi-window.
2099 */
2100 private boolean supportsResizeableMultiWindow() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002101 return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
Winson Chungd3395382016-12-13 11:49:09 -08002102 && (ActivityInfo.isResizeableMode(info.resizeMode)
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002103 || mAtmService.mForceResizableActivities);
Wale Ogunwaled26176f2016-01-25 20:04:04 -08002104 }
2105
Winson Chunge6308042016-10-31 09:24:01 -07002106 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002107 * Check whether this activity can be launched on the specified display.
Riddle Hsu16567132018-08-16 21:37:47 +08002108 *
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002109 * @param displayId Target display id.
Riddle Hsu16567132018-08-16 21:37:47 +08002110 * @return {@code true} if either it is the default display or this activity can be put on a
2111 * secondary screen.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002112 */
2113 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002114 return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
Riddle Hsu16567132018-08-16 21:37:47 +08002115 launchedFromUid, info);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002116 }
2117
2118 /**
Robert Carrc33658e2017-04-11 18:24:20 -07002119 * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
2120 * the activity has requested to enter PiP when it would otherwise be stopped.
2121 *
Winson Chung298f95b2017-08-10 15:57:18 -07002122 * @return whether this activity is currently allowed to enter PIP.
Winson Chunge6308042016-10-31 09:24:01 -07002123 */
Winson Chung298f95b2017-08-10 15:57:18 -07002124 boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
Wale Ogunwaleb9a0c992017-04-18 07:25:20 -07002125 if (!supportsPictureInPicture()) {
2126 return false;
2127 }
2128
Winson Chungf4ac0632017-03-17 12:34:12 -07002129 // Check app-ops and see if PiP is supported for this package
2130 if (!checkEnterPictureInPictureAppOpsState()) {
2131 return false;
2132 }
2133
Winson Chungf1bfee12017-03-24 17:11:33 -07002134 // Check to see if we are in VR mode, and disallow PiP if so
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002135 if (mAtmService.shouldDisableNonVrUiLocked()) {
Winson Chungf1bfee12017-03-24 17:11:33 -07002136 return false;
2137 }
2138
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002139 boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002140 boolean isCurrentAppLocked =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002141 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002142 final ActivityDisplay display = getDisplay();
2143 boolean hasPinnedStack = display != null && display.hasPinnedStack();
Winson Chungbb348802017-01-30 12:01:45 -08002144 // Don't return early if !isNotLocked, since we want to throw an exception if the activity
2145 // is in an incorrect state
Winson Chunge581ebf2017-02-21 08:25:03 -08002146 boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
Robert Carrc33658e2017-04-11 18:24:20 -07002147
2148 // We don't allow auto-PiP when something else is already pipped.
2149 if (beforeStopping && hasPinnedStack) {
2150 return false;
2151 }
2152
Bryce Lee7ace3952018-02-16 14:34:32 -08002153 switch (mState) {
Winson Chungc2baac02017-01-11 13:34:47 -08002154 case RESUMED:
Winson Chunge581ebf2017-02-21 08:25:03 -08002155 // When visible, allow entering PiP if the app is not locked. If it is over the
2156 // keyguard, then we will prompt to unlock in the caller before entering PiP.
Robert Carrc33658e2017-04-11 18:24:20 -07002157 return !isCurrentAppLocked &&
Winson Chungf7e03e12017-08-22 11:32:16 -07002158 (supportsEnterPipOnTaskSwitch || !beforeStopping);
Winson Chungc2baac02017-01-11 13:34:47 -08002159 case PAUSING:
2160 case PAUSED:
Winson Chungbb348802017-01-30 12:01:45 -08002161 // When pausing, then only allow enter PiP as in the resume state, and in addition,
2162 // require that there is not an existing PiP activity and that the current system
2163 // state supports entering PiP
Winson Chunge581ebf2017-02-21 08:25:03 -08002164 return isNotLockedOrOnKeyguard && !hasPinnedStack
Winson Chungf7e03e12017-08-22 11:32:16 -07002165 && supportsEnterPipOnTaskSwitch;
Winson Chungc2baac02017-01-11 13:34:47 -08002166 case STOPPING:
2167 // When stopping in a valid state, then only allow enter PiP as in the pause state.
2168 // Otherwise, fall through to throw an exception if the caller is trying to enter
2169 // PiP in an invalid stopping state.
Winson Chungf7e03e12017-08-22 11:32:16 -07002170 if (supportsEnterPipOnTaskSwitch) {
Winson Chungf4ac0632017-03-17 12:34:12 -07002171 return isNotLockedOrOnKeyguard && !hasPinnedStack;
Winson Chungc2baac02017-01-11 13:34:47 -08002172 }
2173 default:
Winson Chung298f95b2017-08-10 15:57:18 -07002174 return false;
Winson Chungb5c41b72016-12-07 15:00:47 -08002175 }
Winson Chunge6308042016-10-31 09:24:01 -07002176 }
2177
Winson Chung59fda9e2017-01-20 16:14:51 -08002178 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -07002179 * Sets if this AWT is in the process of closing or entering PIP.
2180 * {@link #mWillCloseOrEnterPip}}
2181 */
2182 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
2183 mWillCloseOrEnterPip = willCloseOrEnterPip;
2184 }
2185
2186 /**
2187 * Returns whether this AWT is considered closing. Conditions are either
2188 * 1. Is this app animating and was requested to be hidden
2189 * 2. App is delayed closing since it might enter PIP.
2190 */
2191 boolean isClosingOrEnteringPip() {
Issei Suzuki430a1112019-11-14 16:20:52 +01002192 return (isAnimating(TRANSITION | PARENTS) && hiddenRequested) || mWillCloseOrEnterPip;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002193 }
2194 /**
Winson Chungf4ac0632017-03-17 12:34:12 -07002195 * @return Whether AppOps allows this package to enter picture-in-picture.
Winson Chung59fda9e2017-01-20 16:14:51 -08002196 */
Winson Chungf4ac0632017-03-17 12:34:12 -07002197 private boolean checkEnterPictureInPictureAppOpsState() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002198 return mAtmService.getAppOpsService().checkOperation(
Andrii Kulianeceebbf2019-06-26 17:36:51 -07002199 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
Winson Chung59fda9e2017-01-20 16:14:51 -08002200 }
2201
Garfield Tane8d84ab2019-10-11 09:49:40 -07002202 boolean isAlwaysFocusable() {
2203 return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
2204 }
2205
2206 // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
2207 // focusable means resumeable. I guess with that in mind maybe we should rename the other
2208 // method to isResumeable() or something like that.
2209 boolean windowsAreFocusable() {
2210 if (mTargetSdk < Build.VERSION_CODES.Q) {
2211 final int pid = getPid();
2212 final ActivityRecord topFocusedAppOfMyProcess =
2213 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
2214 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
2215 // For the apps below Q, there can be only one app which has the focused window per
2216 // process, because legacy apps may not be ready for a multi-focus system.
2217 return false;
2218 }
2219 }
Louis Changa9c9d982019-11-11 11:20:19 +08002220 return (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable())
2221 && getParent() != null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002222 }
2223
Louis Chang19443452018-10-09 12:10:21 +08002224 /** Move activity with its stack to front and make the stack focused. */
2225 boolean moveFocusableActivityToTop(String reason) {
2226 if (!isFocusable()) {
2227 if (DEBUG_FOCUS) {
2228 Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
2229 }
2230 return false;
2231 }
2232
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002233 final ActivityStack stack = getActivityStack();
Louis Chang19443452018-10-09 12:10:21 +08002234 if (stack == null) {
2235 Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
2236 + this + " task=" + task);
2237 return false;
2238 }
2239
Wale Ogunwaled32da472018-11-16 07:19:28 -08002240 if (mRootActivityContainer.getTopResumedActivity() == this) {
Louis Chang19443452018-10-09 12:10:21 +08002241 if (DEBUG_FOCUS) {
2242 Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
2243 }
2244 return false;
2245 }
2246
2247 if (DEBUG_FOCUS) {
2248 Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
2249 }
2250
2251 stack.moveToFront(reason, task);
2252 // Report top activity change to tracking services and WM
Wale Ogunwaled32da472018-11-16 07:19:28 -08002253 if (mRootActivityContainer.getTopResumedActivity() == this) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002254 mAtmService.setResumedActivityUncheckLocked(this, reason);
Louis Chang19443452018-10-09 12:10:21 +08002255 }
2256 return true;
2257 }
Jorim Jaggife762342016-10-13 14:33:27 +02002258
Andrii Kuliande93eff2019-07-12 12:21:27 -07002259 /** Finish all activities in the task with the same affinity as this one. */
2260 void finishActivityAffinity() {
Louis Changcdec0802019-11-11 11:45:07 +08002261 final ArrayList<ActivityRecord> activities = task.mChildren;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002262 for (int index = activities.indexOf(this); index >= 0; --index) {
2263 final ActivityRecord cur = activities.get(index);
2264 if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
2265 break;
2266 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002267 cur.finishIfPossible("request-affinity", true /* oomAdj */);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002268 }
2269 }
2270
2271 /**
2272 * Sets the result for activity that started this one, clears the references to activities
2273 * started for result from this one, and clears new intents.
2274 */
2275 void finishActivityResults(int resultCode, Intent resultData) {
2276 // Send the result if needed
2277 if (resultTo != null) {
2278 if (DEBUG_RESULTS) {
2279 Slog.v(TAG_RESULTS, "Adding result to " + resultTo
2280 + " who=" + resultWho + " req=" + requestCode
2281 + " res=" + resultCode + " data=" + resultData);
2282 }
2283 if (resultTo.mUserId != mUserId) {
2284 if (resultData != null) {
2285 resultData.prepareToLeaveUser(mUserId);
2286 }
2287 }
2288 if (info.applicationInfo.uid > 0) {
2289 mAtmService.mUgmInternal.grantUriPermissionFromIntent(info.applicationInfo.uid,
2290 resultTo.packageName, resultData,
2291 resultTo.getUriPermissionsLocked(), resultTo.mUserId);
2292 }
2293 resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
2294 resultTo = null;
2295 } else if (DEBUG_RESULTS) {
2296 Slog.v(TAG_RESULTS, "No result destination from " + this);
2297 }
2298
2299 // Make sure this HistoryRecord is not holding on to other resources,
2300 // because clients have remote IPC references to this object so we
2301 // can't assume that will go away and want to avoid circular IPC refs.
2302 results = null;
2303 pendingResults = null;
2304 newIntents = null;
2305 setSavedState(null /* savedState */);
2306 }
2307
Andrii Kulian057a6512019-07-15 16:15:51 -07002308 /** Activity finish request was not executed. */
2309 static final int FINISH_RESULT_CANCELLED = 0;
2310 /** Activity finish was requested, activity will be fully removed later. */
2311 static final int FINISH_RESULT_REQUESTED = 1;
2312 /** Activity finish was requested, activity was removed from history. */
2313 static final int FINISH_RESULT_REMOVED = 2;
2314
2315 /** Definition of possible results for activity finish request. */
2316 @IntDef(prefix = { "FINISH_RESULT_" }, value = {
2317 FINISH_RESULT_CANCELLED,
2318 FINISH_RESULT_REQUESTED,
2319 FINISH_RESULT_REMOVED,
2320 })
2321 @interface FinishRequest {}
2322
Andrii Kuliande93eff2019-07-12 12:21:27 -07002323 /**
Louis Chang7b03ad92019-08-21 12:32:33 +08002324 * See {@link #finishIfPossible(int, Intent, String, boolean)}
Andrii Kuliande93eff2019-07-12 12:21:27 -07002325 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002326 @FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
Louis Chang7b03ad92019-08-21 12:32:33 +08002327 return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason, oomAdj);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002328 }
2329
2330 /**
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002331 * Finish activity if possible. If activity was resumed - we must first pause it to make the
2332 * activity below resumed. Otherwise we will try to complete the request immediately by calling
2333 * {@link #completeFinishing(String)}.
Andrii Kulian057a6512019-07-15 16:15:51 -07002334 * @return One of {@link FinishRequest} values:
2335 * {@link #FINISH_RESULT_REMOVED} if this activity has been removed from the history list.
2336 * {@link #FINISH_RESULT_REQUESTED} if removal process was started, but it is still in the list
2337 * and will be removed from history later.
2338 * {@link #FINISH_RESULT_CANCELLED} if activity is already finishing or in invalid state and the
2339 * request to finish it was not ignored.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002340 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002341 @FinishRequest int finishIfPossible(int resultCode, Intent resultData, String reason,
Louis Chang7b03ad92019-08-21 12:32:33 +08002342 boolean oomAdj) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002343 if (DEBUG_RESULTS || DEBUG_STATES) {
2344 Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
2345 + ", data=" + resultData + ", reason=" + reason);
2346 }
2347
Andrii Kuliande93eff2019-07-12 12:21:27 -07002348 if (finishing) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002349 Slog.w(TAG, "Duplicate finish request for r=" + this);
2350 return FINISH_RESULT_CANCELLED;
2351 }
2352
2353 if (!isInStackLocked()) {
2354 Slog.w(TAG, "Finish request when not in stack for r=" + this);
2355 return FINISH_RESULT_CANCELLED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002356 }
2357
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002358 final ActivityStack stack = getActivityStack();
Riddle Hsucf920232019-10-04 19:05:36 +08002359 final boolean mayAdjustTop = (isState(RESUMED) || stack.mResumedActivity == null)
2360 && stack.isFocusedStackOnDisplay();
2361 final boolean shouldAdjustGlobalFocus = mayAdjustTop
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002362 // It must be checked before {@link #makeFinishingLocked} is called, because a stack
2363 // is not visible if it only contains finishing activities.
2364 && mRootActivityContainer.isTopDisplayFocusedStack(stack);
2365
Riddle Hsua0022cd2019-09-09 21:12:41 +08002366 mAtmService.deferWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002367 try {
2368 makeFinishingLocked();
Louis Changcdec0802019-11-11 11:45:07 +08002369 // Make a local reference to its task since this.task could be set to null once this
2370 // activity is destroyed and detached from task.
2371 final Task task = getTask();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002372 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2373 mUserId, System.identityHashCode(this),
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002374 task.mTaskId, shortComponentName, reason);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002375 final ArrayList<ActivityRecord> activities = task.mChildren;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002376 final int index = activities.indexOf(this);
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002377 if (index < (task.getChildCount() - 1)) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002378 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2379 // If the caller asked that this activity (and all above it)
2380 // be cleared when the task is reset, don't lose that information,
2381 // but propagate it up to the next activity.
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002382 final ActivityRecord next = task.getChildAt(index + 1);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002383 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2384 }
2385 }
2386
2387 pauseKeyDispatchingLocked();
2388
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002389 // We are finishing the top focused activity and its stack has nothing to be focused so
2390 // the next focusable stack should be focused.
Riddle Hsucf920232019-10-04 19:05:36 +08002391 if (mayAdjustTop
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002392 && (stack.topRunningActivityLocked() == null || !stack.isFocusable())) {
Riddle Hsucf920232019-10-04 19:05:36 +08002393 if (shouldAdjustGlobalFocus) {
2394 // Move the entire hierarchy to top with updating global top resumed activity
2395 // and focused application if needed.
2396 stack.adjustFocusToNextFocusableStack("finish-top");
2397 } else {
2398 // Only move the next stack to top in its display.
2399 final ActivityDisplay display = stack.getDisplay();
2400 final ActivityRecord next = display.topRunningActivity();
2401 if (next != null) {
2402 display.positionChildAtTop(next.getActivityStack(),
2403 false /* includingParents */, "finish-display-top");
2404 }
2405 }
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002406 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002407
2408 finishActivityResults(resultCode, resultData);
2409
2410 final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
2411 final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002412 if (isState(RESUMED)) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002413 if (endTask) {
2414 mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
2415 task.getTaskInfo());
2416 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002417 // Prepare app close transition, but don't execute just yet. It is possible that
2418 // an activity that will be made resumed in place of this one will immediately
2419 // launch another new activity. In this case current closing transition will be
2420 // combined with open transition for the new activity.
2421 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
2422 Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
2423 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002424 getDisplay().mDisplayContent.prepareAppTransition(transit, false);
2425
2426 // When finishing the activity preemptively take the snapshot before the app window
2427 // is marked as hidden and any configuration changes take place
2428 if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002429 final ArraySet<Task> tasks = Sets.newArraySet(task);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002430 mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
2431 mAtmService.mWindowManager.mTaskSnapshotController
2432 .addSkipClosingAppSnapshotTasks(tasks);
2433 }
2434
2435 // Tell window manager to prepare for this one to be removed.
2436 setVisibility(false);
2437
2438 if (stack.mPausingActivity == null) {
2439 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + this);
2440 if (DEBUG_USER_LEAVING) {
2441 Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
2442 }
Louis Chang7b03ad92019-08-21 12:32:33 +08002443 stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
2444 null /* resuming */);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002445 }
2446
2447 if (endTask) {
2448 mAtmService.getLockTaskController().clearLockedTask(task);
2449 }
2450 } else if (!isState(PAUSING)) {
Issei Suzuki430a1112019-11-14 16:20:52 +01002451 if (visible) {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002452 // Prepare and execute close transition.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002453 prepareActivityHideTransitionAnimation(transit);
2454 }
2455
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002456 final boolean removedActivity = completeFinishing("finishIfPossible") == null;
2457 // Performance optimization - only invoke OOM adjustment if the state changed to
2458 // 'STOPPING'. Otherwise it will not change the OOM scores.
2459 if (oomAdj && isState(STOPPING)) {
2460 mAtmService.updateOomAdj();
2461 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002462
2463 // The following code is an optimization. When the last non-task overlay activity
2464 // is removed from the task, we remove the entire task from the stack. However,
2465 // since that is done after the scheduled destroy callback from the activity, that
2466 // call to change the visibility of the task overlay activities would be out of
2467 // sync with the activity visibility being set for this finishing activity above.
2468 // In this case, we can set the visibility of all the task overlay activities when
2469 // we detect the last one is finishing to keep them in sync.
2470 if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002471 for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
2472 final ActivityRecord taskOverlay = task.getChildAt(i);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002473 if (!taskOverlay.mTaskOverlay) {
2474 continue;
2475 }
2476 taskOverlay.prepareActivityHideTransitionAnimation(transit);
2477 }
2478 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002479
Andrii Kulian057a6512019-07-15 16:15:51 -07002480 return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002481 } else {
2482 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
2483 }
2484
Andrii Kulian057a6512019-07-15 16:15:51 -07002485 return FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002486 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +08002487 mAtmService.continueWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002488 }
2489 }
2490
2491 private void prepareActivityHideTransitionAnimation(int transit) {
2492 final DisplayContent dc = getDisplay().mDisplayContent;
2493 dc.prepareAppTransition(transit, false);
2494 setVisibility(false);
2495 dc.executeAppTransition();
2496 }
2497
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002498 /**
2499 * Complete activity finish request that was initiated earlier. If the activity is still
2500 * pausing we will wait for it to complete its transition. If the activity that should appear in
2501 * place of this one is not visible yet - we'll wait for it first. Otherwise - activity can be
2502 * destroyed right away.
2503 * @param reason Reason for finishing the activity.
2504 * @return Flag indicating whether the activity was removed from history.
2505 */
2506 ActivityRecord completeFinishing(String reason) {
2507 if (!finishing || isState(RESUMED)) {
2508 throw new IllegalArgumentException(
2509 "Activity must be finishing and not resumed to complete, r=" + this
2510 + ", finishing=" + finishing + ", state=" + mState);
2511 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002512
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002513 if (isState(PAUSING)) {
2514 // Activity is marked as finishing and will be processed once it completes.
2515 return this;
2516 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002517
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002518 boolean activityRemoved = false;
2519
2520 // If this activity is currently visible, and the resumed activity is not yet visible, then
2521 // hold off on finishing until the resumed one becomes visible.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002522 // The activity that we are finishing may be over the lock screen. In this case, we do not
2523 // want to consider activities that cannot be shown on the lock screen as running and should
2524 // proceed with finishing the activity if there is no valid next top running activity.
2525 // Note that if this finishing activity is floating task, we don't need to wait the
2526 // next activity resume and can destroy it directly.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002527 // TODO(b/137329632): find the next activity directly underneath this one, not just anywhere
2528 final ActivityRecord next = getDisplay().topRunningActivity(
2529 true /* considerKeyguardState */);
Issei Suzuki430a1112019-11-14 16:20:52 +01002530 final boolean isVisible = visible || nowVisible;
lumark50b81542019-09-01 23:11:49 +08002531 // isNextNotYetVisible is to check if the next activity is invisible, or it has been
2532 // requested to be invisible but its windows haven't reported as invisible. If so, it
2533 // implied that the current finishing activity should be added into stopping list rather
2534 // than destroy immediately.
Issei Suzuki430a1112019-11-14 16:20:52 +01002535 final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.visible);
lumark50b81542019-09-01 23:11:49 +08002536 if (isVisible && isNextNotYetVisible) {
Andrii Kulian34acc142019-09-24 15:35:50 -07002537 // Add this activity to the list of stopping activities. It will be processed and
2538 // destroyed when the next activity reports idle.
Andrii Kulian79d67982019-08-19 11:56:16 -07002539 addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
2540 "completeFinishing");
Andrii Kulian79d67982019-08-19 11:56:16 -07002541 setState(STOPPING, "completeFinishing");
Andrii Kulian34acc142019-09-24 15:35:50 -07002542 } else if (addToFinishingAndWaitForIdle()) {
2543 // We added this activity to the finishing list and something else is becoming resumed.
2544 // The activity will complete finishing when the next activity reports idle. No need to
2545 // do anything else here.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002546 } else {
Andrii Kulian34acc142019-09-24 15:35:50 -07002547 // Not waiting for the next one to become visible, and nothing else will be resumed in
2548 // place of this activity - requesting destruction right away.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002549 activityRemoved = destroyIfPossible(reason);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002550 }
2551
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002552 return activityRemoved ? null : this;
2553 }
2554
2555 /**
2556 * Destroy and cleanup the activity both on client and server if possible. If activity is the
2557 * last one left on display with home stack and there is no other running activity - delay
2558 * destroying it until the next one starts.
2559 */
2560 boolean destroyIfPossible(String reason) {
2561 setState(FINISHING, "destroyIfPossible");
2562
2563 // Make sure the record is cleaned out of other places.
2564 mStackSupervisor.mStoppingActivities.remove(this);
2565 mStackSupervisor.mGoingToSleepActivities.remove(this);
2566
2567 final ActivityStack stack = getActivityStack();
2568 final ActivityDisplay display = getDisplay();
2569 // TODO(b/137329632): Exclude current activity when looking for the next one with
2570 // ActivityDisplay#topRunningActivity().
2571 final ActivityRecord next = display.topRunningActivity();
2572 final boolean isLastStackOverEmptyHome =
2573 next == null && stack.isFocusedStackOnDisplay() && display.getHomeStack() != null;
2574 if (isLastStackOverEmptyHome) {
2575 // Don't destroy activity immediately if this is the last activity on the display and
2576 // the display contains home stack. Although there is no next activity at the moment,
2577 // another home activity should be started later. Keep this activity alive until next
2578 // home activity is resumed. This way the user won't see a temporary black screen.
2579 addToFinishingAndWaitForIdle();
2580 return false;
2581 }
2582 makeFinishingLocked();
2583
Andrii Kulian79d67982019-08-19 11:56:16 -07002584 final boolean activityRemoved = destroyImmediately(true /* removeFromApp */,
2585 "finish-imm:" + reason);
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002586
2587 // If the display does not have running activity, the configuration may need to be
2588 // updated for restoring original orientation of the display.
2589 if (next == null) {
2590 mRootActivityContainer.ensureVisibilityAndConfig(next, getDisplayId(),
2591 false /* markFrozenIfConfigChanged */, true /* deferResume */);
2592 }
2593 if (activityRemoved) {
2594 mRootActivityContainer.resumeFocusedStacksTopActivities();
2595 }
2596
2597 if (DEBUG_CONTAINERS) {
2598 Slog.d(TAG_CONTAINERS, "destroyIfPossible: r=" + this + " destroy returned removed="
2599 + activityRemoved);
2600 }
2601
2602 return activityRemoved;
2603 }
2604
Andrii Kulian34acc142019-09-24 15:35:50 -07002605 /**
2606 * Add this activity to the list of finishing and trigger resuming of activities in focused
2607 * stacks.
2608 * @return {@code true} if some other activity is being resumed as a result of this call.
2609 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002610 @VisibleForTesting
Andrii Kulian34acc142019-09-24 15:35:50 -07002611 boolean addToFinishingAndWaitForIdle() {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002612 if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
2613 setState(FINISHING, "addToFinishingAndWaitForIdle");
Andrii Kulian34acc142019-09-24 15:35:50 -07002614 if (!mStackSupervisor.mFinishingActivities.contains(this)) {
2615 mStackSupervisor.mFinishingActivities.add(this);
2616 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002617 resumeKeyDispatchingLocked();
Andrii Kulian34acc142019-09-24 15:35:50 -07002618 return mRootActivityContainer.resumeFocusedStacksTopActivities();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002619 }
2620
Andrii Kulian79d67982019-08-19 11:56:16 -07002621 /**
2622 * Destroy the current CLIENT SIDE instance of an activity. This may be called both when
2623 * actually finishing an activity, or when performing a configuration switch where we destroy
2624 * the current client-side object but then create a new client-side object for this same
2625 * HistoryRecord.
2626 * Normally the server-side record will be removed when the client reports back after
2627 * destruction. If, however, at this point there is no client process attached, the record will
Andrii Kulianf49a58c2019-08-14 17:34:27 -07002628 * be removed immediately.
2629 *
2630 * @return {@code true} if activity was immediately removed from history, {@code false}
2631 * otherwise.
Andrii Kulian79d67982019-08-19 11:56:16 -07002632 */
2633 boolean destroyImmediately(boolean removeFromApp, String reason) {
2634 if (DEBUG_SWITCH || DEBUG_CLEANUP) {
2635 Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this
2636 + ", app=" + (hasProcess() ? app.mName : "(null)"));
2637 }
2638
2639 if (isState(DESTROYING, DESTROYED)) {
2640 if (DEBUG_STATES) {
2641 Slog.v(TAG_STATES, "activity " + this + " already destroying."
2642 + "skipping request with reason:" + reason);
2643 }
2644 return false;
2645 }
2646
2647 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, mUserId,
Louis Changcdec0802019-11-11 11:45:07 +08002648 System.identityHashCode(this), task.mTaskId, shortComponentName, reason);
Andrii Kulian79d67982019-08-19 11:56:16 -07002649
Riddle Hsu5477b572019-11-12 16:07:29 +08002650 final ActivityStack stack = getActivityStack();
2651 if (hasProcess() && !stack.inLruList(this)) {
2652 Slog.w(TAG, "Activity " + this + " being finished, but not in LRU list");
2653 }
2654
Andrii Kulian79d67982019-08-19 11:56:16 -07002655 boolean removedFromHistory = false;
2656
2657 cleanUp(false /* cleanServices */, false /* setState */);
2658
Riddle Hsu5477b572019-11-12 16:07:29 +08002659 if (hasProcess()) {
Andrii Kulian79d67982019-08-19 11:56:16 -07002660 if (removeFromApp) {
2661 app.removeActivity(this);
2662 if (!app.hasActivities()) {
2663 mAtmService.clearHeavyWeightProcessIfEquals(app);
2664 // Update any services we are bound to that might care about whether
2665 // their client may have activities.
2666 // No longer have activities, so update LRU list and oom adj.
2667 app.updateProcessInfo(true /* updateServiceConnectionActivities */,
2668 false /* activityChange */, true /* updateOomAdj */);
2669 }
2670 }
2671
2672 boolean skipDestroy = false;
2673
2674 try {
2675 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
2676 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2677 DestroyActivityItem.obtain(finishing, configChangeFlags));
2678 } catch (Exception e) {
2679 // We can just ignore exceptions here... if the process has crashed, our death
2680 // notification will clean things up.
2681 if (finishing) {
2682 removeFromHistory(reason + " exceptionInScheduleDestroy");
2683 removedFromHistory = true;
2684 skipDestroy = true;
2685 }
2686 }
2687
2688 nowVisible = false;
2689
2690 // If the activity is finishing, we need to wait on removing it from the list to give it
2691 // a chance to do its cleanup. During that time it may make calls back with its token
2692 // so we need to be able to find it on the list and so we don't want to remove it from
2693 // the list yet. Otherwise, we can just immediately put it in the destroyed state since
2694 // we are not removing it from the list.
2695 if (finishing && !skipDestroy) {
2696 if (DEBUG_STATES) {
2697 Slog.v(TAG_STATES, "Moving to DESTROYING: " + this + " (destroy requested)");
2698 }
2699 setState(DESTROYING,
2700 "destroyActivityLocked. finishing and not skipping destroy");
2701 stack.scheduleDestroyTimeoutForActivity(this);
2702 } else {
2703 if (DEBUG_STATES) {
2704 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
2705 }
2706 setState(DESTROYED,
2707 "destroyActivityLocked. not finishing or skipping destroy");
2708 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
2709 app = null;
2710 }
2711 } else {
2712 // Remove this record from the history.
2713 if (finishing) {
2714 removeFromHistory(reason + " hadNoApp");
2715 removedFromHistory = true;
2716 } else {
2717 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (no app)");
2718 setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
2719 }
2720 }
2721
2722 configChangeFlags = 0;
2723
Andrii Kulian79d67982019-08-19 11:56:16 -07002724 return removedFromHistory;
2725 }
2726
2727 boolean safelyDestroy(String reason) {
2728 if (isDestroyable()) {
2729 if (DEBUG_SWITCH) {
2730 final ActivityStack stack = getActivityStack();
2731 Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState()
2732 + " resumed=" + stack.mResumedActivity
2733 + " pausing=" + stack.mPausingActivity
2734 + " for reason " + reason);
2735 }
2736 return destroyImmediately(true /* removeFromApp */, reason);
2737 }
2738 return false;
2739 }
2740
2741 /** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
2742 void removeFromHistory(String reason) {
2743 finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
2744 makeFinishingLocked();
2745 if (ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE) {
2746 Slog.i(TAG_ADD_REMOVE, "Removing activity " + this + " from stack callers="
2747 + Debug.getCallers(5));
2748 }
2749
2750 takeFromHistory();
2751 final ActivityStack stack = getActivityStack();
2752 stack.removeTimeoutsForActivity(this);
2753 if (DEBUG_STATES) {
2754 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
2755 }
2756 setState(DESTROYED, "removeFromHistory");
2757 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
2758 app = null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002759 removeAppTokenFromDisplay();
Andrii Kulian79d67982019-08-19 11:56:16 -07002760
2761 cleanUpActivityServices();
2762 removeUriPermissionsLocked();
2763 }
2764
Wale Ogunwale7d701172015-03-11 15:36:30 -07002765 void makeFinishingLocked() {
Wale Ogunwalec981ad52017-06-13 11:40:06 -07002766 if (finishing) {
2767 return;
2768 }
2769 finishing = true;
2770 if (stopped) {
2771 clearOptionsLocked();
2772 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002773 }
2774
Andrii Kulian79d67982019-08-19 11:56:16 -07002775 /**
2776 * This method is to only be called from the client via binder when the activity is destroyed
2777 * AND finished.
2778 */
2779 void destroyed(String reason) {
2780 getActivityStack().removeDestroyTimeoutForActivity(this);
2781
2782 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + this);
2783
2784 if (!isState(DESTROYING, DESTROYED)) {
2785 throw new IllegalStateException(
2786 "Reported destroyed for activity that is not destroying: r=" + this);
2787 }
2788
2789 if (isInStackLocked()) {
2790 cleanUp(true /* cleanServices */, false /* setState */);
2791 removeFromHistory(reason);
2792 }
2793
2794 mRootActivityContainer.resumeFocusedStacksTopActivities();
2795 }
2796
2797 /**
2798 * Perform the common clean-up of an activity record. This is called both as part of
2799 * destroyActivityLocked() (when destroying the client-side representation) and cleaning things
2800 * up as a result of its hosting processing going away, in which case there is no remaining
2801 * client-side state to destroy so only the cleanup here is needed.
2802 *
2803 * Note: Call before {@link #removeFromHistory(String)}.
2804 */
2805 void cleanUp(boolean cleanServices, boolean setState) {
2806 final ActivityStack stack = getActivityStack();
2807 stack.onActivityRemovedFromStack(this);
2808
2809 deferRelaunchUntilPaused = false;
2810 frozenBeforeDestroy = false;
2811
2812 if (setState) {
2813 setState(DESTROYED, "cleanUp");
2814 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this);
2815 app = null;
2816 }
2817
2818 // Inform supervisor the activity has been removed.
2819 mStackSupervisor.cleanupActivity(this);
2820
2821 // Remove any pending results.
2822 if (finishing && pendingResults != null) {
2823 for (WeakReference<PendingIntentRecord> apr : pendingResults) {
2824 PendingIntentRecord rec = apr.get();
2825 if (rec != null) {
2826 mAtmService.mPendingIntentController.cancelIntentSender(rec,
2827 false /* cleanActivity */);
2828 }
2829 }
2830 pendingResults = null;
2831 }
2832
2833 if (cleanServices) {
2834 cleanUpActivityServices();
2835 }
2836
2837 // Get rid of any pending idle timeouts.
2838 stack.removeTimeoutsForActivity(this);
2839 // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
2840 // manager so it can update its bookkeeping.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002841 clearRelaunching();
Andrii Kulian79d67982019-08-19 11:56:16 -07002842 }
2843
Garfield Tane8d84ab2019-10-11 09:49:40 -07002844 boolean isRelaunching() {
2845 return mPendingRelaunchCount > 0;
2846 }
2847
2848 boolean shouldFreezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002849 // For freeform windows, we can't freeze the bounds at the moment because this would make
2850 // the resizing unresponsive.
2851 if (task == null || task.inFreeformWindowingMode()) {
2852 return false;
2853 }
2854
2855 // We freeze the bounds while drag resizing to deal with the time between
2856 // the divider/drag handle being released, and the handling it's new
2857 // configuration. If we are relaunched outside of the drag resizing state,
2858 // we need to be careful not to do this.
Louis Changcdec0802019-11-11 11:45:07 +08002859 return task.isDragResizing();
Garfield Tane8d84ab2019-10-11 09:49:40 -07002860 }
2861
2862 void startRelaunching() {
2863 if (shouldFreezeBounds()) {
2864 freezeBounds();
2865 }
2866
2867 // In the process of tearing down before relaunching, the app will
2868 // try and clean up it's child surfaces. We need to prevent this from
2869 // happening, so we sever the children, transfering their ownership
2870 // from the client it-self to the parent surface (owned by us).
2871 detachChildren();
2872
2873 mPendingRelaunchCount++;
2874 }
2875
2876 /**
2877 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
2878 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
2879 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
2880 * with a queue.
2881 */
2882 private void freezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002883 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
2884
2885 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
2886 // We didn't call prepareFreezingBounds on the task, so use the current value.
2887 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
2888 } else {
2889 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
2890 }
2891 // Calling unset() to make it equal to Configuration.EMPTY.
2892 task.mPreparedFrozenMergedConfig.unset();
2893 }
2894
2895 void detachChildren() {
2896 SurfaceControl.openTransaction();
2897 for (int i = mChildren.size() - 1; i >= 0; i--) {
2898 final WindowState w = mChildren.get(i);
2899 w.mWinAnimator.detachChildren();
2900 }
2901 SurfaceControl.closeTransaction();
2902 }
2903
2904 void finishRelaunching() {
2905 unfreezeBounds();
2906
2907 if (mPendingRelaunchCount > 0) {
2908 mPendingRelaunchCount--;
2909 } else {
2910 // Update keyguard flags upon finishing relaunch.
2911 checkKeyguardFlagsChanged();
2912 }
2913 }
2914
2915 void clearRelaunching() {
2916 if (mPendingRelaunchCount == 0) {
2917 return;
2918 }
2919 unfreezeBounds();
2920 mPendingRelaunchCount = 0;
2921 }
2922
2923 /**
2924 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
2925 */
2926 private void unfreezeBounds() {
2927 if (mFrozenBounds.isEmpty()) {
2928 return;
2929 }
2930 mFrozenBounds.remove();
2931 if (!mFrozenMergedConfig.isEmpty()) {
2932 mFrozenMergedConfig.remove();
2933 }
2934 for (int i = mChildren.size() - 1; i >= 0; i--) {
2935 final WindowState win = mChildren.get(i);
2936 win.onUnfreezeBounds();
2937 }
2938 mWmService.mWindowPlacerLocked.performSurfacePlacement();
2939 }
2940
Andrii Kulian79d67982019-08-19 11:56:16 -07002941 /**
2942 * Perform clean-up of service connections in an activity record.
2943 */
2944 private void cleanUpActivityServices() {
2945 if (mServiceConnectionsHolder == null) {
2946 return;
2947 }
2948 // Throw away any services that have been bound by this activity.
2949 mServiceConnectionsHolder.disconnectActivityFromServices();
2950 }
2951
Garfield Tane8d84ab2019-10-11 09:49:40 -07002952 @Override
2953 void removeImmediately() {
2954 onRemovedFromDisplay();
2955 super.removeImmediately();
2956 }
2957
2958 @Override
2959 void removeIfPossible() {
2960 mIsExiting = false;
2961 removeAllWindowsIfPossible();
2962 removeImmediately();
2963 }
2964
2965 @Override
2966 boolean checkCompleteDeferredRemoval() {
2967 if (mIsExiting) {
2968 removeIfPossible();
2969 }
2970 return super.checkCompleteDeferredRemoval();
2971 }
2972
2973 void onRemovedFromDisplay() {
2974 if (mRemovingFromDisplay) {
2975 return;
2976 }
2977 mRemovingFromDisplay = true;
2978
2979 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
2980
2981 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
2982
2983 getDisplayContent().mOpeningApps.remove(this);
2984 getDisplayContent().mChangingApps.remove(this);
2985 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
2986 mWmService.mTaskSnapshotController.onAppRemoved(this);
2987 waitingToShow = false;
2988 if (getDisplayContent().mClosingApps.contains(this)) {
2989 delayed = true;
2990 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
2991 getDisplayContent().mClosingApps.add(this);
2992 delayed = true;
2993 }
2994
2995 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
2996 "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
lumark9bca6b42019-10-17 18:35:22 +08002997 getAnimation(), isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07002998
2999 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
3000 + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
3001
3002 if (mStartingData != null) {
3003 removeStartingWindow();
3004 }
3005
3006 // If this window was animating, then we need to ensure that the app transition notifies
3007 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
3008 // so add to that list now
lumark9bca6b42019-10-17 18:35:22 +08003009 if (isAnimating(TRANSITION)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003010 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
3011 }
3012
Louis Changdc077272019-11-12 16:52:56 +08003013 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003014 if (delayed && !isEmpty()) {
3015 // set the token aside because it has an active animation to be finished
3016 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3017 "removeAppToken make exiting: %s", this);
3018 if (stack != null) {
3019 stack.mExitingActivities.add(this);
3020 }
3021 mIsExiting = true;
3022 } else {
3023 // Make sure there is no animation running on this token, so any windows associated
3024 // with it will be removed as soon as their animations are complete
3025 cancelAnimation();
3026 if (stack != null) {
3027 stack.mExitingActivities.remove(this);
3028 }
3029 removeIfPossible();
3030 }
3031
Garfield Tane8d84ab2019-10-11 09:49:40 -07003032 stopFreezingScreen(true, true);
3033
3034 final DisplayContent dc = getDisplayContent();
3035 if (dc.mFocusedApp == this) {
3036 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
3037 "Removing focused app token:%s displayId=%d", this,
3038 dc.getDisplayId());
3039 dc.setFocusedApp(null);
3040 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3041 }
3042 if (mLetterbox != null) {
3043 mLetterbox.destroy();
3044 mLetterbox = null;
3045 }
3046
3047 if (!delayed) {
3048 updateReportedVisibilityLocked();
3049 }
3050
3051 // Reset the last saved PiP snap fraction on removal.
3052 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
3053
3054 mRemovingFromDisplay = false;
3055 }
3056
3057 /**
3058 * Returns true if the new child window we are adding to this token is considered greater than
3059 * the existing child window in this token in terms of z-order.
3060 */
3061 @Override
3062 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
3063 WindowState existingWindow) {
3064 final int type1 = newWindow.mAttrs.type;
3065 final int type2 = existingWindow.mAttrs.type;
3066
3067 // Base application windows should be z-ordered BELOW all other windows in the app token.
3068 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
3069 return false;
3070 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
3071 return true;
3072 }
3073
3074 // Starting windows should be z-ordered ABOVE all other windows in the app token.
3075 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
3076 return true;
3077 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
3078 return false;
3079 }
3080
3081 // Otherwise the new window is greater than the existing window.
3082 return true;
3083 }
3084
3085 /**
3086 * @return {@code true} if starting window is in app's hierarchy.
3087 */
3088 boolean hasStartingWindow() {
3089 if (startingDisplayed || mStartingData != null) {
3090 return true;
3091 }
3092 for (int i = mChildren.size() - 1; i >= 0; i--) {
3093 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
3094 return true;
3095 }
3096 }
3097 return false;
3098 }
3099
3100 boolean isLastWindow(WindowState win) {
3101 return mChildren.size() == 1 && mChildren.get(0) == win;
3102 }
3103
3104 @Override
3105 void addWindow(WindowState w) {
3106 super.addWindow(w);
3107
3108 boolean gotReplacementWindow = false;
3109 for (int i = mChildren.size() - 1; i >= 0; i--) {
3110 final WindowState candidate = mChildren.get(i);
3111 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
3112 }
3113
3114 // if we got a replacement window, reset the timeout to give drawing more time
3115 if (gotReplacementWindow) {
3116 mWmService.scheduleWindowReplacementTimeouts(this);
3117 }
3118 checkKeyguardFlagsChanged();
3119 }
3120
3121 @Override
3122 void removeChild(WindowState child) {
3123 if (!mChildren.contains(child)) {
3124 // This can be true when testing.
3125 return;
3126 }
3127 super.removeChild(child);
3128 checkKeyguardFlagsChanged();
3129 updateLetterboxSurface(child);
3130 }
3131
3132 private boolean waitingForReplacement() {
3133 for (int i = mChildren.size() - 1; i >= 0; i--) {
3134 final WindowState candidate = mChildren.get(i);
3135 if (candidate.waitingForReplacement()) {
3136 return true;
3137 }
3138 }
3139 return false;
3140 }
3141
3142 void onWindowReplacementTimeout() {
3143 for (int i = mChildren.size() - 1; i >= 0; --i) {
3144 (mChildren.get(i)).onWindowReplacementTimeout();
3145 }
3146 }
3147
3148 void setAppLayoutChanges(int changes, String reason) {
3149 if (!mChildren.isEmpty()) {
3150 final DisplayContent dc = getDisplayContent();
3151 dc.pendingLayoutChanges |= changes;
3152 if (DEBUG_LAYOUT_REPEATS) {
3153 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
3154 }
3155 }
3156 }
3157
3158 void removeReplacedWindowIfNeeded(WindowState replacement) {
3159 for (int i = mChildren.size() - 1; i >= 0; i--) {
3160 final WindowState win = mChildren.get(i);
3161 if (win.removeReplacedWindowIfNeeded(replacement)) {
3162 return;
3163 }
3164 }
3165 }
3166
3167 boolean transferStartingWindow(IBinder transferFrom) {
3168 final ActivityRecord fromActivity = getDisplayContent().getActivityRecord(transferFrom);
3169 if (fromActivity == null) {
3170 return false;
3171 }
3172
3173 final WindowState tStartingWindow = fromActivity.startingWindow;
3174 if (tStartingWindow != null && fromActivity.startingSurface != null) {
3175 // In this case, the starting icon has already been displayed, so start
3176 // letting windows get shown immediately without any more transitions.
3177 getDisplayContent().mSkipAppTransitionAnimation = true;
3178
3179 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
3180 + " from %s to %s", tStartingWindow, fromActivity, this);
3181
3182 final long origId = Binder.clearCallingIdentity();
3183 try {
3184 // Transfer the starting window over to the new token.
3185 mStartingData = fromActivity.mStartingData;
3186 startingSurface = fromActivity.startingSurface;
3187 startingDisplayed = fromActivity.startingDisplayed;
3188 fromActivity.startingDisplayed = false;
3189 startingWindow = tStartingWindow;
3190 reportedVisible = fromActivity.reportedVisible;
3191 fromActivity.mStartingData = null;
3192 fromActivity.startingSurface = null;
3193 fromActivity.startingWindow = null;
3194 fromActivity.startingMoved = true;
3195 tStartingWindow.mToken = this;
3196 tStartingWindow.mActivityRecord = this;
3197
3198 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3199 "Removing starting %s from %s", tStartingWindow, fromActivity);
3200 fromActivity.removeChild(tStartingWindow);
3201 fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003202 fromActivity.mHiddenSetFromTransferredStartingWindow = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003203 addWindow(tStartingWindow);
3204
3205 // Propagate other interesting state between the tokens. If the old token is displayed,
3206 // we should immediately force the new one to be displayed. If it is animating, we need
3207 // to move that animation to the new one.
3208 if (fromActivity.allDrawn) {
3209 allDrawn = true;
3210 deferClearAllDrawn = fromActivity.deferClearAllDrawn;
3211 }
3212 if (fromActivity.firstWindowDrawn) {
3213 firstWindowDrawn = true;
3214 }
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003215 if (!fromActivity.isHidden()) {
3216 setHidden(false);
Issei Suzuki430a1112019-11-14 16:20:52 +01003217 hiddenRequested = false;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003218 mHiddenSetFromTransferredStartingWindow = true;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003219 }
Issei Suzukie63eac72019-11-14 15:59:15 +01003220 setClientHidden(fromActivity.mClientHidden);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003221
3222 transferAnimation(fromActivity);
3223
3224 // When transferring an animation, we no longer need to apply an animation to the
3225 // the token we transfer the animation over. Thus, set this flag to indicate we've
3226 // transferred the animation.
3227 mUseTransferredAnimation = true;
3228
3229 mWmService.updateFocusedWindowLocked(
3230 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
3231 getDisplayContent().setLayoutNeeded();
3232 mWmService.mWindowPlacerLocked.performSurfacePlacement();
3233 } finally {
3234 Binder.restoreCallingIdentity(origId);
3235 }
3236 return true;
3237 } else if (fromActivity.mStartingData != null) {
3238 // The previous app was getting ready to show a
3239 // starting window, but hasn't yet done so. Steal it!
3240 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
3241 "Moving pending starting from %s to %s", fromActivity, this);
3242 mStartingData = fromActivity.mStartingData;
3243 fromActivity.mStartingData = null;
3244 fromActivity.startingMoved = true;
3245 scheduleAddStartingWindow();
3246 return true;
3247 }
3248
3249 // TODO: Transfer thumbnail
3250
3251 return false;
3252 }
3253
3254 /**
3255 * Tries to transfer the starting window from a token that's above ourselves in the task but
3256 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
3257 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
3258 * immediately finishes after, so we have to transfer T to M.
3259 */
3260 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003261 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
3262 final ActivityRecord fromActivity = task.mChildren.get(i);
3263 if (fromActivity == this) {
3264 return;
3265 }
Issei Suzuki430a1112019-11-14 16:20:52 +01003266 if (fromActivity.hiddenRequested && transferStartingWindow(fromActivity.token)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003267 return;
3268 }
3269 }
3270 }
3271
3272 void checkKeyguardFlagsChanged() {
3273 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
3274 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
3275 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
3276 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
3277 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
3278 getDisplayContent().getDisplayId());
3279 }
3280 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
3281 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
3282 }
3283
3284 boolean containsDismissKeyguardWindow() {
3285 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
3286 // entirety of the relaunch.
3287 if (isRelaunching()) {
3288 return mLastContainsDismissKeyguardWindow;
3289 }
3290
3291 for (int i = mChildren.size() - 1; i >= 0; i--) {
3292 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
3293 return true;
3294 }
3295 }
3296 return false;
3297 }
3298
3299 boolean containsShowWhenLockedWindow() {
3300 // When we are relaunching, it is possible for us to be unfrozen before our previous
3301 // windows have been added back. Using the cached value ensures that our previous
3302 // showWhenLocked preference is honored until relaunching is complete.
3303 if (isRelaunching()) {
3304 return mLastContainsShowWhenLockedWindow;
3305 }
3306
3307 for (int i = mChildren.size() - 1; i >= 0; i--) {
3308 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
3309 return true;
3310 }
3311 }
3312
3313 return false;
3314 }
3315
3316 void setShowWhenLocked(boolean showWhenLocked) {
3317 mShowWhenLocked = showWhenLocked;
3318 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
3319 0 /* configChanges */, false /* preserveWindows */);
3320 }
3321
3322 void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
3323 mInheritShownWhenLocked = inheritShowWhenLocked;
3324 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
3325 0 /* configChanges */, false /* preserveWindows */);
3326 }
3327
3328 /**
3329 * @return {@code true} if the activity windowing mode is not
3330 * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
3331 * contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
3332 * activity has set {@link #mShowWhenLocked}, or b) if the activity has set
3333 * {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
3334 * conditions a) above.
3335 * Multi-windowing mode will be exited if {@code true} is returned.
3336 */
3337 boolean canShowWhenLocked() {
3338 if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
3339 return true;
3340 } else if (mInheritShownWhenLocked) {
3341 final ActivityRecord r = getActivityBelow();
3342 return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
3343 || r.containsShowWhenLockedWindow());
3344 } else {
3345 return false;
3346 }
3347 }
3348
3349 /**
3350 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3351 * showing windows during transitions in case we have windows that have wide-color-gamut
3352 * color mode set to avoid jank in the middle of the transition.
3353 */
3354 boolean canShowWindows() {
lumark9bca6b42019-10-17 18:35:22 +08003355 return allDrawn && !(isAnimating() && hasNonDefaultColorWindow());
Garfield Tane8d84ab2019-10-11 09:49:40 -07003356 }
3357
3358 /**
3359 * @return true if we have a window that has a non-default color mode set; false otherwise.
3360 */
3361 private boolean hasNonDefaultColorWindow() {
3362 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3363 true /* topToBottom */);
3364 }
3365
3366 /**
3367 * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
3368 * such activity exists.
3369 */
3370 @Nullable
3371 private ActivityRecord getActivityBelow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003372 final int pos = task.mChildren.indexOf(this);
3373 if (pos == -1) {
3374 throw new IllegalStateException("Activity not found in its task");
3375 }
3376 return pos == 0 ? null : task.getChildAt(pos - 1);
3377 }
3378
3379 WindowState getImeTargetBelowWindow(WindowState w) {
3380 final int index = mChildren.indexOf(w);
3381 if (index > 0) {
3382 final WindowState target = mChildren.get(index - 1);
3383 if (target.canBeImeTarget()) {
3384 return target;
3385 }
3386 }
3387 return null;
3388 }
3389
3390 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
3391 WindowState candidate = null;
3392 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
3393 final WindowState w = mChildren.get(i);
3394 if (w.mRemoved) {
3395 continue;
3396 }
3397 if (candidate == null) {
3398 candidate = w;
3399 }
3400 }
3401 return candidate;
3402 }
3403
3404 @Override
3405 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
3406 // For legacy reasons we process the TaskStack.mExitingActivities first in DisplayContent
3407 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
3408 // TODO: Investigate if we need to continue to do this or if we can just process them
3409 // in-order.
3410 if (mIsExiting && !waitingForReplacement()) {
3411 return false;
3412 }
3413 return forAllWindowsUnchecked(callback, traverseTopToBottom);
3414 }
3415
Garfield Tane8d84ab2019-10-11 09:49:40 -07003416 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
3417 boolean traverseTopToBottom) {
3418 return super.forAllWindows(callback, traverseTopToBottom);
3419 }
3420
3421 @Override
lumark9bca6b42019-10-17 18:35:22 +08003422 boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
3423 return callback.apply(this);
3424 }
3425
3426 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07003427 protected void setLayer(Transaction t, int layer) {
3428 if (!mSurfaceAnimator.hasLeash()) {
3429 t.setLayer(mSurfaceControl, layer);
3430 }
3431 }
3432
3433 @Override
3434 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
3435 if (!mSurfaceAnimator.hasLeash()) {
3436 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
3437 }
3438 }
3439
3440 @Override
3441 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
3442 if (!mSurfaceAnimator.hasLeash()) {
3443 t.reparent(mSurfaceControl, newParent);
3444 }
3445 }
3446
Louis Changcdec0802019-11-11 11:45:07 +08003447 void logStartActivity(int tag, Task task) {
Andrii Kulian79d67982019-08-19 11:56:16 -07003448 final Uri data = intent.getData();
3449 final String strData = data != null ? data.toSafeString() : null;
3450
3451 EventLog.writeEvent(tag,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07003452 mUserId, System.identityHashCode(this), task.mTaskId,
Andrii Kulian79d67982019-08-19 11:56:16 -07003453 shortComponentName, intent.getAction(),
3454 intent.getType(), strData, intent.getFlags());
3455 }
3456
Dianne Hackborn7e269642010-08-25 19:50:20 -07003457 UriPermissionOwner getUriPermissionsLocked() {
3458 if (uriPermissions == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003459 uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
Dianne Hackborn7e269642010-08-25 19:50:20 -07003460 }
3461 return uriPermissions;
3462 }
3463
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003464 void addResultLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003465 int requestCode, int resultCode,
3466 Intent resultData) {
3467 ActivityResult r = new ActivityResult(from, resultWho,
John Spurlock8a985d22014-02-25 09:40:05 -05003468 requestCode, resultCode, resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 if (results == null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003470 results = new ArrayList<ResultInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 }
3472 results.add(r);
3473 }
3474
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003475 void removeResultsLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 int requestCode) {
3477 if (results != null) {
3478 for (int i=results.size()-1; i>=0; i--) {
3479 ActivityResult r = (ActivityResult)results.get(i);
3480 if (r.mFrom != from) continue;
3481 if (r.mResultWho == null) {
3482 if (resultWho != null) continue;
3483 } else {
3484 if (!r.mResultWho.equals(resultWho)) continue;
3485 }
3486 if (r.mRequestCode != requestCode) continue;
3487
3488 results.remove(i);
3489 }
3490 }
3491 }
3492
Andrii Kulian79d67982019-08-19 11:56:16 -07003493 void sendResult(int callingUid, String resultWho, int requestCode, int resultCode,
3494 Intent data) {
3495 if (callingUid > 0) {
3496 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3497 data, getUriPermissionsLocked(), mUserId);
3498 }
3499
3500 if (DEBUG_RESULTS) {
3501 Slog.v(TAG, "Send activity result to " + this
3502 + " : who=" + resultWho + " req=" + requestCode
3503 + " res=" + resultCode + " data=" + data);
3504 }
3505 if (isState(RESUMED) && attachedToProcess()) {
3506 try {
3507 final ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3508 list.add(new ResultInfo(resultWho, requestCode, resultCode, data));
3509 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3510 ActivityResultItem.obtain(list));
3511 return;
3512 } catch (Exception e) {
3513 Slog.w(TAG, "Exception thrown sending result to " + this, e);
3514 }
3515 }
3516
3517 addResultLocked(null /* from */, resultWho, requestCode, resultCode, data);
3518 }
3519
Andrii Kulian21713ac2016-10-12 22:05:05 -07003520 private void addNewIntentLocked(ReferrerIntent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 if (newIntents == null) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003522 newIntents = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 }
3524 newIntents.add(intent);
3525 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07003526
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003527 final boolean isSleeping() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003528 final ActivityStack stack = getActivityStack();
3529 return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003530 }
3531
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003532 /**
3533 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3534 * method will be called at the proper time.
3535 */
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003536 final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
Dianne Hackborn514074f2013-02-11 10:52:46 -08003537 // The activity now gets access to the data associated with this Intent.
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003538 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3539 intent, getUriPermissionsLocked(), mUserId);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003540 final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
Craig Mautner86d67a42013-05-14 10:34:38 -07003541 boolean unsent = true;
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003542 final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
Wale Ogunwale826c7062016-09-13 08:25:54 -07003543
3544 // We want to immediately deliver the intent to the activity if:
Wale Ogunwale03f7e9e2016-09-22 09:04:09 -07003545 // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
3546 // the user to see the visual effects caused by the intent delivery now.
Wale Ogunwale826c7062016-09-13 08:25:54 -07003547 // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07003548 if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
3549 && attachedToProcess()) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003550 try {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003551 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
3552 ar.add(rintent);
Louis Changea203cd2019-07-01 12:39:31 +08003553 // Making sure the client state is RESUMED after transaction completed and doing
3554 // so only if activity is currently RESUMED. Otherwise, client may have extra
3555 // life-cycle calls to RESUMED (and PAUSED later).
Louis Chang92d16522019-02-27 12:56:18 +08003556 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Louis Changea203cd2019-07-01 12:39:31 +08003557 NewIntentItem.obtain(ar, mState == RESUMED));
Craig Mautner86d67a42013-05-14 10:34:38 -07003558 unsent = false;
Dianne Hackborn39792d22010-08-19 18:01:52 -07003559 } catch (RemoteException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003560 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003561 } catch (NullPointerException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003562 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003563 }
3564 }
Craig Mautner86d67a42013-05-14 10:34:38 -07003565 if (unsent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003566 addNewIntentLocked(rintent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003567 }
3568 }
3569
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003570 void updateOptionsLocked(ActivityOptions options) {
3571 if (options != null) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003572 if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003573 if (pendingOptions != null) {
3574 pendingOptions.abort();
3575 }
3576 pendingOptions = options;
3577 }
3578 }
3579
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003580 void applyOptionsLocked() {
George Mount2c92c972014-03-20 09:38:23 -07003581 if (pendingOptions != null
Ruben Brunkf53497c2017-03-27 20:26:17 -07003582 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003583 if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003584 applyOptionsLocked(pendingOptions, intent);
chaviw82a0ba82018-03-15 14:26:29 -07003585 if (task == null) {
3586 clearOptionsLocked(false /* withAbort */);
3587 } else {
3588 // This will clear the options for all the ActivityRecords for this Task.
3589 task.clearAllPendingOptions();
3590 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003591 }
3592 }
3593
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003594 /**
3595 * Apply override app transition base on options & animation type.
3596 */
3597 void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
3598 final int animationType = pendingOptions.getAnimationType();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003599 final DisplayContent displayContent = getDisplayContent();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003600 switch (animationType) {
3601 case ANIM_CUSTOM:
3602 displayContent.mAppTransition.overridePendingAppTransition(
3603 pendingOptions.getPackageName(),
3604 pendingOptions.getCustomEnterResId(),
3605 pendingOptions.getCustomExitResId(),
3606 pendingOptions.getOnAnimationStartListener());
3607 break;
3608 case ANIM_CLIP_REVEAL:
3609 displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
3610 pendingOptions.getStartX(), pendingOptions.getStartY(),
3611 pendingOptions.getWidth(), pendingOptions.getHeight());
3612 if (intent.getSourceBounds() == null) {
3613 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3614 pendingOptions.getStartY(),
3615 pendingOptions.getStartX() + pendingOptions.getWidth(),
3616 pendingOptions.getStartY() + pendingOptions.getHeight()));
3617 }
3618 break;
3619 case ANIM_SCALE_UP:
3620 displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
3621 pendingOptions.getStartX(), pendingOptions.getStartY(),
3622 pendingOptions.getWidth(), pendingOptions.getHeight());
3623 if (intent.getSourceBounds() == null) {
3624 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3625 pendingOptions.getStartY(),
3626 pendingOptions.getStartX() + pendingOptions.getWidth(),
3627 pendingOptions.getStartY() + pendingOptions.getHeight()));
3628 }
3629 break;
3630 case ANIM_THUMBNAIL_SCALE_UP:
3631 case ANIM_THUMBNAIL_SCALE_DOWN:
3632 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
3633 final GraphicBuffer buffer = pendingOptions.getThumbnail();
3634 displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
3635 pendingOptions.getStartX(), pendingOptions.getStartY(),
3636 pendingOptions.getOnAnimationStartListener(),
3637 scaleUp);
3638 if (intent.getSourceBounds() == null && buffer != null) {
3639 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3640 pendingOptions.getStartY(),
3641 pendingOptions.getStartX() + buffer.getWidth(),
3642 pendingOptions.getStartY() + buffer.getHeight()));
3643 }
3644 break;
3645 case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
3646 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
3647 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
3648 final IAppTransitionAnimationSpecsFuture specsFuture =
3649 pendingOptions.getSpecsFuture();
3650 if (specsFuture != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003651 displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
3652 specsFuture, pendingOptions.getOnAnimationStartListener(),
3653 animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
3654 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
3655 && specs != null) {
3656 displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
3657 specs, pendingOptions.getOnAnimationStartListener(),
3658 pendingOptions.getAnimationFinishedListener(), false);
3659 } else {
3660 displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
3661 pendingOptions.getThumbnail(),
3662 pendingOptions.getStartX(), pendingOptions.getStartY(),
3663 pendingOptions.getWidth(), pendingOptions.getHeight(),
3664 pendingOptions.getOnAnimationStartListener(),
3665 (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
3666 if (intent.getSourceBounds() == null) {
3667 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3668 pendingOptions.getStartY(),
3669 pendingOptions.getStartX() + pendingOptions.getWidth(),
3670 pendingOptions.getStartY() + pendingOptions.getHeight()));
3671 }
3672 }
3673 break;
3674 case ANIM_OPEN_CROSS_PROFILE_APPS:
3675 displayContent.mAppTransition
3676 .overridePendingAppTransitionStartCrossProfileApps();
3677 break;
3678 case ANIM_REMOTE_ANIMATION:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003679 displayContent.mAppTransition.overridePendingAppTransitionRemote(
3680 pendingOptions.getRemoteAnimationAdapter());
3681 break;
3682 case ANIM_NONE:
Louis Chang477e93e2019-04-24 18:35:20 +08003683 case ANIM_UNDEFINED:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003684 break;
3685 default:
3686 Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
3687 break;
3688 }
3689 }
3690
Garfield Tane8d84ab2019-10-11 09:49:40 -07003691 void clearAllDrawn() {
3692 allDrawn = false;
3693 deferClearAllDrawn = false;
3694 }
3695
3696 /**
3697 * Returns whether the drawn window states of this {@link ActivityRecord} has considered every
3698 * child {@link WindowState}. A child is considered if it has been passed into
3699 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
3700 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
3701 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
3702 *
3703 * @return {@code true} If all children have been considered, {@code false}.
3704 */
3705 private boolean allDrawnStatesConsidered() {
3706 for (int i = mChildren.size() - 1; i >= 0; --i) {
3707 final WindowState child = mChildren.get(i);
3708 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
3709 return false;
3710 }
3711 }
3712 return true;
3713 }
3714
3715 /**
3716 * Determines if the token has finished drawing. This should only be called from
3717 * {@link DisplayContent#applySurfaceChangesTransaction}
3718 */
3719 void updateAllDrawn() {
3720 if (!allDrawn) {
3721 // Number of drawn windows can be less when a window is being relaunched, wait for
3722 // all windows to be launched and drawn for this token be considered all drawn.
3723 final int numInteresting = mNumInterestingWindows;
3724
3725 // We must make sure that all present children have been considered (determined by
3726 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
3727 // drawn.
3728 if (numInteresting > 0 && allDrawnStatesConsidered()
3729 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
3730 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
3731 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
3732 allDrawn = true;
3733 // Force an additional layout pass where
3734 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
3735 if (mDisplayContent != null) {
3736 mDisplayContent.setLayoutNeeded();
3737 }
3738 mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
3739
3740 // Notify the pinned stack upon all windows drawn. If there was an animation in
3741 // progress then this signal will resume that animation.
Louis Changdc077272019-11-12 16:52:56 +08003742 final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003743 if (pinnedStack != null) {
3744 pinnedStack.onAllWindowsDrawn();
3745 }
3746 }
3747 }
3748 }
3749
Adam Powellcfbe9be2013-11-06 14:58:58 -08003750 ActivityOptions getOptionsForTargetActivityLocked() {
3751 return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
3752 }
3753
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003754 void clearOptionsLocked() {
chaviw82a0ba82018-03-15 14:26:29 -07003755 clearOptionsLocked(true /* withAbort */);
3756 }
3757
3758 void clearOptionsLocked(boolean withAbort) {
3759 if (withAbort && pendingOptions != null) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003760 pendingOptions.abort();
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003761 }
chaviw82a0ba82018-03-15 14:26:29 -07003762 pendingOptions = null;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003763 }
3764
Jorim Jaggi346702a2019-05-08 17:49:33 +02003765 ActivityOptions takeOptionsLocked(boolean fromClient) {
3766 if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
3767 + Debug.getCallers(6));
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003768 ActivityOptions opts = pendingOptions;
Jorim Jaggi346702a2019-05-08 17:49:33 +02003769
3770 // If we are trying to take activity options from the client, do not null it out if it's a
3771 // remote animation as the client doesn't need it ever. This is a workaround when client is
3772 // faster to take the options than we are to resume the next activity.
3773 // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
3774 // timing somehow
3775 if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
3776 pendingOptions = null;
3777 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003778 return opts;
3779 }
3780
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003781 void removeUriPermissionsLocked() {
Dianne Hackborn7e269642010-08-25 19:50:20 -07003782 if (uriPermissions != null) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003783 uriPermissions.removeUriPermissions();
Dianne Hackborn7e269642010-08-25 19:50:20 -07003784 uriPermissions = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003785 }
3786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787
3788 void pauseKeyDispatchingLocked() {
3789 if (!keysPaused) {
3790 keysPaused = true;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003791
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003792 if (getDisplayContent() != null) {
3793 getDisplayContent().getInputMonitor().pauseDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 }
3796 }
3797
3798 void resumeKeyDispatchingLocked() {
3799 if (keysPaused) {
3800 keysPaused = false;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003801
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003802 if (getDisplayContent() != null) {
3803 getDisplayContent().getInputMonitor().resumeDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 }
3806 }
3807
Jorim Jaggie7d2b852017-08-28 17:55:15 +02003808 private void updateTaskDescription(CharSequence description) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07003809 task.lastDescription = description;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003810 }
3811
Wale Ogunwaleec950642017-04-25 07:44:21 -07003812 void setDeferHidingClient(boolean deferHidingClient) {
3813 if (mDeferHidingClient == deferHidingClient) {
3814 return;
3815 }
3816 mDeferHidingClient = deferHidingClient;
Issei Suzuki430a1112019-11-14 16:20:52 +01003817 if (!mDeferHidingClient && !visible) {
Wale Ogunwaleec950642017-04-25 07:44:21 -07003818 // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
3819 // update the visibility.
3820 setVisibility(false);
3821 }
Wale Ogunwale89973222017-04-23 18:39:45 -07003822 }
3823
Garfield Tane8d84ab2019-10-11 09:49:40 -07003824 @Override
3825 boolean isVisible() {
3826 // If the activity isn't hidden then it is considered visible and there is no need to check
3827 // its children windows to see if they are visible.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003828 return !isHidden();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003829 }
3830
Wale Ogunwaleec950642017-04-25 07:44:21 -07003831 void setVisibility(boolean visible) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003832 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003833 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
3834 + appToken);
3835 return;
3836 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003837 setVisibility(visible, mDeferHidingClient);
Riddle Hsua0022cd2019-09-09 21:12:41 +08003838 mAtmService.addWindowLayoutReasons(
3839 ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
Bryce Lee2a3cc462017-10-27 10:57:35 -07003840 mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
Issei Suzuki430a1112019-11-14 16:20:52 +01003841 }
3842
3843 // TODO: Look into merging with #commitVisibility()
3844 void setVisible(boolean newVisible) {
3845 visible = newVisible;
3846 mDeferHidingClient = !visible && mDeferHidingClient;
3847 setVisibility(visible);
Andrii Kulian21713ac2016-10-12 22:05:05 -07003848 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
3849 }
3850
Garfield Tane8d84ab2019-10-11 09:49:40 -07003851 void setVisibility(boolean visible, boolean deferHidingClient) {
3852 final AppTransition appTransition = getDisplayContent().mAppTransition;
3853
3854 // Don't set visibility to false if we were already not visible. This prevents WM from
3855 // adding the app to the closing app list which doesn't make sense for something that is
3856 // already not visible. However, set visibility to true even if we are already visible.
3857 // This makes sure the app is added to the opening apps list so that the right
3858 // transition can be selected.
3859 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
3860 // concept of setting visibility...
Issei Suzuki430a1112019-11-14 16:20:52 +01003861 if (!visible && hiddenRequested) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003862
3863 if (!deferHidingClient && mLastDeferHidingClient) {
3864 // We previously deferred telling the client to hide itself when visibility was
3865 // initially set to false. Now we would like it to hide, so go ahead and set it.
3866 mLastDeferHidingClient = deferHidingClient;
Issei Suzukie63eac72019-11-14 15:59:15 +01003867 setClientHidden(true);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003868 }
3869 return;
3870 }
3871
3872 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzuki430a1112019-11-14 16:20:52 +01003873 "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
3874 appToken, visible, appTransition, isHidden(), hiddenRequested,
Garfield Tane8d84ab2019-10-11 09:49:40 -07003875 Debug.getCallers(6));
3876
3877 final DisplayContent displayContent = getDisplayContent();
3878 displayContent.mOpeningApps.remove(this);
3879 displayContent.mClosingApps.remove(this);
3880 if (isInChangeTransition()) {
3881 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3882 }
3883 displayContent.mChangingApps.remove(this);
3884 waitingToShow = false;
Issei Suzuki430a1112019-11-14 16:20:52 +01003885 hiddenRequested = !visible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003886 mLastDeferHidingClient = deferHidingClient;
3887
3888 if (!visible) {
3889 // If the app is dead while it was visible, we kept its dead window on screen.
3890 // Now that the app is going invisible, we can remove it. It will be restarted
3891 // if made visible again.
3892 removeDeadWindows();
3893 } else {
3894 if (!appTransition.isTransitionSet()
3895 && appTransition.isReady()) {
3896 // Add the app mOpeningApps if transition is unset but ready. This means
3897 // we're doing a screen freeze, and the unfreeze will wait for all opening
3898 // apps to be ready.
3899 displayContent.mOpeningApps.add(this);
3900 }
3901 startingMoved = false;
3902 // If the token is currently hidden (should be the common case), or has been
3903 // stopped, then we need to set up to wait for its windows to be ready.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003904 if (isHidden() || mAppStopped) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003905 clearAllDrawn();
3906
3907 // If the app was already visible, don't reset the waitingToShow state.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003908 if (isHidden()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003909 waitingToShow = true;
3910
3911 // If the client isn't hidden, we don't need to reset the drawing state.
Issei Suzukie63eac72019-11-14 15:59:15 +01003912 if (isClientHidden()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003913 // Let's reset the draw state in order to prevent the starting window to be
3914 // immediately dismissed when the app still has the surface.
3915 forAllWindows(w -> {
3916 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
3917 w.mWinAnimator.resetDrawState();
3918
3919 // Force add to mResizingWindows, so that we are guaranteed to get
3920 // another reportDrawn callback.
3921 w.resetLastContentInsets();
3922 }
3923 }, true /* traverseTopToBottom */);
3924 }
3925 }
3926 }
3927
3928 // In the case where we are making an app visible but holding off for a transition,
3929 // we still need to tell the client to make its windows visible so they get drawn.
3930 // Otherwise, we will wait on performing the transition until all windows have been
3931 // drawn, they never will be, and we are sad.
Issei Suzukie63eac72019-11-14 15:59:15 +01003932 setClientHidden(false);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003933
3934 requestUpdateWallpaperIfNeeded();
3935
3936 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
3937 mAppStopped = false;
3938
3939 transferStartingWindowFromHiddenAboveTokenIfNeeded();
3940 }
3941
3942 // If we are preparing an app transition, then delay changing
3943 // the visibility of this token until we execute that transition.
3944 if (okToAnimate() && appTransition.isTransitionSet()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003945 if (visible) {
3946 displayContent.mOpeningApps.add(this);
3947 mEnteringAnimation = true;
3948 } else {
3949 displayContent.mClosingApps.add(this);
3950 mEnteringAnimation = false;
3951 }
3952 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
3953 // We're launchingBehind, add the launching activity to mOpeningApps.
3954 final WindowState win = getDisplayContent().findFocusedWindow();
3955 if (win != null) {
3956 final ActivityRecord focusedActivity = win.mActivityRecord;
3957 if (focusedActivity != null) {
3958 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
3959 "TRANSIT_TASK_OPEN_BEHIND, adding %s to mOpeningApps",
3960 focusedActivity);
3961
3962 // Force animation to be loaded.
3963 displayContent.mOpeningApps.add(focusedActivity);
3964 }
3965 }
3966 }
3967 return;
3968 }
3969
3970 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
3971 updateReportedVisibilityLocked();
3972 }
3973
3974 boolean commitVisibility(WindowManager.LayoutParams lp,
3975 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
3976
3977 boolean delayed = false;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003978 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
Garfield Tane8d84ab2019-10-11 09:49:40 -07003979 // been set by the app now.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003980 mHiddenSetFromTransferredStartingWindow = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003981
3982 // Allow for state changes and animation to be applied if:
3983 // * token is transitioning visibility state
3984 // * or the token was marked as hidden and is exiting before we had a chance to play the
3985 // transition animation
3986 // * or this is an opening app and windows are being replaced
3987 // * or the token is the opening app and visible while opening task behind existing one.
3988 final DisplayContent displayContent = getDisplayContent();
3989 boolean visibilityChanged = false;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003990 if (isHidden() == visible || (isHidden() && mIsExiting)
Garfield Tane8d84ab2019-10-11 09:49:40 -07003991 || (visible && waitingForReplacement())
3992 || (visible && displayContent.mOpeningApps.contains(this)
3993 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
3994 final AccessibilityController accessibilityController =
3995 mWmService.mAccessibilityController;
3996 boolean changed = false;
3997 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003998 "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
Garfield Tane8d84ab2019-10-11 09:49:40 -07003999 performLayout);
4000
4001 boolean runningAppAnimation = false;
4002
4003 if (transit != WindowManager.TRANSIT_UNSET) {
4004 if (mUseTransferredAnimation) {
lumark9bca6b42019-10-17 18:35:22 +08004005 runningAppAnimation = isAnimating();
lumark19a5d2e2019-10-11 16:19:30 +08004006 } else if (applyAnimation(lp, transit, visible, isVoiceInteraction)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004007 runningAppAnimation = true;
4008 }
4009 delayed = runningAppAnimation;
4010 final WindowState window = findMainWindow();
4011 if (window != null && accessibilityController != null) {
4012 accessibilityController.onAppWindowTransitionLocked(window, transit);
4013 }
4014 changed = true;
4015 }
4016
4017 final int windowsCount = mChildren.size();
4018 for (int i = 0; i < windowsCount; i++) {
4019 final WindowState win = mChildren.get(i);
4020 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
4021 }
4022
Issei Suzuki7b9e2572019-11-14 16:19:54 +01004023 setHidden(!visible);
Issei Suzuki430a1112019-11-14 16:20:52 +01004024 hiddenRequested = !visible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07004025 visibilityChanged = true;
4026 if (!visible) {
4027 stopFreezingScreen(true, true);
4028 } else {
4029 // If we are being set visible, and the starting window is not yet displayed,
4030 // then make sure it doesn't get displayed.
4031 if (startingWindow != null && !startingWindow.isDrawnLw()) {
4032 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
4033 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
4034 }
4035
4036 // We are becoming visible, so better freeze the screen with the windows that are
4037 // getting visible so we also wait for them.
4038 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
4039 }
4040
4041 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzuki430a1112019-11-14 16:20:52 +01004042 "commitVisibility: %s: hidden=%b hiddenRequested=%b", this,
4043 isHidden(), hiddenRequested);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004044
4045 if (changed) {
4046 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
4047 if (performLayout) {
4048 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4049 false /*updateInputWindows*/);
4050 mWmService.mWindowPlacerLocked.performSurfacePlacement();
4051 }
4052 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
4053 }
4054 }
4055 mUseTransferredAnimation = false;
4056
lumark9bca6b42019-10-17 18:35:22 +08004057 delayed = isAnimating(CHILDREN);
4058 if (!delayed) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004059 // We aren't animating anything, but exiting windows rely on the animation finished
4060 // callback being called in case the ActivityRecord was pretending to be animating,
4061 // which we might have done because we were in closing/opening apps list.
4062 onAnimationFinished();
4063 }
4064
Garfield Tane8d84ab2019-10-11 09:49:40 -07004065 if (visibilityChanged) {
4066 if (visible && !delayed) {
4067 // The token was made immediately visible, there will be no entrance animation.
4068 // We need to inform the client the enter animation was finished.
4069 mEnteringAnimation = true;
4070 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
4071 token);
4072 }
4073
4074 // If we're becoming visible, immediately change client visibility as well. there seem
4075 // to be some edge cases where we change our visibility but client visibility never gets
4076 // updated.
4077 // If we're becoming invisible, update the client visibility if we are not running an
4078 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
lumark9bca6b42019-10-17 18:35:22 +08004079 if (visible || !isAnimating()) {
Issei Suzukie63eac72019-11-14 15:59:15 +01004080 setClientHidden(!visible);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004081 }
4082
4083 if (!displayContent.mClosingApps.contains(this)
4084 && !displayContent.mOpeningApps.contains(this)) {
4085 // The token is not closing nor opening, so even if there is an animation set, that
4086 // doesn't mean that it goes through the normal app transition cycle so we have
4087 // to inform the docked controller about visibility change.
4088 // TODO(multi-display): notify docked divider on all displays where visibility was
4089 // affected.
4090 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
4091
4092 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
4093 // will not be taken.
4094 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
4095 }
4096
4097 // If we are hidden but there is no delay needed we immediately
4098 // apply the Surface transaction so that the ActivityManager
4099 // can have some guarantee on the Surface state following
4100 // setting the visibility. This captures cases like dismissing
4101 // the docked or pinned stack where there is no app transition.
4102 //
4103 // In the case of a "Null" animation, there will be
4104 // no animation but there will still be a transition set.
4105 // We still need to delay hiding the surface such that it
4106 // can be synchronized with showing the next surface in the transition.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01004107 if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004108 SurfaceControl.openTransaction();
4109 for (int i = mChildren.size() - 1; i >= 0; i--) {
4110 mChildren.get(i).mWinAnimator.hide("immediately hidden");
4111 }
4112 SurfaceControl.closeTransaction();
4113 }
4114 }
4115
4116 return delayed;
4117 }
4118
4119 @Override
Issei Suzuki7b9e2572019-11-14 16:19:54 +01004120 void setHidden(boolean hidden) {
4121 super.setHidden(hidden);
4122 scheduleAnimation();
4123 }
4124
Garfield Tane8d84ab2019-10-11 09:49:40 -07004125 /**
4126 * See {@link Activity#setDisablePreviewScreenshots}.
4127 */
4128 void setDisablePreviewScreenshots(boolean disable) {
4129 mDisablePreviewScreenshots = disable;
4130 }
4131
4132 /**
4133 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
4134 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
4135 * we can't take a snapshot for other reasons, for example, if we have a secure window.
4136 *
4137 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
4138 * screenshot.
4139 */
4140 boolean shouldUseAppThemeSnapshot() {
4141 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
4142 true /* topToBottom */);
4143 }
4144
4145 /**
4146 * Sets whether the current launch can turn the screen on.
4147 * @see #currentLaunchCanTurnScreenOn()
4148 */
4149 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
4150 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
4151 }
4152
4153 /**
4154 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
4155 * relayouts from turning the screen back on. The screen should only turn on at most
4156 * once per activity resume.
4157 * <p>
4158 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
4159 * or {@link ActivityRecord#canTurnScreenOn} is set.
4160 *
4161 * @return {@code true} if the activity is ready to turn on the screen.
4162 */
4163 boolean currentLaunchCanTurnScreenOn() {
4164 return mCurrentLaunchCanTurnScreenOn;
4165 }
4166
Bryce Lee7ace3952018-02-16 14:34:32 -08004167 void setState(ActivityState state, String reason) {
4168 if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
4169 + " to:" + state + " reason:" + reason);
Bryce Lee6ff17072018-02-28 07:26:17 -08004170
Bryce Leeb0f993f2018-03-02 15:38:01 -08004171 if (state == mState) {
4172 // No need to do anything if state doesn't change.
4173 if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
4174 return;
4175 }
4176
Bryce Leeb0f993f2018-03-02 15:38:01 -08004177 mState = state;
4178
Louis Changcdec0802019-11-11 11:45:07 +08004179 if (task != null) {
4180 task.onActivityStateChanged(this, state, reason);
Bryce Leec4ab62a2018-03-05 14:19:26 -08004181 }
Robert Carr29daa922018-04-27 11:56:48 -07004182
Robert Carr9e1bf7c2018-05-31 15:39:07 -07004183 // The WindowManager interprets the app stopping signal as
4184 // an indication that the Surface will eventually be destroyed.
4185 // This however isn't necessarily true if we are going to sleep.
4186 if (state == STOPPING && !isSleeping()) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004187 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004188 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
4189 + appToken);
4190 return;
4191 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004192 detachChildren();
Robert Carr29daa922018-04-27 11:56:48 -07004193 }
Hui Yu03d12402018-12-06 18:00:37 -08004194
4195 if (state == RESUMED) {
4196 mAtmService.updateBatteryStats(this, true);
4197 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
4198 } else if (state == PAUSED) {
4199 mAtmService.updateBatteryStats(this, false);
4200 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
4201 } else if (state == STOPPED) {
4202 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
4203 } else if (state == DESTROYED) {
4204 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
4205 }
Bryce Lee7ace3952018-02-16 14:34:32 -08004206 }
4207
4208 ActivityState getState() {
4209 return mState;
4210 }
4211
4212 /**
4213 * Returns {@code true} if the Activity is in the specified state.
4214 */
4215 boolean isState(ActivityState state) {
4216 return state == mState;
4217 }
4218
4219 /**
4220 * Returns {@code true} if the Activity is in one of the specified states.
4221 */
4222 boolean isState(ActivityState state1, ActivityState state2) {
4223 return state1 == mState || state2 == mState;
4224 }
4225
4226 /**
4227 * Returns {@code true} if the Activity is in one of the specified states.
4228 */
4229 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3) {
4230 return state1 == mState || state2 == mState || state3 == mState;
4231 }
4232
4233 /**
4234 * Returns {@code true} if the Activity is in one of the specified states.
4235 */
4236 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4237 ActivityState state4) {
4238 return state1 == mState || state2 == mState || state3 == mState || state4 == mState;
4239 }
4240
Louis Changeadb22f2019-06-19 12:09:23 +08004241 /**
4242 * Returns {@code true} if the Activity is in one of the specified states.
4243 */
4244 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4245 ActivityState state4, ActivityState state5) {
4246 return state1 == mState || state2 == mState || state3 == mState || state4 == mState
4247 || state5 == mState;
4248 }
4249
Garfield Tane8d84ab2019-10-11 09:49:40 -07004250 void destroySurfaces() {
4251 destroySurfaces(false /*cleanupOnResume*/);
4252 }
4253
4254 /**
4255 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
4256 * the client has finished with them.
4257 *
4258 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
4259 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
4260 * others so that they are ready to be reused. If set to false (common case), destroy all
4261 * surfaces that's eligible, if the app is already stopped.
4262 */
4263 private void destroySurfaces(boolean cleanupOnResume) {
4264 boolean destroyedSomething = false;
4265
4266 // Copying to a different list as multiple children can be removed.
4267 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
4268 for (int i = children.size() - 1; i >= 0; i--) {
4269 final WindowState win = children.get(i);
4270 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
4271 }
4272 if (destroyedSomething) {
4273 final DisplayContent dc = getDisplayContent();
4274 dc.assignWindowLayers(true /*setLayoutNeeded*/);
4275 updateLetterboxSurface(null);
4276 }
4277 }
4278
Jorim Jaggibae01b12017-04-11 16:29:10 -07004279 void notifyAppResumed(boolean wasStopped) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004280 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004281 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
4282 + appToken);
4283 return;
4284 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004285 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
4286 wasStopped, this);
4287 mAppStopped = false;
4288 // Allow the window to turn the screen on once the app is resumed again.
4289 setCurrentLaunchCanTurnScreenOn(true);
4290 if (!wasStopped) {
4291 destroySurfaces(true /*cleanupOnResume*/);
4292 }
4293 }
4294
4295 /**
4296 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
4297 * keeping alive in case they were still being used.
4298 */
4299 void notifyAppStopped() {
4300 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
4301 mAppStopped = true;
4302 // Reset the last saved PiP snap fraction on app stop.
4303 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
4304 destroySurfaces();
4305 // Remove any starting window that was added for this app if they are still around.
4306 removeStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08004307 }
4308
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004309 /**
4310 * Suppress transition until the new activity becomes ready, otherwise the keyguard can appear
4311 * for a short amount of time before the new process with the new activity had the ability to
4312 * set its showWhenLocked flags.
4313 */
4314 void notifyUnknownVisibilityLaunchedForKeyguardTransition() {
Jorim Jaggi838c2452017-08-28 15:44:43 +02004315 // No display activities never add a window, so there is no point in waiting them for
4316 // relayout.
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004317 if (noDisplay || !mStackSupervisor.getKeyguardController().isKeyguardLocked()) {
4318 return;
Andrii Kulian21713ac2016-10-12 22:05:05 -07004319 }
4320
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004321 mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004322 }
4323
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004324 /** @return {@code true} if this activity should be made visible. */
4325 boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
Garfield Tan47e576c2019-01-28 10:26:23 -08004326 // Check whether activity should be visible without Keyguard influence
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004327 visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
4328 && okToShowLocked();
4329
4330 if (ignoringKeyguard) {
4331 return visibleIgnoringKeyguard;
4332 }
Garfield Tan47e576c2019-01-28 10:26:23 -08004333
4334 final ActivityStack stack = getActivityStack();
4335 if (stack == null) {
4336 return false;
4337 }
4338
Issei Suzuki62356a22019-04-11 16:46:37 +02004339 // Whether the activity is on the sleeping display.
4340 // TODO(b/129750406): This should be applied for the default display, too.
4341 final boolean isDisplaySleeping = getDisplay().isSleeping()
4342 && getDisplayId() != DEFAULT_DISPLAY;
Garfield Tan47e576c2019-01-28 10:26:23 -08004343 // Whether this activity is the top activity of this stack.
Wale Ogunwale21e06482019-11-18 05:14:15 -08004344 final boolean isTop = this == stack.getTopNonFinishingActivity();
Garfield Tan47e576c2019-01-28 10:26:23 -08004345 // Exclude the case where this is the top activity in a pinned stack.
4346 final boolean isTopNotPinnedStack = stack.isAttached()
4347 && stack.getDisplay().isTopNotPinnedStack(stack);
Issei Suzuki62356a22019-04-11 16:46:37 +02004348 // Now check whether it's really visible depending on Keyguard state, and update
4349 // {@link ActivityStack} internal states.
4350 final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
Garfield Tan47e576c2019-01-28 10:26:23 -08004351 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
Issei Suzuki62356a22019-04-11 16:46:37 +02004352 return visibleIgnoringDisplayStatus && !isDisplaySleeping;
Garfield Tan47e576c2019-01-28 10:26:23 -08004353 }
4354
4355 boolean shouldBeVisible() {
4356 final ActivityStack stack = getActivityStack();
4357 if (stack == null) {
4358 return false;
4359 }
4360
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004361 final boolean behindFullscreenActivity = stack.checkBehindFullscreenActivity(
4362 this, null /* handleBehindFullscreenActivity */);
4363 return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */);
Garfield Tan47e576c2019-01-28 10:26:23 -08004364 }
4365
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004366 void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004367 // This activity is not currently visible, but is running. Tell it to become visible.
Bryce Lee7ace3952018-02-16 14:34:32 -08004368 if (mState == RESUMED || this == starting) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004369 if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
Bryce Lee7ace3952018-02-16 14:34:32 -08004370 "Not making visible, r=" + this + " state=" + mState + " starting=" + starting);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004371 return;
4372 }
4373
4374 // If this activity is paused, tell it to now show its window.
4375 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
4376 "Making visible and scheduling visibility: " + this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004377 final ActivityStack stack = getActivityStack();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004378 try {
4379 if (stack.mTranslucentActivityWaiting != null) {
4380 updateOptionsLocked(returningOptions);
4381 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
4382 }
Issei Suzuki430a1112019-11-14 16:20:52 +01004383 setVisible(true);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004384 sleeping = false;
Wale Ogunwale342fbe92018-10-09 08:44:10 -07004385 app.postPendingUiCleanMsg(true);
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004386 if (reportToClient) {
4387 makeClientVisible();
4388 } else {
4389 mClientVisibilityDeferred = true;
4390 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004391 // The activity may be waiting for stop, but that is no longer appropriate for it.
4392 mStackSupervisor.mStoppingActivities.remove(this);
4393 mStackSupervisor.mGoingToSleepActivities.remove(this);
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004394 } catch (Exception e) {
4395 // Just skip on any failure; we'll make it visible when it next restarts.
4396 Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
4397 }
4398 handleAlreadyVisible();
4399 }
Andrii Kulian0d595f32018-02-21 15:47:33 -08004400
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004401 /** Send visibility change message to the client and pause if needed. */
4402 void makeClientVisible() {
4403 mClientVisibilityDeferred = false;
4404 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004405 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004406 WindowVisibilityItem.obtain(true /* showWindow */));
Andrii Kulian6b321512019-01-23 06:37:00 +00004407 makeActiveIfNeeded(null /* activeActivity*/);
Louis Changeadb22f2019-06-19 12:09:23 +08004408 if (isState(STOPPING, STOPPED)) {
4409 // Set state to STARTED in order to have consistent state with client while
4410 // making an non-active activity visible from stopped.
4411 setState(STARTED, "makeClientVisible");
Louis Chang3d119a92019-04-22 10:45:37 +08004412 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004413 } catch (Exception e) {
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004414 Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004415 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004416 }
4417
Andrii Kulian79d67982019-08-19 11:56:16 -07004418 void makeInvisible() {
Issei Suzuki430a1112019-11-14 16:20:52 +01004419 if (!visible) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004420 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
4421 return;
4422 }
4423 // Now for any activities that aren't visible to the user, make sure they no longer are
4424 // keeping the screen frozen.
4425 if (DEBUG_VISIBILITY) {
4426 Slog.v(TAG_VISIBILITY, "Making invisible: " + this + ", state=" + getState());
4427 }
4428 try {
4429 final boolean canEnterPictureInPicture = checkEnterPictureInPictureState(
4430 "makeInvisible", true /* beforeStopping */);
4431 // Defer telling the client it is hidden if it can enter Pip and isn't current paused,
4432 // stopped or stopping. This gives it a chance to enter Pip in onPause().
4433 // TODO: There is still a question surrounding activities in multi-window mode that want
4434 // to enter Pip after they are paused, but are still visible. I they should be okay to
4435 // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and
4436 // the current contract for "auto-Pip" is that the app should enter it before onPause
4437 // returns. Just need to confirm this reasoning makes sense.
4438 final boolean deferHidingClient = canEnterPictureInPicture
4439 && !isState(STOPPING, STOPPED, PAUSED);
4440 setDeferHidingClient(deferHidingClient);
Issei Suzuki430a1112019-11-14 16:20:52 +01004441 setVisible(false);
Andrii Kulian79d67982019-08-19 11:56:16 -07004442
4443 switch (getState()) {
4444 case STOPPING:
4445 case STOPPED:
4446 if (attachedToProcess()) {
4447 if (DEBUG_VISIBILITY) {
4448 Slog.v(TAG_VISIBILITY, "Scheduling invisibility: " + this);
4449 }
4450 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
4451 appToken, WindowVisibilityItem.obtain(false /* showWindow */));
4452 }
4453
4454 // Reset the flag indicating that an app can enter picture-in-picture once the
4455 // activity is hidden
4456 supportsEnterPipOnTaskSwitch = false;
4457 break;
4458
4459 case INITIALIZING:
4460 case RESUMED:
4461 case PAUSING:
4462 case PAUSED:
4463 case STARTED:
4464 addToStopping(true /* scheduleIdle */,
4465 canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
4466 break;
4467
4468 default:
4469 break;
4470 }
4471 } catch (Exception e) {
4472 // Just skip on any failure; we'll make it visible when it next restarts.
4473 Slog.w(TAG, "Exception thrown making hidden: " + intent.getComponent(), e);
4474 }
4475 }
4476
Andrii Kulian6b321512019-01-23 06:37:00 +00004477 /**
4478 * Make activity resumed or paused if needed.
4479 * @param activeActivity an activity that is resumed or just completed pause action.
4480 * We won't change the state of this activity.
4481 */
4482 boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
4483 if (shouldResumeActivity(activeActivity)) {
4484 if (DEBUG_VISIBILITY) {
4485 Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this);
4486 }
4487 return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
4488 null /* options */);
4489 } else if (shouldPauseActivity(activeActivity)) {
4490 if (DEBUG_VISIBILITY) {
4491 Slog.v("TAG_VISIBILITY", "Pause visible activity, " + this);
4492 }
4493 // An activity must be in the {@link PAUSING} state for the system to validate
4494 // the move to {@link PAUSED}.
4495 setState(PAUSING, "makeVisibleIfNeeded");
4496 try {
4497 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
4498 PauseActivityItem.obtain(finishing, false /* userLeaving */,
4499 configChangeFlags, false /* dontReport */));
4500 } catch (Exception e) {
4501 Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
4502 }
4503 }
4504 return false;
4505 }
4506
4507 /**
4508 * Check if activity should be moved to PAUSED state. The activity:
4509 * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4510 * - should be non-focusable
4511 * - should not be currently pausing or paused
4512 * @param activeActivity the activity that is active or just completed pause action. We won't
4513 * resume if this activity is active.
4514 */
4515 private boolean shouldPauseActivity(ActivityRecord activeActivity) {
4516 return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED);
4517 }
4518
4519 /**
wilsonshihb5d8f8b2019-10-23 13:01:40 +08004520 * Check if activity should be moved to RESUMED state.
4521 * See {@link #shouldBeResumed(ActivityRecord)}
Andrii Kulian6b321512019-01-23 06:37:00 +00004522 * @param activeActivity the activity that is active or just completed pause action. We won't
4523 * resume if this activity is active.
4524 */
Andrii Kulian0c869cc2019-02-06 19:50:32 -08004525 @VisibleForTesting
4526 boolean shouldResumeActivity(ActivityRecord activeActivity) {
wilsonshihb5d8f8b2019-10-23 13:01:40 +08004527 return shouldBeResumed(activeActivity) && !isState(RESUMED);
4528 }
4529
4530 /**
4531 * Check if activity should be RESUMED now. The activity:
4532 * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4533 * - should be focusable
4534 */
4535 private boolean shouldBeResumed(ActivityRecord activeActivity) {
4536 return shouldMakeActive(activeActivity) && isFocusable()
4537 && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
4538 && canResumeByCompat();
Andrii Kulian6b321512019-01-23 06:37:00 +00004539 }
4540
4541 /**
4542 * Check if activity is eligible to be made active (resumed of paused). The activity:
4543 * - should be paused, stopped or stopping
Andrii Kulian996df0d2019-01-24 17:04:36 -08004544 * - should not be the currently active one or launching behind other tasks
Andrii Kulian6b321512019-01-23 06:37:00 +00004545 * - should be either the topmost in task, or right below the top activity that is finishing
4546 * If all of these conditions are not met at the same time, the activity cannot be made active.
4547 */
Andrii Kulianf2195362019-01-31 18:20:11 -08004548 @VisibleForTesting
4549 boolean shouldMakeActive(ActivityRecord activeActivity) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004550 // If the activity is stopped, stopping, cycle to an active state. We avoid doing
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004551 // this when there is an activity waiting to become translucent as the extra binder
4552 // calls will lead to noticeable jank. A later call to
Andrii Kulian6b321512019-01-23 06:37:00 +00004553 // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to a proper
4554 // active state.
Louis Changeadb22f2019-06-19 12:09:23 +08004555 if (!isState(STARTED, RESUMED, PAUSED, STOPPED, STOPPING)
Andrii Kulian6b321512019-01-23 06:37:00 +00004556 || getActivityStack().mTranslucentActivityWaiting != null) {
4557 return false;
4558 }
4559
4560 if (this == activeActivity) {
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004561 return false;
4562 }
4563
Andrii Kulianf2195362019-01-31 18:20:11 -08004564 if (!mStackSupervisor.readyToResume()) {
4565 // Making active is currently deferred (e.g. because an activity launch is in progress).
4566 return false;
4567 }
4568
Andrii Kulian996df0d2019-01-24 17:04:36 -08004569 if (this.mLaunchTaskBehind) {
4570 // This activity is being launched from behind, which means that it's not intended to be
4571 // presented to user right now, even if it's set to be visible.
4572 return false;
4573 }
4574
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004575 // Check if position in task allows to become paused
Wale Ogunwale2322bed2019-10-10 17:24:19 +02004576 final int positionInTask = task.mChildren.indexOf(this);
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004577 if (positionInTask == -1) {
4578 throw new IllegalStateException("Activity not found in its task");
4579 }
Wale Ogunwale1a06f152019-10-11 11:26:30 +02004580 if (positionInTask == task.getChildCount() - 1) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004581 // It's the topmost activity in the task - should become resumed now
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004582 return true;
4583 }
4584 // Check if activity above is finishing now and this one becomes the topmost in task.
Wale Ogunwale1a06f152019-10-11 11:26:30 +02004585 final ActivityRecord activityAbove = task.getChildAt(positionInTask + 1);
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004586 if (activityAbove.finishing && results == null) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004587 // We will only allow making active if activity above wasn't launched for result.
4588 // Otherwise it will cause this activity to resume before getting result.
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004589 return true;
4590 }
4591 return false;
4592 }
4593
Louis Changcfe46212019-07-30 10:34:18 +08004594 void handleAlreadyVisible() {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004595 stopFreezingScreenLocked(false);
4596 try {
4597 if (returningOptions != null) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004598 app.getThread().scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
Andrii Kulian21713ac2016-10-12 22:05:05 -07004599 }
4600 } catch(RemoteException e) {
4601 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004602 }
4603
4604 static void activityResumedLocked(IBinder token) {
4605 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
4606 if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
Charles Chen69362cd2019-03-29 15:18:45 +08004607 if (r == null) {
4608 // If an app reports resumed after a long delay, the record on server side might have
4609 // been removed (e.g. destroy timeout), so the token could be null.
4610 return;
Andrii Kulian21713ac2016-10-12 22:05:05 -07004611 }
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004612 r.setSavedState(null /* savedState */);
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004613
4614 final ActivityDisplay display = r.getDisplay();
4615 if (display != null) {
4616 display.handleActivitySizeCompatModeIfNeeded(r);
4617 }
Riddle Hsu8419e4b2019-09-18 23:28:01 +08004618
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004619 r.getDisplayContent().mUnknownAppVisibilityController.notifyAppResumedFinished(r);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004620 }
4621
4622 /**
4623 * Once we know that we have asked an application to put an activity in the resumed state
4624 * (either by launching it or explicitly telling it), this function updates the rest of our
4625 * state to match that fact.
4626 */
4627 void completeResumeLocked() {
Issei Suzuki430a1112019-11-14 16:20:52 +01004628 final boolean wasVisible = visible;
4629 setVisible(true);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004630 if (!wasVisible) {
4631 // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
4632 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
4633 }
4634 idle = false;
4635 results = null;
Louis Chang746c2242019-10-08 16:30:44 +08004636 if (newIntents != null && newIntents.size() > 0) {
4637 mLastNewIntent = newIntents.get(newIntents.size() - 1);
4638 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004639 newIntents = null;
4640 stopped = false;
4641
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07004642 if (isActivityTypeHome()) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02004643 mStackSupervisor.updateHomeProcess(task.getChildAt(0).app);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004644 }
4645
4646 if (nowVisible) {
Louis Changa59937a2019-03-20 17:17:22 +08004647 mStackSupervisor.stopWaitingForActivityVisible(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004648 }
4649
4650 // Schedule an idle timeout in case the app doesn't do it for us.
4651 mStackSupervisor.scheduleIdleTimeoutLocked(this);
4652
4653 mStackSupervisor.reportResumedActivityLocked(this);
4654
4655 resumeKeyDispatchingLocked();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004656 final ActivityStack stack = getActivityStack();
Jorim Jaggifa9ed962018-01-25 00:16:49 +01004657 mStackSupervisor.mNoAnimActivities.clear();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004658
4659 // Mark the point when the activity is resuming
4660 // TODO: To be more accurate, the mark should be before the onCreate,
4661 // not after the onResume. But for subsequent starts, onResume is fine.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004662 if (hasProcess()) {
Wale Ogunwale86b74462018-07-02 08:42:43 -07004663 cpuTimeAtResume = app.getCpuTime();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004664 } else {
4665 cpuTimeAtResume = 0; // Couldn't get the cpu time of process
4666 }
4667
4668 returningOptions = null;
chaviw59b98852017-06-13 12:05:44 -07004669
4670 if (canTurnScreenOn()) {
4671 mStackSupervisor.wakeUp("turnScreenOnFlag");
4672 } else {
4673 // If the screen is going to turn on because the caller explicitly requested it and
4674 // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
4675 // pause and then resume again later, which will result in a double life-cycle event.
David Stevens9440dc82017-03-16 19:00:20 -07004676 stack.checkReadyForSleep();
chaviw59b98852017-06-13 12:05:44 -07004677 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004678 }
4679
Andrii Kulian79d67982019-08-19 11:56:16 -07004680 void stopIfPossible() {
4681 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
4682 final ActivityStack stack = getActivityStack();
4683 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4684 || (info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0) {
4685 if (!finishing) {
4686 if (!stack.shouldSleepActivities()) {
4687 if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + this);
4688 if (finishIfPossible("stop-no-history", false /* oomAdj */)
4689 != FINISH_RESULT_CANCELLED) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004690 resumeKeyDispatchingLocked();
4691 return;
4692 }
4693 } else {
4694 if (DEBUG_STATES) {
4695 Slog.d(TAG_STATES, "Not finishing noHistory " + this
4696 + " on stop because we're just sleeping");
4697 }
4698 }
4699 }
4700 }
4701
4702 if (!attachedToProcess()) {
4703 return;
4704 }
Andrii Kulian79d67982019-08-19 11:56:16 -07004705 resumeKeyDispatchingLocked();
4706 try {
4707 stopped = false;
4708 if (DEBUG_STATES) {
4709 Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (stop requested)");
4710 }
4711 setState(STOPPING, "stopIfPossible");
4712 if (DEBUG_VISIBILITY) {
Issei Suzuki430a1112019-11-14 16:20:52 +01004713 Slog.v(TAG_VISIBILITY, "Stopping visible=" + visible + " for " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07004714 }
Issei Suzuki430a1112019-11-14 16:20:52 +01004715 if (!visible) {
4716 setVisible(false);
Andrii Kulian79d67982019-08-19 11:56:16 -07004717 }
4718 EventLogTags.writeAmStopActivity(
4719 mUserId, System.identityHashCode(this), shortComponentName);
4720 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Issei Suzuki430a1112019-11-14 16:20:52 +01004721 StopActivityItem.obtain(visible, configChangeFlags));
Andrii Kulian79d67982019-08-19 11:56:16 -07004722 if (stack.shouldSleepOrShutDownActivities()) {
4723 setSleeping(true);
4724 }
4725 stack.scheduleStopTimeoutForActivity(this);
4726 } catch (Exception e) {
4727 // Maybe just ignore exceptions here... if the process has crashed, our death
4728 // notification will clean things up.
4729 Slog.w(TAG, "Exception thrown during pause", e);
4730 // Just in case, assume it to be stopped.
4731 stopped = true;
4732 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + this);
4733 setState(STOPPED, "stopIfPossible");
4734 if (deferRelaunchUntilPaused) {
4735 destroyImmediately(true /* removeFromApp */, "stop-except");
4736 }
4737 }
4738 }
4739
Andrii Kulian21713ac2016-10-12 22:05:05 -07004740 final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
4741 CharSequence description) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004742 final ActivityStack stack = getActivityStack();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004743 final boolean isStopping = mState == STOPPING;
4744 if (!isStopping && mState != RESTARTING_PROCESS) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004745 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07004746 stack.removeStopTimeoutForActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004747 return;
4748 }
4749 if (newPersistentState != null) {
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004750 mPersistentState = newPersistentState;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004751 mAtmService.notifyTaskPersisterLocked(task, false);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004752 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08004753
Andrii Kulian21713ac2016-10-12 22:05:05 -07004754 if (newIcicle != null) {
4755 // If icicle is null, this is happening due to a timeout, so we haven't really saved
4756 // the state.
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004757 setSavedState(newIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004758 launchCount = 0;
Jorim Jaggie7d2b852017-08-28 17:55:15 +02004759 updateTaskDescription(description);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004760 }
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004761 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004762 if (!stopped) {
4763 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
Andrii Kulian79d67982019-08-19 11:56:16 -07004764 stack.removeStopTimeoutForActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004765 stopped = true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004766 if (isStopping) {
4767 setState(STOPPED, "activityStoppedLocked");
4768 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004769
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004770 notifyAppStopped();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004771
Andrii Kulian21713ac2016-10-12 22:05:05 -07004772 if (finishing) {
4773 clearOptionsLocked();
4774 } else {
4775 if (deferRelaunchUntilPaused) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004776 destroyImmediately(true /* removeFromApp */, "stop-config");
Wale Ogunwaled32da472018-11-16 07:19:28 -08004777 mRootActivityContainer.resumeFocusedStacksTopActivities();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004778 } else {
Wale Ogunwaled32da472018-11-16 07:19:28 -08004779 mRootActivityContainer.updatePreviousProcess(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004780 }
4781 }
4782 }
4783 }
4784
Andrii Kulian79d67982019-08-19 11:56:16 -07004785 void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
4786 if (!mStackSupervisor.mStoppingActivities.contains(this)) {
4787 EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, mUserId,
4788 System.identityHashCode(this), shortComponentName, reason);
4789 mStackSupervisor.mStoppingActivities.add(this);
4790 }
4791
4792 final ActivityStack stack = getActivityStack();
4793 // If we already have a few activities waiting to stop, then give up on things going idle
4794 // and start clearing them out. Or if r is the last of activity of the last task the stack
4795 // will be empty and must be cleared immediately.
4796 boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
4797 || (isRootOfTask() && stack.getChildCount() <= 1);
4798 if (scheduleIdle || forceIdle) {
4799 if (DEBUG_PAUSE) {
4800 Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" + forceIdle
4801 + "immediate=" + !idleDelayed);
4802 }
4803 if (!idleDelayed) {
4804 mStackSupervisor.scheduleIdleLocked();
4805 } else {
4806 mStackSupervisor.scheduleIdleTimeoutLocked(this);
4807 }
4808 } else {
4809 stack.checkReadyForSleep();
4810 }
4811 }
4812
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004813 void startLaunchTickingLocked() {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06004814 if (Build.IS_USER) {
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004815 return;
4816 }
4817 if (launchTickTime == 0) {
4818 launchTickTime = SystemClock.uptimeMillis();
4819 continueLaunchTickingLocked();
4820 }
4821 }
4822
4823 boolean continueLaunchTickingLocked() {
Wale Ogunwale7d701172015-03-11 15:36:30 -07004824 if (launchTickTime == 0) {
4825 return false;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004826 }
Wale Ogunwale7d701172015-03-11 15:36:30 -07004827
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004828 final ActivityStack stack = getActivityStack();
Wale Ogunwale7d701172015-03-11 15:36:30 -07004829 if (stack == null) {
4830 return false;
4831 }
4832
Andrii Kulian79d67982019-08-19 11:56:16 -07004833 stack.removeLaunchTickMessages();
4834 stack.scheduleLaunchTickForActivity(this);
Wale Ogunwale7d701172015-03-11 15:36:30 -07004835 return true;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004836 }
4837
4838 void finishLaunchTickingLocked() {
4839 launchTickTime = 0;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004840 final ActivityStack stack = getActivityStack();
Andrii Kulian79d67982019-08-19 11:56:16 -07004841 if (stack == null) {
4842 return;
Wale Ogunwale7d701172015-03-11 15:36:30 -07004843 }
Andrii Kulian79d67982019-08-19 11:56:16 -07004844 stack.removeLaunchTickMessages();
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004845 }
4846
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004847 boolean mayFreezeScreenLocked() {
4848 return mayFreezeScreenLocked(app);
4849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004851 private boolean mayFreezeScreenLocked(WindowProcessController app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852 // Only freeze the screen if this activity is currently attached to
4853 // an application, and that application is not blocked or unresponding.
4854 // In any other case, we can't count on getting the screen unfrozen,
4855 // so it is best to leave as-is.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004856 return hasProcess() && !app.isCrashing() && !app.isNotResponding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07004858
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004859 void startFreezingScreenLocked(int configChanges) {
4860 startFreezingScreenLocked(app, configChanges);
4861 }
4862
4863 void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004864 if (mayFreezeScreenLocked(app)) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004865 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004866 Slog.w(TAG_WM,
4867 "Attempted to freeze screen with non-existing app token: " + appToken);
4868 return;
4869 }
4870
Evan Roskyb1e75f72019-04-26 20:23:26 -07004871 // Window configuration changes only effect windows, so don't require a screen freeze.
4872 int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004873 if (freezableConfigChanges == 0 && okToDisplay()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02004874 ProtoLog.v(WM_DEBUG_ORIENTATION, "Skipping set freeze of %s", appToken);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004875 return;
4876 }
4877
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004878 startFreezingScreen();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 }
4880 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07004881
Garfield Tane8d84ab2019-10-11 09:49:40 -07004882 void startFreezingScreen() {
4883 ProtoLog.i(WM_DEBUG_ORIENTATION,
Issei Suzuki430a1112019-11-14 16:20:52 +01004884 "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
4885 appToken, isHidden(), mFreezingScreen, hiddenRequested,
Garfield Tane8d84ab2019-10-11 09:49:40 -07004886 new RuntimeException().fillInStackTrace());
Issei Suzuki430a1112019-11-14 16:20:52 +01004887 if (!hiddenRequested) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004888 if (!mFreezingScreen) {
4889 mFreezingScreen = true;
4890 mWmService.registerAppFreezeListener(this);
4891 mWmService.mAppsFreezingScreen++;
4892 if (mWmService.mAppsFreezingScreen == 1) {
4893 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
4894 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4895 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
4896 }
4897 }
4898 final int count = mChildren.size();
4899 for (int i = 0; i < count; i++) {
4900 final WindowState w = mChildren.get(i);
4901 w.onStartFreezingScreen();
4902 }
4903 }
4904 }
4905
4906 boolean isFreezingScreen() {
4907 return mFreezingScreen;
4908 }
4909
4910 @Override
4911 public void onAppFreezeTimeout() {
4912 Slog.w(TAG_WM, "Force clearing freeze: " + this);
4913 stopFreezingScreen(true, true);
4914 }
4915
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004916 void stopFreezingScreenLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917 if (force || frozenBeforeDestroy) {
4918 frozenBeforeDestroy = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004919 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004920 return;
4921 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02004922 ProtoLog.v(WM_DEBUG_ORIENTATION,
Issei Suzuki7b9e2572019-11-14 16:19:54 +01004923 "Clear freezing of %s: hidden=%b freezing=%b", appToken,
4924 isHidden(), isFreezingScreen());
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004925 stopFreezingScreen(true, force);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 }
4927 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07004928
Garfield Tane8d84ab2019-10-11 09:49:40 -07004929 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
4930 if (!mFreezingScreen) {
4931 return;
4932 }
4933 ProtoLog.v(WM_DEBUG_ORIENTATION,
4934 "Clear freezing of %s force=%b", this, force);
4935 final int count = mChildren.size();
4936 boolean unfrozeWindows = false;
4937 for (int i = 0; i < count; i++) {
4938 final WindowState w = mChildren.get(i);
4939 unfrozeWindows |= w.onStopFreezingScreen();
4940 }
4941 if (force || unfrozeWindows) {
4942 ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
4943 mFreezingScreen = false;
4944 mWmService.unregisterAppFreezeListener(this);
4945 mWmService.mAppsFreezingScreen--;
4946 mWmService.mLastFinishedFreezeSource = this;
4947 }
4948 if (unfreezeSurfaceNow) {
4949 if (unfrozeWindows) {
4950 mWmService.mWindowPlacerLocked.performSurfacePlacement();
4951 }
4952 mWmService.stopFreezingDisplayLocked();
4953 }
4954 }
4955
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004956 void reportFullyDrawnLocked(boolean restoredFromBundle) {
Vishnu Nair132ee832018-09-28 15:00:05 -07004957 final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
Yan Wangd47f90b2019-10-03 19:17:15 -07004958 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
Vishnu Nair132ee832018-09-28 15:00:05 -07004959 if (info != null) {
4960 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
Vishnu Nairbb9ab4b2018-12-13 10:29:46 -08004961 info.windowsFullyDrawnDelayMs, info.getLaunchState());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07004962 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07004963 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004964
Garfield Tane8d84ab2019-10-11 09:49:40 -07004965 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
4966 firstWindowDrawn = true;
4967
4968 // We now have a good window to show, remove dead placeholders
4969 removeDeadWindows();
4970
4971 if (startingWindow != null) {
4972 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
4973 + ": first real window is shown, no animation", win.mToken);
4974 // If this initial window is animating, stop it -- we will do an animation to reveal
4975 // it from behind the starting window, so there is no need for it to also be doing its
4976 // own stuff.
4977 win.cancelAnimation();
4978 }
4979 removeStartingWindow();
4980 updateReportedVisibilityLocked();
4981 }
4982
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004983 /** Called when the windows associated app window container are drawn. */
Yan Wangd47f90b2019-10-03 19:17:15 -07004984 void onWindowsDrawn(boolean drawn, long timestampNs) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004985 mDrawn = drawn;
4986 if (!drawn) {
4987 return;
4988 }
4989 final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
Yan Wangd47f90b2019-10-03 19:17:15 -07004990 .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestampNs);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004991 final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
4992 final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
4993 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
4994 windowsDrawnDelayMs, launchState);
Riddle Hsuc48c8912019-10-31 13:34:27 +08004995 mStackSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004996 finishLaunchTickingLocked();
4997 if (task != null) {
4998 task.hasBeenVisible = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 }
5000 }
5001
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005002 /** Called when the windows associated app window container are visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005003 void onWindowsVisible() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005004 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005005 mStackSupervisor.stopWaitingForActivityVisible(this);
5006 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
5007 if (!nowVisible) {
5008 nowVisible = true;
5009 lastVisibleTime = SystemClock.uptimeMillis();
5010 mAtmService.scheduleAppGcsLocked();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005011 }
5012 }
5013
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005014 /** Called when the windows associated app window container are no longer visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005015 void onWindowsGone() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005016 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005017 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
5018 nowVisible = false;
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005019 }
5020
Garfield Tane8d84ab2019-10-11 09:49:40 -07005021 @Override
5022 void checkAppWindowsReadyToShow() {
5023 if (allDrawn == mLastAllDrawn) {
5024 return;
5025 }
5026
5027 mLastAllDrawn = allDrawn;
5028 if (!allDrawn) {
5029 return;
5030 }
5031
5032 // The token has now changed state to having all windows shown... what to do, what to do?
5033 if (mFreezingScreen) {
5034 showAllWindowsLocked();
5035 stopFreezingScreen(false, true);
5036 ProtoLog.i(WM_DEBUG_ORIENTATION,
5037 "Setting mOrientationChangeComplete=true because wtoken %s "
5038 + "numInteresting=%d numDrawn=%d",
5039 this, mNumInterestingWindows, mNumDrawnWindows);
5040 // This will set mOrientationChangeComplete and cause a pass through layout.
5041 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
5042 "checkAppWindowsReadyToShow: freezingScreen");
5043 } else {
5044 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
5045
5046 // We can now show all of the drawn windows!
5047 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
5048 showAllWindowsLocked();
5049 }
5050 }
5051 }
5052
5053 /**
5054 * This must be called while inside a transaction.
5055 */
5056 void showAllWindowsLocked() {
5057 forAllWindows(windowState -> {
5058 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
5059 windowState.performShowLocked();
5060 }, false /* traverseTopToBottom */);
5061 }
5062
5063 void updateReportedVisibilityLocked() {
5064 if (appToken == null) {
5065 return;
5066 }
5067
5068 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
5069 final int count = mChildren.size();
5070
5071 mReportedVisibilityResults.reset();
5072
5073 for (int i = 0; i < count; i++) {
5074 final WindowState win = mChildren.get(i);
5075 win.updateReportedVisibility(mReportedVisibilityResults);
5076 }
5077
5078 int numInteresting = mReportedVisibilityResults.numInteresting;
5079 int numVisible = mReportedVisibilityResults.numVisible;
5080 int numDrawn = mReportedVisibilityResults.numDrawn;
5081 boolean nowGone = mReportedVisibilityResults.nowGone;
5082
5083 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01005084 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005085 if (!nowGone) {
5086 // If the app is not yet gone, then it can only become visible/drawn.
5087 if (!nowDrawn) {
5088 nowDrawn = reportedDrawn;
5089 }
5090 if (!nowVisible) {
5091 nowVisible = reportedVisible;
5092 }
5093 }
5094 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
5095 + numInteresting + " visible=" + numVisible);
5096 if (nowDrawn != reportedDrawn) {
5097 onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
5098 reportedDrawn = nowDrawn;
5099 }
5100 if (nowVisible != reportedVisible) {
5101 if (DEBUG_VISIBILITY) Slog.v(TAG,
5102 "Visibility changed in " + this + ": vis=" + nowVisible);
5103 reportedVisible = nowVisible;
5104 if (nowVisible) {
5105 onWindowsVisible();
5106 } else {
5107 onWindowsGone();
5108 }
5109 }
5110 }
5111
Issei Suzukie63eac72019-11-14 15:59:15 +01005112 boolean isClientHidden() {
5113 return mClientHidden;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005114 }
5115
Issei Suzukie63eac72019-11-14 15:59:15 +01005116 void setClientHidden(boolean hideClient) {
5117 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005118 return;
5119 }
5120 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzukie63eac72019-11-14 15:59:15 +01005121 "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005122 Debug.getCallers(5));
Issei Suzukie63eac72019-11-14 15:59:15 +01005123 mClientHidden = hideClient;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005124 sendAppVisibilityToClients();
5125 }
5126
5127 /**
5128 * Updated this app token tracking states for interesting and drawn windows based on the window.
5129 *
5130 * @return Returns true if the input window is considered interesting and drawn while all the
5131 * windows in this app token where not considered drawn as of the last pass.
5132 */
5133 boolean updateDrawnWindowStates(WindowState w) {
5134 w.setDrawnStateEvaluated(true /*evaluated*/);
5135
5136 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
5137 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
5138 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
5139 }
5140
5141 if (allDrawn && !mFreezingScreen) {
5142 return false;
5143 }
5144
5145 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
5146 mLastTransactionSequence = mWmService.mTransactionSequence;
5147 mNumDrawnWindows = 0;
5148 startingDisplayed = false;
5149
5150 // There is the main base application window, even if it is exiting, wait for it
5151 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
5152 }
5153
5154 final WindowStateAnimator winAnimator = w.mWinAnimator;
5155
5156 boolean isInterestingAndDrawn = false;
5157
5158 if (!allDrawn && w.mightAffectAllDrawn()) {
5159 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5160 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
lumark9bca6b42019-10-17 18:35:22 +08005161 + ", isAnimationSet=" + isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005162 if (!w.isDrawnLw()) {
5163 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
5164 + " pv=" + w.isVisibleByPolicy()
5165 + " mDrawState=" + winAnimator.drawStateToString()
Issei Suzuki430a1112019-11-14 16:20:52 +01005166 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
lumark9bca6b42019-10-17 18:35:22 +08005167 + " a=" + isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005168 }
5169 }
5170
5171 if (w != startingWindow) {
5172 if (w.isInteresting()) {
5173 // Add non-main window as interesting since the main app has already been added
5174 if (findMainWindow(false /* includeStartingApp */) != w) {
5175 mNumInterestingWindows++;
5176 }
5177 if (w.isDrawnLw()) {
5178 mNumDrawnWindows++;
5179
5180 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5181 Slog.v(TAG, "tokenMayBeDrawn: "
5182 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
5183 + " freezingScreen=" + mFreezingScreen
5184 + " mAppFreezing=" + w.mAppFreezing);
5185 }
5186
5187 isInterestingAndDrawn = true;
5188 }
5189 }
5190 } else if (w.isDrawnLw()) {
Yan Wangb0b20062019-10-30 12:47:09 -07005191 onStartingWindowDrawn(SystemClock.elapsedRealtimeNanos());
Garfield Tane8d84ab2019-10-11 09:49:40 -07005192 startingDisplayed = true;
5193 }
5194 }
5195
5196 return isInterestingAndDrawn;
5197 }
5198
5199 /** Called when the starting window for this container is drawn. */
Yan Wangb0b20062019-10-30 12:47:09 -07005200 private void onStartingWindowDrawn(long timestampNs) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005201 synchronized (mAtmService.mGlobalLock) {
5202 mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
Yan Wangb0b20062019-10-30 12:47:09 -07005203 getWindowingMode(), timestampNs);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005204 }
5205 }
5206
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005207 /**
5208 * Called when the key dispatching to a window associated with the app window container
5209 * timed-out.
5210 *
5211 * @param reason The reason for the key dispatching time out.
5212 * @param windowPid The pid of the window key dispatching timed out on.
5213 * @return True if input dispatching should be aborted.
5214 */
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005215 public boolean keyDispatchingTimedOut(String reason, int windowPid) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005216 ActivityRecord anrActivity;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005217 WindowProcessController anrApp;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005218 boolean windowFromSameProcessAsActivity;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005219 synchronized (mAtmService.mGlobalLock) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005220 anrActivity = getWaitingHistoryRecordLocked();
5221 anrApp = app;
Brian Carlstrom7b0f2e82017-03-31 00:24:18 -07005222 windowFromSameProcessAsActivity =
Vishnu Nair19479df2019-10-30 08:03:15 -07005223 !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005224 }
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005225
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005226 if (windowFromSameProcessAsActivity) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005227 return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07005228 anrActivity.shortComponentName, anrActivity.info.applicationInfo,
5229 shortComponentName, app, false, reason);
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005230 } else {
5231 // In this case another process added windows using this activity token. So, we call the
5232 // generic service input dispatch timed out method so that the right process is blamed.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005233 return mAtmService.mAmInternal.inputDispatchingTimedOut(
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005234 windowPid, false /* aboveSystem */, reason) < 0;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005235 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005236 }
5237
5238 private ActivityRecord getWaitingHistoryRecordLocked() {
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005239 // First find the real culprit... if this activity has stopped, then the key dispatching
riddle_hsudb46d6b2015-04-01 18:58:07 +08005240 // timeout should not be caused by this.
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005241 if (stopped) {
Wale Ogunwaled32da472018-11-16 07:19:28 -08005242 final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
riddle_hsudb46d6b2015-04-01 18:58:07 +08005243 // Try to use the one which is closest to top.
Bryce Leec4ab62a2018-03-05 14:19:26 -08005244 ActivityRecord r = stack.getResumedActivity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 if (r == null) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08005246 r = stack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005248 if (r != null) {
5249 return r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 }
5251 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005252 return this;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 }
5254
Chong Zhang87761972016-08-22 13:53:24 -07005255 /** Checks whether the activity should be shown for current user. */
5256 public boolean okToShowLocked() {
Bryce Lee8558ec72017-08-17 15:37:26 -07005257 // We cannot show activities when the device is locked and the application is not
5258 // encryption aware.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005259 if (!StorageManager.isUserKeyUnlocked(mUserId)
Bryce Lee8558ec72017-08-17 15:37:26 -07005260 && !info.applicationInfo.isEncryptionAware()) {
5261 return false;
5262 }
5263
Chong Zhang87761972016-08-22 13:53:24 -07005264 return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005265 || (mStackSupervisor.isCurrentProfileLocked(mUserId)
5266 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
Chong Zhang87761972016-08-22 13:53:24 -07005267 }
5268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 /**
5270 * This method will return true if the activity is either visible, is becoming visible, is
5271 * currently pausing, or is resumed.
5272 */
5273 public boolean isInterestingToUserLocked() {
Issei Suzuki430a1112019-11-14 16:20:52 +01005274 return visible || nowVisible || mState == PAUSING || mState == RESUMED;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005275 }
5276
Wale Ogunwale3e997362016-09-06 10:37:56 -07005277 void setSleeping(boolean _sleeping) {
5278 setSleeping(_sleeping, false);
5279 }
5280
5281 void setSleeping(boolean _sleeping, boolean force) {
5282 if (!force && sleeping == _sleeping) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005283 return;
5284 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005285 if (attachedToProcess()) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005286 try {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005287 app.getThread().scheduleSleeping(appToken, _sleeping);
Craig Mautner0eea92c2013-05-16 13:35:39 -07005288 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
5289 mStackSupervisor.mGoingToSleepActivities.add(this);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005290 }
5291 sleeping = _sleeping;
5292 } catch (RemoteException e) {
Craig Mautner0eea92c2013-05-16 13:35:39 -07005293 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005294 }
5295 }
5296 }
Craig Mautnerf81b90872013-02-26 13:02:43 -08005297
Craig Mautnerd2328952013-03-05 12:46:26 -08005298 static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005299 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Craig Mautnerd2328952013-03-05 12:46:26 -08005300 if (r == null) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005301 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005302 }
Louis Changcdec0802019-11-11 11:45:07 +08005303 final Task task = r.task;
Wale Ogunwale2322bed2019-10-10 17:24:19 +02005304 final int activityNdx = task.mChildren.indexOf(r);
Andrii Kulian39f27442019-06-26 19:09:19 -07005305 if (activityNdx < 0
5306 || (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005307 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005308 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005309 return task.mTaskId;
Craig Mautnerd2328952013-03-05 12:46:26 -08005310 }
5311
5312 static ActivityRecord isInStackLocked(IBinder token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005313 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005314 return (r != null) ? r.getActivityStack().isInStackLocked(r) : null;
Craig Mautnerd2328952013-03-05 12:46:26 -08005315 }
5316
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005317 static ActivityStack getStackLocked(IBinder token) {
Craig Mautnerd2328952013-03-05 12:46:26 -08005318 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
5319 if (r != null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005320 return r.getActivityStack();
Craig Mautnerd2328952013-03-05 12:46:26 -08005321 }
5322 return null;
5323 }
5324
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005325 /**
Riddle Hsufd4a0502018-10-16 01:05:16 +08005326 * @return display id to which this record is attached,
5327 * {@link android.view.Display#INVALID_DISPLAY} if not attached.
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005328 */
5329 int getDisplayId() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005330 final ActivityStack stack = getActivityStack();
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005331 if (stack == null) {
Riddle Hsufd4a0502018-10-16 01:05:16 +08005332 return INVALID_DISPLAY;
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005333 }
5334 return stack.mDisplayId;
5335 }
5336
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005337 final boolean isDestroyable() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005338 if (finishing || !hasProcess()) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005339 // This would be redundant.
5340 return false;
5341 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005342 final ActivityStack stack = getActivityStack();
Andrii Kulianf49a58c2019-08-14 17:34:27 -07005343 if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState
5344 || !stopped) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005345 // We're not ready for this kind of thing.
5346 return false;
5347 }
Issei Suzuki430a1112019-11-14 16:20:52 +01005348 if (visible) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005349 // The user would notice this!
5350 return false;
5351 }
5352 return true;
5353 }
5354
Winson Chung3bad5cc02014-08-19 17:44:32 -07005355 private static String createImageFilename(long createTime, int taskId) {
5356 return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
Ruben Brunkf53497c2017-03-27 20:26:17 -07005357 IMAGE_EXTENSION;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07005358 }
5359
Craig Mautner648f69b2014-09-18 14:16:26 -07005360 void setTaskDescription(TaskDescription _taskDescription) {
5361 Bitmap icon;
5362 if (_taskDescription.getIconFilename() == null &&
5363 (icon = _taskDescription.getIcon()) != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005364 final String iconFilename = createImageFilename(createTime, task.mTaskId);
5365 final File iconFile = new File(TaskPersister.getUserImagesDir(task.mUserId),
Winson Chungc8408b82017-01-25 17:58:56 -08005366 iconFilename);
Suprabh Shukla23593142015-11-03 17:31:15 -08005367 final String iconFilePath = iconFile.getAbsolutePath();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005368 mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
Suprabh Shukla23593142015-11-03 17:31:15 -08005369 _taskDescription.setIconFilename(iconFilePath);
Craig Mautner648f69b2014-09-18 14:16:26 -07005370 }
5371 taskDescription = _taskDescription;
5372 }
5373
Amith Yamasani0af6fa72016-01-17 15:36:19 -08005374 void setVoiceSessionLocked(IVoiceInteractionSession session) {
5375 voiceSession = session;
5376 pendingVoiceInteractionStart = false;
5377 }
5378
5379 void clearVoiceSessionLocked() {
5380 voiceSession = null;
5381 pendingVoiceInteractionStart = false;
5382 }
5383
Jorim Jaggi02886a82016-12-06 09:10:06 -08005384 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
Jorim Jaggi42befc62017-06-13 11:54:04 -07005385 showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
5386 }
5387
5388 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
5389 boolean fromRecents) {
Wale Ogunwale19866e22017-04-19 06:05:13 -07005390 if (mTaskOverlay) {
5391 // We don't show starting window for overlay activities.
5392 return;
5393 }
Sunny Goyald85bed52018-09-25 12:01:01 -07005394 if (pendingOptions != null
5395 && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
5396 // Don't show starting window when using shared element transition.
5397 return;
5398 }
Wale Ogunwale19866e22017-04-19 06:05:13 -07005399
Wale Ogunwale3b232392016-05-13 15:37:13 -07005400 final CompatibilityInfo compatInfo =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005401 mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005402 final boolean shown = addStartingWindow(packageName, theme,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005403 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
Jorim Jaggibae01b12017-04-11 16:29:10 -07005404 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
Jorim Jaggi70aa4d12017-05-15 00:05:54 +02005405 allowTaskSnapshot(),
Louis Changeadb22f2019-06-19 12:09:23 +08005406 mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
Jorim Jaggi42befc62017-06-13 11:54:04 -07005407 fromRecents);
Wale Ogunwale3b232392016-05-13 15:37:13 -07005408 if (shown) {
5409 mStartingWindowState = STARTING_WINDOW_SHOWN;
5410 }
5411 }
5412
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005413 /**
5414 * If any activities below the top running one are in the INITIALIZING state and they have a
5415 * starting window displayed then remove that starting window. It is possible that the activity
5416 * in this state will never resumed in which case that starting window will be orphaned.
5417 * <p>
5418 * It should only be called if this activity is behind other fullscreen activity.
5419 */
5420 void cancelInitializing() {
5421 if (mStartingWindowState == STARTING_WINDOW_SHOWN) {
5422 // Remove orphaned starting window.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005423 if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
5424 mStartingWindowState = STARTING_WINDOW_REMOVED;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005425 removeStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005426 }
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005427 if (isState(INITIALIZING) && !shouldBeVisible(
5428 true /* behindFullscreenActivity */, true /* ignoringKeyguard */)) {
5429 // Remove the unknown visibility record because an invisible activity shouldn't block
5430 // the keyguard transition.
5431 mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
5432 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005433 }
5434
Garfield Tane8d84ab2019-10-11 09:49:40 -07005435 void postWindowRemoveStartingWindowCleanup(WindowState win) {
5436 // TODO: Something smells about the code below...Is there a better way?
5437 if (startingWindow == win) {
5438 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
5439 removeStartingWindow();
5440 } else if (mChildren.size() == 0) {
5441 // If this is the last window and we had requested a starting transition window,
5442 // well there is no point now.
5443 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
5444 mStartingData = null;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01005445 if (mHiddenSetFromTransferredStartingWindow) {
5446 // We set the hidden state to false for the token from a transferred starting window.
5447 // We now reset it back to true since the starting window was the last window in the
5448 // token.
5449 setHidden(true);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005450 }
5451 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
5452 // If this is the last window except for a starting transition window,
5453 // we need to get rid of the starting transition.
5454 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
5455 removeStartingWindow();
5456 }
5457 }
5458
5459 void removeDeadWindows() {
5460 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
5461 WindowState win = mChildren.get(winNdx);
5462 if (win.mAppDied) {
5463 ProtoLog.w(WM_DEBUG_ADD_REMOVE,
5464 "removeDeadWindows: %s", win);
5465 // Set mDestroying, we don't want any animation or delayed removal here.
5466 win.mDestroying = true;
5467 // Also removes child windows.
5468 win.removeIfPossible();
5469 }
5470 }
5471 }
5472
5473 boolean hasWindowsAlive() {
5474 for (int i = mChildren.size() - 1; i >= 0; i--) {
5475 // No need to loop through child windows as the answer should be the same as that of the
5476 // parent window.
5477 if (!(mChildren.get(i)).mAppDied) {
5478 return true;
5479 }
5480 }
5481 return false;
5482 }
5483
5484 void setWillReplaceWindows(boolean animate) {
5485 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5486 "Marking app token %s with replacing windows.", this);
5487
5488 for (int i = mChildren.size() - 1; i >= 0; i--) {
5489 final WindowState w = mChildren.get(i);
5490 w.setWillReplaceWindow(animate);
5491 }
5492 }
5493
5494 void setWillReplaceChildWindows() {
5495 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
5496 + " with replacing child windows.", this);
5497 for (int i = mChildren.size() - 1; i >= 0; i--) {
5498 final WindowState w = mChildren.get(i);
5499 w.setWillReplaceChildWindows();
5500 }
5501 }
5502
5503 void clearWillReplaceWindows() {
5504 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5505 "Resetting app token %s of replacing window marks.", this);
5506
5507 for (int i = mChildren.size() - 1; i >= 0; i--) {
5508 final WindowState w = mChildren.get(i);
5509 w.clearWillReplaceWindow();
5510 }
5511 }
5512
5513 void requestUpdateWallpaperIfNeeded() {
5514 for (int i = mChildren.size() - 1; i >= 0; i--) {
5515 final WindowState w = mChildren.get(i);
5516 w.requestUpdateWallpaperIfNeeded();
5517 }
5518 }
5519
5520 /**
5521 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
5522 * true.
5523 */
5524 WindowState getTopFullscreenWindow() {
5525 for (int i = mChildren.size() - 1; i >= 0; i--) {
5526 final WindowState win = mChildren.get(i);
5527 if (win != null && win.mAttrs.isFullscreen()) {
5528 return win;
5529 }
5530 }
5531 return null;
5532 }
5533
5534 WindowState findMainWindow() {
5535 return findMainWindow(true);
5536 }
5537
5538 /**
5539 * Finds the main window that either has type base application or application starting if
5540 * requested.
5541 *
5542 * @param includeStartingApp Allow to search application-starting windows to also be returned.
5543 * @return The main window of type base application or application starting if requested.
5544 */
5545 WindowState findMainWindow(boolean includeStartingApp) {
5546 WindowState candidate = null;
5547 for (int j = mChildren.size() - 1; j >= 0; --j) {
5548 final WindowState win = mChildren.get(j);
5549 final int type = win.mAttrs.type;
5550 // No need to loop through child window as base application and starting types can't be
5551 // child windows.
5552 if (type == TYPE_BASE_APPLICATION
5553 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
5554 // In cases where there are multiple windows, we prefer the non-exiting window. This
5555 // happens for example when replacing windows during an activity relaunch. When
5556 // constructing the animation, we want the new window, not the exiting one.
5557 if (win.mAnimatingExit) {
5558 candidate = win;
5559 } else {
5560 return win;
5561 }
5562 }
5563 }
5564 return candidate;
5565 }
5566
5567 SurfaceControl getAppAnimationLayer() {
5568 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
5569 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
5570 : ANIMATION_LAYER_STANDARD);
5571 }
5572
5573 @Override
5574 boolean needsZBoost() {
5575 return mNeedsZBoost || super.needsZBoost();
5576 }
5577
5578 @Override
5579 public SurfaceControl getAnimationLeashParent() {
5580 // For transitions in the pinned stack (menu activity) we just let them occur as a child
5581 // of the pinned stack.
5582 // All normal app transitions take place in an animation layer which is below the pinned
5583 // stack but may be above the parent stacks of the given animating apps by default. When
5584 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
5585 // stack, i.e. the hierarchy of the surfaces is unchanged.
5586 if (inPinnedWindowingMode()) {
5587 return getStack().getSurfaceControl();
5588 } else if (WindowManagerService.sHierarchicalAnimations) {
5589 return super.getAnimationLeashParent();
5590 } else {
5591 return getAppAnimationLayer();
5592 }
5593 }
5594
Garfield Tane8d84ab2019-10-11 09:49:40 -07005595 @VisibleForTesting
5596 boolean shouldAnimate(int transit) {
lumark19a5d2e2019-10-11 16:19:30 +08005597 if (task != null && !task.shouldAnimate()) {
5598 return false;
5599 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005600 final boolean isSplitScreenPrimary =
5601 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
5602 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
5603
Garfield Tane8d84ab2019-10-11 09:49:40 -07005604 // We animate always if it's not split screen primary, and only some special cases in split
5605 // screen primary because it causes issues with stack clipping when we run an un-minimize
5606 // animation at the same time.
5607 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
5608 }
5609
lumark19a5d2e2019-10-11 16:19:30 +08005610 @Override
5611 boolean isChangingAppTransition() {
Louis Changcdec0802019-11-11 11:45:07 +08005612 return task != null ? task.isChangingAppTransition() : super.isChangingAppTransition();
lumark19a5d2e2019-10-11 16:19:30 +08005613 }
5614
5615 @Override
5616 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
5617 boolean isVoiceInteraction) {
5618 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
5619 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
5620 "applyAnimation: transition animation is disabled or skipped. "
5621 + "container=%s", this);
5622 cancelAnimation();
5623 return false;
5624 }
5625 return super.applyAnimation(lp, transit, enter, isVoiceInteraction);
5626 }
5627
Garfield Tane8d84ab2019-10-11 09:49:40 -07005628 /**
5629 * Creates a layer to apply crop to an animation.
5630 */
5631 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
5632 ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
5633 final SurfaceControl.Builder builder = makeAnimationLeash()
5634 .setParent(getAnimationLeashParent())
5635 .setName(getSurfaceControl() + " - animation-bounds");
5636 final SurfaceControl boundsLayer = builder.build();
5637 t.show(boundsLayer);
5638 return boundsLayer;
5639 }
5640
Garfield Tane8d84ab2019-10-11 09:49:40 -07005641 @Override
5642 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
5643 return mAnimatingActivityRegistry != null
5644 && mAnimatingActivityRegistry.notifyAboutToFinish(
5645 this, endDeferFinishCallback);
5646 }
5647
5648 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
5649 if (mWmService.mDisableTransitionAnimation
5650 || !isVisible()
5651 || getDisplayContent().mAppTransition.isTransitionSet()
5652 || getSurfaceControl() == null) {
5653 return false;
5654 }
5655 // Only do an animation into and out-of freeform mode for now. Other mode
5656 // transition animations are currently handled by system-ui.
5657 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
5658 }
5659
lumark9bca6b42019-10-17 18:35:22 +08005660 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07005661 boolean isWaitingForTransitionStart() {
5662 final DisplayContent dc = getDisplayContent();
Wale Ogunwale2322bed2019-10-10 17:24:19 +02005663 // TODO(display-unify): Test for null can be removed once unification is done.
Garfield Tane8d84ab2019-10-11 09:49:40 -07005664 if (dc == null) return false;
5665 return dc.mAppTransition.isTransitionSet()
5666 && (dc.mOpeningApps.contains(this)
5667 || dc.mClosingApps.contains(this)
5668 || dc.mChangingApps.contains(this));
5669 }
5670
5671 /**
5672 * Initializes a change transition. Because the app is visible already, there is a small period
5673 * of time where the user can see the app content/window update before the transition starts.
5674 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
5675 * "freezes" the location/crop until the transition starts.
5676 * <p>
5677 * Here's a walk-through of the process:
5678 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
5679 * 2. Set the temporary leash's position/crop to the current state.
5680 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
5681 * 4. Once the transition is ready, it will reparent the app to the animation leash.
5682 * 5. Detach the interim-change-leash.
5683 */
5684 private void initializeChangeTransition(Rect startBounds) {
5685 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
5686 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
5687 mDisplayContent.mChangingApps.add(this);
5688 mTransitStartRect.set(startBounds);
5689
5690 final SurfaceControl.Builder builder = makeAnimationLeash()
5691 .setParent(getAnimationLeashParent())
5692 .setName(getSurfaceControl() + " - interim-change-leash");
5693 mTransitChangeLeash = builder.build();
5694 Transaction t = getPendingTransaction();
5695 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
5696 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
5697 t.show(mTransitChangeLeash);
5698 t.reparent(getSurfaceControl(), mTransitChangeLeash);
5699 onAnimationLeashCreated(t, mTransitChangeLeash);
5700
5701 // Skip creating snapshot if this transition is controlled by a remote animator which
5702 // doesn't need it.
5703 ArraySet<Integer> activityTypes = new ArraySet<>();
5704 activityTypes.add(getActivityType());
5705 RemoteAnimationAdapter adapter =
5706 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
5707 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
5708 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
5709 return;
5710 }
5711
Garfield Tane8d84ab2019-10-11 09:49:40 -07005712 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
5713 SurfaceControl.ScreenshotGraphicBuffer snapshot =
5714 mWmService.mTaskSnapshotController.createTaskSnapshot(
5715 task, 1 /* scaleFraction */);
5716 if (snapshot != null) {
lumarkbc0032a2019-11-01 21:38:13 +08005717 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory, t, this,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005718 snapshot.getGraphicBuffer(), true /* relative */);
5719 }
5720 }
5721 }
5722
5723 @Override
5724 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
5725 // The leash is parented to the animation layer. We need to preserve the z-order by using
5726 // the prefix order index, but we boost if necessary.
5727 int layer = 0;
5728 if (!inPinnedWindowingMode()) {
5729 layer = getPrefixOrderIndex();
5730 } else {
5731 // Pinned stacks have animations take place within themselves rather than an animation
5732 // layer so we need to preserve the order relative to the stack (e.g. the order of our
5733 // task/parent).
5734 layer = getParent().getPrefixOrderIndex();
5735 }
5736
5737 if (mNeedsZBoost) {
5738 layer += Z_BOOST_BASE;
5739 }
5740 if (!mNeedsAnimationBoundsLayer) {
5741 t.setLayer(leash, layer);
5742 }
5743
5744 final DisplayContent dc = getDisplayContent();
5745 dc.assignStackOrdering();
5746
5747 if (leash == mTransitChangeLeash) {
5748 // This is a temporary state so skip any animation notifications
5749 return;
5750 } else if (mTransitChangeLeash != null) {
5751 // unparent mTransitChangeLeash for clean-up
5752 clearChangeLeash(t, false /* cancel */);
5753 }
5754
5755 if (mAnimatingActivityRegistry != null) {
5756 mAnimatingActivityRegistry.notifyStarting(this);
5757 }
5758
5759 // If the animation needs to be cropped then an animation bounds layer is created as a child
5760 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
5761 if (mNeedsAnimationBoundsLayer) {
5762 mTmpRect.setEmpty();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005763 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
5764 getTransit(), task)) {
5765 task.getBounds(mTmpRect);
5766 } else {
Louis Changdc077272019-11-12 16:52:56 +08005767 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005768 if (stack == null) {
5769 return;
5770 }
5771 // Set clip rect to stack bounds.
5772 stack.getBounds(mTmpRect);
5773 }
5774 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
5775
5776 // Crop to stack bounds.
5777 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
5778 t.setLayer(mAnimationBoundsLayer, layer);
5779
5780 // Reparent leash to animation bounds layer.
5781 t.reparent(leash, mAnimationBoundsLayer);
5782 }
5783 }
5784
5785 @Override
5786 void prepareSurfaces() {
Issei Suzuki7b9e2572019-11-14 16:19:54 +01005787 final boolean show = !isHidden() || isAnimating();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005788
5789 if (mSurfaceControl != null) {
5790 if (show && !mLastSurfaceShowing) {
5791 getPendingTransaction().show(mSurfaceControl);
5792 } else if (!show && mLastSurfaceShowing) {
5793 getPendingTransaction().hide(mSurfaceControl);
5794 }
5795 }
5796 if (mThumbnail != null) {
5797 mThumbnail.setShowing(getPendingTransaction(), show);
5798 }
5799 mLastSurfaceShowing = show;
5800 super.prepareSurfaces();
5801 }
5802
5803 /**
5804 * @return Whether our {@link #getSurfaceControl} is currently showing.
5805 */
5806 boolean isSurfaceShowing() {
5807 return mLastSurfaceShowing;
5808 }
5809
5810 boolean isInChangeTransition() {
5811 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
5812 }
5813
5814 void attachThumbnailAnimation() {
lumark9bca6b42019-10-17 18:35:22 +08005815 if (!isAnimating()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005816 return;
5817 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005818 final GraphicBuffer thumbnailHeader =
Louis Changcdec0802019-11-11 11:45:07 +08005819 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005820 if (thumbnailHeader == null) {
Louis Changcdec0802019-11-11 11:45:07 +08005821 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005822 return;
5823 }
5824 clearThumbnail();
lumarkbc0032a2019-11-01 21:38:13 +08005825 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
5826 getPendingTransaction(), this, thumbnailHeader);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005827 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
5828 }
5829
5830 /**
5831 * Attaches a surface with a thumbnail for the
5832 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
5833 */
5834 void attachCrossProfileAppsThumbnailAnimation() {
lumark9bca6b42019-10-17 18:35:22 +08005835 if (!isAnimating()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005836 return;
5837 }
5838 clearThumbnail();
5839
5840 final WindowState win = findMainWindow();
5841 if (win == null) {
5842 return;
5843 }
5844 final Rect frame = win.getFrameLw();
Louis Changcdec0802019-11-11 11:45:07 +08005845 final int thumbnailDrawableRes = task.mUserId == mWmService.mCurrentUserId
Garfield Tane8d84ab2019-10-11 09:49:40 -07005846 ? R.drawable.ic_account_circle
5847 : R.drawable.ic_corp_badge;
5848 final GraphicBuffer thumbnail =
5849 getDisplayContent().mAppTransition
5850 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
5851 if (thumbnail == null) {
5852 return;
5853 }
lumarkbc0032a2019-11-01 21:38:13 +08005854 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005855 getPendingTransaction(), this, thumbnail);
5856 final Animation animation =
5857 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
5858 win.getFrameLw());
5859 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
5860 frame.top));
5861 }
5862
5863 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
5864 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
5865
5866 // If this is a multi-window scenario, we use the windows frame as
5867 // destination of the thumbnail header animation. If this is a full screen
5868 // window scenario, we use the whole display as the target.
5869 WindowState win = findMainWindow();
5870 Rect appRect = win != null ? win.getContentFrameLw() :
5871 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
5872 final Rect insets = win != null ? win.getContentInsets() : null;
5873 final Configuration displayConfig = mDisplayContent.getConfiguration();
5874 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Louis Changcdec0802019-11-11 11:45:07 +08005875 appRect, insets, thumbnailHeader, task, displayConfig.uiMode,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005876 displayConfig.orientation);
5877 }
5878
5879 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07005880 public void onAnimationLeashLost(Transaction t) {
5881 super.onAnimationLeashLost(t);
5882 if (mAnimationBoundsLayer != null) {
5883 t.remove(mAnimationBoundsLayer);
5884 mAnimationBoundsLayer = null;
5885 }
5886
5887 if (mAnimatingActivityRegistry != null) {
5888 mAnimatingActivityRegistry.notifyFinished(this);
5889 }
5890 }
5891
5892 @Override
5893 protected void onAnimationFinished() {
5894 super.onAnimationFinished();
5895
5896 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
5897 mTransit = TRANSIT_UNSET;
5898 mTransitFlags = 0;
5899 mNeedsZBoost = false;
5900 mNeedsAnimationBoundsLayer = false;
5901
5902 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
5903 "AppWindowToken");
5904
5905 clearThumbnail();
Issei Suzuki430a1112019-11-14 16:20:52 +01005906 setClientHidden(isHidden() && hiddenRequested);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005907
5908 getDisplayContent().computeImeTargetIfNeeded(this);
5909
5910 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
5911 + ": reportedVisible=" + reportedVisible
5912 + " okToDisplay=" + okToDisplay()
5913 + " okToAnimate=" + okToAnimate()
5914 + " startingDisplayed=" + startingDisplayed);
5915
5916 // clean up thumbnail window
5917 if (mThumbnail != null) {
5918 mThumbnail.destroy();
5919 mThumbnail = null;
5920 }
5921
5922 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
5923 // traverse the copy.
5924 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
5925 children.forEach(WindowState::onExitAnimationDone);
5926
5927 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
5928 scheduleAnimation();
5929
5930 if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
5931 || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
5932 // If all activities are already idle or there is an activity that must be
5933 // stopped immediately after visible, then we now need to make sure we perform
5934 // the full stop of this activity. This is because we won't do that while they are still
5935 // waiting for the animation to finish.
5936 if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
5937 mAtmService.mStackSupervisor.scheduleIdleLocked();
5938 }
5939 } else {
5940 // Instead of doing the full stop routine here, let's just hide any activities
5941 // we now can, and let them stop when the normal idle happens.
5942 mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
5943 false /* remove */, true /* processPausingActivities */);
5944 }
5945 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
5946 }
5947
5948 /**
5949 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
5950 * to another leash.
5951 */
5952 private void clearChangeLeash(Transaction t, boolean cancel) {
5953 if (mTransitChangeLeash == null) {
5954 return;
5955 }
5956 if (cancel) {
5957 clearThumbnail();
5958 SurfaceControl sc = getSurfaceControl();
5959 SurfaceControl parentSc = getParentSurfaceControl();
5960 // Don't reparent if surface is getting destroyed
5961 if (parentSc != null && sc != null) {
5962 t.reparent(sc, getParentSurfaceControl());
5963 }
5964 }
5965 t.hide(mTransitChangeLeash);
5966 t.remove(mTransitChangeLeash);
5967 mTransitChangeLeash = null;
5968 if (cancel) {
5969 onAnimationLeashLost(t);
5970 }
5971 }
5972
5973 void clearAnimatingFlags() {
5974 boolean wallpaperMightChange = false;
5975 for (int i = mChildren.size() - 1; i >= 0; i--) {
5976 final WindowState win = mChildren.get(i);
5977 wallpaperMightChange |= win.clearAnimatingFlags();
5978 }
5979 if (wallpaperMightChange) {
5980 requestUpdateWallpaperIfNeeded();
5981 }
5982 }
5983
Garfield Tane8d84ab2019-10-11 09:49:40 -07005984 @Override
5985 void cancelAnimation() {
5986 cancelAnimationOnly();
5987 clearThumbnail();
5988 clearChangeLeash(getPendingTransaction(), true /* cancel */);
5989 }
5990
5991 /**
5992 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
5993 * or interim leashes.
5994 * <p>
5995 * Used when canceling in preparation for starting a new animation.
5996 */
5997 void cancelAnimationOnly() {
5998 super.cancelAnimation();
5999 }
6000
6001 @VisibleForTesting
lumarkbc0032a2019-11-01 21:38:13 +08006002 WindowContainerThumbnail getThumbnail() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006003 return mThumbnail;
6004 }
6005
6006 private void clearThumbnail() {
6007 if (mThumbnail == null) {
6008 return;
6009 }
6010 mThumbnail.destroy();
6011 mThumbnail = null;
6012 }
6013
6014 public int getTransit() {
6015 return mTransit;
6016 }
6017
6018 int getTransitFlags() {
6019 return mTransitFlags;
6020 }
6021
6022 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
6023 mRemoteAnimationDefinition = definition;
6024 }
6025
6026 RemoteAnimationDefinition getRemoteAnimationDefinition() {
6027 return mRemoteAnimationDefinition;
6028 }
6029
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006030 void setRequestedOrientation(int requestedOrientation) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006031 setOrientation(requestedOrientation, mayFreezeScreenLocked());
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006032 mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07006033 task.mTaskId, requestedOrientation);
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006034 }
6035
Garfield Tan90b04282018-12-11 14:04:42 -08006036 private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
Evan Rosky730f6e82018-12-03 17:40:11 -08006037 final IBinder binder =
6038 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006039 setOrientation(requestedOrientation, binder, this);
Garfield Tan36a69ad2019-01-16 17:08:23 -08006040
6041 // Push the new configuration to the requested app in case where it's not pushed, e.g. when
6042 // the request is handled at task level with letterbox.
6043 if (!getMergedOverrideConfiguration().equals(
6044 mLastReportedConfiguration.getMergedConfiguration())) {
6045 ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
6046 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08006047 }
6048
Garfield Tane8d84ab2019-10-11 09:49:40 -07006049 void reportDescendantOrientationChangeIfNeeded() {
6050 // Orientation request is exposed only when we're visible. Therefore visibility change
6051 // will change requested orientation. Notify upward the hierarchy ladder to adjust
6052 // configuration. This is important to cases where activities with incompatible
6053 // orientations launch, or user goes back from an activity of bi-orientation to an
6054 // activity with specified orientation.
6055 if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
6056 return;
6057 }
6058
6059 final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
6060 onDescendantOrientationChanged(freezeToken, this);
6061 }
6062
6063 /**
6064 * We override because this class doesn't want its children affecting its reported orientation
6065 * in anyway.
6066 */
6067 @Override
6068 int getOrientation(int candidate) {
6069 if (candidate == SCREEN_ORIENTATION_BEHIND) {
6070 // Allow app to specify orientation regardless of its visibility state if the current
6071 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
6072 // wants us to use the orientation of the app behind it.
6073 return mOrientation;
6074 }
6075
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08006076 // The {@link ActivityRecord} should only specify an orientation when it is not closing.
6077 // Allowing closing {@link ActivityRecord} to participate can lead to an Activity in another
6078 // task being started in the wrong orientation during the transition.
6079 if (!getDisplayContent().mClosingApps.contains(this)
Garfield Tane8d84ab2019-10-11 09:49:40 -07006080 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
6081 return mOrientation;
6082 }
6083
6084 return SCREEN_ORIENTATION_UNSET;
6085 }
6086
6087 /** Returns the app's preferred orientation regardless of its currently visibility state. */
6088 int getRequestedOrientation() {
6089 return mOrientation;
6090 }
6091
Bryce Leea163b762017-01-24 11:05:01 -08006092 /**
6093 * Set the last reported global configuration to the client. Should be called whenever a new
6094 * global configuration is sent to the client for this activity.
6095 */
6096 void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006097 mLastReportedConfiguration.setGlobalConfiguration(config);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006098 }
6099
Bryce Leea163b762017-01-24 11:05:01 -08006100 /**
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006101 * Set the last reported configuration to the client. Should be called whenever
Bryce Leea163b762017-01-24 11:05:01 -08006102 * a new merged configuration is sent to the client for this activity.
6103 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006104 void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006105 setLastReportedConfiguration(config.getGlobalConfiguration(),
6106 config.getOverrideConfiguration());
Bryce Leea163b762017-01-24 11:05:01 -08006107 }
6108
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07006109 private void setLastReportedConfiguration(Configuration global, Configuration override) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006110 mLastReportedConfiguration.setConfiguration(global, override);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006111 }
6112
Riddle Hsu0a343c32018-12-21 00:40:48 +08006113 /**
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006114 * @return {@code true} if this activity is in size compatibility mode that uses the different
6115 * density or bounds from its parent.
6116 */
6117 boolean inSizeCompatMode() {
Evan Rosky72f084d2019-09-11 17:05:16 -07006118 if (mCompatDisplayInsets == null || !shouldUseSizeCompatMode()) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006119 return false;
6120 }
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006121 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu04164182019-03-07 18:03:27 +08006122 final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
6123 if (resolvedAppBounds == null) {
6124 // The override configuration has not been resolved yet.
6125 return false;
6126 }
6127
6128 final Configuration parentConfig = getParent().getConfiguration();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006129 // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
6130 // fields should be changed with density and bounds, so here only compares the most
6131 // significant field.
6132 if (parentConfig.densityDpi != resolvedConfig.densityDpi) {
6133 return true;
6134 }
Riddle Hsu04164182019-03-07 18:03:27 +08006135
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006136 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
Riddle Hsuaec55442019-03-12 17:25:35 +08006137 final int appWidth = resolvedAppBounds.width();
6138 final int appHeight = resolvedAppBounds.height();
6139 final int parentAppWidth = parentAppBounds.width();
6140 final int parentAppHeight = parentAppBounds.height();
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006141 if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
6142 // Matched the parent bounds.
6143 return false;
6144 }
6145 if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
6146 // Both sides are smaller than the parent.
6147 return true;
6148 }
Riddle Hsuaec55442019-03-12 17:25:35 +08006149 if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
Riddle Hsu04164182019-03-07 18:03:27 +08006150 // One side is larger than the parent.
6151 return true;
6152 }
6153
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006154 // The rest of the condition is that only one side is smaller than the parent, but it still
6155 // needs to exclude the cases where the size is limited by the fixed aspect ratio.
6156 if (info.maxAspectRatio > 0) {
Evan Rosky01775072019-09-11 17:28:07 -07006157 final float aspectRatio = Math.max(appWidth, appHeight) / Math.min(appWidth, appHeight);
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006158 if (aspectRatio >= info.maxAspectRatio) {
6159 // The current size has reached the max aspect ratio.
6160 return false;
Riddle Hsuaec55442019-03-12 17:25:35 +08006161 }
6162 }
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006163 if (info.minAspectRatio > 0) {
6164 // The activity should have at least the min aspect ratio, so this checks if the parent
6165 // still has available space to provide larger aspect ratio.
6166 final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
6167 / Math.min(parentAppWidth, parentAppHeight);
6168 if (parentAspectRatio <= info.minAspectRatio) {
6169 // The long side has reached the parent.
6170 return false;
6171 }
6172 }
6173 return true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006174 }
6175
6176 /**
Riddle Hsu0a343c32018-12-21 00:40:48 +08006177 * Indicates the activity will keep the bounds and screen configuration when it was first
6178 * launched, no matter how its parent changes.
6179 *
6180 * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
6181 * aspect ratio.
6182 */
Riddle Hsu74826262019-04-17 14:57:42 +08006183 boolean shouldUseSizeCompatMode() {
Riddle Hsu0a343c32018-12-21 00:40:48 +08006184 return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
6185 // The configuration of non-standard type should be enforced by system.
6186 && isActivityTypeStandard()
6187 && !mAtmService.mForceResizableActivities;
6188 }
6189
Garfield Tane8d84ab2019-10-11 09:49:40 -07006190 boolean hasSizeCompatBounds() {
6191 return mSizeCompatBounds != null;
6192 }
6193
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006194 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006195 private void updateSizeCompatMode() {
6196 if (mCompatDisplayInsets != null || !shouldUseSizeCompatMode()) {
6197 // The override configuration is set only once in size compatibility mode.
6198 return;
6199 }
6200 final Configuration parentConfig = getParent().getConfiguration();
6201 if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
6202 // Don't compute when launching in fullscreen and the fixed orientation is not the
6203 // current orientation. It is more accurately to compute the override bounds from
6204 // the updated configuration after the fixed orientation is applied.
6205 return;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006206 }
Riddle Hsu74826262019-04-17 14:57:42 +08006207
Evan Rosky72f084d2019-09-11 17:05:16 -07006208 Configuration overrideConfig = getRequestedOverrideConfiguration();
6209 final Configuration fullConfig = getConfiguration();
6210
6211 // Ensure the screen related fields are set. It is used to prevent activity relaunch
6212 // when moving between displays. For screenWidthDp and screenWidthDp, because they
6213 // are relative to bounds and density, they will be calculated in
Louis Changcdec0802019-11-11 11:45:07 +08006214 // {@link Task#computeConfigResourceOverrides} and the result will also be
Evan Rosky72f084d2019-09-11 17:05:16 -07006215 // relatively fixed.
6216 overrideConfig.colorMode = fullConfig.colorMode;
6217 overrideConfig.densityDpi = fullConfig.densityDpi;
6218 overrideConfig.screenLayout = fullConfig.screenLayout
6219 & (Configuration.SCREENLAYOUT_LONG_MASK
6220 | Configuration.SCREENLAYOUT_SIZE_MASK);
6221 // The smallest screen width is the short side of screen bounds. Because the bounds
6222 // and density won't be changed, smallestScreenWidthDp is also fixed.
6223 overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
6224 if (info.isFixedOrientation()) {
6225 // lock rotation too. When in size-compat, onConfigurationChanged will watch for and
6226 // apply runtime rotation changes.
6227 overrideConfig.windowConfiguration.setRotation(
6228 fullConfig.windowConfiguration.getRotation());
6229 }
6230
6231 // The role of CompatDisplayInsets is like the override bounds.
6232 final ActivityDisplay display = getDisplay();
6233 if (display != null) {
6234 mCompatDisplayInsets = new CompatDisplayInsets(display.mDisplayContent,
6235 getWindowConfiguration().getBounds(),
6236 getWindowConfiguration().tasksAreFloating());
6237 }
6238 }
6239
6240 private void clearSizeCompatMode() {
6241 mCompatDisplayInsets = null;
6242 onRequestedOverrideConfigurationChanged(EMPTY);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006243 }
6244
Garfield Tan0443b372019-01-04 15:00:13 -08006245 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006246 public boolean matchParentBounds() {
6247 if (super.matchParentBounds()) {
6248 return true;
6249 }
6250 // An activity in size compatibility mode may have override bounds which equals to its
6251 // parent bounds, so the exact bounds should also be checked.
6252 final WindowContainer parent = getParent();
6253 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
6254 }
6255
6256 @Override
6257 float getSizeCompatScale() {
6258 return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
6259 }
6260
6261 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006262 void resolveOverrideConfiguration(Configuration newParentConfiguration) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006263 Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu74826262019-04-17 14:57:42 +08006264 if (mCompatDisplayInsets != null) {
Riddle Hsu04164182019-03-07 18:03:27 +08006265 resolveSizeCompatModeConfiguration(newParentConfiguration);
6266 } else {
6267 super.resolveOverrideConfiguration(newParentConfiguration);
Evan Rosky72f084d2019-09-11 17:05:16 -07006268 applyAspectRatio(resolvedConfig.windowConfiguration.getBounds(),
6269 newParentConfiguration.windowConfiguration.getAppBounds(),
6270 newParentConfiguration.windowConfiguration.getBounds());
Riddle Hsu74826262019-04-17 14:57:42 +08006271 // If the activity has override bounds, the relative configuration (e.g. screen size,
6272 // layout) needs to be resolved according to the bounds.
Evan Rosky72f084d2019-09-11 17:05:16 -07006273 if (task != null && !resolvedConfig.windowConfiguration.getBounds().isEmpty()) {
Riddle Hsu04164182019-03-07 18:03:27 +08006274 task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
Riddle Hsu61987bc2019-04-03 13:08:47 +08006275 newParentConfiguration);
Riddle Hsu04164182019-03-07 18:03:27 +08006276 }
6277 }
Garfield Tan0443b372019-01-04 15:00:13 -08006278
6279 // Assign configuration sequence number into hierarchy because there is a different way than
6280 // ensureActivityConfiguration() in this class that uses configuration in WindowState during
6281 // layout traversals.
6282 mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
6283 getResolvedOverrideConfiguration().seq = mConfigurationSeq;
Riddle Hsu04164182019-03-07 18:03:27 +08006284 }
Riddle Hsu0a343c32018-12-21 00:40:48 +08006285
Riddle Hsu74826262019-04-17 14:57:42 +08006286 /**
6287 * Resolves consistent screen configuration for orientation and rotation changes without
6288 * inheriting the parent bounds.
6289 */
Riddle Hsu04164182019-03-07 18:03:27 +08006290 private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006291 super.resolveOverrideConfiguration(newParentConfiguration);
Riddle Hsu0a343c32018-12-21 00:40:48 +08006292 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu04164182019-03-07 18:03:27 +08006293 final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
Riddle Hsu0a343c32018-12-21 00:40:48 +08006294
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006295 Rect parentBounds = new Rect(newParentConfiguration.windowConfiguration.getBounds());
Riddle Hsu0a343c32018-12-21 00:40:48 +08006296
Evan Rosky72f084d2019-09-11 17:05:16 -07006297 int orientation = getRequestedConfigurationOrientation();
6298 if (orientation == ORIENTATION_UNDEFINED) {
6299 orientation = newParentConfiguration.orientation;
6300 }
6301 int rotation = resolvedConfig.windowConfiguration.getRotation();
6302 if (rotation == ROTATION_UNDEFINED) {
6303 rotation = newParentConfiguration.windowConfiguration.getRotation();
6304 }
6305
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006306 // Use compat insets to lock width and height. We should not use the parent width and height
6307 // because apps in compat mode should have a constant width and height. The compat insets
6308 // are locked when the app is first launched and are never changed after that, so we can
6309 // rely on them to contain the original and unchanging width and height of the app.
6310 final Rect compatDisplayBounds = mTmpBounds;
Evan Rosky72f084d2019-09-11 17:05:16 -07006311 mCompatDisplayInsets.getDisplayBoundsByRotation(compatDisplayBounds, rotation);
6312 final Rect containingAppBounds = new Rect();
6313 mCompatDisplayInsets.getFrameByOrientation(containingAppBounds, orientation);
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006314
Evan Rosky72f084d2019-09-11 17:05:16 -07006315 // Center containingAppBounds horizontally and aligned to top of parent. Both
6316 // are usually the same unless the app was frozen with an orientation letterbox.
6317 int left = compatDisplayBounds.left + compatDisplayBounds.width() / 2
6318 - containingAppBounds.width() / 2;
6319 resolvedBounds.set(left, compatDisplayBounds.top, left + containingAppBounds.width(),
6320 compatDisplayBounds.top + containingAppBounds.height());
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006321
Evan Rosky72f084d2019-09-11 17:05:16 -07006322 if (rotation != ROTATION_UNDEFINED) {
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006323 // Ensure the parent and container bounds won't overlap with insets.
Louis Changcdec0802019-11-11 11:45:07 +08006324 Task.intersectWithInsetsIfFits(containingAppBounds, compatDisplayBounds,
Evan Rosky72f084d2019-09-11 17:05:16 -07006325 mCompatDisplayInsets.mNonDecorInsets[rotation]);
Louis Changcdec0802019-11-11 11:45:07 +08006326 Task.intersectWithInsetsIfFits(parentBounds, compatDisplayBounds,
Evan Rosky72f084d2019-09-11 17:05:16 -07006327 mCompatDisplayInsets.mNonDecorInsets[rotation]);
Riddle Hsu74826262019-04-17 14:57:42 +08006328 }
6329
Evan Rosky72f084d2019-09-11 17:05:16 -07006330 applyAspectRatio(resolvedBounds, containingAppBounds, compatDisplayBounds);
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006331
6332 // Center horizontally in parent and align to top of parent - this is a UX choice
Evan Rosky72f084d2019-09-11 17:05:16 -07006333 left = parentBounds.left + parentBounds.width() / 2 - resolvedBounds.width() / 2;
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006334 resolvedBounds.set(left, parentBounds.top, left + resolvedBounds.width(),
6335 parentBounds.top + resolvedBounds.height());
6336
6337 // We want to get as much of the app on the screen even if insets cover it. This is because
6338 // insets change but an app's bounds are more permanent after launch. After computing insets
6339 // and horizontally centering resolvedBounds, the resolvedBounds may end up outside parent
6340 // bounds. This is okay only if the resolvedBounds exceed their parent on the bottom and
6341 // right, because that is clipped when the final bounds are computed. To reach this state,
6342 // we first try and push the app as much inside the parent towards the top and left (the
6343 // min). The app may then end up outside the parent by going too far left and top, so we
6344 // push it back into the parent by taking the max with parent left and top.
6345 Rect fullParentBounds = newParentConfiguration.windowConfiguration.getBounds();
6346 resolvedBounds.offsetTo(Math.max(fullParentBounds.left,
6347 Math.min(fullParentBounds.right - resolvedBounds.width(), resolvedBounds.left)),
6348 Math.max(fullParentBounds.top,
6349 Math.min(fullParentBounds.bottom - resolvedBounds.height(),
6350 resolvedBounds.top)));
6351
6352 // Use resolvedBounds to compute other override configurations such as appBounds
Riddle Hsu74826262019-04-17 14:57:42 +08006353 task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
6354 mCompatDisplayInsets);
6355
Riddle Hsu04164182019-03-07 18:03:27 +08006356 // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
6357 // the parent bounds appropriately.
6358 if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
6359 resolvedConfig.orientation = newParentConfiguration.orientation;
Riddle Hsu0a343c32018-12-21 00:40:48 +08006360 }
Garfield Tan0443b372019-01-04 15:00:13 -08006361 }
6362
6363 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006364 public Rect getBounds() {
6365 if (mSizeCompatBounds != null) {
6366 return mSizeCompatBounds;
6367 }
6368 return super.getBounds();
6369 }
6370
6371 @Override
6372 Rect getDisplayedBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006373 if (task != null) {
6374 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
6375 if (!overrideDisplayedBounds.isEmpty()) {
6376 return overrideDisplayedBounds;
6377 }
6378 }
6379 return getBounds();
6380 }
6381
6382 @VisibleForTesting
lumark19a5d2e2019-10-11 16:19:30 +08006383 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006384 Rect getAnimationBounds(int appStackClipMode) {
6385 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
6386 // Using the stack bounds here effectively applies the clipping before animation.
6387 return getStack().getBounds();
6388 }
6389 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
6390 // included in the animation.
Louis Changcdec0802019-11-11 11:45:07 +08006391 return task != null ? task.getBounds() : getBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006392 }
6393
6394 /**
6395 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
6396 * region which is available to application.
6397 */
6398 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
6399 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
6400 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
6401 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
6402 final Rect appBounds = getWindowConfiguration().getAppBounds();
6403 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
6404 final float contentW = contentBounds.width();
6405 final float contentH = contentBounds.height();
6406 final float viewportW = viewportBounds.width();
6407 final float viewportH = viewportBounds.height();
6408 // Only allow to scale down.
6409 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
6410 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
6411 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
6412 + viewportBounds.left;
6413
6414 if (mSizeCompatBounds == null) {
6415 mSizeCompatBounds = new Rect();
6416 }
6417 mSizeCompatBounds.set(contentBounds);
6418 mSizeCompatBounds.offsetTo(0, 0);
6419 mSizeCompatBounds.scale(mSizeCompatScale);
6420 // Ensure to align the top with the parent.
6421 mSizeCompatBounds.top = parentBounds.top;
6422 // The decor inset is included in height.
6423 mSizeCompatBounds.bottom += viewportBounds.top;
6424 mSizeCompatBounds.left += offsetX;
6425 mSizeCompatBounds.right += offsetX;
6426 }
6427
6428 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006429 public void onConfigurationChanged(Configuration newParentConfig) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006430 if (mCompatDisplayInsets != null) {
6431 Configuration overrideConfig = getRequestedOverrideConfiguration();
6432 // Adapt to changes in orientation locking. The app is still non-resizable, but
6433 // it can change which orientation is fixed. If the fixed orientation changes,
6434 // update the rotation used on the "compat" display
6435 boolean wasFixedOrient =
6436 overrideConfig.windowConfiguration.getRotation() != ROTATION_UNDEFINED;
6437 int requestedOrient = getRequestedConfigurationOrientation();
6438 if (requestedOrient != ORIENTATION_UNDEFINED
6439 && requestedOrient != getConfiguration().orientation
6440 // The task orientation depends on the top activity orientation, so it
6441 // should match. If it doesn't, just wait until it does.
6442 && requestedOrient == getParent().getConfiguration().orientation
6443 && (overrideConfig.windowConfiguration.getRotation()
6444 != getParent().getWindowConfiguration().getRotation())) {
6445 overrideConfig.windowConfiguration.setRotation(
6446 getParent().getWindowConfiguration().getRotation());
6447 onRequestedOverrideConfigurationChanged(overrideConfig);
6448 return;
6449 } else if (wasFixedOrient && requestedOrient == ORIENTATION_UNDEFINED
6450 && (overrideConfig.windowConfiguration.getRotation()
6451 != ROTATION_UNDEFINED)) {
6452 overrideConfig.windowConfiguration.setRotation(ROTATION_UNDEFINED);
6453 onRequestedOverrideConfigurationChanged(overrideConfig);
6454 return;
6455 }
6456 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07006457 final int prevWinMode = getWindowingMode();
6458 mTmpPrevBounds.set(getBounds());
Garfield Tan0443b372019-01-04 15:00:13 -08006459 super.onConfigurationChanged(newParentConfig);
6460
Garfield Tane8d84ab2019-10-11 09:49:40 -07006461 final Rect overrideBounds = getResolvedOverrideBounds();
6462 if (task != null && !overrideBounds.isEmpty()
6463 // If the changes come from change-listener, the incoming parent configuration is
6464 // still the old one. Make sure their orientations are the same to reduce computing
6465 // the compatibility bounds for the intermediate state.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02006466 && (task.getConfiguration().orientation == newParentConfig.orientation)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006467 final Rect taskBounds = task.getBounds();
6468 // Since we only center the activity horizontally, if only the fixed height is smaller
6469 // than its container, the override bounds don't need to take effect.
6470 if ((overrideBounds.width() != taskBounds.width()
6471 || overrideBounds.height() > taskBounds.height())) {
6472 calculateCompatBoundsTransformation(newParentConfig);
6473 updateSurfacePosition();
6474 } else if (mSizeCompatBounds != null) {
6475 mSizeCompatBounds = null;
6476 mSizeCompatScale = 1f;
6477 updateSurfacePosition();
6478 }
Evan Rosky72f084d2019-09-11 17:05:16 -07006479 } else if (overrideBounds.isEmpty()) {
6480 mSizeCompatBounds = null;
6481 mSizeCompatScale = 1f;
6482 updateSurfacePosition();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006483 }
6484
Hongwei Wange75e1912019-11-07 16:00:32 -08006485 final int newWinMode = getWindowingMode();
6486 if ((prevWinMode != newWinMode) && (mDisplayContent != null)
6487 && shouldStartChangeTransition(prevWinMode, newWinMode)) {
6488 initializeChangeTransition(mTmpPrevBounds);
6489 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07006490
Garfield Tan0443b372019-01-04 15:00:13 -08006491 // Configuration's equality doesn't consider seq so if only seq number changes in resolved
6492 // override configuration. Therefore ConfigurationContainer doesn't change merged override
6493 // configuration, but it's used to push configuration changes so explicitly update that.
6494 if (getMergedOverrideConfiguration().seq != getResolvedOverrideConfiguration().seq) {
6495 onMergedOverrideConfigurationChanged();
6496 }
6497
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006498 final ActivityDisplay display = getDisplay();
Riddle Hsuaec55442019-03-12 17:25:35 +08006499 if (display == null) {
6500 return;
6501 }
Issei Suzuki430a1112019-11-14 16:20:52 +01006502 if (visible) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006503 // It may toggle the UI for user to restart the size compatibility mode activity.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006504 display.handleActivitySizeCompatModeIfNeeded(this);
Evan Rosky72f084d2019-09-11 17:05:16 -07006505 } else if (mCompatDisplayInsets != null) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006506 // The override changes can only be obtained from display, because we don't have the
6507 // difference of full configuration in each hierarchy.
6508 final int displayChanges = display.getLastOverrideConfigurationChanges();
6509 final int orientationChanges = CONFIG_WINDOW_CONFIGURATION
6510 | CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION;
6511 final boolean hasNonOrienSizeChanged = hasResizeChange(displayChanges)
6512 // Filter out the case of simple orientation change.
6513 && (displayChanges & orientationChanges) != orientationChanges;
6514 // For background activity that uses size compatibility mode, if the size or density of
6515 // the display is changed, then reset the override configuration and kill the activity's
6516 // process if its process state is not important to user.
6517 if (hasNonOrienSizeChanged || (displayChanges & ActivityInfo.CONFIG_DENSITY) != 0) {
6518 restartProcessIfVisible();
6519 }
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006520 }
Garfield Tan0443b372019-01-04 15:00:13 -08006521 }
6522
Hongwei Wange75e1912019-11-07 16:00:32 -08006523 void savePinnedStackBounds() {
6524 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
6525 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
Louis Changdc077272019-11-12 16:52:56 +08006526 final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
Hongwei Wange75e1912019-11-07 16:00:32 -08006527 if (pinnedStack == null) return;
6528 final Rect stackBounds;
6529 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
6530 // We are animating the bounds, use the pre-animation bounds to save the snap
6531 // fraction
6532 stackBounds = pinnedStack.mPreAnimationBounds;
6533 } else {
6534 // We skip the animation if the fullscreen configuration is not compatible, so
6535 // use the current bounds to calculate the saved snap fraction instead
6536 // (see PinnedActivityStack.skipResizeAnimation())
6537 stackBounds = mTmpRect;
6538 pinnedStack.getBounds(stackBounds);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006539 }
Hongwei Wange75e1912019-11-07 16:00:32 -08006540 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
6541 mActivityComponent, stackBounds);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006542 }
6543
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006544 /** Returns true if the configuration is compatible with this activity. */
Wale Ogunwale42f07d92017-05-01 21:32:58 -07006545 boolean isConfigurationCompatible(Configuration config) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006546 final int orientation = getRequestedOrientation();
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006547 if (isFixedOrientationPortrait(orientation)
6548 && config.orientation != ORIENTATION_PORTRAIT) {
6549 return false;
6550 }
6551 if (isFixedOrientationLandscape(orientation)
6552 && config.orientation != ORIENTATION_LANDSCAPE) {
6553 return false;
6554 }
6555 return true;
6556 }
6557
Bryce Lee7566d762017-03-30 09:34:15 -07006558 /**
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006559 * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
6560 * made to outBounds.
Bryce Lee7566d762017-03-30 09:34:15 -07006561 */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006562 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006563 private void applyAspectRatio(Rect outBounds, Rect containingAppBounds,
6564 Rect containingBounds) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006565 final float maxAspectRatio = info.maxAspectRatio;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006566 final ActivityStack stack = getActivityStack();
Adrian Roos917791e2018-11-28 16:30:44 +01006567 final float minAspectRatio = info.minAspectRatio;
6568
Evan Rosky72f084d2019-09-11 17:05:16 -07006569 if (task == null || stack == null || (inMultiWindowMode() && !shouldUseSizeCompatMode())
Adrian Roos917791e2018-11-28 16:30:44 +01006570 || (maxAspectRatio == 0 && minAspectRatio == 0)
Bryce Leee5ab4502017-07-11 08:58:05 -07006571 || isInVrUiMode(getConfiguration())) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006572 // We don't enforce aspect ratio if the activity task is in multiwindow unless it
6573 // is in size-compat mode. We also don't set it if we are in VR mode.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006574 return;
6575 }
6576
Riddle Hsu74826262019-04-17 14:57:42 +08006577 final int containingAppWidth = containingAppBounds.width();
6578 final int containingAppHeight = containingAppBounds.height();
Adrian Roos917791e2018-11-28 16:30:44 +01006579 final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
6580 / (float) Math.min(containingAppWidth, containingAppHeight);
Bryce Lee7566d762017-03-30 09:34:15 -07006581
Adrian Roos917791e2018-11-28 16:30:44 +01006582 int activityWidth = containingAppWidth;
6583 int activityHeight = containingAppHeight;
6584
6585 if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
6586 if (containingAppWidth < containingAppHeight) {
6587 // Width is the shorter side, so we use that to figure-out what the max. height
6588 // should be given the aspect ratio.
6589 activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
6590 } else {
6591 // Height is the shorter side, so we use that to figure-out what the max. width
6592 // should be given the aspect ratio.
6593 activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
6594 }
Tiger Huang3d2b8982019-01-29 22:56:48 +08006595 } else if (containingRatio < minAspectRatio) {
6596 boolean adjustWidth;
6597 switch (getRequestedConfigurationOrientation()) {
6598 case ORIENTATION_LANDSCAPE:
6599 // Width should be the longer side for this landscape app, so we use the width
6600 // to figure-out what the max. height should be given the aspect ratio.
6601 adjustWidth = false;
6602 break;
6603 case ORIENTATION_PORTRAIT:
6604 // Height should be the longer side for this portrait app, so we use the height
6605 // to figure-out what the max. width should be given the aspect ratio.
6606 adjustWidth = true;
6607 break;
6608 default:
6609 // This app doesn't have a preferred orientation, so we keep the length of the
6610 // longer side, and use it to figure-out the length of the shorter side.
6611 if (containingAppWidth < containingAppHeight) {
6612 // Width is the shorter side, so we use the height to figure-out what the
6613 // max. width should be given the aspect ratio.
6614 adjustWidth = true;
6615 } else {
6616 // Height is the shorter side, so we use the width to figure-out what the
6617 // max. height should be given the aspect ratio.
6618 adjustWidth = false;
6619 }
6620 break;
6621 }
6622 if (adjustWidth) {
Adrian Roos917791e2018-11-28 16:30:44 +01006623 activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
6624 } else {
Adrian Roos917791e2018-11-28 16:30:44 +01006625 activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
6626 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006627 }
6628
Adrian Roos917791e2018-11-28 16:30:44 +01006629 if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006630 // The display matches or is less than the activity aspect ratio, so nothing else to do.
6631 return;
6632 }
6633
6634 // Compute configuration based on max supported width and height.
Adrian Roos24be34d2018-05-28 18:55:38 +02006635 // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
Louis Changcdec0802019-11-11 11:45:07 +08006636 // away later in {@link Task#computeConfigResourceOverrides()}. Otherwise, the app
Adrian Roos24be34d2018-05-28 18:55:38 +02006637 // bounds would end up too small.
Evan Rosky72f084d2019-09-11 17:05:16 -07006638 outBounds.set(containingBounds.left, containingBounds.top,
6639 activityWidth + containingAppBounds.left,
Riddle Hsu74826262019-04-17 14:57:42 +08006640 activityHeight + containingAppBounds.top);
Andrii Kulian3a1619d2017-07-07 14:38:09 -07006641 }
6642
Riddle Hsu16567132018-08-16 21:37:47 +08006643 /**
6644 * @return {@code true} if this activity was reparented to another display but
6645 * {@link #ensureActivityConfiguration} is not called.
6646 */
6647 boolean shouldUpdateConfigForDisplayChanged() {
6648 return mLastReportedDisplayId != getDisplayId();
6649 }
6650
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006651 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
6652 return ensureActivityConfiguration(globalChanges, preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006653 false /* ignoreVisibility */);
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006654 }
6655
Andrii Kulian21713ac2016-10-12 22:05:05 -07006656 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006657 * Make sure the given activity matches the current configuration. Ensures the HistoryRecord
6658 * is updated with the correct configuration and all other bookkeeping is handled.
6659 *
6660 * @param globalChanges The changes to the global configuration.
6661 * @param preserveWindow If the activity window should be preserved on screen if the activity
6662 * is relaunched.
Riddle Hsu609a8e22019-06-27 16:46:29 -06006663 * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
6664 * (stopped state). This is useful for the case where we know the
6665 * activity will be visible soon and we want to ensure its configuration
6666 * before we make it visible.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006667 * @return False if the activity was relaunched and true if it wasn't relaunched because we
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006668 * can't or the app handles the specific configuration that is changing.
Andrii Kulian21713ac2016-10-12 22:05:05 -07006669 */
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006670 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006671 boolean ignoreVisibility) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006672 final ActivityStack stack = getActivityStack();
Andrii Kulian21713ac2016-10-12 22:05:05 -07006673 if (stack.mConfigWillChange) {
6674 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6675 "Skipping config check (will change): " + this);
6676 return true;
6677 }
6678
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006679 // We don't worry about activities that are finishing.
6680 if (finishing) {
6681 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6682 "Configuration doesn't matter in finishing " + this);
6683 stopFreezingScreenLocked(false);
6684 return true;
6685 }
6686
Riddle Hsu609a8e22019-06-27 16:46:29 -06006687 if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006688 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006689 "Skipping config check invisible: " + this);
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006690 return true;
6691 }
6692
Andrii Kulian21713ac2016-10-12 22:05:05 -07006693 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6694 "Ensuring correct configuration: " + this);
6695
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006696 final int newDisplayId = getDisplayId();
6697 final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
6698 if (displayChanged) {
6699 mLastReportedDisplayId = newDisplayId;
6700 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006701 // TODO(b/36505427): Is there a better place to do this?
Evan Rosky72f084d2019-09-11 17:05:16 -07006702 updateSizeCompatMode();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006703
Winson Chungbdc646f2017-02-13 12:12:22 -08006704 // Short circuit: if the two full configurations are equal (the common case), then there is
6705 // nothing to do. We test the full configuration instead of the global and merged override
6706 // configurations because there are cases (like moving a task to the pinned stack) where
6707 // the combine configurations are equal, but would otherwise differ in the override config
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006708 mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
6709 if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006710 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006711 "Configuration & display unchanged in " + this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006712 return true;
6713 }
6714
6715 // Okay we now are going to make this activity have the new config.
6716 // But then we need to figure out how it needs to deal with that.
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006717
6718 // Find changes between last reported merged configuration and the current one. This is used
6719 // to decide whether to relaunch an activity or just report a configuration change.
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006720 final int changes = getConfigurationChanges(mTmpConfig);
Ruben Brunkf64af332017-03-22 22:03:25 -07006721
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006722 // Update last reported values.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006723 final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
Bryce Lee8104e7a2017-08-17 09:16:03 -07006724
Andrii Kulianbeadacc2019-05-20 12:18:01 +00006725 setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006726
Bryce Lee7ace3952018-02-16 14:34:32 -08006727 if (mState == INITIALIZING) {
Andrii Kulianb372da62018-01-18 10:46:24 -08006728 // No need to relaunch or schedule new config for activity that hasn't been launched
6729 // yet. We do, however, return after applying the config to activity record, so that
6730 // it will use it for launch transaction.
6731 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6732 "Skipping config check for initializing activity: " + this);
6733 return true;
6734 }
6735
Andrii Kulian21713ac2016-10-12 22:05:05 -07006736 if (changes == 0 && !forceNewConfig) {
6737 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6738 "Configuration no differences in " + this);
6739 // There are no significant differences, so we won't relaunch but should still deliver
6740 // the new configuration to the client process.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006741 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006742 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006743 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006744 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006745 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07006746 return true;
6747 }
6748
6749 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006750 "Configuration changes for " + this + ", allChanges="
Andrii Kulian21713ac2016-10-12 22:05:05 -07006751 + Configuration.configurationDiffToString(changes));
6752
6753 // If the activity isn't currently running, just leave the new configuration and it will
6754 // pick that up next time it starts.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006755 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006756 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6757 "Configuration doesn't matter not running " + this);
6758 stopFreezingScreenLocked(false);
6759 forceNewConfig = false;
6760 return true;
6761 }
6762
6763 // Figure out how to handle the changes between the configurations.
6764 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6765 "Checking to restart " + info.name + ": changed=0x"
6766 + Integer.toHexString(changes) + ", handles=0x"
6767 + Integer.toHexString(info.getRealConfigChanged())
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006768 + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006769
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006770 if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006771 // Aha, the activity isn't handling the change, so DIE DIE DIE.
6772 configChangeFlags |= changes;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006773 startFreezingScreenLocked(globalChanges);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006774 forceNewConfig = false;
6775 preserveWindow &= isResizeOnlyChange(changes);
Garfield Tan2746ab52018-07-25 12:33:01 -07006776 final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
6777 if (hasResizeChange) {
Louis Changcdec0802019-11-11 11:45:07 +08006778 final boolean isDragResizing = task.isDragResizing();
Garfield Tan2746ab52018-07-25 12:33:01 -07006779 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
6780 : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
6781 } else {
6782 mRelaunchReason = RELAUNCH_REASON_NONE;
6783 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006784 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006785 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6786 "Config is destroying non-running " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07006787 destroyImmediately(true /* removeFromApp */, "config");
Bryce Lee7ace3952018-02-16 14:34:32 -08006788 } else if (mState == PAUSING) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006789 // A little annoying: we are waiting for this activity to finish pausing. Let's not
6790 // do anything now, but just flag that it needs to be restarted when done pausing.
6791 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6792 "Config is skipping already pausing " + this);
6793 deferRelaunchUntilPaused = true;
6794 preserveWindowOnDeferredRelaunch = preserveWindow;
6795 return true;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006796 } else {
6797 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006798 "Config is relaunching " + this);
Issei Suzuki430a1112019-11-14 16:20:52 +01006799 if (DEBUG_STATES && !visible) {
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006800 Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
6801 + " called by " + Debug.getCallers(4));
6802 }
6803 relaunchActivityLocked(preserveWindow);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006804 }
6805
6806 // All done... tell the caller we weren't able to keep this activity around.
6807 return false;
6808 }
6809
6810 // Default case: the activity can handle this new configuration, so hand it over.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006811 // NOTE: We only forward the override configuration as the system level configuration
Andrii Kulian21713ac2016-10-12 22:05:05 -07006812 // changes is always sent to all processes when they happen so it can just use whatever
6813 // system level configuration it last got.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006814 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006815 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006816 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006817 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006818 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07006819 stopFreezingScreenLocked(false);
6820
6821 return true;
6822 }
6823
Zak Cohen90e7116742017-01-29 12:59:23 -08006824 /**
6825 * When assessing a configuration change, decide if the changes flags and the new configurations
6826 * should cause the Activity to relaunch.
Ruben Brunkf64af332017-03-22 22:03:25 -07006827 *
6828 * @param changes the changes due to the given configuration.
6829 * @param changesConfig the configuration that was used to calculate the given changes via a
6830 * call to getConfigurationChanges.
Zak Cohen90e7116742017-01-29 12:59:23 -08006831 */
Ruben Brunkf64af332017-03-22 22:03:25 -07006832 private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
Zak Cohen90e7116742017-01-29 12:59:23 -08006833 int configChanged = info.getRealConfigChanged();
Ruben Brunkf64af332017-03-22 22:03:25 -07006834 boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
Zak Cohen90e7116742017-01-29 12:59:23 -08006835
6836 // Override for apps targeting pre-O sdks
6837 // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
6838 // to the config change.
6839 // For O and later, apps will be required to add configChanges="uimode" to their manifest.
Andrii Kulianeceebbf2019-06-26 17:36:51 -07006840 if (info.applicationInfo.targetSdkVersion < O
Zak Cohen90e7116742017-01-29 12:59:23 -08006841 && requestedVrComponent != null
Ruben Brunkf64af332017-03-22 22:03:25 -07006842 && onlyVrUiModeChanged) {
Zak Cohen90e7116742017-01-29 12:59:23 -08006843 configChanged |= CONFIG_UI_MODE;
6844 }
6845
6846 return (changes&(~configChanged)) != 0;
6847 }
6848
Ruben Brunkf64af332017-03-22 22:03:25 -07006849 /**
6850 * Returns true if the configuration change is solely due to the UI mode switching into or out
6851 * of UI_MODE_TYPE_VR_HEADSET.
6852 */
6853 private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
6854 final Configuration currentConfig = getConfiguration();
Ruben Brunkf53497c2017-03-27 20:26:17 -07006855 return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
Ruben Brunkf64af332017-03-22 22:03:25 -07006856 != isInVrUiMode(lastReportedConfig));
6857 }
6858
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006859 private int getConfigurationChanges(Configuration lastReportedConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006860 // Determine what has changed. May be nothing, if this is a config that has come back from
6861 // the app after going idle. In that case we just want to leave the official config object
6862 // now in the activity and do nothing else.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006863 final Configuration currentConfig = getConfiguration();
6864 int changes = lastReportedConfig.diff(currentConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006865 // We don't want to use size changes if they don't cross boundaries that are important to
6866 // the app.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006867 if ((changes & CONFIG_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006868 final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
6869 currentConfig.screenWidthDp)
6870 || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
6871 currentConfig.screenHeightDp);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006872 if (!crosses) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006873 changes &= ~CONFIG_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006874 }
6875 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006876 if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006877 final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
6878 final int newSmallest = currentConfig.smallestScreenWidthDp;
6879 if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006880 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006881 }
6882 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07006883 // We don't want window configuration to cause relaunches.
6884 if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
6885 changes &= ~CONFIG_WINDOW_CONFIGURATION;
6886 }
Bryce Lee600dadd2017-07-25 10:48:42 -07006887
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006888 return changes;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006889 }
6890
6891 private static boolean isResizeOnlyChange(int change) {
6892 return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
6893 | CONFIG_SCREEN_LAYOUT)) == 0;
6894 }
6895
Garfield Tan2746ab52018-07-25 12:33:01 -07006896 private static boolean hasResizeChange(int change) {
6897 return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
6898 | CONFIG_SCREEN_LAYOUT)) != 0;
6899 }
6900
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006901 void relaunchActivityLocked(boolean preserveWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006902 if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006903 configChangeFlags = 0;
6904 return;
6905 }
6906
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006907 final boolean andResume = shouldBeResumed(null /*activeActivity*/);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006908 List<ResultInfo> pendingResults = null;
6909 List<ReferrerIntent> pendingNewIntents = null;
6910 if (andResume) {
6911 pendingResults = results;
6912 pendingNewIntents = newIntents;
6913 }
6914 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
6915 "Relaunching: " + this + " with results=" + pendingResults
6916 + " newIntents=" + pendingNewIntents + " andResume=" + andResume
6917 + " preserveWindow=" + preserveWindow);
Ruben Brunkf53497c2017-03-27 20:26:17 -07006918 EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006919 : AM_RELAUNCH_ACTIVITY, mUserId, System.identityHashCode(this),
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07006920 task.mTaskId, shortComponentName);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006921
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006922 startFreezingScreenLocked(0);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006923
Andrii Kulian21713ac2016-10-12 22:05:05 -07006924 try {
6925 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
6926 "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
6927 + " callers=" + Debug.getCallers(6));
6928 forceNewConfig = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006929 startRelaunching();
Andrii Kulianb372da62018-01-18 10:46:24 -08006930 final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
6931 pendingNewIntents, configChangeFlags,
Andrii Kulianbeadacc2019-05-20 12:18:01 +00006932 new MergedConfiguration(mAtmService.getGlobalConfiguration(),
Andrii Kulianb372da62018-01-18 10:46:24 -08006933 getMergedOverrideConfiguration()),
6934 preserveWindow);
6935 final ActivityLifecycleItem lifecycleItem;
6936 if (andResume) {
lumark588a3e82018-07-20 18:53:54 +08006937 lifecycleItem = ResumeActivityItem.obtain(
Wale Ogunwale3a256e62018-12-06 14:41:18 -08006938 getDisplay().mDisplayContent.isNextTransitionForward());
Andrii Kulianb372da62018-01-18 10:46:24 -08006939 } else {
Bryce Lee1d0d5142018-04-12 10:35:07 -07006940 lifecycleItem = PauseActivityItem.obtain();
Andrii Kulianb372da62018-01-18 10:46:24 -08006941 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006942 final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
Andrii Kulianb372da62018-01-18 10:46:24 -08006943 transaction.addCallback(callbackItem);
6944 transaction.setLifecycleStateRequest(lifecycleItem);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006945 mAtmService.getLifecycleManager().scheduleTransaction(transaction);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006946 // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
Andrii Kulianb372da62018-01-18 10:46:24 -08006947 // request resume if this activity is currently resumed, which implies we aren't
Andrii Kulian21713ac2016-10-12 22:05:05 -07006948 // sleeping.
6949 } catch (RemoteException e) {
6950 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
6951 }
6952
6953 if (andResume) {
6954 if (DEBUG_STATES) {
6955 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
6956 }
6957 results = null;
6958 newIntents = null;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006959 mAtmService.getAppWarningsLocked().onResumeActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006960 } else {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006961 final ActivityStack stack = getActivityStack();
Wale Ogunwale008163e2018-07-23 23:11:08 -07006962 if (stack != null) {
Andrii Kulian79d67982019-08-19 11:56:16 -07006963 stack.removePauseTimeoutForActivity(this);
Wale Ogunwale008163e2018-07-23 23:11:08 -07006964 }
Bryce Lee7ace3952018-02-16 14:34:32 -08006965 setState(PAUSED, "relaunchActivityLocked");
Andrii Kulian21713ac2016-10-12 22:05:05 -07006966 }
6967
6968 configChangeFlags = 0;
6969 deferRelaunchUntilPaused = false;
6970 preserveWindowOnDeferredRelaunch = false;
6971 }
6972
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006973 /**
6974 * Request the process of the activity to restart with its saved state (from
6975 * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
6976 * the override configuration. Note if the activity is in background, the process will be killed
6977 * directly with keeping its record.
6978 */
6979 void restartProcessIfVisible() {
6980 Slog.i(TAG, "Request to restart process of " + this);
6981
Riddle Hsuaec55442019-03-12 17:25:35 +08006982 // Reset the existing override configuration so it can be updated according to the latest
6983 // configuration.
Evan Rosky72f084d2019-09-11 17:05:16 -07006984 clearSizeCompatMode();
Issei Suzuki430a1112019-11-14 16:20:52 +01006985 if (visible) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006986 // Configuration will be ensured when becoming visible, so if it is already visible,
6987 // then the manual update is needed.
Evan Rosky72f084d2019-09-11 17:05:16 -07006988 updateSizeCompatMode();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006989 }
6990
6991 if (!attachedToProcess()) {
6992 return;
6993 }
6994
6995 // The restarting state avoids removing this record when process is died.
6996 setState(RESTARTING_PROCESS, "restartActivityProcess");
6997
Issei Suzuki430a1112019-11-14 16:20:52 +01006998 if (!visible || mHaveState) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006999 // Kill its process immediately because the activity should be in background.
7000 // The activity state will be update to {@link #DESTROYED} in
Andrii Kulian79d67982019-08-19 11:56:16 -07007001 // {@link ActivityStack#cleanUp} when handling process died.
Riddle Hsuaec55442019-03-12 17:25:35 +08007002 mAtmService.mH.post(() -> {
7003 final WindowProcessController wpc;
7004 synchronized (mAtmService.mGlobalLock) {
7005 if (!hasProcess()
7006 || app.getReportedProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
7007 return;
7008 }
7009 wpc = app;
7010 }
7011 mAtmService.mAmInternal.killProcess(wpc.mName, wpc.mUid, "resetConfig");
7012 });
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007013 return;
7014 }
7015
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007016 if (getParent() != null) {
7017 startFreezingScreen();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007018 }
7019 // The process will be killed until the activity reports stopped with saved state (see
7020 // {@link ActivityTaskManagerService.activityStopped}).
7021 try {
7022 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
7023 StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */));
7024 } catch (RemoteException e) {
7025 Slog.w(TAG, "Exception thrown during restart " + this, e);
7026 }
7027 mStackSupervisor.scheduleRestartTimeout(this);
7028 }
7029
Riddle Hsu32dbdca2019-05-17 23:10:16 -06007030 boolean isProcessRunning() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007031 WindowProcessController proc = app;
Jorim Jaggi02886a82016-12-06 09:10:06 -08007032 if (proc == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007033 proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
Jorim Jaggi02886a82016-12-06 09:10:06 -08007034 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007035 return proc != null && proc.hasThread();
Jorim Jaggi02886a82016-12-06 09:10:06 -08007036 }
7037
Jorim Jaggibae01b12017-04-11 16:29:10 -07007038 /**
7039 * @return Whether a task snapshot starting window may be shown.
7040 */
7041 private boolean allowTaskSnapshot() {
7042 if (newIntents == null) {
7043 return true;
7044 }
7045
Louis Chang746c2242019-10-08 16:30:44 +08007046 // Restrict task snapshot starting window to launcher start, or is same as the last
7047 // delivered intent, or there is no intent at all (eg. task being brought to front). If
7048 // the intent is something else, likely the app is going to show some specific page or
7049 // view, instead of what's left last time.
Jorim Jaggibae01b12017-04-11 16:29:10 -07007050 for (int i = newIntents.size() - 1; i >= 0; i--) {
7051 final Intent intent = newIntents.get(i);
Louis Chang746c2242019-10-08 16:30:44 +08007052 if (intent == null || ActivityRecord.isMainIntent(intent)) {
7053 continue;
7054 }
7055
7056 final boolean sameIntent = mLastNewIntent != null ? mLastNewIntent.filterEquals(intent)
7057 : this.intent.filterEquals(intent);
7058 if (!sameIntent || intent.getExtras() != null) {
Jorim Jaggibae01b12017-04-11 16:29:10 -07007059 return false;
7060 }
7061 }
7062 return true;
7063 }
7064
Bryce Leeb7c9b802017-05-02 14:20:24 -07007065 /**
7066 * Returns {@code true} if the associated activity has the no history flag set on it.
7067 * {@code false} otherwise.
7068 */
7069 boolean isNoHistory() {
7070 return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
7071 || (info.flags & FLAG_NO_HISTORY) != 0;
7072 }
7073
Craig Mautner21d24a22014-04-23 11:45:37 -07007074 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
7075 out.attribute(null, ATTR_ID, String.valueOf(createTime));
7076 out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
7077 if (launchedFromPackage != null) {
7078 out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
7079 }
7080 if (resolvedType != null) {
7081 out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
7082 }
7083 out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007084 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
Winson Chung2cb86c72014-06-25 12:03:30 -07007085
Craig Mautner21d24a22014-04-23 11:45:37 -07007086 if (taskDescription != null) {
Craig Mautner648f69b2014-09-18 14:16:26 -07007087 taskDescription.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007088 }
7089
7090 out.startTag(null, TAG_INTENT);
7091 intent.saveToXml(out);
7092 out.endTag(null, TAG_INTENT);
7093
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007094 if (isPersistable() && mPersistentState != null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007095 out.startTag(null, TAG_PERSISTABLEBUNDLE);
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007096 mPersistentState.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007097 out.endTag(null, TAG_PERSISTABLEBUNDLE);
7098 }
7099 }
7100
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07007101 static ActivityRecord restoreFromXml(XmlPullParser in,
7102 ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
Craig Mautner21d24a22014-04-23 11:45:37 -07007103 Intent intent = null;
7104 PersistableBundle persistentState = null;
7105 int launchedFromUid = 0;
7106 String launchedFromPackage = null;
7107 String resolvedType = null;
7108 boolean componentSpecified = false;
7109 int userId = 0;
Craig Mautner21d24a22014-04-23 11:45:37 -07007110 long createTime = -1;
7111 final int outerDepth = in.getDepth();
Winson Chung2cb86c72014-06-25 12:03:30 -07007112 TaskDescription taskDescription = new TaskDescription();
Craig Mautner21d24a22014-04-23 11:45:37 -07007113
7114 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
7115 final String attrName = in.getAttributeName(attrNdx);
7116 final String attrValue = in.getAttributeValue(attrNdx);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007117 if (DEBUG) Slog.d(TaskPersister.TAG,
Wale Ogunwale18795a22014-12-03 11:38:33 -08007118 "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007119 if (ATTR_ID.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01007120 createTime = Long.parseLong(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007121 } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007122 launchedFromUid = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007123 } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
7124 launchedFromPackage = attrValue;
7125 } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
7126 resolvedType = attrValue;
7127 } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
Tobias Thiererb0800dc2016-04-21 17:51:41 +01007128 componentSpecified = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007129 } else if (ATTR_USERID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007130 userId = Integer.parseInt(attrValue);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007131 } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
Craig Mautner648f69b2014-09-18 14:16:26 -07007132 taskDescription.restoreFromXml(attrName, attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007133 } else {
7134 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
7135 }
7136 }
7137
7138 int event;
Ruben Brunkf53497c2017-03-27 20:26:17 -07007139 while (((event = in.next()) != END_DOCUMENT) &&
7140 (event != END_TAG || in.getDepth() >= outerDepth)) {
7141 if (event == START_TAG) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007142 final String name = in.getName();
Ruben Brunkf53497c2017-03-27 20:26:17 -07007143 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007144 Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
Craig Mautner21d24a22014-04-23 11:45:37 -07007145 if (TAG_INTENT.equals(name)) {
7146 intent = Intent.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007147 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007148 Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007149 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
7150 persistentState = PersistableBundle.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007151 if (DEBUG) Slog.d(TaskPersister.TAG,
Craig Mautner21d24a22014-04-23 11:45:37 -07007152 "ActivityRecord: persistentState=" + persistentState);
7153 } else {
7154 Slog.w(TAG, "restoreActivity: unexpected name=" + name);
7155 XmlUtils.skipCurrentTag(in);
7156 }
7157 }
7158 }
7159
7160 if (intent == null) {
Craig Mautnere0129b32014-05-25 16:41:09 -07007161 throw new XmlPullParserException("restoreActivity error intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007162 }
7163
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007164 final ActivityTaskManagerService service = stackSupervisor.mService;
Craig Mautner21d24a22014-04-23 11:45:37 -07007165 final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
Patrick Baumann78380272018-04-04 10:41:01 -07007166 userId, Binder.getCallingUid());
Craig Mautnere0129b32014-05-25 16:41:09 -07007167 if (aInfo == null) {
Craig Mautner77b04262014-06-27 15:22:12 -07007168 throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
7169 " resolvedType=" + resolvedType);
Craig Mautnere0129b32014-05-25 16:41:09 -07007170 }
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007171 final ActivityRecord r = new ActivityRecord(service, null /* caller */,
Andrii Kulianfb1bf692017-01-17 11:17:34 -08007172 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
Wale Ogunwalef6733932018-06-27 05:14:34 -07007173 aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
Andrii Kulianfb1bf692017-01-17 11:17:34 -08007174 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07007175 stackSupervisor, null /* options */, null /* sourceRecord */);
Craig Mautner21d24a22014-04-23 11:45:37 -07007176
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007177 r.mPersistentState = persistentState;
Winson Chung2cb86c72014-06-25 12:03:30 -07007178 r.taskDescription = taskDescription;
Craig Mautner21d24a22014-04-23 11:45:37 -07007179 r.createTime = createTime;
7180
7181 return r;
7182 }
7183
Zak Cohen90e7116742017-01-29 12:59:23 -08007184 private static boolean isInVrUiMode(Configuration config) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07007185 return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
Zak Cohen90e7116742017-01-29 12:59:23 -08007186 }
7187
David Stevens82ea6cb2017-03-03 16:18:50 -08007188 int getUid() {
7189 return info.applicationInfo.uid;
7190 }
7191
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007192 int getPid() {
7193 return app != null ? app.getPid() : 0;
chaviw59b98852017-06-13 12:05:44 -07007194 }
7195
7196 /**
7197 * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
Garfield Tane8d84ab2019-10-11 09:49:40 -07007198 * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007199 * should be visible depending on Keyguard state
chaviw59b98852017-06-13 12:05:44 -07007200 *
7201 * @return true if the screen can be turned on, false otherwise.
7202 */
7203 boolean canTurnScreenOn() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007204 if (!getTurnScreenOnFlag()) {
7205 return false;
7206 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007207 final ActivityStack stack = getActivityStack();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007208 return stack != null &&
chaviw59b98852017-06-13 12:05:44 -07007209 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
7210 }
7211
Garfield Tane8d84ab2019-10-11 09:49:40 -07007212 void setTurnScreenOn(boolean turnScreenOn) {
7213 mTurnScreenOn = turnScreenOn;
7214 }
7215
7216 boolean getTurnScreenOnFlag() {
7217 return mTurnScreenOn;
7218 }
7219
Louis Chang77ce34d2019-01-03 15:45:12 +08007220 /**
7221 * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
7222 * process are allowed to be resumed.
7223 *
7224 * @return true if this activity can be resumed.
7225 */
7226 boolean canResumeByCompat() {
7227 return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
7228 }
7229
chaviw59b98852017-06-13 12:05:44 -07007230 boolean isTopRunningActivity() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08007231 return mRootActivityContainer.topRunningActivity() == this;
chaviw59b98852017-06-13 12:05:44 -07007232 }
7233
Andrii Kulian52d255c2018-07-13 11:32:19 -07007234 /**
7235 * @return {@code true} if this is the resumed activity on its current display, {@code false}
7236 * otherwise.
7237 */
7238 boolean isResumedActivityOnDisplay() {
7239 final ActivityDisplay display = getDisplay();
7240 return display != null && this == display.getResumedActivity();
7241 }
7242
Andrii Kulian39f27442019-06-26 19:09:19 -07007243
7244 /**
7245 * Check if this is the root of the task - first activity that is not finishing, starting from
7246 * the bottom of the task. If all activities are finishing - then this method will return
7247 * {@code true} if the activity is at the bottom.
7248 *
7249 * NOTE: This is different from 'effective root' - an activity that defines the task identity.
7250 */
7251 boolean isRootOfTask() {
7252 if (task == null) {
7253 return false;
7254 }
7255 final ActivityRecord rootActivity = task.getRootActivity();
7256 if (rootActivity != null) {
7257 return this == rootActivity;
7258 }
7259 // No non-finishing activity found. In this case the bottom-most activity is considered to
7260 // be the root.
7261 return task.getChildAt(0) == this;
7262 }
7263
Craig Mautnerf81b90872013-02-26 13:02:43 -08007264 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007265 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007266 if (stringName != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07007267 return stringName + " t" + (task == null ? INVALID_TASK_ID : task.mTaskId) +
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007268 (finishing ? " f}" : "") + (mIsExiting ? " mIsExiting=" : "") + "}";
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007269 }
7270 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn30d71892010-12-11 10:37:55 -08007271 sb.append("ActivityRecord{");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007272 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornb12e1352012-09-26 11:39:20 -07007273 sb.append(" u");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007274 sb.append(mUserId);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007275 sb.append(' ');
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007276 sb.append(intent.getComponent().flattenToShortString());
Craig Mautnerf81b90872013-02-26 13:02:43 -08007277 stringName = sb.toString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007278 return stringName;
Steven Timotius4346f0a2017-09-12 11:07:21 -07007279 }
7280
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007281 /**
7282 * Write all fields to an {@code ActivityRecordProto}. This assumes the
7283 * {@code ActivityRecordProto} is the outer-most proto data.
7284 */
7285 void writeToProto(ProtoOutputStream proto) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07007286 writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
Steven Timotius4346f0a2017-09-12 11:07:21 -07007287 writeIdentifierToProto(proto, IDENTIFIER);
Bryce Lee7ace3952018-02-16 14:34:32 -08007288 proto.write(STATE, mState.toString());
Issei Suzuki430a1112019-11-14 16:20:52 +01007289 proto.write(VISIBLE, visible);
Andrii Kulian39f27442019-06-26 19:09:19 -07007290 proto.write(FRONT_OF_TASK, isRootOfTask());
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007291 if (hasProcess()) {
7292 proto.write(PROC_ID, app.getPid());
Steven Timotius4346f0a2017-09-12 11:07:21 -07007293 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007294 proto.write(TRANSLUCENT, !occludesParent());
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007295 }
7296
7297 public void writeToProto(ProtoOutputStream proto, long fieldId) {
7298 final long token = proto.start(fieldId);
7299 writeToProto(proto);
Steven Timotius4346f0a2017-09-12 11:07:21 -07007300 proto.end(token);
7301 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007302
7303 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -07007304 * Copied from old AppWindowToken.
7305 */
7306 @Override
7307 public void writeToProto(ProtoOutputStream proto, long fieldId,
7308 @WindowTraceLogLevel int logLevel) {
7309 // Critical log level logs only visible elements to mitigate performance overheard
7310 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
7311 return;
7312 }
7313
7314 final long token = proto.start(fieldId);
7315 writeNameToProto(proto, NAME);
7316 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
7317 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
7318 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
lumark9bca6b42019-10-17 18:35:22 +08007319 proto.write(IS_ANIMATING, isAnimating());
Garfield Tane8d84ab2019-10-11 09:49:40 -07007320 if (mThumbnail != null){
7321 mThumbnail.writeToProto(proto, THUMBNAIL);
7322 }
7323 proto.write(FILLS_PARENT, mOccludesParent);
7324 proto.write(APP_STOPPED, mAppStopped);
Issei Suzuki430a1112019-11-14 16:20:52 +01007325 proto.write(HIDDEN_REQUESTED, hiddenRequested);
Issei Suzukie63eac72019-11-14 15:59:15 +01007326 proto.write(CLIENT_HIDDEN, mClientHidden);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007327 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
7328 proto.write(REPORTED_DRAWN, reportedDrawn);
7329 proto.write(REPORTED_VISIBLE, reportedVisible);
7330 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
7331 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
7332 proto.write(ALL_DRAWN, allDrawn);
7333 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007334 if (startingWindow != null) {
7335 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
7336 }
7337 proto.write(STARTING_DISPLAYED, startingDisplayed);
7338 proto.write(STARTING_MOVED, startingMoved);
Issei Suzuki7b9e2572019-11-14 16:19:54 +01007339 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
7340 mHiddenSetFromTransferredStartingWindow);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007341 for (Rect bounds : mFrozenBounds) {
7342 bounds.writeToProto(proto, FROZEN_BOUNDS);
7343 }
7344 proto.end(token);
7345 }
7346
7347 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
7348 if (appToken != null) {
7349 proto.write(fieldId, appToken.getName());
7350 }
7351 }
7352
7353 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
7354 final long token = proto.start(fieldId);
7355 proto.write(HASH_CODE, System.identityHashCode(this));
7356 proto.write(USER_ID, mUserId);
7357 proto.write(TITLE, intent.getComponent().flattenToShortString());
7358 proto.end(token);
7359 }
7360
7361 /**
Riddle Hsu61987bc2019-04-03 13:08:47 +08007362 * The precomputed insets of the display in each rotation. This is used to make the size
7363 * compatibility mode activity compute the configuration without relying on its current display.
7364 */
7365 static class CompatDisplayInsets {
Evan Rosky72f084d2019-09-11 17:05:16 -07007366 private final int mDisplayWidth;
7367 private final int mDisplayHeight;
7368 private final int mWidth;
7369 private final int mHeight;
Riddle Hsu61987bc2019-04-03 13:08:47 +08007370
Riddle Hsu74826262019-04-17 14:57:42 +08007371 /**
7372 * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
7373 * is used to compute the appBounds.
7374 */
Riddle Hsu61987bc2019-04-03 13:08:47 +08007375 final Rect[] mNonDecorInsets = new Rect[4];
7376 /**
7377 * The stableInsets for each rotation. Includes the status bar inset and the
7378 * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
7379 * {@link Configuration#screenHeightDp}.
7380 */
7381 final Rect[] mStableInsets = new Rect[4];
7382
Evan Rosky72f084d2019-09-11 17:05:16 -07007383 /**
Louis Changcdec0802019-11-11 11:45:07 +08007384 * Sets bounds to {@link Task} bounds. For apps in freeform, the task bounds are the
Evan Rosky72f084d2019-09-11 17:05:16 -07007385 * parent bounds from the app's perspective. No insets because within a window.
7386 */
7387 CompatDisplayInsets(DisplayContent display, Rect activityBounds, boolean isFloating) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08007388 mDisplayWidth = display.mBaseDisplayWidth;
7389 mDisplayHeight = display.mBaseDisplayHeight;
Evan Rosky72f084d2019-09-11 17:05:16 -07007390 mWidth = activityBounds.width();
7391 mHeight = activityBounds.height();
7392 if (isFloating) {
7393 Rect emptyRect = new Rect();
7394 for (int rotation = 0; rotation < 4; rotation++) {
7395 mNonDecorInsets[rotation] = emptyRect;
7396 mStableInsets[rotation] = emptyRect;
7397 }
7398 return;
7399 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007400 final DisplayPolicy policy = display.getDisplayPolicy();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007401 for (int rotation = 0; rotation < 4; rotation++) {
7402 mNonDecorInsets[rotation] = new Rect();
7403 mStableInsets[rotation] = new Rect();
7404 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7405 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
7406 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
Riddle Hsu74826262019-04-17 14:57:42 +08007407 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
7408 .getDisplayCutout();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007409 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
7410 mStableInsets[rotation].set(mNonDecorInsets[rotation]);
7411 policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
7412 }
7413 }
7414
Riddle Hsu74826262019-04-17 14:57:42 +08007415 void getDisplayBoundsByRotation(Rect outBounds, int rotation) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08007416 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7417 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
7418 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
7419 outBounds.set(0, 0, dw, dh);
7420 }
Riddle Hsu74826262019-04-17 14:57:42 +08007421
Evan Rosky72f084d2019-09-11 17:05:16 -07007422 void getFrameByOrientation(Rect outBounds, int orientation) {
7423 final int longSide = Math.max(mWidth, mHeight);
7424 final int shortSide = Math.min(mWidth, mHeight);
Riddle Hsu74826262019-04-17 14:57:42 +08007425 final boolean isLandscape = orientation == ORIENTATION_LANDSCAPE;
7426 outBounds.set(0, 0, isLandscape ? longSide : shortSide,
7427 isLandscape ? shortSide : longSide);
7428 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007429 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07007430
7431 private static class AppSaturationInfo {
7432 float[] mMatrix = new float[9];
7433 float[] mTranslation = new float[3];
7434
7435 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
7436 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
7437 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
7438 }
7439 }
lumark19a5d2e2019-10-11 16:19:30 +08007440
7441 @Override
7442 RemoteAnimationTarget createRemoteAnimationTarget(
7443 RemoteAnimationController.RemoteAnimationRecord record) {
lumark19a5d2e2019-10-11 16:19:30 +08007444 final WindowState mainWindow = findMainWindow();
7445 if (task == null || mainWindow == null) {
7446 return null;
7447 }
7448 final Rect insets = new Rect();
7449 mainWindow.getContentInsets(insets);
7450 InsetUtils.addInsets(insets, getLetterboxInsets());
7451 return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
7452 record.mAdapter.mCapturedLeash, !task.fillsParent(),
7453 mainWindow.mWinAnimator.mLastClipRect, insets,
7454 getPrefixOrderIndex(), record.mAdapter.mPosition,
7455 record.mAdapter.mStackBounds, task.getWindowConfiguration(),
7456 false /*isNotInRecents*/,
7457 record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
7458 record.mStartBounds);
7459 }
7460
7461 @Override
7462 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
7463 Rect outSurfaceInsets) {
7464 final WindowState win = findMainWindow();
7465 if (win == null) {
7466 return;
7467 }
7468 win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
7469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470}