blob: 521ffa50f869fd23357890b872118cb6b7d462ab [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;
Vishnu Nair9ba31652018-11-13 14:34:05 -080034import static android.app.ActivityTaskManager.INVALID_TASK_ID;
Winson Chung59fda9e2017-01-20 16:14:51 -080035import static android.app.AppOpsManager.MODE_ALLOWED;
Winson Chungf4ac0632017-03-17 12:34:12 -070036import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
Vishnu Nair132ee832018-09-28 15:00:05 -070037import static android.app.WaitResult.INVALID_DELAY;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070038import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
Galia Peycheva480275a2020-03-18 17:33:42 +010039import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070040import 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;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -070044import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070045import static android.app.WindowConfiguration.activityTypeToString;
Ruben Brunkf53497c2017-03-27 20:26:17 -070046import static android.content.Intent.ACTION_MAIN;
47import static android.content.Intent.CATEGORY_HOME;
48import static android.content.Intent.CATEGORY_LAUNCHER;
Chilun2ef71f72018-11-16 17:57:15 +080049import static android.content.Intent.CATEGORY_SECONDARY_HOME;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080050import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Bryce Leeb7c9b802017-05-02 14:20:24 -070051import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY;
Andrii Kulian21713ac2016-10-12 22:05:05 -070052import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
53import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
54import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
55import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
Zak Cohen90e7116742017-01-29 12:59:23 -080056import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
Wale Ogunwale822e5122017-07-26 06:02:24 -070057import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
Garfield Tane8d84ab2019-10-11 09:49:40 -070058import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080059import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
60import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
Garfield Tane8d84ab2019-10-11 09:49:40 -070061import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080062import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020063import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
Chong Zhang87761972016-08-22 13:53:24 -070064import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080065import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
Garfield Tane8d84ab2019-10-11 09:49:40 -070066import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
67import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -080068import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
69import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
Garfield Tane8d84ab2019-10-11 09:49:40 -070070import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Charles He2bf28322017-10-12 22:24:49 +010071import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
72import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
73import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
74import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
Ruben Brunkf53497c2017-03-27 20:26:17 -070075import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
76import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
Wale Ogunwaledf241e92016-10-13 15:14:21 -070077import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Jorim Jaggicd13d332016-04-27 15:40:20 -070078import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -070079import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwaledf241e92016-10-13 15:14:21 -070080import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
Garfield Tane8d84ab2019-10-11 09:49:40 -070081import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
82import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -070083import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
84import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070085import static android.content.res.Configuration.EMPTY;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -070086import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
87import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
Riddle Hsu0a343c32018-12-21 00:40:48 +080088import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
Ruben Brunkf53497c2017-03-27 20:26:17 -070089import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
Zak Cohen90e7116742017-01-29 12:59:23 -080090import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
Garfield Tane8d84ab2019-10-11 09:49:40 -070091import static android.os.Build.VERSION_CODES.HONEYCOMB;
Zak Cohen90e7116742017-01-29 12:59:23 -080092import static android.os.Build.VERSION_CODES.O;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080093import static android.os.Process.SYSTEM_UID;
Garfield Tane8d84ab2019-10-11 09:49:40 -070094import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
95import static android.view.Display.COLOR_MODE_DEFAULT;
Riddle Hsufd4a0502018-10-16 01:05:16 +080096import static android.view.Display.INVALID_DISPLAY;
Riddle Hsu61987bc2019-04-03 13:08:47 +080097import static android.view.Surface.ROTATION_270;
98import static android.view.Surface.ROTATION_90;
Garfield Tane8d84ab2019-10-11 09:49:40 -070099import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
100import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
101import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
102import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
103import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
104import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
105import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700106import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700107import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700108import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700109import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
110import static android.view.WindowManager.TRANSIT_UNSET;
Riddle Hsu16567132018-08-16 21:37:47 +0800111
Garfield Tane8d84ab2019-10-11 09:49:40 -0700112import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
113import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Jeff Changacc340d2019-11-22 14:23:08 +0800114import static com.android.server.wm.ActivityRecordProto.ALL_DRAWN;
115import static com.android.server.wm.ActivityRecordProto.APP_STOPPED;
116import static com.android.server.wm.ActivityRecordProto.CLIENT_VISIBLE;
117import static com.android.server.wm.ActivityRecordProto.DEFER_HIDING_CLIENT;
118import static com.android.server.wm.ActivityRecordProto.FILLS_PARENT;
119import static com.android.server.wm.ActivityRecordProto.FRONT_OF_TASK;
120import static com.android.server.wm.ActivityRecordProto.FROZEN_BOUNDS;
121import static com.android.server.wm.ActivityRecordProto.IDENTIFIER;
122import static com.android.server.wm.ActivityRecordProto.IS_ANIMATING;
123import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
124import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
125import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
126import static com.android.server.wm.ActivityRecordProto.NAME;
127import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
128import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
129import static com.android.server.wm.ActivityRecordProto.PROC_ID;
130import static com.android.server.wm.ActivityRecordProto.REPORTED_DRAWN;
131import static com.android.server.wm.ActivityRecordProto.REPORTED_VISIBLE;
132import static com.android.server.wm.ActivityRecordProto.STARTING_DISPLAYED;
133import static com.android.server.wm.ActivityRecordProto.STARTING_MOVED;
134import static com.android.server.wm.ActivityRecordProto.STARTING_WINDOW;
135import static com.android.server.wm.ActivityRecordProto.STATE;
136import static com.android.server.wm.ActivityRecordProto.THUMBNAIL;
137import static com.android.server.wm.ActivityRecordProto.TRANSLUCENT;
138import static com.android.server.wm.ActivityRecordProto.VISIBLE;
139import static com.android.server.wm.ActivityRecordProto.VISIBLE_REQUESTED;
140import static com.android.server.wm.ActivityRecordProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
141import static com.android.server.wm.ActivityRecordProto.WINDOW_TOKEN;
Hui Yu03d12402018-12-06 18:00:37 -0800142import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
Andrii Kulian79d67982019-08-19 11:56:16 -0700143import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700144import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800145import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
146import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
147import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800148import static com.android.server.wm.ActivityStack.ActivityState.RESTARTING_PROCESS;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800149import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Louis Changeadb22f2019-06-19 12:09:23 +0800150import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800151import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
152import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800153import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -0700154import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
Andrii Kulian79d67982019-08-19 11:56:16 -0700155import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
156import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
Wale Ogunwale59507092018-10-29 09:00:30 -0700157import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700158import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700159import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700160import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
161import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700162import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
163import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
164import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
Jorim Jaggi346702a2019-05-08 17:49:33 +0200165import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700166import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
Wale Ogunwale59507092018-10-29 09:00:30 -0700167import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
Andrii Kulian79d67982019-08-19 11:56:16 -0700168import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
169import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP;
Wale Ogunwale59507092018-10-29 09:00:30 -0700170import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700171import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700172import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700173import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
174import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
Wale Ogunwale59507092018-10-29 09:00:30 -0700175import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
176import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
177import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700178import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
179import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
Wale Ogunwale59507092018-10-29 09:00:30 -0700180import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
181import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
182import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale59507092018-10-29 09:00:30 -0700183import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
184import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
Hui Yu03d12402018-12-06 18:00:37 -0800185import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
Louis Chang746c2242019-10-08 16:30:44 +0800186import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700187import static com.android.server.wm.IdentifierProto.HASH_CODE;
188import static com.android.server.wm.IdentifierProto.TITLE;
189import static com.android.server.wm.IdentifierProto.USER_ID;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200190import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700191import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
192import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
193import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200194import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
195import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100196import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
chaviw9177c772020-03-24 11:35:22 -0700197import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800198import static com.android.server.wm.TaskPersister.DEBUG;
199import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
lumark9bca6b42019-10-17 18:35:22 +0800200import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
201import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
202import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Vishnu Nairdddc9f52020-03-09 09:37:27 -0700203import static com.android.server.wm.WindowContainerChildProto.ACTIVITY;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700204import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
205import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
206import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800207import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700208import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
209import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700210import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
211import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700212import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700213
Ruben Brunkf53497c2017-03-27 20:26:17 -0700214import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
215import static org.xmlpull.v1.XmlPullParser.END_TAG;
216import static org.xmlpull.v1.XmlPullParser.START_TAG;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800217
Andrii Kulian057a6512019-07-15 16:15:51 -0700218import android.annotation.IntDef;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700219import android.annotation.NonNull;
Issei Suzuki74e1eb22018-12-20 17:42:52 +0100220import android.annotation.Nullable;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700221import android.annotation.Size;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700222import android.app.Activity;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700223import android.app.ActivityManager;
Craig Mautner21d24a22014-04-23 11:45:37 -0700224import android.app.ActivityManager.TaskDescription;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -0700225import android.app.ActivityOptions;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800226import android.app.PendingIntent;
Winson Chung709904f2017-04-25 11:00:48 -0700227import android.app.PictureInPictureParams;
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800228import android.app.ResultInfo;
Vishnu Nairbb9ab4b2018-12-13 10:29:46 -0800229import android.app.WaitResult.LaunchState;
Riddle Hsu16567132018-08-16 21:37:47 +0800230import android.app.servertransaction.ActivityConfigurationChangeItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800231import android.app.servertransaction.ActivityLifecycleItem;
232import android.app.servertransaction.ActivityRelaunchItem;
Andrii Kulian79d67982019-08-19 11:56:16 -0700233import android.app.servertransaction.ActivityResultItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800234import android.app.servertransaction.ClientTransaction;
235import android.app.servertransaction.ClientTransactionItem;
Andrii Kulian79d67982019-08-19 11:56:16 -0700236import android.app.servertransaction.DestroyActivityItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700237import android.app.servertransaction.MoveToDisplayItem;
238import android.app.servertransaction.MultiWindowModeChangeItem;
239import android.app.servertransaction.NewIntentItem;
Bryce Lee0bd8d422018-01-09 09:45:57 -0800240import android.app.servertransaction.PauseActivityItem;
Andrii Kulian446e8242017-10-26 15:17:29 -0700241import android.app.servertransaction.PipModeChangeItem;
Andrii Kulianb372da62018-01-18 10:46:24 -0800242import android.app.servertransaction.ResumeActivityItem;
Andrii Kulianb9faa032019-10-17 23:11:54 -0700243import android.app.servertransaction.StartActivityItem;
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800244import android.app.servertransaction.StopActivityItem;
Andrii Kuliand70cdb92019-01-08 15:03:50 -0800245import android.app.servertransaction.TopResumedActivityChangeItem;
Hui Yu03d12402018-12-06 18:00:37 -0800246import android.app.usage.UsageEvents.Event;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247import android.content.ComponentName;
248import android.content.Intent;
249import android.content.pm.ActivityInfo;
250import android.content.pm.ApplicationInfo;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -0700251import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252import android.content.res.Configuration;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700253import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254import android.graphics.Bitmap;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800255import android.graphics.GraphicBuffer;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700256import android.graphics.PixelFormat;
257import android.graphics.Point;
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700258import android.graphics.Rect;
Andrii Kulian79d67982019-08-19 11:56:16 -0700259import android.net.Uri;
Patrick Baumann78380272018-04-04 10:41:01 -0700260import android.os.Binder;
Bryce Lee39791592017-04-26 09:29:12 -0700261import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262import android.os.Bundle;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700263import android.os.Debug;
Dianne Hackbornbe707852011-11-11 14:32:10 -0800264import android.os.IBinder;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800265import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266import android.os.Process;
Dianne Hackborn39792d22010-08-19 18:01:52 -0700267import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268import android.os.SystemClock;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700269import android.os.Trace;
270import android.os.UserHandle;
Bryce Lee8558ec72017-08-17 15:37:26 -0700271import android.os.storage.StorageManager;
Galia Peycheva480275a2020-03-18 17:33:42 +0100272import android.service.dreams.DreamActivity;
273import android.service.dreams.DreamManagerInternal;
Amith Yamasani0af6fa72016-01-17 15:36:19 -0800274import android.service.voice.IVoiceInteractionSession;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700275import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276import android.util.EventLog;
277import android.util.Log;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700278import android.util.MergedConfiguration;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700279import android.util.Slog;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700280import android.util.TimeUtils;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700281import android.util.proto.ProtoOutputStream;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800282import android.view.AppTransitionAnimationSpec;
Riddle Hsu61987bc2019-04-03 13:08:47 +0800283import android.view.DisplayCutout;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700284import android.view.DisplayInfo;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800285import android.view.IAppTransitionAnimationSpecsFuture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286import android.view.IApplicationToken;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700287import android.view.InputApplicationHandle;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700288import android.view.RemoteAnimationDefinition;
lumark19a5d2e2019-10-11 16:19:30 +0800289import android.view.RemoteAnimationTarget;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700290import android.view.SurfaceControl;
291import android.view.SurfaceControl.Transaction;
292import android.view.WindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +0200293import android.view.WindowManager.LayoutParams;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700294import android.view.animation.Animation;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700295
lumark9bca6b42019-10-17 18:35:22 +0800296import com.android.internal.R;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800297import com.android.internal.annotations.VisibleForTesting;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800298import com.android.internal.app.ResolverActivity;
299import com.android.internal.content.ReferrerIntent;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700300import com.android.internal.util.ToBooleanFunction;
Filip Gruszczynski3d026712015-12-16 13:46:38 -0800301import com.android.internal.util.XmlUtils;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800302import com.android.internal.util.function.pooled.PooledConsumer;
303import com.android.internal.util.function.pooled.PooledFunction;
304import com.android.internal.util.function.pooled.PooledLambda;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700305import com.android.server.AttributeCache;
306import com.android.server.LocalServices;
Wale Ogunwale59507092018-10-29 09:00:30 -0700307import com.android.server.am.AppTimeTracker;
308import com.android.server.am.PendingIntentRecord;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700309import com.android.server.display.color.ColorDisplayService;
310import com.android.server.policy.WindowManagerPolicy;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200311import com.android.server.protolog.common.ProtoLog;
Vishnu Nair9ba31652018-11-13 14:34:05 -0800312import com.android.server.uri.UriPermissionOwner;
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800313import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
Wale Ogunwale59507092018-10-29 09:00:30 -0700314import com.android.server.wm.ActivityStack.ActivityState;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100315import com.android.server.wm.SurfaceAnimator.AnimationType;
316import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700317import com.android.server.wm.WindowManagerService.H;
lumark19a5d2e2019-10-11 16:19:30 +0800318import com.android.server.wm.utils.InsetUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319
Andrii Kuliande93eff2019-07-12 12:21:27 -0700320import com.google.android.collect.Sets;
321
Jorim Jaggi02886a82016-12-06 09:10:06 -0800322import org.xmlpull.v1.XmlPullParser;
323import org.xmlpull.v1.XmlPullParserException;
324import org.xmlpull.v1.XmlSerializer;
325
Suprabh Shukla23593142015-11-03 17:31:15 -0800326import java.io.File;
Craig Mautner21d24a22014-04-23 11:45:37 -0700327import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328import java.io.PrintWriter;
329import java.lang.ref.WeakReference;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700330import java.util.ArrayDeque;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331import java.util.ArrayList;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800332import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333import java.util.HashSet;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700334import java.util.List;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700335import java.util.Objects;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800336import java.util.function.Consumer;
337import java.util.function.Function;
338import java.util.function.Predicate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339
340/**
341 * An entry in the history stack, representing an activity.
342 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700343final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
Wale Ogunwale98875612018-10-12 07:53:02 -0700344 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
Andrii Kulian79d67982019-08-19 11:56:16 -0700345 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
346 private static final String TAG_APP = TAG + POSTFIX_APP;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700347 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700348 private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
349 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
350 private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
351 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700352 private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700353 private static final String TAG_STATES = TAG + POSTFIX_STATES;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700354 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
Andrii Kuliande93eff2019-07-12 12:21:27 -0700355 private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
356 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
Andrii Kulian21713ac2016-10-12 22:05:05 -0700357 private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800358
Craig Mautner21d24a22014-04-23 11:45:37 -0700359 private static final String ATTR_ID = "id";
360 private static final String TAG_INTENT = "intent";
361 private static final String ATTR_USERID = "user_id";
362 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
363 private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700364 private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
Philip P. Moltmannee295092020-02-10 08:46:26 -0800365 private static final String ATTR_LAUNCHEDFROMFEATURE = "launched_from_feature";
Craig Mautner21d24a22014-04-23 11:45:37 -0700366 private static final String ATTR_RESOLVEDTYPE = "resolved_type";
367 private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
Dianne Hackborn337abb32014-09-24 12:44:29 -0700368 static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
Craig Mautner21d24a22014-04-23 11:45:37 -0700369
Andrii Kulian79d67982019-08-19 11:56:16 -0700370 // How many activities have to be scheduled to stop to force a stop pass.
371 private static final int MAX_STOPPING_TO_FORCE = 3;
372
Garfield Tane8d84ab2019-10-11 09:49:40 -0700373 private static final int STARTING_WINDOW_TYPE_NONE = 0;
374 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
375 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
376
377 /**
378 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
379 */
380 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Vishnu Nair19479df2019-10-30 08:03:15 -0700381 static final int INVALID_PID = -1;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700382
Wale Ogunwale196db712019-12-27 15:35:39 +0000383 // How long we wait until giving up on the last activity to pause. This
384 // is short because it directly impacts the responsiveness of starting the
385 // next activity.
386 private static final int PAUSE_TIMEOUT = 500;
387
388 // Ticks during which we check progress while waiting for an app to launch.
389 private static final int LAUNCH_TICK = 500;
390
391 // How long we wait for the activity to tell us it has stopped before
392 // giving up. This is a good amount of time because we really need this
393 // from the application in order to get its saved state. Once the stop
394 // is complete we may start destroying client resources triggering
395 // crashes if the UI thread was hung. We put this timeout one second behind
396 // the ANR timeout so these situations will generate ANR instead of
397 // Surface lost or other errors.
398 private static final int STOP_TIMEOUT = 11 * 1000;
399
400 // How long we wait until giving up on an activity telling us it has
401 // finished destroying itself.
402 private static final int DESTROY_TIMEOUT = 10 * 1000;
403
Garfield Tane8d84ab2019-10-11 09:49:40 -0700404 final ActivityTaskManagerService mAtmService;
Andrii Kulianeceebbf2019-06-26 17:36:51 -0700405 final ActivityInfo info; // activity info provided by developer in AndroidManifest
Garfield Tane8d84ab2019-10-11 09:49:40 -0700406 // Non-null only for application tokens.
407 // TODO: rename to mActivityToken
408 final ActivityRecord.Token appToken;
409 // Which user is this running for?
410 final int mUserId;
411 // The package implementing intent's component
412 // TODO: rename to mPackageName
413 final String packageName;
414 // the intent component, or target of an alias.
415 final ComponentName mActivityComponent;
416 // Has a wallpaper window as a background.
417 // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
418 // mOccludesParent field.
419 final boolean hasWallpaper;
420 // Input application handle used by the input dispatcher.
421 final InputApplicationHandle mInputApplicationHandle;
422
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800423 final int launchedFromPid; // always the pid who started the activity.
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700424 final int launchedFromUid; // always the uid who started the activity.
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800425 final String launchedFromPackage; // always the package who started the activity.
Philip P. Moltmannee295092020-02-10 08:46:26 -0800426 final @Nullable String launchedFromFeatureId; // always the feature in launchedFromPackage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 final Intent intent; // the original intent that generated us
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 final String shortComponentName; // the short component name of the intent
429 final String resolvedType; // as per original caller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 final String processName; // process where this component wants to run
431 final String taskAffinity; // as per ActivityInfo.taskAffinity
432 final boolean stateNotNeeded; // As per ActivityInfo.flags
Louis Changd58cb672018-12-24 17:45:16 +0800433 @VisibleForTesting
434 int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800435 private final boolean componentSpecified; // did caller specify an explicit component?
Dianne Hackbornfb81d092015-08-03 17:14:46 -0700436 final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?
Craig Mautner86d67a42013-05-14 10:34:38 -0700437
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800438 private CharSequence nonLocalizedLabel; // the label information from the package mgr.
439 private int labelRes; // the label information from the package mgr.
440 private int icon; // resource identifier of activity's icon.
441 private int logo; // resource identifier of activity's logo.
442 private int theme; // resource identifier of activity's theme.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800443 private int windowFlags; // custom window flags for preview window.
Louis Changcdec0802019-11-11 11:45:07 +0800444 private Task task; // the task this is in.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800445 private long createTime = System.currentTimeMillis();
Andrii Kulian86e70fc2019-02-12 11:04:10 +0000446 long lastVisibleTime; // last time this activity became visible
447 long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
448 long pauseTime; // last time we started pausing the activity
449 long launchTickTime; // base time for launch tick messages
450 long topResumedStateLossTime; // last time we reported top resumed state loss to an activity
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700451 // Last configuration reported to the activity in the client process.
452 private MergedConfiguration mLastReportedConfiguration;
Andrii Kulianb047b8b2017-02-08 18:38:26 -0800453 private int mLastReportedDisplayId;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200454 boolean mLastReportedMultiWindowMode;
455 boolean mLastReportedPictureInPictureMode;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -0700456 CompatibilityInfo compat;// last used compatibility mode
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700457 ActivityRecord resultTo; // who started this entry, so will get our reply
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 final String resultWho; // additional identifier for use by resultTo.
459 final int requestCode; // code given by requester (resultTo)
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800460 ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
Dianne Hackborn85d558c2014-11-04 10:31:54 -0800462 ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
Louis Chang746c2242019-10-08 16:30:44 +0800463 Intent mLastNewIntent; // the last new intent we delivered to client
Dianne Hackborn7a2195c2012-03-19 17:38:00 -0700464 ActivityOptions pendingOptions; // most recently given options
George Mount6ba042b2014-07-28 11:12:28 -0700465 ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
Dianne Hackbornb5a380d2015-05-20 18:18:46 -0700466 AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
Wale Ogunwalec4e63a42018-10-02 13:19:54 -0700467 ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
Dianne Hackborn7e269642010-08-25 19:50:20 -0700468 UriPermissionOwner uriPermissions; // current special URI access perms.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700469 WindowProcessController app; // if non-null, hosting application
Bryce Lee7ace3952018-02-16 14:34:32 -0800470 private ActivityState mState; // current state we are in
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700471 private Bundle mIcicle; // last saved activity state
472 private PersistableBundle mPersistentState; // last persistently saved activity state
473 private boolean mHaveState = true; // Indicates whether the last saved state of activity is
474 // preserved. This starts out 'true', since the initial state
475 // of an activity is that we have everything, and we should
476 // never consider it lacking in state to be removed if it
477 // dies. After an activity is launched it follows the value
478 // of #mIcicle.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 boolean launchFailed; // set if a launched failed, to abort on 2nd try
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 boolean stopped; // is activity pause finished?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700481 boolean delayedResume; // not yet resumed because of stopped app switches?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 boolean finishing; // activity in pending finish list?
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800483 boolean deferRelaunchUntilPaused; // relaunch of activity is being deferred until pause is
484 // completed
485 boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 int configChangeFlags; // which config values have changed
Wale Ogunwaleec950642017-04-25 07:44:21 -0700487 private boolean keysPaused; // has key dispatching been paused for it?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 int launchMode; // the launch mode activity attribute.
Charles He2bf28322017-10-12 22:24:49 +0100489 int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
Issei Suzukif2f6c912019-11-08 11:24:18 +0100490 private boolean mVisible; // Should this token's windows be visible?
Jorim Jaggi241ae102016-11-02 21:57:33 -0700491 boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
492 // might hide this activity?
Issei Suzukid4ee1cc2019-11-08 13:20:14 +0100493 // True if the visible state of this token was forced to true due to a transferred starting
Garfield Tane8d84ab2019-10-11 09:49:40 -0700494 // window.
Issei Suzukif2f6c912019-11-08 11:24:18 +0100495 private boolean mVisibleSetFromTransferredStartingWindow;
496 // TODO: figure out how to consolidate with the same variable in ActivityRecord.
Wale Ogunwaleec950642017-04-25 07:44:21 -0700497 private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
498 // process that it is hidden.
Issei Suzukid4ee1cc2019-11-08 13:20:14 +0100499 private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false
Garfield Tane8d84ab2019-10-11 09:49:40 -0700500 // and reporting to the client that it is hidden.
Andrii Kulian46799182019-10-17 16:26:17 -0700501 private boolean mSetToSleep; // have we told the activity to sleep?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 boolean nowVisible; // is this activity's window visible?
Vishnu Nair9ba31652018-11-13 14:34:05 -0800503 boolean mDrawn; // is this activity's window drawn?
Andrii Kuliana39ae3e2018-05-31 12:43:54 -0700504 boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 boolean idle; // has the activity gone idle?
506 boolean hasBeenLaunched;// has this activity ever been launched?
507 boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
Daniel Sandler69a48172010-06-23 16:29:36 -0400508 boolean immersive; // immersive mode (don't interrupt if possible)
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400509 boolean forceNewConfig; // force re-create with new config next time
Winson Chungf7e03e12017-08-22 11:32:16 -0700510 boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the
511 // activity can enter picture in picture while pausing (only when switching to another task)
Winson Chung709904f2017-04-25 11:00:48 -0700512 PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();
513 // The PiP params used when deferring the entering of picture-in-picture.
Dianne Hackborn07981492013-01-28 11:36:23 -0800514 int launchCount; // count of launches since last state
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800515 long lastLaunchTime; // time of last launch of this activity
Ruben Brunke24b9a62016-02-16 21:38:24 -0800516 ComponentName requestedVrComponent; // the requested component for handling VR mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200518 boolean inHistory; // are we in the history stack?
Craig Mautnerde4ef022013-04-07 19:01:33 -0700519 final ActivityStackSupervisor mStackSupervisor;
Louis Chang149d5c82019-12-30 09:47:39 +0800520 final RootWindowContainer mRootWindowContainer;
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800521
522 static final int STARTING_WINDOW_NOT_SHOWN = 0;
523 static final int STARTING_WINDOW_SHOWN = 1;
524 static final int STARTING_WINDOW_REMOVED = 2;
525 int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800526 private boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800527
Garfield Tan2746ab52018-07-25 12:33:01 -0700528 // Marking the reason why this activity is being relaunched. Mainly used to track that this
529 // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
530 // pre-NYC apps that don't have a sense of being resized.
531 int mRelaunchReason = RELAUNCH_REASON_NONE;
532
Craig Mautner21d24a22014-04-23 11:45:37 -0700533 TaskDescription taskDescription; // the recents information for this activity
Craig Mautner2fbd7542014-03-21 09:34:07 -0700534
Filip Gruszczynski23493322015-07-29 17:02:59 -0700535 // These configurations are collected from application's resources based on size-sensitive
536 // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
537 // and drawable-sw400dp will be added to both as 400.
538 private int[] mVerticalSizeConfigurations;
539 private int[] mHorizontalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -0700540 private int[] mSmallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -0700541
Riddle Hsu61987bc2019-04-03 13:08:47 +0800542 /**
543 * The precomputed display insets for resolving configuration. It will be non-null if
544 * {@link #shouldUseSizeCompatMode} returns {@code true}.
545 */
546 private CompatDisplayInsets mCompatDisplayInsets;
547
Amith Yamasani0af6fa72016-01-17 15:36:19 -0800548 boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session
549 IVoiceInteractionSession voiceSession; // Voice interaction session for this activity
550
Garfield Tane8d84ab2019-10-11 09:49:40 -0700551 boolean mVoiceInteraction;
552
553 private int mPendingRelaunchCount;
554
555 // True if we are current in the process of removing this app token from the display
556 private boolean mRemovingFromDisplay = false;
557
Garfield Tane8d84ab2019-10-11 09:49:40 -0700558 private RemoteAnimationDefinition mRemoteAnimationDefinition;
559
lumark5341d1c2019-12-14 01:54:02 +0800560 AnimatingActivityRegistry mAnimatingActivityRegistry;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700561
562 private Task mLastParent;
563
Issei Suzukid4ee1cc2019-11-08 13:20:14 +0100564 // Have we told the window clients to show themselves?
565 private boolean mClientVisible;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700566
567 boolean firstWindowDrawn;
568 // Last drawn state we reported to the app token.
569 private boolean reportedDrawn;
570 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
571 new WindowState.UpdateReportedVisibilityResults();
572
Issei Suzuki2bcbd682019-11-08 13:20:14 +0100573 boolean mUseTransferredAnimation;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700574
575 /**
576 * @see #currentLaunchCanTurnScreenOn()
577 */
578 private boolean mCurrentLaunchCanTurnScreenOn = true;
579
Garfield Tane8d84ab2019-10-11 09:49:40 -0700580 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
581 private boolean mLastSurfaceShowing = true;
582
583 private Letterbox mLetterbox;
584
585 /**
586 * The activity is opaque and fills the entire space of this task.
587 * @see WindowContainer#fillsParent()
588 */
589 private boolean mOccludesParent;
590
591 // The input dispatching timeout for this application token in nanoseconds.
592 long mInputDispatchingTimeoutNanos;
593
594 private boolean mShowWhenLocked;
595 private boolean mInheritShownWhenLocked;
596 private boolean mTurnScreenOn;
597
598 /** Have we been asked to have this token keep the screen frozen? */
599 private boolean mFreezingScreen;
600
601 // These are used for determining when all windows associated with
602 // an activity have been drawn, so they can be made visible together
603 // at the same time.
604 // initialize so that it doesn't match mTransactionSequence which is an int.
605 private long mLastTransactionSequence = Long.MIN_VALUE;
606 private int mNumInterestingWindows;
607 private int mNumDrawnWindows;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700608 boolean allDrawn;
609 private boolean mLastAllDrawn;
610
611 private boolean mLastContainsShowWhenLockedWindow;
612 private boolean mLastContainsDismissKeyguardWindow;
Andrii Kulian46799182019-10-17 16:26:17 -0700613 private boolean mLastContainsTurnScreenOnWindow;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700614
615 /**
616 * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
617 * to help AR know that the app is in the process of closing but hasn't yet started closing on
618 * the WM side.
619 */
620 private boolean mWillCloseOrEnterPip;
621
622 /**
623 * The scale to fit at least one side of the activity to its parent. If the activity uses
624 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
625 */
626 private float mSizeCompatScale = 1f;
627 /**
628 * The bounds in global coordinates for activity in size compatibility mode.
629 * @see ActivityRecord#hasSizeCompatBounds()
630 */
631 private Rect mSizeCompatBounds;
632
633 // activity is not displayed?
634 // TODO: rename to mNoDisplay
635 @VisibleForTesting
636 boolean noDisplay;
637 boolean mShowForAllUsers;
638 // TODO: Make this final
639 int mTargetSdk;
640
Issei Suzuki1669ea42019-11-06 14:20:59 +0100641 // Is this window's surface needed? This is almost like visible, except
642 // it will sometimes be true a little earlier: when the activity record has
Garfield Tane8d84ab2019-10-11 09:49:40 -0700643 // been shown, but is still waiting for its app transition to execute
644 // before making its windows shown.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100645 boolean mVisibleRequested;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700646
647 // Last visibility state we reported to the app token.
648 boolean reportedVisible;
649
Garfield Tane8d84ab2019-10-11 09:49:40 -0700650 boolean mDisablePreviewScreenshots;
651
652 // Information about an application starting window if displayed.
653 // Note: these are de-referenced before the starting window animates away.
654 StartingData mStartingData;
655 WindowState startingWindow;
656 WindowManagerPolicy.StartingSurface startingSurface;
657 boolean startingDisplayed;
658 boolean startingMoved;
659
660 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
661 boolean mIsExiting;
662
Garfield Tane8d84ab2019-10-11 09:49:40 -0700663 boolean mEnteringAnimation;
664
665 boolean mAppStopped;
666 // A hint to override the window specified rotation animation, or -1 to use the window specified
667 // value. We use this so that we can select the right animation in the cases of starting
668 // windows, where the app hasn't had time to set a value on the window.
669 int mRotationAnimationHint = -1;
670
671 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
672 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
673
Garfield Tane8d84ab2019-10-11 09:49:40 -0700674 private AppSaturationInfo mLastAppSaturationInfo;
675
676 private final ColorDisplayService.ColorTransformController mColorTransformController =
677 (matrix, translation) -> mWmService.mH.post(() -> {
678 synchronized (mWmService.mGlobalLock) {
679 if (mLastAppSaturationInfo == null) {
680 mLastAppSaturationInfo = new AppSaturationInfo();
681 }
682
683 mLastAppSaturationInfo.setSaturation(matrix, translation);
684 updateColorTransform();
685 }
686 });
687
Andrii Kulian21713ac2016-10-12 22:05:05 -0700688 /**
Garfield Tan0443b372019-01-04 15:00:13 -0800689 * Current sequencing integer of the configuration, for skipping old activity configurations.
690 */
691 private int mConfigurationSeq;
692
693 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800694 * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}
Andrii Kulian21713ac2016-10-12 22:05:05 -0700695 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700696 private final Configuration mTmpConfig = new Configuration();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700697 private final Rect mTmpBounds = new Rect();
Andrii Kulian21713ac2016-10-12 22:05:05 -0700698
Sunny Goyald40c3452019-03-20 12:46:55 -0700699 // Token for targeting this activity for assist purposes.
700 final Binder assistToken = new Binder();
701
Wale Ogunwale196db712019-12-27 15:35:39 +0000702 private final Runnable mPauseTimeoutRunnable = new Runnable() {
703 @Override
704 public void run() {
705 // We don't at this point know if the activity is fullscreen,
706 // so we need to be conservative and assume it isn't.
707 Slog.w(TAG, "Activity pause timeout for " + ActivityRecord.this);
708 synchronized (mAtmService.mGlobalLock) {
709 if (hasProcess()) {
710 mAtmService.logAppTooSlow(app, pauseTime, "pausing " + ActivityRecord.this);
711 }
712 activityPaused(true);
713 }
714 }
715 };
716
717 private final Runnable mLaunchTickRunnable = new Runnable() {
718 @Override
719 public void run() {
720 synchronized (mAtmService.mGlobalLock) {
721 if (continueLaunchTicking()) {
722 mAtmService.logAppTooSlow(
723 app, launchTickTime, "launching " + ActivityRecord.this);
724 }
725 }
726 }
727 };
728
729 private final Runnable mDestroyTimeoutRunnable = new Runnable() {
730 @Override
731 public void run() {
732 synchronized (mAtmService.mGlobalLock) {
733 Slog.w(TAG, "Activity destroy timeout for " + ActivityRecord.this);
734 destroyed("destroyTimeout");
735 }
736 }
737 };
738
739 private final Runnable mStopTimeoutRunnable = new Runnable() {
740 @Override
741 public void run() {
742 synchronized (mAtmService.mGlobalLock) {
743 Slog.w(TAG, "Activity stop timeout for " + ActivityRecord.this);
744 if (isInHistory()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800745 activityStopped(
746 null /*icicle*/, null /*persistentState*/, null /*description*/);
Wale Ogunwale196db712019-12-27 15:35:39 +0000747 }
748 }
749 }
750 };
751
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800752 private static String startingWindowStateToString(int state) {
753 switch (state) {
754 case STARTING_WINDOW_NOT_SHOWN:
755 return "STARTING_WINDOW_NOT_SHOWN";
756 case STARTING_WINDOW_SHOWN:
757 return "STARTING_WINDOW_SHOWN";
758 case STARTING_WINDOW_REMOVED:
759 return "STARTING_WINDOW_REMOVED";
760 default:
761 return "unknown state=" + state;
762 }
763 }
764
Garfield Tane8d84ab2019-10-11 09:49:40 -0700765 @Override
766 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700767 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700768 pw.print(prefix); pw.print("packageName="); pw.print(packageName);
769 pw.print(" processName="); pw.println(processName);
770 pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
Craig Mautnere11f2b72013-04-01 12:37:17 -0700771 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -0800772 pw.print(" launchedFromFeature="); pw.print(launchedFromFeatureId);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800773 pw.print(" userId="); pw.println(mUserId);
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800774 pw.print(prefix); pw.print("app="); pw.println(app);
Hui Yu6d5c3b92019-10-22 15:35:53 -0700775 pw.print(prefix); pw.println(intent.toInsecureString());
Andrii Kulian39f27442019-06-26 19:09:19 -0700776 pw.print(prefix); pw.print("rootOfTask="); pw.print(isRootOfTask());
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700777 pw.print(" task="); pw.println(task);
778 pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800779 pw.print(prefix); pw.print("mActivityComponent=");
780 pw.println(mActivityComponent.flattenToShortString());
Andrii Kulianeceebbf2019-06-26 17:36:51 -0700781 if (info != null && info.applicationInfo != null) {
782 final ApplicationInfo appInfo = info.applicationInfo;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700783 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
784 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
785 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
786 }
787 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800788 if (appInfo.splitSourceDirs != null) {
789 pw.print(prefix); pw.print("splitDir=");
790 pw.println(Arrays.toString(appInfo.splitSourceDirs));
791 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800792 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700793 pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
794 pw.print(" componentSpecified="); pw.print(componentSpecified);
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700795 pw.print(" mActivityType="); pw.println(
796 activityTypeToString(getActivityType()));
Dianne Hackbornfb81d092015-08-03 17:14:46 -0700797 if (rootVoiceInteraction) {
798 pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
799 }
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800800 pw.print(prefix); pw.print("compat="); pw.print(compat);
801 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
802 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
803 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
Wale Ogunwalee610d3d2017-04-25 10:23:48 -0700804 pw.println(prefix + "mLastReportedConfigurations:");
805 mLastReportedConfiguration.dump(pw, prefix + " ");
806
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700807 pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
Evan Roskydfe3da72018-10-26 17:21:06 -0700808 if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
809 pw.println(prefix + "RequestedOverrideConfiguration="
810 + getRequestedOverrideConfiguration());
811 }
812 if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
813 pw.println(prefix + "ResolvedOverrideConfiguration="
814 + getResolvedOverrideConfiguration());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700815 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800816 if (!matchParentBounds()) {
817 pw.println(prefix + "bounds=" + getBounds());
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700818 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700819 if (resultTo != null || resultWho != null) {
820 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
821 pw.print(" resultWho="); pw.print(resultWho);
822 pw.print(" resultCode="); pw.println(requestCode);
823 }
Craig Mautner29c58ca2014-10-14 16:17:06 -0700824 if (taskDescription != null) {
825 final String iconFilename = taskDescription.getIconFilename();
826 if (iconFilename != null || taskDescription.getLabel() != null ||
827 taskDescription.getPrimaryColor() != 0) {
828 pw.print(prefix); pw.print("taskDescription:");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700829 pw.print(" label=\""); pw.print(taskDescription.getLabel());
830 pw.print("\"");
Matthew Ng54bc9422017-10-02 17:16:28 -0700831 pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
832 ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
833 : "null");
Winson Chungd6722032020-02-18 15:16:08 -0800834 pw.print(" iconResource=");
835 pw.print(taskDescription.getIconResourcePackage());
836 pw.print("/");
837 pw.print(taskDescription.getIconResource());
Matthew Ng54bc9422017-10-02 17:16:28 -0700838 pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200839 pw.print(" primaryColor=");
Craig Mautner29c58ca2014-10-14 16:17:06 -0700840 pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
Wale Ogunwale822e5122017-07-26 06:02:24 -0700841 pw.print(prefix + " backgroundColor=");
Riddle Hsud8bdc452019-12-06 21:36:32 +0800842 pw.print(Integer.toHexString(taskDescription.getBackgroundColor()));
843 pw.print(" statusBarColor=");
844 pw.print(Integer.toHexString(taskDescription.getStatusBarColor()));
845 pw.print(" navigationBarColor=");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200846 pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
Craig Mautner29c58ca2014-10-14 16:17:06 -0700847 }
Craig Mautner648f69b2014-09-18 14:16:26 -0700848 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700849 if (results != null) {
850 pw.print(prefix); pw.print("results="); pw.println(results);
851 }
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700852 if (pendingResults != null && pendingResults.size() > 0) {
853 pw.print(prefix); pw.println("Pending Results:");
854 for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
855 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
856 pw.print(prefix); pw.print(" - ");
857 if (pir == null) {
858 pw.println("null");
859 } else {
860 pw.println(pir);
861 pir.dump(pw, prefix + " ");
862 }
863 }
864 }
865 if (newIntents != null && newIntents.size() > 0) {
866 pw.print(prefix); pw.println("Pending New Intents:");
867 for (int i=0; i<newIntents.size(); i++) {
Craig Mautnerd2328952013-03-05 12:46:26 -0800868 Intent intent = newIntents.get(i);
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700869 pw.print(prefix); pw.print(" - ");
870 if (intent == null) {
871 pw.println("null");
872 } else {
Hui Yu6d5c3b92019-10-22 15:35:53 -0700873 pw.println(intent.toShortString(false, true, false, false));
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700874 }
875 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700876 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700877 if (pendingOptions != null) {
878 pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
879 }
Dianne Hackbornb5a380d2015-05-20 18:18:46 -0700880 if (appTimeTracker != null) {
881 appTimeTracker.dumpWithHeader(pw, prefix, false);
882 }
Dianne Hackborn7e269642010-08-25 19:50:20 -0700883 if (uriPermissions != null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700884 uriPermissions.dump(pw, prefix);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700885 }
886 pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
Dianne Hackborn07981492013-01-28 11:36:23 -0800887 pw.print(" launchCount="); pw.print(launchCount);
888 pw.print(" lastLaunchTime=");
889 if (lastLaunchTime == 0) pw.print("0");
890 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
891 pw.println();
Andrii Kulian06b8dcb2019-07-10 21:09:38 -0700892 pw.print(prefix); pw.print("mHaveState="); pw.print(mHaveState);
893 pw.print(" mIcicle="); pw.println(mIcicle);
Bryce Lee7ace3952018-02-16 14:34:32 -0800894 pw.print(prefix); pw.print("state="); pw.print(mState);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700895 pw.print(" stopped="); pw.print(stopped);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700896 pw.print(" delayedResume="); pw.print(delayedResume);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700897 pw.print(" finishing="); pw.println(finishing);
898 pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
899 pw.print(" inHistory="); pw.print(inHistory);
Andrii Kulian46799182019-10-17 16:26:17 -0700900 pw.print(" setToSleep="); pw.print(mSetToSleep);
Wale Ogunwalef40c11b2016-02-26 08:16:02 -0800901 pw.print(" idle="); pw.print(idle);
902 pw.print(" mStartingWindowState=");
903 pw.println(startingWindowStateToString(mStartingWindowState));
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800904 pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
Dianne Hackbornff801ec2011-01-22 18:05:38 -0800905 pw.print(" noDisplay="); pw.print(noDisplay);
906 pw.print(" immersive="); pw.print(immersive);
907 pw.print(" launchMode="); pw.println(launchMode);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800908 pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400909 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700910 pw.print(prefix); pw.print("mActivityType=");
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700911 pw.println(activityTypeToString(getActivityType()));
Ruben Brunke24b9a62016-02-16 21:38:24 -0800912 if (requestedVrComponent != null) {
913 pw.print(prefix);
914 pw.print("requestedVrComponent=");
915 pw.println(requestedVrComponent);
916 }
Garfield Tane8d84ab2019-10-11 09:49:40 -0700917 super.dump(pw, prefix, dumpAll);
Riddle Hsud8bdc452019-12-06 21:36:32 +0800918 if (mVoiceInteraction) {
919 pw.println(prefix + "mVoiceInteraction=true");
Garfield Tane8d84ab2019-10-11 09:49:40 -0700920 }
Riddle Hsud8bdc452019-12-06 21:36:32 +0800921 pw.print(prefix); pw.print("mOccludesParent="); pw.print(mOccludesParent);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700922 pw.print(" mOrientation="); pw.println(mOrientation);
Issei Suzuki1669ea42019-11-06 14:20:59 +0100923 pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
Riddle Hsud8bdc452019-12-06 21:36:32 +0800924 + " mVisible=" + mVisible + " mClientVisible=" + mClientVisible
Garfield Tane8d84ab2019-10-11 09:49:40 -0700925 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
926 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
927 if (paused) {
928 pw.print(prefix); pw.print("paused="); pw.println(paused);
929 }
930 if (mAppStopped) {
931 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
932 }
933 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
934 || allDrawn || mLastAllDrawn) {
935 pw.print(prefix); pw.print("mNumInterestingWindows=");
936 pw.print(mNumInterestingWindows);
937 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700938 pw.print(" allDrawn="); pw.print(allDrawn);
939 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
940 pw.println(")");
941 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -0800942 if (mStartingData != null || firstWindowDrawn || mIsExiting) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700943 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700944 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
945 pw.print(" mIsExiting="); pw.println(mIsExiting);
946 }
947 if (startingWindow != null || startingSurface != null
Issei Suzukif2f6c912019-11-08 11:24:18 +0100948 || startingDisplayed || startingMoved || mVisibleSetFromTransferredStartingWindow) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700949 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
950 pw.print(" startingSurface="); pw.print(startingSurface);
951 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
952 pw.print(" startingMoved="); pw.print(startingMoved);
953 pw.println(" mHiddenSetFromTransferredStartingWindow="
Issei Suzukif2f6c912019-11-08 11:24:18 +0100954 + mVisibleSetFromTransferredStartingWindow);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700955 }
956 if (!mFrozenBounds.isEmpty()) {
957 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
958 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
959 }
960 if (mPendingRelaunchCount != 0) {
961 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
962 }
963 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
964 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
965 + mSizeCompatBounds);
966 }
967 if (mRemovingFromDisplay) {
968 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
969 }
Jorim Jaggi9b5e3312019-03-01 18:08:00 +0100970 if (lastVisibleTime != 0 || nowVisible) {
Riddle Hsud8bdc452019-12-06 21:36:32 +0800971 pw.print(prefix); pw.print("nowVisible="); pw.print(nowVisible);
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -0700972 pw.print(" lastVisibleTime=");
Dianne Hackbornf530ac32012-06-21 14:17:48 -0700973 if (lastVisibleTime == 0) pw.print("0");
974 else TimeUtils.formatDuration(lastVisibleTime, now, pw);
975 pw.println();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700976 }
Wale Ogunwaleec950642017-04-25 07:44:21 -0700977 if (mDeferHidingClient) {
978 pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
979 }
Wale Ogunwalef81c1d12016-01-12 12:20:18 -0800980 if (deferRelaunchUntilPaused || configChangeFlags != 0) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700981 pw.print(prefix); pw.print("deferRelaunchUntilPaused=");
982 pw.print(deferRelaunchUntilPaused);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700983 pw.print(" configChangeFlags=");
984 pw.println(Integer.toHexString(configChangeFlags));
985 }
Wale Ogunwalec4e63a42018-10-02 13:19:54 -0700986 if (mServiceConnectionsHolder != null) {
987 pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700988 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -0800989 if (info != null) {
990 pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
Winson Chung609e1e92017-05-08 10:52:12 -0700991 pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode
992 + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700993 if (info.supportsPictureInPicture()) {
994 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
Winson Chungf7e03e12017-08-22 11:32:16 -0700995 pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
996 + supportsEnterPipOnTaskSwitch);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700997 }
998 if (info.maxAspectRatio != 0) {
999 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
1000 }
Adrian Roos917791e2018-11-28 16:30:44 +01001001 if (info.minAspectRatio != 0) {
1002 pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
1003 }
Wale Ogunwaled26176f2016-01-25 20:04:04 -08001004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 }
1006
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001007 void setAppTimeTracker(AppTimeTracker att) {
1008 appTimeTracker = att;
1009 }
1010
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07001011 /** Update the saved state of an activity. */
1012 void setSavedState(@Nullable Bundle savedState) {
1013 mIcicle = savedState;
1014 mHaveState = mIcicle != null;
1015 }
1016
1017 /**
1018 * Get the actual Bundle instance of the saved state.
1019 * @see #hasSavedState() for checking if the record has saved state.
1020 */
1021 @Nullable Bundle getSavedState() {
1022 return mIcicle;
1023 }
1024
1025 /**
1026 * Check if the activity has saved state.
1027 * @return {@code true} if the client reported a non-empty saved state from last onStop(), or
1028 * if this record was just created and the client is yet to be launched and resumed.
1029 */
1030 boolean hasSavedState() {
1031 return mHaveState;
1032 }
1033
1034 /** @return The actual PersistableBundle instance of the saved persistent state. */
1035 @Nullable PersistableBundle getPersistentSavedState() {
1036 return mPersistentState;
1037 }
1038
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -07001039 void updateApplicationInfo(ApplicationInfo aInfo) {
Philip P. Moltmanncff8f0f2018-03-27 12:51:51 -07001040 info.applicationInfo = aInfo;
1041 }
1042
Andrii Kulian21713ac2016-10-12 22:05:05 -07001043 private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001044 return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
1045 }
1046
Andrii Kulian21713ac2016-10-12 22:05:05 -07001047 private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001048 return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
1049 }
1050
Andrii Kulian21713ac2016-10-12 22:05:05 -07001051 private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001052 return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
1053 }
1054
Filip Gruszczynski23493322015-07-29 17:02:59 -07001055 /**
1056 * The purpose of this method is to decide whether the activity needs to be relaunched upon
1057 * changing its size. In most cases the activities don't need to be relaunched, if the resize
1058 * is small, all the activity content has to do is relayout itself within new bounds. There are
1059 * cases however, where the activity's content would be completely changed in the new size and
1060 * the full relaunch is required.
1061 *
1062 * The activity will report to us vertical and horizontal thresholds after which a relaunch is
1063 * required. These thresholds are collected from the application resource qualifiers. For
1064 * example, if application has layout-w600dp resource directory, then it needs a relaunch when
1065 * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
1066 * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
1067 * of the threshold.
1068 */
1069 private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
1070 int secondDp) {
1071 if (thresholds == null) {
1072 return false;
1073 }
1074 for (int i = thresholds.length - 1; i >= 0; i--) {
1075 final int threshold = thresholds[i];
1076 if ((firstDp < threshold && secondDp >= threshold)
1077 || (firstDp >= threshold && secondDp < threshold)) {
1078 return true;
1079 }
1080 }
1081 return false;
1082 }
1083
Andrii Kulian21713ac2016-10-12 22:05:05 -07001084 void setSizeConfigurations(int[] horizontalSizeConfiguration,
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001085 int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
Filip Gruszczynski23493322015-07-29 17:02:59 -07001086 mHorizontalSizeConfigurations = horizontalSizeConfiguration;
1087 mVerticalSizeConfigurations = verticalSizeConfigurations;
Filip Gruszczynski20aa0ae2015-10-30 10:08:27 -07001088 mSmallestSizeConfigurations = smallestSizeConfigurations;
Filip Gruszczynski23493322015-07-29 17:02:59 -07001089 }
1090
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001091 private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001092 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001093 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
1094 "Can't report activity moved to display - client not running, activityRecord="
1095 + this + ", displayId=" + displayId);
Wale Ogunwale22e25262016-02-01 10:32:02 -08001096 return;
1097 }
1098 try {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001099 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
1100 "Reporting activity moved to display" + ", activityRecord=" + this
1101 + ", displayId=" + displayId + ", config=" + config);
Chong Zhang6be533e2016-06-17 16:24:21 -07001102
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001103 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001104 MoveToDisplayItem.obtain(displayId, config));
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001105 } catch (RemoteException e) {
1106 // If process died, whatever.
1107 }
1108 }
1109
1110 private void scheduleConfigurationChanged(Configuration config) {
Wale Ogunwalef6733932018-06-27 05:14:34 -07001111 if (!attachedToProcess()) {
Andrii Kulianb047b8b2017-02-08 18:38:26 -08001112 if (DEBUG_CONFIGURATION) Slog.w(TAG,
1113 "Can't report activity configuration update - client not running"
1114 + ", activityRecord=" + this);
1115 return;
1116 }
1117 try {
1118 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
1119 + config);
1120
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001121 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001122 ActivityConfigurationChangeItem.obtain(config));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001123 } catch (RemoteException e) {
1124 // If process died, whatever.
1125 }
1126 }
1127
Louis Chang3b21bdc2019-03-25 15:49:14 +08001128 boolean scheduleTopResumedActivityChanged(boolean onTop) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001129 if (!attachedToProcess()) {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001130 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001131 Slog.w(TAG, "Can't report activity position update - client not running"
1132 + ", activityRecord=" + this);
1133 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001134 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001135 }
1136 try {
Andrii Kulian86e70fc2019-02-12 11:04:10 +00001137 if (DEBUG_STATES) {
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001138 Slog.v(TAG, "Sending position change to " + this + ", onTop: " + onTop);
1139 }
1140
1141 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1142 TopResumedActivityChangeItem.obtain(onTop));
1143 } catch (RemoteException e) {
1144 // If process died, whatever.
Louis Chang3b21bdc2019-03-25 15:49:14 +08001145 return false;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001146 }
Louis Chang3b21bdc2019-03-25 15:49:14 +08001147 return true;
Andrii Kuliand70cdb92019-01-08 15:03:50 -08001148 }
1149
Winson Chung5af42fc2017-03-24 17:11:33 -07001150 void updateMultiWindowMode() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001151 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001152 return;
1153 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001154
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001155 if (task.getStack().deferScheduleMultiWindowModeChanged()) {
1156 // Don't do anything if we are currently deferring multi-window mode change.
1157 return;
1158 }
1159
Winson Chung5af42fc2017-03-24 17:11:33 -07001160 // An activity is considered to be in multi-window mode if its task isn't fullscreen.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001161 final boolean inMultiWindowMode = inMultiWindowMode();
Winson Chung609e1e92017-05-08 10:52:12 -07001162 if (inMultiWindowMode != mLastReportedMultiWindowMode) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001163 if (!inMultiWindowMode && mLastReportedPictureInPictureMode) {
1164 updatePictureInPictureMode(null, false);
1165 } else {
1166 mLastReportedMultiWindowMode = inMultiWindowMode;
1167 scheduleMultiWindowModeChanged(getConfiguration());
1168 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001169 }
1170 }
1171
1172 private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001173 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001174 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001175 MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001176 } catch (Exception e) {
1177 // If process died, I don't care.
1178 }
1179 }
1180
Winson Chungab76bbc2017-08-14 13:33:51 -07001181 void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001182 if (task == null || task.getStack() == null || !attachedToProcess()) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001183 return;
1184 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001185
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001186 final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
Winson Chungab76bbc2017-08-14 13:33:51 -07001187 if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001188 // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
Winson Chung059955f2018-08-08 16:10:20 -07001189 // update that here in order. Set the last reported MW state to the same as the PiP
1190 // state since we haven't yet actually resized the task (these callbacks need to
1191 // preceed the configuration change from the resiez.
1192 // TODO(110009072): Once we move these callbacks to the client, remove all logic related
1193 // to forcing the update of the picture-in-picture mode as a part of the PiP animation.
Winson Chung609e1e92017-05-08 10:52:12 -07001194 mLastReportedPictureInPictureMode = inPictureInPictureMode;
Winson Chung059955f2018-08-08 16:10:20 -07001195 mLastReportedMultiWindowMode = inPictureInPictureMode;
Evan Rosky1ac84462018-11-13 11:25:30 -08001196 final Configuration newConfig = new Configuration();
1197 if (targetStackBounds != null && !targetStackBounds.isEmpty()) {
Evan Rosky730f6e82018-12-03 17:40:11 -08001198 newConfig.setTo(task.getRequestedOverrideConfiguration());
1199 Rect outBounds = newConfig.windowConfiguration.getBounds();
1200 task.adjustForMinimalTaskDimensions(outBounds, outBounds);
1201 task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration());
Evan Rosky1ac84462018-11-13 11:25:30 -08001202 }
Winson Chung5af42fc2017-03-24 17:11:33 -07001203 schedulePictureInPictureModeChanged(newConfig);
1204 scheduleMultiWindowModeChanged(newConfig);
1205 }
1206 }
1207
1208 private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
Wale Ogunwale22e25262016-02-01 10:32:02 -08001209 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001210 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulian9c5ea9c2017-12-07 09:31:01 -08001211 PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
Andrii Kulian446e8242017-10-26 15:17:29 -07001212 overrideConfig));
Wale Ogunwale22e25262016-02-01 10:32:02 -08001213 } catch (Exception e) {
1214 // If process died, no one cares.
Filip Gruszczynskica664812015-12-04 12:43:36 -08001215 }
1216 }
1217
Louis Changcdec0802019-11-11 11:45:07 +08001218 Task getTask() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001219 return task;
1220 }
1221
Bryce Leeaf691c02017-03-20 14:20:22 -07001222 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001223 * Sets the Task on this activity for the purposes of re-use during launch where we will
1224 * re-use another activity instead of this one for the launch.
chaviw4ad54912018-05-30 11:05:44 -07001225 */
Louis Changcdec0802019-11-11 11:45:07 +08001226 void setTaskForReuse(Task task) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001227 this.task = task;
chaviw4ad54912018-05-30 11:05:44 -07001228 }
1229
Louis Changdc077272019-11-12 16:52:56 +08001230 ActivityStack getStack() {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001231 return task != null ? task.getStack() : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001232 }
1233
1234 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001235 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +08001236 final Task oldTask = oldParent != null ? (Task) oldParent : null;
1237 final Task newTask = newParent != null ? (Task) newParent : null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001238 this.task = newTask;
1239
1240 super.onParentChanged(newParent, oldParent);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001241
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001242 if (isPersistable()) {
1243 if (oldTask != null) {
1244 mAtmService.notifyTaskPersisterLocked(oldTask, false);
1245 }
1246 if (newTask != null) {
1247 mAtmService.notifyTaskPersisterLocked(newTask, false);
1248 }
1249 }
1250
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001251 if (oldParent == null && newParent != null) {
1252 // First time we are adding the activity to the system.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001253 mVoiceInteraction = newTask.voiceSession != null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001254 mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
lumarkbde15132019-12-18 22:29:43 +08001255
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001256 // TODO(b/36505427): Maybe this call should be moved inside
1257 // updateOverrideConfiguration()
1258 newTask.updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001259 // Make sure override configuration is up-to-date before using to create window
1260 // controller.
1261 updateSizeCompatMode();
1262 // When an activity is started directly into a split-screen fullscreen stack, we need to
1263 // update the initial multi-window modes so that the callbacks are scheduled correctly
1264 // when the user leaves that mode.
1265 mLastReportedMultiWindowMode = inMultiWindowMode();
1266 mLastReportedPictureInPictureMode = inPinnedWindowingMode();
1267 }
1268
Garfield Tane8d84ab2019-10-11 09:49:40 -07001269 // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
1270 // access visual elements like the {@link DisplayContent}. We must remove any associations
1271 // such as animations.
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001272 if (task == null) {
1273 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1274 // from this list so we do not participate in any future animations.
1275 if (getDisplayContent() != null) {
1276 getDisplayContent().mClosingApps.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001277 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001278 } else if (mLastParent != null && mLastParent.getStack() != null) {
1279 task.getStack().mExitingActivities.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001280 }
Louis Changdc077272019-11-12 16:52:56 +08001281 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001282
1283 // If we reparent, make sure to remove ourselves from the old animation registry.
1284 if (mAnimatingActivityRegistry != null) {
1285 mAnimatingActivityRegistry.notifyFinished(this);
1286 }
1287 mAnimatingActivityRegistry = stack != null
1288 ? stack.getAnimatingActivityRegistry()
1289 : null;
1290
1291 mLastParent = task;
1292
1293 updateColorTransform();
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001294
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001295 if (oldTask != null) {
1296 oldTask.cleanUpActivityReferences(this);
1297 }
1298 if (newTask != null && isState(RESUMED)) {
1299 newTask.setResumedActivity(this, "onParentChanged");
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001300 }
Hongwei Wange8e32862020-04-08 13:23:45 -07001301
1302 if (stack != null && stack.topRunningActivity() == this) {
1303 // carry over the PictureInPictureParams to the parent stack without calling
1304 // TaskOrganizerController#dispatchTaskInfoChanged.
1305 // this is to ensure the stack holding up-to-dated pinned stack information
1306 // when activity is re-parented to enter pip mode, see also
1307 // RootWindowContainer#moveActivityToPinnedStack
1308 stack.mPictureInPictureParams.copyOnlySet(pictureInPictureArgs);
1309 // make ensure the TaskOrganizer still works after re-parenting
1310 if (firstWindowDrawn) {
1311 stack.setHasBeenVisible(true);
1312 }
1313 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001314 }
1315
1316 private void updateColorTransform() {
1317 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
1318 getPendingTransaction().setColorTransform(mSurfaceControl,
1319 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
1320 mWmService.scheduleAnimationLocked();
1321 }
1322 }
1323
1324 @Override
1325 void onDisplayChanged(DisplayContent dc) {
1326 DisplayContent prevDc = mDisplayContent;
1327 super.onDisplayChanged(dc);
1328 if (prevDc == null || prevDc == mDisplayContent) {
1329 return;
1330 }
1331
1332 if (prevDc.mOpeningApps.remove(this)) {
1333 // Transfer opening transition to new display.
1334 mDisplayContent.mOpeningApps.add(this);
1335 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1336 mDisplayContent.executeAppTransition();
1337 }
1338
Garfield Tane8d84ab2019-10-11 09:49:40 -07001339 prevDc.mClosingApps.remove(this);
1340
1341 if (prevDc.mFocusedApp == this) {
1342 prevDc.setFocusedApp(null);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001343 if (dc.getTopMostActivity() == this) {
1344 dc.setFocusedApp(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001345 }
1346 }
1347
1348 if (mLetterbox != null) {
1349 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1350 }
1351 }
1352
1353 void layoutLetterbox(WindowState winHint) {
1354 final WindowState w = findMainWindow();
1355 if (w == null || winHint != null && w != winHint) {
1356 return;
1357 }
1358 final boolean surfaceReady = w.isDrawnLw() // Regular case
1359 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1360 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1361 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
1362 if (needsLetterbox) {
1363 if (mLetterbox == null) {
1364 mLetterbox = new Letterbox(() -> makeChildSurface(null),
1365 mWmService.mTransactionFactory);
1366 mLetterbox.attachInput(w);
1367 }
1368 getPosition(mTmpPoint);
Riddle Hsu23e18a92020-03-10 00:26:51 +08001369 // Get the bounds of the "space-to-fill". The transformed bounds have the highest
1370 // priority because the activity is launched in a rotated environment. In multi-window
1371 // mode, the task-level represents this. In fullscreen-mode, the task container does
1372 // (since the orientation letterbox is also applied to the task).
1373 final Rect transformedBounds = getFixedRotationTransformDisplayBounds();
1374 final Rect spaceToFill = transformedBounds != null
1375 ? transformedBounds
1376 : inMultiWindowMode()
Evan Rosky6ecd67c2020-04-14 11:50:43 -07001377 ? task.getBounds()
1378 : getRootTask().getParent().getBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001379 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
1380 } else if (mLetterbox != null) {
1381 mLetterbox.hide();
1382 }
1383 }
1384
1385 void updateLetterboxSurface(WindowState winHint) {
1386 final WindowState w = findMainWindow();
1387 if (w != winHint && winHint != null && w != null) {
1388 return;
1389 }
1390 layoutLetterbox(winHint);
1391 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1392 mLetterbox.applySurfaceChanges(getPendingTransaction());
1393 }
1394 }
1395
1396 Rect getLetterboxInsets() {
1397 if (mLetterbox != null) {
1398 return mLetterbox.getInsets();
1399 } else {
1400 return new Rect();
1401 }
1402 }
1403
1404 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
1405 void getLetterboxInnerBounds(Rect outBounds) {
1406 if (mLetterbox != null) {
1407 outBounds.set(mLetterbox.getInnerFrame());
1408 } else {
1409 outBounds.setEmpty();
1410 }
1411 }
1412
1413 /**
1414 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
1415 * the given {@code rect}.
1416 */
1417 boolean isLetterboxOverlappingWith(Rect rect) {
1418 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
1419 }
1420
Dianne Hackbornbe707852011-11-11 14:32:10 -08001421 static class Token extends IApplicationToken.Stub {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001422 private WeakReference<ActivityRecord> weakActivity;
Steven Timotiusaf03df62017-07-18 16:56:43 -07001423 private final String name;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001424 private final String tokenString;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001425
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001426 Token(Intent intent) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07001427 name = intent.getComponent().flattenToShortString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001428 tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
1429 }
1430
1431 private void attach(ActivityRecord activity) {
1432 if (weakActivity != null) {
1433 throw new IllegalStateException("Already attached..." + this);
1434 }
1435 weakActivity = new WeakReference<>(activity);
Wale Ogunwale7d701172015-03-11 15:36:30 -07001436 }
1437
Charles Chen69362cd2019-03-29 15:18:45 +08001438 private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001439 if (token == null) {
1440 return null;
1441 }
1442 ActivityRecord r = token.weakActivity.get();
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08001443 if (r == null || r.getRootTask() == null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001444 return null;
1445 }
1446 return r;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001447 }
1448
Craig Mautnerde4ef022013-04-07 19:01:33 -07001449 @Override
Dianne Hackbornbe707852011-11-11 14:32:10 -08001450 public String toString() {
1451 StringBuilder sb = new StringBuilder(128);
1452 sb.append("Token{");
1453 sb.append(Integer.toHexString(System.identityHashCode(this)));
1454 sb.append(' ');
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001455 if (weakActivity != null) {
1456 sb.append(weakActivity.get());
1457 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001458 sb.append('}');
1459 return sb.toString();
1460 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07001461
1462 @Override
1463 public String getName() {
1464 return name;
1465 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001466 }
1467
Charles Chen69362cd2019-03-29 15:18:45 +08001468 static @Nullable ActivityRecord forTokenLocked(IBinder token) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001469 try {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001470 return Token.tokenToActivityRecordLocked((Token)token);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001471 } catch (ClassCastException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08001472 Slog.w(TAG, "Bad activity token: " + token, e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001473 return null;
1474 }
1475 }
1476
Riddle Hsuff9e8282019-04-24 23:55:11 +08001477 static boolean isResolverActivity(String className) {
1478 return ResolverActivity.class.getName().equals(className);
1479 }
1480
Louis Chang6a9be162019-07-15 10:41:32 +08001481 boolean isResolverOrDelegateActivity() {
1482 return isResolverActivity(mActivityComponent.getClassName()) || Objects.equals(
1483 mActivityComponent, mAtmService.mStackSupervisor.getSystemChooserActivity());
Craig Mautnerac6f8432013-07-17 13:24:59 -07001484 }
1485
Patrick Baumann31426b22018-05-21 13:46:40 -07001486 boolean isResolverOrChildActivity() {
1487 if (!"android".equals(packageName)) {
1488 return false;
1489 }
1490 try {
1491 return ResolverActivity.class.isAssignableFrom(
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001492 Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
Patrick Baumann31426b22018-05-21 13:46:40 -07001493 } catch (ClassNotFoundException e) {
1494 return false;
1495 }
1496 }
1497
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001498 ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
Philip P. Moltmannee295092020-02-10 08:46:26 -08001499 int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
1500 @Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,
1501 ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo,
1502 String _resultWho, int _reqCode, boolean _componentSpecified,
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001503 boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
1504 ActivityOptions options, ActivityRecord sourceRecord) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001505 super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
1506 null /* displayContent */, false /* ownerCanManageAppTokens */);
1507
1508 mAtmService = _service;
1509 appToken = (Token) token;
1510 info = aInfo;
1511 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1512 packageName = info.applicationInfo.packageName;
1513 mInputApplicationHandle = new InputApplicationHandle(appToken);
1514 intent = _intent;
1515
1516 // If the class name in the intent doesn't match that of the target, this is probably an
1517 // alias. We have to create a new ComponentName object to keep track of the real activity
1518 // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
1519 if (info.targetActivity == null
1520 || (info.targetActivity.equals(intent.getComponent().getClassName())
1521 && (info.launchMode == LAUNCH_MULTIPLE
1522 || info.launchMode == LAUNCH_SINGLE_TOP))) {
1523 mActivityComponent = intent.getComponent();
1524 } else {
1525 mActivityComponent =
1526 new ComponentName(info.packageName, info.targetActivity);
1527 }
1528
1529 mTargetSdk = info.applicationInfo.targetSdkVersion;
1530 mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
1531 setOrientation(info.screenOrientation);
1532 mRotationAnimationHint = info.rotationAnimation;
1533
1534 mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
1535 mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
1536 mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
1537
1538 int realTheme = info.getThemeResource();
1539 if (realTheme == Resources.ID_NULL) {
1540 realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
1541 ? android.R.style.Theme : android.R.style.Theme_Holo;
1542 }
1543
1544 final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
1545 realTheme, com.android.internal.R.styleable.Window, mUserId);
1546
1547 if (ent != null) {
1548 mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
1549 hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
1550 noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
1551 } else {
1552 hasWallpaper = false;
1553 noDisplay = false;
1554 }
1555
1556 if (options != null) {
1557 mLaunchTaskBehind = options.getLaunchTaskBehind();
1558
1559 final int rotationAnimation = options.getRotationAnimationHint();
1560 // Only override manifest supplied option if set.
1561 if (rotationAnimation >= 0) {
1562 mRotationAnimationHint = rotationAnimation;
1563 }
1564 }
1565
1566 // Application tokens start out hidden.
Issei Suzukif2f6c912019-11-08 11:24:18 +01001567 setVisible(false);
Issei Suzuki1669ea42019-11-06 14:20:59 +01001568 mVisibleRequested = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001569
1570 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
1571 ColorDisplayService.ColorDisplayServiceInternal.class);
1572 cds.attachColorTransformController(packageName, mUserId,
1573 new WeakReference<>(mColorTransformController));
1574
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001575 appToken.attach(this);
1576
Louis Chang149d5c82019-12-30 09:47:39 +08001577 mRootWindowContainer = _service.mRootWindowContainer;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001578 launchedFromPid = _launchedFromPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 launchedFromUid = _launchedFromUid;
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001580 launchedFromPackage = _launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -08001581 launchedFromFeatureId = _launchedFromFeature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 shortComponentName = _intent.getComponent().flattenToShortString();
1583 resolvedType = _resolvedType;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001584 componentSpecified = _componentSpecified;
Dianne Hackbornfb81d092015-08-03 17:14:46 -07001585 rootVoiceInteraction = _rootVoiceInteraction;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07001586 mLastReportedConfiguration = new MergedConfiguration(_configuration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 resultTo = _resultTo;
1588 resultWho = _resultWho;
1589 requestCode = _reqCode;
Bryce Lee7ace3952018-02-16 14:34:32 -08001590 setState(INITIALIZING, "ActivityRecord ctor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 launchFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 stopped = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001593 delayedResume = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 finishing = false;
Wale Ogunwalef81c1d12016-01-12 12:20:18 -08001595 deferRelaunchUntilPaused = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 keysPaused = false;
1597 inHistory = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 nowVisible = false;
Vishnu Nair9ba31652018-11-13 14:34:05 -08001599 mDrawn = false;
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01001600 mClientVisible = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 idle = false;
1602 hasBeenLaunched = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001603 mStackSupervisor = supervisor;
Robert Carr0f5d7532016-10-17 16:39:17 -07001604
Charles Chenf365d3a2019-11-14 17:22:05 +08001605 // b/35954083: Limit task affinity to uid to avoid various issues associated with sharing
1606 // affinity across uids.
1607 final String uid = Integer.toString(info.applicationInfo.uid);
1608 if (info.taskAffinity != null && !info.taskAffinity.startsWith(uid)) {
1609 info.taskAffinity = uid + ":" + info.taskAffinity;
1610 }
1611 taskAffinity = info.taskAffinity;
Garfield Tan5901e7c2020-02-07 17:12:22 -08001612 if (info.windowLayout != null && info.windowLayout.windowLayoutAffinity != null
1613 && !info.windowLayout.windowLayoutAffinity.startsWith(uid)) {
1614 info.windowLayout.windowLayoutAffinity =
1615 uid + ":" + info.windowLayout.windowLayoutAffinity;
1616 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001617 stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001618 nonLocalizedLabel = aInfo.nonLocalizedLabel;
1619 labelRes = aInfo.labelRes;
1620 if (nonLocalizedLabel == null && labelRes == 0) {
1621 ApplicationInfo app = aInfo.applicationInfo;
1622 nonLocalizedLabel = app.nonLocalizedLabel;
1623 labelRes = app.labelRes;
1624 }
1625 icon = aInfo.getIconResource();
1626 logo = aInfo.getLogoResource();
1627 theme = aInfo.getThemeResource();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001628 if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
1629 windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
1630 }
1631 if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
1632 && (aInfo.applicationInfo.uid == SYSTEM_UID
Wale Ogunwale342fbe92018-10-09 08:44:10 -07001633 || aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
1634 processName = _caller.mName;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001635 } else {
1636 processName = aInfo.processName;
1637 }
1638
1639 if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
1640 intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1641 }
1642
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001643 launchMode = aInfo.launchMode;
1644
Winson Chung83471632016-12-13 11:02:12 -08001645 setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001646
1647 immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
1648
1649 requestedVrComponent = (aInfo.requestedVrComponent == null) ?
1650 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
chaviw59b98852017-06-13 12:05:44 -07001651
Yuhan Zhaof3b3d412020-01-24 23:37:13 +00001652 lockTaskLaunchMode = getLockTaskLaunchMode(aInfo, options);
Charles He2bf28322017-10-12 22:24:49 +01001653
1654 if (options != null) {
1655 pendingOptions = options;
Charles He2bf28322017-10-12 22:24:49 +01001656 final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
1657 if (usageReport != null) {
1658 appTimeTracker = new AppTimeTracker(usageReport);
1659 }
Daniel Chapin781ad9d2020-01-21 21:14:03 +00001660 // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
1661 mHandoverLaunchDisplayId = options.getLaunchDisplayId();
zhaoyuhan3c918592019-12-11 13:11:21 -08001662 }
zhaoyuhan3c918592019-12-11 13:11:21 -08001663 }
1664
Yuhan Zhaof3b3d412020-01-24 23:37:13 +00001665 static int getLockTaskLaunchMode(ActivityInfo aInfo, @Nullable ActivityOptions options) {
1666 int lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
1667 if (aInfo.applicationInfo.isPrivilegedApp()
1668 && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
1669 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1670 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1671 }
1672 if (options != null) {
1673 final boolean useLockTask = options.getLockTaskMode();
1674 if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
1675 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
1676 }
1677 }
1678 return lockTaskLaunchMode;
1679 }
1680
Garfield Tane8d84ab2019-10-11 09:49:40 -07001681 @Override
1682 ActivityRecord asActivityRecord() {
1683 // I am an activity record!
1684 return this;
1685 }
1686
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001687 @Override
1688 boolean hasActivity() {
1689 // I am an activity!
1690 return true;
1691 }
1692
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001693 void setProcess(WindowProcessController proc) {
Dianne Hackborn68a06332017-11-15 17:54:18 -08001694 app = proc;
1695 final ActivityRecord root = task != null ? task.getRootActivity() : null;
1696 if (root == this) {
1697 task.setRootProcess(proc);
1698 }
Andrii Kulianfa23a9e2019-10-10 15:15:36 -07001699 proc.addActivityIfNeeded(this);
Dianne Hackborn68a06332017-11-15 17:54:18 -08001700 }
1701
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001702 boolean hasProcess() {
1703 return app != null;
1704 }
1705
1706 boolean attachedToProcess() {
1707 return hasProcess() && app.hasThread();
1708 }
1709
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001710 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1711 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1712 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1713 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001714 // If the display is frozen, we won't do anything until the actual window is
1715 // displayed so there is no reason to put in the starting window.
1716 if (!okToDisplay()) {
Yunfan Chen48c0ed082018-12-05 18:15:35 -08001717 return false;
1718 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001719
1720 if (mStartingData != null) {
1721 return false;
1722 }
1723
1724 final WindowState mainWin = findMainWindow();
1725 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
1726 // App already has a visible window...why would you want a starting window?
1727 return false;
1728 }
1729
1730 final ActivityManager.TaskSnapshot snapshot =
Louis Changcdec0802019-11-11 11:45:07 +08001731 mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
Peter Kalauskas4dc04602020-02-12 18:49:03 -08001732 false /* restoreFromDisk */, false /* isLowResolution */);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001733 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
1734 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
1735
1736 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
Riddle Hsu440f88b2019-11-06 22:17:35 +08001737 if (isActivityTypeHome()) {
1738 // The snapshot of home is only used once because it won't be updated while screen
1739 // is on (see {@link TaskSnapshotController#screenTurningOff}).
1740 mWmService.mTaskSnapshotController.removeSnapshotCache(task.mTaskId);
Riddle Hsu3b9ac732020-02-18 16:10:29 +08001741 if ((mDisplayContent.mAppTransition.getTransitFlags()
1742 & WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0) {
1743 // Only use snapshot of home as starting window when unlocking directly.
Riddle Hsu440f88b2019-11-06 22:17:35 +08001744 return false;
1745 }
1746 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001747 return createSnapshot(snapshot);
1748 }
1749
1750 // If this is a translucent window, then don't show a starting window -- the current
1751 // effect (a full-screen opaque starting window that fades away to the real contents
1752 // when it is ready) does not work for this.
1753 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
1754 if (theme != 0) {
1755 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
1756 com.android.internal.R.styleable.Window,
1757 mWmService.mCurrentUserId);
1758 if (ent == null) {
1759 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
1760 // see that.
1761 return false;
1762 }
1763 final boolean windowIsTranslucent = ent.array.getBoolean(
1764 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
1765 final boolean windowIsFloating = ent.array.getBoolean(
1766 com.android.internal.R.styleable.Window_windowIsFloating, false);
1767 final boolean windowShowWallpaper = ent.array.getBoolean(
1768 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
1769 final boolean windowDisableStarting = ent.array.getBoolean(
1770 com.android.internal.R.styleable.Window_windowDisablePreview, false);
1771 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
1772 windowIsTranslucent, windowIsFloating, windowShowWallpaper);
1773 if (windowIsTranslucent) {
1774 return false;
1775 }
1776 if (windowIsFloating || windowDisableStarting) {
1777 return false;
1778 }
1779 if (windowShowWallpaper) {
1780 if (getDisplayContent().mWallpaperController
1781 .getWallpaperTarget() == null) {
1782 // If this theme is requesting a wallpaper, and the wallpaper
1783 // is not currently visible, then this effectively serves as
1784 // an opaque window and our starting window transition animation
1785 // can still work. We just need to make sure the starting window
1786 // is also showing the wallpaper.
1787 windowFlags |= FLAG_SHOW_WALLPAPER;
1788 } else {
1789 return false;
1790 }
1791 }
1792 }
1793
1794 if (transferStartingWindow(transferFrom)) {
1795 return true;
1796 }
1797
1798 // There is no existing starting window, and we don't want to create a splash screen, so
1799 // that's it!
1800 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
1801 return false;
1802 }
1803
1804 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
1805 mStartingData = new SplashScreenStartingData(mWmService, pkg,
1806 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
1807 getMergedOverrideConfiguration());
1808 scheduleAddStartingWindow();
1809 return true;
1810 }
1811
1812 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
1813 if (snapshot == null) {
1814 return false;
1815 }
1816
1817 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
1818 mStartingData = new SnapshotStartingData(mWmService, snapshot);
1819 scheduleAddStartingWindow();
1820 return true;
1821 }
1822
1823 void scheduleAddStartingWindow() {
1824 // Note: we really want to do sendMessageAtFrontOfQueue() because we
1825 // want to process the message ASAP, before any other queued
1826 // messages.
1827 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
1828 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
1829 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
1830 }
1831 }
1832
1833 private class AddStartingWindow implements Runnable {
1834
1835 @Override
1836 public void run() {
1837 // Can be accessed without holding the global lock
1838 final StartingData startingData;
1839 synchronized (mWmService.mGlobalLock) {
1840 // There can only be one adding request, silly caller!
1841 mWmService.mAnimationHandler.removeCallbacks(this);
1842
1843 if (mStartingData == null) {
1844 // Animation has been canceled... do nothing.
1845 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1846 "startingData was nulled out before handling"
1847 + " mAddStartingWindow: %s", ActivityRecord.this);
1848 return;
1849 }
1850 startingData = mStartingData;
1851 }
1852
1853 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
1854 this, startingData);
1855
1856
1857 WindowManagerPolicy.StartingSurface surface = null;
1858 try {
1859 surface = startingData.createStartingSurface(ActivityRecord.this);
1860 } catch (Exception e) {
1861 Slog.w(TAG, "Exception when adding starting window", e);
1862 }
1863 if (surface != null) {
1864 boolean abort = false;
1865 synchronized (mWmService.mGlobalLock) {
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08001866 // If the window was successfully added, then we need to remove it.
1867 if (mStartingData == null) {
1868 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Aborted starting %s: startingData=%s",
1869 ActivityRecord.this, mStartingData);
Garfield Tane8d84ab2019-10-11 09:49:40 -07001870
1871 startingWindow = null;
1872 mStartingData = null;
1873 abort = true;
1874 } else {
1875 startingSurface = surface;
1876 }
1877 if (!abort) {
1878 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1879 "Added starting %s: startingWindow=%s startingView=%s",
1880 ActivityRecord.this, startingWindow, startingSurface);
1881 }
1882 }
1883 if (abort) {
1884 surface.remove();
1885 }
1886 } else {
1887 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
1888 ActivityRecord.this);
1889 }
1890 }
1891 }
1892
1893 private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
1894
1895 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
1896 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
1897 ActivityManager.TaskSnapshot snapshot) {
1898 if (getDisplayContent().mAppTransition.getAppTransition()
1899 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
1900 // TODO(b/34099271): Remove this statement to add back the starting window and figure
1901 // out why it causes flickering, the starting window appears over the thumbnail while
1902 // the docked from recents transition occurs
1903 return STARTING_WINDOW_TYPE_NONE;
1904 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
1905 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1906 } else if (taskSwitch && allowTaskSnapshot) {
Jay Aliomer78d7c652020-01-28 11:42:18 -05001907 if (snapshotOrientationSameAsTask(snapshot) || (snapshot != null && fromRecents)) {
1908 return STARTING_WINDOW_TYPE_SNAPSHOT;
1909 }
1910 if (!isActivityTypeHome()) {
1911 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1912 }
1913 return STARTING_WINDOW_TYPE_NONE;
Garfield Tane8d84ab2019-10-11 09:49:40 -07001914 } else {
1915 return STARTING_WINDOW_TYPE_NONE;
1916 }
1917 }
1918
1919 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
1920 if (snapshot == null) {
1921 return false;
1922 }
Louis Changcdec0802019-11-11 11:45:07 +08001923 return task.getConfiguration().orientation == snapshot.getOrientation();
Garfield Tane8d84ab2019-10-11 09:49:40 -07001924 }
1925
1926 void removeStartingWindow() {
1927 if (startingWindow == null) {
1928 if (mStartingData != null) {
1929 // Starting window has not been added yet, but it is scheduled to be added.
1930 // Go ahead and cancel the request.
1931 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
1932 mStartingData = null;
1933 }
1934 return;
1935 }
1936
1937 final WindowManagerPolicy.StartingSurface surface;
1938 if (mStartingData != null) {
1939 surface = startingSurface;
1940 mStartingData = null;
1941 startingSurface = null;
1942 startingWindow = null;
1943 startingDisplayed = false;
1944 if (surface == null) {
1945 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1946 "startingWindow was set but startingSurface==null, couldn't "
1947 + "remove");
1948
1949 return;
1950 }
1951 } else {
1952 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1953 "Tried to remove starting window but startingWindow was null: %s",
1954 this);
1955 return;
1956 }
1957
1958 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
1959 + " startingView=%s Callers=%s",
1960 this, startingWindow, startingSurface, Debug.getCallers(5));
1961
1962
1963 // Use the same thread to remove the window as we used to add it, as otherwise we end up
1964 // with things in the view hierarchy being called from different threads.
1965 mWmService.mAnimationHandler.post(() -> {
1966 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
1967 try {
1968 surface.remove();
1969 } catch (Exception e) {
1970 Slog.w(TAG_WM, "Exception when removing starting window", e);
1971 }
1972 });
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001973 }
1974
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001975 private void removeAppTokenFromDisplay() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001976 if (mWmService.mRoot == null) return;
Yunfan Chend4ef3012018-11-28 21:14:32 -08001977
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001978 final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001979 if (dc == null) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001980 Slog.w(TAG, "removeAppTokenFromDisplay: Attempted to remove token: "
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001981 + appToken + " from non-existing displayId=" + getDisplayId());
Bryce Lee7ace3952018-02-16 14:34:32 -08001982 return;
1983 }
Wale Ogunwalecc367f42017-02-01 08:12:14 -08001984 // Resume key dispatching if it is currently paused before we remove the container.
1985 resumeKeyDispatchingLocked();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001986 dc.removeAppToken(appToken.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001987 }
1988
Winson Chung30480042017-01-26 10:55:34 -08001989 /**
1990 * Reparents this activity into {@param newTask} at the provided {@param position}. The caller
1991 * should ensure that the {@param newTask} is not already the parent of this activity.
1992 */
Louis Changcdec0802019-11-11 11:45:07 +08001993 void reparent(Task newTask, int position, String reason) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001994 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001995 Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
1996 return;
1997 }
Louis Changcdec0802019-11-11 11:45:07 +08001998 final Task prevTask = task;
Winson Chung30480042017-01-26 10:55:34 -08001999 if (prevTask == newTask) {
2000 throw new IllegalArgumentException(reason + ": task=" + newTask
2001 + " is already the parent of r=" + this);
2002 }
2003
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002004 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
Garfield Tane8d84ab2019-10-11 09:49:40 -07002005 + " to task=%d at %d", this, task.mTaskId, position);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002006 reparent(newTask, position);
Winson Chung30480042017-01-26 10:55:34 -08002007 }
2008
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002009 private boolean isHomeIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07002010 return ACTION_MAIN.equals(intent.getAction())
Chilun2ef71f72018-11-16 17:57:15 +08002011 && (intent.hasCategory(CATEGORY_HOME)
2012 || intent.hasCategory(CATEGORY_SECONDARY_HOME))
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002013 && intent.getCategories().size() == 1
2014 && intent.getData() == null
2015 && intent.getType() == null;
2016 }
2017
Chong Zhangad24f962016-08-25 12:12:33 -07002018 static boolean isMainIntent(Intent intent) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07002019 return ACTION_MAIN.equals(intent.getAction())
2020 && intent.hasCategory(CATEGORY_LAUNCHER)
Chong Zhangad24f962016-08-25 12:12:33 -07002021 && intent.getCategories().size() == 1
2022 && intent.getData() == null
2023 && intent.getType() == null;
2024 }
2025
Louis Chang6a9be162019-07-15 10:41:32 +08002026 @VisibleForTesting
2027 boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002028 if (uid == Process.myUid() || uid == 0) {
2029 // System process can launch home activity.
2030 return true;
2031 }
Winson Chung547afd22018-05-17 16:03:25 -07002032 // Allow the recents component to launch the home activity.
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07002033 final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
Winson Chung547afd22018-05-17 16:03:25 -07002034 if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
2035 return true;
2036 }
Louis Chang6a9be162019-07-15 10:41:32 +08002037 // Resolver or system chooser activity can launch home activity.
2038 return sourceRecord != null && sourceRecord.isResolverOrDelegateActivity();
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002039 }
2040
Winson Chung83471632016-12-13 11:02:12 -08002041 /**
2042 * @return whether the given package name can launch an assist activity.
2043 */
2044 private boolean canLaunchAssistActivity(String packageName) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002045 final ComponentName assistComponent =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002046 mAtmService.mActiveVoiceInteractionServiceComponent;
Winson Chung83471632016-12-13 11:02:12 -08002047 if (assistComponent != null) {
2048 return assistComponent.getPackageName().equals(packageName);
2049 }
2050 return false;
2051 }
2052
Galia Peycheva480275a2020-03-18 17:33:42 +01002053 static boolean canLaunchDreamActivity(String packageName) {
2054 final DreamManagerInternal dreamManager =
2055 LocalServices.getService(DreamManagerInternal.class);
2056
2057 // Verify that the package is the current active dream. The getActiveDreamComponent()
2058 // call path does not acquire the DreamManager lock and thus is safe to use.
2059 final ComponentName activeDream = dreamManager.getActiveDreamComponent(false /* doze */);
2060 if (activeDream == null || activeDream.getPackageName() == null
2061 || !activeDream.getPackageName().equals(packageName)) {
2062 return false;
2063 }
2064
2065 // Verify that the device is dreaming.
2066 if (!LocalServices.getService(ActivityTaskManagerInternal.class).isDreaming()) {
2067 return false;
2068 }
2069
2070 return true;
2071 }
2072
Winson Chung83471632016-12-13 11:02:12 -08002073 private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
2074 ActivityOptions options, ActivityRecord sourceRecord) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002075 int activityType = ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002076 if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
Louis Chang6a9be162019-07-15 10:41:32 +08002077 && isHomeIntent(intent) && !isResolverOrDelegateActivity()) {
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002078 // This sure looks like a home activity!
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002079 activityType = ACTIVITY_TYPE_HOME;
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002080
2081 if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
2082 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
2083 // We only allow home activities to be resizeable if they explicitly requested it.
2084 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
2085 }
Andrii Kulian3b3fb662019-06-26 17:52:26 -07002086 } else if (mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07002087 info.applicationInfo.uid)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002088 activityType = ACTIVITY_TYPE_RECENTS;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07002089 } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
Winson Chung83471632016-12-13 11:02:12 -08002090 && canLaunchAssistActivity(launchedFromPackage)) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002091 activityType = ACTIVITY_TYPE_ASSISTANT;
Galia Peycheva480275a2020-03-18 17:33:42 +01002092 } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_DREAM
2093 && canLaunchDreamActivity(launchedFromPackage)
2094 && DreamActivity.class.getName() == info.name) {
2095 activityType = ACTIVITY_TYPE_DREAM;
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002096 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002097 setActivityType(activityType);
Wale Ogunwale1affbbc2016-05-01 09:03:52 -07002098 }
2099
Louis Changcdec0802019-11-11 11:45:07 +08002100 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002101 if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
Craig Mautnera228ae92014-07-09 05:44:55 -07002102 task.setTaskToAffiliateWith(taskToAffiliateWith);
2103 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002104 }
2105
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002106 /** @return Root task of this activity, null if there is no task. */
2107 ActivityStack getRootTask() {
2108 return task != null ? (ActivityStack) task.getRootTask() : null;
Andrii Kulian02b7a832016-10-06 23:11:56 -07002109 }
2110
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002111 int getRootTaskId() {
2112 return task != null ? task.getRootTaskId() : INVALID_TASK_ID;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08002113 }
2114
Louis Chang677921f2019-12-06 16:44:24 +08002115 DisplayContent getDisplay() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002116 final ActivityStack stack = getRootTask();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002117 return stack != null ? stack.getDisplay() : null;
2118 }
2119
Garfield Tane8d84ab2019-10-11 09:49:40 -07002120 @Override
Andrii Kulian86d676c2020-03-27 19:34:54 -07002121 @Nullable
2122 TaskDisplayArea getDisplayArea() {
2123 return (TaskDisplayArea) super.getDisplayArea();
2124 }
2125
2126 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07002127 boolean fillsParent() {
2128 return occludesParent();
2129 }
2130
2131 /** Returns true if this activity is opaque and fills the entire space of this task. */
2132 boolean occludesParent() {
Louis Chang99d6f0e2020-02-21 12:14:32 +08002133 return !finishing && mOccludesParent;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002134 }
2135
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002136 boolean setOccludesParent(boolean occludesParent) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002137 final boolean changed = occludesParent != mOccludesParent;
2138 mOccludesParent = occludesParent;
2139 setMainWindowOpaque(occludesParent);
2140 mWmService.mWindowPlacerLocked.requestTraversal();
2141
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08002142 if (changed && task != null && !occludesParent) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002143 getRootTask().convertActivityToTranslucent(this);
Riddle Hsued5789b2019-08-21 15:12:03 +08002144 }
2145 // Always ensure visibility if this activity doesn't occlude parent, so the
2146 // {@link #returningOptions} of the activity under this one can be applied in
2147 // {@link #handleAlreadyVisible()}.
2148 if (changed || !occludesParent) {
Louis Chang149d5c82019-12-30 09:47:39 +08002149 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Craig Mautner5eda9b32013-07-02 11:58:16 -07002150 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002151 return changed;
Craig Mautner4addfc52013-06-25 08:05:45 -07002152 }
2153
Garfield Tane8d84ab2019-10-11 09:49:40 -07002154 void setMainWindowOpaque(boolean isOpaque) {
2155 final WindowState win = findMainWindow();
2156 if (win == null) {
2157 return;
2158 }
2159 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2160 win.mWinAnimator.setOpaqueLocked(isOpaque);
2161 }
2162
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002163 void takeFromHistory() {
2164 if (inHistory) {
2165 inHistory = false;
2166 if (task != null && !finishing) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002167 task = null;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002168 }
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -07002169 clearOptionsLocked();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002170 }
2171 }
2172
2173 boolean isInHistory() {
2174 return inHistory;
2175 }
2176
Wale Ogunwale7d701172015-03-11 15:36:30 -07002177 boolean isInStackLocked() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002178 final ActivityStack stack = getRootTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07002179 return stack != null && stack.isInStackLocked(this) != null;
Wale Ogunwale7d701172015-03-11 15:36:30 -07002180 }
2181
Craig Mautner21d24a22014-04-23 11:45:37 -07002182 boolean isPersistable() {
Ruben Brunkf53497c2017-03-27 20:26:17 -07002183 return (info.persistableMode == PERSIST_ROOT_ONLY ||
2184 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002185 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
Craig Mautner21d24a22014-04-23 11:45:37 -07002186 }
2187
Evan Rosky226de132020-01-03 18:00:29 -08002188 @Override
Wale Ogunwale4cea0f52015-12-25 06:30:31 -08002189 boolean isFocusable() {
Evan Rosky226de132020-01-03 18:00:29 -08002190 return super.isFocusable()
2191 && (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable());
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002192 }
2193
2194 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08002195 return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002196 }
2197
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07002198 /** @return whether this activity is non-resizeable or forced to be resizeable */
2199 boolean isNonResizableOrForcedResizable(int windowingMode) {
2200 if (windowingMode == WINDOWING_MODE_PINNED && info.supportsPictureInPicture()) {
2201 return false;
2202 }
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002203 return info.resizeMode != RESIZE_MODE_RESIZEABLE
Wale Ogunwale72a73e32016-10-13 12:16:39 -07002204 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Jorim Jaggicd13d332016-04-27 15:40:20 -07002205 }
2206
Winson Chunge6308042016-10-31 09:24:01 -07002207 /**
Winson Chungd3395382016-12-13 11:49:09 -08002208 * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
Winson Chunge6308042016-10-31 09:24:01 -07002209 */
Wale Ogunwale6cae7652015-12-26 07:36:26 -08002210 boolean supportsPictureInPicture() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002211 return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
Winson Chungd3395382016-12-13 11:49:09 -08002212 && info.supportsPictureInPicture();
2213 }
2214
2215 /**
2216 * @return whether this activity supports split-screen multi-window and can be put in the docked
2217 * stack.
2218 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002219 @Override
2220 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08002221 // An activity can not be docked even if it is considered resizeable because it only
2222 // supports picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002223 return super.supportsSplitScreenWindowingMode()
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002224 && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002225 }
2226
2227 /**
2228 * @return whether this activity supports freeform multi-window and can be put in the freeform
2229 * stack.
2230 */
2231 boolean supportsFreeform() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002232 return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
Winson Chungd3395382016-12-13 11:49:09 -08002233 }
2234
2235 /**
2236 * @return whether this activity supports non-PiP multi-window.
2237 */
2238 private boolean supportsResizeableMultiWindow() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002239 return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
Winson Chungd3395382016-12-13 11:49:09 -08002240 && (ActivityInfo.isResizeableMode(info.resizeMode)
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002241 || mAtmService.mForceResizableActivities);
Wale Ogunwaled26176f2016-01-25 20:04:04 -08002242 }
2243
Winson Chunge6308042016-10-31 09:24:01 -07002244 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002245 * Check whether this activity can be launched on the specified display.
Riddle Hsu16567132018-08-16 21:37:47 +08002246 *
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002247 * @param displayId Target display id.
Riddle Hsu16567132018-08-16 21:37:47 +08002248 * @return {@code true} if either it is the default display or this activity can be put on a
2249 * secondary screen.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002250 */
2251 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002252 return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
Riddle Hsu16567132018-08-16 21:37:47 +08002253 launchedFromUid, info);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002254 }
2255
2256 /**
Robert Carrc33658e2017-04-11 18:24:20 -07002257 * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
2258 * the activity has requested to enter PiP when it would otherwise be stopped.
2259 *
Winson Chung298f95b2017-08-10 15:57:18 -07002260 * @return whether this activity is currently allowed to enter PIP.
Winson Chunge6308042016-10-31 09:24:01 -07002261 */
Winson Chung298f95b2017-08-10 15:57:18 -07002262 boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
Wale Ogunwaleb9a0c992017-04-18 07:25:20 -07002263 if (!supportsPictureInPicture()) {
2264 return false;
2265 }
2266
Winson Chungf4ac0632017-03-17 12:34:12 -07002267 // Check app-ops and see if PiP is supported for this package
2268 if (!checkEnterPictureInPictureAppOpsState()) {
2269 return false;
2270 }
2271
Winson Chungf1bfee12017-03-24 17:11:33 -07002272 // Check to see if we are in VR mode, and disallow PiP if so
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002273 if (mAtmService.shouldDisableNonVrUiLocked()) {
Winson Chungf1bfee12017-03-24 17:11:33 -07002274 return false;
2275 }
2276
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002277 boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002278 boolean isCurrentAppLocked =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002279 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
Andrii Kulian86d676c2020-03-27 19:34:54 -07002280 final TaskDisplayArea taskDisplayArea = getDisplayArea();
2281 boolean hasPinnedStack = taskDisplayArea != null && taskDisplayArea.hasPinnedTask();
Winson Chungbb348802017-01-30 12:01:45 -08002282 // Don't return early if !isNotLocked, since we want to throw an exception if the activity
2283 // is in an incorrect state
Winson Chunge581ebf2017-02-21 08:25:03 -08002284 boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
Robert Carrc33658e2017-04-11 18:24:20 -07002285
2286 // We don't allow auto-PiP when something else is already pipped.
2287 if (beforeStopping && hasPinnedStack) {
2288 return false;
2289 }
2290
Bryce Lee7ace3952018-02-16 14:34:32 -08002291 switch (mState) {
Winson Chungc2baac02017-01-11 13:34:47 -08002292 case RESUMED:
Winson Chunge581ebf2017-02-21 08:25:03 -08002293 // When visible, allow entering PiP if the app is not locked. If it is over the
2294 // keyguard, then we will prompt to unlock in the caller before entering PiP.
Robert Carrc33658e2017-04-11 18:24:20 -07002295 return !isCurrentAppLocked &&
Winson Chungf7e03e12017-08-22 11:32:16 -07002296 (supportsEnterPipOnTaskSwitch || !beforeStopping);
Winson Chungc2baac02017-01-11 13:34:47 -08002297 case PAUSING:
2298 case PAUSED:
Winson Chungbb348802017-01-30 12:01:45 -08002299 // When pausing, then only allow enter PiP as in the resume state, and in addition,
2300 // require that there is not an existing PiP activity and that the current system
2301 // state supports entering PiP
Winson Chunge581ebf2017-02-21 08:25:03 -08002302 return isNotLockedOrOnKeyguard && !hasPinnedStack
Winson Chungf7e03e12017-08-22 11:32:16 -07002303 && supportsEnterPipOnTaskSwitch;
Winson Chungc2baac02017-01-11 13:34:47 -08002304 case STOPPING:
2305 // When stopping in a valid state, then only allow enter PiP as in the pause state.
2306 // Otherwise, fall through to throw an exception if the caller is trying to enter
2307 // PiP in an invalid stopping state.
Winson Chungf7e03e12017-08-22 11:32:16 -07002308 if (supportsEnterPipOnTaskSwitch) {
Winson Chungf4ac0632017-03-17 12:34:12 -07002309 return isNotLockedOrOnKeyguard && !hasPinnedStack;
Winson Chungc2baac02017-01-11 13:34:47 -08002310 }
2311 default:
Winson Chung298f95b2017-08-10 15:57:18 -07002312 return false;
Winson Chungb5c41b72016-12-07 15:00:47 -08002313 }
Winson Chunge6308042016-10-31 09:24:01 -07002314 }
2315
Winson Chung59fda9e2017-01-20 16:14:51 -08002316 /**
Issei Suzuki2bcbd682019-11-08 13:20:14 +01002317 * Sets if this {@link ActivityRecord} is in the process of closing or entering PIP.
Garfield Tane8d84ab2019-10-11 09:49:40 -07002318 * {@link #mWillCloseOrEnterPip}}
2319 */
2320 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
2321 mWillCloseOrEnterPip = willCloseOrEnterPip;
2322 }
2323
2324 /**
Issei Suzuki2bcbd682019-11-08 13:20:14 +01002325 * Returns whether this {@link ActivityRecord} is considered closing. Conditions are either
Garfield Tane8d84ab2019-10-11 09:49:40 -07002326 * 1. Is this app animating and was requested to be hidden
2327 * 2. App is delayed closing since it might enter PIP.
2328 */
2329 boolean isClosingOrEnteringPip() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01002330 return (isAnimating(TRANSITION | PARENTS) && !mVisibleRequested) || mWillCloseOrEnterPip;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002331 }
2332 /**
Winson Chungf4ac0632017-03-17 12:34:12 -07002333 * @return Whether AppOps allows this package to enter picture-in-picture.
Winson Chung59fda9e2017-01-20 16:14:51 -08002334 */
Winson Chungf4ac0632017-03-17 12:34:12 -07002335 private boolean checkEnterPictureInPictureAppOpsState() {
Philip P. Moltmannee295092020-02-10 08:46:26 -08002336 return mAtmService.getAppOpsManager().checkOpNoThrow(
Andrii Kulianeceebbf2019-06-26 17:36:51 -07002337 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
Winson Chung59fda9e2017-01-20 16:14:51 -08002338 }
2339
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002340 private boolean isAlwaysFocusable() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002341 return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
2342 }
2343
Louis Chang2104fd92019-11-04 15:43:53 +08002344 boolean windowsAreFocusable() {
2345 return windowsAreFocusable(false /* fromUserTouch */);
2346 }
2347
Garfield Tane8d84ab2019-10-11 09:49:40 -07002348 // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
2349 // focusable means resumeable. I guess with that in mind maybe we should rename the other
2350 // method to isResumeable() or something like that.
Louis Chang2104fd92019-11-04 15:43:53 +08002351 boolean windowsAreFocusable(boolean fromUserTouch) {
2352 if (!fromUserTouch && mTargetSdk < Build.VERSION_CODES.Q) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07002353 final int pid = getPid();
2354 final ActivityRecord topFocusedAppOfMyProcess =
2355 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
2356 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
2357 // For the apps below Q, there can be only one app which has the focused window per
2358 // process, because legacy apps may not be ready for a multi-focus system.
2359 return false;
2360 }
2361 }
Louis Changa9c9d982019-11-11 11:20:19 +08002362 return (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable())
Louis Chang2453d062019-11-19 22:30:48 +08002363 && getDisplay() != null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07002364 }
2365
Louis Chang2104fd92019-11-04 15:43:53 +08002366 /**
2367 * Move activity with its stack to front and make the stack focused.
2368 * @param reason the reason to move to top
2369 * @return {@code true} if the stack is focusable and has been moved to top or the activity
2370 * is not yet resumed while the stack is already on top, {@code false} otherwise.
2371 */
Louis Chang19443452018-10-09 12:10:21 +08002372 boolean moveFocusableActivityToTop(String reason) {
2373 if (!isFocusable()) {
2374 if (DEBUG_FOCUS) {
2375 Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
2376 }
2377 return false;
2378 }
2379
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002380 final ActivityStack stack = getRootTask();
Louis Chang19443452018-10-09 12:10:21 +08002381 if (stack == null) {
2382 Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
2383 + this + " task=" + task);
2384 return false;
2385 }
2386
Louis Chang149d5c82019-12-30 09:47:39 +08002387 if (mRootWindowContainer.getTopResumedActivity() == this
lumarkd0b5c8f2019-09-29 11:30:37 +08002388 && getDisplayContent().mFocusedApp == this) {
Louis Chang19443452018-10-09 12:10:21 +08002389 if (DEBUG_FOCUS) {
2390 Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
2391 }
Louis Chang2104fd92019-11-04 15:43:53 +08002392 return !isState(RESUMED);
Louis Chang19443452018-10-09 12:10:21 +08002393 }
2394
2395 if (DEBUG_FOCUS) {
2396 Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
2397 }
2398
2399 stack.moveToFront(reason, task);
2400 // Report top activity change to tracking services and WM
Louis Chang149d5c82019-12-30 09:47:39 +08002401 if (mRootWindowContainer.getTopResumedActivity() == this) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002402 mAtmService.setResumedActivityUncheckLocked(this, reason);
Louis Chang19443452018-10-09 12:10:21 +08002403 }
2404 return true;
2405 }
Jorim Jaggife762342016-10-13 14:33:27 +02002406
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002407 void finishIfSubActivity(ActivityRecord parent, String otherResultWho, int otherRequestCode) {
2408 if (resultTo != parent
2409 || requestCode != otherRequestCode
2410 || !Objects.equals(resultWho, otherResultWho)) return;
2411
2412 finishIfPossible("request-sub", false /* oomAdj */);
2413 }
2414
Andrii Kuliande93eff2019-07-12 12:21:27 -07002415 /** Finish all activities in the task with the same affinity as this one. */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002416 boolean finishIfSameAffinity(ActivityRecord r) {
2417 // End search once we get to the activity that doesn't have the same affinity.
2418 if (!Objects.equals(r.taskAffinity, taskAffinity)) return true;
2419
2420 r.finishIfPossible("request-affinity", true /* oomAdj */);
2421 return false;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002422 }
2423
2424 /**
2425 * Sets the result for activity that started this one, clears the references to activities
2426 * started for result from this one, and clears new intents.
2427 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002428 private void finishActivityResults(int resultCode, Intent resultData) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002429 // Send the result if needed
2430 if (resultTo != null) {
2431 if (DEBUG_RESULTS) {
2432 Slog.v(TAG_RESULTS, "Adding result to " + resultTo
2433 + " who=" + resultWho + " req=" + requestCode
2434 + " res=" + resultCode + " data=" + resultData);
2435 }
2436 if (resultTo.mUserId != mUserId) {
2437 if (resultData != null) {
2438 resultData.prepareToLeaveUser(mUserId);
2439 }
2440 }
2441 if (info.applicationInfo.uid > 0) {
2442 mAtmService.mUgmInternal.grantUriPermissionFromIntent(info.applicationInfo.uid,
2443 resultTo.packageName, resultData,
2444 resultTo.getUriPermissionsLocked(), resultTo.mUserId);
2445 }
2446 resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
2447 resultTo = null;
2448 } else if (DEBUG_RESULTS) {
2449 Slog.v(TAG_RESULTS, "No result destination from " + this);
2450 }
2451
2452 // Make sure this HistoryRecord is not holding on to other resources,
2453 // because clients have remote IPC references to this object so we
2454 // can't assume that will go away and want to avoid circular IPC refs.
2455 results = null;
2456 pendingResults = null;
2457 newIntents = null;
2458 setSavedState(null /* savedState */);
2459 }
2460
Andrii Kulian057a6512019-07-15 16:15:51 -07002461 /** Activity finish request was not executed. */
2462 static final int FINISH_RESULT_CANCELLED = 0;
2463 /** Activity finish was requested, activity will be fully removed later. */
2464 static final int FINISH_RESULT_REQUESTED = 1;
2465 /** Activity finish was requested, activity was removed from history. */
2466 static final int FINISH_RESULT_REMOVED = 2;
2467
2468 /** Definition of possible results for activity finish request. */
2469 @IntDef(prefix = { "FINISH_RESULT_" }, value = {
2470 FINISH_RESULT_CANCELLED,
2471 FINISH_RESULT_REQUESTED,
2472 FINISH_RESULT_REMOVED,
2473 })
2474 @interface FinishRequest {}
2475
Andrii Kuliande93eff2019-07-12 12:21:27 -07002476 /**
Louis Chang7b03ad92019-08-21 12:32:33 +08002477 * See {@link #finishIfPossible(int, Intent, String, boolean)}
Andrii Kuliande93eff2019-07-12 12:21:27 -07002478 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002479 @FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
Louis Chang7b03ad92019-08-21 12:32:33 +08002480 return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason, oomAdj);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002481 }
2482
2483 /**
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002484 * Finish activity if possible. If activity was resumed - we must first pause it to make the
2485 * activity below resumed. Otherwise we will try to complete the request immediately by calling
2486 * {@link #completeFinishing(String)}.
Andrii Kulian057a6512019-07-15 16:15:51 -07002487 * @return One of {@link FinishRequest} values:
2488 * {@link #FINISH_RESULT_REMOVED} if this activity has been removed from the history list.
2489 * {@link #FINISH_RESULT_REQUESTED} if removal process was started, but it is still in the list
2490 * and will be removed from history later.
2491 * {@link #FINISH_RESULT_CANCELLED} if activity is already finishing or in invalid state and the
2492 * request to finish it was not ignored.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002493 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002494 @FinishRequest int finishIfPossible(int resultCode, Intent resultData, String reason,
Louis Chang7b03ad92019-08-21 12:32:33 +08002495 boolean oomAdj) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002496 if (DEBUG_RESULTS || DEBUG_STATES) {
2497 Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
2498 + ", data=" + resultData + ", reason=" + reason);
2499 }
2500
Andrii Kuliande93eff2019-07-12 12:21:27 -07002501 if (finishing) {
Andrii Kulian057a6512019-07-15 16:15:51 -07002502 Slog.w(TAG, "Duplicate finish request for r=" + this);
2503 return FINISH_RESULT_CANCELLED;
2504 }
2505
2506 if (!isInStackLocked()) {
2507 Slog.w(TAG, "Finish request when not in stack for r=" + this);
2508 return FINISH_RESULT_CANCELLED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002509 }
2510
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002511 final ActivityStack stack = getRootTask();
Riddle Hsucf920232019-10-04 19:05:36 +08002512 final boolean mayAdjustTop = (isState(RESUMED) || stack.mResumedActivity == null)
2513 && stack.isFocusedStackOnDisplay();
2514 final boolean shouldAdjustGlobalFocus = mayAdjustTop
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002515 // It must be checked before {@link #makeFinishingLocked} is called, because a stack
2516 // is not visible if it only contains finishing activities.
Louis Chang149d5c82019-12-30 09:47:39 +08002517 && mRootWindowContainer.isTopDisplayFocusedStack(stack);
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002518
Riddle Hsua0022cd2019-09-09 21:12:41 +08002519 mAtmService.deferWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002520 try {
2521 makeFinishingLocked();
Louis Changcdec0802019-11-11 11:45:07 +08002522 // Make a local reference to its task since this.task could be set to null once this
2523 // activity is destroyed and detached from task.
2524 final Task task = getTask();
Jeff Changd136e772019-11-05 20:33:52 +08002525 EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002526 task.mTaskId, shortComponentName, reason);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002527 ActivityRecord next = task.getActivityAbove(this);
2528 if (next != null) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002529 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2530 // If the caller asked that this activity (and all above it)
2531 // be cleared when the task is reset, don't lose that information,
2532 // but propagate it up to the next activity.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002533 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2534 }
2535 }
2536
2537 pauseKeyDispatchingLocked();
2538
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002539 // We are finishing the top focused activity and its stack has nothing to be focused so
2540 // the next focusable stack should be focused.
Riddle Hsucf920232019-10-04 19:05:36 +08002541 if (mayAdjustTop
Evan Rosky226de132020-01-03 18:00:29 -08002542 && (stack.topRunningActivity() == null || !stack.isTopActivityFocusable())) {
Riddle Hsucf920232019-10-04 19:05:36 +08002543 if (shouldAdjustGlobalFocus) {
2544 // Move the entire hierarchy to top with updating global top resumed activity
2545 // and focused application if needed.
2546 stack.adjustFocusToNextFocusableStack("finish-top");
2547 } else {
Andrii Kulian86d676c2020-03-27 19:34:54 -07002548 // Only move the next stack to top in its task container.
2549 final TaskDisplayArea taskDisplayArea = stack.getDisplayArea();
2550 next = taskDisplayArea.topRunningActivity();
Riddle Hsucf920232019-10-04 19:05:36 +08002551 if (next != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07002552 taskDisplayArea.positionStackAtTop(next.getRootTask(),
Riddle Hsucf920232019-10-04 19:05:36 +08002553 false /* includingParents */, "finish-display-top");
2554 }
2555 }
Riddle Hsu1e7ba582019-08-26 19:18:34 +08002556 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002557
2558 finishActivityResults(resultCode, resultData);
2559
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002560 final boolean endTask = task.getActivityBelow(this) == null
2561 && !task.isClearingToReuseTask();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002562 final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002563 if (isState(RESUMED)) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07002564 if (endTask) {
2565 mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
2566 task.getTaskInfo());
2567 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002568 // Prepare app close transition, but don't execute just yet. It is possible that
2569 // an activity that will be made resumed in place of this one will immediately
2570 // launch another new activity. In this case current closing transition will be
2571 // combined with open transition for the new activity.
2572 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
2573 Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
2574 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002575 getDisplay().mDisplayContent.prepareAppTransition(transit, false);
2576
2577 // When finishing the activity preemptively take the snapshot before the app window
2578 // is marked as hidden and any configuration changes take place
2579 if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002580 final ArraySet<Task> tasks = Sets.newArraySet(task);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002581 mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
2582 mAtmService.mWindowManager.mTaskSnapshotController
2583 .addSkipClosingAppSnapshotTasks(tasks);
2584 }
2585
2586 // Tell window manager to prepare for this one to be removed.
2587 setVisibility(false);
2588
2589 if (stack.mPausingActivity == null) {
2590 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + this);
2591 if (DEBUG_USER_LEAVING) {
2592 Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
2593 }
Louis Chang7b03ad92019-08-21 12:32:33 +08002594 stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
2595 null /* resuming */);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002596 }
2597
2598 if (endTask) {
2599 mAtmService.getLockTaskController().clearLockedTask(task);
2600 }
2601 } else if (!isState(PAUSING)) {
Issei Suzuki1669ea42019-11-06 14:20:59 +01002602 if (mVisibleRequested) {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002603 // Prepare and execute close transition.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002604 prepareActivityHideTransitionAnimation(transit);
2605 }
2606
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002607 final boolean removedActivity = completeFinishing("finishIfPossible") == null;
2608 // Performance optimization - only invoke OOM adjustment if the state changed to
2609 // 'STOPPING'. Otherwise it will not change the OOM scores.
2610 if (oomAdj && isState(STOPPING)) {
2611 mAtmService.updateOomAdj();
2612 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002613
2614 // The following code is an optimization. When the last non-task overlay activity
2615 // is removed from the task, we remove the entire task from the stack. However,
2616 // since that is done after the scheduled destroy callback from the activity, that
2617 // call to change the visibility of the task overlay activities would be out of
2618 // sync with the activity visibility being set for this finishing activity above.
2619 // In this case, we can set the visibility of all the task overlay activities when
2620 // we detect the last one is finishing to keep them in sync.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002621 if (task.onlyHasTaskOverlayActivities(false /* includeFinishing */)) {
2622 final PooledConsumer c = PooledLambda.obtainConsumer(
2623 ActivityRecord::prepareActivityHideTransitionAnimationIfOvarlay,
2624 PooledLambda.__(ActivityRecord.class), transit);
2625 task.forAllActivities(c);
2626 c.recycle();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002627 }
Andrii Kulian057a6512019-07-15 16:15:51 -07002628 return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002629 } else {
2630 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
2631 }
2632
Andrii Kulian057a6512019-07-15 16:15:51 -07002633 return FINISH_RESULT_REQUESTED;
Andrii Kuliande93eff2019-07-12 12:21:27 -07002634 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +08002635 mAtmService.continueWindowLayout();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002636 }
2637 }
2638
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002639 private void prepareActivityHideTransitionAnimationIfOvarlay(int transit) {
2640 if (mTaskOverlay) {
2641 prepareActivityHideTransitionAnimation(transit);
2642 }
2643 }
2644
Andrii Kuliande93eff2019-07-12 12:21:27 -07002645 private void prepareActivityHideTransitionAnimation(int transit) {
2646 final DisplayContent dc = getDisplay().mDisplayContent;
2647 dc.prepareAppTransition(transit, false);
2648 setVisibility(false);
2649 dc.executeAppTransition();
2650 }
2651
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002652 /**
2653 * Complete activity finish request that was initiated earlier. If the activity is still
2654 * pausing we will wait for it to complete its transition. If the activity that should appear in
2655 * place of this one is not visible yet - we'll wait for it first. Otherwise - activity can be
2656 * destroyed right away.
2657 * @param reason Reason for finishing the activity.
2658 * @return Flag indicating whether the activity was removed from history.
2659 */
2660 ActivityRecord completeFinishing(String reason) {
2661 if (!finishing || isState(RESUMED)) {
2662 throw new IllegalArgumentException(
2663 "Activity must be finishing and not resumed to complete, r=" + this
2664 + ", finishing=" + finishing + ", state=" + mState);
2665 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002666
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002667 if (isState(PAUSING)) {
2668 // Activity is marked as finishing and will be processed once it completes.
2669 return this;
2670 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002671
Louis Chang3d718c32020-04-09 16:51:02 +08002672 // Ensure activity visibilities and update lockscreen occluded/dismiss state when
2673 // finishing the top activity that occluded keyguard. So that, the
2674 // ActivityStack#mTopActivityOccludesKeyguard can be updated and the activity below won't
2675 // be resumed.
2676 if (isState(PAUSED)
2677 && mStackSupervisor.getKeyguardController().isKeyguardLocked()
2678 && getStack().topActivityOccludesKeyguard()) {
2679 getStack().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
2680 false /* preserveWindows */, false /* notifyClients */);
2681 }
2682
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002683 boolean activityRemoved = false;
2684
2685 // If this activity is currently visible, and the resumed activity is not yet visible, then
2686 // hold off on finishing until the resumed one becomes visible.
Andrii Kuliande93eff2019-07-12 12:21:27 -07002687 // The activity that we are finishing may be over the lock screen. In this case, we do not
2688 // want to consider activities that cannot be shown on the lock screen as running and should
2689 // proceed with finishing the activity if there is no valid next top running activity.
2690 // Note that if this finishing activity is floating task, we don't need to wait the
2691 // next activity resume and can destroy it directly.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002692 // TODO(b/137329632): find the next activity directly underneath this one, not just anywhere
Andrii Kulian86d676c2020-03-27 19:34:54 -07002693 final ActivityRecord next = getDisplayArea().topRunningActivity(
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002694 true /* considerKeyguardState */);
lumark50b81542019-09-01 23:11:49 +08002695 // isNextNotYetVisible is to check if the next activity is invisible, or it has been
2696 // requested to be invisible but its windows haven't reported as invisible. If so, it
2697 // implied that the current finishing activity should be added into stopping list rather
2698 // than destroy immediately.
Issei Suzuki1669ea42019-11-06 14:20:59 +01002699 final boolean isNextNotYetVisible = next != null
2700 && (!next.nowVisible || !next.mVisibleRequested);
Issei Suzukid0c14f32019-12-19 12:42:13 +01002701 if ((mVisibleRequested || isState(PAUSED)) && isNextNotYetVisible) {
Andrii Kulian34acc142019-09-24 15:35:50 -07002702 // Add this activity to the list of stopping activities. It will be processed and
2703 // destroyed when the next activity reports idle.
Andrii Kulian79d67982019-08-19 11:56:16 -07002704 addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
2705 "completeFinishing");
Andrii Kulian79d67982019-08-19 11:56:16 -07002706 setState(STOPPING, "completeFinishing");
Andrii Kulian34acc142019-09-24 15:35:50 -07002707 } else if (addToFinishingAndWaitForIdle()) {
2708 // We added this activity to the finishing list and something else is becoming resumed.
2709 // The activity will complete finishing when the next activity reports idle. No need to
2710 // do anything else here.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002711 } else {
Andrii Kulian34acc142019-09-24 15:35:50 -07002712 // Not waiting for the next one to become visible, and nothing else will be resumed in
2713 // place of this activity - requesting destruction right away.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002714 activityRemoved = destroyIfPossible(reason);
Andrii Kuliande93eff2019-07-12 12:21:27 -07002715 }
2716
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002717 return activityRemoved ? null : this;
2718 }
2719
2720 /**
2721 * Destroy and cleanup the activity both on client and server if possible. If activity is the
2722 * last one left on display with home stack and there is no other running activity - delay
2723 * destroying it until the next one starts.
2724 */
2725 boolean destroyIfPossible(String reason) {
2726 setState(FINISHING, "destroyIfPossible");
2727
2728 // Make sure the record is cleaned out of other places.
2729 mStackSupervisor.mStoppingActivities.remove(this);
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002730
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002731 final ActivityStack stack = getRootTask();
Andrii Kulian86d676c2020-03-27 19:34:54 -07002732 final TaskDisplayArea taskDisplayArea = getDisplayArea();
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002733 // TODO(b/137329632): Exclude current activity when looking for the next one with
Louis Chang677921f2019-12-06 16:44:24 +08002734 // DisplayContent#topRunningActivity().
Andrii Kulian86d676c2020-03-27 19:34:54 -07002735 final ActivityRecord next = taskDisplayArea.topRunningActivity();
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002736 final boolean isLastStackOverEmptyHome =
Darryl L Johnson3388bd22019-12-19 17:38:41 -08002737 next == null && stack.isFocusedStackOnDisplay()
Andrii Kulian86d676c2020-03-27 19:34:54 -07002738 && taskDisplayArea.getOrCreateRootHomeTask() != null;
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002739 if (isLastStackOverEmptyHome) {
2740 // Don't destroy activity immediately if this is the last activity on the display and
2741 // the display contains home stack. Although there is no next activity at the moment,
2742 // another home activity should be started later. Keep this activity alive until next
2743 // home activity is resumed. This way the user won't see a temporary black screen.
2744 addToFinishingAndWaitForIdle();
2745 return false;
2746 }
2747 makeFinishingLocked();
2748
Andrii Kulian79d67982019-08-19 11:56:16 -07002749 final boolean activityRemoved = destroyImmediately(true /* removeFromApp */,
2750 "finish-imm:" + reason);
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002751
2752 // If the display does not have running activity, the configuration may need to be
2753 // updated for restoring original orientation of the display.
2754 if (next == null) {
Louis Chang149d5c82019-12-30 09:47:39 +08002755 mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002756 false /* markFrozenIfConfigChanged */, true /* deferResume */);
2757 }
2758 if (activityRemoved) {
Louis Chang149d5c82019-12-30 09:47:39 +08002759 mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002760 }
2761
2762 if (DEBUG_CONTAINERS) {
2763 Slog.d(TAG_CONTAINERS, "destroyIfPossible: r=" + this + " destroy returned removed="
2764 + activityRemoved);
2765 }
2766
2767 return activityRemoved;
2768 }
2769
Andrii Kulian34acc142019-09-24 15:35:50 -07002770 /**
2771 * Add this activity to the list of finishing and trigger resuming of activities in focused
2772 * stacks.
2773 * @return {@code true} if some other activity is being resumed as a result of this call.
2774 */
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002775 @VisibleForTesting
Andrii Kulian34acc142019-09-24 15:35:50 -07002776 boolean addToFinishingAndWaitForIdle() {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07002777 if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
2778 setState(FINISHING, "addToFinishingAndWaitForIdle");
Andrii Kulian34acc142019-09-24 15:35:50 -07002779 if (!mStackSupervisor.mFinishingActivities.contains(this)) {
2780 mStackSupervisor.mFinishingActivities.add(this);
2781 }
Andrii Kuliande93eff2019-07-12 12:21:27 -07002782 resumeKeyDispatchingLocked();
Louis Chang149d5c82019-12-30 09:47:39 +08002783 return mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kuliande93eff2019-07-12 12:21:27 -07002784 }
2785
Andrii Kulian79d67982019-08-19 11:56:16 -07002786 /**
2787 * Destroy the current CLIENT SIDE instance of an activity. This may be called both when
2788 * actually finishing an activity, or when performing a configuration switch where we destroy
2789 * the current client-side object but then create a new client-side object for this same
2790 * HistoryRecord.
2791 * Normally the server-side record will be removed when the client reports back after
2792 * destruction. If, however, at this point there is no client process attached, the record will
Andrii Kulianf49a58c2019-08-14 17:34:27 -07002793 * be removed immediately.
2794 *
2795 * @return {@code true} if activity was immediately removed from history, {@code false}
2796 * otherwise.
Andrii Kulian79d67982019-08-19 11:56:16 -07002797 */
2798 boolean destroyImmediately(boolean removeFromApp, String reason) {
2799 if (DEBUG_SWITCH || DEBUG_CLEANUP) {
2800 Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this
2801 + ", app=" + (hasProcess() ? app.mName : "(null)"));
2802 }
2803
2804 if (isState(DESTROYING, DESTROYED)) {
2805 if (DEBUG_STATES) {
2806 Slog.v(TAG_STATES, "activity " + this + " already destroying."
2807 + "skipping request with reason:" + reason);
2808 }
2809 return false;
2810 }
2811
Jeff Changd136e772019-11-05 20:33:52 +08002812 EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this),
2813 task.mTaskId, shortComponentName, reason);
Andrii Kulian79d67982019-08-19 11:56:16 -07002814
2815 boolean removedFromHistory = false;
2816
2817 cleanUp(false /* cleanServices */, false /* setState */);
2818
Riddle Hsu5477b572019-11-12 16:07:29 +08002819 if (hasProcess()) {
Andrii Kulian79d67982019-08-19 11:56:16 -07002820 if (removeFromApp) {
2821 app.removeActivity(this);
2822 if (!app.hasActivities()) {
2823 mAtmService.clearHeavyWeightProcessIfEquals(app);
2824 // Update any services we are bound to that might care about whether
2825 // their client may have activities.
2826 // No longer have activities, so update LRU list and oom adj.
2827 app.updateProcessInfo(true /* updateServiceConnectionActivities */,
2828 false /* activityChange */, true /* updateOomAdj */);
2829 }
2830 }
2831
2832 boolean skipDestroy = false;
2833
2834 try {
2835 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
2836 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2837 DestroyActivityItem.obtain(finishing, configChangeFlags));
2838 } catch (Exception e) {
2839 // We can just ignore exceptions here... if the process has crashed, our death
2840 // notification will clean things up.
2841 if (finishing) {
2842 removeFromHistory(reason + " exceptionInScheduleDestroy");
2843 removedFromHistory = true;
2844 skipDestroy = true;
2845 }
2846 }
2847
2848 nowVisible = false;
2849
2850 // If the activity is finishing, we need to wait on removing it from the list to give it
2851 // a chance to do its cleanup. During that time it may make calls back with its token
2852 // so we need to be able to find it on the list and so we don't want to remove it from
2853 // the list yet. Otherwise, we can just immediately put it in the destroyed state since
2854 // we are not removing it from the list.
2855 if (finishing && !skipDestroy) {
2856 if (DEBUG_STATES) {
2857 Slog.v(TAG_STATES, "Moving to DESTROYING: " + this + " (destroy requested)");
2858 }
2859 setState(DESTROYING,
2860 "destroyActivityLocked. finishing and not skipping destroy");
Wale Ogunwale196db712019-12-27 15:35:39 +00002861 mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT);
Andrii Kulian79d67982019-08-19 11:56:16 -07002862 } else {
2863 if (DEBUG_STATES) {
2864 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
2865 }
2866 setState(DESTROYED,
2867 "destroyActivityLocked. not finishing or skipping destroy");
2868 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
2869 app = null;
2870 }
2871 } else {
2872 // Remove this record from the history.
2873 if (finishing) {
2874 removeFromHistory(reason + " hadNoApp");
2875 removedFromHistory = true;
2876 } else {
2877 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (no app)");
2878 setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
2879 }
2880 }
2881
2882 configChangeFlags = 0;
2883
Andrii Kulian79d67982019-08-19 11:56:16 -07002884 return removedFromHistory;
2885 }
2886
2887 boolean safelyDestroy(String reason) {
2888 if (isDestroyable()) {
2889 if (DEBUG_SWITCH) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002890 final ActivityStack stack = getRootTask();
Andrii Kulian79d67982019-08-19 11:56:16 -07002891 Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState()
2892 + " resumed=" + stack.mResumedActivity
2893 + " pausing=" + stack.mPausingActivity
2894 + " for reason " + reason);
2895 }
2896 return destroyImmediately(true /* removeFromApp */, reason);
2897 }
2898 return false;
2899 }
2900
2901 /** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
2902 void removeFromHistory(String reason) {
2903 finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
2904 makeFinishingLocked();
2905 if (ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE) {
2906 Slog.i(TAG_ADD_REMOVE, "Removing activity " + this + " from stack callers="
2907 + Debug.getCallers(5));
2908 }
2909
2910 takeFromHistory();
Wale Ogunwale196db712019-12-27 15:35:39 +00002911 removeTimeouts();
Andrii Kulian79d67982019-08-19 11:56:16 -07002912 if (DEBUG_STATES) {
2913 Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
2914 }
2915 setState(DESTROYED, "removeFromHistory");
2916 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
2917 app = null;
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002918 removeAppTokenFromDisplay();
Andrii Kulian79d67982019-08-19 11:56:16 -07002919
2920 cleanUpActivityServices();
2921 removeUriPermissionsLocked();
2922 }
2923
Wale Ogunwale7d701172015-03-11 15:36:30 -07002924 void makeFinishingLocked() {
Wale Ogunwalec981ad52017-06-13 11:40:06 -07002925 if (finishing) {
2926 return;
2927 }
2928 finishing = true;
2929 if (stopped) {
2930 clearOptionsLocked();
2931 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002932 }
2933
Andrii Kulian79d67982019-08-19 11:56:16 -07002934 /**
2935 * This method is to only be called from the client via binder when the activity is destroyed
2936 * AND finished.
2937 */
2938 void destroyed(String reason) {
Wale Ogunwale196db712019-12-27 15:35:39 +00002939 removeDestroyTimeout();
Andrii Kulian79d67982019-08-19 11:56:16 -07002940
2941 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + this);
2942
2943 if (!isState(DESTROYING, DESTROYED)) {
2944 throw new IllegalStateException(
2945 "Reported destroyed for activity that is not destroying: r=" + this);
2946 }
2947
2948 if (isInStackLocked()) {
2949 cleanUp(true /* cleanServices */, false /* setState */);
2950 removeFromHistory(reason);
2951 }
2952
Louis Chang149d5c82019-12-30 09:47:39 +08002953 mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kulian79d67982019-08-19 11:56:16 -07002954 }
2955
2956 /**
2957 * Perform the common clean-up of an activity record. This is called both as part of
2958 * destroyActivityLocked() (when destroying the client-side representation) and cleaning things
2959 * up as a result of its hosting processing going away, in which case there is no remaining
2960 * client-side state to destroy so only the cleanup here is needed.
2961 *
2962 * Note: Call before {@link #removeFromHistory(String)}.
2963 */
2964 void cleanUp(boolean cleanServices, boolean setState) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002965 task.cleanUpActivityReferences(this);
Andrii Kulian79d67982019-08-19 11:56:16 -07002966
2967 deferRelaunchUntilPaused = false;
2968 frozenBeforeDestroy = false;
2969
2970 if (setState) {
2971 setState(DESTROYED, "cleanUp");
2972 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this);
2973 app = null;
2974 }
2975
2976 // Inform supervisor the activity has been removed.
2977 mStackSupervisor.cleanupActivity(this);
2978
2979 // Remove any pending results.
2980 if (finishing && pendingResults != null) {
2981 for (WeakReference<PendingIntentRecord> apr : pendingResults) {
2982 PendingIntentRecord rec = apr.get();
2983 if (rec != null) {
2984 mAtmService.mPendingIntentController.cancelIntentSender(rec,
2985 false /* cleanActivity */);
2986 }
2987 }
2988 pendingResults = null;
2989 }
2990
2991 if (cleanServices) {
2992 cleanUpActivityServices();
2993 }
2994
2995 // Get rid of any pending idle timeouts.
Wale Ogunwale196db712019-12-27 15:35:39 +00002996 removeTimeouts();
Andrii Kulian79d67982019-08-19 11:56:16 -07002997 // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
2998 // manager so it can update its bookkeeping.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002999 clearRelaunching();
Andrii Kulian79d67982019-08-19 11:56:16 -07003000 }
3001
Garfield Tane8d84ab2019-10-11 09:49:40 -07003002 boolean isRelaunching() {
3003 return mPendingRelaunchCount > 0;
3004 }
3005
3006 boolean shouldFreezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003007 // For freeform windows, we can't freeze the bounds at the moment because this would make
3008 // the resizing unresponsive.
3009 if (task == null || task.inFreeformWindowingMode()) {
3010 return false;
3011 }
3012
3013 // We freeze the bounds while drag resizing to deal with the time between
3014 // the divider/drag handle being released, and the handling it's new
3015 // configuration. If we are relaunched outside of the drag resizing state,
3016 // we need to be careful not to do this.
Louis Changcdec0802019-11-11 11:45:07 +08003017 return task.isDragResizing();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003018 }
3019
3020 void startRelaunching() {
3021 if (shouldFreezeBounds()) {
3022 freezeBounds();
3023 }
3024
3025 // In the process of tearing down before relaunching, the app will
3026 // try and clean up it's child surfaces. We need to prevent this from
3027 // happening, so we sever the children, transfering their ownership
3028 // from the client it-self to the parent surface (owned by us).
3029 detachChildren();
3030
3031 mPendingRelaunchCount++;
3032 }
3033
3034 /**
3035 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
3036 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
3037 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
3038 * with a queue.
3039 */
3040 private void freezeBounds() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003041 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
3042
3043 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
3044 // We didn't call prepareFreezingBounds on the task, so use the current value.
3045 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
3046 } else {
3047 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
3048 }
3049 // Calling unset() to make it equal to Configuration.EMPTY.
3050 task.mPreparedFrozenMergedConfig.unset();
3051 }
3052
3053 void detachChildren() {
3054 SurfaceControl.openTransaction();
3055 for (int i = mChildren.size() - 1; i >= 0; i--) {
3056 final WindowState w = mChildren.get(i);
3057 w.mWinAnimator.detachChildren();
3058 }
3059 SurfaceControl.closeTransaction();
3060 }
3061
3062 void finishRelaunching() {
3063 unfreezeBounds();
3064
3065 if (mPendingRelaunchCount > 0) {
3066 mPendingRelaunchCount--;
3067 } else {
3068 // Update keyguard flags upon finishing relaunch.
3069 checkKeyguardFlagsChanged();
3070 }
3071 }
3072
3073 void clearRelaunching() {
3074 if (mPendingRelaunchCount == 0) {
3075 return;
3076 }
3077 unfreezeBounds();
3078 mPendingRelaunchCount = 0;
3079 }
3080
3081 /**
3082 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
3083 */
3084 private void unfreezeBounds() {
3085 if (mFrozenBounds.isEmpty()) {
3086 return;
3087 }
3088 mFrozenBounds.remove();
3089 if (!mFrozenMergedConfig.isEmpty()) {
3090 mFrozenMergedConfig.remove();
3091 }
3092 for (int i = mChildren.size() - 1; i >= 0; i--) {
3093 final WindowState win = mChildren.get(i);
3094 win.onUnfreezeBounds();
3095 }
3096 mWmService.mWindowPlacerLocked.performSurfacePlacement();
3097 }
3098
Andrii Kulian79d67982019-08-19 11:56:16 -07003099 /**
3100 * Perform clean-up of service connections in an activity record.
3101 */
3102 private void cleanUpActivityServices() {
3103 if (mServiceConnectionsHolder == null) {
3104 return;
3105 }
3106 // Throw away any services that have been bound by this activity.
3107 mServiceConnectionsHolder.disconnectActivityFromServices();
Riddle Hsu60a494a2020-02-02 18:01:54 +08003108 // This activity record is removing, make sure not to disconnect twice.
3109 mServiceConnectionsHolder = null;
Andrii Kulian79d67982019-08-19 11:56:16 -07003110 }
3111
Garfield Tane8d84ab2019-10-11 09:49:40 -07003112 @Override
3113 void removeImmediately() {
3114 onRemovedFromDisplay();
3115 super.removeImmediately();
3116 }
3117
3118 @Override
3119 void removeIfPossible() {
3120 mIsExiting = false;
3121 removeAllWindowsIfPossible();
3122 removeImmediately();
3123 }
3124
3125 @Override
3126 boolean checkCompleteDeferredRemoval() {
3127 if (mIsExiting) {
3128 removeIfPossible();
3129 }
3130 return super.checkCompleteDeferredRemoval();
3131 }
3132
3133 void onRemovedFromDisplay() {
3134 if (mRemovingFromDisplay) {
3135 return;
3136 }
3137 mRemovingFromDisplay = true;
3138
3139 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
3140
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003141 commitVisibility(false /* visible */, true /* performLayout */);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003142
3143 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky55bddd82020-01-29 13:07:18 -08003144 getDisplayContent().mChangingContainers.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003145 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
3146 mWmService.mTaskSnapshotController.onAppRemoved(this);
Riddle Hsufd66d4d2019-11-14 10:35:55 +08003147 mStackSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003148 waitingToShow = false;
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003149
Issei Suzuki68caca92020-01-27 12:41:54 +01003150 // Defer removal of this activity when either a child is animating, or app transition is on
3151 // going. App transition animation might be applied on the parent stack not on the activity,
3152 // but the actual frame buffer is associated with the activity, so we have to keep the
3153 // activity while a parent is animating.
3154 boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003155 if (getDisplayContent().mClosingApps.contains(this)) {
3156 delayed = true;
3157 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
3158 getDisplayContent().mClosingApps.add(this);
3159 delayed = true;
3160 }
3161
3162 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
3163 "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
lumark5bd11af2019-12-21 01:52:28 +08003164 getAnimation(), isAnimating(TRANSITION | PARENTS));
Garfield Tane8d84ab2019-10-11 09:49:40 -07003165
3166 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
3167 + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
3168
3169 if (mStartingData != null) {
3170 removeStartingWindow();
3171 }
3172
3173 // If this window was animating, then we need to ensure that the app transition notifies
3174 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
3175 // so add to that list now
lumark5bd11af2019-12-21 01:52:28 +08003176 if (isAnimating(TRANSITION | PARENTS)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003177 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
3178 }
3179
Louis Changdc077272019-11-12 16:52:56 +08003180 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003181 if (delayed && !isEmpty()) {
3182 // set the token aside because it has an active animation to be finished
3183 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3184 "removeAppToken make exiting: %s", this);
3185 if (stack != null) {
3186 stack.mExitingActivities.add(this);
3187 }
3188 mIsExiting = true;
3189 } else {
3190 // Make sure there is no animation running on this token, so any windows associated
3191 // with it will be removed as soon as their animations are complete
3192 cancelAnimation();
3193 if (stack != null) {
3194 stack.mExitingActivities.remove(this);
3195 }
3196 removeIfPossible();
3197 }
3198
Garfield Tane8d84ab2019-10-11 09:49:40 -07003199 stopFreezingScreen(true, true);
3200
3201 final DisplayContent dc = getDisplayContent();
3202 if (dc.mFocusedApp == this) {
3203 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
3204 "Removing focused app token:%s displayId=%d", this,
3205 dc.getDisplayId());
3206 dc.setFocusedApp(null);
3207 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3208 }
3209 if (mLetterbox != null) {
3210 mLetterbox.destroy();
3211 mLetterbox = null;
3212 }
3213
3214 if (!delayed) {
3215 updateReportedVisibilityLocked();
3216 }
3217
3218 // Reset the last saved PiP snap fraction on removal.
Hongwei Wang221fe3d2020-03-26 13:13:04 -07003219 mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
Vishnu Nairfca78472020-03-09 15:34:47 -07003220 mWmService.mEmbeddedWindowController.onActivityRemoved(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003221 mRemovingFromDisplay = false;
3222 }
3223
3224 /**
3225 * Returns true if the new child window we are adding to this token is considered greater than
3226 * the existing child window in this token in terms of z-order.
3227 */
3228 @Override
3229 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
3230 WindowState existingWindow) {
3231 final int type1 = newWindow.mAttrs.type;
3232 final int type2 = existingWindow.mAttrs.type;
3233
3234 // Base application windows should be z-ordered BELOW all other windows in the app token.
3235 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
3236 return false;
3237 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
3238 return true;
3239 }
3240
3241 // Starting windows should be z-ordered ABOVE all other windows in the app token.
3242 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
3243 return true;
3244 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
3245 return false;
3246 }
3247
3248 // Otherwise the new window is greater than the existing window.
3249 return true;
3250 }
3251
3252 /**
3253 * @return {@code true} if starting window is in app's hierarchy.
3254 */
3255 boolean hasStartingWindow() {
3256 if (startingDisplayed || mStartingData != null) {
3257 return true;
3258 }
3259 for (int i = mChildren.size() - 1; i >= 0; i--) {
3260 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
3261 return true;
3262 }
3263 }
3264 return false;
3265 }
3266
3267 boolean isLastWindow(WindowState win) {
3268 return mChildren.size() == 1 && mChildren.get(0) == win;
3269 }
3270
3271 @Override
3272 void addWindow(WindowState w) {
3273 super.addWindow(w);
3274
3275 boolean gotReplacementWindow = false;
3276 for (int i = mChildren.size() - 1; i >= 0; i--) {
3277 final WindowState candidate = mChildren.get(i);
3278 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
3279 }
3280
3281 // if we got a replacement window, reset the timeout to give drawing more time
3282 if (gotReplacementWindow) {
3283 mWmService.scheduleWindowReplacementTimeouts(this);
3284 }
3285 checkKeyguardFlagsChanged();
3286 }
3287
3288 @Override
3289 void removeChild(WindowState child) {
3290 if (!mChildren.contains(child)) {
3291 // This can be true when testing.
3292 return;
3293 }
3294 super.removeChild(child);
3295 checkKeyguardFlagsChanged();
3296 updateLetterboxSurface(child);
3297 }
3298
Garfield Tane8d84ab2019-10-11 09:49:40 -07003299 void onWindowReplacementTimeout() {
3300 for (int i = mChildren.size() - 1; i >= 0; --i) {
3301 (mChildren.get(i)).onWindowReplacementTimeout();
3302 }
3303 }
3304
3305 void setAppLayoutChanges(int changes, String reason) {
3306 if (!mChildren.isEmpty()) {
3307 final DisplayContent dc = getDisplayContent();
3308 dc.pendingLayoutChanges |= changes;
3309 if (DEBUG_LAYOUT_REPEATS) {
3310 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
3311 }
3312 }
3313 }
3314
3315 void removeReplacedWindowIfNeeded(WindowState replacement) {
3316 for (int i = mChildren.size() - 1; i >= 0; i--) {
3317 final WindowState win = mChildren.get(i);
3318 if (win.removeReplacedWindowIfNeeded(replacement)) {
3319 return;
3320 }
3321 }
3322 }
3323
3324 boolean transferStartingWindow(IBinder transferFrom) {
3325 final ActivityRecord fromActivity = getDisplayContent().getActivityRecord(transferFrom);
3326 if (fromActivity == null) {
3327 return false;
3328 }
3329
3330 final WindowState tStartingWindow = fromActivity.startingWindow;
3331 if (tStartingWindow != null && fromActivity.startingSurface != null) {
3332 // In this case, the starting icon has already been displayed, so start
3333 // letting windows get shown immediately without any more transitions.
3334 getDisplayContent().mSkipAppTransitionAnimation = true;
3335
3336 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
3337 + " from %s to %s", tStartingWindow, fromActivity, this);
3338
3339 final long origId = Binder.clearCallingIdentity();
3340 try {
3341 // Transfer the starting window over to the new token.
3342 mStartingData = fromActivity.mStartingData;
3343 startingSurface = fromActivity.startingSurface;
3344 startingDisplayed = fromActivity.startingDisplayed;
3345 fromActivity.startingDisplayed = false;
3346 startingWindow = tStartingWindow;
3347 reportedVisible = fromActivity.reportedVisible;
3348 fromActivity.mStartingData = null;
3349 fromActivity.startingSurface = null;
3350 fromActivity.startingWindow = null;
3351 fromActivity.startingMoved = true;
3352 tStartingWindow.mToken = this;
3353 tStartingWindow.mActivityRecord = this;
3354
3355 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3356 "Removing starting %s from %s", tStartingWindow, fromActivity);
3357 fromActivity.removeChild(tStartingWindow);
3358 fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
Issei Suzukif2f6c912019-11-08 11:24:18 +01003359 fromActivity.mVisibleSetFromTransferredStartingWindow = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003360 addWindow(tStartingWindow);
3361
3362 // Propagate other interesting state between the tokens. If the old token is displayed,
3363 // we should immediately force the new one to be displayed. If it is animating, we need
3364 // to move that animation to the new one.
3365 if (fromActivity.allDrawn) {
3366 allDrawn = true;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003367 }
3368 if (fromActivity.firstWindowDrawn) {
3369 firstWindowDrawn = true;
3370 }
Issei Suzukif2f6c912019-11-08 11:24:18 +01003371 if (fromActivity.isVisible()) {
3372 setVisible(true);
Issei Suzuki1669ea42019-11-06 14:20:59 +01003373 mVisibleRequested = true;
Issei Suzukif2f6c912019-11-08 11:24:18 +01003374 mVisibleSetFromTransferredStartingWindow = true;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003375 }
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01003376 setClientVisible(fromActivity.mClientVisible);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003377
3378 transferAnimation(fromActivity);
3379
3380 // When transferring an animation, we no longer need to apply an animation to the
3381 // the token we transfer the animation over. Thus, set this flag to indicate we've
3382 // transferred the animation.
3383 mUseTransferredAnimation = true;
3384
3385 mWmService.updateFocusedWindowLocked(
3386 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
3387 getDisplayContent().setLayoutNeeded();
3388 mWmService.mWindowPlacerLocked.performSurfacePlacement();
3389 } finally {
3390 Binder.restoreCallingIdentity(origId);
3391 }
3392 return true;
3393 } else if (fromActivity.mStartingData != null) {
3394 // The previous app was getting ready to show a
3395 // starting window, but hasn't yet done so. Steal it!
3396 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
3397 "Moving pending starting from %s to %s", fromActivity, this);
3398 mStartingData = fromActivity.mStartingData;
3399 fromActivity.mStartingData = null;
3400 fromActivity.startingMoved = true;
3401 scheduleAddStartingWindow();
3402 return true;
3403 }
3404
3405 // TODO: Transfer thumbnail
3406
3407 return false;
3408 }
3409
3410 /**
3411 * Tries to transfer the starting window from a token that's above ourselves in the task but
3412 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
3413 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
3414 * immediately finishes after, so we have to transfer T to M.
3415 */
3416 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003417 final PooledFunction p = PooledLambda.obtainFunction(ActivityRecord::transferStartingWindow,
3418 this, PooledLambda.__(ActivityRecord.class));
3419 task.forAllActivities(p);
3420 p.recycle();
3421 }
3422
3423 private boolean transferStartingWindow(ActivityRecord fromActivity) {
3424 if (fromActivity == this) return true;
3425
3426 return !fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003427 }
3428
3429 void checkKeyguardFlagsChanged() {
3430 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
3431 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
3432 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
3433 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
3434 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
3435 getDisplayContent().getDisplayId());
3436 }
3437 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
3438 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
Andrii Kulian46799182019-10-17 16:26:17 -07003439 mLastContainsTurnScreenOnWindow = containsTurnScreenOnWindow();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003440 }
3441
3442 boolean containsDismissKeyguardWindow() {
3443 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
3444 // entirety of the relaunch.
3445 if (isRelaunching()) {
3446 return mLastContainsDismissKeyguardWindow;
3447 }
3448
3449 for (int i = mChildren.size() - 1; i >= 0; i--) {
3450 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
3451 return true;
3452 }
3453 }
3454 return false;
3455 }
3456
3457 boolean containsShowWhenLockedWindow() {
3458 // When we are relaunching, it is possible for us to be unfrozen before our previous
3459 // windows have been added back. Using the cached value ensures that our previous
3460 // showWhenLocked preference is honored until relaunching is complete.
3461 if (isRelaunching()) {
3462 return mLastContainsShowWhenLockedWindow;
3463 }
3464
3465 for (int i = mChildren.size() - 1; i >= 0; i--) {
3466 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
3467 return true;
3468 }
3469 }
3470
3471 return false;
3472 }
3473
3474 void setShowWhenLocked(boolean showWhenLocked) {
3475 mShowWhenLocked = showWhenLocked;
Louis Chang149d5c82019-12-30 09:47:39 +08003476 mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
Garfield Tane8d84ab2019-10-11 09:49:40 -07003477 0 /* configChanges */, false /* preserveWindows */);
3478 }
3479
3480 void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
3481 mInheritShownWhenLocked = inheritShowWhenLocked;
Louis Chang149d5c82019-12-30 09:47:39 +08003482 mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
Garfield Tane8d84ab2019-10-11 09:49:40 -07003483 0 /* configChanges */, false /* preserveWindows */);
3484 }
3485
3486 /**
3487 * @return {@code true} if the activity windowing mode is not
3488 * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
3489 * contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
3490 * activity has set {@link #mShowWhenLocked}, or b) if the activity has set
3491 * {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
3492 * conditions a) above.
3493 * Multi-windowing mode will be exited if {@code true} is returned.
3494 */
3495 boolean canShowWhenLocked() {
3496 if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
3497 return true;
3498 } else if (mInheritShownWhenLocked) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003499 final ActivityRecord r = task.getActivityBelow(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07003500 return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
3501 || r.containsShowWhenLockedWindow());
3502 } else {
3503 return false;
3504 }
3505 }
3506
3507 /**
3508 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3509 * showing windows during transitions in case we have windows that have wide-color-gamut
3510 * color mode set to avoid jank in the middle of the transition.
3511 */
3512 boolean canShowWindows() {
lumark5341d1c2019-12-14 01:54:02 +08003513 return allDrawn && !(isAnimating(PARENTS) && hasNonDefaultColorWindow());
Garfield Tane8d84ab2019-10-11 09:49:40 -07003514 }
3515
3516 /**
3517 * @return true if we have a window that has a non-default color mode set; false otherwise.
3518 */
3519 private boolean hasNonDefaultColorWindow() {
3520 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3521 true /* topToBottom */);
3522 }
3523
Garfield Tane8d84ab2019-10-11 09:49:40 -07003524 WindowState getImeTargetBelowWindow(WindowState w) {
3525 final int index = mChildren.indexOf(w);
3526 if (index > 0) {
3527 final WindowState target = mChildren.get(index - 1);
3528 if (target.canBeImeTarget()) {
3529 return target;
3530 }
3531 }
3532 return null;
3533 }
3534
3535 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
3536 WindowState candidate = null;
3537 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
3538 final WindowState w = mChildren.get(i);
3539 if (w.mRemoved) {
3540 continue;
3541 }
3542 if (candidate == null) {
3543 candidate = w;
3544 }
3545 }
3546 return candidate;
3547 }
3548
3549 @Override
3550 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
3551 // For legacy reasons we process the TaskStack.mExitingActivities first in DisplayContent
3552 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
3553 // TODO: Investigate if we need to continue to do this or if we can just process them
3554 // in-order.
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003555 if (mIsExiting && !forAllWindowsUnchecked(WindowState::waitingForReplacement, true)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003556 return false;
3557 }
3558 return forAllWindowsUnchecked(callback, traverseTopToBottom);
3559 }
3560
Garfield Tane8d84ab2019-10-11 09:49:40 -07003561 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
3562 boolean traverseTopToBottom) {
3563 return super.forAllWindows(callback, traverseTopToBottom);
3564 }
3565
3566 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003567 boolean forAllActivities(
3568 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
lumark9bca6b42019-10-17 18:35:22 +08003569 return callback.apply(this);
3570 }
3571
3572 @Override
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08003573 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
3574 callback.accept(this);
3575 }
3576
3577 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003578 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
3579 WindowContainer boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08003580 return callback.test(this) ? this : null;
3581 }
3582
3583 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07003584 protected void setLayer(Transaction t, int layer) {
3585 if (!mSurfaceAnimator.hasLeash()) {
3586 t.setLayer(mSurfaceControl, layer);
3587 }
3588 }
3589
3590 @Override
3591 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
3592 if (!mSurfaceAnimator.hasLeash()) {
3593 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
3594 }
3595 }
3596
3597 @Override
3598 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
3599 if (!mSurfaceAnimator.hasLeash()) {
3600 t.reparent(mSurfaceControl, newParent);
3601 }
3602 }
3603
Louis Changcdec0802019-11-11 11:45:07 +08003604 void logStartActivity(int tag, Task task) {
Andrii Kulian79d67982019-08-19 11:56:16 -07003605 final Uri data = intent.getData();
3606 final String strData = data != null ? data.toSafeString() : null;
3607
3608 EventLog.writeEvent(tag,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07003609 mUserId, System.identityHashCode(this), task.mTaskId,
Andrii Kulian79d67982019-08-19 11:56:16 -07003610 shortComponentName, intent.getAction(),
3611 intent.getType(), strData, intent.getFlags());
3612 }
3613
Dianne Hackborn7e269642010-08-25 19:50:20 -07003614 UriPermissionOwner getUriPermissionsLocked() {
3615 if (uriPermissions == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003616 uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
Dianne Hackborn7e269642010-08-25 19:50:20 -07003617 }
3618 return uriPermissions;
3619 }
3620
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003621 void addResultLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 int requestCode, int resultCode,
3623 Intent resultData) {
3624 ActivityResult r = new ActivityResult(from, resultWho,
John Spurlock8a985d22014-02-25 09:40:05 -05003625 requestCode, resultCode, resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 if (results == null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003627 results = new ArrayList<ResultInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 }
3629 results.add(r);
3630 }
3631
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003632 void removeResultsLocked(ActivityRecord from, String resultWho,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 int requestCode) {
3634 if (results != null) {
3635 for (int i=results.size()-1; i>=0; i--) {
3636 ActivityResult r = (ActivityResult)results.get(i);
3637 if (r.mFrom != from) continue;
3638 if (r.mResultWho == null) {
3639 if (resultWho != null) continue;
3640 } else {
3641 if (!r.mResultWho.equals(resultWho)) continue;
3642 }
3643 if (r.mRequestCode != requestCode) continue;
3644
3645 results.remove(i);
3646 }
3647 }
3648 }
3649
Andrii Kulian79d67982019-08-19 11:56:16 -07003650 void sendResult(int callingUid, String resultWho, int requestCode, int resultCode,
3651 Intent data) {
3652 if (callingUid > 0) {
3653 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3654 data, getUriPermissionsLocked(), mUserId);
3655 }
3656
3657 if (DEBUG_RESULTS) {
3658 Slog.v(TAG, "Send activity result to " + this
3659 + " : who=" + resultWho + " req=" + requestCode
3660 + " res=" + resultCode + " data=" + data);
3661 }
3662 if (isState(RESUMED) && attachedToProcess()) {
3663 try {
3664 final ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3665 list.add(new ResultInfo(resultWho, requestCode, resultCode, data));
3666 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3667 ActivityResultItem.obtain(list));
3668 return;
3669 } catch (Exception e) {
3670 Slog.w(TAG, "Exception thrown sending result to " + this, e);
3671 }
3672 }
3673
3674 addResultLocked(null /* from */, resultWho, requestCode, resultCode, data);
3675 }
3676
Andrii Kulian21713ac2016-10-12 22:05:05 -07003677 private void addNewIntentLocked(ReferrerIntent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003678 if (newIntents == null) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003679 newIntents = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 }
3681 newIntents.add(intent);
3682 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07003683
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003684 final boolean isSleeping() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003685 final ActivityStack stack = getRootTask();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003686 return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003687 }
3688
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003689 /**
3690 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3691 * method will be called at the proper time.
3692 */
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003693 final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
Dianne Hackborn514074f2013-02-11 10:52:46 -08003694 // The activity now gets access to the data associated with this Intent.
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00003695 mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
3696 intent, getUriPermissionsLocked(), mUserId);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003697 final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
Craig Mautner86d67a42013-05-14 10:34:38 -07003698 boolean unsent = true;
Robert Carr9e1bf7c2018-05-31 15:39:07 -07003699 final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
Wale Ogunwale826c7062016-09-13 08:25:54 -07003700
3701 // We want to immediately deliver the intent to the activity if:
Wale Ogunwale03f7e9e2016-09-22 09:04:09 -07003702 // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
3703 // the user to see the visual effects caused by the intent delivery now.
Wale Ogunwale826c7062016-09-13 08:25:54 -07003704 // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07003705 if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
3706 && attachedToProcess()) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003707 try {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003708 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
3709 ar.add(rintent);
Louis Changea203cd2019-07-01 12:39:31 +08003710 // Making sure the client state is RESUMED after transaction completed and doing
3711 // so only if activity is currently RESUMED. Otherwise, client may have extra
3712 // life-cycle calls to RESUMED (and PAUSED later).
Louis Chang92d16522019-02-27 12:56:18 +08003713 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Louis Changea203cd2019-07-01 12:39:31 +08003714 NewIntentItem.obtain(ar, mState == RESUMED));
Craig Mautner86d67a42013-05-14 10:34:38 -07003715 unsent = false;
Dianne Hackborn39792d22010-08-19 18:01:52 -07003716 } catch (RemoteException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003717 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003718 } catch (NullPointerException e) {
Wale Ogunwalee23149f2015-03-06 15:39:44 -08003719 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003720 }
3721 }
Craig Mautner86d67a42013-05-14 10:34:38 -07003722 if (unsent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08003723 addNewIntentLocked(rintent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003724 }
3725 }
3726
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003727 void updateOptionsLocked(ActivityOptions options) {
3728 if (options != null) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003729 if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003730 if (pendingOptions != null) {
3731 pendingOptions.abort();
3732 }
3733 pendingOptions = options;
3734 }
3735 }
3736
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003737 void applyOptionsLocked() {
George Mount2c92c972014-03-20 09:38:23 -07003738 if (pendingOptions != null
Ruben Brunkf53497c2017-03-27 20:26:17 -07003739 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
Jorim Jaggi346702a2019-05-08 17:49:33 +02003740 if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003741 applyOptionsLocked(pendingOptions, intent);
chaviw82a0ba82018-03-15 14:26:29 -07003742 if (task == null) {
3743 clearOptionsLocked(false /* withAbort */);
3744 } else {
3745 // This will clear the options for all the ActivityRecords for this Task.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003746 task.forAllActivities((r) -> {
3747 r.clearOptionsLocked(false /* withAbort */);
3748 });
chaviw82a0ba82018-03-15 14:26:29 -07003749 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003750 }
3751 }
3752
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003753 /**
3754 * Apply override app transition base on options & animation type.
3755 */
3756 void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
3757 final int animationType = pendingOptions.getAnimationType();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003758 final DisplayContent displayContent = getDisplayContent();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003759 switch (animationType) {
3760 case ANIM_CUSTOM:
3761 displayContent.mAppTransition.overridePendingAppTransition(
3762 pendingOptions.getPackageName(),
3763 pendingOptions.getCustomEnterResId(),
3764 pendingOptions.getCustomExitResId(),
3765 pendingOptions.getOnAnimationStartListener());
3766 break;
3767 case ANIM_CLIP_REVEAL:
3768 displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
3769 pendingOptions.getStartX(), pendingOptions.getStartY(),
3770 pendingOptions.getWidth(), pendingOptions.getHeight());
3771 if (intent.getSourceBounds() == null) {
3772 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3773 pendingOptions.getStartY(),
3774 pendingOptions.getStartX() + pendingOptions.getWidth(),
3775 pendingOptions.getStartY() + pendingOptions.getHeight()));
3776 }
3777 break;
3778 case ANIM_SCALE_UP:
3779 displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
3780 pendingOptions.getStartX(), pendingOptions.getStartY(),
3781 pendingOptions.getWidth(), pendingOptions.getHeight());
3782 if (intent.getSourceBounds() == null) {
3783 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3784 pendingOptions.getStartY(),
3785 pendingOptions.getStartX() + pendingOptions.getWidth(),
3786 pendingOptions.getStartY() + pendingOptions.getHeight()));
3787 }
3788 break;
3789 case ANIM_THUMBNAIL_SCALE_UP:
3790 case ANIM_THUMBNAIL_SCALE_DOWN:
3791 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
3792 final GraphicBuffer buffer = pendingOptions.getThumbnail();
3793 displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
3794 pendingOptions.getStartX(), pendingOptions.getStartY(),
3795 pendingOptions.getOnAnimationStartListener(),
3796 scaleUp);
3797 if (intent.getSourceBounds() == null && buffer != null) {
3798 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3799 pendingOptions.getStartY(),
3800 pendingOptions.getStartX() + buffer.getWidth(),
3801 pendingOptions.getStartY() + buffer.getHeight()));
3802 }
3803 break;
3804 case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
3805 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
3806 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
3807 final IAppTransitionAnimationSpecsFuture specsFuture =
3808 pendingOptions.getSpecsFuture();
3809 if (specsFuture != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003810 displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
3811 specsFuture, pendingOptions.getOnAnimationStartListener(),
3812 animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
3813 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
3814 && specs != null) {
3815 displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
3816 specs, pendingOptions.getOnAnimationStartListener(),
3817 pendingOptions.getAnimationFinishedListener(), false);
3818 } else {
3819 displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
3820 pendingOptions.getThumbnail(),
3821 pendingOptions.getStartX(), pendingOptions.getStartY(),
3822 pendingOptions.getWidth(), pendingOptions.getHeight(),
3823 pendingOptions.getOnAnimationStartListener(),
3824 (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
3825 if (intent.getSourceBounds() == null) {
3826 intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3827 pendingOptions.getStartY(),
3828 pendingOptions.getStartX() + pendingOptions.getWidth(),
3829 pendingOptions.getStartY() + pendingOptions.getHeight()));
3830 }
3831 }
3832 break;
3833 case ANIM_OPEN_CROSS_PROFILE_APPS:
3834 displayContent.mAppTransition
3835 .overridePendingAppTransitionStartCrossProfileApps();
3836 break;
3837 case ANIM_REMOTE_ANIMATION:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003838 displayContent.mAppTransition.overridePendingAppTransitionRemote(
3839 pendingOptions.getRemoteAnimationAdapter());
3840 break;
3841 case ANIM_NONE:
Louis Chang477e93e2019-04-24 18:35:20 +08003842 case ANIM_UNDEFINED:
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08003843 break;
3844 default:
3845 Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
3846 break;
3847 }
3848 }
3849
Garfield Tane8d84ab2019-10-11 09:49:40 -07003850 void clearAllDrawn() {
3851 allDrawn = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07003852 }
3853
3854 /**
3855 * Returns whether the drawn window states of this {@link ActivityRecord} has considered every
3856 * child {@link WindowState}. A child is considered if it has been passed into
3857 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
3858 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
3859 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
3860 *
3861 * @return {@code true} If all children have been considered, {@code false}.
3862 */
3863 private boolean allDrawnStatesConsidered() {
3864 for (int i = mChildren.size() - 1; i >= 0; --i) {
3865 final WindowState child = mChildren.get(i);
3866 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
3867 return false;
3868 }
3869 }
3870 return true;
3871 }
3872
3873 /**
3874 * Determines if the token has finished drawing. This should only be called from
3875 * {@link DisplayContent#applySurfaceChangesTransaction}
3876 */
3877 void updateAllDrawn() {
3878 if (!allDrawn) {
3879 // Number of drawn windows can be less when a window is being relaunched, wait for
3880 // all windows to be launched and drawn for this token be considered all drawn.
3881 final int numInteresting = mNumInterestingWindows;
3882
3883 // We must make sure that all present children have been considered (determined by
3884 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
3885 // drawn.
3886 if (numInteresting > 0 && allDrawnStatesConsidered()
3887 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
3888 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
3889 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
3890 allDrawn = true;
3891 // Force an additional layout pass where
3892 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
3893 if (mDisplayContent != null) {
3894 mDisplayContent.setLayoutNeeded();
3895 }
3896 mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Garfield Tane8d84ab2019-10-11 09:49:40 -07003897 }
3898 }
3899 }
3900
Adam Powellcfbe9be2013-11-06 14:58:58 -08003901 ActivityOptions getOptionsForTargetActivityLocked() {
3902 return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
3903 }
3904
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003905 void clearOptionsLocked() {
chaviw82a0ba82018-03-15 14:26:29 -07003906 clearOptionsLocked(true /* withAbort */);
3907 }
3908
3909 void clearOptionsLocked(boolean withAbort) {
3910 if (withAbort && pendingOptions != null) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003911 pendingOptions.abort();
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003912 }
chaviw82a0ba82018-03-15 14:26:29 -07003913 pendingOptions = null;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003914 }
3915
Jorim Jaggi346702a2019-05-08 17:49:33 +02003916 ActivityOptions takeOptionsLocked(boolean fromClient) {
3917 if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
3918 + Debug.getCallers(6));
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003919 ActivityOptions opts = pendingOptions;
Jorim Jaggi346702a2019-05-08 17:49:33 +02003920
3921 // If we are trying to take activity options from the client, do not null it out if it's a
3922 // remote animation as the client doesn't need it ever. This is a workaround when client is
3923 // faster to take the options than we are to resume the next activity.
3924 // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
3925 // timing somehow
3926 if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
3927 pendingOptions = null;
3928 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07003929 return opts;
3930 }
3931
Issei Suzuki1669ea42019-11-06 14:20:59 +01003932 boolean allowMoveToFront() {
3933 return pendingOptions == null || !pendingOptions.getAvoidMoveToFront();
3934 }
3935
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003936 void removeUriPermissionsLocked() {
Dianne Hackborn7e269642010-08-25 19:50:20 -07003937 if (uriPermissions != null) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003938 uriPermissions.removeUriPermissions();
Dianne Hackborn7e269642010-08-25 19:50:20 -07003939 uriPermissions = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003940 }
3941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942
3943 void pauseKeyDispatchingLocked() {
3944 if (!keysPaused) {
3945 keysPaused = true;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003946
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003947 if (getDisplayContent() != null) {
3948 getDisplayContent().getInputMonitor().pauseDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 }
3951 }
3952
3953 void resumeKeyDispatchingLocked() {
3954 if (keysPaused) {
3955 keysPaused = false;
Bryce Lee2b8e0372018-04-05 17:01:37 -07003956
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003957 if (getDisplayContent() != null) {
3958 getDisplayContent().getInputMonitor().resumeDispatchingLw(this);
Bryce Lee2b8e0372018-04-05 17:01:37 -07003959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 }
3961 }
3962
Jorim Jaggie7d2b852017-08-28 17:55:15 +02003963 private void updateTaskDescription(CharSequence description) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07003964 task.lastDescription = description;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003965 }
3966
Wale Ogunwaleec950642017-04-25 07:44:21 -07003967 void setDeferHidingClient(boolean deferHidingClient) {
3968 if (mDeferHidingClient == deferHidingClient) {
3969 return;
3970 }
3971 mDeferHidingClient = deferHidingClient;
Issei Suzuki1669ea42019-11-06 14:20:59 +01003972 if (!mDeferHidingClient && !mVisibleRequested) {
Wale Ogunwaleec950642017-04-25 07:44:21 -07003973 // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
3974 // update the visibility.
3975 setVisibility(false);
3976 }
Wale Ogunwale89973222017-04-23 18:39:45 -07003977 }
3978
Garfield Tane8d84ab2019-10-11 09:49:40 -07003979 @Override
3980 boolean isVisible() {
3981 // If the activity isn't hidden then it is considered visible and there is no need to check
3982 // its children windows to see if they are visible.
Issei Suzukif2f6c912019-11-08 11:24:18 +01003983 return mVisible;
3984 }
3985
3986 void setVisible(boolean visible) {
3987 if (visible != mVisible) {
3988 mVisible = visible;
3989 scheduleAnimation();
3990 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07003991 }
3992
Issei Suzuki2bcbd682019-11-08 13:20:14 +01003993 /**
3994 * Set visibility on this {@link ActivityRecord}
3995 *
3996 * <p class="note"><strong>Note: </strong>This function might not update the visibility of
3997 * this {@link ActivityRecord} immediately. In case we are preparing an app transition, we
3998 * delay changing the visibility of this {@link ActivityRecord} until we execute that
3999 * transition.</p>
4000 *
4001 * @param visible {@code true} if the {@link ActivityRecord} should become visible, otherwise
4002 * this should become invisible.
4003 */
Wale Ogunwaleec950642017-04-25 07:44:21 -07004004 void setVisibility(boolean visible) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004005 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004006 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
4007 + appToken);
4008 return;
4009 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01004010 if (visible) {
4011 mDeferHidingClient = false;
4012 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004013 setVisibility(visible, mDeferHidingClient);
Riddle Hsua0022cd2019-09-09 21:12:41 +08004014 mAtmService.addWindowLayoutReasons(
4015 ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
Bryce Lee2a3cc462017-10-27 10:57:35 -07004016 mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004017 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
4018 }
4019
Issei Suzuki1669ea42019-11-06 14:20:59 +01004020 @VisibleForTesting
Garfield Tane8d84ab2019-10-11 09:49:40 -07004021 void setVisibility(boolean visible, boolean deferHidingClient) {
4022 final AppTransition appTransition = getDisplayContent().mAppTransition;
4023
4024 // Don't set visibility to false if we were already not visible. This prevents WM from
4025 // adding the app to the closing app list which doesn't make sense for something that is
4026 // already not visible. However, set visibility to true even if we are already visible.
4027 // This makes sure the app is added to the opening apps list so that the right
4028 // transition can be selected.
4029 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
4030 // concept of setting visibility...
Issei Suzuki1669ea42019-11-06 14:20:59 +01004031 if (!visible && !mVisibleRequested) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004032
4033 if (!deferHidingClient && mLastDeferHidingClient) {
4034 // We previously deferred telling the client to hide itself when visibility was
4035 // initially set to false. Now we would like it to hide, so go ahead and set it.
4036 mLastDeferHidingClient = deferHidingClient;
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01004037 setClientVisible(false);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004038 }
4039 return;
4040 }
4041
4042 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzukif2f6c912019-11-08 11:24:18 +01004043 "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
4044 appToken, visible, appTransition, isVisible(), mVisibleRequested,
Garfield Tane8d84ab2019-10-11 09:49:40 -07004045 Debug.getCallers(6));
4046
Evan Rosky55bddd82020-01-29 13:07:18 -08004047 onChildVisibilityRequested(visible);
4048
Garfield Tane8d84ab2019-10-11 09:49:40 -07004049 final DisplayContent displayContent = getDisplayContent();
4050 displayContent.mOpeningApps.remove(this);
4051 displayContent.mClosingApps.remove(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004052 waitingToShow = false;
Issei Suzuki1669ea42019-11-06 14:20:59 +01004053 mVisibleRequested = visible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07004054 mLastDeferHidingClient = deferHidingClient;
4055
4056 if (!visible) {
4057 // If the app is dead while it was visible, we kept its dead window on screen.
4058 // Now that the app is going invisible, we can remove it. It will be restarted
4059 // if made visible again.
4060 removeDeadWindows();
4061 } else {
4062 if (!appTransition.isTransitionSet()
4063 && appTransition.isReady()) {
4064 // Add the app mOpeningApps if transition is unset but ready. This means
4065 // we're doing a screen freeze, and the unfreeze will wait for all opening
4066 // apps to be ready.
4067 displayContent.mOpeningApps.add(this);
4068 }
4069 startingMoved = false;
4070 // If the token is currently hidden (should be the common case), or has been
4071 // stopped, then we need to set up to wait for its windows to be ready.
Issei Suzukif2f6c912019-11-08 11:24:18 +01004072 if (!isVisible() || mAppStopped) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004073 clearAllDrawn();
4074
4075 // If the app was already visible, don't reset the waitingToShow state.
Issei Suzukif2f6c912019-11-08 11:24:18 +01004076 if (!isVisible()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004077 waitingToShow = true;
4078
4079 // If the client isn't hidden, we don't need to reset the drawing state.
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01004080 if (!isClientVisible()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004081 // Let's reset the draw state in order to prevent the starting window to be
4082 // immediately dismissed when the app still has the surface.
4083 forAllWindows(w -> {
4084 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
4085 w.mWinAnimator.resetDrawState();
4086
4087 // Force add to mResizingWindows, so that we are guaranteed to get
4088 // another reportDrawn callback.
4089 w.resetLastContentInsets();
4090 }
4091 }, true /* traverseTopToBottom */);
4092 }
4093 }
4094 }
4095
4096 // In the case where we are making an app visible but holding off for a transition,
4097 // we still need to tell the client to make its windows visible so they get drawn.
4098 // Otherwise, we will wait on performing the transition until all windows have been
4099 // drawn, they never will be, and we are sad.
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01004100 setClientVisible(true);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004101
4102 requestUpdateWallpaperIfNeeded();
4103
4104 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
4105 mAppStopped = false;
4106
4107 transferStartingWindowFromHiddenAboveTokenIfNeeded();
4108 }
4109
4110 // If we are preparing an app transition, then delay changing
4111 // the visibility of this token until we execute that transition.
lumark3b8bbc82019-12-02 16:22:08 +08004112 // Note that we ignore display frozen since we want the opening / closing transition type
4113 // can be updated correctly even display frozen, and it's safe since in applyAnimation will
4114 // still check DC#okToAnimate again if the transition animation is fine to apply.
4115 if (okToAnimate(true /* ignoreFrozen */) && appTransition.isTransitionSet()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004116 if (visible) {
4117 displayContent.mOpeningApps.add(this);
4118 mEnteringAnimation = true;
4119 } else {
4120 displayContent.mClosingApps.add(this);
4121 mEnteringAnimation = false;
4122 }
4123 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
4124 // We're launchingBehind, add the launching activity to mOpeningApps.
4125 final WindowState win = getDisplayContent().findFocusedWindow();
4126 if (win != null) {
4127 final ActivityRecord focusedActivity = win.mActivityRecord;
4128 if (focusedActivity != null) {
4129 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
4130 "TRANSIT_TASK_OPEN_BEHIND, adding %s to mOpeningApps",
4131 focusedActivity);
4132
4133 // Force animation to be loaded.
4134 displayContent.mOpeningApps.add(focusedActivity);
4135 }
4136 }
4137 }
4138 return;
4139 }
4140
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004141 commitVisibility(visible, true /* performLayout */);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004142 updateReportedVisibilityLocked();
4143 }
4144
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004145 @Override
4146 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
Issei Suzuki8b995df2020-01-08 12:23:04 +01004147 boolean isVoiceInteraction,
4148 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004149 if (mUseTransferredAnimation) {
4150 return false;
4151 }
Issei Suzuki2f541842020-01-09 20:18:29 +01004152 return super.applyAnimation(lp, transit, enter, isVoiceInteraction,
4153 animationFinishedCallback);
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004154 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004155
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004156 /**
4157 * Update visibility to this {@link ActivityRecord}.
4158 *
4159 * <p class="note"><strong>Note: </strong> Unlike {@link #setVisibility}, this immediately
4160 * updates the visibility without starting an app transition. Since this function may start
4161 * animation on {@link WindowState} depending on app transition animation status, an app
4162 * transition animation must be started before calling this function if necessary.</p>
4163 *
4164 * @param visible {@code true} if this {@link ActivityRecord} should become visible, otherwise
4165 * this should become invisible.
4166 * @param performLayout if {@code true}, perform surface placement after committing visibility.
4167 */
4168 void commitVisibility(boolean visible, boolean performLayout) {
4169 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
Garfield Tane8d84ab2019-10-11 09:49:40 -07004170 // been set by the app now.
Issei Suzukif2f6c912019-11-08 11:24:18 +01004171 mVisibleSetFromTransferredStartingWindow = false;
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004172 if (visible == isVisible()) {
4173 return;
Garfield Tane8d84ab2019-10-11 09:49:40 -07004174 }
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004175
4176 final int windowsCount = mChildren.size();
4177 for (int i = 0; i < windowsCount; i++) {
4178 mChildren.get(i).onAppVisibilityChanged(visible, isAnimating(PARENTS));
4179 }
4180 setVisible(visible);
4181 mVisibleRequested = visible;
4182 if (!visible) {
4183 stopFreezingScreen(true, true);
4184 } else {
4185 // If we are being set visible, and the starting window is not yet displayed,
4186 // then make sure it doesn't get displayed.
4187 if (startingWindow != null && !startingWindow.isDrawnLw()) {
4188 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
4189 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
4190 }
4191 // We are becoming visible, so better freeze the screen with the windows that are
4192 // getting visible so we also wait for them.
4193 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
4194 }
4195 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
4196 "commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
4197 isVisible(), mVisibleRequested);
4198 final DisplayContent displayContent = getDisplayContent();
4199 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
4200 if (performLayout) {
4201 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4202 false /*updateInputWindows*/);
4203 mWmService.mWindowPlacerLocked.performSurfacePlacement();
4204 }
4205 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004206 mUseTransferredAnimation = false;
4207
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004208 postApplyAnimation(visible);
4209 }
4210
4211 /**
4212 * Post process after applying an app transition animation.
4213 *
4214 * <p class="note"><strong>Note: </strong> This function must be called after the animations
4215 * have been applied and {@link #commitVisibility}.</p>
4216 *
4217 * @param visible {@code true} if this {@link ActivityRecord} has become visible, otherwise
4218 * this has become invisible.
4219 */
4220 private void postApplyAnimation(boolean visible) {
4221 final boolean delayed = isAnimating(PARENTS | CHILDREN);
lumark9bca6b42019-10-17 18:35:22 +08004222 if (!delayed) {
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004223 // We aren't delayed anything, but exiting windows rely on the animation finished
4224 // callback being called in case the ActivityRecord was pretending to be delayed,
Garfield Tane8d84ab2019-10-11 09:49:40 -07004225 // which we might have done because we were in closing/opening apps list.
Issei Suzuki8b995df2020-01-08 12:23:04 +01004226 onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION, null /* AnimationAdapter */);
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004227 if (visible) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004228 // The token was made immediately visible, there will be no entrance animation.
4229 // We need to inform the client the enter animation was finished.
4230 mEnteringAnimation = true;
4231 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
4232 token);
4233 }
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004234 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004235
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004236 // If we're becoming visible, immediately change client visibility as well. there seem
4237 // to be some edge cases where we change our visibility but client visibility never gets
4238 // updated.
4239 // If we're becoming invisible, update the client visibility if we are not running an
4240 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
4241 if (visible || !isAnimating(PARENTS)) {
4242 setClientVisible(visible);
4243 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004244
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004245 final DisplayContent displayContent = getDisplayContent();
4246 if (!displayContent.mClosingApps.contains(this)
4247 && !displayContent.mOpeningApps.contains(this)) {
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004248 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
4249 // will not be taken.
4250 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
4251 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004252
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004253 // If we are hidden but there is no delay needed we immediately
4254 // apply the Surface transaction so that the ActivityManager
4255 // can have some guarantee on the Surface state following
4256 // setting the visibility. This captures cases like dismissing
4257 // the docked or pinned stack where there is no app transition.
4258 //
4259 // In the case of a "Null" animation, there will be
4260 // no animation but there will still be a transition set.
4261 // We still need to delay hiding the surface such that it
4262 // can be synchronized with showing the next surface in the transition.
4263 if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
4264 SurfaceControl.openTransaction();
4265 try {
4266 forAllWindows(win -> {
4267 win.mWinAnimator.hide("immediately hidden"); }, true);
4268 } finally {
Garfield Tane8d84ab2019-10-11 09:49:40 -07004269 SurfaceControl.closeTransaction();
4270 }
4271 }
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004272 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004273
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004274 /**
4275 * Check if visibility of this {@link ActivityRecord} should be updated as part of an app
4276 * transition.
4277 *
4278 * <p class="note><strong>Note:</strong> If the visibility of this {@link ActivityRecord} is
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004279 * already set to {@link #mVisible}, we don't need to update the visibility. So {@code false} is
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004280 * returned.</p>
4281 *
4282 * @param visible {@code true} if this {@link ActivityRecord} should become visible,
4283 * {@code false} if this should become invisible.
4284 * @return {@code true} if visibility of this {@link ActivityRecord} should be updated, and
4285 * an app transition animation should be run.
4286 */
4287 boolean shouldApplyAnimation(boolean visible) {
4288 // Allow for state update and animation to be applied if:
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004289 // * activity is transitioning visibility state
4290 // * or the activity was marked as hidden and is exiting before we had a chance to play the
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004291 // transition animation
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004292 // * or this is an opening app and windows are being replaced (e.g. freeform window to
4293 // normal window).
Issei Suzuki2bcbd682019-11-08 13:20:14 +01004294 return isVisible() != visible || (!isVisible() && mIsExiting)
Issei Suzuki0ae90d02019-10-18 17:39:15 +02004295 || (visible && forAllWindows(WindowState::waitingForReplacement, true));
Garfield Tane8d84ab2019-10-11 09:49:40 -07004296 }
4297
Garfield Tane8d84ab2019-10-11 09:49:40 -07004298 /**
4299 * See {@link Activity#setDisablePreviewScreenshots}.
4300 */
4301 void setDisablePreviewScreenshots(boolean disable) {
4302 mDisablePreviewScreenshots = disable;
4303 }
4304
4305 /**
4306 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
4307 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
4308 * we can't take a snapshot for other reasons, for example, if we have a secure window.
4309 *
4310 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
4311 * screenshot.
4312 */
4313 boolean shouldUseAppThemeSnapshot() {
4314 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
4315 true /* topToBottom */);
4316 }
4317
4318 /**
4319 * Sets whether the current launch can turn the screen on.
4320 * @see #currentLaunchCanTurnScreenOn()
4321 */
4322 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
4323 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
4324 }
4325
4326 /**
4327 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
4328 * relayouts from turning the screen back on. The screen should only turn on at most
4329 * once per activity resume.
4330 * <p>
4331 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
4332 * or {@link ActivityRecord#canTurnScreenOn} is set.
4333 *
4334 * @return {@code true} if the activity is ready to turn on the screen.
4335 */
4336 boolean currentLaunchCanTurnScreenOn() {
4337 return mCurrentLaunchCanTurnScreenOn;
4338 }
4339
Bryce Lee7ace3952018-02-16 14:34:32 -08004340 void setState(ActivityState state, String reason) {
4341 if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
4342 + " to:" + state + " reason:" + reason);
Bryce Lee6ff17072018-02-28 07:26:17 -08004343
Bryce Leeb0f993f2018-03-02 15:38:01 -08004344 if (state == mState) {
4345 // No need to do anything if state doesn't change.
4346 if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
4347 return;
4348 }
4349
Bryce Leeb0f993f2018-03-02 15:38:01 -08004350 mState = state;
4351
Louis Changcdec0802019-11-11 11:45:07 +08004352 if (task != null) {
4353 task.onActivityStateChanged(this, state, reason);
Bryce Leec4ab62a2018-03-05 14:19:26 -08004354 }
Robert Carr29daa922018-04-27 11:56:48 -07004355
Robert Carr9e1bf7c2018-05-31 15:39:07 -07004356 // The WindowManager interprets the app stopping signal as
4357 // an indication that the Surface will eventually be destroyed.
4358 // This however isn't necessarily true if we are going to sleep.
4359 if (state == STOPPING && !isSleeping()) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004360 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004361 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
4362 + appToken);
4363 return;
4364 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004365 detachChildren();
Robert Carr29daa922018-04-27 11:56:48 -07004366 }
Hui Yu03d12402018-12-06 18:00:37 -08004367
4368 if (state == RESUMED) {
4369 mAtmService.updateBatteryStats(this, true);
4370 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
4371 } else if (state == PAUSED) {
4372 mAtmService.updateBatteryStats(this, false);
4373 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
4374 } else if (state == STOPPED) {
4375 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
4376 } else if (state == DESTROYED) {
4377 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
4378 }
Bryce Lee7ace3952018-02-16 14:34:32 -08004379 }
4380
4381 ActivityState getState() {
4382 return mState;
4383 }
4384
4385 /**
4386 * Returns {@code true} if the Activity is in the specified state.
4387 */
4388 boolean isState(ActivityState state) {
4389 return state == mState;
4390 }
4391
4392 /**
4393 * Returns {@code true} if the Activity is in one of the specified states.
4394 */
4395 boolean isState(ActivityState state1, ActivityState state2) {
4396 return state1 == mState || state2 == mState;
4397 }
4398
4399 /**
4400 * Returns {@code true} if the Activity is in one of the specified states.
4401 */
4402 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3) {
4403 return state1 == mState || state2 == mState || state3 == mState;
4404 }
4405
4406 /**
4407 * Returns {@code true} if the Activity is in one of the specified states.
4408 */
4409 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4410 ActivityState state4) {
4411 return state1 == mState || state2 == mState || state3 == mState || state4 == mState;
4412 }
4413
Louis Changeadb22f2019-06-19 12:09:23 +08004414 /**
4415 * Returns {@code true} if the Activity is in one of the specified states.
4416 */
4417 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4418 ActivityState state4, ActivityState state5) {
4419 return state1 == mState || state2 == mState || state3 == mState || state4 == mState
4420 || state5 == mState;
4421 }
4422
Andrii Kulian46799182019-10-17 16:26:17 -07004423 /**
4424 * Returns {@code true} if the Activity is in one of the specified states.
4425 */
4426 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4427 ActivityState state4, ActivityState state5, ActivityState state6) {
4428 return state1 == mState || state2 == mState || state3 == mState || state4 == mState
4429 || state5 == mState || state6 == mState;
4430 }
4431
Garfield Tane8d84ab2019-10-11 09:49:40 -07004432 void destroySurfaces() {
4433 destroySurfaces(false /*cleanupOnResume*/);
4434 }
4435
4436 /**
4437 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
4438 * the client has finished with them.
4439 *
4440 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
4441 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
4442 * others so that they are ready to be reused. If set to false (common case), destroy all
4443 * surfaces that's eligible, if the app is already stopped.
4444 */
4445 private void destroySurfaces(boolean cleanupOnResume) {
4446 boolean destroyedSomething = false;
4447
4448 // Copying to a different list as multiple children can be removed.
4449 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
4450 for (int i = children.size() - 1; i >= 0; i--) {
4451 final WindowState win = children.get(i);
4452 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
4453 }
4454 if (destroyedSomething) {
4455 final DisplayContent dc = getDisplayContent();
4456 dc.assignWindowLayers(true /*setLayoutNeeded*/);
4457 updateLetterboxSurface(null);
4458 }
4459 }
4460
Jorim Jaggibae01b12017-04-11 16:29:10 -07004461 void notifyAppResumed(boolean wasStopped) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004462 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08004463 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
4464 + appToken);
4465 return;
4466 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07004467 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
4468 wasStopped, this);
4469 mAppStopped = false;
4470 // Allow the window to turn the screen on once the app is resumed again.
4471 setCurrentLaunchCanTurnScreenOn(true);
4472 if (!wasStopped) {
4473 destroySurfaces(true /*cleanupOnResume*/);
4474 }
4475 }
4476
4477 /**
4478 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
4479 * keeping alive in case they were still being used.
4480 */
4481 void notifyAppStopped() {
4482 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
4483 mAppStopped = true;
4484 // Reset the last saved PiP snap fraction on app stop.
Hongwei Wang221fe3d2020-03-26 13:13:04 -07004485 mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
Garfield Tane8d84ab2019-10-11 09:49:40 -07004486 destroySurfaces();
4487 // Remove any starting window that was added for this app if they are still around.
4488 removeStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08004489 }
4490
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004491 /**
4492 * Suppress transition until the new activity becomes ready, otherwise the keyguard can appear
4493 * for a short amount of time before the new process with the new activity had the ability to
4494 * set its showWhenLocked flags.
4495 */
4496 void notifyUnknownVisibilityLaunchedForKeyguardTransition() {
Jorim Jaggi838c2452017-08-28 15:44:43 +02004497 // No display activities never add a window, so there is no point in waiting them for
4498 // relayout.
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004499 if (noDisplay || !mStackSupervisor.getKeyguardController().isKeyguardLocked()) {
4500 return;
Andrii Kulian21713ac2016-10-12 22:05:05 -07004501 }
4502
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004503 mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004504 }
4505
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004506 /** @return {@code true} if this activity should be made visible. */
4507 boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
Garfield Tan47e576c2019-01-28 10:26:23 -08004508 // Check whether activity should be visible without Keyguard influence
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004509 visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
4510 && okToShowLocked();
4511
4512 if (ignoringKeyguard) {
4513 return visibleIgnoringKeyguard;
4514 }
Garfield Tan47e576c2019-01-28 10:26:23 -08004515
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004516 final ActivityStack stack = getRootTask();
Garfield Tan47e576c2019-01-28 10:26:23 -08004517 if (stack == null) {
4518 return false;
4519 }
4520
Andrii Kulian46799182019-10-17 16:26:17 -07004521 // Check if the activity is on a sleeping display, and if it can turn it ON.
4522 if (getDisplay().isSleeping()) {
4523 final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn()
4524 || canShowWhenLocked() || containsDismissKeyguardWindow();
4525 if (!canTurnScreenOn) {
4526 return false;
4527 }
4528 }
4529
Issei Suzuki62356a22019-04-11 16:46:37 +02004530 // Now check whether it's really visible depending on Keyguard state, and update
4531 // {@link ActivityStack} internal states.
Andrii Kulian46799182019-10-17 16:26:17 -07004532 // Inform the method if this activity is the top activity of this stack, but exclude the
4533 // case where this is the top activity in a pinned stack.
4534 final boolean isTop = this == stack.getTopNonFinishingActivity();
4535 final boolean isTopNotPinnedStack = stack.isAttached()
Andrii Kulian86d676c2020-03-27 19:34:54 -07004536 && stack.getDisplayArea().isTopNotPinnedStack(stack);
Issei Suzuki62356a22019-04-11 16:46:37 +02004537 final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
Garfield Tan47e576c2019-01-28 10:26:23 -08004538 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
Andrii Kulian46799182019-10-17 16:26:17 -07004539
4540 return visibleIgnoringDisplayStatus;
Garfield Tan47e576c2019-01-28 10:26:23 -08004541 }
4542
4543 boolean shouldBeVisible() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004544 final ActivityStack stack = getRootTask();
Garfield Tan47e576c2019-01-28 10:26:23 -08004545 if (stack == null) {
4546 return false;
4547 }
4548
Riddle Hsu13c27ae2019-10-05 23:10:15 +08004549 final boolean behindFullscreenActivity = stack.checkBehindFullscreenActivity(
4550 this, null /* handleBehindFullscreenActivity */);
4551 return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */);
Garfield Tan47e576c2019-01-28 10:26:23 -08004552 }
4553
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004554 void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004555 // This activity is not currently visible, but is running. Tell it to become visible.
Bryce Lee7ace3952018-02-16 14:34:32 -08004556 if (mState == RESUMED || this == starting) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004557 if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
Bryce Lee7ace3952018-02-16 14:34:32 -08004558 "Not making visible, r=" + this + " state=" + mState + " starting=" + starting);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004559 return;
4560 }
4561
4562 // If this activity is paused, tell it to now show its window.
4563 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
4564 "Making visible and scheduling visibility: " + this);
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004565 final ActivityStack stack = getRootTask();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004566 try {
4567 if (stack.mTranslucentActivityWaiting != null) {
4568 updateOptionsLocked(returningOptions);
4569 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
4570 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01004571 setVisibility(true);
Andrii Kulian46799182019-10-17 16:26:17 -07004572 mSetToSleep = false;
Wale Ogunwale342fbe92018-10-09 08:44:10 -07004573 app.postPendingUiCleanMsg(true);
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004574 if (reportToClient) {
Andrii Kulianb9faa032019-10-17 23:11:54 -07004575 mClientVisibilityDeferred = false;
4576 makeActiveIfNeeded(starting);
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004577 } else {
4578 mClientVisibilityDeferred = true;
4579 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004580 // The activity may be waiting for stop, but that is no longer appropriate for it.
4581 mStackSupervisor.mStoppingActivities.remove(this);
Andrii Kuliana39ae3e2018-05-31 12:43:54 -07004582 } catch (Exception e) {
4583 // Just skip on any failure; we'll make it visible when it next restarts.
4584 Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
4585 }
4586 handleAlreadyVisible();
4587 }
Andrii Kulian0d595f32018-02-21 15:47:33 -08004588
Andrii Kulian79d67982019-08-19 11:56:16 -07004589 void makeInvisible() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01004590 if (!mVisibleRequested) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004591 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
4592 return;
4593 }
4594 // Now for any activities that aren't visible to the user, make sure they no longer are
4595 // keeping the screen frozen.
4596 if (DEBUG_VISIBILITY) {
4597 Slog.v(TAG_VISIBILITY, "Making invisible: " + this + ", state=" + getState());
4598 }
4599 try {
4600 final boolean canEnterPictureInPicture = checkEnterPictureInPictureState(
4601 "makeInvisible", true /* beforeStopping */);
4602 // Defer telling the client it is hidden if it can enter Pip and isn't current paused,
4603 // stopped or stopping. This gives it a chance to enter Pip in onPause().
4604 // TODO: There is still a question surrounding activities in multi-window mode that want
4605 // to enter Pip after they are paused, but are still visible. I they should be okay to
4606 // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and
4607 // the current contract for "auto-Pip" is that the app should enter it before onPause
4608 // returns. Just need to confirm this reasoning makes sense.
4609 final boolean deferHidingClient = canEnterPictureInPicture
4610 && !isState(STOPPING, STOPPED, PAUSED);
4611 setDeferHidingClient(deferHidingClient);
Issei Suzuki1669ea42019-11-06 14:20:59 +01004612 setVisibility(false);
Andrii Kulian79d67982019-08-19 11:56:16 -07004613
4614 switch (getState()) {
4615 case STOPPING:
4616 case STOPPED:
Andrii Kulian79d67982019-08-19 11:56:16 -07004617 // Reset the flag indicating that an app can enter picture-in-picture once the
4618 // activity is hidden
4619 supportsEnterPipOnTaskSwitch = false;
4620 break;
4621
4622 case INITIALIZING:
4623 case RESUMED:
4624 case PAUSING:
4625 case PAUSED:
4626 case STARTED:
4627 addToStopping(true /* scheduleIdle */,
4628 canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
4629 break;
4630
4631 default:
4632 break;
4633 }
4634 } catch (Exception e) {
4635 // Just skip on any failure; we'll make it visible when it next restarts.
4636 Slog.w(TAG, "Exception thrown making hidden: " + intent.getComponent(), e);
4637 }
4638 }
4639
Andrii Kulian6b321512019-01-23 06:37:00 +00004640 /**
4641 * Make activity resumed or paused if needed.
4642 * @param activeActivity an activity that is resumed or just completed pause action.
4643 * We won't change the state of this activity.
4644 */
4645 boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
4646 if (shouldResumeActivity(activeActivity)) {
4647 if (DEBUG_VISIBILITY) {
Andrii Kulianb9faa032019-10-17 23:11:54 -07004648 Slog.v(TAG_VISIBILITY, "Resume visible activity, " + this);
Andrii Kulian6b321512019-01-23 06:37:00 +00004649 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004650 return getRootTask().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
Andrii Kulian6b321512019-01-23 06:37:00 +00004651 null /* options */);
4652 } else if (shouldPauseActivity(activeActivity)) {
4653 if (DEBUG_VISIBILITY) {
Andrii Kulianb9faa032019-10-17 23:11:54 -07004654 Slog.v(TAG_VISIBILITY, "Pause visible activity, " + this);
Andrii Kulian6b321512019-01-23 06:37:00 +00004655 }
4656 // An activity must be in the {@link PAUSING} state for the system to validate
4657 // the move to {@link PAUSED}.
Andrii Kulianb9faa032019-10-17 23:11:54 -07004658 setState(PAUSING, "makeActiveIfNeeded");
Andrii Kulian6b321512019-01-23 06:37:00 +00004659 try {
4660 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
4661 PauseActivityItem.obtain(finishing, false /* userLeaving */,
4662 configChangeFlags, false /* dontReport */));
4663 } catch (Exception e) {
4664 Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
4665 }
Andrii Kulianb9faa032019-10-17 23:11:54 -07004666 } else if (shouldStartActivity()) {
4667 if (DEBUG_VISIBILITY) {
4668 Slog.v(TAG_VISIBILITY, "Start visible activity, " + this);
4669 }
4670 setState(STARTED, "makeActiveIfNeeded");
4671 try {
4672 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
4673 StartActivityItem.obtain());
4674 } catch (Exception e) {
4675 Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e);
4676 }
Winson Chungb478e572020-03-20 11:07:17 -07004677 // The activity may be waiting for stop, but that is no longer appropriate if we are
4678 // starting the activity again
4679 mStackSupervisor.mStoppingActivities.remove(this);
Andrii Kulian6b321512019-01-23 06:37:00 +00004680 }
4681 return false;
4682 }
4683
4684 /**
4685 * Check if activity should be moved to PAUSED state. The activity:
4686 * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4687 * - should be non-focusable
4688 * - should not be currently pausing or paused
4689 * @param activeActivity the activity that is active or just completed pause action. We won't
4690 * resume if this activity is active.
4691 */
wilsonshiha96aac62019-11-18 14:53:34 +08004692 @VisibleForTesting
4693 boolean shouldPauseActivity(ActivityRecord activeActivity) {
4694 return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED)
4695 // We will only allow pausing if results is null, otherwise it will cause this
4696 // activity to resume before getting result
4697 && (results == null);
Andrii Kulian6b321512019-01-23 06:37:00 +00004698 }
4699
4700 /**
wilsonshihb5d8f8b2019-10-23 13:01:40 +08004701 * Check if activity should be moved to RESUMED state.
4702 * See {@link #shouldBeResumed(ActivityRecord)}
Andrii Kulian6b321512019-01-23 06:37:00 +00004703 * @param activeActivity the activity that is active or just completed pause action. We won't
4704 * resume if this activity is active.
4705 */
Andrii Kulian0c869cc2019-02-06 19:50:32 -08004706 @VisibleForTesting
4707 boolean shouldResumeActivity(ActivityRecord activeActivity) {
wilsonshihb5d8f8b2019-10-23 13:01:40 +08004708 return shouldBeResumed(activeActivity) && !isState(RESUMED);
4709 }
4710
4711 /**
4712 * Check if activity should be RESUMED now. The activity:
4713 * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4714 * - should be focusable
4715 */
4716 private boolean shouldBeResumed(ActivityRecord activeActivity) {
4717 return shouldMakeActive(activeActivity) && isFocusable()
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004718 && getRootTask().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
wilsonshihb5d8f8b2019-10-23 13:01:40 +08004719 && canResumeByCompat();
Andrii Kulian6b321512019-01-23 06:37:00 +00004720 }
4721
4722 /**
Andrii Kulianb9faa032019-10-17 23:11:54 -07004723 * Check if activity should be moved to STARTED state.
4724 * NOTE: This will not check if activity should be made paused or resumed first, so it must only
4725 * be called after checking with {@link #shouldResumeActivity(ActivityRecord)}
4726 * and {@link #shouldPauseActivity(ActivityRecord)}.
4727 */
4728 private boolean shouldStartActivity() {
Winson Chungb478e572020-03-20 11:07:17 -07004729 return mVisibleRequested && (isState(STOPPED) || isState(STOPPING));
Andrii Kulianb9faa032019-10-17 23:11:54 -07004730 }
4731
4732 /**
Andrii Kulian6b321512019-01-23 06:37:00 +00004733 * Check if activity is eligible to be made active (resumed of paused). The activity:
4734 * - should be paused, stopped or stopping
Andrii Kulian996df0d2019-01-24 17:04:36 -08004735 * - should not be the currently active one or launching behind other tasks
Andrii Kulian6b321512019-01-23 06:37:00 +00004736 * - should be either the topmost in task, or right below the top activity that is finishing
4737 * If all of these conditions are not met at the same time, the activity cannot be made active.
4738 */
Andrii Kulianf2195362019-01-31 18:20:11 -08004739 @VisibleForTesting
4740 boolean shouldMakeActive(ActivityRecord activeActivity) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004741 // If the activity is stopped, stopping, cycle to an active state. We avoid doing
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004742 // this when there is an activity waiting to become translucent as the extra binder
4743 // calls will lead to noticeable jank. A later call to
Wale Ogunwale076c3b12019-11-20 12:17:22 -08004744 // ActivityStack#ensureActivitiesVisible will bring the activity to a proper
Andrii Kulian6b321512019-01-23 06:37:00 +00004745 // active state.
Louis Changeadb22f2019-06-19 12:09:23 +08004746 if (!isState(STARTED, RESUMED, PAUSED, STOPPED, STOPPING)
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004747 || getRootTask().mTranslucentActivityWaiting != null) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004748 return false;
4749 }
4750
4751 if (this == activeActivity) {
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004752 return false;
4753 }
4754
Andrii Kulianf2195362019-01-31 18:20:11 -08004755 if (!mStackSupervisor.readyToResume()) {
4756 // Making active is currently deferred (e.g. because an activity launch is in progress).
4757 return false;
4758 }
4759
Andrii Kulian996df0d2019-01-24 17:04:36 -08004760 if (this.mLaunchTaskBehind) {
4761 // This activity is being launched from behind, which means that it's not intended to be
4762 // presented to user right now, even if it's set to be visible.
4763 return false;
4764 }
4765
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004766 // Check if position in task allows to become paused
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004767 if (!task.hasChild(this)) {
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004768 throw new IllegalStateException("Activity not found in its task");
4769 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004770 final ActivityRecord activityAbove = task.getActivityAbove(this);
4771 if (activityAbove == null) {
Andrii Kulian6b321512019-01-23 06:37:00 +00004772 // It's the topmost activity in the task - should become resumed now
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004773 return true;
4774 }
4775 // Check if activity above is finishing now and this one becomes the topmost in task.
wilsonshiha96aac62019-11-18 14:53:34 +08004776 if (activityAbove.finishing) {
Andrii Kulian09e1afa2018-05-16 21:29:34 -07004777 return true;
4778 }
4779 return false;
4780 }
4781
Louis Changcfe46212019-07-30 10:34:18 +08004782 void handleAlreadyVisible() {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004783 stopFreezingScreenLocked(false);
4784 try {
4785 if (returningOptions != null) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004786 app.getThread().scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
Andrii Kulian21713ac2016-10-12 22:05:05 -07004787 }
4788 } catch(RemoteException e) {
4789 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004790 }
4791
4792 static void activityResumedLocked(IBinder token) {
4793 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
4794 if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
Charles Chen69362cd2019-03-29 15:18:45 +08004795 if (r == null) {
4796 // If an app reports resumed after a long delay, the record on server side might have
4797 // been removed (e.g. destroy timeout), so the token could be null.
4798 return;
Andrii Kulian21713ac2016-10-12 22:05:05 -07004799 }
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07004800 r.setSavedState(null /* savedState */);
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004801
Louis Chang677921f2019-12-06 16:44:24 +08004802 final DisplayContent display = r.getDisplay();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004803 if (display != null) {
4804 display.handleActivitySizeCompatModeIfNeeded(r);
4805 }
Riddle Hsu8419e4b2019-09-18 23:28:01 +08004806
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08004807 r.getDisplayContent().mUnknownAppVisibilityController.notifyAppResumedFinished(r);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004808 }
4809
4810 /**
4811 * Once we know that we have asked an application to put an activity in the resumed state
4812 * (either by launching it or explicitly telling it), this function updates the rest of our
4813 * state to match that fact.
4814 */
4815 void completeResumeLocked() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01004816 final boolean wasVisible = mVisibleRequested;
4817 setVisibility(true);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004818 if (!wasVisible) {
4819 // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
4820 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
4821 }
4822 idle = false;
4823 results = null;
Louis Chang746c2242019-10-08 16:30:44 +08004824 if (newIntents != null && newIntents.size() > 0) {
4825 mLastNewIntent = newIntents.get(newIntents.size() - 1);
4826 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004827 newIntents = null;
4828 stopped = false;
4829
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07004830 if (isActivityTypeHome()) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004831 mStackSupervisor.updateHomeProcess(task.getBottomMostActivity().app);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004832 }
4833
4834 if (nowVisible) {
Louis Changa59937a2019-03-20 17:17:22 +08004835 mStackSupervisor.stopWaitingForActivityVisible(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004836 }
4837
4838 // Schedule an idle timeout in case the app doesn't do it for us.
Riddle Hsufc8ab262019-12-31 15:31:24 +08004839 mStackSupervisor.scheduleIdleTimeout(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07004840
4841 mStackSupervisor.reportResumedActivityLocked(this);
4842
4843 resumeKeyDispatchingLocked();
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004844 final ActivityStack stack = getRootTask();
Jorim Jaggifa9ed962018-01-25 00:16:49 +01004845 mStackSupervisor.mNoAnimActivities.clear();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004846
4847 // Mark the point when the activity is resuming
4848 // TODO: To be more accurate, the mark should be before the onCreate,
4849 // not after the onResume. But for subsequent starts, onResume is fine.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07004850 if (hasProcess()) {
Wale Ogunwale86b74462018-07-02 08:42:43 -07004851 cpuTimeAtResume = app.getCpuTime();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004852 } else {
4853 cpuTimeAtResume = 0; // Couldn't get the cpu time of process
4854 }
4855
4856 returningOptions = null;
chaviw59b98852017-06-13 12:05:44 -07004857
4858 if (canTurnScreenOn()) {
4859 mStackSupervisor.wakeUp("turnScreenOnFlag");
4860 } else {
4861 // If the screen is going to turn on because the caller explicitly requested it and
4862 // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
4863 // pause and then resume again later, which will result in a double life-cycle event.
David Stevens9440dc82017-03-16 19:00:20 -07004864 stack.checkReadyForSleep();
chaviw59b98852017-06-13 12:05:44 -07004865 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07004866 }
4867
Wale Ogunwale196db712019-12-27 15:35:39 +00004868 void activityPaused(boolean timeout) {
4869 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
4870 "Activity paused: token=" + appToken + ", timeout=" + timeout);
4871
4872 final ActivityStack stack = getStack();
4873
4874 if (stack != null) {
4875 removePauseTimeout();
4876
4877 if (stack.mPausingActivity == this) {
4878 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
4879 + (timeout ? " (due to timeout)" : " (pause complete)"));
4880 mAtmService.deferWindowLayout();
4881 try {
4882 stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
4883 } finally {
4884 mAtmService.continueWindowLayout();
4885 }
4886 return;
4887 } else {
4888 EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this),
4889 shortComponentName, stack.mPausingActivity != null
4890 ? stack.mPausingActivity.shortComponentName : "(none)");
4891 if (isState(PAUSING)) {
4892 setState(PAUSED, "activityPausedLocked");
4893 if (finishing) {
4894 if (DEBUG_PAUSE) Slog.v(TAG,
4895 "Executing finish of failed to pause activity: " + this);
4896 completeFinishing("activityPausedLocked");
4897 }
4898 }
4899 }
4900 }
4901
Louis Chang149d5c82019-12-30 09:47:39 +08004902 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwale196db712019-12-27 15:35:39 +00004903 }
4904
4905 /**
4906 * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
4907 * this directly impacts the responsiveness seen by the user.
4908 */
4909 void schedulePauseTimeout() {
4910 pauseTime = SystemClock.uptimeMillis();
4911 mAtmService.mH.postDelayed(mPauseTimeoutRunnable, PAUSE_TIMEOUT);
4912 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
4913 }
4914
4915 private void removePauseTimeout() {
4916 mAtmService.mH.removeCallbacks(mPauseTimeoutRunnable);
4917 }
4918
4919 private void removeDestroyTimeout() {
4920 mAtmService.mH.removeCallbacks(mDestroyTimeoutRunnable);
4921 }
4922
4923 private void removeStopTimeout() {
4924 mAtmService.mH.removeCallbacks(mStopTimeoutRunnable);
4925 }
4926
4927 void removeTimeouts() {
4928 mStackSupervisor.removeIdleTimeoutForActivity(this);
4929 removePauseTimeout();
4930 removeStopTimeout();
4931 removeDestroyTimeout();
4932 finishLaunchTickingLocked();
4933 }
4934
Andrii Kulian79d67982019-08-19 11:56:16 -07004935 void stopIfPossible() {
4936 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004937 final ActivityStack stack = getRootTask();
Riddle Hsu01a62ff2020-01-01 00:43:53 +08004938 if (isNoHistory()) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004939 if (!finishing) {
4940 if (!stack.shouldSleepActivities()) {
4941 if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + this);
4942 if (finishIfPossible("stop-no-history", false /* oomAdj */)
4943 != FINISH_RESULT_CANCELLED) {
Andrii Kulian79d67982019-08-19 11:56:16 -07004944 resumeKeyDispatchingLocked();
4945 return;
4946 }
4947 } else {
4948 if (DEBUG_STATES) {
4949 Slog.d(TAG_STATES, "Not finishing noHistory " + this
4950 + " on stop because we're just sleeping");
4951 }
4952 }
4953 }
4954 }
4955
4956 if (!attachedToProcess()) {
4957 return;
4958 }
Andrii Kulian79d67982019-08-19 11:56:16 -07004959 resumeKeyDispatchingLocked();
4960 try {
4961 stopped = false;
4962 if (DEBUG_STATES) {
4963 Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (stop requested)");
4964 }
4965 setState(STOPPING, "stopIfPossible");
4966 if (DEBUG_VISIBILITY) {
Andrii Kulianb9faa032019-10-17 23:11:54 -07004967 Slog.v(TAG_VISIBILITY, "Stopping:" + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07004968 }
Jeff Changd136e772019-11-05 20:33:52 +08004969 EventLogTags.writeWmStopActivity(
Andrii Kulian79d67982019-08-19 11:56:16 -07004970 mUserId, System.identityHashCode(this), shortComponentName);
4971 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulianb9faa032019-10-17 23:11:54 -07004972 StopActivityItem.obtain(configChangeFlags));
4973
Andrii Kulian79d67982019-08-19 11:56:16 -07004974 if (stack.shouldSleepOrShutDownActivities()) {
4975 setSleeping(true);
4976 }
Wale Ogunwale196db712019-12-27 15:35:39 +00004977 mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
Andrii Kulian79d67982019-08-19 11:56:16 -07004978 } catch (Exception e) {
4979 // Maybe just ignore exceptions here... if the process has crashed, our death
4980 // notification will clean things up.
4981 Slog.w(TAG, "Exception thrown during pause", e);
4982 // Just in case, assume it to be stopped.
4983 stopped = true;
4984 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + this);
4985 setState(STOPPED, "stopIfPossible");
4986 if (deferRelaunchUntilPaused) {
4987 destroyImmediately(true /* removeFromApp */, "stop-except");
4988 }
4989 }
4990 }
4991
Wale Ogunwale196db712019-12-27 15:35:39 +00004992 void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState,
Andrii Kulian21713ac2016-10-12 22:05:05 -07004993 CharSequence description) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08004994 final ActivityStack stack = getRootTask();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08004995 final boolean isStopping = mState == STOPPING;
4996 if (!isStopping && mState != RESTARTING_PROCESS) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07004997 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
Wale Ogunwale196db712019-12-27 15:35:39 +00004998 removeStopTimeout();
Andrii Kulian21713ac2016-10-12 22:05:05 -07004999 return;
5000 }
5001 if (newPersistentState != null) {
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07005002 mPersistentState = newPersistentState;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005003 mAtmService.notifyTaskPersisterLocked(task, false);
Andrii Kulian21713ac2016-10-12 22:05:05 -07005004 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005005
Andrii Kulian21713ac2016-10-12 22:05:05 -07005006 if (newIcicle != null) {
5007 // If icicle is null, this is happening due to a timeout, so we haven't really saved
5008 // the state.
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07005009 setSavedState(newIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07005010 launchCount = 0;
Jorim Jaggie7d2b852017-08-28 17:55:15 +02005011 updateTaskDescription(description);
Andrii Kulian21713ac2016-10-12 22:05:05 -07005012 }
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07005013 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
Andrii Kulian21713ac2016-10-12 22:05:05 -07005014 if (!stopped) {
5015 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
Wale Ogunwale196db712019-12-27 15:35:39 +00005016 removeStopTimeout();
Andrii Kulian21713ac2016-10-12 22:05:05 -07005017 stopped = true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08005018 if (isStopping) {
5019 setState(STOPPED, "activityStoppedLocked");
5020 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07005021
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005022 notifyAppStopped();
Andrii Kulian21713ac2016-10-12 22:05:05 -07005023
Andrii Kulian21713ac2016-10-12 22:05:05 -07005024 if (finishing) {
5025 clearOptionsLocked();
5026 } else {
5027 if (deferRelaunchUntilPaused) {
Andrii Kulian79d67982019-08-19 11:56:16 -07005028 destroyImmediately(true /* removeFromApp */, "stop-config");
Louis Chang149d5c82019-12-30 09:47:39 +08005029 mRootWindowContainer.resumeFocusedStacksTopActivities();
Andrii Kulian21713ac2016-10-12 22:05:05 -07005030 } else {
Louis Chang149d5c82019-12-30 09:47:39 +08005031 mRootWindowContainer.updatePreviousProcess(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07005032 }
5033 }
5034 }
5035 }
5036
Andrii Kulian79d67982019-08-19 11:56:16 -07005037 void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
5038 if (!mStackSupervisor.mStoppingActivities.contains(this)) {
Jeff Changd136e772019-11-05 20:33:52 +08005039 EventLogTags.writeWmAddToStopping(mUserId, System.identityHashCode(this),
5040 shortComponentName, reason);
Andrii Kulian79d67982019-08-19 11:56:16 -07005041 mStackSupervisor.mStoppingActivities.add(this);
5042 }
5043
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08005044 final ActivityStack stack = getRootTask();
Andrii Kulian79d67982019-08-19 11:56:16 -07005045 // If we already have a few activities waiting to stop, then give up on things going idle
5046 // and start clearing them out. Or if r is the last of activity of the last task the stack
5047 // will be empty and must be cleared immediately.
5048 boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
5049 || (isRootOfTask() && stack.getChildCount() <= 1);
5050 if (scheduleIdle || forceIdle) {
5051 if (DEBUG_PAUSE) {
5052 Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" + forceIdle
5053 + "immediate=" + !idleDelayed);
5054 }
5055 if (!idleDelayed) {
Riddle Hsufc8ab262019-12-31 15:31:24 +08005056 mStackSupervisor.scheduleIdle();
Andrii Kulian79d67982019-08-19 11:56:16 -07005057 } else {
Riddle Hsufc8ab262019-12-31 15:31:24 +08005058 mStackSupervisor.scheduleIdleTimeout(this);
Andrii Kulian79d67982019-08-19 11:56:16 -07005059 }
5060 } else {
5061 stack.checkReadyForSleep();
5062 }
5063 }
5064
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005065 void startLaunchTickingLocked() {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06005066 if (Build.IS_USER) {
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005067 return;
5068 }
5069 if (launchTickTime == 0) {
5070 launchTickTime = SystemClock.uptimeMillis();
Wale Ogunwale196db712019-12-27 15:35:39 +00005071 continueLaunchTicking();
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005072 }
5073 }
5074
Wale Ogunwale196db712019-12-27 15:35:39 +00005075 private boolean continueLaunchTicking() {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005076 if (launchTickTime == 0) {
5077 return false;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005078 }
Wale Ogunwale7d701172015-03-11 15:36:30 -07005079
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08005080 final ActivityStack stack = getRootTask();
Wale Ogunwale7d701172015-03-11 15:36:30 -07005081 if (stack == null) {
5082 return false;
5083 }
5084
Andrii Kulian79d67982019-08-19 11:56:16 -07005085 stack.removeLaunchTickMessages();
Wale Ogunwale196db712019-12-27 15:35:39 +00005086 mAtmService.mH.postDelayed(mLaunchTickRunnable, LAUNCH_TICK);
Wale Ogunwale7d701172015-03-11 15:36:30 -07005087 return true;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005088 }
5089
Wale Ogunwale196db712019-12-27 15:35:39 +00005090 void removeLaunchTickRunnable() {
5091 mAtmService.mH.removeCallbacks(mLaunchTickRunnable);
5092 }
5093
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005094 void finishLaunchTickingLocked() {
5095 launchTickTime = 0;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08005096 final ActivityStack stack = getRootTask();
Andrii Kulian79d67982019-08-19 11:56:16 -07005097 if (stack == null) {
5098 return;
Wale Ogunwale7d701172015-03-11 15:36:30 -07005099 }
Andrii Kulian79d67982019-08-19 11:56:16 -07005100 stack.removeLaunchTickMessages();
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07005101 }
5102
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005103 boolean mayFreezeScreenLocked() {
5104 return mayFreezeScreenLocked(app);
5105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005107 private boolean mayFreezeScreenLocked(WindowProcessController app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005108 // Only freeze the screen if this activity is currently attached to
5109 // an application, and that application is not blocked or unresponding.
5110 // In any other case, we can't count on getting the screen unfrozen,
5111 // so it is best to leave as-is.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005112 return hasProcess() && !app.isCrashing() && !app.isNotResponding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005114
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005115 void startFreezingScreenLocked(int configChanges) {
5116 startFreezingScreenLocked(app, configChanges);
5117 }
5118
5119 void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005120 if (mayFreezeScreenLocked(app)) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005121 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005122 Slog.w(TAG_WM,
5123 "Attempted to freeze screen with non-existing app token: " + appToken);
5124 return;
5125 }
5126
Evan Roskyb1e75f72019-04-26 20:23:26 -07005127 // Window configuration changes only effect windows, so don't require a screen freeze.
5128 int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005129 if (freezableConfigChanges == 0 && okToDisplay()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02005130 ProtoLog.v(WM_DEBUG_ORIENTATION, "Skipping set freeze of %s", appToken);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005131 return;
5132 }
5133
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005134 startFreezingScreen();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 }
5136 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005137
Garfield Tane8d84ab2019-10-11 09:49:40 -07005138 void startFreezingScreen() {
Riddle Hsud16620e2020-04-06 20:48:06 +08005139 startFreezingScreen(ROTATION_UNDEFINED /* overrideOriginalDisplayRotation */);
5140 }
5141
5142 void startFreezingScreen(int overrideOriginalDisplayRotation) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005143 ProtoLog.i(WM_DEBUG_ORIENTATION,
Issei Suzukif2f6c912019-11-08 11:24:18 +01005144 "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
5145 appToken, isVisible(), mFreezingScreen, mVisibleRequested,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005146 new RuntimeException().fillInStackTrace());
Riddle Hsud16620e2020-04-06 20:48:06 +08005147 if (!mVisibleRequested) {
5148 return;
5149 }
5150
5151 // If the override is given, the rotation of display doesn't change but we still want to
5152 // cover the activity whose configuration is changing by freezing the display and running
5153 // the rotation animation.
5154 final boolean forceRotation = overrideOriginalDisplayRotation != ROTATION_UNDEFINED;
5155 if (!mFreezingScreen) {
5156 mFreezingScreen = true;
5157 mWmService.registerAppFreezeListener(this);
5158 mWmService.mAppsFreezingScreen++;
5159 if (mWmService.mAppsFreezingScreen == 1) {
5160 if (forceRotation) {
5161 // Make sure normal rotation animation will be applied.
5162 mDisplayContent.getDisplayRotation().cancelSeamlessRotation();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005163 }
Riddle Hsud16620e2020-04-06 20:48:06 +08005164 mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */,
5165 mDisplayContent, overrideOriginalDisplayRotation);
5166 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
5167 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005168 }
Riddle Hsud16620e2020-04-06 20:48:06 +08005169 }
5170 if (forceRotation) {
5171 // The rotation of the real display won't change, so in order to unfreeze the screen
5172 // via {@link #checkAppWindowsReadyToShow}, the windows have to be able to call
5173 // {@link WindowState#reportResized} (it is skipped if the window is freezing) to update
5174 // the drawn state.
5175 return;
5176 }
5177 final int count = mChildren.size();
5178 for (int i = 0; i < count; i++) {
5179 final WindowState w = mChildren.get(i);
5180 w.onStartFreezingScreen();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005181 }
5182 }
5183
5184 boolean isFreezingScreen() {
5185 return mFreezingScreen;
5186 }
5187
5188 @Override
5189 public void onAppFreezeTimeout() {
5190 Slog.w(TAG_WM, "Force clearing freeze: " + this);
5191 stopFreezingScreen(true, true);
5192 }
5193
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005194 void stopFreezingScreenLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 if (force || frozenBeforeDestroy) {
5196 frozenBeforeDestroy = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005197 if (getParent() == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005198 return;
5199 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02005200 ProtoLog.v(WM_DEBUG_ORIENTATION,
Issei Suzukif2f6c912019-11-08 11:24:18 +01005201 "Clear freezing of %s: visible=%b freezing=%b", appToken,
5202 isVisible(), isFreezingScreen());
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005203 stopFreezingScreen(true, force);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 }
5205 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005206
Garfield Tane8d84ab2019-10-11 09:49:40 -07005207 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
5208 if (!mFreezingScreen) {
5209 return;
5210 }
5211 ProtoLog.v(WM_DEBUG_ORIENTATION,
5212 "Clear freezing of %s force=%b", this, force);
5213 final int count = mChildren.size();
5214 boolean unfrozeWindows = false;
5215 for (int i = 0; i < count; i++) {
5216 final WindowState w = mChildren.get(i);
5217 unfrozeWindows |= w.onStopFreezingScreen();
5218 }
5219 if (force || unfrozeWindows) {
5220 ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
5221 mFreezingScreen = false;
5222 mWmService.unregisterAppFreezeListener(this);
5223 mWmService.mAppsFreezingScreen--;
5224 mWmService.mLastFinishedFreezeSource = this;
5225 }
5226 if (unfreezeSurfaceNow) {
5227 if (unfrozeWindows) {
5228 mWmService.mWindowPlacerLocked.performSurfacePlacement();
5229 }
5230 mWmService.stopFreezingDisplayLocked();
5231 }
5232 }
5233
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005234 void reportFullyDrawnLocked(boolean restoredFromBundle) {
Riddle Hsufd66d4d2019-11-14 10:35:55 +08005235 final TransitionInfoSnapshot info = mStackSupervisor
Yan Wangd47f90b2019-10-03 19:17:15 -07005236 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
Vishnu Nair132ee832018-09-28 15:00:05 -07005237 if (info != null) {
5238 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
Vishnu Nairbb9ab4b2018-12-13 10:29:46 -08005239 info.windowsFullyDrawnDelayMs, info.getLaunchState());
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07005240 }
Dianne Hackborn2286cdc2013-07-01 19:10:06 -07005241 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005242
Garfield Tane8d84ab2019-10-11 09:49:40 -07005243 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
5244 firstWindowDrawn = true;
5245
5246 // We now have a good window to show, remove dead placeholders
5247 removeDeadWindows();
5248
5249 if (startingWindow != null) {
5250 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
5251 + ": first real window is shown, no animation", win.mToken);
5252 // If this initial window is animating, stop it -- we will do an animation to reveal
5253 // it from behind the starting window, so there is no need for it to also be doing its
5254 // own stuff.
5255 win.cancelAnimation();
5256 }
5257 removeStartingWindow();
5258 updateReportedVisibilityLocked();
5259 }
5260
Winson Chung8b5d23a2020-04-06 19:23:23 -07005261 void onStartingWindowDrawn() {
5262 if (task != null) {
5263 task.setHasBeenVisible(true);
5264 }
5265 }
5266
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005267 /** Called when the windows associated app window container are drawn. */
Yan Wangd47f90b2019-10-03 19:17:15 -07005268 void onWindowsDrawn(boolean drawn, long timestampNs) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005269 mDrawn = drawn;
5270 if (!drawn) {
5271 return;
5272 }
Riddle Hsufd66d4d2019-11-14 10:35:55 +08005273 final TransitionInfoSnapshot info = mStackSupervisor
5274 .getActivityMetricsLogger().notifyWindowsDrawn(this, timestampNs);
Riddle Hsueb628a52020-02-14 00:48:51 +08005275 final boolean validInfo = info != null;
5276 final int windowsDrawnDelayMs = validInfo ? info.windowsDrawnDelayMs : INVALID_DELAY;
5277 final @LaunchState int launchState = validInfo ? info.getLaunchState() : -1;
5278 // The activity may have been requested to be invisible (another activity has been launched)
5279 // so there is no valid info. But if it is the current top activity (e.g. sleeping), the
5280 // invalid state is still reported to make sure the waiting result is notified.
Andrii Kulian86d676c2020-03-27 19:34:54 -07005281 if (validInfo || this == getDisplayArea().topRunningActivity()) {
Riddle Hsueb628a52020-02-14 00:48:51 +08005282 mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
5283 windowsDrawnDelayMs, launchState);
5284 mStackSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs);
5285 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005286 finishLaunchTickingLocked();
5287 if (task != null) {
Robert Carrde96c8a2020-03-24 15:22:21 -07005288 task.setHasBeenVisible(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 }
5290 }
5291
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005292 /** Called when the windows associated app window container are visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005293 void onWindowsVisible() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005294 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005295 mStackSupervisor.stopWaitingForActivityVisible(this);
5296 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
5297 if (!nowVisible) {
5298 nowVisible = true;
5299 lastVisibleTime = SystemClock.uptimeMillis();
5300 mAtmService.scheduleAppGcsLocked();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005301 }
5302 }
5303
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005304 /** Called when the windows associated app window container are no longer visible. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005305 void onWindowsGone() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005306 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005307 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
5308 nowVisible = false;
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005309 }
5310
Garfield Tane8d84ab2019-10-11 09:49:40 -07005311 @Override
5312 void checkAppWindowsReadyToShow() {
5313 if (allDrawn == mLastAllDrawn) {
5314 return;
5315 }
5316
5317 mLastAllDrawn = allDrawn;
5318 if (!allDrawn) {
5319 return;
5320 }
5321
5322 // The token has now changed state to having all windows shown... what to do, what to do?
5323 if (mFreezingScreen) {
5324 showAllWindowsLocked();
5325 stopFreezingScreen(false, true);
5326 ProtoLog.i(WM_DEBUG_ORIENTATION,
5327 "Setting mOrientationChangeComplete=true because wtoken %s "
5328 + "numInteresting=%d numDrawn=%d",
5329 this, mNumInterestingWindows, mNumDrawnWindows);
5330 // This will set mOrientationChangeComplete and cause a pass through layout.
5331 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
5332 "checkAppWindowsReadyToShow: freezingScreen");
5333 } else {
5334 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
5335
5336 // We can now show all of the drawn windows!
5337 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
5338 showAllWindowsLocked();
5339 }
5340 }
5341 }
5342
5343 /**
5344 * This must be called while inside a transaction.
5345 */
5346 void showAllWindowsLocked() {
5347 forAllWindows(windowState -> {
5348 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
5349 windowState.performShowLocked();
5350 }, false /* traverseTopToBottom */);
5351 }
5352
5353 void updateReportedVisibilityLocked() {
5354 if (appToken == null) {
5355 return;
5356 }
5357
5358 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
5359 final int count = mChildren.size();
5360
5361 mReportedVisibilityResults.reset();
5362
5363 for (int i = 0; i < count; i++) {
5364 final WindowState win = mChildren.get(i);
5365 win.updateReportedVisibility(mReportedVisibilityResults);
5366 }
5367
5368 int numInteresting = mReportedVisibilityResults.numInteresting;
5369 int numVisible = mReportedVisibilityResults.numVisible;
5370 int numDrawn = mReportedVisibilityResults.numDrawn;
5371 boolean nowGone = mReportedVisibilityResults.nowGone;
5372
5373 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Issei Suzukif2f6c912019-11-08 11:24:18 +01005374 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && isVisible();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005375 if (!nowGone) {
5376 // If the app is not yet gone, then it can only become visible/drawn.
5377 if (!nowDrawn) {
5378 nowDrawn = reportedDrawn;
5379 }
5380 if (!nowVisible) {
5381 nowVisible = reportedVisible;
5382 }
5383 }
5384 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
5385 + numInteresting + " visible=" + numVisible);
5386 if (nowDrawn != reportedDrawn) {
5387 onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
5388 reportedDrawn = nowDrawn;
5389 }
5390 if (nowVisible != reportedVisible) {
5391 if (DEBUG_VISIBILITY) Slog.v(TAG,
5392 "Visibility changed in " + this + ": vis=" + nowVisible);
5393 reportedVisible = nowVisible;
5394 if (nowVisible) {
5395 onWindowsVisible();
5396 } else {
5397 onWindowsGone();
5398 }
5399 }
5400 }
5401
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005402 boolean isClientVisible() {
5403 return mClientVisible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005404 }
5405
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005406 void setClientVisible(boolean clientVisible) {
5407 if (mClientVisible == clientVisible || (!clientVisible && mDeferHidingClient)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005408 return;
5409 }
5410 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005411 "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible,
Garfield Tane8d84ab2019-10-11 09:49:40 -07005412 Debug.getCallers(5));
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01005413 mClientVisible = clientVisible;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005414 sendAppVisibilityToClients();
5415 }
5416
5417 /**
5418 * Updated this app token tracking states for interesting and drawn windows based on the window.
5419 *
5420 * @return Returns true if the input window is considered interesting and drawn while all the
5421 * windows in this app token where not considered drawn as of the last pass.
5422 */
5423 boolean updateDrawnWindowStates(WindowState w) {
5424 w.setDrawnStateEvaluated(true /*evaluated*/);
5425
5426 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
5427 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
5428 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
5429 }
5430
5431 if (allDrawn && !mFreezingScreen) {
5432 return false;
5433 }
5434
5435 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
5436 mLastTransactionSequence = mWmService.mTransactionSequence;
5437 mNumDrawnWindows = 0;
5438 startingDisplayed = false;
5439
5440 // There is the main base application window, even if it is exiting, wait for it
5441 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
5442 }
5443
5444 final WindowStateAnimator winAnimator = w.mWinAnimator;
5445
5446 boolean isInterestingAndDrawn = false;
5447
5448 if (!allDrawn && w.mightAffectAllDrawn()) {
5449 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5450 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
lumark5bd11af2019-12-21 01:52:28 +08005451 + ", isAnimationSet=" + isAnimating(TRANSITION | PARENTS));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005452 if (!w.isDrawnLw()) {
5453 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
5454 + " pv=" + w.isVisibleByPolicy()
5455 + " mDrawState=" + winAnimator.drawStateToString()
Issei Suzuki1669ea42019-11-06 14:20:59 +01005456 + " ph=" + w.isParentWindowHidden() + " th=" + mVisibleRequested
lumark5bd11af2019-12-21 01:52:28 +08005457 + " a=" + isAnimating(TRANSITION | PARENTS));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005458 }
5459 }
5460
5461 if (w != startingWindow) {
5462 if (w.isInteresting()) {
5463 // Add non-main window as interesting since the main app has already been added
5464 if (findMainWindow(false /* includeStartingApp */) != w) {
5465 mNumInterestingWindows++;
5466 }
5467 if (w.isDrawnLw()) {
5468 mNumDrawnWindows++;
5469
5470 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5471 Slog.v(TAG, "tokenMayBeDrawn: "
5472 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
5473 + " freezingScreen=" + mFreezingScreen
5474 + " mAppFreezing=" + w.mAppFreezing);
5475 }
5476
5477 isInterestingAndDrawn = true;
5478 }
5479 }
5480 } else if (w.isDrawnLw()) {
Riddle Hsufd66d4d2019-11-14 10:35:55 +08005481 // The starting window for this container is drawn.
5482 mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(this);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005483 startingDisplayed = true;
5484 }
5485 }
5486
5487 return isInterestingAndDrawn;
5488 }
5489
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005490 /**
5491 * Called when the key dispatching to a window associated with the app window container
5492 * timed-out.
5493 *
5494 * @param reason The reason for the key dispatching time out.
5495 * @param windowPid The pid of the window key dispatching timed out on.
5496 * @return True if input dispatching should be aborted.
5497 */
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005498 public boolean keyDispatchingTimedOut(String reason, int windowPid) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005499 ActivityRecord anrActivity;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005500 WindowProcessController anrApp;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005501 boolean windowFromSameProcessAsActivity;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005502 synchronized (mAtmService.mGlobalLock) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005503 anrActivity = getWaitingHistoryRecordLocked();
5504 anrApp = app;
Brian Carlstrom7b0f2e82017-03-31 00:24:18 -07005505 windowFromSameProcessAsActivity =
Vishnu Nair19479df2019-10-30 08:03:15 -07005506 !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005507 }
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005508
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005509 if (windowFromSameProcessAsActivity) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005510 return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
Andrii Kulianeceebbf2019-06-26 17:36:51 -07005511 anrActivity.shortComponentName, anrActivity.info.applicationInfo,
5512 shortComponentName, app, false, reason);
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005513 } else {
5514 // In this case another process added windows using this activity token. So, we call the
5515 // generic service input dispatch timed out method so that the right process is blamed.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005516 return mAtmService.mAmInternal.inputDispatchingTimedOut(
Wale Ogunwale51cc98a2018-10-15 10:41:05 -07005517 windowPid, false /* aboveSystem */, reason) < 0;
Wale Ogunwale7402ddf2017-03-29 12:58:24 -07005518 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005519 }
5520
5521 private ActivityRecord getWaitingHistoryRecordLocked() {
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005522 // First find the real culprit... if this activity has stopped, then the key dispatching
riddle_hsudb46d6b2015-04-01 18:58:07 +08005523 // timeout should not be caused by this.
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01005524 if (stopped) {
Louis Chang149d5c82019-12-30 09:47:39 +08005525 final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
riddle_hsudb46d6b2015-04-01 18:58:07 +08005526 // Try to use the one which is closest to top.
Bryce Leec4ab62a2018-03-05 14:19:26 -08005527 ActivityRecord r = stack.getResumedActivity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005528 if (r == null) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08005529 r = stack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005531 if (r != null) {
5532 return r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 }
5534 }
riddle_hsudb46d6b2015-04-01 18:58:07 +08005535 return this;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 }
5537
Chong Zhang87761972016-08-22 13:53:24 -07005538 /** Checks whether the activity should be shown for current user. */
5539 public boolean okToShowLocked() {
Bryce Lee8558ec72017-08-17 15:37:26 -07005540 // We cannot show activities when the device is locked and the application is not
5541 // encryption aware.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005542 if (!StorageManager.isUserKeyUnlocked(mUserId)
Bryce Lee8558ec72017-08-17 15:37:26 -07005543 && !info.applicationInfo.isEncryptionAware()) {
5544 return false;
5545 }
5546
Chong Zhang87761972016-08-22 13:53:24 -07005547 return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005548 || (mStackSupervisor.isCurrentProfileLocked(mUserId)
5549 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
Chong Zhang87761972016-08-22 13:53:24 -07005550 }
5551
Wale Ogunwalea38654f2019-11-17 20:37:15 -08005552 boolean canBeTopRunning() {
5553 return !finishing && okToShowLocked();
5554 }
5555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 /**
5557 * This method will return true if the activity is either visible, is becoming visible, is
5558 * currently pausing, or is resumed.
5559 */
5560 public boolean isInterestingToUserLocked() {
Issei Suzuki1669ea42019-11-06 14:20:59 +01005561 return mVisibleRequested || nowVisible || mState == PAUSING || mState == RESUMED;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005562 }
5563
Andrii Kulian46799182019-10-17 16:26:17 -07005564 void setSleeping(boolean sleeping) {
5565 mSetToSleep = sleeping;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005566 }
Craig Mautnerf81b90872013-02-26 13:02:43 -08005567
Craig Mautnerd2328952013-03-05 12:46:26 -08005568 static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005569 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08005570 if (r == null || r.getParent() == null) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005571 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005572 }
Louis Changcdec0802019-11-11 11:45:07 +08005573 final Task task = r.task;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08005574 if (onlyRoot && r.compareTo(task.getRootActivity(
5575 false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)) > 0) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08005576 return INVALID_TASK_ID;
Craig Mautnerd2328952013-03-05 12:46:26 -08005577 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005578 return task.mTaskId;
Craig Mautnerd2328952013-03-05 12:46:26 -08005579 }
5580
5581 static ActivityRecord isInStackLocked(IBinder token) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07005582 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08005583 return (r != null) ? r.getRootTask().isInStackLocked(r) : null;
Craig Mautnerd2328952013-03-05 12:46:26 -08005584 }
5585
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07005586 static ActivityStack getStackLocked(IBinder token) {
Craig Mautnerd2328952013-03-05 12:46:26 -08005587 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
5588 if (r != null) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08005589 return r.getRootTask();
Craig Mautnerd2328952013-03-05 12:46:26 -08005590 }
5591 return null;
5592 }
5593
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005594 /**
Riddle Hsufd4a0502018-10-16 01:05:16 +08005595 * @return display id to which this record is attached,
5596 * {@link android.view.Display#INVALID_DISPLAY} if not attached.
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005597 */
5598 int getDisplayId() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08005599 final ActivityStack stack = getRootTask();
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005600 if (stack == null) {
Riddle Hsufd4a0502018-10-16 01:05:16 +08005601 return INVALID_DISPLAY;
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005602 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08005603 return stack.getDisplayId();
Andrii Kulian5406e7a2016-10-21 11:55:23 -07005604 }
5605
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005606 final boolean isDestroyable() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005607 if (finishing || !hasProcess()) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005608 // This would be redundant.
5609 return false;
5610 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08005611 final ActivityStack stack = getRootTask();
Andrii Kulianf49a58c2019-08-14 17:34:27 -07005612 if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState
5613 || !stopped) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005614 // We're not ready for this kind of thing.
5615 return false;
5616 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01005617 if (mVisibleRequested) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07005618 // The user would notice this!
5619 return false;
5620 }
5621 return true;
5622 }
5623
Winson Chung3bad5cc02014-08-19 17:44:32 -07005624 private static String createImageFilename(long createTime, int taskId) {
5625 return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
Ruben Brunkf53497c2017-03-27 20:26:17 -07005626 IMAGE_EXTENSION;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07005627 }
5628
Craig Mautner648f69b2014-09-18 14:16:26 -07005629 void setTaskDescription(TaskDescription _taskDescription) {
5630 Bitmap icon;
5631 if (_taskDescription.getIconFilename() == null &&
5632 (icon = _taskDescription.getIcon()) != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07005633 final String iconFilename = createImageFilename(createTime, task.mTaskId);
5634 final File iconFile = new File(TaskPersister.getUserImagesDir(task.mUserId),
Winson Chungc8408b82017-01-25 17:58:56 -08005635 iconFilename);
Suprabh Shukla23593142015-11-03 17:31:15 -08005636 final String iconFilePath = iconFile.getAbsolutePath();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005637 mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
Suprabh Shukla23593142015-11-03 17:31:15 -08005638 _taskDescription.setIconFilename(iconFilePath);
Craig Mautner648f69b2014-09-18 14:16:26 -07005639 }
5640 taskDescription = _taskDescription;
Winson Chung1df39e22020-04-09 14:30:55 -07005641 getTask().updateTaskDescription();
Craig Mautner648f69b2014-09-18 14:16:26 -07005642 }
5643
Amith Yamasani0af6fa72016-01-17 15:36:19 -08005644 void setVoiceSessionLocked(IVoiceInteractionSession session) {
5645 voiceSession = session;
5646 pendingVoiceInteractionStart = false;
5647 }
5648
5649 void clearVoiceSessionLocked() {
5650 voiceSession = null;
5651 pendingVoiceInteractionStart = false;
5652 }
5653
Jorim Jaggi02886a82016-12-06 09:10:06 -08005654 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
Jorim Jaggi42befc62017-06-13 11:54:04 -07005655 showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
5656 }
5657
5658 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
5659 boolean fromRecents) {
Wale Ogunwale19866e22017-04-19 06:05:13 -07005660 if (mTaskOverlay) {
5661 // We don't show starting window for overlay activities.
5662 return;
5663 }
Sunny Goyald85bed52018-09-25 12:01:01 -07005664 if (pendingOptions != null
5665 && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
5666 // Don't show starting window when using shared element transition.
5667 return;
5668 }
Wale Ogunwale19866e22017-04-19 06:05:13 -07005669
Wale Ogunwale3b232392016-05-13 15:37:13 -07005670 final CompatibilityInfo compatInfo =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08005671 mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08005672 final boolean shown = addStartingWindow(packageName, theme,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005673 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
Jorim Jaggibae01b12017-04-11 16:29:10 -07005674 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
Jorim Jaggi70aa4d12017-05-15 00:05:54 +02005675 allowTaskSnapshot(),
Louis Changeadb22f2019-06-19 12:09:23 +08005676 mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
Jorim Jaggi42befc62017-06-13 11:54:04 -07005677 fromRecents);
Wale Ogunwale3b232392016-05-13 15:37:13 -07005678 if (shown) {
5679 mStartingWindowState = STARTING_WINDOW_SHOWN;
5680 }
5681 }
5682
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005683 /**
5684 * If any activities below the top running one are in the INITIALIZING state and they have a
5685 * starting window displayed then remove that starting window. It is possible that the activity
5686 * in this state will never resumed in which case that starting window will be orphaned.
5687 * <p>
5688 * It should only be called if this activity is behind other fullscreen activity.
5689 */
5690 void cancelInitializing() {
5691 if (mStartingWindowState == STARTING_WINDOW_SHOWN) {
5692 // Remove orphaned starting window.
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005693 if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
5694 mStartingWindowState = STARTING_WINDOW_REMOVED;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08005695 removeStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005696 }
Riddle Hsu13c27ae2019-10-05 23:10:15 +08005697 if (isState(INITIALIZING) && !shouldBeVisible(
5698 true /* behindFullscreenActivity */, true /* ignoringKeyguard */)) {
5699 // Remove the unknown visibility record because an invisible activity shouldn't block
5700 // the keyguard transition.
5701 mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
5702 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08005703 }
5704
Garfield Tane8d84ab2019-10-11 09:49:40 -07005705 void postWindowRemoveStartingWindowCleanup(WindowState win) {
5706 // TODO: Something smells about the code below...Is there a better way?
5707 if (startingWindow == win) {
5708 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
5709 removeStartingWindow();
5710 } else if (mChildren.size() == 0) {
5711 // If this is the last window and we had requested a starting transition window,
5712 // well there is no point now.
5713 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
5714 mStartingData = null;
Issei Suzukif2f6c912019-11-08 11:24:18 +01005715 if (mVisibleSetFromTransferredStartingWindow) {
5716 // We set the visible state to true for the token from a transferred starting
5717 // window. We now reset it back to false since the starting window was the last
5718 // window in the token.
5719 setVisible(false);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005720 }
5721 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
5722 // If this is the last window except for a starting transition window,
5723 // we need to get rid of the starting transition.
5724 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
5725 removeStartingWindow();
5726 }
5727 }
5728
5729 void removeDeadWindows() {
5730 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
5731 WindowState win = mChildren.get(winNdx);
5732 if (win.mAppDied) {
5733 ProtoLog.w(WM_DEBUG_ADD_REMOVE,
5734 "removeDeadWindows: %s", win);
5735 // Set mDestroying, we don't want any animation or delayed removal here.
5736 win.mDestroying = true;
5737 // Also removes child windows.
5738 win.removeIfPossible();
5739 }
5740 }
5741 }
5742
5743 boolean hasWindowsAlive() {
5744 for (int i = mChildren.size() - 1; i >= 0; i--) {
5745 // No need to loop through child windows as the answer should be the same as that of the
5746 // parent window.
5747 if (!(mChildren.get(i)).mAppDied) {
5748 return true;
5749 }
5750 }
5751 return false;
5752 }
5753
5754 void setWillReplaceWindows(boolean animate) {
5755 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5756 "Marking app token %s with replacing windows.", this);
5757
5758 for (int i = mChildren.size() - 1; i >= 0; i--) {
5759 final WindowState w = mChildren.get(i);
5760 w.setWillReplaceWindow(animate);
5761 }
5762 }
5763
5764 void setWillReplaceChildWindows() {
5765 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
5766 + " with replacing child windows.", this);
5767 for (int i = mChildren.size() - 1; i >= 0; i--) {
5768 final WindowState w = mChildren.get(i);
5769 w.setWillReplaceChildWindows();
5770 }
5771 }
5772
5773 void clearWillReplaceWindows() {
5774 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5775 "Resetting app token %s of replacing window marks.", this);
5776
5777 for (int i = mChildren.size() - 1; i >= 0; i--) {
5778 final WindowState w = mChildren.get(i);
5779 w.clearWillReplaceWindow();
5780 }
5781 }
5782
5783 void requestUpdateWallpaperIfNeeded() {
5784 for (int i = mChildren.size() - 1; i >= 0; i--) {
5785 final WindowState w = mChildren.get(i);
5786 w.requestUpdateWallpaperIfNeeded();
5787 }
5788 }
5789
5790 /**
5791 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
Riddle Hsu84bc3d72019-12-19 19:24:07 +08005792 * true and isn't fully transparent.
Garfield Tane8d84ab2019-10-11 09:49:40 -07005793 */
Riddle Hsu84bc3d72019-12-19 19:24:07 +08005794 WindowState getTopFullscreenOpaqueWindow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005795 for (int i = mChildren.size() - 1; i >= 0; i--) {
5796 final WindowState win = mChildren.get(i);
Riddle Hsu84bc3d72019-12-19 19:24:07 +08005797 if (win != null && win.mAttrs.isFullscreen() && !win.isFullyTransparent()) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005798 return win;
5799 }
5800 }
5801 return null;
5802 }
5803
5804 WindowState findMainWindow() {
5805 return findMainWindow(true);
5806 }
5807
5808 /**
5809 * Finds the main window that either has type base application or application starting if
5810 * requested.
5811 *
5812 * @param includeStartingApp Allow to search application-starting windows to also be returned.
5813 * @return The main window of type base application or application starting if requested.
5814 */
5815 WindowState findMainWindow(boolean includeStartingApp) {
5816 WindowState candidate = null;
5817 for (int j = mChildren.size() - 1; j >= 0; --j) {
5818 final WindowState win = mChildren.get(j);
5819 final int type = win.mAttrs.type;
5820 // No need to loop through child window as base application and starting types can't be
5821 // child windows.
5822 if (type == TYPE_BASE_APPLICATION
5823 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
5824 // In cases where there are multiple windows, we prefer the non-exiting window. This
5825 // happens for example when replacing windows during an activity relaunch. When
5826 // constructing the animation, we want the new window, not the exiting one.
5827 if (win.mAnimatingExit) {
5828 candidate = win;
5829 } else {
5830 return win;
5831 }
5832 }
5833 }
5834 return candidate;
5835 }
5836
5837 SurfaceControl getAppAnimationLayer() {
5838 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
5839 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
5840 : ANIMATION_LAYER_STANDARD);
5841 }
5842
5843 @Override
5844 boolean needsZBoost() {
5845 return mNeedsZBoost || super.needsZBoost();
5846 }
5847
5848 @Override
5849 public SurfaceControl getAnimationLeashParent() {
5850 // For transitions in the pinned stack (menu activity) we just let them occur as a child
5851 // of the pinned stack.
5852 // All normal app transitions take place in an animation layer which is below the pinned
5853 // stack but may be above the parent stacks of the given animating apps by default. When
5854 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
5855 // stack, i.e. the hierarchy of the surfaces is unchanged.
5856 if (inPinnedWindowingMode()) {
5857 return getStack().getSurfaceControl();
5858 } else if (WindowManagerService.sHierarchicalAnimations) {
5859 return super.getAnimationLeashParent();
5860 } else {
5861 return getAppAnimationLayer();
5862 }
5863 }
5864
Garfield Tane8d84ab2019-10-11 09:49:40 -07005865 @VisibleForTesting
Evan Rosky50ea8c12020-04-02 20:49:05 -07005866 boolean shouldAnimate() {
5867 return task == null || task.shouldAnimate();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005868 }
5869
5870 /**
5871 * Creates a layer to apply crop to an animation.
5872 */
5873 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
5874 ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
5875 final SurfaceControl.Builder builder = makeAnimationLeash()
5876 .setParent(getAnimationLeashParent())
5877 .setName(getSurfaceControl() + " - animation-bounds");
5878 final SurfaceControl boundsLayer = builder.build();
5879 t.show(boundsLayer);
5880 return boundsLayer;
5881 }
5882
Garfield Tane8d84ab2019-10-11 09:49:40 -07005883 @Override
5884 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
5885 return mAnimatingActivityRegistry != null
5886 && mAnimatingActivityRegistry.notifyAboutToFinish(
5887 this, endDeferFinishCallback);
5888 }
5889
lumark9bca6b42019-10-17 18:35:22 +08005890 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07005891 boolean isWaitingForTransitionStart() {
5892 final DisplayContent dc = getDisplayContent();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08005893 return dc != null && dc.mAppTransition.isTransitionSet()
Garfield Tane8d84ab2019-10-11 09:49:40 -07005894 && (dc.mOpeningApps.contains(this)
5895 || dc.mClosingApps.contains(this)
Evan Rosky55bddd82020-01-29 13:07:18 -08005896 || dc.mChangingContainers.contains(this));
Garfield Tane8d84ab2019-10-11 09:49:40 -07005897 }
5898
Evan Rosky55bddd82020-01-29 13:07:18 -08005899 private int getAnimationLayer() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005900 // The leash is parented to the animation layer. We need to preserve the z-order by using
5901 // the prefix order index, but we boost if necessary.
Evan Rosky55bddd82020-01-29 13:07:18 -08005902 int layer;
Garfield Tane8d84ab2019-10-11 09:49:40 -07005903 if (!inPinnedWindowingMode()) {
5904 layer = getPrefixOrderIndex();
5905 } else {
5906 // Pinned stacks have animations take place within themselves rather than an animation
5907 // layer so we need to preserve the order relative to the stack (e.g. the order of our
5908 // task/parent).
5909 layer = getParent().getPrefixOrderIndex();
5910 }
5911
5912 if (mNeedsZBoost) {
5913 layer += Z_BOOST_BASE;
5914 }
Evan Rosky55bddd82020-01-29 13:07:18 -08005915 return layer;
5916 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005917
Evan Rosky55bddd82020-01-29 13:07:18 -08005918 @Override
5919 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
5920 t.setLayer(leash, getAnimationLayer());
5921 getDisplayContent().assignStackOrdering();
5922 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005923
Evan Rosky55bddd82020-01-29 13:07:18 -08005924 @Override
5925 public void onLeashAnimationStarting(Transaction t, SurfaceControl leash) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005926 if (mAnimatingActivityRegistry != null) {
5927 mAnimatingActivityRegistry.notifyStarting(this);
5928 }
5929
5930 // If the animation needs to be cropped then an animation bounds layer is created as a child
5931 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
5932 if (mNeedsAnimationBoundsLayer) {
5933 mTmpRect.setEmpty();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005934 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
5935 getTransit(), task)) {
5936 task.getBounds(mTmpRect);
5937 } else {
Louis Changdc077272019-11-12 16:52:56 +08005938 final ActivityStack stack = getStack();
Garfield Tane8d84ab2019-10-11 09:49:40 -07005939 if (stack == null) {
5940 return;
5941 }
5942 // Set clip rect to stack bounds.
5943 stack.getBounds(mTmpRect);
5944 }
5945 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
5946
5947 // Crop to stack bounds.
lumark85718662019-12-26 22:05:12 +08005948 if (!WindowManagerService.sHierarchicalAnimations) {
5949 // For Hierarchical animation, we don't need to set window crop since the leash
5950 // surface size has already same as the animating container.
5951 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
5952 }
Evan Rosky55bddd82020-01-29 13:07:18 -08005953 t.setLayer(leash, 0);
5954 t.setLayer(mAnimationBoundsLayer, getAnimationLayer());
Garfield Tane8d84ab2019-10-11 09:49:40 -07005955
5956 // Reparent leash to animation bounds layer.
5957 t.reparent(leash, mAnimationBoundsLayer);
5958 }
5959 }
5960
5961 @Override
5962 void prepareSurfaces() {
chaviw9177c772020-03-24 11:35:22 -07005963 final boolean show = isVisible() || isAnimatingExcluding(PARENTS,
5964 ANIMATION_TYPE_SCREEN_ROTATION);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005965
5966 if (mSurfaceControl != null) {
5967 if (show && !mLastSurfaceShowing) {
5968 getPendingTransaction().show(mSurfaceControl);
5969 } else if (!show && mLastSurfaceShowing) {
5970 getPendingTransaction().hide(mSurfaceControl);
5971 }
5972 }
5973 if (mThumbnail != null) {
5974 mThumbnail.setShowing(getPendingTransaction(), show);
5975 }
5976 mLastSurfaceShowing = show;
5977 super.prepareSurfaces();
5978 }
5979
5980 /**
5981 * @return Whether our {@link #getSurfaceControl} is currently showing.
5982 */
5983 boolean isSurfaceShowing() {
5984 return mLastSurfaceShowing;
5985 }
5986
Garfield Tane8d84ab2019-10-11 09:49:40 -07005987 void attachThumbnailAnimation() {
lumark5341d1c2019-12-14 01:54:02 +08005988 if (!isAnimating(PARENTS)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07005989 return;
5990 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07005991 final GraphicBuffer thumbnailHeader =
Louis Changcdec0802019-11-11 11:45:07 +08005992 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005993 if (thumbnailHeader == null) {
Louis Changcdec0802019-11-11 11:45:07 +08005994 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", task);
Garfield Tane8d84ab2019-10-11 09:49:40 -07005995 return;
5996 }
5997 clearThumbnail();
lumark85718662019-12-26 22:05:12 +08005998 final Transaction transaction = getAnimatingContainer().getPendingTransaction();
lumarkbc0032a2019-11-01 21:38:13 +08005999 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
lumark85718662019-12-26 22:05:12 +08006000 transaction, getAnimatingContainer(), thumbnailHeader);
6001 mThumbnail.startAnimation(transaction, loadThumbnailAnimation(thumbnailHeader));
Garfield Tane8d84ab2019-10-11 09:49:40 -07006002 }
6003
6004 /**
6005 * Attaches a surface with a thumbnail for the
6006 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
6007 */
6008 void attachCrossProfileAppsThumbnailAnimation() {
lumark5341d1c2019-12-14 01:54:02 +08006009 if (!isAnimating(PARENTS)) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006010 return;
6011 }
6012 clearThumbnail();
6013
6014 final WindowState win = findMainWindow();
6015 if (win == null) {
6016 return;
6017 }
lumarkb46c4fe2020-03-16 19:24:01 +08006018 final Rect frame = win.getRelativeFrameLw();
Louis Changcdec0802019-11-11 11:45:07 +08006019 final int thumbnailDrawableRes = task.mUserId == mWmService.mCurrentUserId
Garfield Tane8d84ab2019-10-11 09:49:40 -07006020 ? R.drawable.ic_account_circle
6021 : R.drawable.ic_corp_badge;
6022 final GraphicBuffer thumbnail =
6023 getDisplayContent().mAppTransition
6024 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
6025 if (thumbnail == null) {
6026 return;
6027 }
lumarkb46c4fe2020-03-16 19:24:01 +08006028 final Transaction transaction = getPendingTransaction();
lumarkbc0032a2019-11-01 21:38:13 +08006029 mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
lumarkb46c4fe2020-03-16 19:24:01 +08006030 transaction, getTask(), thumbnail);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006031 final Animation animation =
6032 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
lumarkb46c4fe2020-03-16 19:24:01 +08006033 frame);
lumark85718662019-12-26 22:05:12 +08006034 mThumbnail.startAnimation(transaction, animation, new Point(frame.left, frame.top));
Garfield Tane8d84ab2019-10-11 09:49:40 -07006035 }
6036
6037 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
6038 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
6039
6040 // If this is a multi-window scenario, we use the windows frame as
6041 // destination of the thumbnail header animation. If this is a full screen
6042 // window scenario, we use the whole display as the target.
6043 WindowState win = findMainWindow();
6044 Rect appRect = win != null ? win.getContentFrameLw() :
6045 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
6046 final Rect insets = win != null ? win.getContentInsets() : null;
6047 final Configuration displayConfig = mDisplayContent.getConfiguration();
6048 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Louis Changcdec0802019-11-11 11:45:07 +08006049 appRect, insets, thumbnailHeader, task, displayConfig.uiMode,
Garfield Tane8d84ab2019-10-11 09:49:40 -07006050 displayConfig.orientation);
6051 }
6052
6053 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006054 public void onAnimationLeashLost(Transaction t) {
6055 super.onAnimationLeashLost(t);
6056 if (mAnimationBoundsLayer != null) {
6057 t.remove(mAnimationBoundsLayer);
6058 mAnimationBoundsLayer = null;
6059 }
6060
6061 if (mAnimatingActivityRegistry != null) {
6062 mAnimatingActivityRegistry.notifyFinished(this);
6063 }
6064 }
6065
6066 @Override
Issei Suzuki8b995df2020-01-08 12:23:04 +01006067 protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
6068 super.onAnimationFinished(type, anim);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006069
Issei Suzuki2bcbd682019-11-08 13:20:14 +01006070 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished");
Garfield Tane8d84ab2019-10-11 09:49:40 -07006071 mTransit = TRANSIT_UNSET;
6072 mTransitFlags = 0;
6073 mNeedsZBoost = false;
6074 mNeedsAnimationBoundsLayer = false;
6075
6076 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
Issei Suzuki2bcbd682019-11-08 13:20:14 +01006077 "ActivityRecord");
Garfield Tane8d84ab2019-10-11 09:49:40 -07006078
6079 clearThumbnail();
Issei Suzukid4ee1cc2019-11-08 13:20:14 +01006080 setClientVisible(isVisible() || mVisibleRequested);
Garfield Tane8d84ab2019-10-11 09:49:40 -07006081
6082 getDisplayContent().computeImeTargetIfNeeded(this);
6083
6084 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
6085 + ": reportedVisible=" + reportedVisible
6086 + " okToDisplay=" + okToDisplay()
6087 + " okToAnimate=" + okToAnimate()
6088 + " startingDisplayed=" + startingDisplayed);
6089
6090 // clean up thumbnail window
6091 if (mThumbnail != null) {
6092 mThumbnail.destroy();
6093 mThumbnail = null;
6094 }
6095
6096 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
6097 // traverse the copy.
6098 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
6099 children.forEach(WindowState::onExitAnimationDone);
6100
6101 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
6102 scheduleAnimation();
6103
Riddle Hsu01a62ff2020-01-01 00:43:53 +08006104 if (!mStackSupervisor.mStoppingActivities.isEmpty()
6105 || !mStackSupervisor.mFinishingActivities.isEmpty()) {
6106 if (mRootWindowContainer.allResumedActivitiesIdle()) {
6107 // If all activities are already idle then we now need to make sure we perform
6108 // the full stop of this activity. This is because we won't do that while they
6109 // are still waiting for the animation to finish.
Riddle Hsufc8ab262019-12-31 15:31:24 +08006110 mStackSupervisor.scheduleIdle();
Riddle Hsu01a62ff2020-01-01 00:43:53 +08006111 } else if (mRootWindowContainer.allResumedActivitiesVisible()) {
6112 // If all resumed activities are already visible (and should be drawn, see
6113 // updateReportedVisibility ~ nowVisible) but not idle, we still schedule to
6114 // process the stopping and finishing activities because the transition is done.
6115 // This also avoids if the next activity never reports idle (e.g. animating view),
6116 // the previous will need to wait until idle timeout to be stopped or destroyed.
6117 mStackSupervisor.scheduleProcessStoppingAndFinishingActivities();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006118 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07006119 }
6120 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
6121 }
6122
Garfield Tane8d84ab2019-10-11 09:49:40 -07006123 void clearAnimatingFlags() {
6124 boolean wallpaperMightChange = false;
6125 for (int i = mChildren.size() - 1; i >= 0; i--) {
6126 final WindowState win = mChildren.get(i);
6127 wallpaperMightChange |= win.clearAnimatingFlags();
6128 }
6129 if (wallpaperMightChange) {
6130 requestUpdateWallpaperIfNeeded();
6131 }
6132 }
6133
Garfield Tane8d84ab2019-10-11 09:49:40 -07006134 @Override
6135 void cancelAnimation() {
6136 cancelAnimationOnly();
6137 clearThumbnail();
Evan Rosky55bddd82020-01-29 13:07:18 -08006138 mSurfaceFreezer.unfreeze(getPendingTransaction());
Garfield Tane8d84ab2019-10-11 09:49:40 -07006139 }
6140
6141 /**
6142 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
6143 * or interim leashes.
6144 * <p>
6145 * Used when canceling in preparation for starting a new animation.
6146 */
6147 void cancelAnimationOnly() {
6148 super.cancelAnimation();
6149 }
6150
6151 @VisibleForTesting
lumarkbc0032a2019-11-01 21:38:13 +08006152 WindowContainerThumbnail getThumbnail() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006153 return mThumbnail;
6154 }
6155
6156 private void clearThumbnail() {
6157 if (mThumbnail == null) {
6158 return;
6159 }
6160 mThumbnail.destroy();
6161 mThumbnail = null;
6162 }
6163
6164 public int getTransit() {
6165 return mTransit;
6166 }
6167
6168 int getTransitFlags() {
6169 return mTransitFlags;
6170 }
6171
6172 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
6173 mRemoteAnimationDefinition = definition;
Winson Chung10fc25d2019-12-10 14:13:56 -08006174 if (definition != null) {
6175 definition.linkToDeath(this::unregisterRemoteAnimations);
6176 }
6177 }
6178
6179 void unregisterRemoteAnimations() {
6180 mRemoteAnimationDefinition = null;
Garfield Tane8d84ab2019-10-11 09:49:40 -07006181 }
6182
Evan Rosky55bddd82020-01-29 13:07:18 -08006183 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006184 RemoteAnimationDefinition getRemoteAnimationDefinition() {
6185 return mRemoteAnimationDefinition;
6186 }
6187
Riddle Hsu6f548e92020-01-13 13:34:09 +08006188 @Override
6189 void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames,
6190 Configuration config) {
6191 super.applyFixedRotationTransform(info, displayFrames, config);
6192 ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
6193 }
6194
Riddle Hsud16620e2020-04-06 20:48:06 +08006195 @Override
6196 void onCancelFixedRotationTransform(int originalDisplayRotation) {
6197 if (this != mDisplayContent.getLastOrientationSource()
6198 || getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED) {
6199 // Only need to handle the activity that should be rotated with display.
6200 return;
6201 }
6202
6203 // Perform rotation animation according to the rotation of this activity.
6204 startFreezingScreen(originalDisplayRotation);
6205 // This activity may relaunch or perform configuration change so once it has reported drawn,
6206 // the screen can be unfrozen.
6207 ensureActivityConfiguration(0 /* globalChanges */, !PRESERVE_WINDOWS);
6208 }
6209
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006210 void setRequestedOrientation(int requestedOrientation) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006211 setOrientation(requestedOrientation, mayFreezeScreenLocked());
Wale Ogunwale8b19de92018-11-29 19:58:26 -08006212 mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07006213 task.mTaskId, requestedOrientation);
Andrii Kulian5406e7a2016-10-21 11:55:23 -07006214 }
6215
Garfield Tan90b04282018-12-11 14:04:42 -08006216 private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
Evan Rosky730f6e82018-12-03 17:40:11 -08006217 final IBinder binder =
6218 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006219 setOrientation(requestedOrientation, binder, this);
Garfield Tan36a69ad2019-01-16 17:08:23 -08006220
6221 // Push the new configuration to the requested app in case where it's not pushed, e.g. when
6222 // the request is handled at task level with letterbox.
6223 if (!getMergedOverrideConfiguration().equals(
6224 mLastReportedConfiguration.getMergedConfiguration())) {
6225 ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
6226 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08006227 }
6228
Garfield Tane8d84ab2019-10-11 09:49:40 -07006229 void reportDescendantOrientationChangeIfNeeded() {
6230 // Orientation request is exposed only when we're visible. Therefore visibility change
6231 // will change requested orientation. Notify upward the hierarchy ladder to adjust
6232 // configuration. This is important to cases where activities with incompatible
6233 // orientations launch, or user goes back from an activity of bi-orientation to an
6234 // activity with specified orientation.
6235 if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
6236 return;
6237 }
6238
6239 final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
6240 onDescendantOrientationChanged(freezeToken, this);
6241 }
6242
6243 /**
6244 * We override because this class doesn't want its children affecting its reported orientation
6245 * in anyway.
6246 */
6247 @Override
6248 int getOrientation(int candidate) {
6249 if (candidate == SCREEN_ORIENTATION_BEHIND) {
6250 // Allow app to specify orientation regardless of its visibility state if the current
6251 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
6252 // wants us to use the orientation of the app behind it.
6253 return mOrientation;
6254 }
6255
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08006256 // The {@link ActivityRecord} should only specify an orientation when it is not closing.
6257 // Allowing closing {@link ActivityRecord} to participate can lead to an Activity in another
6258 // task being started in the wrong orientation during the transition.
6259 if (!getDisplayContent().mClosingApps.contains(this)
Garfield Tane8d84ab2019-10-11 09:49:40 -07006260 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
6261 return mOrientation;
6262 }
6263
6264 return SCREEN_ORIENTATION_UNSET;
6265 }
6266
6267 /** Returns the app's preferred orientation regardless of its currently visibility state. */
6268 int getRequestedOrientation() {
6269 return mOrientation;
6270 }
6271
Bryce Leea163b762017-01-24 11:05:01 -08006272 /**
6273 * Set the last reported global configuration to the client. Should be called whenever a new
6274 * global configuration is sent to the client for this activity.
6275 */
6276 void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006277 mLastReportedConfiguration.setGlobalConfiguration(config);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006278 }
6279
Bryce Leea163b762017-01-24 11:05:01 -08006280 /**
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006281 * Set the last reported configuration to the client. Should be called whenever
Bryce Leea163b762017-01-24 11:05:01 -08006282 * a new merged configuration is sent to the client for this activity.
6283 */
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006284 void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006285 setLastReportedConfiguration(config.getGlobalConfiguration(),
6286 config.getOverrideConfiguration());
Bryce Leea163b762017-01-24 11:05:01 -08006287 }
6288
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07006289 private void setLastReportedConfiguration(Configuration global, Configuration override) {
Bryce Lee8104e7a2017-08-17 09:16:03 -07006290 mLastReportedConfiguration.setConfiguration(global, override);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006291 }
6292
Riddle Hsu0a343c32018-12-21 00:40:48 +08006293 /**
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006294 * @return {@code true} if this activity is in size compatibility mode that uses the different
Riddle Hsue47501b2020-02-18 12:45:41 +08006295 * density than its parent or its bounds don't fit in parent naturally.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006296 */
6297 boolean inSizeCompatMode() {
Riddle Hsu9264a272020-03-04 23:10:41 +08006298 if (mCompatDisplayInsets == null || !shouldUseSizeCompatMode()
6299 // The orientation is different from parent when transforming.
6300 || isFixedRotationTransforming()) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006301 return false;
6302 }
Riddle Hsu359c84d2019-12-10 17:49:52 +08006303 final Rect appBounds = getConfiguration().windowConfiguration.getAppBounds();
6304 if (appBounds == null) {
6305 // The app bounds hasn't been computed yet.
Riddle Hsu04164182019-03-07 18:03:27 +08006306 return false;
6307 }
6308
6309 final Configuration parentConfig = getParent().getConfiguration();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006310 // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
6311 // fields should be changed with density and bounds, so here only compares the most
6312 // significant field.
Riddle Hsu359c84d2019-12-10 17:49:52 +08006313 if (parentConfig.densityDpi != getConfiguration().densityDpi) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006314 return true;
6315 }
Riddle Hsu04164182019-03-07 18:03:27 +08006316
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006317 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
Riddle Hsu359c84d2019-12-10 17:49:52 +08006318 final int appWidth = appBounds.width();
6319 final int appHeight = appBounds.height();
Riddle Hsuaec55442019-03-12 17:25:35 +08006320 final int parentAppWidth = parentAppBounds.width();
6321 final int parentAppHeight = parentAppBounds.height();
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006322 if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
6323 // Matched the parent bounds.
6324 return false;
6325 }
6326 if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
6327 // Both sides are smaller than the parent.
6328 return true;
6329 }
Riddle Hsuaec55442019-03-12 17:25:35 +08006330 if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
Riddle Hsu04164182019-03-07 18:03:27 +08006331 // One side is larger than the parent.
6332 return true;
6333 }
6334
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006335 // The rest of the condition is that only one side is smaller than the parent, but it still
6336 // needs to exclude the cases where the size is limited by the fixed aspect ratio.
6337 if (info.maxAspectRatio > 0) {
Riddle Hsue47501b2020-02-18 12:45:41 +08006338 final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
6339 / Math.min(appWidth, appHeight);
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006340 if (aspectRatio >= info.maxAspectRatio) {
6341 // The current size has reached the max aspect ratio.
6342 return false;
Riddle Hsuaec55442019-03-12 17:25:35 +08006343 }
6344 }
Riddle Hsu9ad1785102019-03-26 00:26:54 +08006345 if (info.minAspectRatio > 0) {
6346 // The activity should have at least the min aspect ratio, so this checks if the parent
6347 // still has available space to provide larger aspect ratio.
6348 final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
6349 / Math.min(parentAppWidth, parentAppHeight);
6350 if (parentAspectRatio <= info.minAspectRatio) {
6351 // The long side has reached the parent.
6352 return false;
6353 }
6354 }
6355 return true;
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006356 }
6357
6358 /**
Riddle Hsu0a343c32018-12-21 00:40:48 +08006359 * Indicates the activity will keep the bounds and screen configuration when it was first
6360 * launched, no matter how its parent changes.
6361 *
6362 * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
6363 * aspect ratio.
6364 */
Riddle Hsu74826262019-04-17 14:57:42 +08006365 boolean shouldUseSizeCompatMode() {
yunho.shinaeb50b92019-12-05 13:06:42 +09006366 if (inMultiWindowMode() || getWindowConfiguration().hasWindowDecorCaption()) {
6367 final ActivityRecord root = task != null ? task.getRootActivity() : null;
6368 if (root != null && root != this && !root.shouldUseSizeCompatMode()) {
6369 // If the root activity doesn't use size compatibility mode, the activities above
6370 // are forced to be the same for consistent visual appearance.
6371 return false;
6372 }
6373 }
Riddle Hsu0a343c32018-12-21 00:40:48 +08006374 return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
6375 // The configuration of non-standard type should be enforced by system.
6376 && isActivityTypeStandard()
6377 && !mAtmService.mForceResizableActivities;
6378 }
6379
Garfield Tane8d84ab2019-10-11 09:49:40 -07006380 boolean hasSizeCompatBounds() {
6381 return mSizeCompatBounds != null;
6382 }
6383
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006384 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006385 private void updateSizeCompatMode() {
6386 if (mCompatDisplayInsets != null || !shouldUseSizeCompatMode()) {
6387 // The override configuration is set only once in size compatibility mode.
6388 return;
6389 }
6390 final Configuration parentConfig = getParent().getConfiguration();
6391 if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
6392 // Don't compute when launching in fullscreen and the fixed orientation is not the
6393 // current orientation. It is more accurately to compute the override bounds from
6394 // the updated configuration after the fixed orientation is applied.
6395 return;
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006396 }
Riddle Hsu74826262019-04-17 14:57:42 +08006397
Evan Rosky72f084d2019-09-11 17:05:16 -07006398 Configuration overrideConfig = getRequestedOverrideConfiguration();
6399 final Configuration fullConfig = getConfiguration();
6400
6401 // Ensure the screen related fields are set. It is used to prevent activity relaunch
6402 // when moving between displays. For screenWidthDp and screenWidthDp, because they
6403 // are relative to bounds and density, they will be calculated in
Louis Changcdec0802019-11-11 11:45:07 +08006404 // {@link Task#computeConfigResourceOverrides} and the result will also be
Evan Rosky72f084d2019-09-11 17:05:16 -07006405 // relatively fixed.
6406 overrideConfig.colorMode = fullConfig.colorMode;
6407 overrideConfig.densityDpi = fullConfig.densityDpi;
Evan Rosky72f084d2019-09-11 17:05:16 -07006408 // The smallest screen width is the short side of screen bounds. Because the bounds
6409 // and density won't be changed, smallestScreenWidthDp is also fixed.
6410 overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
6411 if (info.isFixedOrientation()) {
6412 // lock rotation too. When in size-compat, onConfigurationChanged will watch for and
6413 // apply runtime rotation changes.
6414 overrideConfig.windowConfiguration.setRotation(
6415 fullConfig.windowConfiguration.getRotation());
6416 }
6417
6418 // The role of CompatDisplayInsets is like the override bounds.
Riddle Hsue47501b2020-02-18 12:45:41 +08006419 mCompatDisplayInsets = new CompatDisplayInsets(mDisplayContent, this);
Evan Rosky72f084d2019-09-11 17:05:16 -07006420 }
6421
Riddle Hsue47501b2020-02-18 12:45:41 +08006422 @VisibleForTesting
6423 void clearSizeCompatMode() {
6424 mSizeCompatScale = 1f;
6425 mSizeCompatBounds = null;
Evan Rosky72f084d2019-09-11 17:05:16 -07006426 mCompatDisplayInsets = null;
6427 onRequestedOverrideConfigurationChanged(EMPTY);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006428 }
6429
Garfield Tan0443b372019-01-04 15:00:13 -08006430 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006431 public boolean matchParentBounds() {
Riddle Hsue47501b2020-02-18 12:45:41 +08006432 if (super.matchParentBounds() && mCompatDisplayInsets == null) {
Garfield Tane8d84ab2019-10-11 09:49:40 -07006433 return true;
6434 }
Riddle Hsue47501b2020-02-18 12:45:41 +08006435 // An activity in size compatibility mode may have resolved override bounds, so the exact
6436 // bounds should also be checked. Otherwise IME window will show with offset. See
6437 // {@link DisplayContent#isImeAttachedToApp}.
Garfield Tane8d84ab2019-10-11 09:49:40 -07006438 final WindowContainer parent = getParent();
6439 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
6440 }
6441
6442 @Override
6443 float getSizeCompatScale() {
6444 return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
6445 }
6446
6447 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006448 void resolveOverrideConfiguration(Configuration newParentConfiguration) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08006449 super.resolveOverrideConfiguration(newParentConfiguration);
6450 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
6451 if (isFixedRotationTransforming()) {
6452 // The resolved configuration is applied with rotated display configuration. If this
6453 // activity matches its parent (the following resolving procedures are no-op), then it
6454 // can use the resolved configuration directly. Otherwise (e.g. fixed aspect ratio),
6455 // the rotated configuration is used as parent configuration to compute the actual
6456 // resolved configuration. It is like putting the activity in a rotated container.
Riddle Hsu9264a272020-03-04 23:10:41 +08006457 mTmpConfig.setTo(newParentConfiguration);
6458 mTmpConfig.updateFrom(resolvedConfig);
Riddle Hsu6f548e92020-01-13 13:34:09 +08006459 newParentConfiguration = mTmpConfig;
6460 }
Riddle Hsu74826262019-04-17 14:57:42 +08006461 if (mCompatDisplayInsets != null) {
Riddle Hsu04164182019-03-07 18:03:27 +08006462 resolveSizeCompatModeConfiguration(newParentConfiguration);
6463 } else {
Riddle Hsue47501b2020-02-18 12:45:41 +08006464 if (inMultiWindowMode()) {
Riddle Hsu23e18a92020-03-10 00:26:51 +08006465 // We ignore activities' requested orientation in multi-window modes. Task level may
6466 // take them into consideration when calculating bounds.
Garfield Tan966c0412019-11-19 11:34:27 -08006467 resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
Riddle Hsu23e18a92020-03-10 00:26:51 +08006468 // If the activity has requested override bounds, the configuration needs to be
6469 // computed accordingly.
6470 if (!matchParentBounds()) {
6471 task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
Riddle Hsue47501b2020-02-18 12:45:41 +08006472 }
Riddle Hsu23e18a92020-03-10 00:26:51 +08006473 } else {
6474 resolveFullscreenConfiguration(newParentConfiguration);
Riddle Hsu04164182019-03-07 18:03:27 +08006475 }
6476 }
Garfield Tan0443b372019-01-04 15:00:13 -08006477
6478 // Assign configuration sequence number into hierarchy because there is a different way than
6479 // ensureActivityConfiguration() in this class that uses configuration in WindowState during
6480 // layout traversals.
6481 mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
6482 getResolvedOverrideConfiguration().seq = mConfigurationSeq;
Riddle Hsu04164182019-03-07 18:03:27 +08006483 }
Riddle Hsu0a343c32018-12-21 00:40:48 +08006484
Riddle Hsu74826262019-04-17 14:57:42 +08006485 /**
Riddle Hsu23e18a92020-03-10 00:26:51 +08006486 * Resolves the configuration of activity in fullscreen mode. If the bounds are restricted by
6487 * aspect ratio, the position will be centered horizontally in parent's app bounds to balance
6488 * the visual appearance. The policy of aspect ratio has higher priority than the requested
6489 * override bounds.
6490 */
6491 private void resolveFullscreenConfiguration(Configuration newParentConfiguration) {
6492 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
6493 final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
6494 final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
6495 final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
6496 // Use tmp bounds to calculate aspect ratio so we can know whether the activity should use
6497 // restricted size (resolved bounds may be the requested override bounds).
6498 mTmpBounds.setEmpty();
6499 applyAspectRatio(mTmpBounds, parentAppBounds, parentBounds);
6500 // If the out bounds is not empty, it means the activity cannot fill parent's app bounds,
6501 // then there is space to be centered.
6502 final boolean needToBeCentered = !mTmpBounds.isEmpty();
6503 if (needToBeCentered) {
6504 resolvedBounds.set(mTmpBounds);
6505 // Exclude the horizontal decor area.
6506 resolvedBounds.left = parentAppBounds.left;
6507 }
6508 if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
6509 // Compute the configuration based on the resolved bounds. If aspect ratio doesn't
6510 // restrict, the bounds should be the requested override bounds.
6511 task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
6512 getFixedRotationTransformDisplayInfo());
6513 }
6514 if (needToBeCentered) {
6515 // Offset to center relative to parent's app bounds.
6516 final int offsetX = getHorizontalCenterOffset(
6517 parentAppBounds.width(), resolvedBounds.width());
6518 offsetBounds(resolvedConfig, offsetX, 0 /* offsetY */);
6519 }
6520 }
6521
6522 /**
Riddle Hsu74826262019-04-17 14:57:42 +08006523 * Resolves consistent screen configuration for orientation and rotation changes without
6524 * inheriting the parent bounds.
6525 */
Riddle Hsu04164182019-03-07 18:03:27 +08006526 private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
Riddle Hsu0a343c32018-12-21 00:40:48 +08006527 final Configuration resolvedConfig = getResolvedOverrideConfiguration();
Riddle Hsu04164182019-03-07 18:03:27 +08006528 final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
Riddle Hsue47501b2020-02-18 12:45:41 +08006529 final int requestedOrientation = getRequestedConfigurationOrientation();
6530 final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED;
6531 final int orientation = orientationRequested
6532 ? requestedOrientation
6533 : newParentConfiguration.orientation;
6534 int rotation = newParentConfiguration.windowConfiguration.getRotation();
6535 final boolean canChangeOrientation = handlesOrientationChangeFromDescendant();
6536 if (canChangeOrientation && mCompatDisplayInsets.mIsRotatable
6537 && !mCompatDisplayInsets.mIsFloating) {
6538 // Use parent rotation because the original display can rotate by requested orientation.
6539 resolvedConfig.windowConfiguration.setRotation(rotation);
6540 } else {
6541 final int overrideRotation = resolvedConfig.windowConfiguration.getRotation();
6542 if (overrideRotation != ROTATION_UNDEFINED) {
6543 rotation = overrideRotation;
6544 }
Evan Rosky72f084d2019-09-11 17:05:16 -07006545 }
6546
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006547 // Use compat insets to lock width and height. We should not use the parent width and height
6548 // because apps in compat mode should have a constant width and height. The compat insets
6549 // are locked when the app is first launched and are never changed after that, so we can
6550 // rely on them to contain the original and unchanging width and height of the app.
Evan Rosky72f084d2019-09-11 17:05:16 -07006551 final Rect containingAppBounds = new Rect();
Riddle Hsue47501b2020-02-18 12:45:41 +08006552 final Rect containingBounds = mTmpBounds;
6553 mCompatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
6554 orientation, orientationRequested, canChangeOrientation);
Riddle Hsu89e82062020-04-09 01:57:36 +08006555 resolvedBounds.set(containingBounds);
Riddle Hsue47501b2020-02-18 12:45:41 +08006556 // The size of floating task is fixed (only swap), so the aspect ratio is already correct.
6557 if (!mCompatDisplayInsets.mIsFloating) {
6558 applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
Riddle Hsu74826262019-04-17 14:57:42 +08006559 }
Riddle Hsu89e82062020-04-09 01:57:36 +08006560 // If the bounds are restricted by fixed aspect ratio, the resolved bounds should be put in
6561 // the container app bounds. Otherwise the entire container bounds are available.
6562 final boolean fillContainer = resolvedBounds.equals(containingBounds);
6563 if (!fillContainer) {
6564 // The horizontal position should not cover insets.
6565 resolvedBounds.left = containingAppBounds.left;
6566 }
Riddle Hsu74826262019-04-17 14:57:42 +08006567
Riddle Hsue47501b2020-02-18 12:45:41 +08006568 // Use resolvedBounds to compute other override configurations such as appBounds. The bounds
6569 // are calculated in compat container space. The actual position on screen will be applied
6570 // later, so the calculation is simpler that doesn't need to involve offset from parent.
Riddle Hsu74826262019-04-17 14:57:42 +08006571 task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
6572 mCompatDisplayInsets);
Riddle Hsuca928562019-11-22 01:04:14 +08006573 // Use current screen layout as source because the size of app is independent to parent.
6574 resolvedConfig.screenLayout = Task.computeScreenLayoutOverride(
6575 getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
6576 resolvedConfig.screenHeightDp);
Riddle Hsu74826262019-04-17 14:57:42 +08006577
Riddle Hsu04164182019-03-07 18:03:27 +08006578 // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
6579 // the parent bounds appropriately.
6580 if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
6581 resolvedConfig.orientation = newParentConfiguration.orientation;
Riddle Hsu0a343c32018-12-21 00:40:48 +08006582 }
Riddle Hsue47501b2020-02-18 12:45:41 +08006583
6584 // Below figure is an example that puts an activity which was launched in a larger container
6585 // into a smaller container.
6586 // The outermost rectangle is the real display bounds.
6587 // "@" is the parent app bounds.
6588 // "#" is the {@code resolvedBounds} that applies to application.
6589 // "*" is the {@code mSizeCompatBounds} that used to show on screen if scaled.
6590 // ------------------------------
6591 // | |
6592 // | @@@@*********@@@@### |
6593 // | @ * * @ # |
6594 // | @ * * @ # |
6595 // | @ * * @ # |
6596 // | @@@@*********@@@@ # |
6597 // ---------#--------------#-----
6598 // # #
6599 // ################
6600 // The application is still layouted in "#" since it was launched, and it will be visually
6601 // scaled and positioned to "*".
6602
6603 // Calculates the scale and offset to horizontal center the size compatibility bounds into
6604 // the region which is available to application.
6605 final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
6606 final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
6607 final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
6608 final int contentW = resolvedAppBounds.width();
6609 final int contentH = resolvedAppBounds.height();
6610 final int viewportW = parentAppBounds.width();
6611 final int viewportH = parentAppBounds.height();
6612 // Only allow to scale down.
6613 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
6614 ? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
6615 final int screenTopInset = parentAppBounds.top - parentBounds.top;
6616 final boolean topNotAligned = screenTopInset != resolvedAppBounds.top - resolvedBounds.top;
6617 if (mSizeCompatScale != 1f || topNotAligned) {
6618 if (mSizeCompatBounds == null) {
6619 mSizeCompatBounds = new Rect();
6620 }
6621 mSizeCompatBounds.set(resolvedAppBounds);
6622 mSizeCompatBounds.offsetTo(0, 0);
6623 mSizeCompatBounds.scale(mSizeCompatScale);
6624 // The insets are included in height, e.g. the area of real cutout shouldn't be scaled.
6625 mSizeCompatBounds.bottom += screenTopInset;
6626 } else {
6627 mSizeCompatBounds = null;
6628 }
6629
6630 // Center horizontally in parent (app bounds) and align to top of parent (bounds)
6631 // - this is a UX choice.
6632 final int offsetX = getHorizontalCenterOffset(
6633 (int) viewportW, (int) (contentW * mSizeCompatScale));
6634 // Above coordinates are in "@" space, now place "*" and "#" to screen space.
Riddle Hsu89e82062020-04-09 01:57:36 +08006635 final int screenPosX = (fillContainer ? parentBounds.left : parentAppBounds.left) + offsetX;
Riddle Hsue47501b2020-02-18 12:45:41 +08006636 final int screenPosY = parentBounds.top;
Riddle Hsu23e18a92020-03-10 00:26:51 +08006637 if (screenPosX != 0 || screenPosY != 0) {
Riddle Hsue47501b2020-02-18 12:45:41 +08006638 if (mSizeCompatBounds != null) {
6639 mSizeCompatBounds.offset(screenPosX, screenPosY);
6640 }
6641 // Add the global coordinates and remove the local coordinates.
6642 final int dx = screenPosX - resolvedBounds.left;
6643 final int dy = screenPosY - resolvedBounds.top;
6644 offsetBounds(resolvedConfig, dx, dy);
6645 }
6646 }
6647
6648 /** @return The horizontal offset of putting the content in the center of viewport. */
6649 private static int getHorizontalCenterOffset(int viewportW, int contentW) {
6650 return (int) ((viewportW - contentW + 1) * 0.5f);
6651 }
6652
6653 private static void offsetBounds(Configuration inOutConfig, int offsetX, int offsetY) {
6654 inOutConfig.windowConfiguration.getBounds().offset(offsetX, offsetY);
6655 inOutConfig.windowConfiguration.getAppBounds().offset(offsetX, offsetY);
Garfield Tan0443b372019-01-04 15:00:13 -08006656 }
6657
6658 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006659 public Rect getBounds() {
6660 if (mSizeCompatBounds != null) {
6661 return mSizeCompatBounds;
6662 }
6663 return super.getBounds();
6664 }
6665
Garfield Tane8d84ab2019-10-11 09:49:40 -07006666 @VisibleForTesting
lumark19a5d2e2019-10-11 16:19:30 +08006667 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07006668 Rect getAnimationBounds(int appStackClipMode) {
6669 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
6670 // Using the stack bounds here effectively applies the clipping before animation.
6671 return getStack().getBounds();
6672 }
6673 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
6674 // included in the animation.
Louis Changcdec0802019-11-11 11:45:07 +08006675 return task != null ? task.getBounds() : getBounds();
Garfield Tane8d84ab2019-10-11 09:49:40 -07006676 }
6677
Garfield Tane8d84ab2019-10-11 09:49:40 -07006678 @Override
Garfield Tan0443b372019-01-04 15:00:13 -08006679 public void onConfigurationChanged(Configuration newParentConfig) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006680 if (mCompatDisplayInsets != null) {
6681 Configuration overrideConfig = getRequestedOverrideConfiguration();
6682 // Adapt to changes in orientation locking. The app is still non-resizable, but
6683 // it can change which orientation is fixed. If the fixed orientation changes,
6684 // update the rotation used on the "compat" display
6685 boolean wasFixedOrient =
6686 overrideConfig.windowConfiguration.getRotation() != ROTATION_UNDEFINED;
6687 int requestedOrient = getRequestedConfigurationOrientation();
6688 if (requestedOrient != ORIENTATION_UNDEFINED
6689 && requestedOrient != getConfiguration().orientation
6690 // The task orientation depends on the top activity orientation, so it
6691 // should match. If it doesn't, just wait until it does.
6692 && requestedOrient == getParent().getConfiguration().orientation
6693 && (overrideConfig.windowConfiguration.getRotation()
6694 != getParent().getWindowConfiguration().getRotation())) {
6695 overrideConfig.windowConfiguration.setRotation(
6696 getParent().getWindowConfiguration().getRotation());
6697 onRequestedOverrideConfigurationChanged(overrideConfig);
6698 return;
6699 } else if (wasFixedOrient && requestedOrient == ORIENTATION_UNDEFINED
6700 && (overrideConfig.windowConfiguration.getRotation()
6701 != ROTATION_UNDEFINED)) {
6702 overrideConfig.windowConfiguration.setRotation(ROTATION_UNDEFINED);
6703 onRequestedOverrideConfigurationChanged(overrideConfig);
6704 return;
6705 }
6706 }
Garfield Tan0443b372019-01-04 15:00:13 -08006707 super.onConfigurationChanged(newParentConfig);
6708
6709 // Configuration's equality doesn't consider seq so if only seq number changes in resolved
6710 // override configuration. Therefore ConfigurationContainer doesn't change merged override
6711 // configuration, but it's used to push configuration changes so explicitly update that.
6712 if (getMergedOverrideConfiguration().seq != getResolvedOverrideConfiguration().seq) {
6713 onMergedOverrideConfigurationChanged();
6714 }
6715
Louis Chang677921f2019-12-06 16:44:24 +08006716 final DisplayContent display = getDisplay();
Riddle Hsuaec55442019-03-12 17:25:35 +08006717 if (display == null) {
6718 return;
6719 }
Issei Suzuki1669ea42019-11-06 14:20:59 +01006720 if (mVisibleRequested) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006721 // It may toggle the UI for user to restart the size compatibility mode activity.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006722 display.handleActivitySizeCompatModeIfNeeded(this);
Evan Rosky72f084d2019-09-11 17:05:16 -07006723 } else if (mCompatDisplayInsets != null) {
Riddle Hsuaec55442019-03-12 17:25:35 +08006724 // The override changes can only be obtained from display, because we don't have the
6725 // difference of full configuration in each hierarchy.
Riddle Hsu7f704b52019-12-10 23:10:45 +08006726 final int displayChanges = display.getCurrentOverrideConfigurationChanges();
Riddle Hsuaec55442019-03-12 17:25:35 +08006727 final int orientationChanges = CONFIG_WINDOW_CONFIGURATION
6728 | CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION;
6729 final boolean hasNonOrienSizeChanged = hasResizeChange(displayChanges)
6730 // Filter out the case of simple orientation change.
6731 && (displayChanges & orientationChanges) != orientationChanges;
6732 // For background activity that uses size compatibility mode, if the size or density of
6733 // the display is changed, then reset the override configuration and kill the activity's
6734 // process if its process state is not important to user.
6735 if (hasNonOrienSizeChanged || (displayChanges & ActivityInfo.CONFIG_DENSITY) != 0) {
6736 restartProcessIfVisible();
6737 }
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006738 }
Garfield Tan0443b372019-01-04 15:00:13 -08006739 }
6740
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006741 /** Returns true if the configuration is compatible with this activity. */
Wale Ogunwale42f07d92017-05-01 21:32:58 -07006742 boolean isConfigurationCompatible(Configuration config) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006743 final int orientation = getRequestedOrientation();
Wale Ogunwaled4b1d1e2017-04-10 06:35:59 -07006744 if (isFixedOrientationPortrait(orientation)
6745 && config.orientation != ORIENTATION_PORTRAIT) {
6746 return false;
6747 }
6748 if (isFixedOrientationLandscape(orientation)
6749 && config.orientation != ORIENTATION_LANDSCAPE) {
6750 return false;
6751 }
6752 return true;
6753 }
6754
Bryce Lee7566d762017-03-30 09:34:15 -07006755 /**
Shivam Agrawal780b5bb2019-07-17 10:17:11 -07006756 * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
6757 * made to outBounds.
Bryce Lee7566d762017-03-30 09:34:15 -07006758 */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006759 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
Evan Rosky72f084d2019-09-11 17:05:16 -07006760 private void applyAspectRatio(Rect outBounds, Rect containingAppBounds,
6761 Rect containingBounds) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006762 final float maxAspectRatio = info.maxAspectRatio;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08006763 final ActivityStack stack = getRootTask();
Adrian Roos917791e2018-11-28 16:30:44 +01006764 final float minAspectRatio = info.minAspectRatio;
6765
Evan Rosky72f084d2019-09-11 17:05:16 -07006766 if (task == null || stack == null || (inMultiWindowMode() && !shouldUseSizeCompatMode())
Adrian Roos917791e2018-11-28 16:30:44 +01006767 || (maxAspectRatio == 0 && minAspectRatio == 0)
Bryce Leee5ab4502017-07-11 08:58:05 -07006768 || isInVrUiMode(getConfiguration())) {
Evan Rosky72f084d2019-09-11 17:05:16 -07006769 // We don't enforce aspect ratio if the activity task is in multiwindow unless it
6770 // is in size-compat mode. We also don't set it if we are in VR mode.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006771 return;
6772 }
6773
Riddle Hsu74826262019-04-17 14:57:42 +08006774 final int containingAppWidth = containingAppBounds.width();
6775 final int containingAppHeight = containingAppBounds.height();
Adrian Roos917791e2018-11-28 16:30:44 +01006776 final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
6777 / (float) Math.min(containingAppWidth, containingAppHeight);
Bryce Lee7566d762017-03-30 09:34:15 -07006778
Adrian Roos917791e2018-11-28 16:30:44 +01006779 int activityWidth = containingAppWidth;
6780 int activityHeight = containingAppHeight;
6781
6782 if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
6783 if (containingAppWidth < containingAppHeight) {
6784 // Width is the shorter side, so we use that to figure-out what the max. height
6785 // should be given the aspect ratio.
6786 activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
6787 } else {
6788 // Height is the shorter side, so we use that to figure-out what the max. width
6789 // should be given the aspect ratio.
6790 activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
6791 }
Tiger Huang3d2b8982019-01-29 22:56:48 +08006792 } else if (containingRatio < minAspectRatio) {
6793 boolean adjustWidth;
6794 switch (getRequestedConfigurationOrientation()) {
6795 case ORIENTATION_LANDSCAPE:
6796 // Width should be the longer side for this landscape app, so we use the width
6797 // to figure-out what the max. height should be given the aspect ratio.
6798 adjustWidth = false;
6799 break;
6800 case ORIENTATION_PORTRAIT:
6801 // Height should be the longer side for this portrait app, so we use the height
6802 // to figure-out what the max. width should be given the aspect ratio.
6803 adjustWidth = true;
6804 break;
6805 default:
6806 // This app doesn't have a preferred orientation, so we keep the length of the
6807 // longer side, and use it to figure-out the length of the shorter side.
6808 if (containingAppWidth < containingAppHeight) {
6809 // Width is the shorter side, so we use the height to figure-out what the
6810 // max. width should be given the aspect ratio.
6811 adjustWidth = true;
6812 } else {
6813 // Height is the shorter side, so we use the width to figure-out what the
6814 // max. height should be given the aspect ratio.
6815 adjustWidth = false;
6816 }
6817 break;
6818 }
6819 if (adjustWidth) {
Adrian Roos917791e2018-11-28 16:30:44 +01006820 activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
6821 } else {
Adrian Roos917791e2018-11-28 16:30:44 +01006822 activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
6823 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006824 }
6825
Adrian Roos917791e2018-11-28 16:30:44 +01006826 if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006827 // The display matches or is less than the activity aspect ratio, so nothing else to do.
6828 return;
6829 }
6830
6831 // Compute configuration based on max supported width and height.
Adrian Roos24be34d2018-05-28 18:55:38 +02006832 // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
Louis Changcdec0802019-11-11 11:45:07 +08006833 // away later in {@link Task#computeConfigResourceOverrides()}. Otherwise, the app
Adrian Roos24be34d2018-05-28 18:55:38 +02006834 // bounds would end up too small.
Evan Rosky72f084d2019-09-11 17:05:16 -07006835 outBounds.set(containingBounds.left, containingBounds.top,
6836 activityWidth + containingAppBounds.left,
Riddle Hsu74826262019-04-17 14:57:42 +08006837 activityHeight + containingAppBounds.top);
Andrii Kulian3a1619d2017-07-07 14:38:09 -07006838 }
6839
Riddle Hsu16567132018-08-16 21:37:47 +08006840 /**
6841 * @return {@code true} if this activity was reparented to another display but
6842 * {@link #ensureActivityConfiguration} is not called.
6843 */
6844 boolean shouldUpdateConfigForDisplayChanged() {
6845 return mLastReportedDisplayId != getDisplayId();
6846 }
6847
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006848 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
6849 return ensureActivityConfiguration(globalChanges, preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006850 false /* ignoreVisibility */);
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006851 }
6852
Andrii Kulian21713ac2016-10-12 22:05:05 -07006853 /**
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006854 * Make sure the given activity matches the current configuration. Ensures the HistoryRecord
6855 * is updated with the correct configuration and all other bookkeeping is handled.
6856 *
6857 * @param globalChanges The changes to the global configuration.
6858 * @param preserveWindow If the activity window should be preserved on screen if the activity
6859 * is relaunched.
Riddle Hsu609a8e22019-06-27 16:46:29 -06006860 * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
6861 * (stopped state). This is useful for the case where we know the
6862 * activity will be visible soon and we want to ensure its configuration
6863 * before we make it visible.
Riddle Hsu7b766fd2019-01-28 21:14:59 +08006864 * @return False if the activity was relaunched and true if it wasn't relaunched because we
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006865 * can't or the app handles the specific configuration that is changing.
Andrii Kulian21713ac2016-10-12 22:05:05 -07006866 */
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -08006867 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006868 boolean ignoreVisibility) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08006869 final ActivityStack stack = getRootTask();
Andrii Kulian21713ac2016-10-12 22:05:05 -07006870 if (stack.mConfigWillChange) {
6871 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6872 "Skipping config check (will change): " + this);
6873 return true;
6874 }
6875
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006876 // We don't worry about activities that are finishing.
6877 if (finishing) {
6878 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6879 "Configuration doesn't matter in finishing " + this);
6880 stopFreezingScreenLocked(false);
6881 return true;
6882 }
6883
Riddle Hsu609a8e22019-06-27 16:46:29 -06006884 if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006885 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Riddle Hsu609a8e22019-06-27 16:46:29 -06006886 "Skipping config check invisible: " + this);
Wale Ogunwale9b7a8272017-04-10 08:05:41 -07006887 return true;
6888 }
6889
Andrii Kulian21713ac2016-10-12 22:05:05 -07006890 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6891 "Ensuring correct configuration: " + this);
6892
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006893 final int newDisplayId = getDisplayId();
6894 final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
6895 if (displayChanged) {
6896 mLastReportedDisplayId = newDisplayId;
6897 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006898 // TODO(b/36505427): Is there a better place to do this?
Evan Rosky72f084d2019-09-11 17:05:16 -07006899 updateSizeCompatMode();
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006900
Winson Chungbdc646f2017-02-13 12:12:22 -08006901 // Short circuit: if the two full configurations are equal (the common case), then there is
6902 // nothing to do. We test the full configuration instead of the global and merged override
6903 // configurations because there are cases (like moving a task to the pinned stack) where
6904 // the combine configurations are equal, but would otherwise differ in the override config
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006905 mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
6906 if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006907 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006908 "Configuration & display unchanged in " + this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006909 return true;
6910 }
6911
6912 // Okay we now are going to make this activity have the new config.
6913 // But then we need to figure out how it needs to deal with that.
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006914
6915 // Find changes between last reported merged configuration and the current one. This is used
6916 // to decide whether to relaunch an activity or just report a configuration change.
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006917 final int changes = getConfigurationChanges(mTmpConfig);
Ruben Brunkf64af332017-03-22 22:03:25 -07006918
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006919 // Update last reported values.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006920 final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
Bryce Lee8104e7a2017-08-17 09:16:03 -07006921
Andrii Kulianfa23a9e2019-10-10 15:15:36 -07006922 setLastReportedConfiguration(getProcessGlobalConfiguration(), newMergedOverrideConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006923
Bryce Lee7ace3952018-02-16 14:34:32 -08006924 if (mState == INITIALIZING) {
Andrii Kulianb372da62018-01-18 10:46:24 -08006925 // No need to relaunch or schedule new config for activity that hasn't been launched
6926 // yet. We do, however, return after applying the config to activity record, so that
6927 // it will use it for launch transaction.
6928 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6929 "Skipping config check for initializing activity: " + this);
6930 return true;
6931 }
6932
Andrii Kulian21713ac2016-10-12 22:05:05 -07006933 if (changes == 0 && !forceNewConfig) {
6934 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6935 "Configuration no differences in " + this);
6936 // There are no significant differences, so we won't relaunch but should still deliver
6937 // the new configuration to the client process.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006938 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006939 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006940 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07006941 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08006942 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07006943 return true;
6944 }
6945
6946 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
Andrii Kulianb43be0a2017-03-02 17:29:40 -08006947 "Configuration changes for " + this + ", allChanges="
Andrii Kulian21713ac2016-10-12 22:05:05 -07006948 + Configuration.configurationDiffToString(changes));
6949
6950 // If the activity isn't currently running, just leave the new configuration and it will
6951 // pick that up next time it starts.
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006952 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006953 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6954 "Configuration doesn't matter not running " + this);
6955 stopFreezingScreenLocked(false);
6956 forceNewConfig = false;
6957 return true;
6958 }
6959
6960 // Figure out how to handle the changes between the configurations.
6961 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6962 "Checking to restart " + info.name + ": changed=0x"
6963 + Integer.toHexString(changes) + ", handles=0x"
6964 + Integer.toHexString(info.getRealConfigChanged())
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006965 + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006966
Wale Ogunwalee610d3d2017-04-25 10:23:48 -07006967 if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006968 // Aha, the activity isn't handling the change, so DIE DIE DIE.
6969 configChangeFlags |= changes;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08006970 startFreezingScreenLocked(globalChanges);
Andrii Kulian21713ac2016-10-12 22:05:05 -07006971 forceNewConfig = false;
6972 preserveWindow &= isResizeOnlyChange(changes);
Garfield Tan2746ab52018-07-25 12:33:01 -07006973 final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
6974 if (hasResizeChange) {
Louis Changcdec0802019-11-11 11:45:07 +08006975 final boolean isDragResizing = task.isDragResizing();
Garfield Tan2746ab52018-07-25 12:33:01 -07006976 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
6977 : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
6978 } else {
6979 mRelaunchReason = RELAUNCH_REASON_NONE;
6980 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07006981 if (!attachedToProcess()) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006982 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6983 "Config is destroying non-running " + this);
Andrii Kulian79d67982019-08-19 11:56:16 -07006984 destroyImmediately(true /* removeFromApp */, "config");
Bryce Lee7ace3952018-02-16 14:34:32 -08006985 } else if (mState == PAUSING) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07006986 // A little annoying: we are waiting for this activity to finish pausing. Let's not
6987 // do anything now, but just flag that it needs to be restarted when done pausing.
6988 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6989 "Config is skipping already pausing " + this);
6990 deferRelaunchUntilPaused = true;
6991 preserveWindowOnDeferredRelaunch = preserveWindow;
6992 return true;
Andrii Kulian21713ac2016-10-12 22:05:05 -07006993 } else {
6994 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006995 "Config is relaunching " + this);
Issei Suzuki1669ea42019-11-06 14:20:59 +01006996 if (DEBUG_STATES && !mVisibleRequested) {
wilsonshihb5d8f8b2019-10-23 13:01:40 +08006997 Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
6998 + " called by " + Debug.getCallers(4));
6999 }
7000 relaunchActivityLocked(preserveWindow);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007001 }
7002
7003 // All done... tell the caller we weren't able to keep this activity around.
7004 return false;
7005 }
7006
7007 // Default case: the activity can handle this new configuration, so hand it over.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007008 // NOTE: We only forward the override configuration as the system level configuration
Andrii Kulian21713ac2016-10-12 22:05:05 -07007009 // changes is always sent to all processes when they happen so it can just use whatever
7010 // system level configuration it last got.
Andrii Kulianb047b8b2017-02-08 18:38:26 -08007011 if (displayChanged) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007012 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08007013 } else {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007014 scheduleConfigurationChanged(newMergedOverrideConfig);
Andrii Kulianb047b8b2017-02-08 18:38:26 -08007015 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07007016 stopFreezingScreenLocked(false);
7017
7018 return true;
7019 }
7020
Andrii Kulianfa23a9e2019-10-10 15:15:36 -07007021 /** Get process configuration, or global config if the process is not set. */
7022 private Configuration getProcessGlobalConfiguration() {
7023 return app != null ? app.getConfiguration() : mAtmService.getGlobalConfiguration();
7024 }
7025
Zak Cohen90e7116742017-01-29 12:59:23 -08007026 /**
7027 * When assessing a configuration change, decide if the changes flags and the new configurations
7028 * should cause the Activity to relaunch.
Ruben Brunkf64af332017-03-22 22:03:25 -07007029 *
7030 * @param changes the changes due to the given configuration.
7031 * @param changesConfig the configuration that was used to calculate the given changes via a
7032 * call to getConfigurationChanges.
Zak Cohen90e7116742017-01-29 12:59:23 -08007033 */
Ruben Brunkf64af332017-03-22 22:03:25 -07007034 private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
Zak Cohen90e7116742017-01-29 12:59:23 -08007035 int configChanged = info.getRealConfigChanged();
Ruben Brunkf64af332017-03-22 22:03:25 -07007036 boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
Zak Cohen90e7116742017-01-29 12:59:23 -08007037
7038 // Override for apps targeting pre-O sdks
7039 // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
7040 // to the config change.
7041 // For O and later, apps will be required to add configChanges="uimode" to their manifest.
Andrii Kulianeceebbf2019-06-26 17:36:51 -07007042 if (info.applicationInfo.targetSdkVersion < O
Zak Cohen90e7116742017-01-29 12:59:23 -08007043 && requestedVrComponent != null
Ruben Brunkf64af332017-03-22 22:03:25 -07007044 && onlyVrUiModeChanged) {
Zak Cohen90e7116742017-01-29 12:59:23 -08007045 configChanged |= CONFIG_UI_MODE;
7046 }
7047
7048 return (changes&(~configChanged)) != 0;
7049 }
7050
Ruben Brunkf64af332017-03-22 22:03:25 -07007051 /**
7052 * Returns true if the configuration change is solely due to the UI mode switching into or out
7053 * of UI_MODE_TYPE_VR_HEADSET.
7054 */
7055 private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
7056 final Configuration currentConfig = getConfiguration();
Ruben Brunkf53497c2017-03-27 20:26:17 -07007057 return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
Ruben Brunkf64af332017-03-22 22:03:25 -07007058 != isInVrUiMode(lastReportedConfig));
7059 }
7060
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007061 private int getConfigurationChanges(Configuration lastReportedConfig) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07007062 // Determine what has changed. May be nothing, if this is a config that has come back from
7063 // the app after going idle. In that case we just want to leave the official config object
7064 // now in the activity and do nothing else.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007065 final Configuration currentConfig = getConfiguration();
7066 int changes = lastReportedConfig.diff(currentConfig);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007067 // We don't want to use size changes if they don't cross boundaries that are important to
7068 // the app.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007069 if ((changes & CONFIG_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08007070 final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
7071 currentConfig.screenWidthDp)
7072 || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
7073 currentConfig.screenHeightDp);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007074 if (!crosses) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007075 changes &= ~CONFIG_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07007076 }
7077 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007078 if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
Andrii Kulianb43be0a2017-03-02 17:29:40 -08007079 final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
7080 final int newSmallest = currentConfig.smallestScreenWidthDp;
7081 if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007082 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
Andrii Kulian21713ac2016-10-12 22:05:05 -07007083 }
7084 }
Wale Ogunwale822e5122017-07-26 06:02:24 -07007085 // We don't want window configuration to cause relaunches.
7086 if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
7087 changes &= ~CONFIG_WINDOW_CONFIGURATION;
7088 }
Bryce Lee600dadd2017-07-25 10:48:42 -07007089
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07007090 return changes;
Andrii Kulian21713ac2016-10-12 22:05:05 -07007091 }
7092
7093 private static boolean isResizeOnlyChange(int change) {
7094 return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
7095 | CONFIG_SCREEN_LAYOUT)) == 0;
7096 }
7097
Garfield Tan2746ab52018-07-25 12:33:01 -07007098 private static boolean hasResizeChange(int change) {
7099 return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
7100 | CONFIG_SCREEN_LAYOUT)) != 0;
7101 }
7102
wilsonshihb5d8f8b2019-10-23 13:01:40 +08007103 void relaunchActivityLocked(boolean preserveWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007104 if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07007105 configChangeFlags = 0;
7106 return;
7107 }
7108
wilsonshihb5d8f8b2019-10-23 13:01:40 +08007109 final boolean andResume = shouldBeResumed(null /*activeActivity*/);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007110 List<ResultInfo> pendingResults = null;
7111 List<ReferrerIntent> pendingNewIntents = null;
7112 if (andResume) {
7113 pendingResults = results;
7114 pendingNewIntents = newIntents;
7115 }
7116 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
7117 "Relaunching: " + this + " with results=" + pendingResults
7118 + " newIntents=" + pendingNewIntents + " andResume=" + andResume
7119 + " preserveWindow=" + preserveWindow);
Jeff Changd136e772019-11-05 20:33:52 +08007120 if (andResume) {
7121 EventLogTags.writeWmRelaunchResumeActivity(mUserId, System.identityHashCode(this),
7122 task.mTaskId, shortComponentName);
7123 } else {
7124 EventLogTags.writeWmRelaunchActivity(mUserId, System.identityHashCode(this),
7125 task.mTaskId, shortComponentName);
7126 }
Andrii Kulian21713ac2016-10-12 22:05:05 -07007127
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007128 startFreezingScreenLocked(0);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007129
Andrii Kulian21713ac2016-10-12 22:05:05 -07007130 try {
7131 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
7132 "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
7133 + " callers=" + Debug.getCallers(6));
7134 forceNewConfig = false;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007135 startRelaunching();
Andrii Kulianb372da62018-01-18 10:46:24 -08007136 final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
7137 pendingNewIntents, configChangeFlags,
Andrii Kulianfa23a9e2019-10-10 15:15:36 -07007138 new MergedConfiguration(getProcessGlobalConfiguration(),
Andrii Kulianb372da62018-01-18 10:46:24 -08007139 getMergedOverrideConfiguration()),
7140 preserveWindow);
7141 final ActivityLifecycleItem lifecycleItem;
7142 if (andResume) {
lumark588a3e82018-07-20 18:53:54 +08007143 lifecycleItem = ResumeActivityItem.obtain(
Wale Ogunwale3a256e62018-12-06 14:41:18 -08007144 getDisplay().mDisplayContent.isNextTransitionForward());
Andrii Kulianb372da62018-01-18 10:46:24 -08007145 } else {
Bryce Lee1d0d5142018-04-12 10:35:07 -07007146 lifecycleItem = PauseActivityItem.obtain();
Andrii Kulianb372da62018-01-18 10:46:24 -08007147 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007148 final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
Andrii Kulianb372da62018-01-18 10:46:24 -08007149 transaction.addCallback(callbackItem);
7150 transaction.setLifecycleStateRequest(lifecycleItem);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007151 mAtmService.getLifecycleManager().scheduleTransaction(transaction);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007152 // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
Andrii Kulianb372da62018-01-18 10:46:24 -08007153 // request resume if this activity is currently resumed, which implies we aren't
Andrii Kulian21713ac2016-10-12 22:05:05 -07007154 // sleeping.
7155 } catch (RemoteException e) {
7156 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
7157 }
7158
7159 if (andResume) {
7160 if (DEBUG_STATES) {
7161 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
7162 }
7163 results = null;
7164 newIntents = null;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007165 mAtmService.getAppWarningsLocked().onResumeActivity(this);
Andrii Kulian21713ac2016-10-12 22:05:05 -07007166 } else {
Wale Ogunwale196db712019-12-27 15:35:39 +00007167 removePauseTimeout();
Bryce Lee7ace3952018-02-16 14:34:32 -08007168 setState(PAUSED, "relaunchActivityLocked");
Andrii Kulian21713ac2016-10-12 22:05:05 -07007169 }
7170
7171 configChangeFlags = 0;
7172 deferRelaunchUntilPaused = false;
7173 preserveWindowOnDeferredRelaunch = false;
7174 }
7175
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007176 /**
7177 * Request the process of the activity to restart with its saved state (from
7178 * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
7179 * the override configuration. Note if the activity is in background, the process will be killed
7180 * directly with keeping its record.
7181 */
7182 void restartProcessIfVisible() {
7183 Slog.i(TAG, "Request to restart process of " + this);
7184
Riddle Hsuaec55442019-03-12 17:25:35 +08007185 // Reset the existing override configuration so it can be updated according to the latest
7186 // configuration.
Evan Rosky72f084d2019-09-11 17:05:16 -07007187 clearSizeCompatMode();
Issei Suzuki1669ea42019-11-06 14:20:59 +01007188 if (mVisibleRequested) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007189 // Configuration will be ensured when becoming visible, so if it is already visible,
7190 // then the manual update is needed.
Evan Rosky72f084d2019-09-11 17:05:16 -07007191 updateSizeCompatMode();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007192 }
7193
7194 if (!attachedToProcess()) {
7195 return;
7196 }
7197
7198 // The restarting state avoids removing this record when process is died.
7199 setState(RESTARTING_PROCESS, "restartActivityProcess");
7200
Issei Suzuki1669ea42019-11-06 14:20:59 +01007201 if (!mVisibleRequested || mHaveState) {
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007202 // Kill its process immediately because the activity should be in background.
7203 // The activity state will be update to {@link #DESTROYED} in
Andrii Kulian79d67982019-08-19 11:56:16 -07007204 // {@link ActivityStack#cleanUp} when handling process died.
Riddle Hsuaec55442019-03-12 17:25:35 +08007205 mAtmService.mH.post(() -> {
7206 final WindowProcessController wpc;
7207 synchronized (mAtmService.mGlobalLock) {
7208 if (!hasProcess()
7209 || app.getReportedProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
7210 return;
7211 }
7212 wpc = app;
7213 }
7214 mAtmService.mAmInternal.killProcess(wpc.mName, wpc.mUid, "resetConfig");
7215 });
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007216 return;
7217 }
7218
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007219 if (getParent() != null) {
7220 startFreezingScreen();
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007221 }
7222 // The process will be killed until the activity reports stopped with saved state (see
7223 // {@link ActivityTaskManagerService.activityStopped}).
7224 try {
7225 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
Andrii Kulianb9faa032019-10-17 23:11:54 -07007226 StopActivityItem.obtain(0 /* configChanges */));
Riddle Hsu7b766fd2019-01-28 21:14:59 +08007227 } catch (RemoteException e) {
7228 Slog.w(TAG, "Exception thrown during restart " + this, e);
7229 }
7230 mStackSupervisor.scheduleRestartTimeout(this);
7231 }
7232
Riddle Hsu32dbdca2019-05-17 23:10:16 -06007233 boolean isProcessRunning() {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007234 WindowProcessController proc = app;
Jorim Jaggi02886a82016-12-06 09:10:06 -08007235 if (proc == null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007236 proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
Jorim Jaggi02886a82016-12-06 09:10:06 -08007237 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007238 return proc != null && proc.hasThread();
Jorim Jaggi02886a82016-12-06 09:10:06 -08007239 }
7240
Jorim Jaggibae01b12017-04-11 16:29:10 -07007241 /**
7242 * @return Whether a task snapshot starting window may be shown.
7243 */
7244 private boolean allowTaskSnapshot() {
7245 if (newIntents == null) {
7246 return true;
7247 }
7248
Louis Chang746c2242019-10-08 16:30:44 +08007249 // Restrict task snapshot starting window to launcher start, or is same as the last
7250 // delivered intent, or there is no intent at all (eg. task being brought to front). If
7251 // the intent is something else, likely the app is going to show some specific page or
7252 // view, instead of what's left last time.
Jorim Jaggibae01b12017-04-11 16:29:10 -07007253 for (int i = newIntents.size() - 1; i >= 0; i--) {
7254 final Intent intent = newIntents.get(i);
Louis Chang746c2242019-10-08 16:30:44 +08007255 if (intent == null || ActivityRecord.isMainIntent(intent)) {
7256 continue;
7257 }
7258
7259 final boolean sameIntent = mLastNewIntent != null ? mLastNewIntent.filterEquals(intent)
7260 : this.intent.filterEquals(intent);
7261 if (!sameIntent || intent.getExtras() != null) {
Jorim Jaggibae01b12017-04-11 16:29:10 -07007262 return false;
7263 }
7264 }
7265 return true;
7266 }
7267
Bryce Leeb7c9b802017-05-02 14:20:24 -07007268 /**
7269 * Returns {@code true} if the associated activity has the no history flag set on it.
7270 * {@code false} otherwise.
7271 */
7272 boolean isNoHistory() {
7273 return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
7274 || (info.flags & FLAG_NO_HISTORY) != 0;
7275 }
7276
Craig Mautner21d24a22014-04-23 11:45:37 -07007277 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
7278 out.attribute(null, ATTR_ID, String.valueOf(createTime));
7279 out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
7280 if (launchedFromPackage != null) {
7281 out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
7282 }
Philip P. Moltmannee295092020-02-10 08:46:26 -08007283 if (launchedFromFeatureId != null) {
7284 out.attribute(null, ATTR_LAUNCHEDFROMFEATURE, launchedFromFeatureId);
7285 }
Craig Mautner21d24a22014-04-23 11:45:37 -07007286 if (resolvedType != null) {
7287 out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
7288 }
7289 out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007290 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
Winson Chung2cb86c72014-06-25 12:03:30 -07007291
Craig Mautner21d24a22014-04-23 11:45:37 -07007292 if (taskDescription != null) {
Craig Mautner648f69b2014-09-18 14:16:26 -07007293 taskDescription.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007294 }
7295
7296 out.startTag(null, TAG_INTENT);
7297 intent.saveToXml(out);
7298 out.endTag(null, TAG_INTENT);
7299
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007300 if (isPersistable() && mPersistentState != null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007301 out.startTag(null, TAG_PERSISTABLEBUNDLE);
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007302 mPersistentState.saveToXml(out);
Craig Mautner21d24a22014-04-23 11:45:37 -07007303 out.endTag(null, TAG_PERSISTABLEBUNDLE);
7304 }
7305 }
7306
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07007307 static ActivityRecord restoreFromXml(XmlPullParser in,
7308 ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
Craig Mautner21d24a22014-04-23 11:45:37 -07007309 Intent intent = null;
7310 PersistableBundle persistentState = null;
7311 int launchedFromUid = 0;
7312 String launchedFromPackage = null;
Philip P. Moltmannee295092020-02-10 08:46:26 -08007313 String launchedFromFeature = null;
Craig Mautner21d24a22014-04-23 11:45:37 -07007314 String resolvedType = null;
7315 boolean componentSpecified = false;
7316 int userId = 0;
Craig Mautner21d24a22014-04-23 11:45:37 -07007317 long createTime = -1;
7318 final int outerDepth = in.getDepth();
Winson Chung2cb86c72014-06-25 12:03:30 -07007319 TaskDescription taskDescription = new TaskDescription();
Craig Mautner21d24a22014-04-23 11:45:37 -07007320
7321 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
7322 final String attrName = in.getAttributeName(attrNdx);
7323 final String attrValue = in.getAttributeValue(attrNdx);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007324 if (DEBUG) Slog.d(TaskPersister.TAG,
Wale Ogunwale18795a22014-12-03 11:38:33 -08007325 "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007326 if (ATTR_ID.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01007327 createTime = Long.parseLong(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007328 } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007329 launchedFromUid = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007330 } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
7331 launchedFromPackage = attrValue;
Philip P. Moltmannee295092020-02-10 08:46:26 -08007332 } else if (ATTR_LAUNCHEDFROMFEATURE.equals(attrName)) {
7333 launchedFromFeature = attrValue;
Craig Mautner21d24a22014-04-23 11:45:37 -07007334 } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
7335 resolvedType = attrValue;
7336 } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
Tobias Thiererb0800dc2016-04-21 17:51:41 +01007337 componentSpecified = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07007338 } else if (ATTR_USERID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01007339 userId = Integer.parseInt(attrValue);
Winson Chungd6722032020-02-18 15:16:08 -08007340 } else if (!attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007341 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
7342 }
7343 }
Winson Chungd6722032020-02-18 15:16:08 -08007344 taskDescription.restoreFromXml(in);
Craig Mautner21d24a22014-04-23 11:45:37 -07007345
7346 int event;
Ruben Brunkf53497c2017-03-27 20:26:17 -07007347 while (((event = in.next()) != END_DOCUMENT) &&
7348 (event != END_TAG || in.getDepth() >= outerDepth)) {
7349 if (event == START_TAG) {
Craig Mautner21d24a22014-04-23 11:45:37 -07007350 final String name = in.getName();
Ruben Brunkf53497c2017-03-27 20:26:17 -07007351 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007352 Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
Craig Mautner21d24a22014-04-23 11:45:37 -07007353 if (TAG_INTENT.equals(name)) {
7354 intent = Intent.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007355 if (DEBUG)
Wale Ogunwale18795a22014-12-03 11:38:33 -08007356 Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007357 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
7358 persistentState = PersistableBundle.restoreFromXml(in);
Ruben Brunkf53497c2017-03-27 20:26:17 -07007359 if (DEBUG) Slog.d(TaskPersister.TAG,
Craig Mautner21d24a22014-04-23 11:45:37 -07007360 "ActivityRecord: persistentState=" + persistentState);
7361 } else {
7362 Slog.w(TAG, "restoreActivity: unexpected name=" + name);
7363 XmlUtils.skipCurrentTag(in);
7364 }
7365 }
7366 }
7367
7368 if (intent == null) {
Craig Mautnere0129b32014-05-25 16:41:09 -07007369 throw new XmlPullParserException("restoreActivity error intent=" + intent);
Craig Mautner21d24a22014-04-23 11:45:37 -07007370 }
7371
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007372 final ActivityTaskManagerService service = stackSupervisor.mService;
Craig Mautner21d24a22014-04-23 11:45:37 -07007373 final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
Patrick Baumann78380272018-04-04 10:41:01 -07007374 userId, Binder.getCallingUid());
Craig Mautnere0129b32014-05-25 16:41:09 -07007375 if (aInfo == null) {
Craig Mautner77b04262014-06-27 15:22:12 -07007376 throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
7377 " resolvedType=" + resolvedType);
Craig Mautnere0129b32014-05-25 16:41:09 -07007378 }
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07007379 final ActivityRecord r = new ActivityRecord(service, null /* caller */,
Philip P. Moltmannee295092020-02-10 08:46:26 -08007380 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, launchedFromFeature,
7381 intent, resolvedType, aInfo, service.getConfiguration(), null /* resultTo */,
7382 null /* resultWho */, 0 /* reqCode */, componentSpecified,
7383 false /* rootVoiceInteraction */, stackSupervisor, null /* options */,
7384 null /* sourceRecord */);
Craig Mautner21d24a22014-04-23 11:45:37 -07007385
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07007386 r.mPersistentState = persistentState;
Winson Chung2cb86c72014-06-25 12:03:30 -07007387 r.taskDescription = taskDescription;
Craig Mautner21d24a22014-04-23 11:45:37 -07007388 r.createTime = createTime;
7389
7390 return r;
7391 }
7392
Zak Cohen90e7116742017-01-29 12:59:23 -08007393 private static boolean isInVrUiMode(Configuration config) {
Ruben Brunkf53497c2017-03-27 20:26:17 -07007394 return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
Zak Cohen90e7116742017-01-29 12:59:23 -08007395 }
7396
David Stevens82ea6cb2017-03-03 16:18:50 -08007397 int getUid() {
7398 return info.applicationInfo.uid;
7399 }
7400
Wale Ogunwalea38654f2019-11-17 20:37:15 -08007401 boolean isUid(int uid) {
7402 return info.applicationInfo.uid == uid;
7403 }
7404
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007405 int getPid() {
7406 return app != null ? app.getPid() : 0;
chaviw59b98852017-06-13 12:05:44 -07007407 }
7408
7409 /**
7410 * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
Garfield Tane8d84ab2019-10-11 09:49:40 -07007411 * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007412 * should be visible depending on Keyguard state
chaviw59b98852017-06-13 12:05:44 -07007413 *
7414 * @return true if the screen can be turned on, false otherwise.
7415 */
7416 boolean canTurnScreenOn() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007417 if (!getTurnScreenOnFlag()) {
7418 return false;
7419 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08007420 final ActivityStack stack = getRootTask();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007421 return stack != null &&
Louis Changd73abe22020-04-09 13:15:34 +08007422 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */,
7423 stack.topRunningActivity() == this /* isTop */);
chaviw59b98852017-06-13 12:05:44 -07007424 }
7425
Garfield Tane8d84ab2019-10-11 09:49:40 -07007426 void setTurnScreenOn(boolean turnScreenOn) {
7427 mTurnScreenOn = turnScreenOn;
7428 }
7429
7430 boolean getTurnScreenOnFlag() {
Andrii Kulian46799182019-10-17 16:26:17 -07007431 return mTurnScreenOn || containsTurnScreenOnWindow();
7432 }
7433
7434 private boolean containsTurnScreenOnWindow() {
7435 // When we are relaunching, it is possible for us to be unfrozen before our previous
7436 // windows have been added back. Using the cached value ensures that our previous
7437 // showWhenLocked preference is honored until relaunching is complete.
7438 if (isRelaunching()) {
7439 return mLastContainsTurnScreenOnWindow;
7440 }
7441 for (int i = mChildren.size() - 1; i >= 0; i--) {
7442 if ((mChildren.get(i).mAttrs.flags & LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
7443 return true;
7444 }
7445 }
7446 return false;
Garfield Tane8d84ab2019-10-11 09:49:40 -07007447 }
7448
Louis Chang77ce34d2019-01-03 15:45:12 +08007449 /**
7450 * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
7451 * process are allowed to be resumed.
7452 *
7453 * @return true if this activity can be resumed.
7454 */
7455 boolean canResumeByCompat() {
7456 return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
7457 }
7458
chaviw59b98852017-06-13 12:05:44 -07007459 boolean isTopRunningActivity() {
Louis Chang149d5c82019-12-30 09:47:39 +08007460 return mRootWindowContainer.topRunningActivity() == this;
chaviw59b98852017-06-13 12:05:44 -07007461 }
7462
Andrii Kulian52d255c2018-07-13 11:32:19 -07007463 /**
7464 * @return {@code true} if this is the resumed activity on its current display, {@code false}
7465 * otherwise.
7466 */
7467 boolean isResumedActivityOnDisplay() {
Louis Chang677921f2019-12-06 16:44:24 +08007468 final DisplayContent display = getDisplay();
Andrii Kulianf9df4a82020-03-31 12:09:27 -07007469 if (display == null) {
7470 return false;
7471 }
7472 for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
7473 final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
7474 final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity();
7475 if (resumedActivity != null) {
7476 return resumedActivity == this;
7477 }
7478 }
7479 return false;
Andrii Kulian52d255c2018-07-13 11:32:19 -07007480 }
7481
Andrii Kulian39f27442019-06-26 19:09:19 -07007482
7483 /**
7484 * Check if this is the root of the task - first activity that is not finishing, starting from
7485 * the bottom of the task. If all activities are finishing - then this method will return
7486 * {@code true} if the activity is at the bottom.
7487 *
7488 * NOTE: This is different from 'effective root' - an activity that defines the task identity.
7489 */
7490 boolean isRootOfTask() {
7491 if (task == null) {
7492 return false;
7493 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08007494 final ActivityRecord rootActivity = task.getRootActivity(true);
7495 return this == rootActivity;
Andrii Kulian39f27442019-06-26 19:09:19 -07007496 }
7497
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08007498 void setTaskOverlay(boolean taskOverlay) {
7499 mTaskOverlay = taskOverlay;
7500 setAlwaysOnTop(mTaskOverlay);
7501 }
7502
7503 boolean isTaskOverlay() {
7504 return mTaskOverlay;
7505 }
7506
Craig Mautnerf81b90872013-02-26 13:02:43 -08007507 @Override
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08007508 boolean showToCurrentUser() {
7509 return mShowForAllUsers || mWmService.isCurrentProfile(mUserId);
7510 }
7511
7512 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007514 if (stringName != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07007515 return stringName + " t" + (task == null ? INVALID_TASK_ID : task.mTaskId) +
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007516 (finishing ? " f}" : "") + (mIsExiting ? " mIsExiting=" : "") + "}";
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007517 }
7518 StringBuilder sb = new StringBuilder(128);
Dianne Hackborn30d71892010-12-11 10:37:55 -08007519 sb.append("ActivityRecord{");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007520 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornb12e1352012-09-26 11:39:20 -07007521 sb.append(" u");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08007522 sb.append(mUserId);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007523 sb.append(' ');
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007524 sb.append(intent.getComponent().flattenToShortString());
Craig Mautnerf81b90872013-02-26 13:02:43 -08007525 stringName = sb.toString();
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08007526 return stringName;
Steven Timotius4346f0a2017-09-12 11:07:21 -07007527 }
7528
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007529 /**
7530 * Write all fields to an {@code ActivityRecordProto}. This assumes the
7531 * {@code ActivityRecordProto} is the outer-most proto data.
7532 */
Wale Ogunwalef342f062020-01-27 07:34:13 -08007533 void dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
Jeff Changacc340d2019-11-22 14:23:08 +08007534 writeNameToProto(proto, NAME);
Wale Ogunwalef342f062020-01-27 07:34:13 -08007535 super.dumpDebug(proto, WINDOW_TOKEN, logLevel);
Jeff Changacc340d2019-11-22 14:23:08 +08007536 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
7537 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
Wale Ogunwalef342f062020-01-27 07:34:13 -08007538 proto.write(IS_ANIMATING, isAnimating(PARENTS));
7539 if (mThumbnail != null){
Jeff Changacc340d2019-11-22 14:23:08 +08007540 mThumbnail.dumpDebug(proto, THUMBNAIL);
7541 }
7542 proto.write(FILLS_PARENT, mOccludesParent);
7543 proto.write(APP_STOPPED, mAppStopped);
Wale Ogunwalef342f062020-01-27 07:34:13 -08007544 proto.write(TRANSLUCENT, !occludesParent());
7545 proto.write(VISIBLE, mVisible);
Jeff Changacc340d2019-11-22 14:23:08 +08007546 proto.write(VISIBLE_REQUESTED, mVisibleRequested);
7547 proto.write(CLIENT_VISIBLE, mClientVisible);
7548 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
7549 proto.write(REPORTED_DRAWN, reportedDrawn);
7550 proto.write(REPORTED_VISIBLE, reportedVisible);
7551 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
7552 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
7553 proto.write(ALL_DRAWN, allDrawn);
7554 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
7555 if (startingWindow != null) {
7556 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
7557 }
7558 proto.write(STARTING_DISPLAYED, startingDisplayed);
7559 proto.write(STARTING_MOVED, startingMoved);
7560 proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW,
7561 mVisibleSetFromTransferredStartingWindow);
7562 for (Rect bounds : mFrozenBounds) {
7563 bounds.dumpDebug(proto, FROZEN_BOUNDS);
7564 }
7565
Steven Timotius4346f0a2017-09-12 11:07:21 -07007566 writeIdentifierToProto(proto, IDENTIFIER);
Bryce Lee7ace3952018-02-16 14:34:32 -08007567 proto.write(STATE, mState.toString());
Andrii Kulian39f27442019-06-26 19:09:19 -07007568 proto.write(FRONT_OF_TASK, isRootOfTask());
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07007569 if (hasProcess()) {
7570 proto.write(PROC_ID, app.getPid());
Steven Timotius4346f0a2017-09-12 11:07:21 -07007571 }
Igor Murashkinc0b47e42018-11-07 15:54:18 -08007572 }
7573
Garfield Tane8d84ab2019-10-11 09:49:40 -07007574 @Override
Vishnu Nairdddc9f52020-03-09 09:37:27 -07007575 long getProtoFieldId() {
7576 return ACTIVITY;
7577 }
7578
7579 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08007580 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Garfield Tane8d84ab2019-10-11 09:49:40 -07007581 @WindowTraceLogLevel int logLevel) {
7582 // Critical log level logs only visible elements to mitigate performance overheard
7583 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
7584 return;
7585 }
7586
7587 final long token = proto.start(fieldId);
Wale Ogunwalef342f062020-01-27 07:34:13 -08007588 dumpDebug(proto, logLevel);
Garfield Tane8d84ab2019-10-11 09:49:40 -07007589 proto.end(token);
7590 }
7591
7592 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
7593 if (appToken != null) {
7594 proto.write(fieldId, appToken.getName());
7595 }
7596 }
7597
Evan Rosky55bddd82020-01-29 13:07:18 -08007598 @Override
Garfield Tane8d84ab2019-10-11 09:49:40 -07007599 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
7600 final long token = proto.start(fieldId);
7601 proto.write(HASH_CODE, System.identityHashCode(this));
7602 proto.write(USER_ID, mUserId);
7603 proto.write(TITLE, intent.getComponent().flattenToShortString());
7604 proto.end(token);
7605 }
7606
7607 /**
Riddle Hsu61987bc2019-04-03 13:08:47 +08007608 * The precomputed insets of the display in each rotation. This is used to make the size
7609 * compatibility mode activity compute the configuration without relying on its current display.
Riddle Hsue47501b2020-02-18 12:45:41 +08007610 * This currently only supports fullscreen and freeform windowing mode.
Riddle Hsu61987bc2019-04-03 13:08:47 +08007611 */
7612 static class CompatDisplayInsets {
Evan Rosky72f084d2019-09-11 17:05:16 -07007613 private final int mWidth;
7614 private final int mHeight;
Riddle Hsue47501b2020-02-18 12:45:41 +08007615 final boolean mIsFloating;
7616 final boolean mIsRotatable;
Riddle Hsu61987bc2019-04-03 13:08:47 +08007617
Riddle Hsu74826262019-04-17 14:57:42 +08007618 /**
7619 * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
7620 * is used to compute the appBounds.
7621 */
Riddle Hsu61987bc2019-04-03 13:08:47 +08007622 final Rect[] mNonDecorInsets = new Rect[4];
7623 /**
7624 * The stableInsets for each rotation. Includes the status bar inset and the
7625 * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
7626 * {@link Configuration#screenHeightDp}.
7627 */
7628 final Rect[] mStableInsets = new Rect[4];
7629
Riddle Hsue47501b2020-02-18 12:45:41 +08007630 /** Constructs the environment to simulate the bounds behavior of the given container. */
7631 CompatDisplayInsets(DisplayContent display, WindowContainer container) {
7632 mIsFloating = container.getWindowConfiguration().tasksAreFloating();
7633 mIsRotatable = !mIsFloating && !display.ignoreRotationForApps();
7634 if (mIsFloating) {
7635 final Rect containerBounds = container.getWindowConfiguration().getBounds();
7636 mWidth = containerBounds.width();
7637 mHeight = containerBounds.height();
7638 // For apps in freeform, the task bounds are the parent bounds from the app's
7639 // perspective. No insets because within a window.
7640 final Rect emptyRect = new Rect();
Evan Rosky72f084d2019-09-11 17:05:16 -07007641 for (int rotation = 0; rotation < 4; rotation++) {
7642 mNonDecorInsets[rotation] = emptyRect;
7643 mStableInsets[rotation] = emptyRect;
7644 }
7645 return;
7646 }
Riddle Hsue47501b2020-02-18 12:45:41 +08007647
7648 // If the activity is not floating, assume it fills the display.
7649 mWidth = display.mBaseDisplayWidth;
7650 mHeight = display.mBaseDisplayHeight;
Riddle Hsu61987bc2019-04-03 13:08:47 +08007651 final DisplayPolicy policy = display.getDisplayPolicy();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007652 for (int rotation = 0; rotation < 4; rotation++) {
7653 mNonDecorInsets[rotation] = new Rect();
7654 mStableInsets[rotation] = new Rect();
7655 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
Riddle Hsue47501b2020-02-18 12:45:41 +08007656 final int dw = rotated ? mHeight : mWidth;
7657 final int dh = rotated ? mWidth : mHeight;
Riddle Hsu74826262019-04-17 14:57:42 +08007658 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
7659 .getDisplayCutout();
Riddle Hsu61987bc2019-04-03 13:08:47 +08007660 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
7661 mStableInsets[rotation].set(mNonDecorInsets[rotation]);
7662 policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
7663 }
7664 }
7665
Riddle Hsue47501b2020-02-18 12:45:41 +08007666 void getBoundsByRotation(Rect outBounds, int rotation) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08007667 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
Riddle Hsue47501b2020-02-18 12:45:41 +08007668 final int dw = rotated ? mHeight : mWidth;
7669 final int dh = rotated ? mWidth : mHeight;
Riddle Hsu61987bc2019-04-03 13:08:47 +08007670 outBounds.set(0, 0, dw, dh);
7671 }
Riddle Hsu74826262019-04-17 14:57:42 +08007672
Evan Rosky72f084d2019-09-11 17:05:16 -07007673 void getFrameByOrientation(Rect outBounds, int orientation) {
7674 final int longSide = Math.max(mWidth, mHeight);
7675 final int shortSide = Math.min(mWidth, mHeight);
Riddle Hsu74826262019-04-17 14:57:42 +08007676 final boolean isLandscape = orientation == ORIENTATION_LANDSCAPE;
7677 outBounds.set(0, 0, isLandscape ? longSide : shortSide,
7678 isLandscape ? shortSide : longSide);
7679 }
Riddle Hsue47501b2020-02-18 12:45:41 +08007680
7681 /** Gets the horizontal centered container bounds for size compatibility mode. */
7682 void getContainerBounds(Rect outAppBounds, Rect outBounds, int rotation, int orientation,
7683 boolean orientationRequested, boolean canChangeOrientation) {
7684 if (mIsFloating) {
7685 getFrameByOrientation(outBounds, orientation);
7686 outAppBounds.set(outBounds);
7687 return;
7688 }
7689
7690 if (mIsRotatable && canChangeOrientation) {
7691 getBoundsByRotation(outBounds, rotation);
7692 if (orientationRequested) {
7693 getFrameByOrientation(outAppBounds, orientation);
7694 } else {
7695 outAppBounds.set(outBounds);
7696 }
7697 } else {
7698 outBounds.set(0, 0, mWidth, mHeight);
7699 getFrameByOrientation(outAppBounds, orientation);
7700 if (orientationRequested && !canChangeOrientation
7701 && (outAppBounds.width() > outAppBounds.height()) != (mWidth > mHeight)) {
7702 // The orientation is mismatched but the display cannot rotate. The bounds will
7703 // fit to the short side of display.
7704 if (orientation == ORIENTATION_LANDSCAPE) {
7705 outAppBounds.bottom = (int) ((float) mWidth * mWidth / mHeight);
7706 outAppBounds.right = mWidth;
7707 } else {
7708 outAppBounds.bottom = mHeight;
7709 outAppBounds.right = (int) ((float) mHeight * mHeight / mWidth);
7710 }
7711 outAppBounds.offset(getHorizontalCenterOffset(outBounds.width(),
7712 outAppBounds.width()), 0 /* dy */);
7713 } else {
7714 outAppBounds.set(outBounds);
7715 }
7716 }
7717
7718 if (rotation != ROTATION_UNDEFINED) {
7719 // Ensure the app bounds won't overlap with insets.
7720 Task.intersectWithInsetsIfFits(outAppBounds, outBounds, mNonDecorInsets[rotation]);
7721 }
Riddle Hsue47501b2020-02-18 12:45:41 +08007722 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08007723 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07007724
7725 private static class AppSaturationInfo {
7726 float[] mMatrix = new float[9];
7727 float[] mTranslation = new float[3];
7728
7729 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
7730 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
7731 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
7732 }
7733 }
lumark19a5d2e2019-10-11 16:19:30 +08007734
7735 @Override
7736 RemoteAnimationTarget createRemoteAnimationTarget(
7737 RemoteAnimationController.RemoteAnimationRecord record) {
lumark19a5d2e2019-10-11 16:19:30 +08007738 final WindowState mainWindow = findMainWindow();
7739 if (task == null || mainWindow == null) {
7740 return null;
7741 }
7742 final Rect insets = new Rect();
7743 mainWindow.getContentInsets(insets);
7744 InsetUtils.addInsets(insets, getLetterboxInsets());
7745 return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
Winson Chung13af7092020-01-31 10:23:28 -08007746 record.mAdapter.mCapturedLeash, !fillsParent(),
lumark19a5d2e2019-10-11 16:19:30 +08007747 mainWindow.mWinAnimator.mLastClipRect, insets,
lumark2ec19122020-01-23 00:09:04 +08007748 getPrefixOrderIndex(), record.mAdapter.mPosition, record.mAdapter.mLocalBounds,
lumark19a5d2e2019-10-11 16:19:30 +08007749 record.mAdapter.mStackBounds, task.getWindowConfiguration(),
7750 false /*isNotInRecents*/,
7751 record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
7752 record.mStartBounds);
7753 }
7754
7755 @Override
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09007756 boolean canCreateRemoteAnimationTarget() {
7757 return true;
7758 }
7759
7760 @Override
lumark19a5d2e2019-10-11 16:19:30 +08007761 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
7762 Rect outSurfaceInsets) {
7763 final WindowState win = findMainWindow();
7764 if (win == null) {
7765 return;
7766 }
7767 win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
7768 }
Robert Carrf6690d12020-02-04 14:16:21 -08007769
7770 void setPictureInPictureParams(PictureInPictureParams p) {
7771 pictureInPictureArgs.copyOnlySet(p);
7772 getTask().getRootTask().setPictureInPictureParams(p);
7773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774}