blob: f24fa077bb6c094108535d7eb5484f450f169215 [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 Suzuki7b9e2572019-11-14 16:19:54 +0100179import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
lumark9bca6b42019-10-17 18:35:22 +0800180import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700181import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
182import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
183import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
184import static com.android.server.wm.AppWindowTokenProto.NAME;
185import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
186import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700187import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
188import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
189import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
190import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
191import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
192import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
Issei Suzuki1669ea42019-11-06 14:20:59 +0100193import static com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700194import 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
Jorim Jaggi241ae102016-11-02 21:57:33 -0700464 boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
465 // might hide this activity?
Issei Suzukie63eac72019-11-14 15:59:15 +0100466 // True if the hidden state of this token was forced to false due to a transferred starting
Garfield Tane8d84ab2019-10-11 09:49:40 -0700467 // window.
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100468 private boolean mHiddenSetFromTransferredStartingWindow;
469 // TODO: figureout how to consolidate with the same variable in ActivityRecord.
Wale Ogunwaleec950642017-04-25 07:44:21 -0700470 private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
471 // process that it is hidden.
Issei Suzukie63eac72019-11-14 15:59:15 +0100472 private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true
Garfield Tane8d84ab2019-10-11 09:49:40 -0700473 // and reporting to the client that it is hidden.
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800474 boolean sleeping; // have we told the activity to sleep?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 boolean nowVisible; // is this activity's window visible?
Vishnu Nair9ba31652018-11-13 14:34:05 -0800476 boolean mDrawn; // is this activity's window drawn?
Andrii Kuliana39ae3e2018-05-31 12:43:54 -0700477 boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 boolean idle; // has the activity gone idle?
479 boolean hasBeenLaunched;// has this activity ever been launched?
480 boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
Daniel Sandler69a48172010-06-23 16:29:36 -0400481 boolean immersive; // immersive mode (don't interrupt if possible)
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400482 boolean forceNewConfig; // force re-create with new config next time
Winson Chungf7e03e12017-08-22 11:32:16 -0700483 boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the
484 // activity can enter picture in picture while pausing (only when switching to another task)
Winson Chung709904f2017-04-25 11:00:48 -0700485 PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();
486 // The PiP params used when deferring the entering of picture-in-picture.
Dianne Hackborn07981492013-01-28 11:36:23 -0800487 int launchCount; // count of launches since last state
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800488 long lastLaunchTime; // time of last launch of this activity
Ruben Brunke24b9a62016-02-16 21:38:24 -0800489 ComponentName requestedVrComponent; // the requested component for handling VR mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200491 boolean inHistory; // are we in the history stack?
Craig Mautnerde4ef022013-04-07 19:01:33 -0700492 final ActivityStackSupervisor mStackSupervisor;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800493 final RootActivityContainer mRootActivityContainer;
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800494
495 static final int STARTING_WINDOW_NOT_SHOWN = 0;
496 static final int STARTING_WINDOW_SHOWN = 1;
497 static final int STARTING_WINDOW_REMOVED = 2;
498 int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
Wale Ogunwale3b232392016-05-13 15:37:13 -0700499 boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800500
Garfield Tan2746ab52018-07-25 12:33:01 -0700501 // Marking the reason why this activity is being relaunched. Mainly used to track that this
502 // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
503 // pre-NYC apps that don't have a sense of being resized.
504 int mRelaunchReason = RELAUNCH_REASON_NONE;
505
Craig Mautner21d24a22014-04-23 11:45:37 -0700506 TaskDescription taskDescription; // the recents information for this activity
Craig Mautner2fbd7542014-03-21 09:34:07 -0700507
Filip Gruszczynski23493322015-07-29 17:02:59 -0700508 // These configurations are collected from application's resources based on size-sensitive
509 // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
510 // and drawable-sw400dp will be added to both as 400.
511 private int[] mVerticalSizeConfigurations;
512 private int[] mHorizontalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -0700513 private int[] mSmallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -0700514
Riddle Hsu61987bc2019-04-03 13:08:47 +0800515 /**
516 * The precomputed display insets for resolving configuration. It will be non-null if
517 * {@link #shouldUseSizeCompatMode} returns {@code true}.
518 */
519 private CompatDisplayInsets mCompatDisplayInsets;
520
Amith Yamasani0af6fa72016-01-17 15:36:19 -0800521 boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session
522 IVoiceInteractionSession voiceSession; // Voice interaction session for this activity
523
Garfield Tane8d84ab2019-10-11 09:49:40 -0700524 boolean mVoiceInteraction;
525
526 private int mPendingRelaunchCount;
527
528 // True if we are current in the process of removing this app token from the display
529 private boolean mRemovingFromDisplay = false;
530
Garfield Tane8d84ab2019-10-11 09:49:40 -0700531 private RemoteAnimationDefinition mRemoteAnimationDefinition;
532
533 private AnimatingActivityRegistry mAnimatingActivityRegistry;
534
535 private Task mLastParent;
536
Issei Suzukie63eac72019-11-14 15:59:15 +0100537 // Have we told the window clients to hide themselves?
538 private boolean mClientHidden;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700539
540 boolean firstWindowDrawn;
541 // Last drawn state we reported to the app token.
542 private boolean reportedDrawn;
543 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
544 new WindowState.UpdateReportedVisibilityResults();
545
546 private boolean mUseTransferredAnimation;
547
548 /**
549 * @see #currentLaunchCanTurnScreenOn()
550 */
551 private boolean mCurrentLaunchCanTurnScreenOn = true;
552
553 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -0700554 * This leash is used to "freeze" the app surface in place after the state change, but before
555 * the animation is ready to start.
556 */
557 private SurfaceControl mTransitChangeLeash = null;
558
559 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
560 private boolean mLastSurfaceShowing = true;
561
562 private Letterbox mLetterbox;
563
564 /**
565 * The activity is opaque and fills the entire space of this task.
566 * @see WindowContainer#fillsParent()
567 */
568 private boolean mOccludesParent;
569
570 // The input dispatching timeout for this application token in nanoseconds.
571 long mInputDispatchingTimeoutNanos;
572
573 private boolean mShowWhenLocked;
574 private boolean mInheritShownWhenLocked;
575 private boolean mTurnScreenOn;
576
577 /** Have we been asked to have this token keep the screen frozen? */
578 private boolean mFreezingScreen;
579
580 // These are used for determining when all windows associated with
581 // an activity have been drawn, so they can be made visible together
582 // at the same time.
583 // initialize so that it doesn't match mTransactionSequence which is an int.
584 private long mLastTransactionSequence = Long.MIN_VALUE;
585 private int mNumInterestingWindows;
586 private int mNumDrawnWindows;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700587 boolean allDrawn;
588 private boolean mLastAllDrawn;
589
590 private boolean mLastContainsShowWhenLockedWindow;
591 private boolean mLastContainsDismissKeyguardWindow;
592
593 /**
594 * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
595 * to help AR know that the app is in the process of closing but hasn't yet started closing on
596 * the WM side.
597 */
598 private boolean mWillCloseOrEnterPip;
599
600 /**
601 * The scale to fit at least one side of the activity to its parent. If the activity uses
602 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
603 */
604 private float mSizeCompatScale = 1f;
605 /**
606 * The bounds in global coordinates for activity in size compatibility mode.
607 * @see ActivityRecord#hasSizeCompatBounds()
608 */
609 private Rect mSizeCompatBounds;
610
611 // activity is not displayed?
612 // TODO: rename to mNoDisplay
613 @VisibleForTesting
614 boolean noDisplay;
615 boolean mShowForAllUsers;
616 // TODO: Make this final
617 int mTargetSdk;
618
619 // Set to true when this app creates a surface while in the middle of an animation. In that
620 // case do not clear allDrawn until the animation completes.
621 boolean deferClearAllDrawn;
622
Issei Suzuki1669ea42019-11-06 14:20:59 +0100623 // Is this window's surface needed? This is almost like visible, except
624 // it will sometimes be true a little earlier: when the activity record has
Garfield Tane8d84ab2019-10-11 09:49:40 -0700625 // been shown, but is still waiting for its app transition to execute
626 // before making its windows shown.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100627 boolean mVisibleRequested;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700628
629 // Last visibility state we reported to the app token.
630 boolean reportedVisible;
631
Garfield Tane8d84ab2019-10-11 09:49:40 -0700632 boolean mDisablePreviewScreenshots;
633
634 // Information about an application starting window if displayed.
635 // Note: these are de-referenced before the starting window animates away.
636 StartingData mStartingData;
637 WindowState startingWindow;
638 WindowManagerPolicy.StartingSurface startingSurface;
639 boolean startingDisplayed;
640 boolean startingMoved;
641
642 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
643 boolean mIsExiting;
644
Garfield Tane8d84ab2019-10-11 09:49:40 -0700645 boolean mEnteringAnimation;
646
647 boolean mAppStopped;
648 // A hint to override the window specified rotation animation, or -1 to use the window specified
649 // value. We use this so that we can select the right animation in the cases of starting
650 // windows, where the app hasn't had time to set a value on the window.
651 int mRotationAnimationHint = -1;
652
653 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
654 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
655
Garfield Tane8d84ab2019-10-11 09:49:40 -0700656 private AppSaturationInfo mLastAppSaturationInfo;
657
658 private final ColorDisplayService.ColorTransformController mColorTransformController =
659 (matrix, translation) -> mWmService.mH.post(() -> {
660 synchronized (mWmService.mGlobalLock) {
661 if (mLastAppSaturationInfo == null) {
662 mLastAppSaturationInfo = new AppSaturationInfo();
663 }
664
665 mLastAppSaturationInfo.setSaturation(matrix, translation);
666 updateColorTransform();
667 }
668 });
669
Andrii Kulian21713ac2016-10-12 22:05:05 -0700670 /**
Garfield Tan0443b372019-01-04 15:00:13 -0800671 * Current sequencing integer of the configuration, for skipping old activity configurations.
672 */
673 private int mConfigurationSeq;
674
675 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800676 * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}
Andrii Kulian21713ac2016-10-12 22:05:05 -0700677 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700678 private final Configuration mTmpConfig = new Configuration();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700679 private final Rect mTmpBounds = new Rect();
Andrii Kulian21713ac2016-10-12 22:05:05 -0700680
Sunny Goyald40c3452019-03-20 12:46:55 -0700681 // Token for targeting this activity for assist purposes.
682 final Binder assistToken = new Binder();
683
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800684 private static String startingWindowStateToString(int state) {
685 switch (state) {
686 case STARTING_WINDOW_NOT_SHOWN:
687 return "STARTING_WINDOW_NOT_SHOWN";
688 case STARTING_WINDOW_SHOWN:
689 return "STARTING_WINDOW_SHOWN";
690 case STARTING_WINDOW_REMOVED:
691 return "STARTING_WINDOW_REMOVED";
692 default:
693 return "unknown state=" + state;
694 }
695 }
696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 void dump(PrintWriter pw, String prefix) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700698 }
699
700 /**
701 * Copied from old AppWindowToken.
702 */
703 @Override
704 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700705 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700706 pw.print(prefix); pw.print("packageName="); pw.print(packageName);
707 pw.print(" processName="); pw.println(processName);
708 pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
Craig Mautnere11f2b72013-04-01 12:37:17 -0700709 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800710 pw.print(" userId="); pw.println(mUserId);
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800711 pw.print(prefix); pw.print("app="); pw.println(app);
Hui Yu6d5c3b92019-10-22 15:35:53 -0700712 pw.print(prefix); pw.println(intent.toInsecureString());
Andrii Kulian39f27442019-06-26 19:09:19 -0700713 pw.print(prefix); pw.print("rootOfTask="); pw.print(isRootOfTask());
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700714 pw.print(" task="); pw.println(task);
715 pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800716 pw.print(prefix); pw.print("mActivityComponent=");
717 pw.println(mActivityComponent.flattenToShortString());
Andrii Kulianeceebbf2019-06-26 17:36:51 -0700718 if (info != null && info.applicationInfo != null) {
719 final ApplicationInfo appInfo = info.applicationInfo;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700720 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
721 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
722 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
723 }
724 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800725 if (appInfo.splitSourceDirs != null) {
726 pw.print(prefix); pw.print("splitDir=");
727 pw.println(Arrays.toString(appInfo.splitSourceDirs));
728 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800729 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700730 pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
731 pw.print(" componentSpecified="); pw.print(componentSpecified);
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700732 pw.print(" mActivityType="); pw.println(
733 activityTypeToString(getActivityType()));
Dianne Hackbornfb81d092015-08-03 17:14:46 -0700734 if (rootVoiceInteraction) {
735 pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
736 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800737 pw.print(prefix); pw.print("compat="); pw.print(compat);
738 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
739 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
740 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700741 pw.println(prefix + "mLastReportedConfigurations:");
742 mLastReportedConfiguration.dump(pw, prefix + " ");
743
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700744 pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
Evan Roskydfe3da72018-10-26 17:21:06 -0700745 if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
746 pw.println(prefix + "RequestedOverrideConfiguration="
747 + getRequestedOverrideConfiguration());
748 }
749 if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
750 pw.println(prefix + "ResolvedOverrideConfiguration="
751 + getResolvedOverrideConfiguration());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700752 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800753 if (!matchParentBounds()) {
754 pw.println(prefix + "bounds=" + getBounds());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700755 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700756 if (resultTo != null || resultWho != null) {
757 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
758 pw.print(" resultWho="); pw.print(resultWho);
759 pw.print(" resultCode="); pw.println(requestCode);
760 }
Craig Mautner29c58ca2014-10-14 16:17:06 -0700761 if (taskDescription != null) {
762 final String iconFilename = taskDescription.getIconFilename();
763 if (iconFilename != null || taskDescription.getLabel() != null ||
764 taskDescription.getPrimaryColor() != 0) {
765 pw.print(prefix); pw.print("taskDescription:");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700766 pw.print(" label=\""); pw.print(taskDescription.getLabel());
767 pw.print("\"");
Matthew Ng54bc9422017-10-02 17:16:28 -0700768 pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
769 ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
770 : "null");
771 pw.print(" iconResource="); pw.print(taskDescription.getIconResource());
772 pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200773 pw.print(" primaryColor=");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700774 pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700775 pw.print(prefix + " backgroundColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200776 pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700777 pw.print(prefix + " statusBarColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200778 pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700779 pw.print(prefix + " navigationBarColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200780 pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
Craig Mautner29c58ca2014-10-14 16:17:06 -0700781 }
Craig Mautner648f69b2014-09-18 14:16:26 -0700782 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700783 if (results != null) {
784 pw.print(prefix); pw.print("results="); pw.println(results);
785 }
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700786 if (pendingResults != null && pendingResults.size() > 0) {
787 pw.print(prefix); pw.println("Pending Results:");
788 for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
789 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
790 pw.print(prefix); pw.print(" - ");
791 if (pir == null) {
792 pw.println("null");
793 } else {
794 pw.println(pir);
795 pir.dump(pw, prefix + " ");
796 }
797 }
798 }
799 if (newIntents != null && newIntents.size() > 0) {
800 pw.print(prefix); pw.println("Pending New Intents:");
801 for (int i=0; i<newIntents.size(); i++) {
Craig Mautnerd2328952013-03-05 12:46:26 -0800802 Intent intent = newIntents.get(i);
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700803 pw.print(prefix); pw.print(" - ");
804 if (intent == null) {
805 pw.println("null");
806 } else {
Hui Yu6d5c3b92019-10-22 15:35:53 -0700807 pw.println(intent.toShortString(false, true, false, false));
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700808 }
809 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700810 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700811 if (pendingOptions != null) {
812 pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
813 }
Dianne Hackbornb5a380d2015-05-20 18:18:46 -0700814 if (appTimeTracker != null) {
815 appTimeTracker.dumpWithHeader(pw, prefix, false);
816 }
Dianne Hackborn7e269642010-08-25 19:50:20 -0700817 if (uriPermissions != null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700818 uriPermissions.dump(pw, prefix);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700819 }
820 pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
Dianne Hackborn07981492013-01-28 11:36:23 -0800821 pw.print(" launchCount="); pw.print(launchCount);
822 pw.print(" lastLaunchTime=");
823 if (lastLaunchTime == 0) pw.print("0");
824 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
825 pw.println();
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700826 pw.print(prefix); pw.print("mHaveState="); pw.print(mHaveState);
827 pw.print(" mIcicle="); pw.println(mIcicle);
Bryce Lee7ace3952018-02-16 14:34:32 -0800828 pw.print(prefix); pw.print("state="); pw.print(mState);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700829 pw.print(" stopped="); pw.print(stopped);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700830 pw.print(" delayedResume="); pw.print(delayedResume);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700831 pw.print(" finishing="); pw.println(finishing);
832 pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
833 pw.print(" inHistory="); pw.print(inHistory);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800834 pw.print(" sleeping="); pw.print(sleeping);
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800835 pw.print(" idle="); pw.print(idle);
836 pw.print(" mStartingWindowState=");
837 pw.println(startingWindowStateToString(mStartingWindowState));
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800838 pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
Dianne Hackbornff801ec2011-01-22 18:05:38 -0800839 pw.print(" noDisplay="); pw.print(noDisplay);
840 pw.print(" immersive="); pw.print(immersive);
841 pw.print(" launchMode="); pw.println(launchMode);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800842 pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400843 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700844 pw.print(prefix); pw.print("mActivityType=");
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700845 pw.println(activityTypeToString(getActivityType()));
Ruben Brunke24b9a62016-02-16 21:38:24 -0800846 if (requestedVrComponent != null) {
847 pw.print(prefix);
848 pw.print("requestedVrComponent=");
849 pw.println(requestedVrComponent);
850 }
Garfield Tane8d84ab2019-10-11 09:49:40 -0700851 super.dump(pw, prefix, dumpAll);
852 if (appToken != null) {
853 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
854 }
855 pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
856 pw.print(" mOrientation="); pw.println(mOrientation);
Issei Suzuki1669ea42019-11-06 14:20:59 +0100857 pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
858 + " mClientHidden=" + mClientHidden
Garfield Tane8d84ab2019-10-11 09:49:40 -0700859 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
860 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
861 if (paused) {
862 pw.print(prefix); pw.print("paused="); pw.println(paused);
863 }
864 if (mAppStopped) {
865 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
866 }
867 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
868 || allDrawn || mLastAllDrawn) {
869 pw.print(prefix); pw.print("mNumInterestingWindows=");
870 pw.print(mNumInterestingWindows);
871 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700872 pw.print(" allDrawn="); pw.print(allDrawn);
873 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
874 pw.println(")");
875 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -0800876 if (mStartingData != null || firstWindowDrawn || mIsExiting) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700877 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700878 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
879 pw.print(" mIsExiting="); pw.println(mIsExiting);
880 }
881 if (startingWindow != null || startingSurface != null
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100882 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700883 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
884 pw.print(" startingSurface="); pw.print(startingSurface);
885 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
886 pw.print(" startingMoved="); pw.print(startingMoved);
887 pw.println(" mHiddenSetFromTransferredStartingWindow="
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100888 + mHiddenSetFromTransferredStartingWindow);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700889 }
890 if (!mFrozenBounds.isEmpty()) {
891 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
892 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
893 }
894 if (mPendingRelaunchCount != 0) {
895 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
896 }
897 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
898 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
899 + mSizeCompatBounds);
900 }
901 if (mRemovingFromDisplay) {
902 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
903 }
Jorim Jaggi9b5e3312019-03-01 18:08:00 +0100904 if (lastVisibleTime != 0 || nowVisible) {
905 pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700906 pw.print(" lastVisibleTime=");
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700907 if (lastVisibleTime == 0) pw.print("0");
908 else TimeUtils.formatDuration(lastVisibleTime, now, pw);
909 pw.println();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700910 }
Wale Ogunwaleec950642017-04-25 07:44:21 -0700911 if (mDeferHidingClient) {
912 pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
913 }
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800914 if (deferRelaunchUntilPaused || configChangeFlags != 0) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700915 pw.print(prefix); pw.print("deferRelaunchUntilPaused=");
916 pw.print(deferRelaunchUntilPaused);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700917 pw.print(" configChangeFlags=");
918 pw.println(Integer.toHexString(configChangeFlags));
919 }
Wale Ogunwalec4e63a42018-10-02 13:19:54 -0700920 if (mServiceConnectionsHolder != null) {
921 pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700922 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -0800923 if (info != null) {
924 pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
Winson Chung609e1e92017-05-08 10:52:12 -0700925 pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode
926 + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700927 if (info.supportsPictureInPicture()) {
928 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
Winson Chungf7e03e12017-08-22 11:32:16 -0700929 pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
930 + supportsEnterPipOnTaskSwitch);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700931 }
932 if (info.maxAspectRatio != 0) {
933 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
934 }
Adrian Roos917791e2018-11-28 16:30:44 +0100935 if (info.minAspectRatio != 0) {
936 pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
937 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -0800938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 }
940
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700941 /** Update the saved state of an activity. */
942 void setSavedState(@Nullable Bundle savedState) {
943 mIcicle = savedState;
944 mHaveState = mIcicle != null;
945 }
946
947 /**
948 * Get the actual Bundle instance of the saved state.
949 * @see #hasSavedState() for checking if the record has saved state.
950 */
951 @Nullable Bundle getSavedState() {
952 return mIcicle;
953 }
954
955 /**
956 * Check if the activity has saved state.
957 * @return {@code true} if the client reported a non-empty saved state from last onStop(), or
958 * if this record was just created and the client is yet to be launched and resumed.
959 */
960 boolean hasSavedState() {
961 return mHaveState;
962 }
963
964 /** @return The actual PersistableBundle instance of the saved persistent state. */
965 @Nullable PersistableBundle getPersistentSavedState() {
966 return mPersistentState;
967 }
968
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -0700969 void updateApplicationInfo(ApplicationInfo aInfo) {
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -0700970 info.applicationInfo = aInfo;
971 }
972
Andrii Kulian21713ac2016-10-12 22:05:05 -0700973 private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -0700974 return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
975 }
976
Andrii Kulian21713ac2016-10-12 22:05:05 -0700977 private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -0700978 return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
979 }
980
Andrii Kulian21713ac2016-10-12 22:05:05 -0700981 private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -0700982 return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
983 }
984
Filip Gruszczynski23493322015-07-29 17:02:59 -0700985 /**
986 * The purpose of this method is to decide whether the activity needs to be relaunched upon
987 * changing its size. In most cases the activities don't need to be relaunched, if the resize
988 * is small, all the activity content has to do is relayout itself within new bounds. There are
989 * cases however, where the activity's content would be completely changed in the new size and
990 * the full relaunch is required.
991 *
992 * The activity will report to us vertical and horizontal thresholds after which a relaunch is
993 * required. These thresholds are collected from the application resource qualifiers. For
994 * example, if application has layout-w600dp resource directory, then it needs a relaunch when
995 * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
996 * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
997 * of the threshold.
998 */
999 private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
1000 int secondDp) {
1001 if (thresholds == null) {
1002 return false;
1003 }
1004 for (int i = thresholds.length - 1; i >= 0; i--) {
1005 final int threshold = thresholds[i];
1006 if ((firstDp < threshold && secondDp >= threshold)
1007 || (firstDp >= threshold && secondDp < threshold)) {
1008 return true;
1009 }
1010 }
1011 return false;
1012 }
1013
Andrii Kulian21713ac2016-10-12 22:05:05 -07001014 void setSizeConfigurations(int[] horizontalSizeConfiguration,
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001015 int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001016 mHorizontalSizeConfigurations = horizontalSizeConfiguration;
1017 mVerticalSizeConfigurations = verticalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001018 mSmallestSizeConfigurations = smallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -07001019 }
1020
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001021 private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001022 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001023 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
1024 "Can't report activity moved to display - client not running, activityRecord="
1025 + this + ", displayId=" + displayId);
Wale Ogunwale22e25262016-02-01 10:32:02 -08001026 return;
1027 }
1028 try {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001029 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
1030 "Reporting activity moved to display" + ", activityRecord=" + this
1031 + ", displayId=" + displayId + ", config=" + config);
Chong Zhang6be533e2016-06-17 16:24:21 -07001032
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001033 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001034 MoveToDisplayItem.obtain(displayId, config));
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001035 } catch (RemoteException e) {
1036 // If process died, whatever.
1037 }
1038 }
1039
1040 private void scheduleConfigurationChanged(Configuration config) {
Wale Ogunwalef6733932018-06-27 05:14:34 -07001041 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001042 if (DEBUG_CONFIGURATION) Slog.w(TAG,
1043 "Can't report activity configuration update - client not running"
1044 + ", activityRecord=" + this);
1045 return;
1046 }
1047 try {
1048 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
1049 + config);
1050
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001051 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001052 ActivityConfigurationChangeItem.obtain(config));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001053 } catch (RemoteException e) {
1054 // If process died, whatever.
1055 }
1056 }
1057
Louis Chang3b21bdc2019-03-25 15:49:14 +08001058 boolean scheduleTopResumedActivityChanged(boolean onTop) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001059 if (!attachedToProcess()) {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001060 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001061 Slog.w(TAG, "Can't report activity position update - client not running"
1062 + ", activityRecord=" + this);
1063 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001064 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001065 }
1066 try {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001067 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001068 Slog.v(TAG, "Sending position change to " + this + ", onTop: " + onTop);
1069 }
1070
1071 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1072 TopResumedActivityChangeItem.obtain(onTop));
1073 } catch (RemoteException e) {
1074 // If process died, whatever.
Louis Chang3b21bdc2019-03-25 15:49:14 +08001075 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001076 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001077 return true;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001078 }
1079
Winson Chung5af42fc2017-03-24 17:11:33 -07001080 void updateMultiWindowMode() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001081 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001082 return;
1083 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001084
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001085 if (task.getStack().deferScheduleMultiWindowModeChanged()) {
1086 // Don't do anything if we are currently deferring multi-window mode change.
1087 return;
1088 }
1089
Winson Chung5af42fc2017-03-24 17:11:33 -07001090 // An activity is considered to be in multi-window mode if its task isn't fullscreen.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001091 final boolean inMultiWindowMode = inMultiWindowMode();
Winson Chung609e1e92017-05-08 10:52:12 -07001092 if (inMultiWindowMode != mLastReportedMultiWindowMode) {
1093 mLastReportedMultiWindowMode = inMultiWindowMode;
Winson Chung5af42fc2017-03-24 17:11:33 -07001094 scheduleMultiWindowModeChanged(getConfiguration());
1095 }
1096 }
1097
1098 private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001099 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001100 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001101 MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001102 } catch (Exception e) {
1103 // If process died, I don't care.
1104 }
1105 }
1106
Winson Chungab76bbc2017-08-14 13:33:51 -07001107 void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001108 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001109 return;
1110 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001111
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001112 final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
Winson Chungab76bbc2017-08-14 13:33:51 -07001113 if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001114 // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
Winson Chung059955f2018-08-08 16:10:20 -07001115 // update that here in order. Set the last reported MW state to the same as the PiP
1116 // state since we haven't yet actually resized the task (these callbacks need to
1117 // preceed the configuration change from the resiez.
1118 // TODO(110009072): Once we move these callbacks to the client, remove all logic related
1119 // to forcing the update of the picture-in-picture mode as a part of the PiP animation.
Winson Chung609e1e92017-05-08 10:52:12 -07001120 mLastReportedPictureInPictureMode = inPictureInPictureMode;
Winson Chung059955f2018-08-08 16:10:20 -07001121 mLastReportedMultiWindowMode = inPictureInPictureMode;
Evan Rosky1ac84462018-11-13 11:25:30 -08001122 final Configuration newConfig = new Configuration();
1123 if (targetStackBounds != null && !targetStackBounds.isEmpty()) {
Evan Rosky730f6e82018-12-03 17:40:11 -08001124 newConfig.setTo(task.getRequestedOverrideConfiguration());
1125 Rect outBounds = newConfig.windowConfiguration.getBounds();
1126 task.adjustForMinimalTaskDimensions(outBounds, outBounds);
1127 task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration());
Evan Rosky1ac84462018-11-13 11:25:30 -08001128 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001129 schedulePictureInPictureModeChanged(newConfig);
1130 scheduleMultiWindowModeChanged(newConfig);
1131 }
1132 }
1133
1134 private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001135 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001136 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001137 PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
Andrii Kulian446e8242017-10-26 15:17:29 -07001138 overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001139 } catch (Exception e) {
1140 // If process died, no one cares.
Filip Gruszczynskica664812015-12-04 12:43:36 -08001141 }
1142 }
1143
Louis Changcdec0802019-11-11 11:45:07 +08001144 Task getTask() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001145 return task;
1146 }
1147
Bryce Leeaf691c02017-03-20 14:20:22 -07001148 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001149 * Sets the Task on this activity for the purposes of re-use during launch where we will
1150 * re-use another activity instead of this one for the launch.
chaviw4ad54912018-05-30 11:05:44 -07001151 */
Louis Changcdec0802019-11-11 11:45:07 +08001152 void setTaskForReuse(Task task) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001153 this.task = task;
chaviw4ad54912018-05-30 11:05:44 -07001154 }
1155
Louis Changdc077272019-11-12 16:52:56 +08001156 ActivityStack getStack() {
Louis Changcdec0802019-11-11 11:45:07 +08001157 return task != null ? task.getTaskStack() : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001158 }
1159
1160 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001161 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +08001162 final Task oldTask = oldParent != null ? (Task) oldParent : null;
1163 final Task newTask = newParent != null ? (Task) newParent : null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001164 this.task = newTask;
1165
1166 super.onParentChanged(newParent, oldParent);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001167
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001168 if (oldParent == null && newParent != null) {
1169 // First time we are adding the activity to the system.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001170 mVoiceInteraction = newTask.voiceSession != null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001171 mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
1172 onDisplayChanged(task.getDisplayContent());
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001173 // TODO(b/36505427): Maybe this call should be moved inside
1174 // updateOverrideConfiguration()
1175 newTask.updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001176 // Make sure override configuration is up-to-date before using to create window
1177 // controller.
1178 updateSizeCompatMode();
1179 // When an activity is started directly into a split-screen fullscreen stack, we need to
1180 // update the initial multi-window modes so that the callbacks are scheduled correctly
1181 // when the user leaves that mode.
1182 mLastReportedMultiWindowMode = inMultiWindowMode();
1183 mLastReportedPictureInPictureMode = inPinnedWindowingMode();
1184 }
1185
Garfield Tane8d84ab2019-10-11 09:49:40 -07001186 // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
1187 // access visual elements like the {@link DisplayContent}. We must remove any associations
1188 // such as animations.
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001189 if (task == null) {
1190 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1191 // from this list so we do not participate in any future animations.
1192 if (getDisplayContent() != null) {
1193 getDisplayContent().mClosingApps.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001194 }
Wale Ogunwale8577a052019-10-26 23:22:34 -07001195 } else if (mLastParent != null && mLastParent.getTaskStack() != null) {
1196 task.getTaskStack().mExitingActivities.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001197 }
Louis Changdc077272019-11-12 16:52:56 +08001198 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001199
1200 // If we reparent, make sure to remove ourselves from the old animation registry.
1201 if (mAnimatingActivityRegistry != null) {
1202 mAnimatingActivityRegistry.notifyFinished(this);
1203 }
1204 mAnimatingActivityRegistry = stack != null
1205 ? stack.getAnimatingActivityRegistry()
1206 : null;
1207
1208 mLastParent = task;
1209
1210 updateColorTransform();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001211
1212 final ActivityStack oldStack = (oldTask != null) ? oldTask.getStack() : null;
1213 final ActivityStack newStack = (newTask != null) ? newTask.getStack() : null;
1214 // Inform old stack (if present) of activity removal and new stack (if set) of activity
1215 // addition.
1216 if (oldStack != newStack) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001217 if (oldStack != null) {
1218 oldStack.onActivityRemovedFromStack(this);
1219 }
1220 if (newStack != null) {
1221 newStack.onActivityAddedToStack(this);
1222 }
1223 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001224 }
1225
1226 private void updateColorTransform() {
1227 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
1228 getPendingTransaction().setColorTransform(mSurfaceControl,
1229 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
1230 mWmService.scheduleAnimationLocked();
1231 }
1232 }
1233
1234 @Override
1235 void onDisplayChanged(DisplayContent dc) {
1236 DisplayContent prevDc = mDisplayContent;
1237 super.onDisplayChanged(dc);
1238 if (prevDc == null || prevDc == mDisplayContent) {
1239 return;
1240 }
1241
1242 if (prevDc.mOpeningApps.remove(this)) {
1243 // Transfer opening transition to new display.
1244 mDisplayContent.mOpeningApps.add(this);
1245 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1246 mDisplayContent.executeAppTransition();
1247 }
1248
1249 if (prevDc.mChangingApps.remove(this)) {
1250 // This gets called *after* the ActivityRecord has been reparented to the new display.
1251 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1252 // so this token is now "frozen" while waiting for the animation to start on prevDc
1253 // (which will be cancelled since the window is no-longer a child). However, since this
1254 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1255 // so we need to cancel the change transition here.
1256 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1257 }
1258 prevDc.mClosingApps.remove(this);
1259
1260 if (prevDc.mFocusedApp == this) {
1261 prevDc.setFocusedApp(null);
Louis Changdc077272019-11-12 16:52:56 +08001262 final ActivityStack stack = dc.getTopStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001263 if (stack != null) {
1264 final Task task = stack.getTopChild();
1265 if (task != null && task.getTopChild() == this) {
1266 dc.setFocusedApp(this);
1267 }
1268 }
1269 }
1270
1271 if (mLetterbox != null) {
1272 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1273 }
1274 }
1275
1276 void layoutLetterbox(WindowState winHint) {
1277 final WindowState w = findMainWindow();
1278 if (w == null || winHint != null && w != winHint) {
1279 return;
1280 }
1281 final boolean surfaceReady = w.isDrawnLw() // Regular case
1282 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1283 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1284 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
1285 if (needsLetterbox) {
1286 if (mLetterbox == null) {
1287 mLetterbox = new Letterbox(() -> makeChildSurface(null),
1288 mWmService.mTransactionFactory);
1289 mLetterbox.attachInput(w);
1290 }
1291 getPosition(mTmpPoint);
1292 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1293 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1294 // is also applied to the task).
1295 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
Louis Changcdec0802019-11-11 11:45:07 +08001296 ? task.getDisplayedBounds() : getStack().getDisplayedBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001297 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
1298 } else if (mLetterbox != null) {
1299 mLetterbox.hide();
1300 }
1301 }
1302
1303 void updateLetterboxSurface(WindowState winHint) {
1304 final WindowState w = findMainWindow();
1305 if (w != winHint && winHint != null && w != null) {
1306 return;
1307 }
1308 layoutLetterbox(winHint);
1309 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1310 mLetterbox.applySurfaceChanges(getPendingTransaction());
1311 }
1312 }
1313
1314 Rect getLetterboxInsets() {
1315 if (mLetterbox != null) {
1316 return mLetterbox.getInsets();
1317 } else {
1318 return new Rect();
1319 }
1320 }
1321
1322 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
1323 void getLetterboxInnerBounds(Rect outBounds) {
1324 if (mLetterbox != null) {
1325 outBounds.set(mLetterbox.getInnerFrame());
1326 } else {
1327 outBounds.setEmpty();
1328 }
1329 }
1330
1331 /**
1332 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
1333 * the given {@code rect}.
1334 */
1335 boolean isLetterboxOverlappingWith(Rect rect) {
1336 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
1337 }
1338
Dianne Hackbornbe707852011-11-11 14:32:10 -08001339 static class Token extends IApplicationToken.Stub {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001340 private WeakReference<ActivityRecord> weakActivity;
Steven Timotiusaf03df62017-07-18 16:56:43 -07001341 private final String name;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001342 private final String tokenString;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001343
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001344 Token(Intent intent) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07001345 name = intent.getComponent().flattenToShortString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001346 tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
1347 }
1348
1349 private void attach(ActivityRecord activity) {
1350 if (weakActivity != null) {
1351 throw new IllegalStateException("Already attached..." + this);
1352 }
1353 weakActivity = new WeakReference<>(activity);
Wale Ogunwale7d701172015-03-11 15:36:30 -07001354 }
1355
Charles Chen69362cd2019-03-29 15:18:45 +08001356 private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001357 if (token == null) {
1358 return null;
1359 }
1360 ActivityRecord r = token.weakActivity.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001361 if (r == null || r.getActivityStack() == null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001362 return null;
1363 }
1364 return r;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001365 }
1366
Craig Mautnerde4ef022013-04-07 19:01:33 -07001367 @Override
Dianne Hackbornbe707852011-11-11 14:32:10 -08001368 public String toString() {
1369 StringBuilder sb = new StringBuilder(128);
1370 sb.append("Token{");
1371 sb.append(Integer.toHexString(System.identityHashCode(this)));
1372 sb.append(' ');
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001373 if (weakActivity != null) {
1374 sb.append(weakActivity.get());
1375 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001376 sb.append('}');
1377 return sb.toString();
1378 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07001379
1380 @Override
1381 public String getName() {
1382 return name;
1383 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001384 }
1385
Charles Chen69362cd2019-03-29 15:18:45 +08001386 static @Nullable ActivityRecord forTokenLocked(IBinder token) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001387 try {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001388 return Token.tokenToActivityRecordLocked((Token)token);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001389 } catch (ClassCastException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08001390 Slog.w(TAG, "Bad activity token: " + token, e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001391 return null;
1392 }
1393 }
1394
Riddle Hsuff9e8282019-04-24 23:55:11 +08001395 static boolean isResolverActivity(String className) {
1396 return ResolverActivity.class.getName().equals(className);
1397 }
1398
Louis Chang6a9be162019-07-15 10:41:32 +08001399 boolean isResolverOrDelegateActivity() {
1400 return isResolverActivity(mActivityComponent.getClassName()) || Objects.equals(
1401 mActivityComponent, mAtmService.mStackSupervisor.getSystemChooserActivity());
Craig Mautnerac6f8432013-07-17 13:24:59 -07001402 }
1403
Patrick Baumann31426b22018-05-21 13:46:40 -07001404 boolean isResolverOrChildActivity() {
1405 if (!"android".equals(packageName)) {
1406 return false;
1407 }
1408 try {
1409 return ResolverActivity.class.isAssignableFrom(
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001410 Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
Patrick Baumann31426b22018-05-21 13:46:40 -07001411 } catch (ClassNotFoundException e) {
1412 return false;
1413 }
1414 }
1415
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001416 ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
1417 int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent,
1418 String _resolvedType, ActivityInfo aInfo, Configuration _configuration,
1419 ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
1420 boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
1421 ActivityOptions options, ActivityRecord sourceRecord) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001422 super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
1423 null /* displayContent */, false /* ownerCanManageAppTokens */);
1424
1425 mAtmService = _service;
1426 appToken = (Token) token;
1427 info = aInfo;
1428 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1429 packageName = info.applicationInfo.packageName;
1430 mInputApplicationHandle = new InputApplicationHandle(appToken);
1431 intent = _intent;
1432
1433 // If the class name in the intent doesn't match that of the target, this is probably an
1434 // alias. We have to create a new ComponentName object to keep track of the real activity
1435 // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
1436 if (info.targetActivity == null
1437 || (info.targetActivity.equals(intent.getComponent().getClassName())
1438 && (info.launchMode == LAUNCH_MULTIPLE
1439 || info.launchMode == LAUNCH_SINGLE_TOP))) {
1440 mActivityComponent = intent.getComponent();
1441 } else {
1442 mActivityComponent =
1443 new ComponentName(info.packageName, info.targetActivity);
1444 }
1445
1446 mTargetSdk = info.applicationInfo.targetSdkVersion;
1447 mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
1448 setOrientation(info.screenOrientation);
1449 mRotationAnimationHint = info.rotationAnimation;
1450
1451 mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
1452 mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
1453 mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
1454
1455 int realTheme = info.getThemeResource();
1456 if (realTheme == Resources.ID_NULL) {
1457 realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
1458 ? android.R.style.Theme : android.R.style.Theme_Holo;
1459 }
1460
1461 final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
1462 realTheme, com.android.internal.R.styleable.Window, mUserId);
1463
1464 if (ent != null) {
1465 mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
1466 hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
1467 noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
1468 } else {
1469 hasWallpaper = false;
1470 noDisplay = false;
1471 }
1472
1473 if (options != null) {
1474 mLaunchTaskBehind = options.getLaunchTaskBehind();
1475
1476 final int rotationAnimation = options.getRotationAnimationHint();
1477 // Only override manifest supplied option if set.
1478 if (rotationAnimation >= 0) {
1479 mRotationAnimationHint = rotationAnimation;
1480 }
1481 }
1482
1483 // Application tokens start out hidden.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01001484 setHidden(true);
Issei Suzuki1669ea42019-11-06 14:20:59 +01001485 mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001486
1487 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
1488 ColorDisplayService.ColorDisplayServiceInternal.class);
1489 cds.attachColorTransformController(packageName, mUserId,
1490 new WeakReference<>(mColorTransformController));
1491
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001492 appToken.attach(this);
1493
Wale Ogunwaled32da472018-11-16 07:19:28 -08001494 mRootActivityContainer = _service.mRootActivityContainer;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001495 launchedFromPid = _launchedFromPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 launchedFromUid = _launchedFromUid;
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001497 launchedFromPackage = _launchedFromPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 shortComponentName = _intent.getComponent().flattenToShortString();
1499 resolvedType = _resolvedType;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001500 componentSpecified = _componentSpecified;
Dianne Hackbornfb81d092015-08-03 17:14:46 -07001501 rootVoiceInteraction = _rootVoiceInteraction;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07001502 mLastReportedConfiguration = new MergedConfiguration(_configuration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 resultTo = _resultTo;
1504 resultWho = _resultWho;
1505 requestCode = _reqCode;
Bryce Lee7ace3952018-02-16 14:34:32 -08001506 setState(INITIALIZING, "ActivityRecord ctor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 launchFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 stopped = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001509 delayedResume = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 finishing = false;
Wale Ogunwalef81c1d12016-01-12 12:20:18 -08001511 deferRelaunchUntilPaused = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 keysPaused = false;
1513 inHistory = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 nowVisible = false;
Vishnu Nair9ba31652018-11-13 14:34:05 -08001515 mDrawn = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 idle = false;
1517 hasBeenLaunched = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001518 mStackSupervisor = supervisor;
Robert Carr0f5d7532016-10-17 16:39:17 -07001519
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001520 taskAffinity = aInfo.taskAffinity;
1521 stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001522 nonLocalizedLabel = aInfo.nonLocalizedLabel;
1523 labelRes = aInfo.labelRes;
1524 if (nonLocalizedLabel == null && labelRes == 0) {
1525 ApplicationInfo app = aInfo.applicationInfo;
1526 nonLocalizedLabel = app.nonLocalizedLabel;
1527 labelRes = app.labelRes;
1528 }
1529 icon = aInfo.getIconResource();
1530 logo = aInfo.getLogoResource();
1531 theme = aInfo.getThemeResource();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001532 if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
1533 windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
1534 }
1535 if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
1536 && (aInfo.applicationInfo.uid == SYSTEM_UID
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001537 || aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
1538 processName = _caller.mName;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001539 } else {
1540 processName = aInfo.processName;
1541 }
1542
1543 if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
1544 intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1545 }
1546
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001547 launchMode = aInfo.launchMode;
1548
Winson Chung83471632016-12-13 11:02:12 -08001549 setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001550
1551 immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
1552
1553 requestedVrComponent = (aInfo.requestedVrComponent == null) ?
1554 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
chaviw59b98852017-06-13 12:05:44 -07001555
Charles He2bf28322017-10-12 22:24:49 +01001556 lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
Andrii Kulianeceebbf2019-06-26 17:36:51 -07001557 if (info.applicationInfo.isPrivilegedApp()
1558 && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
Charles He2bf28322017-10-12 22:24:49 +01001559 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1560 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1561 }
1562
1563 if (options != null) {
1564 pendingOptions = options;
Charles He2bf28322017-10-12 22:24:49 +01001565 final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
1566 if (usageReport != null) {
1567 appTimeTracker = new AppTimeTracker(usageReport);
1568 }
1569 final boolean useLockTask = pendingOptions.getLockTaskMode();
1570 if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
1571 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
1572 }
Louis Changd58cb672018-12-24 17:45:16 +08001573 // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
1574 mHandoverLaunchDisplayId = options.getLaunchDisplayId();
Charles He2bf28322017-10-12 22:24:49 +01001575 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001576 }
1577
Garfield Tane8d84ab2019-10-11 09:49:40 -07001578 @Override
1579 ActivityRecord asActivityRecord() {
1580 // I am an activity record!
1581 return this;
1582 }
1583
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001584 void setProcess(WindowProcessController proc) {
Dianne Hackborn68a06332017-11-15 17:54:18 -08001585 app = proc;
1586 final ActivityRecord root = task != null ? task.getRootActivity() : null;
1587 if (root == this) {
1588 task.setRootProcess(proc);
1589 }
1590 }
1591
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001592 boolean hasProcess() {
1593 return app != null;
1594 }
1595
1596 boolean attachedToProcess() {
1597 return hasProcess() && app.hasThread();
1598 }
1599
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001600 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1601 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1602 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1603 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001604 // If the display is frozen, we won't do anything until the actual window is
1605 // displayed so there is no reason to put in the starting window.
1606 if (!okToDisplay()) {
Yunfan Chen48c0ed082018-12-05 18:15:35 -08001607 return false;
1608 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001609
1610 if (mStartingData != null) {
1611 return false;
1612 }
1613
1614 final WindowState mainWin = findMainWindow();
1615 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
1616 // App already has a visible window...why would you want a starting window?
1617 return false;
1618 }
1619
1620 final ActivityManager.TaskSnapshot snapshot =
Louis Changcdec0802019-11-11 11:45:07 +08001621 mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
Garfield Tane8d84ab2019-10-11 09:49:40 -07001622 false /* restoreFromDisk */, false /* reducedResolution */);
1623 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
1624 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
1625
1626 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
1627 return createSnapshot(snapshot);
1628 }
1629
1630 // If this is a translucent window, then don't show a starting window -- the current
1631 // effect (a full-screen opaque starting window that fades away to the real contents
1632 // when it is ready) does not work for this.
1633 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
1634 if (theme != 0) {
1635 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
1636 com.android.internal.R.styleable.Window,
1637 mWmService.mCurrentUserId);
1638 if (ent == null) {
1639 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
1640 // see that.
1641 return false;
1642 }
1643 final boolean windowIsTranslucent = ent.array.getBoolean(
1644 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
1645 final boolean windowIsFloating = ent.array.getBoolean(
1646 com.android.internal.R.styleable.Window_windowIsFloating, false);
1647 final boolean windowShowWallpaper = ent.array.getBoolean(
1648 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
1649 final boolean windowDisableStarting = ent.array.getBoolean(
1650 com.android.internal.R.styleable.Window_windowDisablePreview, false);
1651 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
1652 windowIsTranslucent, windowIsFloating, windowShowWallpaper);
1653 if (windowIsTranslucent) {
1654 return false;
1655 }
1656 if (windowIsFloating || windowDisableStarting) {
1657 return false;
1658 }
1659 if (windowShowWallpaper) {
1660 if (getDisplayContent().mWallpaperController
1661 .getWallpaperTarget() == null) {
1662 // If this theme is requesting a wallpaper, and the wallpaper
1663 // is not currently visible, then this effectively serves as
1664 // an opaque window and our starting window transition animation
1665 // can still work. We just need to make sure the starting window
1666 // is also showing the wallpaper.
1667 windowFlags |= FLAG_SHOW_WALLPAPER;
1668 } else {
1669 return false;
1670 }
1671 }
1672 }
1673
1674 if (transferStartingWindow(transferFrom)) {
1675 return true;
1676 }
1677
1678 // There is no existing starting window, and we don't want to create a splash screen, so
1679 // that's it!
1680 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
1681 return false;
1682 }
1683
1684 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
1685 mStartingData = new SplashScreenStartingData(mWmService, pkg,
1686 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
1687 getMergedOverrideConfiguration());
1688 scheduleAddStartingWindow();
1689 return true;
1690 }
1691
1692 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
1693 if (snapshot == null) {
1694 return false;
1695 }
1696
1697 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
1698 mStartingData = new SnapshotStartingData(mWmService, snapshot);
1699 scheduleAddStartingWindow();
1700 return true;
1701 }
1702
1703 void scheduleAddStartingWindow() {
1704 // Note: we really want to do sendMessageAtFrontOfQueue() because we
1705 // want to process the message ASAP, before any other queued
1706 // messages.
1707 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
1708 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
1709 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
1710 }
1711 }
1712
1713 private class AddStartingWindow implements Runnable {
1714
1715 @Override
1716 public void run() {
1717 // Can be accessed without holding the global lock
1718 final StartingData startingData;
1719 synchronized (mWmService.mGlobalLock) {
1720 // There can only be one adding request, silly caller!
1721 mWmService.mAnimationHandler.removeCallbacks(this);
1722
1723 if (mStartingData == null) {
1724 // Animation has been canceled... do nothing.
1725 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1726 "startingData was nulled out before handling"
1727 + " mAddStartingWindow: %s", ActivityRecord.this);
1728 return;
1729 }
1730 startingData = mStartingData;
1731 }
1732
1733 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
1734 this, startingData);
1735
1736
1737 WindowManagerPolicy.StartingSurface surface = null;
1738 try {
1739 surface = startingData.createStartingSurface(ActivityRecord.this);
1740 } catch (Exception e) {
1741 Slog.w(TAG, "Exception when adding starting window", e);
1742 }
1743 if (surface != null) {
1744 boolean abort = false;
1745 synchronized (mWmService.mGlobalLock) {
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08001746 // If the window was successfully added, then we need to remove it.
1747 if (mStartingData == null) {
1748 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Aborted starting %s: startingData=%s",
1749 ActivityRecord.this, mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001750
1751 startingWindow = null;
1752 mStartingData = null;
1753 abort = true;
1754 } else {
1755 startingSurface = surface;
1756 }
1757 if (!abort) {
1758 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1759 "Added starting %s: startingWindow=%s startingView=%s",
1760 ActivityRecord.this, startingWindow, startingSurface);
1761 }
1762 }
1763 if (abort) {
1764 surface.remove();
1765 }
1766 } else {
1767 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
1768 ActivityRecord.this);
1769 }
1770 }
1771 }
1772
1773 private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
1774
1775 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
1776 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
1777 ActivityManager.TaskSnapshot snapshot) {
1778 if (getDisplayContent().mAppTransition.getAppTransition()
1779 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
1780 // TODO(b/34099271): Remove this statement to add back the starting window and figure
1781 // out why it causes flickering, the starting window appears over the thumbnail while
1782 // the docked from recents transition occurs
1783 return STARTING_WINDOW_TYPE_NONE;
1784 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
1785 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1786 } else if (taskSwitch && allowTaskSnapshot) {
1787 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
1788 // For low RAM devices, we use the splash screen starting window instead of the
1789 // task snapshot starting window.
1790 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1791 }
Jay Aliomer8b2671b2019-10-24 13:18:06 -04001792 return snapshot == null ? STARTING_WINDOW_TYPE_SPLASH_SCREEN
Garfield Tane8d84ab2019-10-11 09:49:40 -07001793 : snapshotOrientationSameAsTask(snapshot) || fromRecents
1794 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1795 } else {
1796 return STARTING_WINDOW_TYPE_NONE;
1797 }
1798 }
1799
1800 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
1801 if (snapshot == null) {
1802 return false;
1803 }
Louis Changcdec0802019-11-11 11:45:07 +08001804 return task.getConfiguration().orientation == snapshot.getOrientation();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001805 }
1806
1807 void removeStartingWindow() {
1808 if (startingWindow == null) {
1809 if (mStartingData != null) {
1810 // Starting window has not been added yet, but it is scheduled to be added.
1811 // Go ahead and cancel the request.
1812 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
1813 mStartingData = null;
1814 }
1815 return;
1816 }
1817
1818 final WindowManagerPolicy.StartingSurface surface;
1819 if (mStartingData != null) {
1820 surface = startingSurface;
1821 mStartingData = null;
1822 startingSurface = null;
1823 startingWindow = null;
1824 startingDisplayed = false;
1825 if (surface == null) {
1826 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1827 "startingWindow was set but startingSurface==null, couldn't "
1828 + "remove");
1829
1830 return;
1831 }
1832 } else {
1833 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1834 "Tried to remove starting window but startingWindow was null: %s",
1835 this);
1836 return;
1837 }
1838
1839 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
1840 + " startingView=%s Callers=%s",
1841 this, startingWindow, startingSurface, Debug.getCallers(5));
1842
1843
1844 // Use the same thread to remove the window as we used to add it, as otherwise we end up
1845 // with things in the view hierarchy being called from different threads.
1846 mWmService.mAnimationHandler.post(() -> {
1847 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
1848 try {
1849 surface.remove();
1850 } catch (Exception e) {
1851 Slog.w(TAG_WM, "Exception when removing starting window", e);
1852 }
1853 });
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001854 }
1855
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001856 private void removeAppTokenFromDisplay() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001857 if (mWmService.mRoot == null) return;
Yunfan Chend4ef3012018-11-28 21:14:32 -08001858
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001859 final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001860 if (dc == null) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001861 Slog.w(TAG, "removeAppTokenFromDisplay: Attempted to remove token: "
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001862 + appToken + " from non-existing displayId=" + getDisplayId());
Bryce Lee7ace3952018-02-16 14:34:32 -08001863 return;
1864 }
Wale Ogunwalecc367f42017-02-01 08:12:14 -08001865 // Resume key dispatching if it is currently paused before we remove the container.
1866 resumeKeyDispatchingLocked();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001867 dc.removeAppToken(appToken.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 }
1869
Winson Chung30480042017-01-26 10:55:34 -08001870 /**
1871 * Reparents this activity into {@param newTask} at the provided {@param position}. The caller
1872 * should ensure that the {@param newTask} is not already the parent of this activity.
1873 */
Louis Changcdec0802019-11-11 11:45:07 +08001874 void reparent(Task newTask, int position, String reason) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001875 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001876 Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
1877 return;
1878 }
Louis Changcdec0802019-11-11 11:45:07 +08001879 final Task prevTask = task;
Winson Chung30480042017-01-26 10:55:34 -08001880 if (prevTask == newTask) {
1881 throw new IllegalArgumentException(reason + ": task=" + newTask
1882 + " is already the parent of r=" + this);
1883 }
1884
Winson Chung74666102017-02-22 17:49:24 -08001885 // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
1886 // the stacks in strange states. For now, we should use Task.reparent() to ensure that
1887 // the stack is left in an OK state.
1888 if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
1889 throw new IllegalArgumentException(reason + ": task=" + newTask
1890 + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
1891 + " r=" + this + " (" + prevTask.getStackId() + ")");
1892 }
1893
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001894 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
Garfield Tane8d84ab2019-10-11 09:49:40 -07001895 + " to task=%d at %d", this, task.mTaskId, position);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001896 reparent(newTask, position);
Winson Chung30480042017-01-26 10:55:34 -08001897 }
1898
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001899 private boolean isHomeIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07001900 return ACTION_MAIN.equals(intent.getAction())
Chilun2ef71f72018-11-16 17:57:15 +08001901 && (intent.hasCategory(CATEGORY_HOME)
1902 || intent.hasCategory(CATEGORY_SECONDARY_HOME))
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001903 && intent.getCategories().size() == 1
1904 && intent.getData() == null
1905 && intent.getType() == null;
1906 }
1907
Chong Zhangad24f962016-08-25 12:12:33 -07001908 static boolean isMainIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07001909 return ACTION_MAIN.equals(intent.getAction())
1910 && intent.hasCategory(CATEGORY_LAUNCHER)
Chong Zhangad24f962016-08-25 12:12:33 -07001911 && intent.getCategories().size() == 1
1912 && intent.getData() == null
1913 && intent.getType() == null;
1914 }
1915
Louis Chang6a9be162019-07-15 10:41:32 +08001916 @VisibleForTesting
1917 boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001918 if (uid == Process.myUid() || uid == 0) {
1919 // System process can launch home activity.
1920 return true;
1921 }
Winson Chung547afd22018-05-17 16:03:25 -07001922 // Allow the recents component to launch the home activity.
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07001923 final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
Winson Chung547afd22018-05-17 16:03:25 -07001924 if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
1925 return true;
1926 }
Louis Chang6a9be162019-07-15 10:41:32 +08001927 // Resolver or system chooser activity can launch home activity.
1928 return sourceRecord != null && sourceRecord.isResolverOrDelegateActivity();
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001929 }
1930
Winson Chung83471632016-12-13 11:02:12 -08001931 /**
1932 * @return whether the given package name can launch an assist activity.
1933 */
1934 private boolean canLaunchAssistActivity(String packageName) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001935 final ComponentName assistComponent =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001936 mAtmService.mActiveVoiceInteractionServiceComponent;
Winson Chung83471632016-12-13 11:02:12 -08001937 if (assistComponent != null) {
1938 return assistComponent.getPackageName().equals(packageName);
1939 }
1940 return false;
1941 }
1942
1943 private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
1944 ActivityOptions options, ActivityRecord sourceRecord) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001945 int activityType = ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001946 if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
Louis Chang6a9be162019-07-15 10:41:32 +08001947 && isHomeIntent(intent) && !isResolverOrDelegateActivity()) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001948 // This sure looks like a home activity!
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001949 activityType = ACTIVITY_TYPE_HOME;
Wale Ogunwaledf241e92016-10-13 15:14:21 -07001950
1951 if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
1952 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
1953 // We only allow home activities to be resizeable if they explicitly requested it.
1954 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
1955 }
Andrii Kulian3b3fb662019-06-26 17:52:26 -07001956 } else if (mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07001957 info.applicationInfo.uid)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001958 activityType = ACTIVITY_TYPE_RECENTS;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001959 } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
Winson Chung83471632016-12-13 11:02:12 -08001960 && canLaunchAssistActivity(launchedFromPackage)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001961 activityType = ACTIVITY_TYPE_ASSISTANT;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001962 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001963 setActivityType(activityType);
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07001964 }
1965
Louis Changcdec0802019-11-11 11:45:07 +08001966 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001967 if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
Craig Mautnera228ae92014-07-09 05:44:55 -07001968 task.setTaskToAffiliateWith(taskToAffiliateWith);
1969 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07001970 }
1971
Andrii Kulian02b7a832016-10-06 23:11:56 -07001972 /**
1973 * @return Stack value from current task, null if there is no task.
1974 */
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001975 ActivityStack getActivityStack() {
1976 return task != null ? task.getStack() : null;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001977 }
1978
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001979 int getStackId() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001980 return getActivityStack() != null ? getActivityStack().mStackId : INVALID_STACK_ID;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001981 }
1982
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001983 ActivityDisplay getDisplay() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001984 final ActivityStack stack = getActivityStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001985 return stack != null ? stack.getDisplay() : null;
1986 }
1987
Garfield Tane8d84ab2019-10-11 09:49:40 -07001988 @Override
1989 boolean fillsParent() {
1990 return occludesParent();
1991 }
1992
1993 /** Returns true if this activity is opaque and fills the entire space of this task. */
1994 boolean occludesParent() {
1995 return mOccludesParent;
1996 }
1997
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07001998 boolean setOccludesParent(boolean occludesParent) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001999 final boolean changed = occludesParent != mOccludesParent;
2000 mOccludesParent = occludesParent;
2001 setMainWindowOpaque(occludesParent);
2002 mWmService.mWindowPlacerLocked.requestTraversal();
2003
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08002004 if (changed && task != null && !occludesParent) {
2005 getActivityStack().convertActivityToTranslucent(this);
Riddle Hsued5789b2019-08-21 15:12:03 +08002006 }
2007 // Always ensure visibility if this activity doesn't occlude parent, so the
2008 // {@link #returningOptions} of the activity under this one can be applied in
2009 // {@link #handleAlreadyVisible()}.
2010 if (changed || !occludesParent) {
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002011 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Craig Mautner5eda9b32013-07-02 11:58:16 -07002012 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002013 return changed;
Craig Mautner4addfc52013-06-25 08:05:45 -07002014 }
2015
Garfield Tane8d84ab2019-10-11 09:49:40 -07002016 void setMainWindowOpaque(boolean isOpaque) {
2017 final WindowState win = findMainWindow();
2018 if (win == null) {
2019 return;
2020 }
2021 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2022 win.mWinAnimator.setOpaqueLocked(isOpaque);
2023 }
2024
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002025 void takeFromHistory() {
2026 if (inHistory) {
2027 inHistory = false;
2028 if (task != null && !finishing) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002029 task = null;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002030 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -07002031 clearOptionsLocked();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002032 }
2033 }
2034
2035 boolean isInHistory() {
2036 return inHistory;
2037 }
2038
Wale Ogunwale7d701172015-03-11 15:36:30 -07002039 boolean isInStackLocked() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002040 final ActivityStack stack = getActivityStack();
Andrii Kulian02b7a832016-10-06 23:11:56 -07002041 return stack != null && stack.isInStackLocked(this) != null;
Wale Ogunwale7d701172015-03-11 15:36:30 -07002042 }
2043
Craig Mautner21d24a22014-04-23 11:45:37 -07002044 boolean isPersistable() {
Ruben Brunkf53497c2017-03-27 20:26:17 -07002045 return (info.persistableMode == PERSIST_ROOT_ONLY ||
2046 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002047 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
Craig Mautner21d24a22014-04-23 11:45:37 -07002048 }
2049
Wale Ogunwale4cea0f52015-12-25 06:30:31 -08002050 boolean isFocusable() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08002051 return mRootActivityContainer.isFocusable(this, isAlwaysFocusable());
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002052 }
2053
2054 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08002055 return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002056 }
2057
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07002058 /** @return whether this activity is non-resizeable or forced to be resizeable */
2059 boolean isNonResizableOrForcedResizable(int windowingMode) {
2060 if (windowingMode == WINDOWING_MODE_PINNED && info.supportsPictureInPicture()) {
2061 return false;
2062 }
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002063 return info.resizeMode != RESIZE_MODE_RESIZEABLE
Wale Ogunwale72a73e32016-10-13 12:16:39 -07002064 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Jorim Jaggicd13d332016-04-27 15:40:20 -07002065 }
2066
Winson Chunge6308042016-10-31 09:24:01 -07002067 /**
Winson Chungd3395382016-12-13 11:49:09 -08002068 * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
Winson Chunge6308042016-10-31 09:24:01 -07002069 */
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002070 boolean supportsPictureInPicture() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002071 return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
Winson Chungd3395382016-12-13 11:49:09 -08002072 && info.supportsPictureInPicture();
2073 }
2074
2075 /**
2076 * @return whether this activity supports split-screen multi-window and can be put in the docked
2077 * stack.
2078 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002079 @Override
2080 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08002081 // An activity can not be docked even if it is considered resizeable because it only
2082 // supports picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002083 return super.supportsSplitScreenWindowingMode()
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002084 && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002085 }
2086
2087 /**
2088 * @return whether this activity supports freeform multi-window and can be put in the freeform
2089 * stack.
2090 */
2091 boolean supportsFreeform() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002092 return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002093 }
2094
2095 /**
2096 * @return whether this activity supports non-PiP multi-window.
2097 */
2098 private boolean supportsResizeableMultiWindow() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002099 return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
Winson Chungd3395382016-12-13 11:49:09 -08002100 && (ActivityInfo.isResizeableMode(info.resizeMode)
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002101 || mAtmService.mForceResizableActivities);
Wale Ogunwaled26176f2016-01-25 20:04:04 -08002102 }
2103
Winson Chunge6308042016-10-31 09:24:01 -07002104 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002105 * Check whether this activity can be launched on the specified display.
Riddle Hsu16567132018-08-16 21:37:47 +08002106 *
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002107 * @param displayId Target display id.
Riddle Hsu16567132018-08-16 21:37:47 +08002108 * @return {@code true} if either it is the default display or this activity can be put on a
2109 * secondary screen.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002110 */
2111 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002112 return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
Riddle Hsu16567132018-08-16 21:37:47 +08002113 launchedFromUid, info);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002114 }
2115
2116 /**
Robert Carrc33658e2017-04-11 18:24:20 -07002117 * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
2118 * the activity has requested to enter PiP when it would otherwise be stopped.
2119 *
Winson Chung298f95b2017-08-10 15:57:18 -07002120 * @return whether this activity is currently allowed to enter PIP.
Winson Chunge6308042016-10-31 09:24:01 -07002121 */
Winson Chung298f95b2017-08-10 15:57:18 -07002122 boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
Wale Ogunwaleb9a0c992017-04-18 07:25:20 -07002123 if (!supportsPictureInPicture()) {
2124 return false;
2125 }
2126
Winson Chungf4ac0632017-03-17 12:34:12 -07002127 // Check app-ops and see if PiP is supported for this package
2128 if (!checkEnterPictureInPictureAppOpsState()) {
2129 return false;
2130 }
2131
Winson Chungf1bfee12017-03-24 17:11:33 -07002132 // Check to see if we are in VR mode, and disallow PiP if so
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002133 if (mAtmService.shouldDisableNonVrUiLocked()) {
Winson Chungf1bfee12017-03-24 17:11:33 -07002134 return false;
2135 }
2136
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002137 boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002138 boolean isCurrentAppLocked =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002139 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002140 final ActivityDisplay display = getDisplay();
2141 boolean hasPinnedStack = display != null && display.hasPinnedStack();
Winson Chungbb348802017-01-30 12:01:45 -08002142 // Don't return early if !isNotLocked, since we want to throw an exception if the activity
2143 // is in an incorrect state
Winson Chunge581ebf2017-02-21 08:25:03 -08002144 boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
Robert Carrc33658e2017-04-11 18:24:20 -07002145
2146 // We don't allow auto-PiP when something else is already pipped.
2147 if (beforeStopping && hasPinnedStack) {
2148 return false;
2149 }
2150
Bryce Lee7ace3952018-02-16 14:34:32 -08002151 switch (mState) {
Winson Chungc2baac02017-01-11 13:34:47 -08002152 case RESUMED:
Winson Chunge581ebf2017-02-21 08:25:03 -08002153 // When visible, allow entering PiP if the app is not locked. If it is over the
2154 // keyguard, then we will prompt to unlock in the caller before entering PiP.
Robert Carrc33658e2017-04-11 18:24:20 -07002155 return !isCurrentAppLocked &&
Winson Chungf7e03e12017-08-22 11:32:16 -07002156 (supportsEnterPipOnTaskSwitch || !beforeStopping);
Winson Chungc2baac02017-01-11 13:34:47 -08002157 case PAUSING:
2158 case PAUSED:
Winson Chungbb348802017-01-30 12:01:45 -08002159 // When pausing, then only allow enter PiP as in the resume state, and in addition,
2160 // require that there is not an existing PiP activity and that the current system
2161 // state supports entering PiP
Winson Chunge581ebf2017-02-21 08:25:03 -08002162 return isNotLockedOrOnKeyguard && !hasPinnedStack
Winson Chungf7e03e12017-08-22 11:32:16 -07002163 && supportsEnterPipOnTaskSwitch;
Winson Chungc2baac02017-01-11 13:34:47 -08002164 case STOPPING:
2165 // When stopping in a valid state, then only allow enter PiP as in the pause state.
2166 // Otherwise, fall through to throw an exception if the caller is trying to enter
2167 // PiP in an invalid stopping state.
Winson Chungf7e03e12017-08-22 11:32:16 -07002168 if (supportsEnterPipOnTaskSwitch) {
Winson Chungf4ac0632017-03-17 12:34:12 -07002169 return isNotLockedOrOnKeyguard && !hasPinnedStack;
Winson Chungc2baac02017-01-11 13:34:47 -08002170 }
2171 default:
Winson Chung298f95b2017-08-10 15:57:18 -07002172 return false;
Winson Chungb5c41b72016-12-07 15:00:47 -08002173 }
Winson Chunge6308042016-10-31 09:24:01 -07002174 }
2175
Winson Chung59fda9e2017-01-20 16:14:51 -08002176 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -07002177 * Sets if this AWT is in the process of closing or entering PIP.
2178 * {@link #mWillCloseOrEnterPip}}
2179 */
2180 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
2181 mWillCloseOrEnterPip = willCloseOrEnterPip;
2182 }
2183
2184 /**
2185 * Returns whether this AWT is considered closing. Conditions are either
2186 * 1. Is this app animating and was requested to be hidden
2187 * 2. App is delayed closing since it might enter PIP.
2188 */
2189 boolean isClosingOrEnteringPip() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01002190 return (isAnimating(TRANSITION | PARENTS) && !mVisibleRequested) || mWillCloseOrEnterPip;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002191 }
2192 /**
Winson Chungf4ac0632017-03-17 12:34:12 -07002193 * @return Whether AppOps allows this package to enter picture-in-picture.
Winson Chung59fda9e2017-01-20 16:14:51 -08002194 */
Winson Chungf4ac0632017-03-17 12:34:12 -07002195 private boolean checkEnterPictureInPictureAppOpsState() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002196 return mAtmService.getAppOpsService().checkOperation(
Andrii Kulianeceebbf2019-06-26 17:36:51 -07002197 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
Winson Chung59fda9e2017-01-20 16:14:51 -08002198 }
2199
Garfield Tane8d84ab2019-10-11 09:49:40 -07002200 boolean isAlwaysFocusable() {
2201 return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
2202 }
2203
2204 // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
2205 // focusable means resumeable. I guess with that in mind maybe we should rename the other
2206 // method to isResumeable() or something like that.
2207 boolean windowsAreFocusable() {
2208 if (mTargetSdk < Build.VERSION_CODES.Q) {
2209 final int pid = getPid();
2210 final ActivityRecord topFocusedAppOfMyProcess =
2211 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
2212 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
2213 // For the apps below Q, there can be only one app which has the focused window per
2214 // process, because legacy apps may not be ready for a multi-focus system.
2215 return false;
2216 }
2217 }
Louis Changa9c9d982019-11-11 11:20:19 +08002218 return (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable())
2219 && getParent() != null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002220 }
2221
Louis Chang19443452018-10-09 12:10:21 +08002222 /** Move activity with its stack to front and make the stack focused. */
2223 boolean moveFocusableActivityToTop(String reason) {
2224 if (!isFocusable()) {
2225 if (DEBUG_FOCUS) {
2226 Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
2227 }
2228 return false;
2229 }
2230
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002231 final ActivityStack stack = getActivityStack();
Louis Chang19443452018-10-09 12:10:21 +08002232 if (stack == null) {
2233 Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
2234 + this + " task=" + task);
2235 return false;
2236 }
2237
Wale Ogunwaled32da472018-11-16 07:19:28 -08002238 if (mRootActivityContainer.getTopResumedActivity() == this) {
Louis Chang19443452018-10-09 12:10:21 +08002239 if (DEBUG_FOCUS) {
2240 Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
2241 }
2242 return false;
2243 }
2244
2245 if (DEBUG_FOCUS) {
2246 Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
2247 }
2248
2249 stack.moveToFront(reason, task);
2250 // Report top activity change to tracking services and WM
Wale Ogunwaled32da472018-11-16 07:19:28 -08002251 if (mRootActivityContainer.getTopResumedActivity() == this) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002252 mAtmService.setResumedActivityUncheckLocked(this, reason);
Louis Chang19443452018-10-09 12:10:21 +08002253 }
2254 return true;
2255 }
Jorim Jaggife762342016-10-13 14:33:27 +02002256
Andrii Kuliande93eff2019-07-12 12:21:27 -07002257 /** Finish all activities in the task with the same affinity as this one. */
2258 void finishActivityAffinity() {
Louis Changcdec0802019-11-11 11:45:07 +08002259 final ArrayList<ActivityRecord> activities = task.mChildren;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002260 for (int index = activities.indexOf(this); index >= 0; --index) {
2261 final ActivityRecord cur = activities.get(index);
2262 if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
2263 break;
2264 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002265 cur.finishIfPossible("request-affinity", true /* oomAdj */);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002266 }
2267 }
2268
2269 /**
2270 * Sets the result for activity that started this one, clears the references to activities
2271 * started for result from this one, and clears new intents.
2272 */
2273 void finishActivityResults(int resultCode, Intent resultData) {
2274 // Send the result if needed
2275 if (resultTo != null) {
2276 if (DEBUG_RESULTS) {
2277 Slog.v(TAG_RESULTS, "Adding result to " + resultTo
2278 + " who=" + resultWho + " req=" + requestCode
2279 + " res=" + resultCode + " data=" + resultData);
2280 }
2281 if (resultTo.mUserId != mUserId) {
2282 if (resultData != null) {
2283 resultData.prepareToLeaveUser(mUserId);
2284 }
2285 }
2286 if (info.applicationInfo.uid > 0) {
2287 mAtmService.mUgmInternal.grantUriPermissionFromIntent(info.applicationInfo.uid,
2288 resultTo.packageName, resultData,
2289 resultTo.getUriPermissionsLocked(), resultTo.mUserId);
2290 }
2291 resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
2292 resultTo = null;
2293 } else if (DEBUG_RESULTS) {
2294 Slog.v(TAG_RESULTS, "No result destination from " + this);
2295 }
2296
2297 // Make sure this HistoryRecord is not holding on to other resources,
2298 // because clients have remote IPC references to this object so we
2299 // can't assume that will go away and want to avoid circular IPC refs.
2300 results = null;
2301 pendingResults = null;
2302 newIntents = null;
2303 setSavedState(null /* savedState */);
2304 }
2305
Andrii Kulian057a6512019-07-15 16:15:51 -07002306 /** Activity finish request was not executed. */
2307 static final int FINISH_RESULT_CANCELLED = 0;
2308 /** Activity finish was requested, activity will be fully removed later. */
2309 static final int FINISH_RESULT_REQUESTED = 1;
2310 /** Activity finish was requested, activity was removed from history. */
2311 static final int FINISH_RESULT_REMOVED = 2;
2312
2313 /** Definition of possible results for activity finish request. */
2314 @IntDef(prefix = { "FINISH_RESULT_" }, value = {
2315 FINISH_RESULT_CANCELLED,
2316 FINISH_RESULT_REQUESTED,
2317 FINISH_RESULT_REMOVED,
2318 })
2319 @interface FinishRequest {}
2320
Andrii Kuliande93eff2019-07-12 12:21:27 -07002321 /**
Louis Chang7b03ad92019-08-21 12:32:33 +08002322 * See {@link #finishIfPossible(int, Intent, String, boolean)}
Andrii Kuliande93eff2019-07-12 12:21:27 -07002323 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002324 @FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
Louis Chang7b03ad92019-08-21 12:32:33 +08002325 return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason, oomAdj);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002326 }
2327
2328 /**
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002329 * Finish activity if possible. If activity was resumed - we must first pause it to make the
2330 * activity below resumed. Otherwise we will try to complete the request immediately by calling
2331 * {@link #completeFinishing(String)}.
Andrii Kulian057a6512019-07-15 16:15:51 -07002332 * @return One of {@link FinishRequest} values:
2333 * {@link #FINISH_RESULT_REMOVED} if this activity has been removed from the history list.
2334 * {@link #FINISH_RESULT_REQUESTED} if removal process was started, but it is still in the list
2335 * and will be removed from history later.
2336 * {@link #FINISH_RESULT_CANCELLED} if activity is already finishing or in invalid state and the
2337 * request to finish it was not ignored.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002338 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002339 @FinishRequest int finishIfPossible(int resultCode, Intent resultData, String reason,
Louis Chang7b03ad92019-08-21 12:32:33 +08002340 boolean oomAdj) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002341 if (DEBUG_RESULTS || DEBUG_STATES) {
2342 Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
2343 + ", data=" + resultData + ", reason=" + reason);
2344 }
2345
Andrii Kuliande93eff2019-07-12 12:21:27 -07002346 if (finishing) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002347 Slog.w(TAG, "Duplicate finish request for r=" + this);
2348 return FINISH_RESULT_CANCELLED;
2349 }
2350
2351 if (!isInStackLocked()) {
2352 Slog.w(TAG, "Finish request when not in stack for r=" + this);
2353 return FINISH_RESULT_CANCELLED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002354 }
2355
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002356 final ActivityStack stack = getActivityStack();
Riddle Hsucf920232019-10-04 19:05:36 +08002357 final boolean mayAdjustTop = (isState(RESUMED) || stack.mResumedActivity == null)
2358 && stack.isFocusedStackOnDisplay();
2359 final boolean shouldAdjustGlobalFocus = mayAdjustTop
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002360 // It must be checked before {@link #makeFinishingLocked} is called, because a stack
2361 // is not visible if it only contains finishing activities.
2362 && mRootActivityContainer.isTopDisplayFocusedStack(stack);
2363
Riddle Hsua0022cd2019-09-09 21:12:41 +08002364 mAtmService.deferWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002365 try {
2366 makeFinishingLocked();
Louis Changcdec0802019-11-11 11:45:07 +08002367 // Make a local reference to its task since this.task could be set to null once this
2368 // activity is destroyed and detached from task.
2369 final Task task = getTask();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002370 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2371 mUserId, System.identityHashCode(this),
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002372 task.mTaskId, shortComponentName, reason);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002373 final ArrayList<ActivityRecord> activities = task.mChildren;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002374 final int index = activities.indexOf(this);
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002375 if (index < (task.getChildCount() - 1)) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002376 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2377 // If the caller asked that this activity (and all above it)
2378 // be cleared when the task is reset, don't lose that information,
2379 // but propagate it up to the next activity.
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002380 final ActivityRecord next = task.getChildAt(index + 1);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002381 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2382 }
2383 }
2384
2385 pauseKeyDispatchingLocked();
2386
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002387 // We are finishing the top focused activity and its stack has nothing to be focused so
2388 // the next focusable stack should be focused.
Riddle Hsucf920232019-10-04 19:05:36 +08002389 if (mayAdjustTop
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002390 && (stack.topRunningActivityLocked() == null || !stack.isFocusable())) {
Riddle Hsucf920232019-10-04 19:05:36 +08002391 if (shouldAdjustGlobalFocus) {
2392 // Move the entire hierarchy to top with updating global top resumed activity
2393 // and focused application if needed.
2394 stack.adjustFocusToNextFocusableStack("finish-top");
2395 } else {
2396 // Only move the next stack to top in its display.
2397 final ActivityDisplay display = stack.getDisplay();
2398 final ActivityRecord next = display.topRunningActivity();
2399 if (next != null) {
2400 display.positionChildAtTop(next.getActivityStack(),
2401 false /* includingParents */, "finish-display-top");
2402 }
2403 }
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002404 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002405
2406 finishActivityResults(resultCode, resultData);
2407
2408 final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
2409 final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002410 if (isState(RESUMED)) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002411 if (endTask) {
2412 mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
2413 task.getTaskInfo());
2414 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002415 // Prepare app close transition, but don't execute just yet. It is possible that
2416 // an activity that will be made resumed in place of this one will immediately
2417 // launch another new activity. In this case current closing transition will be
2418 // combined with open transition for the new activity.
2419 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
2420 Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
2421 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002422 getDisplay().mDisplayContent.prepareAppTransition(transit, false);
2423
2424 // When finishing the activity preemptively take the snapshot before the app window
2425 // is marked as hidden and any configuration changes take place
2426 if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002427 final ArraySet<Task> tasks = Sets.newArraySet(task);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002428 mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
2429 mAtmService.mWindowManager.mTaskSnapshotController
2430 .addSkipClosingAppSnapshotTasks(tasks);
2431 }
2432
2433 // Tell window manager to prepare for this one to be removed.
2434 setVisibility(false);
2435
2436 if (stack.mPausingActivity == null) {
2437 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + this);
2438 if (DEBUG_USER_LEAVING) {
2439 Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
2440 }
Louis Chang7b03ad92019-08-21 12:32:33 +08002441 stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
2442 null /* resuming */);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002443 }
2444
2445 if (endTask) {
2446 mAtmService.getLockTaskController().clearLockedTask(task);
2447 }
2448 } else if (!isState(PAUSING)) {
Issei Suzuki1669ea42019-11-06 14:20:59 +01002449 if (mVisibleRequested) {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002450 // Prepare and execute close transition.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002451 prepareActivityHideTransitionAnimation(transit);
2452 }
2453
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002454 final boolean removedActivity = completeFinishing("finishIfPossible") == null;
2455 // Performance optimization - only invoke OOM adjustment if the state changed to
2456 // 'STOPPING'. Otherwise it will not change the OOM scores.
2457 if (oomAdj && isState(STOPPING)) {
2458 mAtmService.updateOomAdj();
2459 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002460
2461 // The following code is an optimization. When the last non-task overlay activity
2462 // is removed from the task, we remove the entire task from the stack. However,
2463 // since that is done after the scheduled destroy callback from the activity, that
2464 // call to change the visibility of the task overlay activities would be out of
2465 // sync with the activity visibility being set for this finishing activity above.
2466 // In this case, we can set the visibility of all the task overlay activities when
2467 // we detect the last one is finishing to keep them in sync.
2468 if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002469 for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
2470 final ActivityRecord taskOverlay = task.getChildAt(i);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002471 if (!taskOverlay.mTaskOverlay) {
2472 continue;
2473 }
2474 taskOverlay.prepareActivityHideTransitionAnimation(transit);
2475 }
2476 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002477
Andrii Kulian057a6512019-07-15 16:15:51 -07002478 return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002479 } else {
2480 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
2481 }
2482
Andrii Kulian057a6512019-07-15 16:15:51 -07002483 return FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002484 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +08002485 mAtmService.continueWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002486 }
2487 }
2488
2489 private void prepareActivityHideTransitionAnimation(int transit) {
2490 final DisplayContent dc = getDisplay().mDisplayContent;
2491 dc.prepareAppTransition(transit, false);
2492 setVisibility(false);
2493 dc.executeAppTransition();
2494 }
2495
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002496 /**
2497 * Complete activity finish request that was initiated earlier. If the activity is still
2498 * pausing we will wait for it to complete its transition. If the activity that should appear in
2499 * place of this one is not visible yet - we'll wait for it first. Otherwise - activity can be
2500 * destroyed right away.
2501 * @param reason Reason for finishing the activity.
2502 * @return Flag indicating whether the activity was removed from history.
2503 */
2504 ActivityRecord completeFinishing(String reason) {
2505 if (!finishing || isState(RESUMED)) {
2506 throw new IllegalArgumentException(
2507 "Activity must be finishing and not resumed to complete, r=" + this
2508 + ", finishing=" + finishing + ", state=" + mState);
2509 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002510
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002511 if (isState(PAUSING)) {
2512 // Activity is marked as finishing and will be processed once it completes.
2513 return this;
2514 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002515
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002516 boolean activityRemoved = false;
2517
2518 // If this activity is currently visible, and the resumed activity is not yet visible, then
2519 // hold off on finishing until the resumed one becomes visible.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002520 // The activity that we are finishing may be over the lock screen. In this case, we do not
2521 // want to consider activities that cannot be shown on the lock screen as running and should
2522 // proceed with finishing the activity if there is no valid next top running activity.
2523 // Note that if this finishing activity is floating task, we don't need to wait the
2524 // next activity resume and can destroy it directly.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002525 // TODO(b/137329632): find the next activity directly underneath this one, not just anywhere
2526 final ActivityRecord next = getDisplay().topRunningActivity(
2527 true /* considerKeyguardState */);
Issei Suzuki1669ea42019-11-06 14:20:59 +01002528 final boolean isVisible = mVisibleRequested || nowVisible;
lumark50b81542019-09-01 23:11:49 +08002529 // isNextNotYetVisible is to check if the next activity is invisible, or it has been
2530 // requested to be invisible but its windows haven't reported as invisible. If so, it
2531 // implied that the current finishing activity should be added into stopping list rather
2532 // than destroy immediately.
Issei Suzuki1669ea42019-11-06 14:20:59 +01002533 final boolean isNextNotYetVisible = next != null
2534 && (!next.nowVisible || !next.mVisibleRequested);
lumark50b81542019-09-01 23:11:49 +08002535 if (isVisible && isNextNotYetVisible) {
Andrii Kulian34acc142019-09-24 15:35:50 -07002536 // Add this activity to the list of stopping activities. It will be processed and
2537 // destroyed when the next activity reports idle.
Andrii Kulian79d67982019-08-19 11:56:16 -07002538 addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
2539 "completeFinishing");
Andrii Kulian79d67982019-08-19 11:56:16 -07002540 setState(STOPPING, "completeFinishing");
Andrii Kulian34acc142019-09-24 15:35:50 -07002541 } else if (addToFinishingAndWaitForIdle()) {
2542 // We added this activity to the finishing list and something else is becoming resumed.
2543 // The activity will complete finishing when the next activity reports idle. No need to
2544 // do anything else here.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002545 } else {
Andrii Kulian34acc142019-09-24 15:35:50 -07002546 // Not waiting for the next one to become visible, and nothing else will be resumed in
2547 // place of this activity - requesting destruction right away.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002548 activityRemoved = destroyIfPossible(reason);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002549 }
2550
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002551 return activityRemoved ? null : this;
2552 }
2553
2554 /**
2555 * Destroy and cleanup the activity both on client and server if possible. If activity is the
2556 * last one left on display with home stack and there is no other running activity - delay
2557 * destroying it until the next one starts.
2558 */
2559 boolean destroyIfPossible(String reason) {
2560 setState(FINISHING, "destroyIfPossible");
2561
2562 // Make sure the record is cleaned out of other places.
2563 mStackSupervisor.mStoppingActivities.remove(this);
2564 mStackSupervisor.mGoingToSleepActivities.remove(this);
2565
2566 final ActivityStack stack = getActivityStack();
2567 final ActivityDisplay display = getDisplay();
2568 // TODO(b/137329632): Exclude current activity when looking for the next one with
2569 // ActivityDisplay#topRunningActivity().
2570 final ActivityRecord next = display.topRunningActivity();
2571 final boolean isLastStackOverEmptyHome =
2572 next == null && stack.isFocusedStackOnDisplay() && display.getHomeStack() != null;
2573 if (isLastStackOverEmptyHome) {
2574 // Don't destroy activity immediately if this is the last activity on the display and
2575 // the display contains home stack. Although there is no next activity at the moment,
2576 // another home activity should be started later. Keep this activity alive until next
2577 // home activity is resumed. This way the user won't see a temporary black screen.
2578 addToFinishingAndWaitForIdle();
2579 return false;
2580 }
2581 makeFinishingLocked();
2582
Andrii Kulian79d67982019-08-19 11:56:16 -07002583 final boolean activityRemoved = destroyImmediately(true /* removeFromApp */,
2584 "finish-imm:" + reason);
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002585
2586 // If the display does not have running activity, the configuration may need to be
2587 // updated for restoring original orientation of the display.
2588 if (next == null) {
2589 mRootActivityContainer.ensureVisibilityAndConfig(next, getDisplayId(),
2590 false /* markFrozenIfConfigChanged */, true /* deferResume */);
2591 }
2592 if (activityRemoved) {
2593 mRootActivityContainer.resumeFocusedStacksTopActivities();
2594 }
2595
2596 if (DEBUG_CONTAINERS) {
2597 Slog.d(TAG_CONTAINERS, "destroyIfPossible: r=" + this + " destroy returned removed="
2598 + activityRemoved);
2599 }
2600
2601 return activityRemoved;
2602 }
2603
Andrii Kulian34acc142019-09-24 15:35:50 -07002604 /**
2605 * Add this activity to the list of finishing and trigger resuming of activities in focused
2606 * stacks.
2607 * @return {@code true} if some other activity is being resumed as a result of this call.
2608 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002609 @VisibleForTesting
Andrii Kulian34acc142019-09-24 15:35:50 -07002610 boolean addToFinishingAndWaitForIdle() {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002611 if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
2612 setState(FINISHING, "addToFinishingAndWaitForIdle");
Andrii Kulian34acc142019-09-24 15:35:50 -07002613 if (!mStackSupervisor.mFinishingActivities.contains(this)) {
2614 mStackSupervisor.mFinishingActivities.add(this);
2615 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002616 resumeKeyDispatchingLocked();
Andrii Kulian34acc142019-09-24 15:35:50 -07002617 return mRootActivityContainer.resumeFocusedStacksTopActivities();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002618 }
2619
Andrii Kulian79d67982019-08-19 11:56:16 -07002620 /**
2621 * Destroy the current CLIENT SIDE instance of an activity. This may be called both when
2622 * actually finishing an activity, or when performing a configuration switch where we destroy
2623 * the current client-side object but then create a new client-side object for this same
2624 * HistoryRecord.
2625 * Normally the server-side record will be removed when the client reports back after
2626 * destruction. If, however, at this point there is no client process attached, the record will
Andrii Kulianf49a58c2019-08-14 17:34:27 -07002627 * be removed immediately.
2628 *
2629 * @return {@code true} if activity was immediately removed from history, {@code false}
2630 * otherwise.
Andrii Kulian79d67982019-08-19 11:56:16 -07002631 */
2632 boolean destroyImmediately(boolean removeFromApp, String reason) {
2633 if (DEBUG_SWITCH || DEBUG_CLEANUP) {
2634 Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this
2635 + ", app=" + (hasProcess() ? app.mName : "(null)"));
2636 }
2637
2638 if (isState(DESTROYING, DESTROYED)) {
2639 if (DEBUG_STATES) {
2640 Slog.v(TAG_STATES, "activity " + this + " already destroying."
2641 + "skipping request with reason:" + reason);
2642 }
2643 return false;
2644 }
2645
2646 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, mUserId,
Louis Changcdec0802019-11-11 11:45:07 +08002647 System.identityHashCode(this), task.mTaskId, shortComponentName, reason);
Andrii Kulian79d67982019-08-19 11:56:16 -07002648
Riddle Hsu5477b572019-11-12 16:07:29 +08002649 final ActivityStack stack = getActivityStack();
2650 if (hasProcess() && !stack.inLruList(this)) {
2651 Slog.w(TAG, "Activity " + this + " being finished, but not in LRU list");
2652 }
2653
Andrii Kulian79d67982019-08-19 11:56:16 -07002654 boolean removedFromHistory = false;
2655
2656 cleanUp(false /* cleanServices */, false /* setState */);
2657
Riddle Hsu5477b572019-11-12 16:07:29 +08002658 if (hasProcess()) {
Andrii Kulian79d67982019-08-19 11:56:16 -07002659 if (removeFromApp) {
2660 app.removeActivity(this);
2661 if (!app.hasActivities()) {
2662 mAtmService.clearHeavyWeightProcessIfEquals(app);
2663 // Update any services we are bound to that might care about whether
2664 // their client may have activities.
2665 // No longer have activities, so update LRU list and oom adj.
2666 app.updateProcessInfo(true /* updateServiceConnectionActivities */,
2667 false /* activityChange */, true /* updateOomAdj */);
2668 }
2669 }
2670
2671 boolean skipDestroy = false;
2672
2673 try {
2674 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
2675 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2676 DestroyActivityItem.obtain(finishing, configChangeFlags));
2677 } catch (Exception e) {
2678 // We can just ignore exceptions here... if the process has crashed, our death
2679 // notification will clean things up.
2680 if (finishing) {
2681 removeFromHistory(reason + " exceptionInScheduleDestroy");
2682 removedFromHistory = true;
2683 skipDestroy = true;
2684 }
2685 }
2686
2687 nowVisible = false;
2688
2689 // If the activity is finishing, we need to wait on removing it from the list to give it
2690 // a chance to do its cleanup. During that time it may make calls back with its token
2691 // so we need to be able to find it on the list and so we don't want to remove it from
2692 // the list yet. Otherwise, we can just immediately put it in the destroyed state since
2693 // we are not removing it from the list.
2694 if (finishing && !skipDestroy) {
2695 if (DEBUG_STATES) {
2696 Slog.v(TAG_STATES, "Moving to DESTROYING: " + this + " (destroy requested)");
2697 }
2698 setState(DESTROYING,
2699 "destroyActivityLocked. finishing and not skipping destroy");
2700 stack.scheduleDestroyTimeoutForActivity(this);
2701 } else {
2702 if (DEBUG_STATES) {
2703 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
2704 }
2705 setState(DESTROYED,
2706 "destroyActivityLocked. not finishing or skipping destroy");
2707 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
2708 app = null;
2709 }
2710 } else {
2711 // Remove this record from the history.
2712 if (finishing) {
2713 removeFromHistory(reason + " hadNoApp");
2714 removedFromHistory = true;
2715 } else {
2716 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (no app)");
2717 setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
2718 }
2719 }
2720
2721 configChangeFlags = 0;
2722
Andrii Kulian79d67982019-08-19 11:56:16 -07002723 return removedFromHistory;
2724 }
2725
2726 boolean safelyDestroy(String reason) {
2727 if (isDestroyable()) {
2728 if (DEBUG_SWITCH) {
2729 final ActivityStack stack = getActivityStack();
2730 Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState()
2731 + " resumed=" + stack.mResumedActivity
2732 + " pausing=" + stack.mPausingActivity
2733 + " for reason " + reason);
2734 }
2735 return destroyImmediately(true /* removeFromApp */, reason);
2736 }
2737 return false;
2738 }
2739
2740 /** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
2741 void removeFromHistory(String reason) {
2742 finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
2743 makeFinishingLocked();
2744 if (ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE) {
2745 Slog.i(TAG_ADD_REMOVE, "Removing activity " + this + " from stack callers="
2746 + Debug.getCallers(5));
2747 }
2748
2749 takeFromHistory();
2750 final ActivityStack stack = getActivityStack();
2751 stack.removeTimeoutsForActivity(this);
2752 if (DEBUG_STATES) {
2753 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
2754 }
2755 setState(DESTROYED, "removeFromHistory");
2756 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
2757 app = null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002758 removeAppTokenFromDisplay();
Andrii Kulian79d67982019-08-19 11:56:16 -07002759
2760 cleanUpActivityServices();
2761 removeUriPermissionsLocked();
2762 }
2763
Wale Ogunwale7d701172015-03-11 15:36:30 -07002764 void makeFinishingLocked() {
Wale Ogunwalec981ad52017-06-13 11:40:06 -07002765 if (finishing) {
2766 return;
2767 }
2768 finishing = true;
2769 if (stopped) {
2770 clearOptionsLocked();
2771 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002772 }
2773
Andrii Kulian79d67982019-08-19 11:56:16 -07002774 /**
2775 * This method is to only be called from the client via binder when the activity is destroyed
2776 * AND finished.
2777 */
2778 void destroyed(String reason) {
2779 getActivityStack().removeDestroyTimeoutForActivity(this);
2780
2781 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + this);
2782
2783 if (!isState(DESTROYING, DESTROYED)) {
2784 throw new IllegalStateException(
2785 "Reported destroyed for activity that is not destroying: r=" + this);
2786 }
2787
2788 if (isInStackLocked()) {
2789 cleanUp(true /* cleanServices */, false /* setState */);
2790 removeFromHistory(reason);
2791 }
2792
2793 mRootActivityContainer.resumeFocusedStacksTopActivities();
2794 }
2795
2796 /**
2797 * Perform the common clean-up of an activity record. This is called both as part of
2798 * destroyActivityLocked() (when destroying the client-side representation) and cleaning things
2799 * up as a result of its hosting processing going away, in which case there is no remaining
2800 * client-side state to destroy so only the cleanup here is needed.
2801 *
2802 * Note: Call before {@link #removeFromHistory(String)}.
2803 */
2804 void cleanUp(boolean cleanServices, boolean setState) {
2805 final ActivityStack stack = getActivityStack();
2806 stack.onActivityRemovedFromStack(this);
2807
2808 deferRelaunchUntilPaused = false;
2809 frozenBeforeDestroy = false;
2810
2811 if (setState) {
2812 setState(DESTROYED, "cleanUp");
2813 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this);
2814 app = null;
2815 }
2816
2817 // Inform supervisor the activity has been removed.
2818 mStackSupervisor.cleanupActivity(this);
2819
2820 // Remove any pending results.
2821 if (finishing && pendingResults != null) {
2822 for (WeakReference<PendingIntentRecord> apr : pendingResults) {
2823 PendingIntentRecord rec = apr.get();
2824 if (rec != null) {
2825 mAtmService.mPendingIntentController.cancelIntentSender(rec,
2826 false /* cleanActivity */);
2827 }
2828 }
2829 pendingResults = null;
2830 }
2831
2832 if (cleanServices) {
2833 cleanUpActivityServices();
2834 }
2835
2836 // Get rid of any pending idle timeouts.
2837 stack.removeTimeoutsForActivity(this);
2838 // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
2839 // manager so it can update its bookkeeping.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002840 clearRelaunching();
Andrii Kulian79d67982019-08-19 11:56:16 -07002841 }
2842
Garfield Tane8d84ab2019-10-11 09:49:40 -07002843 boolean isRelaunching() {
2844 return mPendingRelaunchCount > 0;
2845 }
2846
2847 boolean shouldFreezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002848 // For freeform windows, we can't freeze the bounds at the moment because this would make
2849 // the resizing unresponsive.
2850 if (task == null || task.inFreeformWindowingMode()) {
2851 return false;
2852 }
2853
2854 // We freeze the bounds while drag resizing to deal with the time between
2855 // the divider/drag handle being released, and the handling it's new
2856 // configuration. If we are relaunched outside of the drag resizing state,
2857 // we need to be careful not to do this.
Louis Changcdec0802019-11-11 11:45:07 +08002858 return task.isDragResizing();
Garfield Tane8d84ab2019-10-11 09:49:40 -07002859 }
2860
2861 void startRelaunching() {
2862 if (shouldFreezeBounds()) {
2863 freezeBounds();
2864 }
2865
2866 // In the process of tearing down before relaunching, the app will
2867 // try and clean up it's child surfaces. We need to prevent this from
2868 // happening, so we sever the children, transfering their ownership
2869 // from the client it-self to the parent surface (owned by us).
2870 detachChildren();
2871
2872 mPendingRelaunchCount++;
2873 }
2874
2875 /**
2876 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
2877 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
2878 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
2879 * with a queue.
2880 */
2881 private void freezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002882 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
2883
2884 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
2885 // We didn't call prepareFreezingBounds on the task, so use the current value.
2886 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
2887 } else {
2888 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
2889 }
2890 // Calling unset() to make it equal to Configuration.EMPTY.
2891 task.mPreparedFrozenMergedConfig.unset();
2892 }
2893
2894 void detachChildren() {
2895 SurfaceControl.openTransaction();
2896 for (int i = mChildren.size() - 1; i >= 0; i--) {
2897 final WindowState w = mChildren.get(i);
2898 w.mWinAnimator.detachChildren();
2899 }
2900 SurfaceControl.closeTransaction();
2901 }
2902
2903 void finishRelaunching() {
2904 unfreezeBounds();
2905
2906 if (mPendingRelaunchCount > 0) {
2907 mPendingRelaunchCount--;
2908 } else {
2909 // Update keyguard flags upon finishing relaunch.
2910 checkKeyguardFlagsChanged();
2911 }
2912 }
2913
2914 void clearRelaunching() {
2915 if (mPendingRelaunchCount == 0) {
2916 return;
2917 }
2918 unfreezeBounds();
2919 mPendingRelaunchCount = 0;
2920 }
2921
2922 /**
2923 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
2924 */
2925 private void unfreezeBounds() {
2926 if (mFrozenBounds.isEmpty()) {
2927 return;
2928 }
2929 mFrozenBounds.remove();
2930 if (!mFrozenMergedConfig.isEmpty()) {
2931 mFrozenMergedConfig.remove();
2932 }
2933 for (int i = mChildren.size() - 1; i >= 0; i--) {
2934 final WindowState win = mChildren.get(i);
2935 win.onUnfreezeBounds();
2936 }
2937 mWmService.mWindowPlacerLocked.performSurfacePlacement();
2938 }
2939
Andrii Kulian79d67982019-08-19 11:56:16 -07002940 /**
2941 * Perform clean-up of service connections in an activity record.
2942 */
2943 private void cleanUpActivityServices() {
2944 if (mServiceConnectionsHolder == null) {
2945 return;
2946 }
2947 // Throw away any services that have been bound by this activity.
2948 mServiceConnectionsHolder.disconnectActivityFromServices();
2949 }
2950
Garfield Tane8d84ab2019-10-11 09:49:40 -07002951 @Override
2952 void removeImmediately() {
2953 onRemovedFromDisplay();
2954 super.removeImmediately();
2955 }
2956
2957 @Override
2958 void removeIfPossible() {
2959 mIsExiting = false;
2960 removeAllWindowsIfPossible();
2961 removeImmediately();
2962 }
2963
2964 @Override
2965 boolean checkCompleteDeferredRemoval() {
2966 if (mIsExiting) {
2967 removeIfPossible();
2968 }
2969 return super.checkCompleteDeferredRemoval();
2970 }
2971
2972 void onRemovedFromDisplay() {
2973 if (mRemovingFromDisplay) {
2974 return;
2975 }
2976 mRemovingFromDisplay = true;
2977
2978 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
2979
2980 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
2981
2982 getDisplayContent().mOpeningApps.remove(this);
2983 getDisplayContent().mChangingApps.remove(this);
2984 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
2985 mWmService.mTaskSnapshotController.onAppRemoved(this);
2986 waitingToShow = false;
2987 if (getDisplayContent().mClosingApps.contains(this)) {
2988 delayed = true;
2989 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
2990 getDisplayContent().mClosingApps.add(this);
2991 delayed = true;
2992 }
2993
2994 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
2995 "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
lumark9bca6b42019-10-17 18:35:22 +08002996 getAnimation(), isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07002997
2998 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
2999 + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
3000
3001 if (mStartingData != null) {
3002 removeStartingWindow();
3003 }
3004
3005 // If this window was animating, then we need to ensure that the app transition notifies
3006 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
3007 // so add to that list now
lumark9bca6b42019-10-17 18:35:22 +08003008 if (isAnimating(TRANSITION)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003009 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
3010 }
3011
Louis Changdc077272019-11-12 16:52:56 +08003012 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003013 if (delayed && !isEmpty()) {
3014 // set the token aside because it has an active animation to be finished
3015 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3016 "removeAppToken make exiting: %s", this);
3017 if (stack != null) {
3018 stack.mExitingActivities.add(this);
3019 }
3020 mIsExiting = true;
3021 } else {
3022 // Make sure there is no animation running on this token, so any windows associated
3023 // with it will be removed as soon as their animations are complete
3024 cancelAnimation();
3025 if (stack != null) {
3026 stack.mExitingActivities.remove(this);
3027 }
3028 removeIfPossible();
3029 }
3030
Garfield Tane8d84ab2019-10-11 09:49:40 -07003031 stopFreezingScreen(true, true);
3032
3033 final DisplayContent dc = getDisplayContent();
3034 if (dc.mFocusedApp == this) {
3035 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
3036 "Removing focused app token:%s displayId=%d", this,
3037 dc.getDisplayId());
3038 dc.setFocusedApp(null);
3039 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3040 }
3041 if (mLetterbox != null) {
3042 mLetterbox.destroy();
3043 mLetterbox = null;
3044 }
3045
3046 if (!delayed) {
3047 updateReportedVisibilityLocked();
3048 }
3049
3050 // Reset the last saved PiP snap fraction on removal.
3051 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
3052
3053 mRemovingFromDisplay = false;
3054 }
3055
3056 /**
3057 * Returns true if the new child window we are adding to this token is considered greater than
3058 * the existing child window in this token in terms of z-order.
3059 */
3060 @Override
3061 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
3062 WindowState existingWindow) {
3063 final int type1 = newWindow.mAttrs.type;
3064 final int type2 = existingWindow.mAttrs.type;
3065
3066 // Base application windows should be z-ordered BELOW all other windows in the app token.
3067 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
3068 return false;
3069 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
3070 return true;
3071 }
3072
3073 // Starting windows should be z-ordered ABOVE all other windows in the app token.
3074 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
3075 return true;
3076 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
3077 return false;
3078 }
3079
3080 // Otherwise the new window is greater than the existing window.
3081 return true;
3082 }
3083
3084 /**
3085 * @return {@code true} if starting window is in app's hierarchy.
3086 */
3087 boolean hasStartingWindow() {
3088 if (startingDisplayed || mStartingData != null) {
3089 return true;
3090 }
3091 for (int i = mChildren.size() - 1; i >= 0; i--) {
3092 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
3093 return true;
3094 }
3095 }
3096 return false;
3097 }
3098
3099 boolean isLastWindow(WindowState win) {
3100 return mChildren.size() == 1 && mChildren.get(0) == win;
3101 }
3102
3103 @Override
3104 void addWindow(WindowState w) {
3105 super.addWindow(w);
3106
3107 boolean gotReplacementWindow = false;
3108 for (int i = mChildren.size() - 1; i >= 0; i--) {
3109 final WindowState candidate = mChildren.get(i);
3110 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
3111 }
3112
3113 // if we got a replacement window, reset the timeout to give drawing more time
3114 if (gotReplacementWindow) {
3115 mWmService.scheduleWindowReplacementTimeouts(this);
3116 }
3117 checkKeyguardFlagsChanged();
3118 }
3119
3120 @Override
3121 void removeChild(WindowState child) {
3122 if (!mChildren.contains(child)) {
3123 // This can be true when testing.
3124 return;
3125 }
3126 super.removeChild(child);
3127 checkKeyguardFlagsChanged();
3128 updateLetterboxSurface(child);
3129 }
3130
3131 private boolean waitingForReplacement() {
3132 for (int i = mChildren.size() - 1; i >= 0; i--) {
3133 final WindowState candidate = mChildren.get(i);
3134 if (candidate.waitingForReplacement()) {
3135 return true;
3136 }
3137 }
3138 return false;
3139 }
3140
3141 void onWindowReplacementTimeout() {
3142 for (int i = mChildren.size() - 1; i >= 0; --i) {
3143 (mChildren.get(i)).onWindowReplacementTimeout();
3144 }
3145 }
3146
3147 void setAppLayoutChanges(int changes, String reason) {
3148 if (!mChildren.isEmpty()) {
3149 final DisplayContent dc = getDisplayContent();
3150 dc.pendingLayoutChanges |= changes;
3151 if (DEBUG_LAYOUT_REPEATS) {
3152 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
3153 }
3154 }
3155 }
3156
3157 void removeReplacedWindowIfNeeded(WindowState replacement) {
3158 for (int i = mChildren.size() - 1; i >= 0; i--) {
3159 final WindowState win = mChildren.get(i);
3160 if (win.removeReplacedWindowIfNeeded(replacement)) {
3161 return;
3162 }
3163 }
3164 }
3165
3166 boolean transferStartingWindow(IBinder transferFrom) {
3167 final ActivityRecord fromActivity = getDisplayContent().getActivityRecord(transferFrom);
3168 if (fromActivity == null) {
3169 return false;
3170 }
3171
3172 final WindowState tStartingWindow = fromActivity.startingWindow;
3173 if (tStartingWindow != null && fromActivity.startingSurface != null) {
3174 // In this case, the starting icon has already been displayed, so start
3175 // letting windows get shown immediately without any more transitions.
3176 getDisplayContent().mSkipAppTransitionAnimation = true;
3177
3178 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
3179 + " from %s to %s", tStartingWindow, fromActivity, this);
3180
3181 final long origId = Binder.clearCallingIdentity();
3182 try {
3183 // Transfer the starting window over to the new token.
3184 mStartingData = fromActivity.mStartingData;
3185 startingSurface = fromActivity.startingSurface;
3186 startingDisplayed = fromActivity.startingDisplayed;
3187 fromActivity.startingDisplayed = false;
3188 startingWindow = tStartingWindow;
3189 reportedVisible = fromActivity.reportedVisible;
3190 fromActivity.mStartingData = null;
3191 fromActivity.startingSurface = null;
3192 fromActivity.startingWindow = null;
3193 fromActivity.startingMoved = true;
3194 tStartingWindow.mToken = this;
3195 tStartingWindow.mActivityRecord = this;
3196
3197 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3198 "Removing starting %s from %s", tStartingWindow, fromActivity);
3199 fromActivity.removeChild(tStartingWindow);
3200 fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003201 fromActivity.mHiddenSetFromTransferredStartingWindow = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003202 addWindow(tStartingWindow);
3203
3204 // Propagate other interesting state between the tokens. If the old token is displayed,
3205 // we should immediately force the new one to be displayed. If it is animating, we need
3206 // to move that animation to the new one.
3207 if (fromActivity.allDrawn) {
3208 allDrawn = true;
3209 deferClearAllDrawn = fromActivity.deferClearAllDrawn;
3210 }
3211 if (fromActivity.firstWindowDrawn) {
3212 firstWindowDrawn = true;
3213 }
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003214 if (!fromActivity.isHidden()) {
3215 setHidden(false);
Issei Suzuki1669ea42019-11-06 14:20:59 +01003216 mVisibleRequested = true;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003217 mHiddenSetFromTransferredStartingWindow = true;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003218 }
Issei Suzukie63eac72019-11-14 15:59:15 +01003219 setClientHidden(fromActivity.mClientHidden);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003220
3221 transferAnimation(fromActivity);
3222
3223 // When transferring an animation, we no longer need to apply an animation to the
3224 // the token we transfer the animation over. Thus, set this flag to indicate we've
3225 // transferred the animation.
3226 mUseTransferredAnimation = true;
3227
3228 mWmService.updateFocusedWindowLocked(
3229 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
3230 getDisplayContent().setLayoutNeeded();
3231 mWmService.mWindowPlacerLocked.performSurfacePlacement();
3232 } finally {
3233 Binder.restoreCallingIdentity(origId);
3234 }
3235 return true;
3236 } else if (fromActivity.mStartingData != null) {
3237 // The previous app was getting ready to show a
3238 // starting window, but hasn't yet done so. Steal it!
3239 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
3240 "Moving pending starting from %s to %s", fromActivity, this);
3241 mStartingData = fromActivity.mStartingData;
3242 fromActivity.mStartingData = null;
3243 fromActivity.startingMoved = true;
3244 scheduleAddStartingWindow();
3245 return true;
3246 }
3247
3248 // TODO: Transfer thumbnail
3249
3250 return false;
3251 }
3252
3253 /**
3254 * Tries to transfer the starting window from a token that's above ourselves in the task but
3255 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
3256 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
3257 * immediately finishes after, so we have to transfer T to M.
3258 */
3259 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003260 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
3261 final ActivityRecord fromActivity = task.mChildren.get(i);
3262 if (fromActivity == this) {
3263 return;
3264 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01003265 if (!fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003266 return;
3267 }
3268 }
3269 }
3270
3271 void checkKeyguardFlagsChanged() {
3272 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
3273 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
3274 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
3275 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
3276 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
3277 getDisplayContent().getDisplayId());
3278 }
3279 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
3280 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
3281 }
3282
3283 boolean containsDismissKeyguardWindow() {
3284 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
3285 // entirety of the relaunch.
3286 if (isRelaunching()) {
3287 return mLastContainsDismissKeyguardWindow;
3288 }
3289
3290 for (int i = mChildren.size() - 1; i >= 0; i--) {
3291 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
3292 return true;
3293 }
3294 }
3295 return false;
3296 }
3297
3298 boolean containsShowWhenLockedWindow() {
3299 // When we are relaunching, it is possible for us to be unfrozen before our previous
3300 // windows have been added back. Using the cached value ensures that our previous
3301 // showWhenLocked preference is honored until relaunching is complete.
3302 if (isRelaunching()) {
3303 return mLastContainsShowWhenLockedWindow;
3304 }
3305
3306 for (int i = mChildren.size() - 1; i >= 0; i--) {
3307 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
3308 return true;
3309 }
3310 }
3311
3312 return false;
3313 }
3314
3315 void setShowWhenLocked(boolean showWhenLocked) {
3316 mShowWhenLocked = showWhenLocked;
3317 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
3318 0 /* configChanges */, false /* preserveWindows */);
3319 }
3320
3321 void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
3322 mInheritShownWhenLocked = inheritShowWhenLocked;
3323 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
3324 0 /* configChanges */, false /* preserveWindows */);
3325 }
3326
3327 /**
3328 * @return {@code true} if the activity windowing mode is not
3329 * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
3330 * contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
3331 * activity has set {@link #mShowWhenLocked}, or b) if the activity has set
3332 * {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
3333 * conditions a) above.
3334 * Multi-windowing mode will be exited if {@code true} is returned.
3335 */
3336 boolean canShowWhenLocked() {
3337 if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
3338 return true;
3339 } else if (mInheritShownWhenLocked) {
3340 final ActivityRecord r = getActivityBelow();
3341 return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
3342 || r.containsShowWhenLockedWindow());
3343 } else {
3344 return false;
3345 }
3346 }
3347
3348 /**
3349 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3350 * showing windows during transitions in case we have windows that have wide-color-gamut
3351 * color mode set to avoid jank in the middle of the transition.
3352 */
3353 boolean canShowWindows() {
lumark9bca6b42019-10-17 18:35:22 +08003354 return allDrawn && !(isAnimating() && hasNonDefaultColorWindow());
Garfield Tane8d84ab2019-10-11 09:49:40 -07003355 }
3356
3357 /**
3358 * @return true if we have a window that has a non-default color mode set; false otherwise.
3359 */
3360 private boolean hasNonDefaultColorWindow() {
3361 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3362 true /* topToBottom */);
3363 }
3364
3365 /**
3366 * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
3367 * such activity exists.
3368 */
3369 @Nullable
3370 private ActivityRecord getActivityBelow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003371 final int pos = task.mChildren.indexOf(this);
3372 if (pos == -1) {
3373 throw new IllegalStateException("Activity not found in its task");
3374 }
3375 return pos == 0 ? null : task.getChildAt(pos - 1);
3376 }
3377
3378 WindowState getImeTargetBelowWindow(WindowState w) {
3379 final int index = mChildren.indexOf(w);
3380 if (index > 0) {
3381 final WindowState target = mChildren.get(index - 1);
3382 if (target.canBeImeTarget()) {
3383 return target;
3384 }
3385 }
3386 return null;
3387 }
3388
3389 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
3390 WindowState candidate = null;
3391 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
3392 final WindowState w = mChildren.get(i);
3393 if (w.mRemoved) {
3394 continue;
3395 }
3396 if (candidate == null) {
3397 candidate = w;
3398 }
3399 }
3400 return candidate;
3401 }
3402
3403 @Override
3404 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
3405 // For legacy reasons we process the TaskStack.mExitingActivities first in DisplayContent
3406 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
3407 // TODO: Investigate if we need to continue to do this or if we can just process them
3408 // in-order.
3409 if (mIsExiting && !waitingForReplacement()) {
3410 return false;
3411 }
3412 return forAllWindowsUnchecked(callback, traverseTopToBottom);
3413 }
3414
Garfield Tane8d84ab2019-10-11 09:49:40 -07003415 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
3416 boolean traverseTopToBottom) {
3417 return super.forAllWindows(callback, traverseTopToBottom);
3418 }
3419
3420 @Override
lumark9bca6b42019-10-17 18:35:22 +08003421 boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
3422 return callback.apply(this);
3423 }
3424
3425 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07003426 protected void setLayer(Transaction t, int layer) {
3427 if (!mSurfaceAnimator.hasLeash()) {
3428 t.setLayer(mSurfaceControl, layer);
3429 }
3430 }
3431
3432 @Override
3433 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
3434 if (!mSurfaceAnimator.hasLeash()) {
3435 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
3436 }
3437 }
3438
3439 @Override
3440 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
3441 if (!mSurfaceAnimator.hasLeash()) {
3442 t.reparent(mSurfaceControl, newParent);
3443 }
3444 }
3445
Louis Changcdec0802019-11-11 11:45:07 +08003446 void logStartActivity(int tag, Task task) {
Andrii Kulian79d67982019-08-19 11:56:16 -07003447 final Uri data = intent.getData();
3448 final String strData = data != null ? data.toSafeString() : null;
3449
3450 EventLog.writeEvent(tag,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07003451 mUserId, System.identityHashCode(this), task.mTaskId,
Andrii Kulian79d67982019-08-19 11:56:16 -07003452 shortComponentName, intent.getAction(),
3453 intent.getType(), strData, intent.getFlags());
3454 }
3455
Dianne Hackborn7e269642010-08-25 19:50:20 -07003456 UriPermissionOwner getUriPermissionsLocked() {
3457 if (uriPermissions == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003458 uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
Dianne Hackborn7e269642010-08-25 19:50:20 -07003459 }
3460 return uriPermissions;
3461 }
3462
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003463 void addResultLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 int requestCode, int resultCode,
3465 Intent resultData) {
3466 ActivityResult r = new ActivityResult(from, resultWho,
John Spurlock8a985d22014-02-25 09:40:05 -05003467 requestCode, resultCode, resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 if (results == null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003469 results = new ArrayList<ResultInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 }
3471 results.add(r);
3472 }
3473
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003474 void removeResultsLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 int requestCode) {
3476 if (results != null) {
3477 for (int i=results.size()-1; i>=0; i--) {
3478 ActivityResult r = (ActivityResult)results.get(i);
3479 if (r.mFrom != from) continue;
3480 if (r.mResultWho == null) {
3481 if (resultWho != null) continue;
3482 } else {
3483 if (!r.mResultWho.equals(resultWho)) continue;
3484 }
3485 if (r.mRequestCode != requestCode) continue;
3486
3487 results.remove(i);
3488 }
3489 }
3490 }
3491
Andrii Kulian79d67982019-08-19 11:56:16 -07003492 void sendResult(int callingUid, String resultWho, int requestCode, int resultCode,
3493 Intent data) {
3494 if (callingUid > 0) {
3495 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3496 data, getUriPermissionsLocked(), mUserId);
3497 }
3498
3499 if (DEBUG_RESULTS) {
3500 Slog.v(TAG, "Send activity result to " + this
3501 + " : who=" + resultWho + " req=" + requestCode
3502 + " res=" + resultCode + " data=" + data);
3503 }
3504 if (isState(RESUMED) && attachedToProcess()) {
3505 try {
3506 final ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3507 list.add(new ResultInfo(resultWho, requestCode, resultCode, data));
3508 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3509 ActivityResultItem.obtain(list));
3510 return;
3511 } catch (Exception e) {
3512 Slog.w(TAG, "Exception thrown sending result to " + this, e);
3513 }
3514 }
3515
3516 addResultLocked(null /* from */, resultWho, requestCode, resultCode, data);
3517 }
3518
Andrii Kulian21713ac2016-10-12 22:05:05 -07003519 private void addNewIntentLocked(ReferrerIntent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 if (newIntents == null) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003521 newIntents = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 }
3523 newIntents.add(intent);
3524 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07003525
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003526 final boolean isSleeping() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003527 final ActivityStack stack = getActivityStack();
3528 return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003529 }
3530
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003531 /**
3532 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3533 * method will be called at the proper time.
3534 */
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003535 final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
Dianne Hackborn514074f2013-02-11 10:52:46 -08003536 // The activity now gets access to the data associated with this Intent.
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003537 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3538 intent, getUriPermissionsLocked(), mUserId);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003539 final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
Craig Mautner86d67a42013-05-14 10:34:38 -07003540 boolean unsent = true;
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003541 final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
Wale Ogunwale826c7062016-09-13 08:25:54 -07003542
3543 // We want to immediately deliver the intent to the activity if:
Wale Ogunwale03f7e9e2016-09-22 09:04:09 -07003544 // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
3545 // the user to see the visual effects caused by the intent delivery now.
Wale Ogunwale826c7062016-09-13 08:25:54 -07003546 // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07003547 if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
3548 && attachedToProcess()) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003549 try {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003550 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
3551 ar.add(rintent);
Louis Changea203cd2019-07-01 12:39:31 +08003552 // Making sure the client state is RESUMED after transaction completed and doing
3553 // so only if activity is currently RESUMED. Otherwise, client may have extra
3554 // life-cycle calls to RESUMED (and PAUSED later).
Louis Chang92d16522019-02-27 12:56:18 +08003555 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Louis Changea203cd2019-07-01 12:39:31 +08003556 NewIntentItem.obtain(ar, mState == RESUMED));
Craig Mautner86d67a42013-05-14 10:34:38 -07003557 unsent = false;
Dianne Hackborn39792d22010-08-19 18:01:52 -07003558 } catch (RemoteException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003559 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003560 } catch (NullPointerException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003561 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003562 }
3563 }
Craig Mautner86d67a42013-05-14 10:34:38 -07003564 if (unsent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003565 addNewIntentLocked(rintent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003566 }
3567 }
3568
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003569 void updateOptionsLocked(ActivityOptions options) {
3570 if (options != null) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003571 if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003572 if (pendingOptions != null) {
3573 pendingOptions.abort();
3574 }
3575 pendingOptions = options;
3576 }
3577 }
3578
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003579 void applyOptionsLocked() {
George Mount2c92c972014-03-20 09:38:23 -07003580 if (pendingOptions != null
Ruben Brunkf53497c2017-03-27 20:26:17 -07003581 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003582 if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003583 applyOptionsLocked(pendingOptions, intent);
chaviw82a0ba82018-03-15 14:26:29 -07003584 if (task == null) {
3585 clearOptionsLocked(false /* withAbort */);
3586 } else {
3587 // This will clear the options for all the ActivityRecords for this Task.
3588 task.clearAllPendingOptions();
3589 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003590 }
3591 }
3592
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003593 /**
3594 * Apply override app transition base on options & animation type.
3595 */
3596 void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
3597 final int animationType = pendingOptions.getAnimationType();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003598 final DisplayContent displayContent = getDisplayContent();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003599 switch (animationType) {
3600 case ANIM_CUSTOM:
3601 displayContent.mAppTransition.overridePendingAppTransition(
3602 pendingOptions.getPackageName(),
3603 pendingOptions.getCustomEnterResId(),
3604 pendingOptions.getCustomExitResId(),
3605 pendingOptions.getOnAnimationStartListener());
3606 break;
3607 case ANIM_CLIP_REVEAL:
3608 displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
3609 pendingOptions.getStartX(), pendingOptions.getStartY(),
3610 pendingOptions.getWidth(), pendingOptions.getHeight());
3611 if (intent.getSourceBounds() == null) {
3612 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3613 pendingOptions.getStartY(),
3614 pendingOptions.getStartX() + pendingOptions.getWidth(),
3615 pendingOptions.getStartY() + pendingOptions.getHeight()));
3616 }
3617 break;
3618 case ANIM_SCALE_UP:
3619 displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
3620 pendingOptions.getStartX(), pendingOptions.getStartY(),
3621 pendingOptions.getWidth(), pendingOptions.getHeight());
3622 if (intent.getSourceBounds() == null) {
3623 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3624 pendingOptions.getStartY(),
3625 pendingOptions.getStartX() + pendingOptions.getWidth(),
3626 pendingOptions.getStartY() + pendingOptions.getHeight()));
3627 }
3628 break;
3629 case ANIM_THUMBNAIL_SCALE_UP:
3630 case ANIM_THUMBNAIL_SCALE_DOWN:
3631 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
3632 final GraphicBuffer buffer = pendingOptions.getThumbnail();
3633 displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
3634 pendingOptions.getStartX(), pendingOptions.getStartY(),
3635 pendingOptions.getOnAnimationStartListener(),
3636 scaleUp);
3637 if (intent.getSourceBounds() == null && buffer != null) {
3638 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3639 pendingOptions.getStartY(),
3640 pendingOptions.getStartX() + buffer.getWidth(),
3641 pendingOptions.getStartY() + buffer.getHeight()));
3642 }
3643 break;
3644 case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
3645 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
3646 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
3647 final IAppTransitionAnimationSpecsFuture specsFuture =
3648 pendingOptions.getSpecsFuture();
3649 if (specsFuture != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003650 displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
3651 specsFuture, pendingOptions.getOnAnimationStartListener(),
3652 animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
3653 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
3654 && specs != null) {
3655 displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
3656 specs, pendingOptions.getOnAnimationStartListener(),
3657 pendingOptions.getAnimationFinishedListener(), false);
3658 } else {
3659 displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
3660 pendingOptions.getThumbnail(),
3661 pendingOptions.getStartX(), pendingOptions.getStartY(),
3662 pendingOptions.getWidth(), pendingOptions.getHeight(),
3663 pendingOptions.getOnAnimationStartListener(),
3664 (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
3665 if (intent.getSourceBounds() == null) {
3666 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3667 pendingOptions.getStartY(),
3668 pendingOptions.getStartX() + pendingOptions.getWidth(),
3669 pendingOptions.getStartY() + pendingOptions.getHeight()));
3670 }
3671 }
3672 break;
3673 case ANIM_OPEN_CROSS_PROFILE_APPS:
3674 displayContent.mAppTransition
3675 .overridePendingAppTransitionStartCrossProfileApps();
3676 break;
3677 case ANIM_REMOTE_ANIMATION:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003678 displayContent.mAppTransition.overridePendingAppTransitionRemote(
3679 pendingOptions.getRemoteAnimationAdapter());
3680 break;
3681 case ANIM_NONE:
Louis Chang477e93e2019-04-24 18:35:20 +08003682 case ANIM_UNDEFINED:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003683 break;
3684 default:
3685 Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
3686 break;
3687 }
3688 }
3689
Garfield Tane8d84ab2019-10-11 09:49:40 -07003690 void clearAllDrawn() {
3691 allDrawn = false;
3692 deferClearAllDrawn = false;
3693 }
3694
3695 /**
3696 * Returns whether the drawn window states of this {@link ActivityRecord} has considered every
3697 * child {@link WindowState}. A child is considered if it has been passed into
3698 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
3699 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
3700 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
3701 *
3702 * @return {@code true} If all children have been considered, {@code false}.
3703 */
3704 private boolean allDrawnStatesConsidered() {
3705 for (int i = mChildren.size() - 1; i >= 0; --i) {
3706 final WindowState child = mChildren.get(i);
3707 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
3708 return false;
3709 }
3710 }
3711 return true;
3712 }
3713
3714 /**
3715 * Determines if the token has finished drawing. This should only be called from
3716 * {@link DisplayContent#applySurfaceChangesTransaction}
3717 */
3718 void updateAllDrawn() {
3719 if (!allDrawn) {
3720 // Number of drawn windows can be less when a window is being relaunched, wait for
3721 // all windows to be launched and drawn for this token be considered all drawn.
3722 final int numInteresting = mNumInterestingWindows;
3723
3724 // We must make sure that all present children have been considered (determined by
3725 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
3726 // drawn.
3727 if (numInteresting > 0 && allDrawnStatesConsidered()
3728 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
3729 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
3730 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
3731 allDrawn = true;
3732 // Force an additional layout pass where
3733 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
3734 if (mDisplayContent != null) {
3735 mDisplayContent.setLayoutNeeded();
3736 }
3737 mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
3738
3739 // Notify the pinned stack upon all windows drawn. If there was an animation in
3740 // progress then this signal will resume that animation.
Louis Changdc077272019-11-12 16:52:56 +08003741 final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003742 if (pinnedStack != null) {
3743 pinnedStack.onAllWindowsDrawn();
3744 }
3745 }
3746 }
3747 }
3748
Adam Powellcfbe9be2013-11-06 14:58:58 -08003749 ActivityOptions getOptionsForTargetActivityLocked() {
3750 return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
3751 }
3752
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003753 void clearOptionsLocked() {
chaviw82a0ba82018-03-15 14:26:29 -07003754 clearOptionsLocked(true /* withAbort */);
3755 }
3756
3757 void clearOptionsLocked(boolean withAbort) {
3758 if (withAbort && pendingOptions != null) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003759 pendingOptions.abort();
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003760 }
chaviw82a0ba82018-03-15 14:26:29 -07003761 pendingOptions = null;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003762 }
3763
Jorim Jaggi346702a2019-05-08 17:49:33 +02003764 ActivityOptions takeOptionsLocked(boolean fromClient) {
3765 if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
3766 + Debug.getCallers(6));
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003767 ActivityOptions opts = pendingOptions;
Jorim Jaggi346702a2019-05-08 17:49:33 +02003768
3769 // If we are trying to take activity options from the client, do not null it out if it's a
3770 // remote animation as the client doesn't need it ever. This is a workaround when client is
3771 // faster to take the options than we are to resume the next activity.
3772 // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
3773 // timing somehow
3774 if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
3775 pendingOptions = null;
3776 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003777 return opts;
3778 }
3779
Issei Suzuki1669ea42019-11-06 14:20:59 +01003780 boolean allowMoveToFront() {
3781 return pendingOptions == null || !pendingOptions.getAvoidMoveToFront();
3782 }
3783
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003784 void removeUriPermissionsLocked() {
Dianne Hackborn7e269642010-08-25 19:50:20 -07003785 if (uriPermissions != null) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003786 uriPermissions.removeUriPermissions();
Dianne Hackborn7e269642010-08-25 19:50:20 -07003787 uriPermissions = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003788 }
3789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790
3791 void pauseKeyDispatchingLocked() {
3792 if (!keysPaused) {
3793 keysPaused = true;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003794
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003795 if (getDisplayContent() != null) {
3796 getDisplayContent().getInputMonitor().pauseDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 }
3799 }
3800
3801 void resumeKeyDispatchingLocked() {
3802 if (keysPaused) {
3803 keysPaused = false;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003804
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003805 if (getDisplayContent() != null) {
3806 getDisplayContent().getInputMonitor().resumeDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 }
3809 }
3810
Jorim Jaggie7d2b852017-08-28 17:55:15 +02003811 private void updateTaskDescription(CharSequence description) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07003812 task.lastDescription = description;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003813 }
3814
Wale Ogunwaleec950642017-04-25 07:44:21 -07003815 void setDeferHidingClient(boolean deferHidingClient) {
3816 if (mDeferHidingClient == deferHidingClient) {
3817 return;
3818 }
3819 mDeferHidingClient = deferHidingClient;
Issei Suzuki1669ea42019-11-06 14:20:59 +01003820 if (!mDeferHidingClient && !mVisibleRequested) {
Wale Ogunwaleec950642017-04-25 07:44:21 -07003821 // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
3822 // update the visibility.
3823 setVisibility(false);
3824 }
Wale Ogunwale89973222017-04-23 18:39:45 -07003825 }
3826
Garfield Tane8d84ab2019-10-11 09:49:40 -07003827 @Override
3828 boolean isVisible() {
3829 // If the activity isn't hidden then it is considered visible and there is no need to check
3830 // its children windows to see if they are visible.
Issei Suzuki7b9e2572019-11-14 16:19:54 +01003831 return !isHidden();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003832 }
3833
Wale Ogunwaleec950642017-04-25 07:44:21 -07003834 void setVisibility(boolean visible) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003835 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003836 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
3837 + appToken);
3838 return;
3839 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01003840 if (visible) {
3841 mDeferHidingClient = false;
3842 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003843 setVisibility(visible, mDeferHidingClient);
Riddle Hsua0022cd2019-09-09 21:12:41 +08003844 mAtmService.addWindowLayoutReasons(
3845 ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
Bryce Lee2a3cc462017-10-27 10:57:35 -07003846 mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07003847 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
3848 }
3849
Issei Suzuki1669ea42019-11-06 14:20:59 +01003850 @VisibleForTesting
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 Suzuki1669ea42019-11-06 14:20:59 +01003861 if (!visible && !mVisibleRequested) {
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 Suzuki1669ea42019-11-06 14:20:59 +01003873 "setAppVisibility(%s, visible=%b): %s hidden=%b mVisibleRequested=%b Callers=%s",
3874 appToken, visible, appTransition, isHidden(), mVisibleRequested,
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 Suzuki1669ea42019-11-06 14:20:59 +01003885 mVisibleRequested = 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 Suzuki1669ea42019-11-06 14:20:59 +01004024 mVisibleRequested = 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 Suzuki1669ea42019-11-06 14:20:59 +01004042 "commitVisibility: %s: hidden=%b visibleRequested=%b", this,
4043 isHidden(), mVisibleRequested);
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 Suzuki1669ea42019-11-06 14:20:59 +01004383 setVisibility(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 Suzuki1669ea42019-11-06 14:20:59 +01004419 if (!mVisibleRequested) {
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 Suzuki1669ea42019-11-06 14:20:59 +01004441 setVisibility(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 Suzuki1669ea42019-11-06 14:20:59 +01004628 final boolean wasVisible = mVisibleRequested;
4629 setVisibility(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 Suzuki1669ea42019-11-06 14:20:59 +01004713 Slog.v(TAG_VISIBILITY, "Stopping visibleRequested="
4714 + mVisibleRequested + " for " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07004715 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01004716 if (!mVisibleRequested) {
4717 setVisibility(false);
Andrii Kulian79d67982019-08-19 11:56:16 -07004718 }
4719 EventLogTags.writeAmStopActivity(
4720 mUserId, System.identityHashCode(this), shortComponentName);
4721 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Issei Suzuki1669ea42019-11-06 14:20:59 +01004722 StopActivityItem.obtain(mVisibleRequested, configChangeFlags));
Andrii Kulian79d67982019-08-19 11:56:16 -07004723 if (stack.shouldSleepOrShutDownActivities()) {
4724 setSleeping(true);
4725 }
4726 stack.scheduleStopTimeoutForActivity(this);
4727 } catch (Exception e) {
4728 // Maybe just ignore exceptions here... if the process has crashed, our death
4729 // notification will clean things up.
4730 Slog.w(TAG, "Exception thrown during pause", e);
4731 // Just in case, assume it to be stopped.
4732 stopped = true;
4733 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + this);
4734 setState(STOPPED, "stopIfPossible");
4735 if (deferRelaunchUntilPaused) {
4736 destroyImmediately(true /* removeFromApp */, "stop-except");
4737 }
4738 }
4739 }
4740
Andrii Kulian21713ac2016-10-12 22:05:05 -07004741 final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
4742 CharSequence description) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004743 final ActivityStack stack = getActivityStack();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004744 final boolean isStopping = mState == STOPPING;
4745 if (!isStopping && mState != RESTARTING_PROCESS) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004746 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07004747 stack.removeStopTimeoutForActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004748 return;
4749 }
4750 if (newPersistentState != null) {
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004751 mPersistentState = newPersistentState;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004752 mAtmService.notifyTaskPersisterLocked(task, false);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004753 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08004754
Andrii Kulian21713ac2016-10-12 22:05:05 -07004755 if (newIcicle != null) {
4756 // If icicle is null, this is happening due to a timeout, so we haven't really saved
4757 // the state.
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004758 setSavedState(newIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004759 launchCount = 0;
Jorim Jaggie7d2b852017-08-28 17:55:15 +02004760 updateTaskDescription(description);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004761 }
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004762 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004763 if (!stopped) {
4764 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
Andrii Kulian79d67982019-08-19 11:56:16 -07004765 stack.removeStopTimeoutForActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004766 stopped = true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004767 if (isStopping) {
4768 setState(STOPPED, "activityStoppedLocked");
4769 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004770
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004771 notifyAppStopped();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004772
Andrii Kulian21713ac2016-10-12 22:05:05 -07004773 if (finishing) {
4774 clearOptionsLocked();
4775 } else {
4776 if (deferRelaunchUntilPaused) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004777 destroyImmediately(true /* removeFromApp */, "stop-config");
Wale Ogunwaled32da472018-11-16 07:19:28 -08004778 mRootActivityContainer.resumeFocusedStacksTopActivities();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004779 } else {
Wale Ogunwaled32da472018-11-16 07:19:28 -08004780 mRootActivityContainer.updatePreviousProcess(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004781 }
4782 }
4783 }
4784 }
4785
Andrii Kulian79d67982019-08-19 11:56:16 -07004786 void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
4787 if (!mStackSupervisor.mStoppingActivities.contains(this)) {
4788 EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, mUserId,
4789 System.identityHashCode(this), shortComponentName, reason);
4790 mStackSupervisor.mStoppingActivities.add(this);
4791 }
4792
4793 final ActivityStack stack = getActivityStack();
4794 // If we already have a few activities waiting to stop, then give up on things going idle
4795 // and start clearing them out. Or if r is the last of activity of the last task the stack
4796 // will be empty and must be cleared immediately.
4797 boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
4798 || (isRootOfTask() && stack.getChildCount() <= 1);
4799 if (scheduleIdle || forceIdle) {
4800 if (DEBUG_PAUSE) {
4801 Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" + forceIdle
4802 + "immediate=" + !idleDelayed);
4803 }
4804 if (!idleDelayed) {
4805 mStackSupervisor.scheduleIdleLocked();
4806 } else {
4807 mStackSupervisor.scheduleIdleTimeoutLocked(this);
4808 }
4809 } else {
4810 stack.checkReadyForSleep();
4811 }
4812 }
4813
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004814 void startLaunchTickingLocked() {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06004815 if (Build.IS_USER) {
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004816 return;
4817 }
4818 if (launchTickTime == 0) {
4819 launchTickTime = SystemClock.uptimeMillis();
4820 continueLaunchTickingLocked();
4821 }
4822 }
4823
4824 boolean continueLaunchTickingLocked() {
Wale Ogunwale7d701172015-03-11 15:36:30 -07004825 if (launchTickTime == 0) {
4826 return false;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004827 }
Wale Ogunwale7d701172015-03-11 15:36:30 -07004828
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004829 final ActivityStack stack = getActivityStack();
Wale Ogunwale7d701172015-03-11 15:36:30 -07004830 if (stack == null) {
4831 return false;
4832 }
4833
Andrii Kulian79d67982019-08-19 11:56:16 -07004834 stack.removeLaunchTickMessages();
4835 stack.scheduleLaunchTickForActivity(this);
Wale Ogunwale7d701172015-03-11 15:36:30 -07004836 return true;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004837 }
4838
4839 void finishLaunchTickingLocked() {
4840 launchTickTime = 0;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08004841 final ActivityStack stack = getActivityStack();
Andrii Kulian79d67982019-08-19 11:56:16 -07004842 if (stack == null) {
4843 return;
Wale Ogunwale7d701172015-03-11 15:36:30 -07004844 }
Andrii Kulian79d67982019-08-19 11:56:16 -07004845 stack.removeLaunchTickMessages();
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004846 }
4847
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004848 boolean mayFreezeScreenLocked() {
4849 return mayFreezeScreenLocked(app);
4850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004852 private boolean mayFreezeScreenLocked(WindowProcessController app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 // Only freeze the screen if this activity is currently attached to
4854 // an application, and that application is not blocked or unresponding.
4855 // In any other case, we can't count on getting the screen unfrozen,
4856 // so it is best to leave as-is.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004857 return hasProcess() && !app.isCrashing() && !app.isNotResponding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07004859
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004860 void startFreezingScreenLocked(int configChanges) {
4861 startFreezingScreenLocked(app, configChanges);
4862 }
4863
4864 void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 if (mayFreezeScreenLocked(app)) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004866 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004867 Slog.w(TAG_WM,
4868 "Attempted to freeze screen with non-existing app token: " + appToken);
4869 return;
4870 }
4871
Evan Roskyb1e75f72019-04-26 20:23:26 -07004872 // Window configuration changes only effect windows, so don't require a screen freeze.
4873 int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004874 if (freezableConfigChanges == 0 && okToDisplay()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02004875 ProtoLog.v(WM_DEBUG_ORIENTATION, "Skipping set freeze of %s", appToken);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004876 return;
4877 }
4878
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004879 startFreezingScreen();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 }
4881 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07004882
Garfield Tane8d84ab2019-10-11 09:49:40 -07004883 void startFreezingScreen() {
4884 ProtoLog.i(WM_DEBUG_ORIENTATION,
Issei Suzuki1669ea42019-11-06 14:20:59 +01004885 "Set freezing of %s: hidden=%b freezing=%b visibleRequested=%b. %s",
4886 appToken, isHidden(), mFreezingScreen, mVisibleRequested,
Garfield Tane8d84ab2019-10-11 09:49:40 -07004887 new RuntimeException().fillInStackTrace());
Issei Suzuki1669ea42019-11-06 14:20:59 +01004888 if (mVisibleRequested) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004889 if (!mFreezingScreen) {
4890 mFreezingScreen = true;
4891 mWmService.registerAppFreezeListener(this);
4892 mWmService.mAppsFreezingScreen++;
4893 if (mWmService.mAppsFreezingScreen == 1) {
4894 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
4895 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4896 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
4897 }
4898 }
4899 final int count = mChildren.size();
4900 for (int i = 0; i < count; i++) {
4901 final WindowState w = mChildren.get(i);
4902 w.onStartFreezingScreen();
4903 }
4904 }
4905 }
4906
4907 boolean isFreezingScreen() {
4908 return mFreezingScreen;
4909 }
4910
4911 @Override
4912 public void onAppFreezeTimeout() {
4913 Slog.w(TAG_WM, "Force clearing freeze: " + this);
4914 stopFreezingScreen(true, true);
4915 }
4916
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004917 void stopFreezingScreenLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 if (force || frozenBeforeDestroy) {
4919 frozenBeforeDestroy = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004920 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004921 return;
4922 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02004923 ProtoLog.v(WM_DEBUG_ORIENTATION,
Issei Suzuki7b9e2572019-11-14 16:19:54 +01004924 "Clear freezing of %s: hidden=%b freezing=%b", appToken,
4925 isHidden(), isFreezingScreen());
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004926 stopFreezingScreen(true, force);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 }
4928 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07004929
Garfield Tane8d84ab2019-10-11 09:49:40 -07004930 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
4931 if (!mFreezingScreen) {
4932 return;
4933 }
4934 ProtoLog.v(WM_DEBUG_ORIENTATION,
4935 "Clear freezing of %s force=%b", this, force);
4936 final int count = mChildren.size();
4937 boolean unfrozeWindows = false;
4938 for (int i = 0; i < count; i++) {
4939 final WindowState w = mChildren.get(i);
4940 unfrozeWindows |= w.onStopFreezingScreen();
4941 }
4942 if (force || unfrozeWindows) {
4943 ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
4944 mFreezingScreen = false;
4945 mWmService.unregisterAppFreezeListener(this);
4946 mWmService.mAppsFreezingScreen--;
4947 mWmService.mLastFinishedFreezeSource = this;
4948 }
4949 if (unfreezeSurfaceNow) {
4950 if (unfrozeWindows) {
4951 mWmService.mWindowPlacerLocked.performSurfacePlacement();
4952 }
4953 mWmService.stopFreezingDisplayLocked();
4954 }
4955 }
4956
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004957 void reportFullyDrawnLocked(boolean restoredFromBundle) {
Vishnu Nair132ee832018-09-28 15:00:05 -07004958 final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
Yan Wangd47f90b2019-10-03 19:17:15 -07004959 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
Vishnu Nair132ee832018-09-28 15:00:05 -07004960 if (info != null) {
4961 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
Vishnu Nairbb9ab4b2018-12-13 10:29:46 -08004962 info.windowsFullyDrawnDelayMs, info.getLaunchState());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07004963 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07004964 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004965
Garfield Tane8d84ab2019-10-11 09:49:40 -07004966 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
4967 firstWindowDrawn = true;
4968
4969 // We now have a good window to show, remove dead placeholders
4970 removeDeadWindows();
4971
4972 if (startingWindow != null) {
4973 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
4974 + ": first real window is shown, no animation", win.mToken);
4975 // If this initial window is animating, stop it -- we will do an animation to reveal
4976 // it from behind the starting window, so there is no need for it to also be doing its
4977 // own stuff.
4978 win.cancelAnimation();
4979 }
4980 removeStartingWindow();
4981 updateReportedVisibilityLocked();
4982 }
4983
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004984 /** Called when the windows associated app window container are drawn. */
Yan Wangd47f90b2019-10-03 19:17:15 -07004985 void onWindowsDrawn(boolean drawn, long timestampNs) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004986 mDrawn = drawn;
4987 if (!drawn) {
4988 return;
4989 }
4990 final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
Yan Wangd47f90b2019-10-03 19:17:15 -07004991 .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestampNs);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004992 final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
4993 final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
4994 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
4995 windowsDrawnDelayMs, launchState);
Riddle Hsuc48c8912019-10-31 13:34:27 +08004996 mStackSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004997 finishLaunchTickingLocked();
4998 if (task != null) {
4999 task.hasBeenVisible = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 }
5001 }
5002
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005003 /** Called when the windows associated app window container are visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005004 void onWindowsVisible() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005005 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005006 mStackSupervisor.stopWaitingForActivityVisible(this);
5007 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
5008 if (!nowVisible) {
5009 nowVisible = true;
5010 lastVisibleTime = SystemClock.uptimeMillis();
5011 mAtmService.scheduleAppGcsLocked();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005012 }
5013 }
5014
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005015 /** Called when the windows associated app window container are no longer visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005016 void onWindowsGone() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005017 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005018 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
5019 nowVisible = false;
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005020 }
5021
Garfield Tane8d84ab2019-10-11 09:49:40 -07005022 @Override
5023 void checkAppWindowsReadyToShow() {
5024 if (allDrawn == mLastAllDrawn) {
5025 return;
5026 }
5027
5028 mLastAllDrawn = allDrawn;
5029 if (!allDrawn) {
5030 return;
5031 }
5032
5033 // The token has now changed state to having all windows shown... what to do, what to do?
5034 if (mFreezingScreen) {
5035 showAllWindowsLocked();
5036 stopFreezingScreen(false, true);
5037 ProtoLog.i(WM_DEBUG_ORIENTATION,
5038 "Setting mOrientationChangeComplete=true because wtoken %s "
5039 + "numInteresting=%d numDrawn=%d",
5040 this, mNumInterestingWindows, mNumDrawnWindows);
5041 // This will set mOrientationChangeComplete and cause a pass through layout.
5042 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
5043 "checkAppWindowsReadyToShow: freezingScreen");
5044 } else {
5045 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
5046
5047 // We can now show all of the drawn windows!
5048 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
5049 showAllWindowsLocked();
5050 }
5051 }
5052 }
5053
5054 /**
5055 * This must be called while inside a transaction.
5056 */
5057 void showAllWindowsLocked() {
5058 forAllWindows(windowState -> {
5059 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
5060 windowState.performShowLocked();
5061 }, false /* traverseTopToBottom */);
5062 }
5063
5064 void updateReportedVisibilityLocked() {
5065 if (appToken == null) {
5066 return;
5067 }
5068
5069 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
5070 final int count = mChildren.size();
5071
5072 mReportedVisibilityResults.reset();
5073
5074 for (int i = 0; i < count; i++) {
5075 final WindowState win = mChildren.get(i);
5076 win.updateReportedVisibility(mReportedVisibilityResults);
5077 }
5078
5079 int numInteresting = mReportedVisibilityResults.numInteresting;
5080 int numVisible = mReportedVisibilityResults.numVisible;
5081 int numDrawn = mReportedVisibilityResults.numDrawn;
5082 boolean nowGone = mReportedVisibilityResults.nowGone;
5083
5084 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01005085 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005086 if (!nowGone) {
5087 // If the app is not yet gone, then it can only become visible/drawn.
5088 if (!nowDrawn) {
5089 nowDrawn = reportedDrawn;
5090 }
5091 if (!nowVisible) {
5092 nowVisible = reportedVisible;
5093 }
5094 }
5095 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
5096 + numInteresting + " visible=" + numVisible);
5097 if (nowDrawn != reportedDrawn) {
5098 onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
5099 reportedDrawn = nowDrawn;
5100 }
5101 if (nowVisible != reportedVisible) {
5102 if (DEBUG_VISIBILITY) Slog.v(TAG,
5103 "Visibility changed in " + this + ": vis=" + nowVisible);
5104 reportedVisible = nowVisible;
5105 if (nowVisible) {
5106 onWindowsVisible();
5107 } else {
5108 onWindowsGone();
5109 }
5110 }
5111 }
5112
Issei Suzukie63eac72019-11-14 15:59:15 +01005113 boolean isClientHidden() {
5114 return mClientHidden;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005115 }
5116
Issei Suzukie63eac72019-11-14 15:59:15 +01005117 void setClientHidden(boolean hideClient) {
5118 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005119 return;
5120 }
5121 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzukie63eac72019-11-14 15:59:15 +01005122 "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005123 Debug.getCallers(5));
Issei Suzukie63eac72019-11-14 15:59:15 +01005124 mClientHidden = hideClient;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005125 sendAppVisibilityToClients();
5126 }
5127
5128 /**
5129 * Updated this app token tracking states for interesting and drawn windows based on the window.
5130 *
5131 * @return Returns true if the input window is considered interesting and drawn while all the
5132 * windows in this app token where not considered drawn as of the last pass.
5133 */
5134 boolean updateDrawnWindowStates(WindowState w) {
5135 w.setDrawnStateEvaluated(true /*evaluated*/);
5136
5137 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
5138 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
5139 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
5140 }
5141
5142 if (allDrawn && !mFreezingScreen) {
5143 return false;
5144 }
5145
5146 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
5147 mLastTransactionSequence = mWmService.mTransactionSequence;
5148 mNumDrawnWindows = 0;
5149 startingDisplayed = false;
5150
5151 // There is the main base application window, even if it is exiting, wait for it
5152 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
5153 }
5154
5155 final WindowStateAnimator winAnimator = w.mWinAnimator;
5156
5157 boolean isInterestingAndDrawn = false;
5158
5159 if (!allDrawn && w.mightAffectAllDrawn()) {
5160 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5161 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
lumark9bca6b42019-10-17 18:35:22 +08005162 + ", isAnimationSet=" + isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005163 if (!w.isDrawnLw()) {
5164 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
5165 + " pv=" + w.isVisibleByPolicy()
5166 + " mDrawState=" + winAnimator.drawStateToString()
Issei Suzuki1669ea42019-11-06 14:20:59 +01005167 + " ph=" + w.isParentWindowHidden() + " th=" + mVisibleRequested
lumark9bca6b42019-10-17 18:35:22 +08005168 + " a=" + isAnimating(TRANSITION));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005169 }
5170 }
5171
5172 if (w != startingWindow) {
5173 if (w.isInteresting()) {
5174 // Add non-main window as interesting since the main app has already been added
5175 if (findMainWindow(false /* includeStartingApp */) != w) {
5176 mNumInterestingWindows++;
5177 }
5178 if (w.isDrawnLw()) {
5179 mNumDrawnWindows++;
5180
5181 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5182 Slog.v(TAG, "tokenMayBeDrawn: "
5183 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
5184 + " freezingScreen=" + mFreezingScreen
5185 + " mAppFreezing=" + w.mAppFreezing);
5186 }
5187
5188 isInterestingAndDrawn = true;
5189 }
5190 }
5191 } else if (w.isDrawnLw()) {
Yan Wangb0b20062019-10-30 12:47:09 -07005192 onStartingWindowDrawn(SystemClock.elapsedRealtimeNanos());
Garfield Tane8d84ab2019-10-11 09:49:40 -07005193 startingDisplayed = true;
5194 }
5195 }
5196
5197 return isInterestingAndDrawn;
5198 }
5199
5200 /** Called when the starting window for this container is drawn. */
Yan Wangb0b20062019-10-30 12:47:09 -07005201 private void onStartingWindowDrawn(long timestampNs) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005202 synchronized (mAtmService.mGlobalLock) {
5203 mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
Yan Wangb0b20062019-10-30 12:47:09 -07005204 getWindowingMode(), timestampNs);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005205 }
5206 }
5207
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005208 /**
5209 * Called when the key dispatching to a window associated with the app window container
5210 * timed-out.
5211 *
5212 * @param reason The reason for the key dispatching time out.
5213 * @param windowPid The pid of the window key dispatching timed out on.
5214 * @return True if input dispatching should be aborted.
5215 */
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005216 public boolean keyDispatchingTimedOut(String reason, int windowPid) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005217 ActivityRecord anrActivity;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005218 WindowProcessController anrApp;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005219 boolean windowFromSameProcessAsActivity;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005220 synchronized (mAtmService.mGlobalLock) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005221 anrActivity = getWaitingHistoryRecordLocked();
5222 anrApp = app;
Brian Carlstrom7b0f2e82017-03-31 00:24:18 -07005223 windowFromSameProcessAsActivity =
Vishnu Nair19479df2019-10-30 08:03:15 -07005224 !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005225 }
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005226
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005227 if (windowFromSameProcessAsActivity) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005228 return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07005229 anrActivity.shortComponentName, anrActivity.info.applicationInfo,
5230 shortComponentName, app, false, reason);
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005231 } else {
5232 // In this case another process added windows using this activity token. So, we call the
5233 // generic service input dispatch timed out method so that the right process is blamed.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005234 return mAtmService.mAmInternal.inputDispatchingTimedOut(
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005235 windowPid, false /* aboveSystem */, reason) < 0;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005236 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005237 }
5238
5239 private ActivityRecord getWaitingHistoryRecordLocked() {
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005240 // First find the real culprit... if this activity has stopped, then the key dispatching
riddle_hsudb46d6b2015-04-01 18:58:07 +08005241 // timeout should not be caused by this.
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005242 if (stopped) {
Wale Ogunwaled32da472018-11-16 07:19:28 -08005243 final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
riddle_hsudb46d6b2015-04-01 18:58:07 +08005244 // Try to use the one which is closest to top.
Bryce Leec4ab62a2018-03-05 14:19:26 -08005245 ActivityRecord r = stack.getResumedActivity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 if (r == null) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08005247 r = stack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005249 if (r != null) {
5250 return r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 }
5252 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005253 return this;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 }
5255
Chong Zhang87761972016-08-22 13:53:24 -07005256 /** Checks whether the activity should be shown for current user. */
5257 public boolean okToShowLocked() {
Bryce Lee8558ec72017-08-17 15:37:26 -07005258 // We cannot show activities when the device is locked and the application is not
5259 // encryption aware.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005260 if (!StorageManager.isUserKeyUnlocked(mUserId)
Bryce Lee8558ec72017-08-17 15:37:26 -07005261 && !info.applicationInfo.isEncryptionAware()) {
5262 return false;
5263 }
5264
Chong Zhang87761972016-08-22 13:53:24 -07005265 return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005266 || (mStackSupervisor.isCurrentProfileLocked(mUserId)
5267 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
Chong Zhang87761972016-08-22 13:53:24 -07005268 }
5269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 /**
5271 * This method will return true if the activity is either visible, is becoming visible, is
5272 * currently pausing, or is resumed.
5273 */
5274 public boolean isInterestingToUserLocked() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01005275 return mVisibleRequested || nowVisible || mState == PAUSING || mState == RESUMED;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005276 }
5277
Wale Ogunwale3e997362016-09-06 10:37:56 -07005278 void setSleeping(boolean _sleeping) {
5279 setSleeping(_sleeping, false);
5280 }
5281
5282 void setSleeping(boolean _sleeping, boolean force) {
5283 if (!force && sleeping == _sleeping) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005284 return;
5285 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005286 if (attachedToProcess()) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005287 try {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005288 app.getThread().scheduleSleeping(appToken, _sleeping);
Craig Mautner0eea92c2013-05-16 13:35:39 -07005289 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
5290 mStackSupervisor.mGoingToSleepActivities.add(this);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005291 }
5292 sleeping = _sleeping;
5293 } catch (RemoteException e) {
Craig Mautner0eea92c2013-05-16 13:35:39 -07005294 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005295 }
5296 }
5297 }
Craig Mautnerf81b90872013-02-26 13:02:43 -08005298
Craig Mautnerd2328952013-03-05 12:46:26 -08005299 static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005300 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Craig Mautnerd2328952013-03-05 12:46:26 -08005301 if (r == null) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005302 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005303 }
Louis Changcdec0802019-11-11 11:45:07 +08005304 final Task task = r.task;
Wale Ogunwale2322bed2019-10-10 17:24:19 +02005305 final int activityNdx = task.mChildren.indexOf(r);
Andrii Kulian39f27442019-06-26 19:09:19 -07005306 if (activityNdx < 0
5307 || (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005308 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005309 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005310 return task.mTaskId;
Craig Mautnerd2328952013-03-05 12:46:26 -08005311 }
5312
5313 static ActivityRecord isInStackLocked(IBinder token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005314 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005315 return (r != null) ? r.getActivityStack().isInStackLocked(r) : null;
Craig Mautnerd2328952013-03-05 12:46:26 -08005316 }
5317
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005318 static ActivityStack getStackLocked(IBinder token) {
Craig Mautnerd2328952013-03-05 12:46:26 -08005319 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
5320 if (r != null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005321 return r.getActivityStack();
Craig Mautnerd2328952013-03-05 12:46:26 -08005322 }
5323 return null;
5324 }
5325
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005326 /**
Riddle Hsufd4a0502018-10-16 01:05:16 +08005327 * @return display id to which this record is attached,
5328 * {@link android.view.Display#INVALID_DISPLAY} if not attached.
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005329 */
5330 int getDisplayId() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005331 final ActivityStack stack = getActivityStack();
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005332 if (stack == null) {
Riddle Hsufd4a0502018-10-16 01:05:16 +08005333 return INVALID_DISPLAY;
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005334 }
5335 return stack.mDisplayId;
5336 }
5337
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005338 final boolean isDestroyable() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005339 if (finishing || !hasProcess()) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005340 // This would be redundant.
5341 return false;
5342 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005343 final ActivityStack stack = getActivityStack();
Andrii Kulianf49a58c2019-08-14 17:34:27 -07005344 if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState
5345 || !stopped) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005346 // We're not ready for this kind of thing.
5347 return false;
5348 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01005349 if (mVisibleRequested) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005350 // The user would notice this!
5351 return false;
5352 }
5353 return true;
5354 }
5355
Winson Chung3bad5cc02014-08-19 17:44:32 -07005356 private static String createImageFilename(long createTime, int taskId) {
5357 return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
Ruben Brunkf53497c2017-03-27 20:26:17 -07005358 IMAGE_EXTENSION;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07005359 }
5360
Craig Mautner648f69b2014-09-18 14:16:26 -07005361 void setTaskDescription(TaskDescription _taskDescription) {
5362 Bitmap icon;
5363 if (_taskDescription.getIconFilename() == null &&
5364 (icon = _taskDescription.getIcon()) != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005365 final String iconFilename = createImageFilename(createTime, task.mTaskId);
5366 final File iconFile = new File(TaskPersister.getUserImagesDir(task.mUserId),
Winson Chungc8408b82017-01-25 17:58:56 -08005367 iconFilename);
Suprabh Shukla23593142015-11-03 17:31:15 -08005368 final String iconFilePath = iconFile.getAbsolutePath();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005369 mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
Suprabh Shukla23593142015-11-03 17:31:15 -08005370 _taskDescription.setIconFilename(iconFilePath);
Craig Mautner648f69b2014-09-18 14:16:26 -07005371 }
5372 taskDescription = _taskDescription;
5373 }
5374
Amith Yamasani0af6fa72016-01-17 15:36:19 -08005375 void setVoiceSessionLocked(IVoiceInteractionSession session) {
5376 voiceSession = session;
5377 pendingVoiceInteractionStart = false;
5378 }
5379
5380 void clearVoiceSessionLocked() {
5381 voiceSession = null;
5382 pendingVoiceInteractionStart = false;
5383 }
5384
Jorim Jaggi02886a82016-12-06 09:10:06 -08005385 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
Jorim Jaggi42befc62017-06-13 11:54:04 -07005386 showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
5387 }
5388
5389 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
5390 boolean fromRecents) {
Wale Ogunwale19866e22017-04-19 06:05:13 -07005391 if (mTaskOverlay) {
5392 // We don't show starting window for overlay activities.
5393 return;
5394 }
Sunny Goyald85bed52018-09-25 12:01:01 -07005395 if (pendingOptions != null
5396 && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
5397 // Don't show starting window when using shared element transition.
5398 return;
5399 }
Wale Ogunwale19866e22017-04-19 06:05:13 -07005400
Wale Ogunwale3b232392016-05-13 15:37:13 -07005401 final CompatibilityInfo compatInfo =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005402 mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005403 final boolean shown = addStartingWindow(packageName, theme,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005404 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
Jorim Jaggibae01b12017-04-11 16:29:10 -07005405 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
Jorim Jaggi70aa4d12017-05-15 00:05:54 +02005406 allowTaskSnapshot(),
Louis Changeadb22f2019-06-19 12:09:23 +08005407 mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
Jorim Jaggi42befc62017-06-13 11:54:04 -07005408 fromRecents);
Wale Ogunwale3b232392016-05-13 15:37:13 -07005409 if (shown) {
5410 mStartingWindowState = STARTING_WINDOW_SHOWN;
5411 }
5412 }
5413
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005414 /**
5415 * If any activities below the top running one are in the INITIALIZING state and they have a
5416 * starting window displayed then remove that starting window. It is possible that the activity
5417 * in this state will never resumed in which case that starting window will be orphaned.
5418 * <p>
5419 * It should only be called if this activity is behind other fullscreen activity.
5420 */
5421 void cancelInitializing() {
5422 if (mStartingWindowState == STARTING_WINDOW_SHOWN) {
5423 // Remove orphaned starting window.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005424 if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
5425 mStartingWindowState = STARTING_WINDOW_REMOVED;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005426 removeStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005427 }
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005428 if (isState(INITIALIZING) && !shouldBeVisible(
5429 true /* behindFullscreenActivity */, true /* ignoringKeyguard */)) {
5430 // Remove the unknown visibility record because an invisible activity shouldn't block
5431 // the keyguard transition.
5432 mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
5433 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005434 }
5435
Garfield Tane8d84ab2019-10-11 09:49:40 -07005436 void postWindowRemoveStartingWindowCleanup(WindowState win) {
5437 // TODO: Something smells about the code below...Is there a better way?
5438 if (startingWindow == win) {
5439 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
5440 removeStartingWindow();
5441 } else if (mChildren.size() == 0) {
5442 // If this is the last window and we had requested a starting transition window,
5443 // well there is no point now.
5444 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
5445 mStartingData = null;
Issei Suzuki7b9e2572019-11-14 16:19:54 +01005446 if (mHiddenSetFromTransferredStartingWindow) {
5447 // We set the hidden state to false for the token from a transferred starting window.
5448 // We now reset it back to true since the starting window was the last window in the
5449 // token.
5450 setHidden(true);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005451 }
5452 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
5453 // If this is the last window except for a starting transition window,
5454 // we need to get rid of the starting transition.
5455 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
5456 removeStartingWindow();
5457 }
5458 }
5459
5460 void removeDeadWindows() {
5461 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
5462 WindowState win = mChildren.get(winNdx);
5463 if (win.mAppDied) {
5464 ProtoLog.w(WM_DEBUG_ADD_REMOVE,
5465 "removeDeadWindows: %s", win);
5466 // Set mDestroying, we don't want any animation or delayed removal here.
5467 win.mDestroying = true;
5468 // Also removes child windows.
5469 win.removeIfPossible();
5470 }
5471 }
5472 }
5473
5474 boolean hasWindowsAlive() {
5475 for (int i = mChildren.size() - 1; i >= 0; i--) {
5476 // No need to loop through child windows as the answer should be the same as that of the
5477 // parent window.
5478 if (!(mChildren.get(i)).mAppDied) {
5479 return true;
5480 }
5481 }
5482 return false;
5483 }
5484
5485 void setWillReplaceWindows(boolean animate) {
5486 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5487 "Marking app token %s with replacing windows.", this);
5488
5489 for (int i = mChildren.size() - 1; i >= 0; i--) {
5490 final WindowState w = mChildren.get(i);
5491 w.setWillReplaceWindow(animate);
5492 }
5493 }
5494
5495 void setWillReplaceChildWindows() {
5496 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
5497 + " with replacing child windows.", this);
5498 for (int i = mChildren.size() - 1; i >= 0; i--) {
5499 final WindowState w = mChildren.get(i);
5500 w.setWillReplaceChildWindows();
5501 }
5502 }
5503
5504 void clearWillReplaceWindows() {
5505 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5506 "Resetting app token %s of replacing window marks.", this);
5507
5508 for (int i = mChildren.size() - 1; i >= 0; i--) {
5509 final WindowState w = mChildren.get(i);
5510 w.clearWillReplaceWindow();
5511 }
5512 }
5513
5514 void requestUpdateWallpaperIfNeeded() {
5515 for (int i = mChildren.size() - 1; i >= 0; i--) {
5516 final WindowState w = mChildren.get(i);
5517 w.requestUpdateWallpaperIfNeeded();
5518 }
5519 }
5520
5521 /**
5522 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
5523 * true.
5524 */
5525 WindowState getTopFullscreenWindow() {
5526 for (int i = mChildren.size() - 1; i >= 0; i--) {
5527 final WindowState win = mChildren.get(i);
5528 if (win != null && win.mAttrs.isFullscreen()) {
5529 return win;
5530 }
5531 }
5532 return null;
5533 }
5534
5535 WindowState findMainWindow() {
5536 return findMainWindow(true);
5537 }
5538
5539 /**
5540 * Finds the main window that either has type base application or application starting if
5541 * requested.
5542 *
5543 * @param includeStartingApp Allow to search application-starting windows to also be returned.
5544 * @return The main window of type base application or application starting if requested.
5545 */
5546 WindowState findMainWindow(boolean includeStartingApp) {
5547 WindowState candidate = null;
5548 for (int j = mChildren.size() - 1; j >= 0; --j) {
5549 final WindowState win = mChildren.get(j);
5550 final int type = win.mAttrs.type;
5551 // No need to loop through child window as base application and starting types can't be
5552 // child windows.
5553 if (type == TYPE_BASE_APPLICATION
5554 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
5555 // In cases where there are multiple windows, we prefer the non-exiting window. This
5556 // happens for example when replacing windows during an activity relaunch. When
5557 // constructing the animation, we want the new window, not the exiting one.
5558 if (win.mAnimatingExit) {
5559 candidate = win;
5560 } else {
5561 return win;
5562 }
5563 }
5564 }
5565 return candidate;
5566 }
5567
5568 SurfaceControl getAppAnimationLayer() {
5569 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
5570 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
5571 : ANIMATION_LAYER_STANDARD);
5572 }
5573
5574 @Override
5575 boolean needsZBoost() {
5576 return mNeedsZBoost || super.needsZBoost();
5577 }
5578
5579 @Override
5580 public SurfaceControl getAnimationLeashParent() {
5581 // For transitions in the pinned stack (menu activity) we just let them occur as a child
5582 // of the pinned stack.
5583 // All normal app transitions take place in an animation layer which is below the pinned
5584 // stack but may be above the parent stacks of the given animating apps by default. When
5585 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
5586 // stack, i.e. the hierarchy of the surfaces is unchanged.
5587 if (inPinnedWindowingMode()) {
5588 return getStack().getSurfaceControl();
5589 } else if (WindowManagerService.sHierarchicalAnimations) {
5590 return super.getAnimationLeashParent();
5591 } else {
5592 return getAppAnimationLayer();
5593 }
5594 }
5595
Garfield Tane8d84ab2019-10-11 09:49:40 -07005596 @VisibleForTesting
5597 boolean shouldAnimate(int transit) {
lumark19a5d2e2019-10-11 16:19:30 +08005598 if (task != null && !task.shouldAnimate()) {
5599 return false;
5600 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005601 final boolean isSplitScreenPrimary =
5602 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
5603 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
5604
Garfield Tane8d84ab2019-10-11 09:49:40 -07005605 // We animate always if it's not split screen primary, and only some special cases in split
5606 // screen primary because it causes issues with stack clipping when we run an un-minimize
5607 // animation at the same time.
5608 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
5609 }
5610
lumark19a5d2e2019-10-11 16:19:30 +08005611 @Override
5612 boolean isChangingAppTransition() {
Louis Changcdec0802019-11-11 11:45:07 +08005613 return task != null ? task.isChangingAppTransition() : super.isChangingAppTransition();
lumark19a5d2e2019-10-11 16:19:30 +08005614 }
5615
5616 @Override
5617 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
5618 boolean isVoiceInteraction) {
5619 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
5620 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
5621 "applyAnimation: transition animation is disabled or skipped. "
5622 + "container=%s", this);
5623 cancelAnimation();
5624 return false;
5625 }
5626 return super.applyAnimation(lp, transit, enter, isVoiceInteraction);
5627 }
5628
Garfield Tane8d84ab2019-10-11 09:49:40 -07005629 /**
5630 * Creates a layer to apply crop to an animation.
5631 */
5632 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
5633 ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
5634 final SurfaceControl.Builder builder = makeAnimationLeash()
5635 .setParent(getAnimationLeashParent())
5636 .setName(getSurfaceControl() + " - animation-bounds");
5637 final SurfaceControl boundsLayer = builder.build();
5638 t.show(boundsLayer);
5639 return boundsLayer;
5640 }
5641
Garfield Tane8d84ab2019-10-11 09:49:40 -07005642 @Override
5643 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
5644 return mAnimatingActivityRegistry != null
5645 && mAnimatingActivityRegistry.notifyAboutToFinish(
5646 this, endDeferFinishCallback);
5647 }
5648
5649 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
5650 if (mWmService.mDisableTransitionAnimation
5651 || !isVisible()
5652 || getDisplayContent().mAppTransition.isTransitionSet()
5653 || getSurfaceControl() == null) {
5654 return false;
5655 }
5656 // Only do an animation into and out-of freeform mode for now. Other mode
5657 // transition animations are currently handled by system-ui.
5658 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
5659 }
5660
lumark9bca6b42019-10-17 18:35:22 +08005661 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07005662 boolean isWaitingForTransitionStart() {
5663 final DisplayContent dc = getDisplayContent();
Wale Ogunwale2322bed2019-10-10 17:24:19 +02005664 // TODO(display-unify): Test for null can be removed once unification is done.
Garfield Tane8d84ab2019-10-11 09:49:40 -07005665 if (dc == null) return false;
5666 return dc.mAppTransition.isTransitionSet()
5667 && (dc.mOpeningApps.contains(this)
5668 || dc.mClosingApps.contains(this)
5669 || dc.mChangingApps.contains(this));
5670 }
5671
5672 /**
5673 * Initializes a change transition. Because the app is visible already, there is a small period
5674 * of time where the user can see the app content/window update before the transition starts.
5675 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
5676 * "freezes" the location/crop until the transition starts.
5677 * <p>
5678 * Here's a walk-through of the process:
5679 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
5680 * 2. Set the temporary leash's position/crop to the current state.
5681 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
5682 * 4. Once the transition is ready, it will reparent the app to the animation leash.
5683 * 5. Detach the interim-change-leash.
5684 */
5685 private void initializeChangeTransition(Rect startBounds) {
5686 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
5687 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
5688 mDisplayContent.mChangingApps.add(this);
5689 mTransitStartRect.set(startBounds);
5690
5691 final SurfaceControl.Builder builder = makeAnimationLeash()
5692 .setParent(getAnimationLeashParent())
5693 .setName(getSurfaceControl() + " - interim-change-leash");
5694 mTransitChangeLeash = builder.build();
5695 Transaction t = getPendingTransaction();
5696 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
5697 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
5698 t.show(mTransitChangeLeash);
5699 t.reparent(getSurfaceControl(), mTransitChangeLeash);
5700 onAnimationLeashCreated(t, mTransitChangeLeash);
5701
5702 // Skip creating snapshot if this transition is controlled by a remote animator which
5703 // doesn't need it.
5704 ArraySet<Integer> activityTypes = new ArraySet<>();
5705 activityTypes.add(getActivityType());
5706 RemoteAnimationAdapter adapter =
5707 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
5708 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
5709 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
5710 return;
5711 }
5712
Garfield Tane8d84ab2019-10-11 09:49:40 -07005713 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
5714 SurfaceControl.ScreenshotGraphicBuffer snapshot =
5715 mWmService.mTaskSnapshotController.createTaskSnapshot(
5716 task, 1 /* scaleFraction */);
5717 if (snapshot != null) {
lumarkbc0032a2019-11-01 21:38:13 +08005718 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory, t, this,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005719 snapshot.getGraphicBuffer(), true /* relative */);
5720 }
5721 }
5722 }
5723
5724 @Override
5725 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
5726 // The leash is parented to the animation layer. We need to preserve the z-order by using
5727 // the prefix order index, but we boost if necessary.
5728 int layer = 0;
5729 if (!inPinnedWindowingMode()) {
5730 layer = getPrefixOrderIndex();
5731 } else {
5732 // Pinned stacks have animations take place within themselves rather than an animation
5733 // layer so we need to preserve the order relative to the stack (e.g. the order of our
5734 // task/parent).
5735 layer = getParent().getPrefixOrderIndex();
5736 }
5737
5738 if (mNeedsZBoost) {
5739 layer += Z_BOOST_BASE;
5740 }
5741 if (!mNeedsAnimationBoundsLayer) {
5742 t.setLayer(leash, layer);
5743 }
5744
5745 final DisplayContent dc = getDisplayContent();
5746 dc.assignStackOrdering();
5747
5748 if (leash == mTransitChangeLeash) {
5749 // This is a temporary state so skip any animation notifications
5750 return;
5751 } else if (mTransitChangeLeash != null) {
5752 // unparent mTransitChangeLeash for clean-up
5753 clearChangeLeash(t, false /* cancel */);
5754 }
5755
5756 if (mAnimatingActivityRegistry != null) {
5757 mAnimatingActivityRegistry.notifyStarting(this);
5758 }
5759
5760 // If the animation needs to be cropped then an animation bounds layer is created as a child
5761 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
5762 if (mNeedsAnimationBoundsLayer) {
5763 mTmpRect.setEmpty();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005764 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
5765 getTransit(), task)) {
5766 task.getBounds(mTmpRect);
5767 } else {
Louis Changdc077272019-11-12 16:52:56 +08005768 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005769 if (stack == null) {
5770 return;
5771 }
5772 // Set clip rect to stack bounds.
5773 stack.getBounds(mTmpRect);
5774 }
5775 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
5776
5777 // Crop to stack bounds.
5778 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
5779 t.setLayer(mAnimationBoundsLayer, layer);
5780
5781 // Reparent leash to animation bounds layer.
5782 t.reparent(leash, mAnimationBoundsLayer);
5783 }
5784 }
5785
5786 @Override
5787 void prepareSurfaces() {
Issei Suzuki7b9e2572019-11-14 16:19:54 +01005788 final boolean show = !isHidden() || isAnimating();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005789
5790 if (mSurfaceControl != null) {
5791 if (show && !mLastSurfaceShowing) {
5792 getPendingTransaction().show(mSurfaceControl);
5793 } else if (!show && mLastSurfaceShowing) {
5794 getPendingTransaction().hide(mSurfaceControl);
5795 }
5796 }
5797 if (mThumbnail != null) {
5798 mThumbnail.setShowing(getPendingTransaction(), show);
5799 }
5800 mLastSurfaceShowing = show;
5801 super.prepareSurfaces();
5802 }
5803
5804 /**
5805 * @return Whether our {@link #getSurfaceControl} is currently showing.
5806 */
5807 boolean isSurfaceShowing() {
5808 return mLastSurfaceShowing;
5809 }
5810
5811 boolean isInChangeTransition() {
5812 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
5813 }
5814
5815 void attachThumbnailAnimation() {
lumark9bca6b42019-10-17 18:35:22 +08005816 if (!isAnimating()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005817 return;
5818 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005819 final GraphicBuffer thumbnailHeader =
Louis Changcdec0802019-11-11 11:45:07 +08005820 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005821 if (thumbnailHeader == null) {
Louis Changcdec0802019-11-11 11:45:07 +08005822 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005823 return;
5824 }
5825 clearThumbnail();
lumarkbc0032a2019-11-01 21:38:13 +08005826 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
5827 getPendingTransaction(), this, thumbnailHeader);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005828 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
5829 }
5830
5831 /**
5832 * Attaches a surface with a thumbnail for the
5833 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
5834 */
5835 void attachCrossProfileAppsThumbnailAnimation() {
lumark9bca6b42019-10-17 18:35:22 +08005836 if (!isAnimating()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005837 return;
5838 }
5839 clearThumbnail();
5840
5841 final WindowState win = findMainWindow();
5842 if (win == null) {
5843 return;
5844 }
5845 final Rect frame = win.getFrameLw();
Louis Changcdec0802019-11-11 11:45:07 +08005846 final int thumbnailDrawableRes = task.mUserId == mWmService.mCurrentUserId
Garfield Tane8d84ab2019-10-11 09:49:40 -07005847 ? R.drawable.ic_account_circle
5848 : R.drawable.ic_corp_badge;
5849 final GraphicBuffer thumbnail =
5850 getDisplayContent().mAppTransition
5851 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
5852 if (thumbnail == null) {
5853 return;
5854 }
lumarkbc0032a2019-11-01 21:38:13 +08005855 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005856 getPendingTransaction(), this, thumbnail);
5857 final Animation animation =
5858 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
5859 win.getFrameLw());
5860 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
5861 frame.top));
5862 }
5863
5864 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
5865 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
5866
5867 // If this is a multi-window scenario, we use the windows frame as
5868 // destination of the thumbnail header animation. If this is a full screen
5869 // window scenario, we use the whole display as the target.
5870 WindowState win = findMainWindow();
5871 Rect appRect = win != null ? win.getContentFrameLw() :
5872 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
5873 final Rect insets = win != null ? win.getContentInsets() : null;
5874 final Configuration displayConfig = mDisplayContent.getConfiguration();
5875 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Louis Changcdec0802019-11-11 11:45:07 +08005876 appRect, insets, thumbnailHeader, task, displayConfig.uiMode,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005877 displayConfig.orientation);
5878 }
5879
5880 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07005881 public void onAnimationLeashLost(Transaction t) {
5882 super.onAnimationLeashLost(t);
5883 if (mAnimationBoundsLayer != null) {
5884 t.remove(mAnimationBoundsLayer);
5885 mAnimationBoundsLayer = null;
5886 }
5887
5888 if (mAnimatingActivityRegistry != null) {
5889 mAnimatingActivityRegistry.notifyFinished(this);
5890 }
5891 }
5892
5893 @Override
5894 protected void onAnimationFinished() {
5895 super.onAnimationFinished();
5896
5897 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
5898 mTransit = TRANSIT_UNSET;
5899 mTransitFlags = 0;
5900 mNeedsZBoost = false;
5901 mNeedsAnimationBoundsLayer = false;
5902
5903 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
5904 "AppWindowToken");
5905
5906 clearThumbnail();
Issei Suzuki1669ea42019-11-06 14:20:59 +01005907 setClientHidden(isHidden() && !mVisibleRequested);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005908
5909 getDisplayContent().computeImeTargetIfNeeded(this);
5910
5911 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
5912 + ": reportedVisible=" + reportedVisible
5913 + " okToDisplay=" + okToDisplay()
5914 + " okToAnimate=" + okToAnimate()
5915 + " startingDisplayed=" + startingDisplayed);
5916
5917 // clean up thumbnail window
5918 if (mThumbnail != null) {
5919 mThumbnail.destroy();
5920 mThumbnail = null;
5921 }
5922
5923 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
5924 // traverse the copy.
5925 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
5926 children.forEach(WindowState::onExitAnimationDone);
5927
5928 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
5929 scheduleAnimation();
5930
5931 if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
5932 || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
5933 // If all activities are already idle or there is an activity that must be
5934 // stopped immediately after visible, then we now need to make sure we perform
5935 // the full stop of this activity. This is because we won't do that while they are still
5936 // waiting for the animation to finish.
5937 if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
5938 mAtmService.mStackSupervisor.scheduleIdleLocked();
5939 }
5940 } else {
5941 // Instead of doing the full stop routine here, let's just hide any activities
5942 // we now can, and let them stop when the normal idle happens.
5943 mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
5944 false /* remove */, true /* processPausingActivities */);
5945 }
5946 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
5947 }
5948
5949 /**
5950 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
5951 * to another leash.
5952 */
5953 private void clearChangeLeash(Transaction t, boolean cancel) {
5954 if (mTransitChangeLeash == null) {
5955 return;
5956 }
5957 if (cancel) {
5958 clearThumbnail();
5959 SurfaceControl sc = getSurfaceControl();
5960 SurfaceControl parentSc = getParentSurfaceControl();
5961 // Don't reparent if surface is getting destroyed
5962 if (parentSc != null && sc != null) {
5963 t.reparent(sc, getParentSurfaceControl());
5964 }
5965 }
5966 t.hide(mTransitChangeLeash);
5967 t.remove(mTransitChangeLeash);
5968 mTransitChangeLeash = null;
5969 if (cancel) {
5970 onAnimationLeashLost(t);
5971 }
5972 }
5973
5974 void clearAnimatingFlags() {
5975 boolean wallpaperMightChange = false;
5976 for (int i = mChildren.size() - 1; i >= 0; i--) {
5977 final WindowState win = mChildren.get(i);
5978 wallpaperMightChange |= win.clearAnimatingFlags();
5979 }
5980 if (wallpaperMightChange) {
5981 requestUpdateWallpaperIfNeeded();
5982 }
5983 }
5984
Garfield Tane8d84ab2019-10-11 09:49:40 -07005985 @Override
5986 void cancelAnimation() {
5987 cancelAnimationOnly();
5988 clearThumbnail();
5989 clearChangeLeash(getPendingTransaction(), true /* cancel */);
5990 }
5991
5992 /**
5993 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
5994 * or interim leashes.
5995 * <p>
5996 * Used when canceling in preparation for starting a new animation.
5997 */
5998 void cancelAnimationOnly() {
5999 super.cancelAnimation();
6000 }
6001
6002 @VisibleForTesting
lumarkbc0032a2019-11-01 21:38:13 +08006003 WindowContainerThumbnail getThumbnail() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006004 return mThumbnail;
6005 }
6006
6007 private void clearThumbnail() {
6008 if (mThumbnail == null) {
6009 return;
6010 }
6011 mThumbnail.destroy();
6012 mThumbnail = null;
6013 }
6014
6015 public int getTransit() {
6016 return mTransit;
6017 }
6018
6019 int getTransitFlags() {
6020 return mTransitFlags;
6021 }
6022
6023 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
6024 mRemoteAnimationDefinition = definition;
6025 }
6026
6027 RemoteAnimationDefinition getRemoteAnimationDefinition() {
6028 return mRemoteAnimationDefinition;
6029 }
6030
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006031 void setRequestedOrientation(int requestedOrientation) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006032 setOrientation(requestedOrientation, mayFreezeScreenLocked());
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006033 mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07006034 task.mTaskId, requestedOrientation);
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006035 }
6036
Garfield Tan90b04282018-12-11 14:04:42 -08006037 private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
Evan Rosky730f6e82018-12-03 17:40:11 -08006038 final IBinder binder =
6039 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006040 setOrientation(requestedOrientation, binder, this);
Garfield Tan36a69ad2019-01-16 17:08:23 -08006041
6042 // Push the new configuration to the requested app in case where it's not pushed, e.g. when
6043 // the request is handled at task level with letterbox.
6044 if (!getMergedOverrideConfiguration().equals(
6045 mLastReportedConfiguration.getMergedConfiguration())) {
6046 ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
6047 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08006048 }
6049
Garfield Tane8d84ab2019-10-11 09:49:40 -07006050 void reportDescendantOrientationChangeIfNeeded() {
6051 // Orientation request is exposed only when we're visible. Therefore visibility change
6052 // will change requested orientation. Notify upward the hierarchy ladder to adjust
6053 // configuration. This is important to cases where activities with incompatible
6054 // orientations launch, or user goes back from an activity of bi-orientation to an
6055 // activity with specified orientation.
6056 if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
6057 return;
6058 }
6059
6060 final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
6061 onDescendantOrientationChanged(freezeToken, this);
6062 }
6063
6064 /**
6065 * We override because this class doesn't want its children affecting its reported orientation
6066 * in anyway.
6067 */
6068 @Override
6069 int getOrientation(int candidate) {
6070 if (candidate == SCREEN_ORIENTATION_BEHIND) {
6071 // Allow app to specify orientation regardless of its visibility state if the current
6072 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
6073 // wants us to use the orientation of the app behind it.
6074 return mOrientation;
6075 }
6076
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08006077 // The {@link ActivityRecord} should only specify an orientation when it is not closing.
6078 // Allowing closing {@link ActivityRecord} to participate can lead to an Activity in another
6079 // task being started in the wrong orientation during the transition.
6080 if (!getDisplayContent().mClosingApps.contains(this)
Garfield Tane8d84ab2019-10-11 09:49:40 -07006081 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
6082 return mOrientation;
6083 }
6084
6085 return SCREEN_ORIENTATION_UNSET;
6086 }
6087
6088 /** Returns the app's preferred orientation regardless of its currently visibility state. */
6089 int getRequestedOrientation() {
6090 return mOrientation;
6091 }
6092
Bryce Leea163b762017-01-24 11:05:01 -08006093 /**
6094 * Set the last reported global configuration to the client. Should be called whenever a new
6095 * global configuration is sent to the client for this activity.
6096 */
6097 void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006098 mLastReportedConfiguration.setGlobalConfiguration(config);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006099 }
6100
Bryce Leea163b762017-01-24 11:05:01 -08006101 /**
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006102 * Set the last reported configuration to the client. Should be called whenever
Bryce Leea163b762017-01-24 11:05:01 -08006103 * a new merged configuration is sent to the client for this activity.
6104 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006105 void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006106 setLastReportedConfiguration(config.getGlobalConfiguration(),
6107 config.getOverrideConfiguration());
Bryce Leea163b762017-01-24 11:05:01 -08006108 }
6109
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07006110 private void setLastReportedConfiguration(Configuration global, Configuration override) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006111 mLastReportedConfiguration.setConfiguration(global, override);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006112 }
6113
Riddle Hsu0a343c32018-12-21 00:40:48 +08006114 /**
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006115 * @return {@code true} if this activity is in size compatibility mode that uses the different
6116 * density or bounds from its parent.
6117 */
6118 boolean inSizeCompatMode() {
Evan Rosky72f084d2019-09-11 17:05:16 -07006119 if (mCompatDisplayInsets == null || !shouldUseSizeCompatMode()) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006120 return false;
6121 }
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006122 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu04164182019-03-07 18:03:27 +08006123 final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
6124 if (resolvedAppBounds == null) {
6125 // The override configuration has not been resolved yet.
6126 return false;
6127 }
6128
6129 final Configuration parentConfig = getParent().getConfiguration();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006130 // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
6131 // fields should be changed with density and bounds, so here only compares the most
6132 // significant field.
6133 if (parentConfig.densityDpi != resolvedConfig.densityDpi) {
6134 return true;
6135 }
Riddle Hsu04164182019-03-07 18:03:27 +08006136
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006137 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
Riddle Hsuaec55442019-03-12 17:25:35 +08006138 final int appWidth = resolvedAppBounds.width();
6139 final int appHeight = resolvedAppBounds.height();
6140 final int parentAppWidth = parentAppBounds.width();
6141 final int parentAppHeight = parentAppBounds.height();
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006142 if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
6143 // Matched the parent bounds.
6144 return false;
6145 }
6146 if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
6147 // Both sides are smaller than the parent.
6148 return true;
6149 }
Riddle Hsuaec55442019-03-12 17:25:35 +08006150 if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
Riddle Hsu04164182019-03-07 18:03:27 +08006151 // One side is larger than the parent.
6152 return true;
6153 }
6154
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006155 // The rest of the condition is that only one side is smaller than the parent, but it still
6156 // needs to exclude the cases where the size is limited by the fixed aspect ratio.
6157 if (info.maxAspectRatio > 0) {
Evan Rosky01775072019-09-11 17:28:07 -07006158 final float aspectRatio = Math.max(appWidth, appHeight) / Math.min(appWidth, appHeight);
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006159 if (aspectRatio >= info.maxAspectRatio) {
6160 // The current size has reached the max aspect ratio.
6161 return false;
Riddle Hsuaec55442019-03-12 17:25:35 +08006162 }
6163 }
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006164 if (info.minAspectRatio > 0) {
6165 // The activity should have at least the min aspect ratio, so this checks if the parent
6166 // still has available space to provide larger aspect ratio.
6167 final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
6168 / Math.min(parentAppWidth, parentAppHeight);
6169 if (parentAspectRatio <= info.minAspectRatio) {
6170 // The long side has reached the parent.
6171 return false;
6172 }
6173 }
6174 return true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006175 }
6176
6177 /**
Riddle Hsu0a343c32018-12-21 00:40:48 +08006178 * Indicates the activity will keep the bounds and screen configuration when it was first
6179 * launched, no matter how its parent changes.
6180 *
6181 * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
6182 * aspect ratio.
6183 */
Riddle Hsu74826262019-04-17 14:57:42 +08006184 boolean shouldUseSizeCompatMode() {
Riddle Hsu0a343c32018-12-21 00:40:48 +08006185 return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
6186 // The configuration of non-standard type should be enforced by system.
6187 && isActivityTypeStandard()
6188 && !mAtmService.mForceResizableActivities;
6189 }
6190
Garfield Tane8d84ab2019-10-11 09:49:40 -07006191 boolean hasSizeCompatBounds() {
6192 return mSizeCompatBounds != null;
6193 }
6194
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006195 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006196 private void updateSizeCompatMode() {
6197 if (mCompatDisplayInsets != null || !shouldUseSizeCompatMode()) {
6198 // The override configuration is set only once in size compatibility mode.
6199 return;
6200 }
6201 final Configuration parentConfig = getParent().getConfiguration();
6202 if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
6203 // Don't compute when launching in fullscreen and the fixed orientation is not the
6204 // current orientation. It is more accurately to compute the override bounds from
6205 // the updated configuration after the fixed orientation is applied.
6206 return;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006207 }
Riddle Hsu74826262019-04-17 14:57:42 +08006208
Evan Rosky72f084d2019-09-11 17:05:16 -07006209 Configuration overrideConfig = getRequestedOverrideConfiguration();
6210 final Configuration fullConfig = getConfiguration();
6211
6212 // Ensure the screen related fields are set. It is used to prevent activity relaunch
6213 // when moving between displays. For screenWidthDp and screenWidthDp, because they
6214 // are relative to bounds and density, they will be calculated in
Louis Changcdec0802019-11-11 11:45:07 +08006215 // {@link Task#computeConfigResourceOverrides} and the result will also be
Evan Rosky72f084d2019-09-11 17:05:16 -07006216 // relatively fixed.
6217 overrideConfig.colorMode = fullConfig.colorMode;
6218 overrideConfig.densityDpi = fullConfig.densityDpi;
6219 overrideConfig.screenLayout = fullConfig.screenLayout
6220 & (Configuration.SCREENLAYOUT_LONG_MASK
6221 | Configuration.SCREENLAYOUT_SIZE_MASK);
6222 // The smallest screen width is the short side of screen bounds. Because the bounds
6223 // and density won't be changed, smallestScreenWidthDp is also fixed.
6224 overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
6225 if (info.isFixedOrientation()) {
6226 // lock rotation too. When in size-compat, onConfigurationChanged will watch for and
6227 // apply runtime rotation changes.
6228 overrideConfig.windowConfiguration.setRotation(
6229 fullConfig.windowConfiguration.getRotation());
6230 }
6231
6232 // The role of CompatDisplayInsets is like the override bounds.
6233 final ActivityDisplay display = getDisplay();
6234 if (display != null) {
6235 mCompatDisplayInsets = new CompatDisplayInsets(display.mDisplayContent,
6236 getWindowConfiguration().getBounds(),
6237 getWindowConfiguration().tasksAreFloating());
6238 }
6239 }
6240
6241 private void clearSizeCompatMode() {
6242 mCompatDisplayInsets = null;
6243 onRequestedOverrideConfigurationChanged(EMPTY);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006244 }
6245
Garfield Tan0443b372019-01-04 15:00:13 -08006246 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006247 public boolean matchParentBounds() {
6248 if (super.matchParentBounds()) {
6249 return true;
6250 }
6251 // An activity in size compatibility mode may have override bounds which equals to its
6252 // parent bounds, so the exact bounds should also be checked.
6253 final WindowContainer parent = getParent();
6254 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
6255 }
6256
6257 @Override
6258 float getSizeCompatScale() {
6259 return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
6260 }
6261
6262 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006263 void resolveOverrideConfiguration(Configuration newParentConfiguration) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006264 Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu74826262019-04-17 14:57:42 +08006265 if (mCompatDisplayInsets != null) {
Riddle Hsu04164182019-03-07 18:03:27 +08006266 resolveSizeCompatModeConfiguration(newParentConfiguration);
6267 } else {
6268 super.resolveOverrideConfiguration(newParentConfiguration);
Evan Rosky72f084d2019-09-11 17:05:16 -07006269 applyAspectRatio(resolvedConfig.windowConfiguration.getBounds(),
6270 newParentConfiguration.windowConfiguration.getAppBounds(),
6271 newParentConfiguration.windowConfiguration.getBounds());
Riddle Hsu74826262019-04-17 14:57:42 +08006272 // If the activity has override bounds, the relative configuration (e.g. screen size,
6273 // layout) needs to be resolved according to the bounds.
Evan Rosky72f084d2019-09-11 17:05:16 -07006274 if (task != null && !resolvedConfig.windowConfiguration.getBounds().isEmpty()) {
Riddle Hsu04164182019-03-07 18:03:27 +08006275 task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
Riddle Hsu61987bc2019-04-03 13:08:47 +08006276 newParentConfiguration);
Riddle Hsu04164182019-03-07 18:03:27 +08006277 }
6278 }
Garfield Tan0443b372019-01-04 15:00:13 -08006279
6280 // Assign configuration sequence number into hierarchy because there is a different way than
6281 // ensureActivityConfiguration() in this class that uses configuration in WindowState during
6282 // layout traversals.
6283 mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
6284 getResolvedOverrideConfiguration().seq = mConfigurationSeq;
Riddle Hsu04164182019-03-07 18:03:27 +08006285 }
Riddle Hsu0a343c32018-12-21 00:40:48 +08006286
Riddle Hsu74826262019-04-17 14:57:42 +08006287 /**
6288 * Resolves consistent screen configuration for orientation and rotation changes without
6289 * inheriting the parent bounds.
6290 */
Riddle Hsu04164182019-03-07 18:03:27 +08006291 private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006292 super.resolveOverrideConfiguration(newParentConfiguration);
Riddle Hsu0a343c32018-12-21 00:40:48 +08006293 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu04164182019-03-07 18:03:27 +08006294 final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
Riddle Hsu0a343c32018-12-21 00:40:48 +08006295
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006296 Rect parentBounds = new Rect(newParentConfiguration.windowConfiguration.getBounds());
Riddle Hsu0a343c32018-12-21 00:40:48 +08006297
Evan Rosky72f084d2019-09-11 17:05:16 -07006298 int orientation = getRequestedConfigurationOrientation();
6299 if (orientation == ORIENTATION_UNDEFINED) {
6300 orientation = newParentConfiguration.orientation;
6301 }
6302 int rotation = resolvedConfig.windowConfiguration.getRotation();
6303 if (rotation == ROTATION_UNDEFINED) {
6304 rotation = newParentConfiguration.windowConfiguration.getRotation();
6305 }
6306
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006307 // Use compat insets to lock width and height. We should not use the parent width and height
6308 // because apps in compat mode should have a constant width and height. The compat insets
6309 // are locked when the app is first launched and are never changed after that, so we can
6310 // rely on them to contain the original and unchanging width and height of the app.
6311 final Rect compatDisplayBounds = mTmpBounds;
Evan Rosky72f084d2019-09-11 17:05:16 -07006312 mCompatDisplayInsets.getDisplayBoundsByRotation(compatDisplayBounds, rotation);
6313 final Rect containingAppBounds = new Rect();
6314 mCompatDisplayInsets.getFrameByOrientation(containingAppBounds, orientation);
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006315
Evan Rosky72f084d2019-09-11 17:05:16 -07006316 // Center containingAppBounds horizontally and aligned to top of parent. Both
6317 // are usually the same unless the app was frozen with an orientation letterbox.
6318 int left = compatDisplayBounds.left + compatDisplayBounds.width() / 2
6319 - containingAppBounds.width() / 2;
6320 resolvedBounds.set(left, compatDisplayBounds.top, left + containingAppBounds.width(),
6321 compatDisplayBounds.top + containingAppBounds.height());
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006322
Evan Rosky72f084d2019-09-11 17:05:16 -07006323 if (rotation != ROTATION_UNDEFINED) {
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006324 // Ensure the parent and container bounds won't overlap with insets.
Louis Changcdec0802019-11-11 11:45:07 +08006325 Task.intersectWithInsetsIfFits(containingAppBounds, compatDisplayBounds,
Evan Rosky72f084d2019-09-11 17:05:16 -07006326 mCompatDisplayInsets.mNonDecorInsets[rotation]);
Louis Changcdec0802019-11-11 11:45:07 +08006327 Task.intersectWithInsetsIfFits(parentBounds, compatDisplayBounds,
Evan Rosky72f084d2019-09-11 17:05:16 -07006328 mCompatDisplayInsets.mNonDecorInsets[rotation]);
Riddle Hsu74826262019-04-17 14:57:42 +08006329 }
6330
Evan Rosky72f084d2019-09-11 17:05:16 -07006331 applyAspectRatio(resolvedBounds, containingAppBounds, compatDisplayBounds);
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006332
6333 // Center horizontally in parent and align to top of parent - this is a UX choice
Evan Rosky72f084d2019-09-11 17:05:16 -07006334 left = parentBounds.left + parentBounds.width() / 2 - resolvedBounds.width() / 2;
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006335 resolvedBounds.set(left, parentBounds.top, left + resolvedBounds.width(),
6336 parentBounds.top + resolvedBounds.height());
6337
6338 // We want to get as much of the app on the screen even if insets cover it. This is because
6339 // insets change but an app's bounds are more permanent after launch. After computing insets
6340 // and horizontally centering resolvedBounds, the resolvedBounds may end up outside parent
6341 // bounds. This is okay only if the resolvedBounds exceed their parent on the bottom and
6342 // right, because that is clipped when the final bounds are computed. To reach this state,
6343 // we first try and push the app as much inside the parent towards the top and left (the
6344 // min). The app may then end up outside the parent by going too far left and top, so we
6345 // push it back into the parent by taking the max with parent left and top.
6346 Rect fullParentBounds = newParentConfiguration.windowConfiguration.getBounds();
6347 resolvedBounds.offsetTo(Math.max(fullParentBounds.left,
6348 Math.min(fullParentBounds.right - resolvedBounds.width(), resolvedBounds.left)),
6349 Math.max(fullParentBounds.top,
6350 Math.min(fullParentBounds.bottom - resolvedBounds.height(),
6351 resolvedBounds.top)));
6352
6353 // Use resolvedBounds to compute other override configurations such as appBounds
Riddle Hsu74826262019-04-17 14:57:42 +08006354 task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
6355 mCompatDisplayInsets);
6356
Riddle Hsu04164182019-03-07 18:03:27 +08006357 // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
6358 // the parent bounds appropriately.
6359 if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
6360 resolvedConfig.orientation = newParentConfiguration.orientation;
Riddle Hsu0a343c32018-12-21 00:40:48 +08006361 }
Garfield Tan0443b372019-01-04 15:00:13 -08006362 }
6363
6364 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006365 public Rect getBounds() {
6366 if (mSizeCompatBounds != null) {
6367 return mSizeCompatBounds;
6368 }
6369 return super.getBounds();
6370 }
6371
6372 @Override
6373 Rect getDisplayedBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006374 if (task != null) {
6375 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
6376 if (!overrideDisplayedBounds.isEmpty()) {
6377 return overrideDisplayedBounds;
6378 }
6379 }
6380 return getBounds();
6381 }
6382
6383 @VisibleForTesting
lumark19a5d2e2019-10-11 16:19:30 +08006384 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006385 Rect getAnimationBounds(int appStackClipMode) {
6386 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
6387 // Using the stack bounds here effectively applies the clipping before animation.
6388 return getStack().getBounds();
6389 }
6390 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
6391 // included in the animation.
Louis Changcdec0802019-11-11 11:45:07 +08006392 return task != null ? task.getBounds() : getBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006393 }
6394
6395 /**
6396 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
6397 * region which is available to application.
6398 */
6399 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
6400 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
6401 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
6402 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
6403 final Rect appBounds = getWindowConfiguration().getAppBounds();
6404 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
6405 final float contentW = contentBounds.width();
6406 final float contentH = contentBounds.height();
6407 final float viewportW = viewportBounds.width();
6408 final float viewportH = viewportBounds.height();
6409 // Only allow to scale down.
6410 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
6411 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
6412 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
6413 + viewportBounds.left;
6414
6415 if (mSizeCompatBounds == null) {
6416 mSizeCompatBounds = new Rect();
6417 }
6418 mSizeCompatBounds.set(contentBounds);
6419 mSizeCompatBounds.offsetTo(0, 0);
6420 mSizeCompatBounds.scale(mSizeCompatScale);
6421 // Ensure to align the top with the parent.
6422 mSizeCompatBounds.top = parentBounds.top;
6423 // The decor inset is included in height.
6424 mSizeCompatBounds.bottom += viewportBounds.top;
6425 mSizeCompatBounds.left += offsetX;
6426 mSizeCompatBounds.right += offsetX;
6427 }
6428
6429 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006430 public void onConfigurationChanged(Configuration newParentConfig) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006431 if (mCompatDisplayInsets != null) {
6432 Configuration overrideConfig = getRequestedOverrideConfiguration();
6433 // Adapt to changes in orientation locking. The app is still non-resizable, but
6434 // it can change which orientation is fixed. If the fixed orientation changes,
6435 // update the rotation used on the "compat" display
6436 boolean wasFixedOrient =
6437 overrideConfig.windowConfiguration.getRotation() != ROTATION_UNDEFINED;
6438 int requestedOrient = getRequestedConfigurationOrientation();
6439 if (requestedOrient != ORIENTATION_UNDEFINED
6440 && requestedOrient != getConfiguration().orientation
6441 // The task orientation depends on the top activity orientation, so it
6442 // should match. If it doesn't, just wait until it does.
6443 && requestedOrient == getParent().getConfiguration().orientation
6444 && (overrideConfig.windowConfiguration.getRotation()
6445 != getParent().getWindowConfiguration().getRotation())) {
6446 overrideConfig.windowConfiguration.setRotation(
6447 getParent().getWindowConfiguration().getRotation());
6448 onRequestedOverrideConfigurationChanged(overrideConfig);
6449 return;
6450 } else if (wasFixedOrient && requestedOrient == ORIENTATION_UNDEFINED
6451 && (overrideConfig.windowConfiguration.getRotation()
6452 != ROTATION_UNDEFINED)) {
6453 overrideConfig.windowConfiguration.setRotation(ROTATION_UNDEFINED);
6454 onRequestedOverrideConfigurationChanged(overrideConfig);
6455 return;
6456 }
6457 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07006458 final int prevWinMode = getWindowingMode();
6459 mTmpPrevBounds.set(getBounds());
Garfield Tan0443b372019-01-04 15:00:13 -08006460 super.onConfigurationChanged(newParentConfig);
6461
Garfield Tane8d84ab2019-10-11 09:49:40 -07006462 final Rect overrideBounds = getResolvedOverrideBounds();
6463 if (task != null && !overrideBounds.isEmpty()
6464 // If the changes come from change-listener, the incoming parent configuration is
6465 // still the old one. Make sure their orientations are the same to reduce computing
6466 // the compatibility bounds for the intermediate state.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02006467 && (task.getConfiguration().orientation == newParentConfig.orientation)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006468 final Rect taskBounds = task.getBounds();
6469 // Since we only center the activity horizontally, if only the fixed height is smaller
6470 // than its container, the override bounds don't need to take effect.
6471 if ((overrideBounds.width() != taskBounds.width()
6472 || overrideBounds.height() > taskBounds.height())) {
6473 calculateCompatBoundsTransformation(newParentConfig);
6474 updateSurfacePosition();
6475 } else if (mSizeCompatBounds != null) {
6476 mSizeCompatBounds = null;
6477 mSizeCompatScale = 1f;
6478 updateSurfacePosition();
6479 }
Evan Rosky72f084d2019-09-11 17:05:16 -07006480 } else if (overrideBounds.isEmpty()) {
6481 mSizeCompatBounds = null;
6482 mSizeCompatScale = 1f;
6483 updateSurfacePosition();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006484 }
6485
Hongwei Wange75e1912019-11-07 16:00:32 -08006486 final int newWinMode = getWindowingMode();
6487 if ((prevWinMode != newWinMode) && (mDisplayContent != null)
6488 && shouldStartChangeTransition(prevWinMode, newWinMode)) {
6489 initializeChangeTransition(mTmpPrevBounds);
6490 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07006491
Garfield Tan0443b372019-01-04 15:00:13 -08006492 // Configuration's equality doesn't consider seq so if only seq number changes in resolved
6493 // override configuration. Therefore ConfigurationContainer doesn't change merged override
6494 // configuration, but it's used to push configuration changes so explicitly update that.
6495 if (getMergedOverrideConfiguration().seq != getResolvedOverrideConfiguration().seq) {
6496 onMergedOverrideConfigurationChanged();
6497 }
6498
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006499 final ActivityDisplay display = getDisplay();
Riddle Hsuaec55442019-03-12 17:25:35 +08006500 if (display == null) {
6501 return;
6502 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01006503 if (mVisibleRequested) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006504 // It may toggle the UI for user to restart the size compatibility mode activity.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006505 display.handleActivitySizeCompatModeIfNeeded(this);
Evan Rosky72f084d2019-09-11 17:05:16 -07006506 } else if (mCompatDisplayInsets != null) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006507 // The override changes can only be obtained from display, because we don't have the
6508 // difference of full configuration in each hierarchy.
6509 final int displayChanges = display.getLastOverrideConfigurationChanges();
6510 final int orientationChanges = CONFIG_WINDOW_CONFIGURATION
6511 | CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION;
6512 final boolean hasNonOrienSizeChanged = hasResizeChange(displayChanges)
6513 // Filter out the case of simple orientation change.
6514 && (displayChanges & orientationChanges) != orientationChanges;
6515 // For background activity that uses size compatibility mode, if the size or density of
6516 // the display is changed, then reset the override configuration and kill the activity's
6517 // process if its process state is not important to user.
6518 if (hasNonOrienSizeChanged || (displayChanges & ActivityInfo.CONFIG_DENSITY) != 0) {
6519 restartProcessIfVisible();
6520 }
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006521 }
Garfield Tan0443b372019-01-04 15:00:13 -08006522 }
6523
Hongwei Wange75e1912019-11-07 16:00:32 -08006524 void savePinnedStackBounds() {
6525 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
6526 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
Louis Changdc077272019-11-12 16:52:56 +08006527 final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
Hongwei Wange75e1912019-11-07 16:00:32 -08006528 if (pinnedStack == null) return;
6529 final Rect stackBounds;
6530 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
6531 // We are animating the bounds, use the pre-animation bounds to save the snap
6532 // fraction
6533 stackBounds = pinnedStack.mPreAnimationBounds;
6534 } else {
6535 // We skip the animation if the fullscreen configuration is not compatible, so
6536 // use the current bounds to calculate the saved snap fraction instead
6537 // (see PinnedActivityStack.skipResizeAnimation())
6538 stackBounds = mTmpRect;
6539 pinnedStack.getBounds(stackBounds);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006540 }
Hongwei Wange75e1912019-11-07 16:00:32 -08006541 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
6542 mActivityComponent, stackBounds);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006543 }
6544
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006545 /** Returns true if the configuration is compatible with this activity. */
Wale Ogunwale42f07d92017-05-01 21:32:58 -07006546 boolean isConfigurationCompatible(Configuration config) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006547 final int orientation = getRequestedOrientation();
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006548 if (isFixedOrientationPortrait(orientation)
6549 && config.orientation != ORIENTATION_PORTRAIT) {
6550 return false;
6551 }
6552 if (isFixedOrientationLandscape(orientation)
6553 && config.orientation != ORIENTATION_LANDSCAPE) {
6554 return false;
6555 }
6556 return true;
6557 }
6558
Bryce Lee7566d762017-03-30 09:34:15 -07006559 /**
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006560 * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
6561 * made to outBounds.
Bryce Lee7566d762017-03-30 09:34:15 -07006562 */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006563 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006564 private void applyAspectRatio(Rect outBounds, Rect containingAppBounds,
6565 Rect containingBounds) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006566 final float maxAspectRatio = info.maxAspectRatio;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006567 final ActivityStack stack = getActivityStack();
Adrian Roos917791e2018-11-28 16:30:44 +01006568 final float minAspectRatio = info.minAspectRatio;
6569
Evan Rosky72f084d2019-09-11 17:05:16 -07006570 if (task == null || stack == null || (inMultiWindowMode() && !shouldUseSizeCompatMode())
Adrian Roos917791e2018-11-28 16:30:44 +01006571 || (maxAspectRatio == 0 && minAspectRatio == 0)
Bryce Leee5ab4502017-07-11 08:58:05 -07006572 || isInVrUiMode(getConfiguration())) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006573 // We don't enforce aspect ratio if the activity task is in multiwindow unless it
6574 // is in size-compat mode. We also don't set it if we are in VR mode.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006575 return;
6576 }
6577
Riddle Hsu74826262019-04-17 14:57:42 +08006578 final int containingAppWidth = containingAppBounds.width();
6579 final int containingAppHeight = containingAppBounds.height();
Adrian Roos917791e2018-11-28 16:30:44 +01006580 final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
6581 / (float) Math.min(containingAppWidth, containingAppHeight);
Bryce Lee7566d762017-03-30 09:34:15 -07006582
Adrian Roos917791e2018-11-28 16:30:44 +01006583 int activityWidth = containingAppWidth;
6584 int activityHeight = containingAppHeight;
6585
6586 if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
6587 if (containingAppWidth < containingAppHeight) {
6588 // Width is the shorter side, so we use that to figure-out what the max. height
6589 // should be given the aspect ratio.
6590 activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
6591 } else {
6592 // Height is the shorter side, so we use that to figure-out what the max. width
6593 // should be given the aspect ratio.
6594 activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
6595 }
Tiger Huang3d2b8982019-01-29 22:56:48 +08006596 } else if (containingRatio < minAspectRatio) {
6597 boolean adjustWidth;
6598 switch (getRequestedConfigurationOrientation()) {
6599 case ORIENTATION_LANDSCAPE:
6600 // Width should be the longer side for this landscape app, so we use the width
6601 // to figure-out what the max. height should be given the aspect ratio.
6602 adjustWidth = false;
6603 break;
6604 case ORIENTATION_PORTRAIT:
6605 // Height should be the longer side for this portrait app, so we use the height
6606 // to figure-out what the max. width should be given the aspect ratio.
6607 adjustWidth = true;
6608 break;
6609 default:
6610 // This app doesn't have a preferred orientation, so we keep the length of the
6611 // longer side, and use it to figure-out the length of the shorter side.
6612 if (containingAppWidth < containingAppHeight) {
6613 // Width is the shorter side, so we use the height to figure-out what the
6614 // max. width should be given the aspect ratio.
6615 adjustWidth = true;
6616 } else {
6617 // Height is the shorter side, so we use the width to figure-out what the
6618 // max. height should be given the aspect ratio.
6619 adjustWidth = false;
6620 }
6621 break;
6622 }
6623 if (adjustWidth) {
Adrian Roos917791e2018-11-28 16:30:44 +01006624 activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
6625 } else {
Adrian Roos917791e2018-11-28 16:30:44 +01006626 activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
6627 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006628 }
6629
Adrian Roos917791e2018-11-28 16:30:44 +01006630 if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006631 // The display matches or is less than the activity aspect ratio, so nothing else to do.
6632 return;
6633 }
6634
6635 // Compute configuration based on max supported width and height.
Adrian Roos24be34d2018-05-28 18:55:38 +02006636 // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
Louis Changcdec0802019-11-11 11:45:07 +08006637 // away later in {@link Task#computeConfigResourceOverrides()}. Otherwise, the app
Adrian Roos24be34d2018-05-28 18:55:38 +02006638 // bounds would end up too small.
Evan Rosky72f084d2019-09-11 17:05:16 -07006639 outBounds.set(containingBounds.left, containingBounds.top,
6640 activityWidth + containingAppBounds.left,
Riddle Hsu74826262019-04-17 14:57:42 +08006641 activityHeight + containingAppBounds.top);
Andrii Kulian3a1619d2017-07-07 14:38:09 -07006642 }
6643
Riddle Hsu16567132018-08-16 21:37:47 +08006644 /**
6645 * @return {@code true} if this activity was reparented to another display but
6646 * {@link #ensureActivityConfiguration} is not called.
6647 */
6648 boolean shouldUpdateConfigForDisplayChanged() {
6649 return mLastReportedDisplayId != getDisplayId();
6650 }
6651
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006652 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
6653 return ensureActivityConfiguration(globalChanges, preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006654 false /* ignoreVisibility */);
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006655 }
6656
Andrii Kulian21713ac2016-10-12 22:05:05 -07006657 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006658 * Make sure the given activity matches the current configuration. Ensures the HistoryRecord
6659 * is updated with the correct configuration and all other bookkeeping is handled.
6660 *
6661 * @param globalChanges The changes to the global configuration.
6662 * @param preserveWindow If the activity window should be preserved on screen if the activity
6663 * is relaunched.
Riddle Hsu609a8e22019-06-27 16:46:29 -06006664 * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
6665 * (stopped state). This is useful for the case where we know the
6666 * activity will be visible soon and we want to ensure its configuration
6667 * before we make it visible.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006668 * @return False if the activity was relaunched and true if it wasn't relaunched because we
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006669 * can't or the app handles the specific configuration that is changing.
Andrii Kulian21713ac2016-10-12 22:05:05 -07006670 */
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006671 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006672 boolean ignoreVisibility) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006673 final ActivityStack stack = getActivityStack();
Andrii Kulian21713ac2016-10-12 22:05:05 -07006674 if (stack.mConfigWillChange) {
6675 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6676 "Skipping config check (will change): " + this);
6677 return true;
6678 }
6679
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006680 // We don't worry about activities that are finishing.
6681 if (finishing) {
6682 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6683 "Configuration doesn't matter in finishing " + this);
6684 stopFreezingScreenLocked(false);
6685 return true;
6686 }
6687
Riddle Hsu609a8e22019-06-27 16:46:29 -06006688 if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006689 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006690 "Skipping config check invisible: " + this);
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006691 return true;
6692 }
6693
Andrii Kulian21713ac2016-10-12 22:05:05 -07006694 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6695 "Ensuring correct configuration: " + this);
6696
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006697 final int newDisplayId = getDisplayId();
6698 final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
6699 if (displayChanged) {
6700 mLastReportedDisplayId = newDisplayId;
6701 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006702 // TODO(b/36505427): Is there a better place to do this?
Evan Rosky72f084d2019-09-11 17:05:16 -07006703 updateSizeCompatMode();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006704
Winson Chungbdc646f2017-02-13 12:12:22 -08006705 // Short circuit: if the two full configurations are equal (the common case), then there is
6706 // nothing to do. We test the full configuration instead of the global and merged override
6707 // configurations because there are cases (like moving a task to the pinned stack) where
6708 // the combine configurations are equal, but would otherwise differ in the override config
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006709 mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
6710 if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006711 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006712 "Configuration & display unchanged in " + this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006713 return true;
6714 }
6715
6716 // Okay we now are going to make this activity have the new config.
6717 // But then we need to figure out how it needs to deal with that.
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006718
6719 // Find changes between last reported merged configuration and the current one. This is used
6720 // to decide whether to relaunch an activity or just report a configuration change.
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006721 final int changes = getConfigurationChanges(mTmpConfig);
Ruben Brunkf64af332017-03-22 22:03:25 -07006722
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006723 // Update last reported values.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006724 final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
Bryce Lee8104e7a2017-08-17 09:16:03 -07006725
Andrii Kulianbeadacc2019-05-20 12:18:01 +00006726 setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006727
Bryce Lee7ace3952018-02-16 14:34:32 -08006728 if (mState == INITIALIZING) {
Andrii Kulianb372da62018-01-18 10:46:24 -08006729 // No need to relaunch or schedule new config for activity that hasn't been launched
6730 // yet. We do, however, return after applying the config to activity record, so that
6731 // it will use it for launch transaction.
6732 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6733 "Skipping config check for initializing activity: " + this);
6734 return true;
6735 }
6736
Andrii Kulian21713ac2016-10-12 22:05:05 -07006737 if (changes == 0 && !forceNewConfig) {
6738 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6739 "Configuration no differences in " + this);
6740 // There are no significant differences, so we won't relaunch but should still deliver
6741 // the new configuration to the client process.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006742 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006743 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006744 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006745 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006746 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07006747 return true;
6748 }
6749
6750 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006751 "Configuration changes for " + this + ", allChanges="
Andrii Kulian21713ac2016-10-12 22:05:05 -07006752 + Configuration.configurationDiffToString(changes));
6753
6754 // If the activity isn't currently running, just leave the new configuration and it will
6755 // pick that up next time it starts.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006756 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006757 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6758 "Configuration doesn't matter not running " + this);
6759 stopFreezingScreenLocked(false);
6760 forceNewConfig = false;
6761 return true;
6762 }
6763
6764 // Figure out how to handle the changes between the configurations.
6765 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6766 "Checking to restart " + info.name + ": changed=0x"
6767 + Integer.toHexString(changes) + ", handles=0x"
6768 + Integer.toHexString(info.getRealConfigChanged())
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006769 + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006770
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006771 if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006772 // Aha, the activity isn't handling the change, so DIE DIE DIE.
6773 configChangeFlags |= changes;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006774 startFreezingScreenLocked(globalChanges);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006775 forceNewConfig = false;
6776 preserveWindow &= isResizeOnlyChange(changes);
Garfield Tan2746ab52018-07-25 12:33:01 -07006777 final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
6778 if (hasResizeChange) {
Louis Changcdec0802019-11-11 11:45:07 +08006779 final boolean isDragResizing = task.isDragResizing();
Garfield Tan2746ab52018-07-25 12:33:01 -07006780 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
6781 : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
6782 } else {
6783 mRelaunchReason = RELAUNCH_REASON_NONE;
6784 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006785 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006786 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6787 "Config is destroying non-running " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07006788 destroyImmediately(true /* removeFromApp */, "config");
Bryce Lee7ace3952018-02-16 14:34:32 -08006789 } else if (mState == PAUSING) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006790 // A little annoying: we are waiting for this activity to finish pausing. Let's not
6791 // do anything now, but just flag that it needs to be restarted when done pausing.
6792 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6793 "Config is skipping already pausing " + this);
6794 deferRelaunchUntilPaused = true;
6795 preserveWindowOnDeferredRelaunch = preserveWindow;
6796 return true;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006797 } else {
6798 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006799 "Config is relaunching " + this);
Issei Suzuki1669ea42019-11-06 14:20:59 +01006800 if (DEBUG_STATES && !mVisibleRequested) {
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006801 Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
6802 + " called by " + Debug.getCallers(4));
6803 }
6804 relaunchActivityLocked(preserveWindow);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006805 }
6806
6807 // All done... tell the caller we weren't able to keep this activity around.
6808 return false;
6809 }
6810
6811 // Default case: the activity can handle this new configuration, so hand it over.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006812 // NOTE: We only forward the override configuration as the system level configuration
Andrii Kulian21713ac2016-10-12 22:05:05 -07006813 // changes is always sent to all processes when they happen so it can just use whatever
6814 // system level configuration it last got.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006815 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006816 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006817 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006818 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006819 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07006820 stopFreezingScreenLocked(false);
6821
6822 return true;
6823 }
6824
Zak Cohen90e7116742017-01-29 12:59:23 -08006825 /**
6826 * When assessing a configuration change, decide if the changes flags and the new configurations
6827 * should cause the Activity to relaunch.
Ruben Brunkf64af332017-03-22 22:03:25 -07006828 *
6829 * @param changes the changes due to the given configuration.
6830 * @param changesConfig the configuration that was used to calculate the given changes via a
6831 * call to getConfigurationChanges.
Zak Cohen90e7116742017-01-29 12:59:23 -08006832 */
Ruben Brunkf64af332017-03-22 22:03:25 -07006833 private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
Zak Cohen90e7116742017-01-29 12:59:23 -08006834 int configChanged = info.getRealConfigChanged();
Ruben Brunkf64af332017-03-22 22:03:25 -07006835 boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
Zak Cohen90e7116742017-01-29 12:59:23 -08006836
6837 // Override for apps targeting pre-O sdks
6838 // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
6839 // to the config change.
6840 // For O and later, apps will be required to add configChanges="uimode" to their manifest.
Andrii Kulianeceebbf2019-06-26 17:36:51 -07006841 if (info.applicationInfo.targetSdkVersion < O
Zak Cohen90e7116742017-01-29 12:59:23 -08006842 && requestedVrComponent != null
Ruben Brunkf64af332017-03-22 22:03:25 -07006843 && onlyVrUiModeChanged) {
Zak Cohen90e7116742017-01-29 12:59:23 -08006844 configChanged |= CONFIG_UI_MODE;
6845 }
6846
6847 return (changes&(~configChanged)) != 0;
6848 }
6849
Ruben Brunkf64af332017-03-22 22:03:25 -07006850 /**
6851 * Returns true if the configuration change is solely due to the UI mode switching into or out
6852 * of UI_MODE_TYPE_VR_HEADSET.
6853 */
6854 private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
6855 final Configuration currentConfig = getConfiguration();
Ruben Brunkf53497c2017-03-27 20:26:17 -07006856 return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
Ruben Brunkf64af332017-03-22 22:03:25 -07006857 != isInVrUiMode(lastReportedConfig));
6858 }
6859
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006860 private int getConfigurationChanges(Configuration lastReportedConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006861 // Determine what has changed. May be nothing, if this is a config that has come back from
6862 // the app after going idle. In that case we just want to leave the official config object
6863 // now in the activity and do nothing else.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006864 final Configuration currentConfig = getConfiguration();
6865 int changes = lastReportedConfig.diff(currentConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006866 // We don't want to use size changes if they don't cross boundaries that are important to
6867 // the app.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006868 if ((changes & CONFIG_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006869 final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
6870 currentConfig.screenWidthDp)
6871 || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
6872 currentConfig.screenHeightDp);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006873 if (!crosses) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006874 changes &= ~CONFIG_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006875 }
6876 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006877 if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006878 final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
6879 final int newSmallest = currentConfig.smallestScreenWidthDp;
6880 if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006881 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006882 }
6883 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07006884 // We don't want window configuration to cause relaunches.
6885 if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
6886 changes &= ~CONFIG_WINDOW_CONFIGURATION;
6887 }
Bryce Lee600dadd2017-07-25 10:48:42 -07006888
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006889 return changes;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006890 }
6891
6892 private static boolean isResizeOnlyChange(int change) {
6893 return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
6894 | CONFIG_SCREEN_LAYOUT)) == 0;
6895 }
6896
Garfield Tan2746ab52018-07-25 12:33:01 -07006897 private static boolean hasResizeChange(int change) {
6898 return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
6899 | CONFIG_SCREEN_LAYOUT)) != 0;
6900 }
6901
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006902 void relaunchActivityLocked(boolean preserveWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006903 if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006904 configChangeFlags = 0;
6905 return;
6906 }
6907
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006908 final boolean andResume = shouldBeResumed(null /*activeActivity*/);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006909 List<ResultInfo> pendingResults = null;
6910 List<ReferrerIntent> pendingNewIntents = null;
6911 if (andResume) {
6912 pendingResults = results;
6913 pendingNewIntents = newIntents;
6914 }
6915 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
6916 "Relaunching: " + this + " with results=" + pendingResults
6917 + " newIntents=" + pendingNewIntents + " andResume=" + andResume
6918 + " preserveWindow=" + preserveWindow);
Ruben Brunkf53497c2017-03-27 20:26:17 -07006919 EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006920 : AM_RELAUNCH_ACTIVITY, mUserId, System.identityHashCode(this),
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07006921 task.mTaskId, shortComponentName);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006922
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006923 startFreezingScreenLocked(0);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006924
Andrii Kulian21713ac2016-10-12 22:05:05 -07006925 try {
6926 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
6927 "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
6928 + " callers=" + Debug.getCallers(6));
6929 forceNewConfig = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006930 startRelaunching();
Andrii Kulianb372da62018-01-18 10:46:24 -08006931 final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
6932 pendingNewIntents, configChangeFlags,
Andrii Kulianbeadacc2019-05-20 12:18:01 +00006933 new MergedConfiguration(mAtmService.getGlobalConfiguration(),
Andrii Kulianb372da62018-01-18 10:46:24 -08006934 getMergedOverrideConfiguration()),
6935 preserveWindow);
6936 final ActivityLifecycleItem lifecycleItem;
6937 if (andResume) {
lumark588a3e82018-07-20 18:53:54 +08006938 lifecycleItem = ResumeActivityItem.obtain(
Wale Ogunwale3a256e62018-12-06 14:41:18 -08006939 getDisplay().mDisplayContent.isNextTransitionForward());
Andrii Kulianb372da62018-01-18 10:46:24 -08006940 } else {
Bryce Lee1d0d5142018-04-12 10:35:07 -07006941 lifecycleItem = PauseActivityItem.obtain();
Andrii Kulianb372da62018-01-18 10:46:24 -08006942 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006943 final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
Andrii Kulianb372da62018-01-18 10:46:24 -08006944 transaction.addCallback(callbackItem);
6945 transaction.setLifecycleStateRequest(lifecycleItem);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006946 mAtmService.getLifecycleManager().scheduleTransaction(transaction);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006947 // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
Andrii Kulianb372da62018-01-18 10:46:24 -08006948 // request resume if this activity is currently resumed, which implies we aren't
Andrii Kulian21713ac2016-10-12 22:05:05 -07006949 // sleeping.
6950 } catch (RemoteException e) {
6951 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
6952 }
6953
6954 if (andResume) {
6955 if (DEBUG_STATES) {
6956 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
6957 }
6958 results = null;
6959 newIntents = null;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006960 mAtmService.getAppWarningsLocked().onResumeActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006961 } else {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006962 final ActivityStack stack = getActivityStack();
Wale Ogunwale008163e2018-07-23 23:11:08 -07006963 if (stack != null) {
Andrii Kulian79d67982019-08-19 11:56:16 -07006964 stack.removePauseTimeoutForActivity(this);
Wale Ogunwale008163e2018-07-23 23:11:08 -07006965 }
Bryce Lee7ace3952018-02-16 14:34:32 -08006966 setState(PAUSED, "relaunchActivityLocked");
Andrii Kulian21713ac2016-10-12 22:05:05 -07006967 }
6968
6969 configChangeFlags = 0;
6970 deferRelaunchUntilPaused = false;
6971 preserveWindowOnDeferredRelaunch = false;
6972 }
6973
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006974 /**
6975 * Request the process of the activity to restart with its saved state (from
6976 * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
6977 * the override configuration. Note if the activity is in background, the process will be killed
6978 * directly with keeping its record.
6979 */
6980 void restartProcessIfVisible() {
6981 Slog.i(TAG, "Request to restart process of " + this);
6982
Riddle Hsuaec55442019-03-12 17:25:35 +08006983 // Reset the existing override configuration so it can be updated according to the latest
6984 // configuration.
Evan Rosky72f084d2019-09-11 17:05:16 -07006985 clearSizeCompatMode();
Issei Suzuki1669ea42019-11-06 14:20:59 +01006986 if (mVisibleRequested) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006987 // Configuration will be ensured when becoming visible, so if it is already visible,
6988 // then the manual update is needed.
Evan Rosky72f084d2019-09-11 17:05:16 -07006989 updateSizeCompatMode();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006990 }
6991
6992 if (!attachedToProcess()) {
6993 return;
6994 }
6995
6996 // The restarting state avoids removing this record when process is died.
6997 setState(RESTARTING_PROCESS, "restartActivityProcess");
6998
Issei Suzuki1669ea42019-11-06 14:20:59 +01006999 if (!mVisibleRequested || mHaveState) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007000 // Kill its process immediately because the activity should be in background.
7001 // The activity state will be update to {@link #DESTROYED} in
Andrii Kulian79d67982019-08-19 11:56:16 -07007002 // {@link ActivityStack#cleanUp} when handling process died.
Riddle Hsuaec55442019-03-12 17:25:35 +08007003 mAtmService.mH.post(() -> {
7004 final WindowProcessController wpc;
7005 synchronized (mAtmService.mGlobalLock) {
7006 if (!hasProcess()
7007 || app.getReportedProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
7008 return;
7009 }
7010 wpc = app;
7011 }
7012 mAtmService.mAmInternal.killProcess(wpc.mName, wpc.mUid, "resetConfig");
7013 });
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007014 return;
7015 }
7016
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007017 if (getParent() != null) {
7018 startFreezingScreen();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007019 }
7020 // The process will be killed until the activity reports stopped with saved state (see
7021 // {@link ActivityTaskManagerService.activityStopped}).
7022 try {
7023 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
7024 StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */));
7025 } catch (RemoteException e) {
7026 Slog.w(TAG, "Exception thrown during restart " + this, e);
7027 }
7028 mStackSupervisor.scheduleRestartTimeout(this);
7029 }
7030
Riddle Hsu32dbdca2019-05-17 23:10:16 -06007031 boolean isProcessRunning() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007032 WindowProcessController proc = app;
Jorim Jaggi02886a82016-12-06 09:10:06 -08007033 if (proc == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007034 proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
Jorim Jaggi02886a82016-12-06 09:10:06 -08007035 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007036 return proc != null && proc.hasThread();
Jorim Jaggi02886a82016-12-06 09:10:06 -08007037 }
7038
Jorim Jaggibae01b12017-04-11 16:29:10 -07007039 /**
7040 * @return Whether a task snapshot starting window may be shown.
7041 */
7042 private boolean allowTaskSnapshot() {
7043 if (newIntents == null) {
7044 return true;
7045 }
7046
Louis Chang746c2242019-10-08 16:30:44 +08007047 // Restrict task snapshot starting window to launcher start, or is same as the last
7048 // delivered intent, or there is no intent at all (eg. task being brought to front). If
7049 // the intent is something else, likely the app is going to show some specific page or
7050 // view, instead of what's left last time.
Jorim Jaggibae01b12017-04-11 16:29:10 -07007051 for (int i = newIntents.size() - 1; i >= 0; i--) {
7052 final Intent intent = newIntents.get(i);
Louis Chang746c2242019-10-08 16:30:44 +08007053 if (intent == null || ActivityRecord.isMainIntent(intent)) {
7054 continue;
7055 }
7056
7057 final boolean sameIntent = mLastNewIntent != null ? mLastNewIntent.filterEquals(intent)
7058 : this.intent.filterEquals(intent);
7059 if (!sameIntent || intent.getExtras() != null) {
Jorim Jaggibae01b12017-04-11 16:29:10 -07007060 return false;
7061 }
7062 }
7063 return true;
7064 }
7065
Bryce Leeb7c9b802017-05-02 14:20:24 -07007066 /**
7067 * Returns {@code true} if the associated activity has the no history flag set on it.
7068 * {@code false} otherwise.
7069 */
7070 boolean isNoHistory() {
7071 return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
7072 || (info.flags & FLAG_NO_HISTORY) != 0;
7073 }
7074
Craig Mautner21d24a22014-04-23 11:45:37 -07007075 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
7076 out.attribute(null, ATTR_ID, String.valueOf(createTime));
7077 out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
7078 if (launchedFromPackage != null) {
7079 out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
7080 }
7081 if (resolvedType != null) {
7082 out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
7083 }
7084 out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007085 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
Winson Chung2cb86c72014-06-25 12:03:30 -07007086
Craig Mautner21d24a22014-04-23 11:45:37 -07007087 if (taskDescription != null) {
Craig Mautner648f69b2014-09-18 14:16:26 -07007088 taskDescription.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007089 }
7090
7091 out.startTag(null, TAG_INTENT);
7092 intent.saveToXml(out);
7093 out.endTag(null, TAG_INTENT);
7094
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007095 if (isPersistable() && mPersistentState != null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007096 out.startTag(null, TAG_PERSISTABLEBUNDLE);
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007097 mPersistentState.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007098 out.endTag(null, TAG_PERSISTABLEBUNDLE);
7099 }
7100 }
7101
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07007102 static ActivityRecord restoreFromXml(XmlPullParser in,
7103 ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
Craig Mautner21d24a22014-04-23 11:45:37 -07007104 Intent intent = null;
7105 PersistableBundle persistentState = null;
7106 int launchedFromUid = 0;
7107 String launchedFromPackage = null;
7108 String resolvedType = null;
7109 boolean componentSpecified = false;
7110 int userId = 0;
Craig Mautner21d24a22014-04-23 11:45:37 -07007111 long createTime = -1;
7112 final int outerDepth = in.getDepth();
Winson Chung2cb86c72014-06-25 12:03:30 -07007113 TaskDescription taskDescription = new TaskDescription();
Craig Mautner21d24a22014-04-23 11:45:37 -07007114
7115 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
7116 final String attrName = in.getAttributeName(attrNdx);
7117 final String attrValue = in.getAttributeValue(attrNdx);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007118 if (DEBUG) Slog.d(TaskPersister.TAG,
Wale Ogunwale18795a22014-12-03 11:38:33 -08007119 "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007120 if (ATTR_ID.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01007121 createTime = Long.parseLong(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007122 } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007123 launchedFromUid = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007124 } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
7125 launchedFromPackage = attrValue;
7126 } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
7127 resolvedType = attrValue;
7128 } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
Tobias Thiererb0800dc2016-04-21 17:51:41 +01007129 componentSpecified = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007130 } else if (ATTR_USERID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007131 userId = Integer.parseInt(attrValue);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007132 } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
Craig Mautner648f69b2014-09-18 14:16:26 -07007133 taskDescription.restoreFromXml(attrName, attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007134 } else {
7135 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
7136 }
7137 }
7138
7139 int event;
Ruben Brunkf53497c2017-03-27 20:26:17 -07007140 while (((event = in.next()) != END_DOCUMENT) &&
7141 (event != END_TAG || in.getDepth() >= outerDepth)) {
7142 if (event == START_TAG) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007143 final String name = in.getName();
Ruben Brunkf53497c2017-03-27 20:26:17 -07007144 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007145 Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
Craig Mautner21d24a22014-04-23 11:45:37 -07007146 if (TAG_INTENT.equals(name)) {
7147 intent = Intent.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007148 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007149 Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007150 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
7151 persistentState = PersistableBundle.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007152 if (DEBUG) Slog.d(TaskPersister.TAG,
Craig Mautner21d24a22014-04-23 11:45:37 -07007153 "ActivityRecord: persistentState=" + persistentState);
7154 } else {
7155 Slog.w(TAG, "restoreActivity: unexpected name=" + name);
7156 XmlUtils.skipCurrentTag(in);
7157 }
7158 }
7159 }
7160
7161 if (intent == null) {
Craig Mautnere0129b32014-05-25 16:41:09 -07007162 throw new XmlPullParserException("restoreActivity error intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007163 }
7164
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007165 final ActivityTaskManagerService service = stackSupervisor.mService;
Craig Mautner21d24a22014-04-23 11:45:37 -07007166 final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
Patrick Baumann78380272018-04-04 10:41:01 -07007167 userId, Binder.getCallingUid());
Craig Mautnere0129b32014-05-25 16:41:09 -07007168 if (aInfo == null) {
Craig Mautner77b04262014-06-27 15:22:12 -07007169 throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
7170 " resolvedType=" + resolvedType);
Craig Mautnere0129b32014-05-25 16:41:09 -07007171 }
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007172 final ActivityRecord r = new ActivityRecord(service, null /* caller */,
Andrii Kulianfb1bf692017-01-17 11:17:34 -08007173 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
Wale Ogunwalef6733932018-06-27 05:14:34 -07007174 aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
Andrii Kulianfb1bf692017-01-17 11:17:34 -08007175 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07007176 stackSupervisor, null /* options */, null /* sourceRecord */);
Craig Mautner21d24a22014-04-23 11:45:37 -07007177
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007178 r.mPersistentState = persistentState;
Winson Chung2cb86c72014-06-25 12:03:30 -07007179 r.taskDescription = taskDescription;
Craig Mautner21d24a22014-04-23 11:45:37 -07007180 r.createTime = createTime;
7181
7182 return r;
7183 }
7184
Zak Cohen90e7116742017-01-29 12:59:23 -08007185 private static boolean isInVrUiMode(Configuration config) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07007186 return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
Zak Cohen90e7116742017-01-29 12:59:23 -08007187 }
7188
David Stevens82ea6cb2017-03-03 16:18:50 -08007189 int getUid() {
7190 return info.applicationInfo.uid;
7191 }
7192
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007193 int getPid() {
7194 return app != null ? app.getPid() : 0;
chaviw59b98852017-06-13 12:05:44 -07007195 }
7196
7197 /**
7198 * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
Garfield Tane8d84ab2019-10-11 09:49:40 -07007199 * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007200 * should be visible depending on Keyguard state
chaviw59b98852017-06-13 12:05:44 -07007201 *
7202 * @return true if the screen can be turned on, false otherwise.
7203 */
7204 boolean canTurnScreenOn() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007205 if (!getTurnScreenOnFlag()) {
7206 return false;
7207 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007208 final ActivityStack stack = getActivityStack();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007209 return stack != null &&
chaviw59b98852017-06-13 12:05:44 -07007210 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
7211 }
7212
Garfield Tane8d84ab2019-10-11 09:49:40 -07007213 void setTurnScreenOn(boolean turnScreenOn) {
7214 mTurnScreenOn = turnScreenOn;
7215 }
7216
7217 boolean getTurnScreenOnFlag() {
7218 return mTurnScreenOn;
7219 }
7220
Louis Chang77ce34d2019-01-03 15:45:12 +08007221 /**
7222 * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
7223 * process are allowed to be resumed.
7224 *
7225 * @return true if this activity can be resumed.
7226 */
7227 boolean canResumeByCompat() {
7228 return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
7229 }
7230
chaviw59b98852017-06-13 12:05:44 -07007231 boolean isTopRunningActivity() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08007232 return mRootActivityContainer.topRunningActivity() == this;
chaviw59b98852017-06-13 12:05:44 -07007233 }
7234
Andrii Kulian52d255c2018-07-13 11:32:19 -07007235 /**
7236 * @return {@code true} if this is the resumed activity on its current display, {@code false}
7237 * otherwise.
7238 */
7239 boolean isResumedActivityOnDisplay() {
7240 final ActivityDisplay display = getDisplay();
7241 return display != null && this == display.getResumedActivity();
7242 }
7243
Andrii Kulian39f27442019-06-26 19:09:19 -07007244
7245 /**
7246 * Check if this is the root of the task - first activity that is not finishing, starting from
7247 * the bottom of the task. If all activities are finishing - then this method will return
7248 * {@code true} if the activity is at the bottom.
7249 *
7250 * NOTE: This is different from 'effective root' - an activity that defines the task identity.
7251 */
7252 boolean isRootOfTask() {
7253 if (task == null) {
7254 return false;
7255 }
7256 final ActivityRecord rootActivity = task.getRootActivity();
7257 if (rootActivity != null) {
7258 return this == rootActivity;
7259 }
7260 // No non-finishing activity found. In this case the bottom-most activity is considered to
7261 // be the root.
7262 return task.getChildAt(0) == this;
7263 }
7264
Craig Mautnerf81b90872013-02-26 13:02:43 -08007265 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007267 if (stringName != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07007268 return stringName + " t" + (task == null ? INVALID_TASK_ID : task.mTaskId) +
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007269 (finishing ? " f}" : "") + (mIsExiting ? " mIsExiting=" : "") + "}";
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007270 }
7271 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn30d71892010-12-11 10:37:55 -08007272 sb.append("ActivityRecord{");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007273 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornb12e1352012-09-26 11:39:20 -07007274 sb.append(" u");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007275 sb.append(mUserId);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007276 sb.append(' ');
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007277 sb.append(intent.getComponent().flattenToShortString());
Craig Mautnerf81b90872013-02-26 13:02:43 -08007278 stringName = sb.toString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007279 return stringName;
Steven Timotius4346f0a2017-09-12 11:07:21 -07007280 }
7281
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007282 /**
7283 * Write all fields to an {@code ActivityRecordProto}. This assumes the
7284 * {@code ActivityRecordProto} is the outer-most proto data.
7285 */
7286 void writeToProto(ProtoOutputStream proto) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07007287 writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
Steven Timotius4346f0a2017-09-12 11:07:21 -07007288 writeIdentifierToProto(proto, IDENTIFIER);
Bryce Lee7ace3952018-02-16 14:34:32 -08007289 proto.write(STATE, mState.toString());
Issei Suzuki1669ea42019-11-06 14:20:59 +01007290 proto.write(VISIBLE, mVisibleRequested);
Andrii Kulian39f27442019-06-26 19:09:19 -07007291 proto.write(FRONT_OF_TASK, isRootOfTask());
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007292 if (hasProcess()) {
7293 proto.write(PROC_ID, app.getPid());
Steven Timotius4346f0a2017-09-12 11:07:21 -07007294 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007295 proto.write(TRANSLUCENT, !occludesParent());
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007296 }
7297
7298 public void writeToProto(ProtoOutputStream proto, long fieldId) {
7299 final long token = proto.start(fieldId);
7300 writeToProto(proto);
Steven Timotius4346f0a2017-09-12 11:07:21 -07007301 proto.end(token);
7302 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007303
7304 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -07007305 * Copied from old AppWindowToken.
7306 */
7307 @Override
7308 public void writeToProto(ProtoOutputStream proto, long fieldId,
7309 @WindowTraceLogLevel int logLevel) {
7310 // Critical log level logs only visible elements to mitigate performance overheard
7311 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
7312 return;
7313 }
7314
7315 final long token = proto.start(fieldId);
7316 writeNameToProto(proto, NAME);
7317 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
7318 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
7319 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
lumark9bca6b42019-10-17 18:35:22 +08007320 proto.write(IS_ANIMATING, isAnimating());
Garfield Tane8d84ab2019-10-11 09:49:40 -07007321 if (mThumbnail != null){
7322 mThumbnail.writeToProto(proto, THUMBNAIL);
7323 }
7324 proto.write(FILLS_PARENT, mOccludesParent);
7325 proto.write(APP_STOPPED, mAppStopped);
Issei Suzuki1669ea42019-11-06 14:20:59 +01007326 proto.write(VISIBLE_REQUESTED, mVisibleRequested);
Issei Suzukie63eac72019-11-14 15:59:15 +01007327 proto.write(CLIENT_HIDDEN, mClientHidden);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007328 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
7329 proto.write(REPORTED_DRAWN, reportedDrawn);
7330 proto.write(REPORTED_VISIBLE, reportedVisible);
7331 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
7332 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
7333 proto.write(ALL_DRAWN, allDrawn);
7334 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007335 if (startingWindow != null) {
7336 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
7337 }
7338 proto.write(STARTING_DISPLAYED, startingDisplayed);
7339 proto.write(STARTING_MOVED, startingMoved);
Issei Suzuki7b9e2572019-11-14 16:19:54 +01007340 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
7341 mHiddenSetFromTransferredStartingWindow);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007342 for (Rect bounds : mFrozenBounds) {
7343 bounds.writeToProto(proto, FROZEN_BOUNDS);
7344 }
7345 proto.end(token);
7346 }
7347
7348 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
7349 if (appToken != null) {
7350 proto.write(fieldId, appToken.getName());
7351 }
7352 }
7353
7354 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
7355 final long token = proto.start(fieldId);
7356 proto.write(HASH_CODE, System.identityHashCode(this));
7357 proto.write(USER_ID, mUserId);
7358 proto.write(TITLE, intent.getComponent().flattenToShortString());
7359 proto.end(token);
7360 }
7361
7362 /**
Riddle Hsu61987bc2019-04-03 13:08:47 +08007363 * The precomputed insets of the display in each rotation. This is used to make the size
7364 * compatibility mode activity compute the configuration without relying on its current display.
7365 */
7366 static class CompatDisplayInsets {
Evan Rosky72f084d2019-09-11 17:05:16 -07007367 private final int mDisplayWidth;
7368 private final int mDisplayHeight;
7369 private final int mWidth;
7370 private final int mHeight;
Riddle Hsu61987bc2019-04-03 13:08:47 +08007371
Riddle Hsu74826262019-04-17 14:57:42 +08007372 /**
7373 * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
7374 * is used to compute the appBounds.
7375 */
Riddle Hsu61987bc2019-04-03 13:08:47 +08007376 final Rect[] mNonDecorInsets = new Rect[4];
7377 /**
7378 * The stableInsets for each rotation. Includes the status bar inset and the
7379 * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
7380 * {@link Configuration#screenHeightDp}.
7381 */
7382 final Rect[] mStableInsets = new Rect[4];
7383
Evan Rosky72f084d2019-09-11 17:05:16 -07007384 /**
Louis Changcdec0802019-11-11 11:45:07 +08007385 * Sets bounds to {@link Task} bounds. For apps in freeform, the task bounds are the
Evan Rosky72f084d2019-09-11 17:05:16 -07007386 * parent bounds from the app's perspective. No insets because within a window.
7387 */
7388 CompatDisplayInsets(DisplayContent display, Rect activityBounds, boolean isFloating) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08007389 mDisplayWidth = display.mBaseDisplayWidth;
7390 mDisplayHeight = display.mBaseDisplayHeight;
Evan Rosky72f084d2019-09-11 17:05:16 -07007391 mWidth = activityBounds.width();
7392 mHeight = activityBounds.height();
7393 if (isFloating) {
7394 Rect emptyRect = new Rect();
7395 for (int rotation = 0; rotation < 4; rotation++) {
7396 mNonDecorInsets[rotation] = emptyRect;
7397 mStableInsets[rotation] = emptyRect;
7398 }
7399 return;
7400 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007401 final DisplayPolicy policy = display.getDisplayPolicy();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007402 for (int rotation = 0; rotation < 4; rotation++) {
7403 mNonDecorInsets[rotation] = new Rect();
7404 mStableInsets[rotation] = new Rect();
7405 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7406 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
7407 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
Riddle Hsu74826262019-04-17 14:57:42 +08007408 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
7409 .getDisplayCutout();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007410 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
7411 mStableInsets[rotation].set(mNonDecorInsets[rotation]);
7412 policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
7413 }
7414 }
7415
Riddle Hsu74826262019-04-17 14:57:42 +08007416 void getDisplayBoundsByRotation(Rect outBounds, int rotation) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08007417 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7418 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
7419 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
7420 outBounds.set(0, 0, dw, dh);
7421 }
Riddle Hsu74826262019-04-17 14:57:42 +08007422
Evan Rosky72f084d2019-09-11 17:05:16 -07007423 void getFrameByOrientation(Rect outBounds, int orientation) {
7424 final int longSide = Math.max(mWidth, mHeight);
7425 final int shortSide = Math.min(mWidth, mHeight);
Riddle Hsu74826262019-04-17 14:57:42 +08007426 final boolean isLandscape = orientation == ORIENTATION_LANDSCAPE;
7427 outBounds.set(0, 0, isLandscape ? longSide : shortSide,
7428 isLandscape ? shortSide : longSide);
7429 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007430 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07007431
7432 private static class AppSaturationInfo {
7433 float[] mMatrix = new float[9];
7434 float[] mTranslation = new float[3];
7435
7436 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
7437 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
7438 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
7439 }
7440 }
lumark19a5d2e2019-10-11 16:19:30 +08007441
7442 @Override
7443 RemoteAnimationTarget createRemoteAnimationTarget(
7444 RemoteAnimationController.RemoteAnimationRecord record) {
lumark19a5d2e2019-10-11 16:19:30 +08007445 final WindowState mainWindow = findMainWindow();
7446 if (task == null || mainWindow == null) {
7447 return null;
7448 }
7449 final Rect insets = new Rect();
7450 mainWindow.getContentInsets(insets);
7451 InsetUtils.addInsets(insets, getLetterboxInsets());
7452 return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
7453 record.mAdapter.mCapturedLeash, !task.fillsParent(),
7454 mainWindow.mWinAnimator.mLastClipRect, insets,
7455 getPrefixOrderIndex(), record.mAdapter.mPosition,
7456 record.mAdapter.mStackBounds, task.getWindowConfiguration(),
7457 false /*isNotInRecents*/,
7458 record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
7459 record.mStartBounds);
7460 }
7461
7462 @Override
7463 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
7464 Rect outSurfaceInsets) {
7465 final WindowState win = findMainWindow();
7466 if (win == null) {
7467 return;
7468 }
7469 win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
7470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471}