1 /* 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 17 package com.android.server.am; 18 19 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; 20 import static android.app.ActivityManager.StackId.INVALID_STACK_ID; 21 import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX; 22 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; 23 import static android.app.ActivityOptions.ANIM_CUSTOM; 24 import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION; 25 import static android.app.ActivityOptions.ANIM_SCALE_UP; 26 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION; 27 import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; 28 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN; 29 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP; 30 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; 31 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP; 32 import static android.app.AppOpsManager.MODE_ALLOWED; 33 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; 34 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; 35 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 36 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 37 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 38 import static android.app.WindowConfiguration.activityTypeToString; 39 import static android.content.Intent.ACTION_MAIN; 40 import static android.content.Intent.CATEGORY_HOME; 41 import static android.content.Intent.CATEGORY_LAUNCHER; 42 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; 43 import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY; 44 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; 45 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; 46 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; 47 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 48 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; 49 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 50 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; 51 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; 52 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE; 53 import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS; 54 import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY; 55 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; 56 import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; 57 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED; 58 import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON; 59 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE; 60 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; 61 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; 62 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP; 63 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS; 64 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT; 65 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED; 66 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER; 67 import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS; 68 import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY; 69 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; 70 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; 71 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 72 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; 73 import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; 74 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; 75 import static android.content.res.Configuration.EMPTY; 76 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 77 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 78 import static android.content.res.Configuration.UI_MODE_TYPE_MASK; 79 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET; 80 import static android.os.Build.VERSION_CODES.HONEYCOMB; 81 import static android.os.Build.VERSION_CODES.O; 82 import static android.os.Process.SYSTEM_UID; 83 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; 84 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; 85 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE; 86 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; 87 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; 88 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY; 89 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; 90 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE; 91 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES; 92 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; 93 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; 94 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 95 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 96 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING; 97 import static com.android.server.am.ActivityStack.ActivityState.PAUSED; 98 import static com.android.server.am.ActivityStack.ActivityState.PAUSING; 99 import static com.android.server.am.ActivityStack.ActivityState.RESUMED; 100 import static com.android.server.am.ActivityStack.ActivityState.STOPPED; 101 import static com.android.server.am.ActivityStack.ActivityState.STOPPING; 102 import static com.android.server.am.ActivityStack.LAUNCH_TICK; 103 import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG; 104 import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG; 105 import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG; 106 import static com.android.server.am.EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME; 107 import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME; 108 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY; 109 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY; 110 import static com.android.server.am.TaskPersister.DEBUG; 111 import static com.android.server.am.TaskPersister.IMAGE_EXTENSION; 112 import static com.android.server.am.TaskRecord.INVALID_TASK_ID; 113 import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER; 114 import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK; 115 import static com.android.server.am.ActivityRecordProto.IDENTIFIER; 116 import static com.android.server.am.ActivityRecordProto.PROC_ID; 117 import static com.android.server.am.ActivityRecordProto.STATE; 118 import static com.android.server.am.ActivityRecordProto.TRANSLUCENT; 119 import static com.android.server.am.ActivityRecordProto.VISIBLE; 120 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT; 121 import static com.android.server.wm.IdentifierProto.HASH_CODE; 122 import static com.android.server.wm.IdentifierProto.TITLE; 123 import static com.android.server.wm.IdentifierProto.USER_ID; 124 125 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 126 import static org.xmlpull.v1.XmlPullParser.END_TAG; 127 import static org.xmlpull.v1.XmlPullParser.START_TAG; 128 129 import android.annotation.NonNull; 130 import android.app.ActivityManager.TaskDescription; 131 import android.app.ActivityOptions; 132 import android.app.PendingIntent; 133 import android.app.PictureInPictureParams; 134 import android.app.ResultInfo; 135 import android.app.servertransaction.ActivityLifecycleItem; 136 import android.app.servertransaction.ActivityRelaunchItem; 137 import android.app.servertransaction.ClientTransaction; 138 import android.app.servertransaction.ClientTransactionItem; 139 import android.app.servertransaction.MoveToDisplayItem; 140 import android.app.servertransaction.MultiWindowModeChangeItem; 141 import android.app.servertransaction.NewIntentItem; 142 import android.app.servertransaction.PauseActivityItem; 143 import android.app.servertransaction.PipModeChangeItem; 144 import android.app.servertransaction.ResumeActivityItem; 145 import android.app.servertransaction.WindowVisibilityItem; 146 import android.app.servertransaction.ActivityConfigurationChangeItem; 147 import android.content.ComponentName; 148 import android.content.Intent; 149 import android.content.pm.ActivityInfo; 150 import android.content.pm.ApplicationInfo; 151 import android.content.res.CompatibilityInfo; 152 import android.content.res.Configuration; 153 import android.graphics.Bitmap; 154 import android.graphics.GraphicBuffer; 155 import android.graphics.Rect; 156 import android.os.Binder; 157 import android.os.Build; 158 import android.os.Bundle; 159 import android.os.Debug; 160 import android.os.IBinder; 161 import android.os.Message; 162 import android.os.PersistableBundle; 163 import android.os.Process; 164 import android.os.RemoteException; 165 import android.os.SystemClock; 166 import android.os.Trace; 167 import android.os.UserHandle; 168 import android.os.storage.StorageManager; 169 import android.service.voice.IVoiceInteractionSession; 170 import android.util.EventLog; 171 import android.util.Log; 172 import android.util.MergedConfiguration; 173 import android.util.Slog; 174 import android.util.TimeUtils; 175 import android.util.proto.ProtoOutputStream; 176 import android.view.AppTransitionAnimationSpec; 177 import android.view.IAppTransitionAnimationSpecsFuture; 178 import android.view.IApplicationToken; 179 import android.view.RemoteAnimationDefinition; 180 import android.view.WindowManager.LayoutParams; 181 182 import com.android.internal.R; 183 import com.android.internal.app.ResolverActivity; 184 import com.android.internal.content.ReferrerIntent; 185 import com.android.internal.util.XmlUtils; 186 import com.android.server.AttributeCache; 187 import com.android.server.AttributeCache.Entry; 188 import com.android.server.am.ActivityStack.ActivityState; 189 import com.android.server.wm.AppWindowContainerController; 190 import com.android.server.wm.AppWindowContainerListener; 191 import com.android.server.wm.ConfigurationContainer; 192 import com.android.server.wm.TaskWindowContainerController; 193 194 import org.xmlpull.v1.XmlPullParser; 195 import org.xmlpull.v1.XmlPullParserException; 196 import org.xmlpull.v1.XmlSerializer; 197 198 import java.io.File; 199 import java.io.IOException; 200 import java.io.PrintWriter; 201 import java.lang.ref.WeakReference; 202 import java.util.ArrayList; 203 import java.util.Arrays; 204 import java.util.HashSet; 205 import java.util.List; 206 import java.util.Objects; 207 208 /** 209 * An entry in the history stack, representing an activity. 210 */ 211 final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener { 212 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM; 213 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; 214 private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE; 215 private static final String TAG_STATES = TAG + POSTFIX_STATES; 216 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; 217 private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; 218 // TODO(b/67864419): Remove once recents component is overridden 219 private static final String LEGACY_RECENTS_PACKAGE_NAME = "com.android.systemui.recents"; 220 221 private static final boolean SHOW_ACTIVITY_START_TIME = true; 222 223 private static final String ATTR_ID = "id"; 224 private static final String TAG_INTENT = "intent"; 225 private static final String ATTR_USERID = "user_id"; 226 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle"; 227 private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid"; 228 private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package"; 229 private static final String ATTR_RESOLVEDTYPE = "resolved_type"; 230 private static final String ATTR_COMPONENTSPECIFIED = "component_specified"; 231 static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_"; 232 233 final ActivityManagerService service; // owner 234 final IApplicationToken.Stub appToken; // window manager token 235 AppWindowContainerController mWindowContainerController; 236 final ActivityInfo info; // all about me 237 // TODO: This is duplicated state already contained in info.applicationInfo - remove 238 ApplicationInfo appInfo; // information about activity's app 239 final int launchedFromPid; // always the pid who started the activity. 240 final int launchedFromUid; // always the uid who started the activity. 241 final String launchedFromPackage; // always the package who started the activity. 242 final int userId; // Which user is this running for? 243 final Intent intent; // the original intent that generated us 244 final ComponentName realActivity; // the intent component, or target of an alias. 245 final String shortComponentName; // the short component name of the intent 246 final String resolvedType; // as per original caller; 247 final String packageName; // the package implementing intent's component 248 final String processName; // process where this component wants to run 249 final String taskAffinity; // as per ActivityInfo.taskAffinity 250 final boolean stateNotNeeded; // As per ActivityInfo.flags 251 boolean fullscreen; // The activity is opaque and fills the entire space of this task. 252 // TODO: See if it possible to combine this with the fullscreen field. 253 final boolean hasWallpaper; // Has a wallpaper window as a background. 254 final boolean noDisplay; // activity is not displayed? 255 private final boolean componentSpecified; // did caller specify an explicit component? 256 final boolean rootVoiceInteraction; // was this the root activity of a voice interaction? 257 258 private CharSequence nonLocalizedLabel; // the label information from the package mgr. 259 private int labelRes; // the label information from the package mgr. 260 private int icon; // resource identifier of activity's icon. 261 private int logo; // resource identifier of activity's logo. 262 private int theme; // resource identifier of activity's theme. 263 private int realTheme; // actual theme resource we will use, never 0. 264 private int windowFlags; // custom window flags for preview window. 265 private TaskRecord task; // the task this is in. 266 private long createTime = System.currentTimeMillis(); 267 long displayStartTime; // when we started launching this activity 268 long fullyDrawnStartTime; // when we started launching this activity 269 private long startTime; // last time this activity was started 270 long lastVisibleTime; // last time this activity became visible 271 long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity 272 long pauseTime; // last time we started pausing the activity 273 long launchTickTime; // base time for launch tick messages 274 // Last configuration reported to the activity in the client process. 275 private MergedConfiguration mLastReportedConfiguration; 276 private int mLastReportedDisplayId; 277 private boolean mLastReportedMultiWindowMode; 278 private boolean mLastReportedPictureInPictureMode; 279 CompatibilityInfo compat;// last used compatibility mode 280 ActivityRecord resultTo; // who started this entry, so will get our reply 281 final String resultWho; // additional identifier for use by resultTo. 282 final int requestCode; // code given by requester (resultTo) 283 ArrayList<ResultInfo> results; // pending ActivityResult objs we have received 284 HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act 285 ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode 286 ActivityOptions pendingOptions; // most recently given options 287 ActivityOptions returningOptions; // options that are coming back via convertToTranslucent 288 AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity 289 HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold 290 UriPermissionOwner uriPermissions; // current special URI access perms. 291 ProcessRecord app; // if non-null, hosting application 292 private ActivityState mState; // current state we are in 293 Bundle icicle; // last saved activity state 294 PersistableBundle persistentState; // last persistently saved activity state 295 // TODO: See if this is still needed. 296 boolean frontOfTask; // is this the root activity of its task? 297 boolean launchFailed; // set if a launched failed, to abort on 2nd try 298 boolean haveState; // have we gotten the last activity state? 299 boolean stopped; // is activity pause finished? 300 boolean delayedResume; // not yet resumed because of stopped app switches? 301 boolean finishing; // activity in pending finish list? 302 boolean deferRelaunchUntilPaused; // relaunch of activity is being deferred until pause is 303 // completed 304 boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch 305 int configChangeFlags; // which config values have changed 306 private boolean keysPaused; // has key dispatching been paused for it? 307 int launchMode; // the launch mode activity attribute. 308 int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override 309 boolean visible; // does this activity's window need to be shown? 310 boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard 311 // might hide this activity? 312 private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client 313 // process that it is hidden. 314 boolean sleeping; // have we told the activity to sleep? 315 boolean nowVisible; // is this activity's window visible? 316 boolean mClientVisibilityDeferred;// was the visibility change message to client deferred? 317 boolean idle; // has the activity gone idle? 318 boolean hasBeenLaunched;// has this activity ever been launched? 319 boolean frozenBeforeDestroy;// has been frozen but not yet destroyed. 320 boolean immersive; // immersive mode (don't interrupt if possible) 321 boolean forceNewConfig; // force re-create with new config next time 322 boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the 323 // activity can enter picture in picture while pausing (only when switching to another task) 324 PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build(); 325 // The PiP params used when deferring the entering of picture-in-picture. 326 int launchCount; // count of launches since last state 327 long lastLaunchTime; // time of last launch of this activity 328 ComponentName requestedVrComponent; // the requested component for handling VR mode. 329 330 String stringName; // for caching of toString(). 331 332 private boolean inHistory; // are we in the history stack? 333 final ActivityStackSupervisor mStackSupervisor; 334 335 static final int STARTING_WINDOW_NOT_SHOWN = 0; 336 static final int STARTING_WINDOW_SHOWN = 1; 337 static final int STARTING_WINDOW_REMOVED = 2; 338 int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN; 339 boolean mTaskOverlay = false; // Task is always on-top of other activities in the task. 340 341 TaskDescription taskDescription; // the recents information for this activity 342 boolean mLaunchTaskBehind; // this activity is actively being launched with 343 // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed. 344 345 // These configurations are collected from application's resources based on size-sensitive 346 // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800 347 // and drawable-sw400dp will be added to both as 400. 348 private int[] mVerticalSizeConfigurations; 349 private int[] mHorizontalSizeConfigurations; 350 private int[] mSmallestSizeConfigurations; 351 352 boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session 353 IVoiceInteractionSession voiceSession; // Voice interaction session for this activity 354 355 // A hint to override the window specified rotation animation, or -1 356 // to use the window specified value. We use this so that 357 // we can select the right animation in the cases of starting 358 // windows, where the app hasn't had time to set a value 359 // on the window. 360 int mRotationAnimationHint = -1; 361 362 private boolean mShowWhenLocked; 363 private boolean mTurnScreenOn; 364 365 /** 366 * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)} 367 */ 368 private final Configuration mTmpConfig = new Configuration(); 369 private final Rect mTmpBounds = new Rect(); 370 startingWindowStateToString(int state)371 private static String startingWindowStateToString(int state) { 372 switch (state) { 373 case STARTING_WINDOW_NOT_SHOWN: 374 return "STARTING_WINDOW_NOT_SHOWN"; 375 case STARTING_WINDOW_SHOWN: 376 return "STARTING_WINDOW_SHOWN"; 377 case STARTING_WINDOW_REMOVED: 378 return "STARTING_WINDOW_REMOVED"; 379 default: 380 return "unknown state=" + state; 381 } 382 } 383 dump(PrintWriter pw, String prefix)384 void dump(PrintWriter pw, String prefix) { 385 final long now = SystemClock.uptimeMillis(); 386 pw.print(prefix); pw.print("packageName="); pw.print(packageName); 387 pw.print(" processName="); pw.println(processName); 388 pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid); 389 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage); 390 pw.print(" userId="); pw.println(userId); 391 pw.print(prefix); pw.print("app="); pw.println(app); 392 pw.print(prefix); pw.println(intent.toInsecureStringWithClip()); 393 pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask); 394 pw.print(" task="); pw.println(task); 395 pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity); 396 pw.print(prefix); pw.print("realActivity="); 397 pw.println(realActivity.flattenToShortString()); 398 if (appInfo != null) { 399 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir); 400 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) { 401 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir); 402 } 403 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir); 404 if (appInfo.splitSourceDirs != null) { 405 pw.print(prefix); pw.print("splitDir="); 406 pw.println(Arrays.toString(appInfo.splitSourceDirs)); 407 } 408 } 409 pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded); 410 pw.print(" componentSpecified="); pw.print(componentSpecified); 411 pw.print(" mActivityType="); pw.println( 412 activityTypeToString(getActivityType())); 413 if (rootVoiceInteraction) { 414 pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction); 415 } 416 pw.print(prefix); pw.print("compat="); pw.print(compat); 417 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes)); 418 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); 419 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme)); 420 pw.println(prefix + "mLastReportedConfigurations:"); 421 mLastReportedConfiguration.dump(pw, prefix + " "); 422 423 pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration()); 424 if (!getOverrideConfiguration().equals(EMPTY)) { 425 pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration()); 426 } 427 if (!matchParentBounds()) { 428 pw.println(prefix + "bounds=" + getBounds()); 429 } 430 if (resultTo != null || resultWho != null) { 431 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo); 432 pw.print(" resultWho="); pw.print(resultWho); 433 pw.print(" resultCode="); pw.println(requestCode); 434 } 435 if (taskDescription != null) { 436 final String iconFilename = taskDescription.getIconFilename(); 437 if (iconFilename != null || taskDescription.getLabel() != null || 438 taskDescription.getPrimaryColor() != 0) { 439 pw.print(prefix); pw.print("taskDescription:"); 440 pw.print(" label=\""); pw.print(taskDescription.getLabel()); 441 pw.print("\""); 442 pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null 443 ? taskDescription.getInMemoryIcon().getByteCount() + " bytes" 444 : "null"); 445 pw.print(" iconResource="); pw.print(taskDescription.getIconResource()); 446 pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename()); 447 pw.print(" primaryColor="); 448 pw.println(Integer.toHexString(taskDescription.getPrimaryColor())); 449 pw.print(prefix + " backgroundColor="); 450 pw.println(Integer.toHexString(taskDescription.getBackgroundColor())); 451 pw.print(prefix + " statusBarColor="); 452 pw.println(Integer.toHexString(taskDescription.getStatusBarColor())); 453 pw.print(prefix + " navigationBarColor="); 454 pw.println(Integer.toHexString(taskDescription.getNavigationBarColor())); 455 } 456 } 457 if (results != null) { 458 pw.print(prefix); pw.print("results="); pw.println(results); 459 } 460 if (pendingResults != null && pendingResults.size() > 0) { 461 pw.print(prefix); pw.println("Pending Results:"); 462 for (WeakReference<PendingIntentRecord> wpir : pendingResults) { 463 PendingIntentRecord pir = wpir != null ? wpir.get() : null; 464 pw.print(prefix); pw.print(" - "); 465 if (pir == null) { 466 pw.println("null"); 467 } else { 468 pw.println(pir); 469 pir.dump(pw, prefix + " "); 470 } 471 } 472 } 473 if (newIntents != null && newIntents.size() > 0) { 474 pw.print(prefix); pw.println("Pending New Intents:"); 475 for (int i=0; i<newIntents.size(); i++) { 476 Intent intent = newIntents.get(i); 477 pw.print(prefix); pw.print(" - "); 478 if (intent == null) { 479 pw.println("null"); 480 } else { 481 pw.println(intent.toShortString(false, true, false, true)); 482 } 483 } 484 } 485 if (pendingOptions != null) { 486 pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions); 487 } 488 if (appTimeTracker != null) { 489 appTimeTracker.dumpWithHeader(pw, prefix, false); 490 } 491 if (uriPermissions != null) { 492 uriPermissions.dump(pw, prefix); 493 } 494 pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed); 495 pw.print(" launchCount="); pw.print(launchCount); 496 pw.print(" lastLaunchTime="); 497 if (lastLaunchTime == 0) pw.print("0"); 498 else TimeUtils.formatDuration(lastLaunchTime, now, pw); 499 pw.println(); 500 pw.print(prefix); pw.print("haveState="); pw.print(haveState); 501 pw.print(" icicle="); pw.println(icicle); 502 pw.print(prefix); pw.print("state="); pw.print(mState); 503 pw.print(" stopped="); pw.print(stopped); 504 pw.print(" delayedResume="); pw.print(delayedResume); 505 pw.print(" finishing="); pw.println(finishing); 506 pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused); 507 pw.print(" inHistory="); pw.print(inHistory); 508 pw.print(" visible="); pw.print(visible); 509 pw.print(" sleeping="); pw.print(sleeping); 510 pw.print(" idle="); pw.print(idle); 511 pw.print(" mStartingWindowState="); 512 pw.println(startingWindowStateToString(mStartingWindowState)); 513 pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen); 514 pw.print(" noDisplay="); pw.print(noDisplay); 515 pw.print(" immersive="); pw.print(immersive); 516 pw.print(" launchMode="); pw.println(launchMode); 517 pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy); 518 pw.print(" forceNewConfig="); pw.println(forceNewConfig); 519 pw.print(prefix); pw.print("mActivityType="); 520 pw.println(activityTypeToString(getActivityType())); 521 if (requestedVrComponent != null) { 522 pw.print(prefix); 523 pw.print("requestedVrComponent="); 524 pw.println(requestedVrComponent); 525 } 526 if (displayStartTime != 0 || startTime != 0) { 527 pw.print(prefix); pw.print("displayStartTime="); 528 if (displayStartTime == 0) pw.print("0"); 529 else TimeUtils.formatDuration(displayStartTime, now, pw); 530 pw.print(" startTime="); 531 if (startTime == 0) pw.print("0"); 532 else TimeUtils.formatDuration(startTime, now, pw); 533 pw.println(); 534 } 535 final boolean waitingVisible = 536 mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this); 537 if (lastVisibleTime != 0 || waitingVisible || nowVisible) { 538 pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible); 539 pw.print(" nowVisible="); pw.print(nowVisible); 540 pw.print(" lastVisibleTime="); 541 if (lastVisibleTime == 0) pw.print("0"); 542 else TimeUtils.formatDuration(lastVisibleTime, now, pw); 543 pw.println(); 544 } 545 if (mDeferHidingClient) { 546 pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient); 547 } 548 if (deferRelaunchUntilPaused || configChangeFlags != 0) { 549 pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused); 550 pw.print(" configChangeFlags="); 551 pw.println(Integer.toHexString(configChangeFlags)); 552 } 553 if (connections != null) { 554 pw.print(prefix); pw.print("connections="); pw.println(connections); 555 } 556 if (info != null) { 557 pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode)); 558 pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode 559 + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode); 560 if (info.supportsPictureInPicture()) { 561 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture()); 562 pw.println(prefix + "supportsEnterPipOnTaskSwitch: " 563 + supportsEnterPipOnTaskSwitch); 564 } 565 if (info.maxAspectRatio != 0) { 566 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio); 567 } 568 } 569 } 570 updateApplicationInfo(ApplicationInfo aInfo)571 void updateApplicationInfo(ApplicationInfo aInfo) { 572 appInfo = aInfo; 573 info.applicationInfo = aInfo; 574 } 575 crossesHorizontalSizeThreshold(int firstDp, int secondDp)576 private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) { 577 return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp); 578 } 579 crossesVerticalSizeThreshold(int firstDp, int secondDp)580 private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) { 581 return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp); 582 } 583 crossesSmallestSizeThreshold(int firstDp, int secondDp)584 private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) { 585 return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp); 586 } 587 588 /** 589 * The purpose of this method is to decide whether the activity needs to be relaunched upon 590 * changing its size. In most cases the activities don't need to be relaunched, if the resize 591 * is small, all the activity content has to do is relayout itself within new bounds. There are 592 * cases however, where the activity's content would be completely changed in the new size and 593 * the full relaunch is required. 594 * 595 * The activity will report to us vertical and horizontal thresholds after which a relaunch is 596 * required. These thresholds are collected from the application resource qualifiers. For 597 * example, if application has layout-w600dp resource directory, then it needs a relaunch when 598 * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if 599 * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side 600 * of the threshold. 601 */ crossesSizeThreshold(int[] thresholds, int firstDp, int secondDp)602 private static boolean crossesSizeThreshold(int[] thresholds, int firstDp, 603 int secondDp) { 604 if (thresholds == null) { 605 return false; 606 } 607 for (int i = thresholds.length - 1; i >= 0; i--) { 608 final int threshold = thresholds[i]; 609 if ((firstDp < threshold && secondDp >= threshold) 610 || (firstDp >= threshold && secondDp < threshold)) { 611 return true; 612 } 613 } 614 return false; 615 } 616 setSizeConfigurations(int[] horizontalSizeConfiguration, int[] verticalSizeConfigurations, int[] smallestSizeConfigurations)617 void setSizeConfigurations(int[] horizontalSizeConfiguration, 618 int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) { 619 mHorizontalSizeConfigurations = horizontalSizeConfiguration; 620 mVerticalSizeConfigurations = verticalSizeConfigurations; 621 mSmallestSizeConfigurations = smallestSizeConfigurations; 622 } 623 scheduleActivityMovedToDisplay(int displayId, Configuration config)624 private void scheduleActivityMovedToDisplay(int displayId, Configuration config) { 625 if (app == null || app.thread == null) { 626 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG, 627 "Can't report activity moved to display - client not running, activityRecord=" 628 + this + ", displayId=" + displayId); 629 return; 630 } 631 try { 632 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 633 "Reporting activity moved to display" + ", activityRecord=" + this 634 + ", displayId=" + displayId + ", config=" + config); 635 636 service.getLifecycleManager().scheduleTransaction(app.thread, appToken, 637 MoveToDisplayItem.obtain(displayId, config)); 638 } catch (RemoteException e) { 639 // If process died, whatever. 640 } 641 } 642 scheduleConfigurationChanged(Configuration config)643 private void scheduleConfigurationChanged(Configuration config) { 644 if (app == null || app.thread == null) { 645 if (DEBUG_CONFIGURATION) Slog.w(TAG, 646 "Can't report activity configuration update - client not running" 647 + ", activityRecord=" + this); 648 return; 649 } 650 try { 651 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: " 652 + config); 653 654 service.getLifecycleManager().scheduleTransaction(app.thread, appToken, 655 ActivityConfigurationChangeItem.obtain(config)); 656 } catch (RemoteException e) { 657 // If process died, whatever. 658 } 659 } 660 updateMultiWindowMode()661 void updateMultiWindowMode() { 662 if (task == null || task.getStack() == null || app == null || app.thread == null) { 663 return; 664 } 665 666 if (task.getStack().deferScheduleMultiWindowModeChanged()) { 667 // Don't do anything if we are currently deferring multi-window mode change. 668 return; 669 } 670 671 // An activity is considered to be in multi-window mode if its task isn't fullscreen. 672 final boolean inMultiWindowMode = inMultiWindowMode(); 673 if (inMultiWindowMode != mLastReportedMultiWindowMode) { 674 mLastReportedMultiWindowMode = inMultiWindowMode; 675 scheduleMultiWindowModeChanged(getConfiguration()); 676 } 677 } 678 scheduleMultiWindowModeChanged(Configuration overrideConfig)679 private void scheduleMultiWindowModeChanged(Configuration overrideConfig) { 680 try { 681 service.getLifecycleManager().scheduleTransaction(app.thread, appToken, 682 MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, 683 overrideConfig)); 684 } catch (Exception e) { 685 // If process died, I don't care. 686 } 687 } 688 updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate)689 void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) { 690 if (task == null || task.getStack() == null || app == null || app.thread == null) { 691 return; 692 } 693 694 final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null; 695 if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) { 696 // Picture-in-picture mode changes also trigger a multi-window mode change as well, so 697 // update that here in order 698 mLastReportedPictureInPictureMode = inPictureInPictureMode; 699 mLastReportedMultiWindowMode = inMultiWindowMode(); 700 final Configuration newConfig = task.computeNewOverrideConfigurationForBounds( 701 targetStackBounds, null); 702 schedulePictureInPictureModeChanged(newConfig); 703 scheduleMultiWindowModeChanged(newConfig); 704 } 705 } 706 schedulePictureInPictureModeChanged(Configuration overrideConfig)707 private void schedulePictureInPictureModeChanged(Configuration overrideConfig) { 708 try { 709 service.getLifecycleManager().scheduleTransaction(app.thread, appToken, 710 PipModeChangeItem.obtain(mLastReportedPictureInPictureMode, 711 overrideConfig)); 712 } catch (Exception e) { 713 // If process died, no one cares. 714 } 715 } 716 717 @Override getChildCount()718 protected int getChildCount() { 719 // {@link ActivityRecord} is a leaf node and has no children. 720 return 0; 721 } 722 723 @Override getChildAt(int index)724 protected ConfigurationContainer getChildAt(int index) { 725 return null; 726 } 727 728 @Override getParent()729 protected ConfigurationContainer getParent() { 730 return getTask(); 731 } 732 getTask()733 TaskRecord getTask() { 734 return task; 735 } 736 737 /** 738 * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent. 739 * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord} 740 * children. However, this method will clean up references to this {@link ActivityRecord} in 741 * {@link ActivityStack}. 742 * @param task The new parent {@link TaskRecord}. 743 */ setTask(TaskRecord task)744 void setTask(TaskRecord task) { 745 setTask(task /* task */, false /* reparenting */); 746 } 747 748 /** 749 * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}. 750 * @param task The new parent task. 751 * @param reparenting Whether we're in the middle of reparenting. 752 */ setTask(TaskRecord task, boolean reparenting)753 void setTask(TaskRecord task, boolean reparenting) { 754 // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}. 755 if (task != null && task == getTask()) { 756 return; 757 } 758 759 final ActivityStack oldStack = getStack(); 760 final ActivityStack newStack = task != null ? task.getStack() : null; 761 762 // Inform old stack (if present) of activity removal and new stack (if set) of activity 763 // addition. 764 if (oldStack != newStack) { 765 if (!reparenting && oldStack != null) { 766 oldStack.onActivityRemovedFromStack(this); 767 } 768 769 if (newStack != null) { 770 newStack.onActivityAddedToStack(this); 771 } 772 } 773 774 this.task = task; 775 776 if (!reparenting) { 777 onParentChanged(); 778 } 779 } 780 781 /** 782 * See {@link AppWindowContainerController#setWillCloseOrEnterPip(boolean)} 783 */ setWillCloseOrEnterPip(boolean willCloseOrEnterPip)784 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) { 785 getWindowContainerController().setWillCloseOrEnterPip(willCloseOrEnterPip); 786 } 787 788 static class Token extends IApplicationToken.Stub { 789 private final WeakReference<ActivityRecord> weakActivity; 790 private final String name; 791 Token(ActivityRecord activity, Intent intent)792 Token(ActivityRecord activity, Intent intent) { 793 weakActivity = new WeakReference<>(activity); 794 name = intent.getComponent().flattenToShortString(); 795 } 796 tokenToActivityRecordLocked(Token token)797 private static ActivityRecord tokenToActivityRecordLocked(Token token) { 798 if (token == null) { 799 return null; 800 } 801 ActivityRecord r = token.weakActivity.get(); 802 if (r == null || r.getStack() == null) { 803 return null; 804 } 805 return r; 806 } 807 808 @Override toString()809 public String toString() { 810 StringBuilder sb = new StringBuilder(128); 811 sb.append("Token{"); 812 sb.append(Integer.toHexString(System.identityHashCode(this))); 813 sb.append(' '); 814 sb.append(weakActivity.get()); 815 sb.append('}'); 816 return sb.toString(); 817 } 818 819 @Override getName()820 public String getName() { 821 return name; 822 } 823 } 824 forTokenLocked(IBinder token)825 static ActivityRecord forTokenLocked(IBinder token) { 826 try { 827 return Token.tokenToActivityRecordLocked((Token)token); 828 } catch (ClassCastException e) { 829 Slog.w(TAG, "Bad activity token: " + token, e); 830 return null; 831 } 832 } 833 isResolverActivity()834 boolean isResolverActivity() { 835 return ResolverActivity.class.getName().equals(realActivity.getClassName()); 836 } 837 isResolverOrChildActivity()838 boolean isResolverOrChildActivity() { 839 if (!"android".equals(packageName)) { 840 return false; 841 } 842 try { 843 return ResolverActivity.class.isAssignableFrom( 844 Object.class.getClassLoader().loadClass(realActivity.getClassName())); 845 } catch (ClassNotFoundException e) { 846 return false; 847 } 848 } 849 ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified, boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor, ActivityOptions options, ActivityRecord sourceRecord)850 ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid, 851 int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, 852 ActivityInfo aInfo, Configuration _configuration, 853 ActivityRecord _resultTo, String _resultWho, int _reqCode, 854 boolean _componentSpecified, boolean _rootVoiceInteraction, 855 ActivityStackSupervisor supervisor, ActivityOptions options, 856 ActivityRecord sourceRecord) { 857 service = _service; 858 appToken = new Token(this, _intent); 859 info = aInfo; 860 launchedFromPid = _launchedFromPid; 861 launchedFromUid = _launchedFromUid; 862 launchedFromPackage = _launchedFromPackage; 863 userId = UserHandle.getUserId(aInfo.applicationInfo.uid); 864 intent = _intent; 865 shortComponentName = _intent.getComponent().flattenToShortString(); 866 resolvedType = _resolvedType; 867 componentSpecified = _componentSpecified; 868 rootVoiceInteraction = _rootVoiceInteraction; 869 mLastReportedConfiguration = new MergedConfiguration(_configuration); 870 resultTo = _resultTo; 871 resultWho = _resultWho; 872 requestCode = _reqCode; 873 setState(INITIALIZING, "ActivityRecord ctor"); 874 frontOfTask = false; 875 launchFailed = false; 876 stopped = false; 877 delayedResume = false; 878 finishing = false; 879 deferRelaunchUntilPaused = false; 880 keysPaused = false; 881 inHistory = false; 882 visible = false; 883 nowVisible = false; 884 idle = false; 885 hasBeenLaunched = false; 886 mStackSupervisor = supervisor; 887 888 // This starts out true, since the initial state of an activity is that we have everything, 889 // and we shouldn't never consider it lacking in state to be removed if it dies. 890 haveState = true; 891 892 // If the class name in the intent doesn't match that of the target, this is 893 // probably an alias. We have to create a new ComponentName object to keep track 894 // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly. 895 if (aInfo.targetActivity == null 896 || (aInfo.targetActivity.equals(_intent.getComponent().getClassName()) 897 && (aInfo.launchMode == LAUNCH_MULTIPLE 898 || aInfo.launchMode == LAUNCH_SINGLE_TOP))) { 899 realActivity = _intent.getComponent(); 900 } else { 901 realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity); 902 } 903 taskAffinity = aInfo.taskAffinity; 904 stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0; 905 appInfo = aInfo.applicationInfo; 906 nonLocalizedLabel = aInfo.nonLocalizedLabel; 907 labelRes = aInfo.labelRes; 908 if (nonLocalizedLabel == null && labelRes == 0) { 909 ApplicationInfo app = aInfo.applicationInfo; 910 nonLocalizedLabel = app.nonLocalizedLabel; 911 labelRes = app.labelRes; 912 } 913 icon = aInfo.getIconResource(); 914 logo = aInfo.getLogoResource(); 915 theme = aInfo.getThemeResource(); 916 realTheme = theme; 917 if (realTheme == 0) { 918 realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB 919 ? android.R.style.Theme : android.R.style.Theme_Holo; 920 } 921 if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { 922 windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED; 923 } 924 if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null 925 && (aInfo.applicationInfo.uid == SYSTEM_UID 926 || aInfo.applicationInfo.uid == _caller.info.uid)) { 927 processName = _caller.processName; 928 } else { 929 processName = aInfo.processName; 930 } 931 932 if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) { 933 intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 934 } 935 936 packageName = aInfo.applicationInfo.packageName; 937 launchMode = aInfo.launchMode; 938 939 Entry ent = AttributeCache.instance().get(packageName, 940 realTheme, com.android.internal.R.styleable.Window, userId); 941 942 if (ent != null) { 943 fullscreen = !ActivityInfo.isTranslucentOrFloating(ent.array); 944 hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false); 945 noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false); 946 } else { 947 hasWallpaper = false; 948 noDisplay = false; 949 } 950 951 setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord); 952 953 immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0; 954 955 requestedVrComponent = (aInfo.requestedVrComponent == null) ? 956 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent); 957 958 mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0; 959 mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0; 960 961 mRotationAnimationHint = aInfo.rotationAnimation; 962 lockTaskLaunchMode = aInfo.lockTaskLaunchMode; 963 if (appInfo.isPrivilegedApp() && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS 964 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) { 965 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT; 966 } 967 968 if (options != null) { 969 pendingOptions = options; 970 mLaunchTaskBehind = options.getLaunchTaskBehind(); 971 972 final int rotationAnimation = pendingOptions.getRotationAnimationHint(); 973 // Only override manifest supplied option if set. 974 if (rotationAnimation >= 0) { 975 mRotationAnimationHint = rotationAnimation; 976 } 977 final PendingIntent usageReport = pendingOptions.getUsageTimeReport(); 978 if (usageReport != null) { 979 appTimeTracker = new AppTimeTracker(usageReport); 980 } 981 final boolean useLockTask = pendingOptions.getLockTaskMode(); 982 if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) { 983 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED; 984 } 985 } 986 } 987 setProcess(ProcessRecord proc)988 void setProcess(ProcessRecord proc) { 989 app = proc; 990 final ActivityRecord root = task != null ? task.getRootActivity() : null; 991 if (root == this) { 992 task.setRootProcess(proc); 993 } 994 } 995 getWindowContainerController()996 AppWindowContainerController getWindowContainerController() { 997 return mWindowContainerController; 998 } 999 createWindowContainer()1000 void createWindowContainer() { 1001 if (mWindowContainerController != null) { 1002 throw new IllegalArgumentException("Window container=" + mWindowContainerController 1003 + " already created for r=" + this); 1004 } 1005 1006 inHistory = true; 1007 1008 final TaskWindowContainerController taskController = task.getWindowContainerController(); 1009 1010 // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration() 1011 task.updateOverrideConfigurationFromLaunchBounds(); 1012 // Make sure override configuration is up-to-date before using to create window controller. 1013 updateOverrideConfiguration(); 1014 1015 mWindowContainerController = new AppWindowContainerController(taskController, appToken, 1016 this, Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen, 1017 (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges, 1018 task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(), 1019 appInfo.targetSdkVersion, mRotationAnimationHint, 1020 ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L); 1021 1022 task.addActivityToTop(this); 1023 1024 // When an activity is started directly into a split-screen fullscreen stack, we need to 1025 // update the initial multi-window modes so that the callbacks are scheduled correctly when 1026 // the user leaves that mode. 1027 mLastReportedMultiWindowMode = inMultiWindowMode(); 1028 mLastReportedPictureInPictureMode = inPinnedWindowingMode(); 1029 } 1030 removeWindowContainer()1031 void removeWindowContainer() { 1032 // Do not try to remove a window container if we have already removed it. 1033 if (mWindowContainerController == null) { 1034 return; 1035 } 1036 1037 // Resume key dispatching if it is currently paused before we remove the container. 1038 resumeKeyDispatchingLocked(); 1039 1040 mWindowContainerController.removeContainer(getDisplayId()); 1041 mWindowContainerController = null; 1042 } 1043 1044 /** 1045 * Reparents this activity into {@param newTask} at the provided {@param position}. The caller 1046 * should ensure that the {@param newTask} is not already the parent of this activity. 1047 */ reparent(TaskRecord newTask, int position, String reason)1048 void reparent(TaskRecord newTask, int position, String reason) { 1049 final TaskRecord prevTask = task; 1050 if (prevTask == newTask) { 1051 throw new IllegalArgumentException(reason + ": task=" + newTask 1052 + " is already the parent of r=" + this); 1053 } 1054 1055 // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave 1056 // the stacks in strange states. For now, we should use Task.reparent() to ensure that 1057 // the stack is left in an OK state. 1058 if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) { 1059 throw new IllegalArgumentException(reason + ": task=" + newTask 1060 + " is in a different stack (" + newTask.getStackId() + ") than the parent of" 1061 + " r=" + this + " (" + prevTask.getStackId() + ")"); 1062 } 1063 1064 // Must reparent first in window manager 1065 mWindowContainerController.reparent(newTask.getWindowContainerController(), position); 1066 1067 // Reparenting prevents informing the parent stack of activity removal in the case that 1068 // the new stack has the same parent. we must manually signal here if this is not the case. 1069 final ActivityStack prevStack = prevTask.getStack(); 1070 1071 if (prevStack != newTask.getStack()) { 1072 prevStack.onActivityRemovedFromStack(this); 1073 } 1074 // Remove the activity from the old task and add it to the new task. 1075 prevTask.removeActivity(this, true /* reparenting */); 1076 1077 newTask.addActivityAtIndex(position, this); 1078 } 1079 isHomeIntent(Intent intent)1080 private boolean isHomeIntent(Intent intent) { 1081 return ACTION_MAIN.equals(intent.getAction()) 1082 && intent.hasCategory(CATEGORY_HOME) 1083 && intent.getCategories().size() == 1 1084 && intent.getData() == null 1085 && intent.getType() == null; 1086 } 1087 isMainIntent(Intent intent)1088 static boolean isMainIntent(Intent intent) { 1089 return ACTION_MAIN.equals(intent.getAction()) 1090 && intent.hasCategory(CATEGORY_LAUNCHER) 1091 && intent.getCategories().size() == 1 1092 && intent.getData() == null 1093 && intent.getType() == null; 1094 } 1095 canLaunchHomeActivity(int uid, ActivityRecord sourceRecord)1096 private boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) { 1097 if (uid == Process.myUid() || uid == 0) { 1098 // System process can launch home activity. 1099 return true; 1100 } 1101 // Allow the recents component to launch the home activity. 1102 final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks(); 1103 if (recentTasks != null && recentTasks.isCallerRecents(uid)) { 1104 return true; 1105 } 1106 // Resolver activity can launch home activity. 1107 return sourceRecord != null && sourceRecord.isResolverActivity(); 1108 } 1109 1110 /** 1111 * @return whether the given package name can launch an assist activity. 1112 */ canLaunchAssistActivity(String packageName)1113 private boolean canLaunchAssistActivity(String packageName) { 1114 final ComponentName assistComponent = service.mActiveVoiceInteractionServiceComponent; 1115 if (assistComponent != null) { 1116 return assistComponent.getPackageName().equals(packageName); 1117 } 1118 return false; 1119 } 1120 setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent, ActivityOptions options, ActivityRecord sourceRecord)1121 private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent, 1122 ActivityOptions options, ActivityRecord sourceRecord) { 1123 int activityType = ACTIVITY_TYPE_UNDEFINED; 1124 if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord)) 1125 && isHomeIntent(intent) && !isResolverActivity()) { 1126 // This sure looks like a home activity! 1127 activityType = ACTIVITY_TYPE_HOME; 1128 1129 if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE 1130 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) { 1131 // We only allow home activities to be resizeable if they explicitly requested it. 1132 info.resizeMode = RESIZE_MODE_UNRESIZEABLE; 1133 } 1134 } else if (realActivity.getClassName().contains(LEGACY_RECENTS_PACKAGE_NAME) || 1135 service.getRecentTasks().isRecentsComponent(realActivity, appInfo.uid)) { 1136 activityType = ACTIVITY_TYPE_RECENTS; 1137 } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT 1138 && canLaunchAssistActivity(launchedFromPackage)) { 1139 activityType = ACTIVITY_TYPE_ASSISTANT; 1140 } 1141 setActivityType(activityType); 1142 } 1143 setTaskToAffiliateWith(TaskRecord taskToAffiliateWith)1144 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) { 1145 if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) { 1146 task.setTaskToAffiliateWith(taskToAffiliateWith); 1147 } 1148 } 1149 1150 /** 1151 * @return Stack value from current task, null if there is no task. 1152 */ getStack()1153 <T extends ActivityStack> T getStack() { 1154 return task != null ? (T) task.getStack() : null; 1155 } 1156 getStackId()1157 int getStackId() { 1158 return getStack() != null ? getStack().mStackId : INVALID_STACK_ID; 1159 } 1160 getDisplay()1161 ActivityDisplay getDisplay() { 1162 final ActivityStack stack = getStack(); 1163 return stack != null ? stack.getDisplay() : null; 1164 } 1165 changeWindowTranslucency(boolean toOpaque)1166 boolean changeWindowTranslucency(boolean toOpaque) { 1167 if (fullscreen == toOpaque) { 1168 return false; 1169 } 1170 1171 // Keep track of the number of fullscreen activities in this task. 1172 task.numFullscreen += toOpaque ? +1 : -1; 1173 1174 fullscreen = toOpaque; 1175 return true; 1176 } 1177 takeFromHistory()1178 void takeFromHistory() { 1179 if (inHistory) { 1180 inHistory = false; 1181 if (task != null && !finishing) { 1182 task = null; 1183 } 1184 clearOptionsLocked(); 1185 } 1186 } 1187 isInHistory()1188 boolean isInHistory() { 1189 return inHistory; 1190 } 1191 isInStackLocked()1192 boolean isInStackLocked() { 1193 final ActivityStack stack = getStack(); 1194 return stack != null && stack.isInStackLocked(this) != null; 1195 } 1196 isPersistable()1197 boolean isPersistable() { 1198 return (info.persistableMode == PERSIST_ROOT_ONLY || 1199 info.persistableMode == PERSIST_ACROSS_REBOOTS) && 1200 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0); 1201 } 1202 isFocusable()1203 boolean isFocusable() { 1204 return mStackSupervisor.isFocusable(this, isAlwaysFocusable()); 1205 } 1206 isResizeable()1207 boolean isResizeable() { 1208 return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture(); 1209 } 1210 1211 /** 1212 * @return whether this activity is non-resizeable or forced to be resizeable 1213 */ isNonResizableOrForcedResizable()1214 boolean isNonResizableOrForcedResizable() { 1215 return info.resizeMode != RESIZE_MODE_RESIZEABLE 1216 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 1217 } 1218 1219 /** 1220 * @return whether this activity supports PiP multi-window and can be put in the pinned stack. 1221 */ supportsPictureInPicture()1222 boolean supportsPictureInPicture() { 1223 return service.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined() 1224 && info.supportsPictureInPicture(); 1225 } 1226 1227 /** 1228 * @return whether this activity supports split-screen multi-window and can be put in the docked 1229 * stack. 1230 */ 1231 @Override supportsSplitScreenWindowingMode()1232 public boolean supportsSplitScreenWindowingMode() { 1233 // An activity can not be docked even if it is considered resizeable because it only 1234 // supports picture-in-picture mode but has a non-resizeable resizeMode 1235 return super.supportsSplitScreenWindowingMode() 1236 && service.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow(); 1237 } 1238 1239 /** 1240 * @return whether this activity supports freeform multi-window and can be put in the freeform 1241 * stack. 1242 */ supportsFreeform()1243 boolean supportsFreeform() { 1244 return service.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow(); 1245 } 1246 1247 /** 1248 * @return whether this activity supports non-PiP multi-window. 1249 */ supportsResizeableMultiWindow()1250 private boolean supportsResizeableMultiWindow() { 1251 return service.mSupportsMultiWindow && !isActivityTypeHome() 1252 && (ActivityInfo.isResizeableMode(info.resizeMode) 1253 || service.mForceResizableActivities); 1254 } 1255 1256 /** 1257 * Check whether this activity can be launched on the specified display. 1258 * @param displayId Target display id. 1259 * @return {@code true} if either it is the default display or this activity is resizeable and 1260 * can be put a secondary screen. 1261 */ canBeLaunchedOnDisplay(int displayId)1262 boolean canBeLaunchedOnDisplay(int displayId) { 1263 final TaskRecord task = getTask(); 1264 1265 // The resizeability of an Activity's parent task takes precendence over the ActivityInfo. 1266 // This allows for a non resizable activity to be launched into a resizeable task. 1267 final boolean resizeable = 1268 task != null ? task.isResizeable() : supportsResizeableMultiWindow(); 1269 1270 return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId, 1271 resizeable, launchedFromPid, launchedFromUid, info); 1272 } 1273 1274 /** 1275 * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say 1276 * the activity has requested to enter PiP when it would otherwise be stopped. 1277 * 1278 * @return whether this activity is currently allowed to enter PIP. 1279 */ checkEnterPictureInPictureState(String caller, boolean beforeStopping)1280 boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) { 1281 if (!supportsPictureInPicture()) { 1282 return false; 1283 } 1284 1285 // Check app-ops and see if PiP is supported for this package 1286 if (!checkEnterPictureInPictureAppOpsState()) { 1287 return false; 1288 } 1289 1290 // Check to see if we are in VR mode, and disallow PiP if so 1291 if (service.shouldDisableNonVrUiLocked()) { 1292 return false; 1293 } 1294 1295 boolean isKeyguardLocked = service.isKeyguardLocked(); 1296 boolean isCurrentAppLocked = service.getLockTaskModeState() != LOCK_TASK_MODE_NONE; 1297 final ActivityDisplay display = getDisplay(); 1298 boolean hasPinnedStack = display != null && display.hasPinnedStack(); 1299 // Don't return early if !isNotLocked, since we want to throw an exception if the activity 1300 // is in an incorrect state 1301 boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked; 1302 1303 // We don't allow auto-PiP when something else is already pipped. 1304 if (beforeStopping && hasPinnedStack) { 1305 return false; 1306 } 1307 1308 switch (mState) { 1309 case RESUMED: 1310 // When visible, allow entering PiP if the app is not locked. If it is over the 1311 // keyguard, then we will prompt to unlock in the caller before entering PiP. 1312 return !isCurrentAppLocked && 1313 (supportsEnterPipOnTaskSwitch || !beforeStopping); 1314 case PAUSING: 1315 case PAUSED: 1316 // When pausing, then only allow enter PiP as in the resume state, and in addition, 1317 // require that there is not an existing PiP activity and that the current system 1318 // state supports entering PiP 1319 return isNotLockedOrOnKeyguard && !hasPinnedStack 1320 && supportsEnterPipOnTaskSwitch; 1321 case STOPPING: 1322 // When stopping in a valid state, then only allow enter PiP as in the pause state. 1323 // Otherwise, fall through to throw an exception if the caller is trying to enter 1324 // PiP in an invalid stopping state. 1325 if (supportsEnterPipOnTaskSwitch) { 1326 return isNotLockedOrOnKeyguard && !hasPinnedStack; 1327 } 1328 default: 1329 return false; 1330 } 1331 } 1332 1333 /** 1334 * @return Whether AppOps allows this package to enter picture-in-picture. 1335 */ checkEnterPictureInPictureAppOpsState()1336 private boolean checkEnterPictureInPictureAppOpsState() { 1337 try { 1338 return service.getAppOpsService().checkOperation(OP_PICTURE_IN_PICTURE, 1339 appInfo.uid, packageName) == MODE_ALLOWED; 1340 } catch (RemoteException e) { 1341 // Local call 1342 } 1343 return false; 1344 } 1345 isAlwaysFocusable()1346 boolean isAlwaysFocusable() { 1347 return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0; 1348 } 1349 1350 1351 /** 1352 * @return true if the activity contains windows that have 1353 * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set 1354 */ hasDismissKeyguardWindows()1355 boolean hasDismissKeyguardWindows() { 1356 return service.mWindowManager.containsDismissKeyguardWindow(appToken); 1357 } 1358 makeFinishingLocked()1359 void makeFinishingLocked() { 1360 if (finishing) { 1361 return; 1362 } 1363 finishing = true; 1364 if (stopped) { 1365 clearOptionsLocked(); 1366 } 1367 1368 if (service != null) { 1369 service.mTaskChangeNotificationController.notifyTaskStackChanged(); 1370 } 1371 } 1372 getUriPermissionsLocked()1373 UriPermissionOwner getUriPermissionsLocked() { 1374 if (uriPermissions == null) { 1375 uriPermissions = new UriPermissionOwner(service, this); 1376 } 1377 return uriPermissions; 1378 } 1379 addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, Intent resultData)1380 void addResultLocked(ActivityRecord from, String resultWho, 1381 int requestCode, int resultCode, 1382 Intent resultData) { 1383 ActivityResult r = new ActivityResult(from, resultWho, 1384 requestCode, resultCode, resultData); 1385 if (results == null) { 1386 results = new ArrayList<ResultInfo>(); 1387 } 1388 results.add(r); 1389 } 1390 removeResultsLocked(ActivityRecord from, String resultWho, int requestCode)1391 void removeResultsLocked(ActivityRecord from, String resultWho, 1392 int requestCode) { 1393 if (results != null) { 1394 for (int i=results.size()-1; i>=0; i--) { 1395 ActivityResult r = (ActivityResult)results.get(i); 1396 if (r.mFrom != from) continue; 1397 if (r.mResultWho == null) { 1398 if (resultWho != null) continue; 1399 } else { 1400 if (!r.mResultWho.equals(resultWho)) continue; 1401 } 1402 if (r.mRequestCode != requestCode) continue; 1403 1404 results.remove(i); 1405 } 1406 } 1407 } 1408 addNewIntentLocked(ReferrerIntent intent)1409 private void addNewIntentLocked(ReferrerIntent intent) { 1410 if (newIntents == null) { 1411 newIntents = new ArrayList<>(); 1412 } 1413 newIntents.add(intent); 1414 } 1415 isSleeping()1416 final boolean isSleeping() { 1417 final ActivityStack stack = getStack(); 1418 return stack != null ? stack.shouldSleepActivities() : service.isSleepingLocked(); 1419 } 1420 1421 /** 1422 * Deliver a new Intent to an existing activity, so that its onNewIntent() 1423 * method will be called at the proper time. 1424 */ deliverNewIntentLocked(int callingUid, Intent intent, String referrer)1425 final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) { 1426 // The activity now gets access to the data associated with this Intent. 1427 service.grantUriPermissionFromIntentLocked(callingUid, packageName, 1428 intent, getUriPermissionsLocked(), userId); 1429 final ReferrerIntent rintent = new ReferrerIntent(intent, referrer); 1430 boolean unsent = true; 1431 final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping(); 1432 1433 // We want to immediately deliver the intent to the activity if: 1434 // - It is currently resumed or paused. i.e. it is currently visible to the user and we want 1435 // the user to see the visual effects caused by the intent delivery now. 1436 // - The device is sleeping and it is the top activity behind the lock screen (b/6700897). 1437 if ((mState == RESUMED || mState == PAUSED 1438 || isTopActivityWhileSleeping) && app != null && app.thread != null) { 1439 try { 1440 ArrayList<ReferrerIntent> ar = new ArrayList<>(1); 1441 ar.add(rintent); 1442 service.getLifecycleManager().scheduleTransaction(app.thread, appToken, 1443 NewIntentItem.obtain(ar, mState == PAUSED)); 1444 unsent = false; 1445 } catch (RemoteException e) { 1446 Slog.w(TAG, "Exception thrown sending new intent to " + this, e); 1447 } catch (NullPointerException e) { 1448 Slog.w(TAG, "Exception thrown sending new intent to " + this, e); 1449 } 1450 } 1451 if (unsent) { 1452 addNewIntentLocked(rintent); 1453 } 1454 } 1455 updateOptionsLocked(ActivityOptions options)1456 void updateOptionsLocked(ActivityOptions options) { 1457 if (options != null) { 1458 if (pendingOptions != null) { 1459 pendingOptions.abort(); 1460 } 1461 pendingOptions = options; 1462 } 1463 } 1464 applyOptionsLocked()1465 void applyOptionsLocked() { 1466 if (pendingOptions != null 1467 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) { 1468 final int animationType = pendingOptions.getAnimationType(); 1469 switch (animationType) { 1470 case ANIM_CUSTOM: 1471 service.mWindowManager.overridePendingAppTransition( 1472 pendingOptions.getPackageName(), 1473 pendingOptions.getCustomEnterResId(), 1474 pendingOptions.getCustomExitResId(), 1475 pendingOptions.getOnAnimationStartListener()); 1476 break; 1477 case ANIM_CLIP_REVEAL: 1478 service.mWindowManager.overridePendingAppTransitionClipReveal( 1479 pendingOptions.getStartX(), pendingOptions.getStartY(), 1480 pendingOptions.getWidth(), pendingOptions.getHeight()); 1481 if (intent.getSourceBounds() == null) { 1482 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 1483 pendingOptions.getStartY(), 1484 pendingOptions.getStartX()+pendingOptions.getWidth(), 1485 pendingOptions.getStartY()+pendingOptions.getHeight())); 1486 } 1487 break; 1488 case ANIM_SCALE_UP: 1489 service.mWindowManager.overridePendingAppTransitionScaleUp( 1490 pendingOptions.getStartX(), pendingOptions.getStartY(), 1491 pendingOptions.getWidth(), pendingOptions.getHeight()); 1492 if (intent.getSourceBounds() == null) { 1493 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 1494 pendingOptions.getStartY(), 1495 pendingOptions.getStartX()+pendingOptions.getWidth(), 1496 pendingOptions.getStartY()+pendingOptions.getHeight())); 1497 } 1498 break; 1499 case ANIM_THUMBNAIL_SCALE_UP: 1500 case ANIM_THUMBNAIL_SCALE_DOWN: 1501 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP); 1502 final GraphicBuffer buffer = pendingOptions.getThumbnail(); 1503 service.mWindowManager.overridePendingAppTransitionThumb(buffer, 1504 pendingOptions.getStartX(), pendingOptions.getStartY(), 1505 pendingOptions.getOnAnimationStartListener(), 1506 scaleUp); 1507 if (intent.getSourceBounds() == null && buffer != null) { 1508 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 1509 pendingOptions.getStartY(), 1510 pendingOptions.getStartX() + buffer.getWidth(), 1511 pendingOptions.getStartY() + buffer.getHeight())); 1512 } 1513 break; 1514 case ANIM_THUMBNAIL_ASPECT_SCALE_UP: 1515 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: 1516 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs(); 1517 final IAppTransitionAnimationSpecsFuture specsFuture = 1518 pendingOptions.getSpecsFuture(); 1519 if (specsFuture != null) { 1520 service.mWindowManager.overridePendingAppTransitionMultiThumbFuture( 1521 specsFuture, pendingOptions.getOnAnimationStartListener(), 1522 animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP); 1523 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN 1524 && specs != null) { 1525 service.mWindowManager.overridePendingAppTransitionMultiThumb( 1526 specs, pendingOptions.getOnAnimationStartListener(), 1527 pendingOptions.getAnimationFinishedListener(), false); 1528 } else { 1529 service.mWindowManager.overridePendingAppTransitionAspectScaledThumb( 1530 pendingOptions.getThumbnail(), 1531 pendingOptions.getStartX(), pendingOptions.getStartY(), 1532 pendingOptions.getWidth(), pendingOptions.getHeight(), 1533 pendingOptions.getOnAnimationStartListener(), 1534 (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP)); 1535 if (intent.getSourceBounds() == null) { 1536 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 1537 pendingOptions.getStartY(), 1538 pendingOptions.getStartX() + pendingOptions.getWidth(), 1539 pendingOptions.getStartY() + pendingOptions.getHeight())); 1540 } 1541 } 1542 break; 1543 case ANIM_OPEN_CROSS_PROFILE_APPS: 1544 service.mWindowManager.overridePendingAppTransitionStartCrossProfileApps(); 1545 break; 1546 case ANIM_REMOTE_ANIMATION: 1547 service.mWindowManager.overridePendingAppTransitionRemote( 1548 pendingOptions.getRemoteAnimationAdapter()); 1549 break; 1550 default: 1551 Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType); 1552 break; 1553 } 1554 1555 if (task == null) { 1556 clearOptionsLocked(false /* withAbort */); 1557 } else { 1558 // This will clear the options for all the ActivityRecords for this Task. 1559 task.clearAllPendingOptions(); 1560 } 1561 } 1562 } 1563 getOptionsForTargetActivityLocked()1564 ActivityOptions getOptionsForTargetActivityLocked() { 1565 return pendingOptions != null ? pendingOptions.forTargetActivity() : null; 1566 } 1567 clearOptionsLocked()1568 void clearOptionsLocked() { 1569 clearOptionsLocked(true /* withAbort */); 1570 } 1571 clearOptionsLocked(boolean withAbort)1572 void clearOptionsLocked(boolean withAbort) { 1573 if (withAbort && pendingOptions != null) { 1574 pendingOptions.abort(); 1575 } 1576 pendingOptions = null; 1577 } 1578 takeOptionsLocked()1579 ActivityOptions takeOptionsLocked() { 1580 ActivityOptions opts = pendingOptions; 1581 pendingOptions = null; 1582 return opts; 1583 } 1584 removeUriPermissionsLocked()1585 void removeUriPermissionsLocked() { 1586 if (uriPermissions != null) { 1587 uriPermissions.removeUriPermissionsLocked(); 1588 uriPermissions = null; 1589 } 1590 } 1591 pauseKeyDispatchingLocked()1592 void pauseKeyDispatchingLocked() { 1593 if (!keysPaused) { 1594 keysPaused = true; 1595 1596 if (mWindowContainerController != null) { 1597 mWindowContainerController.pauseKeyDispatching(); 1598 } 1599 } 1600 } 1601 resumeKeyDispatchingLocked()1602 void resumeKeyDispatchingLocked() { 1603 if (keysPaused) { 1604 keysPaused = false; 1605 1606 if (mWindowContainerController != null) { 1607 mWindowContainerController.resumeKeyDispatching(); 1608 } 1609 } 1610 } 1611 updateTaskDescription(CharSequence description)1612 private void updateTaskDescription(CharSequence description) { 1613 task.lastDescription = description; 1614 } 1615 setDeferHidingClient(boolean deferHidingClient)1616 void setDeferHidingClient(boolean deferHidingClient) { 1617 if (mDeferHidingClient == deferHidingClient) { 1618 return; 1619 } 1620 mDeferHidingClient = deferHidingClient; 1621 if (!mDeferHidingClient && !visible) { 1622 // Hiding the client is no longer deferred and the app isn't visible still, go ahead and 1623 // update the visibility. 1624 setVisibility(false); 1625 } 1626 } 1627 setVisibility(boolean visible)1628 void setVisibility(boolean visible) { 1629 mWindowContainerController.setVisibility(visible, mDeferHidingClient); 1630 mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this); 1631 } 1632 1633 // TODO: Look into merging with #setVisibility() setVisible(boolean newVisible)1634 void setVisible(boolean newVisible) { 1635 visible = newVisible; 1636 mDeferHidingClient = !visible && mDeferHidingClient; 1637 setVisibility(visible); 1638 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true; 1639 } 1640 setState(ActivityState state, String reason)1641 void setState(ActivityState state, String reason) { 1642 if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState() 1643 + " to:" + state + " reason:" + reason); 1644 1645 if (state == mState) { 1646 // No need to do anything if state doesn't change. 1647 if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state); 1648 return; 1649 } 1650 1651 mState = state; 1652 1653 final TaskRecord parent = getTask(); 1654 1655 if (parent != null) { 1656 parent.onActivityStateChanged(this, state, reason); 1657 } 1658 1659 // The WindowManager interprets the app stopping signal as 1660 // an indication that the Surface will eventually be destroyed. 1661 // This however isn't necessarily true if we are going to sleep. 1662 if (state == STOPPING && !isSleeping()) { 1663 mWindowContainerController.notifyAppStopping(); 1664 } 1665 } 1666 getState()1667 ActivityState getState() { 1668 return mState; 1669 } 1670 1671 /** 1672 * Returns {@code true} if the Activity is in the specified state. 1673 */ isState(ActivityState state)1674 boolean isState(ActivityState state) { 1675 return state == mState; 1676 } 1677 1678 /** 1679 * Returns {@code true} if the Activity is in one of the specified states. 1680 */ isState(ActivityState state1, ActivityState state2)1681 boolean isState(ActivityState state1, ActivityState state2) { 1682 return state1 == mState || state2 == mState; 1683 } 1684 1685 /** 1686 * Returns {@code true} if the Activity is in one of the specified states. 1687 */ isState(ActivityState state1, ActivityState state2, ActivityState state3)1688 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3) { 1689 return state1 == mState || state2 == mState || state3 == mState; 1690 } 1691 1692 /** 1693 * Returns {@code true} if the Activity is in one of the specified states. 1694 */ isState(ActivityState state1, ActivityState state2, ActivityState state3, ActivityState state4)1695 boolean isState(ActivityState state1, ActivityState state2, ActivityState state3, 1696 ActivityState state4) { 1697 return state1 == mState || state2 == mState || state3 == mState || state4 == mState; 1698 } 1699 notifyAppResumed(boolean wasStopped)1700 void notifyAppResumed(boolean wasStopped) { 1701 mWindowContainerController.notifyAppResumed(wasStopped); 1702 } 1703 notifyUnknownVisibilityLaunched()1704 void notifyUnknownVisibilityLaunched() { 1705 1706 // No display activities never add a window, so there is no point in waiting them for 1707 // relayout. 1708 if (!noDisplay) { 1709 mWindowContainerController.notifyUnknownVisibilityLaunched(); 1710 } 1711 } 1712 1713 /** 1714 * @return true if the input activity should be made visible, ignoring any effect Keyguard 1715 * might have on the visibility 1716 * 1717 * @see {@link ActivityStack#checkKeyguardVisibility} 1718 */ shouldBeVisibleIgnoringKeyguard(boolean behindFullscreenActivity)1719 boolean shouldBeVisibleIgnoringKeyguard(boolean behindFullscreenActivity) { 1720 if (!okToShowLocked()) { 1721 return false; 1722 } 1723 1724 return !behindFullscreenActivity || mLaunchTaskBehind; 1725 } 1726 makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient)1727 void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) { 1728 // This activity is not currently visible, but is running. Tell it to become visible. 1729 if (mState == RESUMED || this == starting) { 1730 if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, 1731 "Not making visible, r=" + this + " state=" + mState + " starting=" + starting); 1732 return; 1733 } 1734 1735 // If this activity is paused, tell it to now show its window. 1736 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1737 "Making visible and scheduling visibility: " + this); 1738 final ActivityStack stack = getStack(); 1739 try { 1740 if (stack.mTranslucentActivityWaiting != null) { 1741 updateOptionsLocked(returningOptions); 1742 stack.mUndrawnActivitiesBelowTopTranslucent.add(this); 1743 } 1744 setVisible(true); 1745 sleeping = false; 1746 app.pendingUiClean = true; 1747 if (reportToClient) { 1748 makeClientVisible(); 1749 } else { 1750 mClientVisibilityDeferred = true; 1751 } 1752 // The activity may be waiting for stop, but that is no longer appropriate for it. 1753 mStackSupervisor.mStoppingActivities.remove(this); 1754 mStackSupervisor.mGoingToSleepActivities.remove(this); 1755 } catch (Exception e) { 1756 // Just skip on any failure; we'll make it visible when it next restarts. 1757 Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e); 1758 } 1759 handleAlreadyVisible(); 1760 } 1761 1762 /** Send visibility change message to the client and pause if needed. */ makeClientVisible()1763 void makeClientVisible() { 1764 mClientVisibilityDeferred = false; 1765 try { 1766 service.getLifecycleManager().scheduleTransaction(app.thread, appToken, 1767 WindowVisibilityItem.obtain(true /* showWindow */)); 1768 if (shouldPauseWhenBecomingVisible()) { 1769 // An activity must be in the {@link PAUSING} state for the system to validate 1770 // the move to {@link PAUSED}. 1771 setState(PAUSING, "makeVisibleIfNeeded"); 1772 service.getLifecycleManager().scheduleTransaction(app.thread, appToken, 1773 PauseActivityItem.obtain(finishing, false /* userLeaving */, 1774 configChangeFlags, false /* dontReport */)); 1775 } 1776 } catch (Exception e) { 1777 Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e); 1778 } 1779 } 1780 1781 /** Check if activity should be moved to PAUSED state when it becomes visible. */ shouldPauseWhenBecomingVisible()1782 private boolean shouldPauseWhenBecomingVisible() { 1783 // If the activity is stopped or stopping, cycle to the paused state. We avoid doing 1784 // this when there is an activity waiting to become translucent as the extra binder 1785 // calls will lead to noticeable jank. A later call to 1786 // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to the proper 1787 // paused state. We also avoid doing this for the activity the stack supervisor 1788 // considers the resumed activity, as normal means will bring the activity from STOPPED 1789 // to RESUMED. Adding PAUSING in this scenario will lead to double lifecycles. 1790 if (!isState(STOPPED, STOPPING) || getStack().mTranslucentActivityWaiting != null 1791 || mStackSupervisor.getResumedActivityLocked() == this) { 1792 return false; 1793 } 1794 1795 // Check if position in task allows to become paused 1796 final int positionInTask = task.mActivities.indexOf(this); 1797 if (positionInTask == -1) { 1798 throw new IllegalStateException("Activity not found in its task"); 1799 } 1800 if (positionInTask == task.mActivities.size() - 1) { 1801 // It's the topmost activity in the task - should become paused now 1802 return true; 1803 } 1804 // Check if activity above is finishing now and this one becomes the topmost in task. 1805 final ActivityRecord activityAbove = task.mActivities.get(positionInTask + 1); 1806 if (activityAbove.finishing && results == null) { 1807 // We will only allow pausing if activity above wasn't launched for result. Otherwise it 1808 // will cause this activity to resume before getting result. 1809 return true; 1810 } 1811 return false; 1812 } 1813 handleAlreadyVisible()1814 boolean handleAlreadyVisible() { 1815 stopFreezingScreenLocked(false); 1816 try { 1817 if (returningOptions != null) { 1818 app.thread.scheduleOnNewActivityOptions(appToken, returningOptions.toBundle()); 1819 } 1820 } catch(RemoteException e) { 1821 } 1822 return mState == RESUMED; 1823 } 1824 activityResumedLocked(IBinder token)1825 static void activityResumedLocked(IBinder token) { 1826 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1827 if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r); 1828 if (r != null) { 1829 r.icicle = null; 1830 r.haveState = false; 1831 } 1832 } 1833 1834 /** 1835 * Once we know that we have asked an application to put an activity in the resumed state 1836 * (either by launching it or explicitly telling it), this function updates the rest of our 1837 * state to match that fact. 1838 */ completeResumeLocked()1839 void completeResumeLocked() { 1840 final boolean wasVisible = visible; 1841 setVisible(true); 1842 if (!wasVisible) { 1843 // Visibility has changed, so take a note of it so we call the TaskStackChangedListener 1844 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true; 1845 } 1846 idle = false; 1847 results = null; 1848 newIntents = null; 1849 stopped = false; 1850 1851 if (isActivityTypeHome()) { 1852 ProcessRecord app = task.mActivities.get(0).app; 1853 if (app != null && app != service.mHomeProcess) { 1854 service.mHomeProcess = app; 1855 } 1856 } 1857 1858 if (nowVisible) { 1859 // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now. 1860 mStackSupervisor.reportActivityVisibleLocked(this); 1861 } 1862 1863 // Schedule an idle timeout in case the app doesn't do it for us. 1864 mStackSupervisor.scheduleIdleTimeoutLocked(this); 1865 1866 mStackSupervisor.reportResumedActivityLocked(this); 1867 1868 resumeKeyDispatchingLocked(); 1869 final ActivityStack stack = getStack(); 1870 mStackSupervisor.mNoAnimActivities.clear(); 1871 1872 // Mark the point when the activity is resuming 1873 // TODO: To be more accurate, the mark should be before the onCreate, 1874 // not after the onResume. But for subsequent starts, onResume is fine. 1875 if (app != null) { 1876 cpuTimeAtResume = service.mProcessCpuTracker.getCpuTimeForPid(app.pid); 1877 } else { 1878 cpuTimeAtResume = 0; // Couldn't get the cpu time of process 1879 } 1880 1881 returningOptions = null; 1882 1883 if (canTurnScreenOn()) { 1884 mStackSupervisor.wakeUp("turnScreenOnFlag"); 1885 } else { 1886 // If the screen is going to turn on because the caller explicitly requested it and 1887 // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will 1888 // pause and then resume again later, which will result in a double life-cycle event. 1889 stack.checkReadyForSleep(); 1890 } 1891 } 1892 activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState, CharSequence description)1893 final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState, 1894 CharSequence description) { 1895 final ActivityStack stack = getStack(); 1896 if (mState != STOPPING) { 1897 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this); 1898 stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this); 1899 return; 1900 } 1901 if (newPersistentState != null) { 1902 persistentState = newPersistentState; 1903 service.notifyTaskPersisterLocked(task, false); 1904 } 1905 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + icicle); 1906 1907 if (newIcicle != null) { 1908 // If icicle is null, this is happening due to a timeout, so we haven't really saved 1909 // the state. 1910 icicle = newIcicle; 1911 haveState = true; 1912 launchCount = 0; 1913 updateTaskDescription(description); 1914 } 1915 if (!stopped) { 1916 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)"); 1917 stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this); 1918 stopped = true; 1919 setState(STOPPED, "activityStoppedLocked"); 1920 1921 mWindowContainerController.notifyAppStopped(); 1922 1923 if (finishing) { 1924 clearOptionsLocked(); 1925 } else { 1926 if (deferRelaunchUntilPaused) { 1927 stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config"); 1928 mStackSupervisor.resumeFocusedStackTopActivityLocked(); 1929 } else { 1930 mStackSupervisor.updatePreviousProcessLocked(this); 1931 } 1932 } 1933 } 1934 } 1935 startLaunchTickingLocked()1936 void startLaunchTickingLocked() { 1937 if (Build.IS_USER) { 1938 return; 1939 } 1940 if (launchTickTime == 0) { 1941 launchTickTime = SystemClock.uptimeMillis(); 1942 continueLaunchTickingLocked(); 1943 } 1944 } 1945 continueLaunchTickingLocked()1946 boolean continueLaunchTickingLocked() { 1947 if (launchTickTime == 0) { 1948 return false; 1949 } 1950 1951 final ActivityStack stack = getStack(); 1952 if (stack == null) { 1953 return false; 1954 } 1955 1956 Message msg = stack.mHandler.obtainMessage(LAUNCH_TICK_MSG, this); 1957 stack.mHandler.removeMessages(LAUNCH_TICK_MSG); 1958 stack.mHandler.sendMessageDelayed(msg, LAUNCH_TICK); 1959 return true; 1960 } 1961 finishLaunchTickingLocked()1962 void finishLaunchTickingLocked() { 1963 launchTickTime = 0; 1964 final ActivityStack stack = getStack(); 1965 if (stack != null) { 1966 stack.mHandler.removeMessages(LAUNCH_TICK_MSG); 1967 } 1968 } 1969 1970 // IApplicationToken 1971 mayFreezeScreenLocked(ProcessRecord app)1972 public boolean mayFreezeScreenLocked(ProcessRecord app) { 1973 // Only freeze the screen if this activity is currently attached to 1974 // an application, and that application is not blocked or unresponding. 1975 // In any other case, we can't count on getting the screen unfrozen, 1976 // so it is best to leave as-is. 1977 return app != null && !app.crashing && !app.notResponding; 1978 } 1979 startFreezingScreenLocked(ProcessRecord app, int configChanges)1980 public void startFreezingScreenLocked(ProcessRecord app, int configChanges) { 1981 if (mayFreezeScreenLocked(app)) { 1982 mWindowContainerController.startFreezingScreen(configChanges); 1983 } 1984 } 1985 stopFreezingScreenLocked(boolean force)1986 public void stopFreezingScreenLocked(boolean force) { 1987 if (force || frozenBeforeDestroy) { 1988 frozenBeforeDestroy = false; 1989 mWindowContainerController.stopFreezingScreen(force); 1990 } 1991 } 1992 reportFullyDrawnLocked(boolean restoredFromBundle)1993 public void reportFullyDrawnLocked(boolean restoredFromBundle) { 1994 final long curTime = SystemClock.uptimeMillis(); 1995 if (displayStartTime != 0) { 1996 reportLaunchTimeLocked(curTime); 1997 } 1998 final LaunchTimeTracker.Entry entry = mStackSupervisor.getLaunchTimeTracker().getEntry( 1999 getWindowingMode()); 2000 if (fullyDrawnStartTime != 0 && entry != null) { 2001 final long thisTime = curTime - fullyDrawnStartTime; 2002 final long totalTime = entry.mFullyDrawnStartTime != 0 2003 ? (curTime - entry.mFullyDrawnStartTime) : thisTime; 2004 if (SHOW_ACTIVITY_START_TIME) { 2005 Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0); 2006 EventLog.writeEvent(AM_ACTIVITY_FULLY_DRAWN_TIME, 2007 userId, System.identityHashCode(this), shortComponentName, 2008 thisTime, totalTime); 2009 StringBuilder sb = service.mStringBuilder; 2010 sb.setLength(0); 2011 sb.append("Fully drawn "); 2012 sb.append(shortComponentName); 2013 sb.append(": "); 2014 TimeUtils.formatDuration(thisTime, sb); 2015 if (thisTime != totalTime) { 2016 sb.append(" (total "); 2017 TimeUtils.formatDuration(totalTime, sb); 2018 sb.append(")"); 2019 } 2020 Log.i(TAG, sb.toString()); 2021 } 2022 if (totalTime > 0) { 2023 //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime); 2024 } 2025 entry.mFullyDrawnStartTime = 0; 2026 } 2027 mStackSupervisor.getActivityMetricsLogger().logAppTransitionReportedDrawn(this, 2028 restoredFromBundle); 2029 fullyDrawnStartTime = 0; 2030 } 2031 reportLaunchTimeLocked(final long curTime)2032 private void reportLaunchTimeLocked(final long curTime) { 2033 final LaunchTimeTracker.Entry entry = mStackSupervisor.getLaunchTimeTracker().getEntry( 2034 getWindowingMode()); 2035 if (entry == null) { 2036 return; 2037 } 2038 final long thisTime = curTime - displayStartTime; 2039 final long totalTime = entry.mLaunchStartTime != 0 2040 ? (curTime - entry.mLaunchStartTime) : thisTime; 2041 if (SHOW_ACTIVITY_START_TIME) { 2042 Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0); 2043 EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME, 2044 userId, System.identityHashCode(this), shortComponentName, 2045 thisTime, totalTime); 2046 StringBuilder sb = service.mStringBuilder; 2047 sb.setLength(0); 2048 sb.append("Displayed "); 2049 sb.append(shortComponentName); 2050 sb.append(": "); 2051 TimeUtils.formatDuration(thisTime, sb); 2052 if (thisTime != totalTime) { 2053 sb.append(" (total "); 2054 TimeUtils.formatDuration(totalTime, sb); 2055 sb.append(")"); 2056 } 2057 Log.i(TAG, sb.toString()); 2058 } 2059 mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime); 2060 if (totalTime > 0) { 2061 //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime); 2062 } 2063 displayStartTime = 0; 2064 entry.mLaunchStartTime = 0; 2065 } 2066 2067 @Override onStartingWindowDrawn(long timestamp)2068 public void onStartingWindowDrawn(long timestamp) { 2069 synchronized (service) { 2070 mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn( 2071 getWindowingMode(), timestamp); 2072 } 2073 } 2074 2075 @Override onWindowsDrawn(long timestamp)2076 public void onWindowsDrawn(long timestamp) { 2077 synchronized (service) { 2078 mStackSupervisor.getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), 2079 timestamp); 2080 if (displayStartTime != 0) { 2081 reportLaunchTimeLocked(timestamp); 2082 } 2083 mStackSupervisor.sendWaitingVisibleReportLocked(this); 2084 startTime = 0; 2085 finishLaunchTickingLocked(); 2086 if (task != null) { 2087 task.hasBeenVisible = true; 2088 } 2089 } 2090 } 2091 2092 @Override onWindowsVisible()2093 public void onWindowsVisible() { 2094 synchronized (service) { 2095 mStackSupervisor.reportActivityVisibleLocked(this); 2096 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this); 2097 if (!nowVisible) { 2098 nowVisible = true; 2099 lastVisibleTime = SystemClock.uptimeMillis(); 2100 if (idle || mStackSupervisor.isStoppingNoHistoryActivity()) { 2101 // If this activity was already idle or there is an activity that must be 2102 // stopped immediately after visible, then we now need to make sure we perform 2103 // the full stop of any activities that are waiting to do so. This is because 2104 // we won't do that while they are still waiting for this one to become visible. 2105 final int size = mStackSupervisor.mActivitiesWaitingForVisibleActivity.size(); 2106 if (size > 0) { 2107 for (int i = 0; i < size; i++) { 2108 final ActivityRecord r = 2109 mStackSupervisor.mActivitiesWaitingForVisibleActivity.get(i); 2110 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r); 2111 } 2112 mStackSupervisor.mActivitiesWaitingForVisibleActivity.clear(); 2113 mStackSupervisor.scheduleIdleLocked(); 2114 } 2115 } else { 2116 // Instead of doing the full stop routine here, let's just hide any activities 2117 // we now can, and let them stop when the normal idle happens. 2118 mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */, 2119 false /* remove */, true /* processPausingActivities */); 2120 } 2121 service.scheduleAppGcsLocked(); 2122 } 2123 } 2124 } 2125 2126 @Override onWindowsGone()2127 public void onWindowsGone() { 2128 synchronized (service) { 2129 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this); 2130 nowVisible = false; 2131 } 2132 } 2133 2134 @Override keyDispatchingTimedOut(String reason, int windowPid)2135 public boolean keyDispatchingTimedOut(String reason, int windowPid) { 2136 ActivityRecord anrActivity; 2137 ProcessRecord anrApp; 2138 boolean windowFromSameProcessAsActivity; 2139 synchronized (service) { 2140 anrActivity = getWaitingHistoryRecordLocked(); 2141 anrApp = app; 2142 windowFromSameProcessAsActivity = 2143 app == null || app.pid == windowPid || windowPid == -1; 2144 } 2145 if (windowFromSameProcessAsActivity) { 2146 return service.inputDispatchingTimedOut(anrApp, anrActivity, this, false, reason); 2147 } else { 2148 // In this case another process added windows using this activity token. So, we call the 2149 // generic service input dispatch timed out method so that the right process is blamed. 2150 return service.inputDispatchingTimedOut(windowPid, false /* aboveSystem */, reason) < 0; 2151 } 2152 } 2153 getWaitingHistoryRecordLocked()2154 private ActivityRecord getWaitingHistoryRecordLocked() { 2155 // First find the real culprit... if this activity is waiting for 2156 // another activity to start or has stopped, then the key dispatching 2157 // timeout should not be caused by this. 2158 if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) { 2159 final ActivityStack stack = mStackSupervisor.getFocusedStack(); 2160 // Try to use the one which is closest to top. 2161 ActivityRecord r = stack.getResumedActivity(); 2162 if (r == null) { 2163 r = stack.mPausingActivity; 2164 } 2165 if (r != null) { 2166 return r; 2167 } 2168 } 2169 return this; 2170 } 2171 2172 /** Checks whether the activity should be shown for current user. */ okToShowLocked()2173 public boolean okToShowLocked() { 2174 // We cannot show activities when the device is locked and the application is not 2175 // encryption aware. 2176 if (!StorageManager.isUserKeyUnlocked(userId) 2177 && !info.applicationInfo.isEncryptionAware()) { 2178 return false; 2179 } 2180 2181 return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 2182 || (mStackSupervisor.isCurrentProfileLocked(userId) 2183 && service.mUserController.isUserRunning(userId, 0 /* flags */)); 2184 } 2185 2186 /** 2187 * This method will return true if the activity is either visible, is becoming visible, is 2188 * currently pausing, or is resumed. 2189 */ isInterestingToUserLocked()2190 public boolean isInterestingToUserLocked() { 2191 return visible || nowVisible || mState == PAUSING || mState == RESUMED; 2192 } 2193 setSleeping(boolean _sleeping)2194 void setSleeping(boolean _sleeping) { 2195 setSleeping(_sleeping, false); 2196 } 2197 setSleeping(boolean _sleeping, boolean force)2198 void setSleeping(boolean _sleeping, boolean force) { 2199 if (!force && sleeping == _sleeping) { 2200 return; 2201 } 2202 if (app != null && app.thread != null) { 2203 try { 2204 app.thread.scheduleSleeping(appToken, _sleeping); 2205 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) { 2206 mStackSupervisor.mGoingToSleepActivities.add(this); 2207 } 2208 sleeping = _sleeping; 2209 } catch (RemoteException e) { 2210 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e); 2211 } 2212 } 2213 } 2214 getTaskForActivityLocked(IBinder token, boolean onlyRoot)2215 static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) { 2216 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 2217 if (r == null) { 2218 return INVALID_TASK_ID; 2219 } 2220 final TaskRecord task = r.task; 2221 final int activityNdx = task.mActivities.indexOf(r); 2222 if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) { 2223 return INVALID_TASK_ID; 2224 } 2225 return task.taskId; 2226 } 2227 isInStackLocked(IBinder token)2228 static ActivityRecord isInStackLocked(IBinder token) { 2229 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 2230 return (r != null) ? r.getStack().isInStackLocked(r) : null; 2231 } 2232 getStackLocked(IBinder token)2233 static ActivityStack getStackLocked(IBinder token) { 2234 final ActivityRecord r = ActivityRecord.isInStackLocked(token); 2235 if (r != null) { 2236 return r.getStack(); 2237 } 2238 return null; 2239 } 2240 2241 /** 2242 * @return display id to which this record is attached, -1 if not attached. 2243 */ getDisplayId()2244 int getDisplayId() { 2245 final ActivityStack stack = getStack(); 2246 if (stack == null) { 2247 return -1; 2248 } 2249 return stack.mDisplayId; 2250 } 2251 isDestroyable()2252 final boolean isDestroyable() { 2253 if (finishing || app == null) { 2254 // This would be redundant. 2255 return false; 2256 } 2257 final ActivityStack stack = getStack(); 2258 if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity 2259 || !haveState || !stopped) { 2260 // We're not ready for this kind of thing. 2261 return false; 2262 } 2263 if (visible) { 2264 // The user would notice this! 2265 return false; 2266 } 2267 return true; 2268 } 2269 createImageFilename(long createTime, int taskId)2270 private static String createImageFilename(long createTime, int taskId) { 2271 return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime + 2272 IMAGE_EXTENSION; 2273 } 2274 setTaskDescription(TaskDescription _taskDescription)2275 void setTaskDescription(TaskDescription _taskDescription) { 2276 Bitmap icon; 2277 if (_taskDescription.getIconFilename() == null && 2278 (icon = _taskDescription.getIcon()) != null) { 2279 final String iconFilename = createImageFilename(createTime, task.taskId); 2280 final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId), 2281 iconFilename); 2282 final String iconFilePath = iconFile.getAbsolutePath(); 2283 service.getRecentTasks().saveImage(icon, iconFilePath); 2284 _taskDescription.setIconFilename(iconFilePath); 2285 } 2286 taskDescription = _taskDescription; 2287 } 2288 setVoiceSessionLocked(IVoiceInteractionSession session)2289 void setVoiceSessionLocked(IVoiceInteractionSession session) { 2290 voiceSession = session; 2291 pendingVoiceInteractionStart = false; 2292 } 2293 clearVoiceSessionLocked()2294 void clearVoiceSessionLocked() { 2295 voiceSession = null; 2296 pendingVoiceInteractionStart = false; 2297 } 2298 showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch)2299 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) { 2300 showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */); 2301 } 2302 showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch, boolean fromRecents)2303 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch, 2304 boolean fromRecents) { 2305 if (mWindowContainerController == null) { 2306 return; 2307 } 2308 if (mTaskOverlay) { 2309 // We don't show starting window for overlay activities. 2310 return; 2311 } 2312 2313 final CompatibilityInfo compatInfo = 2314 service.compatibilityInfoForPackageLocked(info.applicationInfo); 2315 final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme, 2316 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags, 2317 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(), 2318 allowTaskSnapshot(), 2319 mState.ordinal() >= RESUMED.ordinal() && mState.ordinal() <= STOPPED.ordinal(), 2320 fromRecents); 2321 if (shown) { 2322 mStartingWindowState = STARTING_WINDOW_SHOWN; 2323 } 2324 } 2325 removeOrphanedStartingWindow(boolean behindFullscreenActivity)2326 void removeOrphanedStartingWindow(boolean behindFullscreenActivity) { 2327 if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) { 2328 if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this); 2329 mStartingWindowState = STARTING_WINDOW_REMOVED; 2330 mWindowContainerController.removeStartingWindow(); 2331 } 2332 } 2333 getRequestedOrientation()2334 int getRequestedOrientation() { 2335 return mWindowContainerController.getOrientation(); 2336 } 2337 setRequestedOrientation(int requestedOrientation)2338 void setRequestedOrientation(int requestedOrientation) { 2339 final int displayId = getDisplayId(); 2340 final Configuration displayConfig = 2341 mStackSupervisor.getDisplayOverrideConfiguration(displayId); 2342 2343 final Configuration config = mWindowContainerController.setOrientation(requestedOrientation, 2344 displayId, displayConfig, mayFreezeScreenLocked(app)); 2345 if (config != null) { 2346 frozenBeforeDestroy = true; 2347 if (!service.updateDisplayOverrideConfigurationLocked(config, this, 2348 false /* deferResume */, displayId)) { 2349 mStackSupervisor.resumeFocusedStackTopActivityLocked(); 2350 } 2351 } 2352 service.mTaskChangeNotificationController.notifyActivityRequestedOrientationChanged( 2353 task.taskId, requestedOrientation); 2354 } 2355 setDisablePreviewScreenshots(boolean disable)2356 void setDisablePreviewScreenshots(boolean disable) { 2357 mWindowContainerController.setDisablePreviewScreenshots(disable); 2358 } 2359 2360 /** 2361 * Set the last reported global configuration to the client. Should be called whenever a new 2362 * global configuration is sent to the client for this activity. 2363 */ setLastReportedGlobalConfiguration(@onNull Configuration config)2364 void setLastReportedGlobalConfiguration(@NonNull Configuration config) { 2365 mLastReportedConfiguration.setGlobalConfiguration(config); 2366 } 2367 2368 /** 2369 * Set the last reported configuration to the client. Should be called whenever 2370 * a new merged configuration is sent to the client for this activity. 2371 */ setLastReportedConfiguration(@onNull MergedConfiguration config)2372 void setLastReportedConfiguration(@NonNull MergedConfiguration config) { 2373 setLastReportedConfiguration(config.getGlobalConfiguration(), 2374 config.getOverrideConfiguration()); 2375 } 2376 setLastReportedConfiguration(Configuration global, Configuration override)2377 private void setLastReportedConfiguration(Configuration global, Configuration override) { 2378 mLastReportedConfiguration.setConfiguration(global, override); 2379 } 2380 2381 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. updateOverrideConfiguration()2382 private void updateOverrideConfiguration() { 2383 mTmpConfig.unset(); 2384 computeBounds(mTmpBounds); 2385 2386 if (mTmpBounds.equals(getOverrideBounds())) { 2387 return; 2388 } 2389 2390 setBounds(mTmpBounds); 2391 2392 final Rect updatedBounds = getOverrideBounds(); 2393 2394 // Bounds changed...update configuration to match. 2395 if (!matchParentBounds()) { 2396 task.computeOverrideConfiguration(mTmpConfig, updatedBounds, null /* insetBounds */, 2397 false /* overrideWidth */, false /* overrideHeight */); 2398 } 2399 2400 onOverrideConfigurationChanged(mTmpConfig); 2401 } 2402 2403 /** Returns true if the configuration is compatible with this activity. */ isConfigurationCompatible(Configuration config)2404 boolean isConfigurationCompatible(Configuration config) { 2405 final int orientation = mWindowContainerController != null 2406 ? mWindowContainerController.getOrientation() : info.screenOrientation; 2407 if (isFixedOrientationPortrait(orientation) 2408 && config.orientation != ORIENTATION_PORTRAIT) { 2409 return false; 2410 } 2411 if (isFixedOrientationLandscape(orientation) 2412 && config.orientation != ORIENTATION_LANDSCAPE) { 2413 return false; 2414 } 2415 return true; 2416 } 2417 2418 /** 2419 * Computes the bounds to fit the Activity within the bounds of the {@link Configuration}. 2420 */ 2421 // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. computeBounds(Rect outBounds)2422 private void computeBounds(Rect outBounds) { 2423 outBounds.setEmpty(); 2424 final float maxAspectRatio = info.maxAspectRatio; 2425 final ActivityStack stack = getStack(); 2426 if (task == null || stack == null || task.inMultiWindowMode() || maxAspectRatio == 0 2427 || isInVrUiMode(getConfiguration())) { 2428 // We don't set override configuration if that activity task isn't fullscreen. I.e. the 2429 // activity is in multi-window mode. Or, there isn't a max aspect ratio specified for 2430 // the activity. This is indicated by an empty {@link outBounds}. We also don't set it 2431 // if we are in VR mode. 2432 return; 2433 } 2434 2435 // We must base this on the parent configuration, because we set our override 2436 // configuration's appBounds based on the result of this method. If we used our own 2437 // configuration, it would be influenced by past invocations. 2438 final Rect appBounds = getParent().getWindowConfiguration().getAppBounds(); 2439 final int containingAppWidth = appBounds.width(); 2440 final int containingAppHeight = appBounds.height(); 2441 int maxActivityWidth = containingAppWidth; 2442 int maxActivityHeight = containingAppHeight; 2443 2444 if (containingAppWidth < containingAppHeight) { 2445 // Width is the shorter side, so we use that to figure-out what the max. height 2446 // should be given the aspect ratio. 2447 maxActivityHeight = (int) ((maxActivityWidth * maxAspectRatio) + 0.5f); 2448 } else { 2449 // Height is the shorter side, so we use that to figure-out what the max. width 2450 // should be given the aspect ratio. 2451 maxActivityWidth = (int) ((maxActivityHeight * maxAspectRatio) + 0.5f); 2452 } 2453 2454 if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) { 2455 // The display matches or is less than the activity aspect ratio, so nothing else to do. 2456 // Return the existing bounds. If this method is running for the first time, 2457 // {@link #getOverrideBounds()} will be empty (representing no override). If the method has run 2458 // before, then effect of {@link #getOverrideBounds()} will already have been applied to the 2459 // value returned from {@link getConfiguration}. Refer to 2460 // {@link TaskRecord#computeOverrideConfiguration}. 2461 outBounds.set(getOverrideBounds()); 2462 return; 2463 } 2464 2465 // Compute configuration based on max supported width and height. 2466 // Also account for the left / top insets (e.g. from display cutouts), which will be clipped 2467 // away later in StackWindowController.adjustConfigurationForBounds(). Otherwise, the app 2468 // bounds would end up too small. 2469 outBounds.set(0, 0, maxActivityWidth + appBounds.left, maxActivityHeight + appBounds.top); 2470 2471 if (service.mWindowManager.getNavBarPosition() == NAV_BAR_LEFT) { 2472 // Position the activity frame on the opposite side of the nav bar. 2473 outBounds.left = appBounds.right - maxActivityWidth; 2474 outBounds.right = appBounds.right; 2475 } 2476 } 2477 ensureActivityConfiguration(int globalChanges, boolean preserveWindow)2478 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) { 2479 return ensureActivityConfiguration(globalChanges, preserveWindow, 2480 false /* ignoreStopState */); 2481 } 2482 2483 /** 2484 * Make sure the given activity matches the current configuration. Ensures the HistoryRecord 2485 * is updated with the correct configuration and all other bookkeeping is handled. 2486 * 2487 * @param globalChanges The changes to the global configuration. 2488 * @param preserveWindow If the activity window should be preserved on screen if the activity 2489 * is relaunched. 2490 * @param ignoreStopState If we should try to relaunch the activity even if it is in the stopped 2491 * state. This is useful for the case where we know the activity will be 2492 * visible soon and we want to ensure its configuration before we make it 2493 * visible. 2494 * @return True if the activity was relaunched and false if it wasn't relaunched because we 2495 * can't or the app handles the specific configuration that is changing. 2496 */ ensureActivityConfiguration(int globalChanges, boolean preserveWindow, boolean ignoreStopState)2497 boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow, 2498 boolean ignoreStopState) { 2499 final ActivityStack stack = getStack(); 2500 if (stack.mConfigWillChange) { 2501 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2502 "Skipping config check (will change): " + this); 2503 return true; 2504 } 2505 2506 // We don't worry about activities that are finishing. 2507 if (finishing) { 2508 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2509 "Configuration doesn't matter in finishing " + this); 2510 stopFreezingScreenLocked(false); 2511 return true; 2512 } 2513 2514 if (!ignoreStopState && (mState == STOPPING || mState == STOPPED)) { 2515 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2516 "Skipping config check stopped or stopping: " + this); 2517 return true; 2518 } 2519 2520 // TODO: We should add ActivityRecord.shouldBeVisible() that checks if the activity should 2521 // be visible based on the stack, task, and lockscreen state and use that here instead. The 2522 // method should be based on the logic in ActivityStack.ensureActivitiesVisibleLocked(). 2523 // Skip updating configuration for activity is a stack that shouldn't be visible. 2524 if (!stack.shouldBeVisible(null /* starting */)) { 2525 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2526 "Skipping config check invisible stack: " + this); 2527 return true; 2528 } 2529 2530 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2531 "Ensuring correct configuration: " + this); 2532 2533 final int newDisplayId = getDisplayId(); 2534 final boolean displayChanged = mLastReportedDisplayId != newDisplayId; 2535 if (displayChanged) { 2536 mLastReportedDisplayId = newDisplayId; 2537 } 2538 // TODO(b/36505427): Is there a better place to do this? 2539 updateOverrideConfiguration(); 2540 2541 // Short circuit: if the two full configurations are equal (the common case), then there is 2542 // nothing to do. We test the full configuration instead of the global and merged override 2543 // configurations because there are cases (like moving a task to the pinned stack) where 2544 // the combine configurations are equal, but would otherwise differ in the override config 2545 mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration()); 2546 if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) { 2547 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2548 "Configuration & display unchanged in " + this); 2549 return true; 2550 } 2551 2552 // Okay we now are going to make this activity have the new config. 2553 // But then we need to figure out how it needs to deal with that. 2554 2555 // Find changes between last reported merged configuration and the current one. This is used 2556 // to decide whether to relaunch an activity or just report a configuration change. 2557 final int changes = getConfigurationChanges(mTmpConfig); 2558 2559 // Update last reported values. 2560 final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration(); 2561 2562 setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig); 2563 2564 if (mState == INITIALIZING) { 2565 // No need to relaunch or schedule new config for activity that hasn't been launched 2566 // yet. We do, however, return after applying the config to activity record, so that 2567 // it will use it for launch transaction. 2568 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2569 "Skipping config check for initializing activity: " + this); 2570 return true; 2571 } 2572 2573 if (changes == 0 && !forceNewConfig) { 2574 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2575 "Configuration no differences in " + this); 2576 // There are no significant differences, so we won't relaunch but should still deliver 2577 // the new configuration to the client process. 2578 if (displayChanged) { 2579 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig); 2580 } else { 2581 scheduleConfigurationChanged(newMergedOverrideConfig); 2582 } 2583 return true; 2584 } 2585 2586 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2587 "Configuration changes for " + this + ", allChanges=" 2588 + Configuration.configurationDiffToString(changes)); 2589 2590 // If the activity isn't currently running, just leave the new configuration and it will 2591 // pick that up next time it starts. 2592 if (app == null || app.thread == null) { 2593 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2594 "Configuration doesn't matter not running " + this); 2595 stopFreezingScreenLocked(false); 2596 forceNewConfig = false; 2597 return true; 2598 } 2599 2600 // Figure out how to handle the changes between the configurations. 2601 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2602 "Checking to restart " + info.name + ": changed=0x" 2603 + Integer.toHexString(changes) + ", handles=0x" 2604 + Integer.toHexString(info.getRealConfigChanged()) 2605 + ", mLastReportedConfiguration=" + mLastReportedConfiguration); 2606 2607 if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) { 2608 // Aha, the activity isn't handling the change, so DIE DIE DIE. 2609 configChangeFlags |= changes; 2610 startFreezingScreenLocked(app, globalChanges); 2611 forceNewConfig = false; 2612 preserveWindow &= isResizeOnlyChange(changes); 2613 if (app == null || app.thread == null) { 2614 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2615 "Config is destroying non-running " + this); 2616 stack.destroyActivityLocked(this, true, "config"); 2617 } else if (mState == PAUSING) { 2618 // A little annoying: we are waiting for this activity to finish pausing. Let's not 2619 // do anything now, but just flag that it needs to be restarted when done pausing. 2620 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2621 "Config is skipping already pausing " + this); 2622 deferRelaunchUntilPaused = true; 2623 preserveWindowOnDeferredRelaunch = preserveWindow; 2624 return true; 2625 } else if (mState == RESUMED) { 2626 // Try to optimize this case: the configuration is changing and we need to restart 2627 // the top, resumed activity. Instead of doing the normal handshaking, just say 2628 // "restart!". 2629 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2630 "Config is relaunching resumed " + this); 2631 2632 if (DEBUG_STATES && !visible) { 2633 Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this 2634 + " called by " + Debug.getCallers(4)); 2635 } 2636 2637 relaunchActivityLocked(true /* andResume */, preserveWindow); 2638 } else { 2639 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 2640 "Config is relaunching non-resumed " + this); 2641 relaunchActivityLocked(false /* andResume */, preserveWindow); 2642 } 2643 2644 // All done... tell the caller we weren't able to keep this activity around. 2645 return false; 2646 } 2647 2648 // Default case: the activity can handle this new configuration, so hand it over. 2649 // NOTE: We only forward the override configuration as the system level configuration 2650 // changes is always sent to all processes when they happen so it can just use whatever 2651 // system level configuration it last got. 2652 if (displayChanged) { 2653 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig); 2654 } else { 2655 scheduleConfigurationChanged(newMergedOverrideConfig); 2656 } 2657 stopFreezingScreenLocked(false); 2658 2659 return true; 2660 } 2661 2662 /** 2663 * When assessing a configuration change, decide if the changes flags and the new configurations 2664 * should cause the Activity to relaunch. 2665 * 2666 * @param changes the changes due to the given configuration. 2667 * @param changesConfig the configuration that was used to calculate the given changes via a 2668 * call to getConfigurationChanges. 2669 */ shouldRelaunchLocked(int changes, Configuration changesConfig)2670 private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) { 2671 int configChanged = info.getRealConfigChanged(); 2672 boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig); 2673 2674 // Override for apps targeting pre-O sdks 2675 // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode 2676 // to the config change. 2677 // For O and later, apps will be required to add configChanges="uimode" to their manifest. 2678 if (appInfo.targetSdkVersion < O 2679 && requestedVrComponent != null 2680 && onlyVrUiModeChanged) { 2681 configChanged |= CONFIG_UI_MODE; 2682 } 2683 2684 return (changes&(~configChanged)) != 0; 2685 } 2686 2687 /** 2688 * Returns true if the configuration change is solely due to the UI mode switching into or out 2689 * of UI_MODE_TYPE_VR_HEADSET. 2690 */ onlyVrUiModeChanged(int changes, Configuration lastReportedConfig)2691 private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) { 2692 final Configuration currentConfig = getConfiguration(); 2693 return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig) 2694 != isInVrUiMode(lastReportedConfig)); 2695 } 2696 getConfigurationChanges(Configuration lastReportedConfig)2697 private int getConfigurationChanges(Configuration lastReportedConfig) { 2698 // Determine what has changed. May be nothing, if this is a config that has come back from 2699 // the app after going idle. In that case we just want to leave the official config object 2700 // now in the activity and do nothing else. 2701 final Configuration currentConfig = getConfiguration(); 2702 int changes = lastReportedConfig.diff(currentConfig); 2703 // We don't want to use size changes if they don't cross boundaries that are important to 2704 // the app. 2705 if ((changes & CONFIG_SCREEN_SIZE) != 0) { 2706 final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp, 2707 currentConfig.screenWidthDp) 2708 || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp, 2709 currentConfig.screenHeightDp); 2710 if (!crosses) { 2711 changes &= ~CONFIG_SCREEN_SIZE; 2712 } 2713 } 2714 if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) { 2715 final int oldSmallest = lastReportedConfig.smallestScreenWidthDp; 2716 final int newSmallest = currentConfig.smallestScreenWidthDp; 2717 if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) { 2718 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE; 2719 } 2720 } 2721 // We don't want window configuration to cause relaunches. 2722 if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) { 2723 changes &= ~CONFIG_WINDOW_CONFIGURATION; 2724 } 2725 2726 return changes; 2727 } 2728 isResizeOnlyChange(int change)2729 private static boolean isResizeOnlyChange(int change) { 2730 return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION 2731 | CONFIG_SCREEN_LAYOUT)) == 0; 2732 } 2733 relaunchActivityLocked(boolean andResume, boolean preserveWindow)2734 void relaunchActivityLocked(boolean andResume, boolean preserveWindow) { 2735 if (service.mSuppressResizeConfigChanges && preserveWindow) { 2736 configChangeFlags = 0; 2737 return; 2738 } 2739 2740 List<ResultInfo> pendingResults = null; 2741 List<ReferrerIntent> pendingNewIntents = null; 2742 if (andResume) { 2743 pendingResults = results; 2744 pendingNewIntents = newIntents; 2745 } 2746 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 2747 "Relaunching: " + this + " with results=" + pendingResults 2748 + " newIntents=" + pendingNewIntents + " andResume=" + andResume 2749 + " preserveWindow=" + preserveWindow); 2750 EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY 2751 : AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this), 2752 task.taskId, shortComponentName); 2753 2754 startFreezingScreenLocked(app, 0); 2755 2756 try { 2757 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, 2758 "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this 2759 + " callers=" + Debug.getCallers(6)); 2760 forceNewConfig = false; 2761 mStackSupervisor.activityRelaunchingLocked(this); 2762 final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults, 2763 pendingNewIntents, configChangeFlags, 2764 new MergedConfiguration(service.getGlobalConfiguration(), 2765 getMergedOverrideConfiguration()), 2766 preserveWindow); 2767 final ActivityLifecycleItem lifecycleItem; 2768 if (andResume) { 2769 lifecycleItem = ResumeActivityItem.obtain(service.isNextTransitionForward()); 2770 } else { 2771 lifecycleItem = PauseActivityItem.obtain(); 2772 } 2773 final ClientTransaction transaction = ClientTransaction.obtain(app.thread, appToken); 2774 transaction.addCallback(callbackItem); 2775 transaction.setLifecycleStateRequest(lifecycleItem); 2776 service.getLifecycleManager().scheduleTransaction(transaction); 2777 // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only 2778 // request resume if this activity is currently resumed, which implies we aren't 2779 // sleeping. 2780 } catch (RemoteException e) { 2781 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e); 2782 } 2783 2784 if (andResume) { 2785 if (DEBUG_STATES) { 2786 Slog.d(TAG_STATES, "Resumed after relaunch " + this); 2787 } 2788 results = null; 2789 newIntents = null; 2790 service.getAppWarningsLocked().onResumeActivity(this); 2791 service.showAskCompatModeDialogLocked(this); 2792 } else { 2793 service.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this); 2794 setState(PAUSED, "relaunchActivityLocked"); 2795 } 2796 2797 configChangeFlags = 0; 2798 deferRelaunchUntilPaused = false; 2799 preserveWindowOnDeferredRelaunch = false; 2800 } 2801 isProcessRunning()2802 private boolean isProcessRunning() { 2803 ProcessRecord proc = app; 2804 if (proc == null) { 2805 proc = service.mProcessNames.get(processName, info.applicationInfo.uid); 2806 } 2807 return proc != null && proc.thread != null; 2808 } 2809 2810 /** 2811 * @return Whether a task snapshot starting window may be shown. 2812 */ allowTaskSnapshot()2813 private boolean allowTaskSnapshot() { 2814 if (newIntents == null) { 2815 return true; 2816 } 2817 2818 // Restrict task snapshot starting window to launcher start, or there is no intent at all 2819 // (eg. task being brought to front). If the intent is something else, likely the app is 2820 // going to show some specific page or view, instead of what's left last time. 2821 for (int i = newIntents.size() - 1; i >= 0; i--) { 2822 final Intent intent = newIntents.get(i); 2823 if (intent != null && !ActivityRecord.isMainIntent(intent)) { 2824 return false; 2825 } 2826 } 2827 return true; 2828 } 2829 2830 /** 2831 * Returns {@code true} if the associated activity has the no history flag set on it. 2832 * {@code false} otherwise. 2833 */ isNoHistory()2834 boolean isNoHistory() { 2835 return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0 2836 || (info.flags & FLAG_NO_HISTORY) != 0; 2837 } 2838 saveToXml(XmlSerializer out)2839 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException { 2840 out.attribute(null, ATTR_ID, String.valueOf(createTime)); 2841 out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid)); 2842 if (launchedFromPackage != null) { 2843 out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage); 2844 } 2845 if (resolvedType != null) { 2846 out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType); 2847 } 2848 out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified)); 2849 out.attribute(null, ATTR_USERID, String.valueOf(userId)); 2850 2851 if (taskDescription != null) { 2852 taskDescription.saveToXml(out); 2853 } 2854 2855 out.startTag(null, TAG_INTENT); 2856 intent.saveToXml(out); 2857 out.endTag(null, TAG_INTENT); 2858 2859 if (isPersistable() && persistentState != null) { 2860 out.startTag(null, TAG_PERSISTABLEBUNDLE); 2861 persistentState.saveToXml(out); 2862 out.endTag(null, TAG_PERSISTABLEBUNDLE); 2863 } 2864 } 2865 restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)2866 static ActivityRecord restoreFromXml(XmlPullParser in, 2867 ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException { 2868 Intent intent = null; 2869 PersistableBundle persistentState = null; 2870 int launchedFromUid = 0; 2871 String launchedFromPackage = null; 2872 String resolvedType = null; 2873 boolean componentSpecified = false; 2874 int userId = 0; 2875 long createTime = -1; 2876 final int outerDepth = in.getDepth(); 2877 TaskDescription taskDescription = new TaskDescription(); 2878 2879 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) { 2880 final String attrName = in.getAttributeName(attrNdx); 2881 final String attrValue = in.getAttributeValue(attrNdx); 2882 if (DEBUG) Slog.d(TaskPersister.TAG, 2883 "ActivityRecord: attribute name=" + attrName + " value=" + attrValue); 2884 if (ATTR_ID.equals(attrName)) { 2885 createTime = Long.parseLong(attrValue); 2886 } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) { 2887 launchedFromUid = Integer.parseInt(attrValue); 2888 } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) { 2889 launchedFromPackage = attrValue; 2890 } else if (ATTR_RESOLVEDTYPE.equals(attrName)) { 2891 resolvedType = attrValue; 2892 } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) { 2893 componentSpecified = Boolean.parseBoolean(attrValue); 2894 } else if (ATTR_USERID.equals(attrName)) { 2895 userId = Integer.parseInt(attrValue); 2896 } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) { 2897 taskDescription.restoreFromXml(attrName, attrValue); 2898 } else { 2899 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName); 2900 } 2901 } 2902 2903 int event; 2904 while (((event = in.next()) != END_DOCUMENT) && 2905 (event != END_TAG || in.getDepth() >= outerDepth)) { 2906 if (event == START_TAG) { 2907 final String name = in.getName(); 2908 if (DEBUG) 2909 Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name); 2910 if (TAG_INTENT.equals(name)) { 2911 intent = Intent.restoreFromXml(in); 2912 if (DEBUG) 2913 Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent); 2914 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) { 2915 persistentState = PersistableBundle.restoreFromXml(in); 2916 if (DEBUG) Slog.d(TaskPersister.TAG, 2917 "ActivityRecord: persistentState=" + persistentState); 2918 } else { 2919 Slog.w(TAG, "restoreActivity: unexpected name=" + name); 2920 XmlUtils.skipCurrentTag(in); 2921 } 2922 } 2923 } 2924 2925 if (intent == null) { 2926 throw new XmlPullParserException("restoreActivity error intent=" + intent); 2927 } 2928 2929 final ActivityManagerService service = stackSupervisor.mService; 2930 final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null, 2931 userId, Binder.getCallingUid()); 2932 if (aInfo == null) { 2933 throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent + 2934 " resolvedType=" + resolvedType); 2935 } 2936 final ActivityRecord r = new ActivityRecord(service, null /* caller */, 2937 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType, 2938 aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */, 2939 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */, 2940 stackSupervisor, null /* options */, null /* sourceRecord */); 2941 2942 r.persistentState = persistentState; 2943 r.taskDescription = taskDescription; 2944 r.createTime = createTime; 2945 2946 return r; 2947 } 2948 isInVrUiMode(Configuration config)2949 private static boolean isInVrUiMode(Configuration config) { 2950 return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET; 2951 } 2952 getUid()2953 int getUid() { 2954 return info.applicationInfo.uid; 2955 } 2956 setShowWhenLocked(boolean showWhenLocked)2957 void setShowWhenLocked(boolean showWhenLocked) { 2958 mShowWhenLocked = showWhenLocked; 2959 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0 /* configChanges */, 2960 false /* preserveWindows */); 2961 } 2962 2963 /** 2964 * @return true if the activity windowing mode is not 2965 * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and activity contains 2966 * windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the activity 2967 * has set {@link #mShowWhenLocked}. 2968 * Multi-windowing mode will be exited if true is returned. 2969 */ canShowWhenLocked()2970 boolean canShowWhenLocked() { 2971 return !inPinnedWindowingMode() && (mShowWhenLocked 2972 || service.mWindowManager.containsShowWhenLockedWindow(appToken)); 2973 } 2974 setTurnScreenOn(boolean turnScreenOn)2975 void setTurnScreenOn(boolean turnScreenOn) { 2976 mTurnScreenOn = turnScreenOn; 2977 } 2978 2979 /** 2980 * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag 2981 * {@link #mTurnScreenOn} is set and checks whether the ActivityRecord should be visible 2982 * depending on Keyguard state 2983 * 2984 * @return true if the screen can be turned on, false otherwise. 2985 */ canTurnScreenOn()2986 boolean canTurnScreenOn() { 2987 final ActivityStack stack = getStack(); 2988 return mTurnScreenOn && stack != null && 2989 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */); 2990 } 2991 getTurnScreenOnFlag()2992 boolean getTurnScreenOnFlag() { 2993 return mTurnScreenOn; 2994 } 2995 isTopRunningActivity()2996 boolean isTopRunningActivity() { 2997 return mStackSupervisor.topRunningActivityLocked() == this; 2998 } 2999 registerRemoteAnimations(RemoteAnimationDefinition definition)3000 void registerRemoteAnimations(RemoteAnimationDefinition definition) { 3001 mWindowContainerController.registerRemoteAnimations(definition); 3002 } 3003 3004 @Override toString()3005 public String toString() { 3006 if (stringName != null) { 3007 return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) + 3008 (finishing ? " f}" : "}"); 3009 } 3010 StringBuilder sb = new StringBuilder(128); 3011 sb.append("ActivityRecord{"); 3012 sb.append(Integer.toHexString(System.identityHashCode(this))); 3013 sb.append(" u"); 3014 sb.append(userId); 3015 sb.append(' '); 3016 sb.append(intent.getComponent().flattenToShortString()); 3017 stringName = sb.toString(); 3018 return toString(); 3019 } 3020 writeIdentifierToProto(ProtoOutputStream proto, long fieldId)3021 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) { 3022 final long token = proto.start(fieldId); 3023 proto.write(HASH_CODE, System.identityHashCode(this)); 3024 proto.write(USER_ID, userId); 3025 proto.write(TITLE, intent.getComponent().flattenToShortString()); 3026 proto.end(token); 3027 } 3028 writeToProto(ProtoOutputStream proto, long fieldId)3029 public void writeToProto(ProtoOutputStream proto, long fieldId) { 3030 final long token = proto.start(fieldId); 3031 super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); 3032 writeIdentifierToProto(proto, IDENTIFIER); 3033 proto.write(STATE, mState.toString()); 3034 proto.write(VISIBLE, visible); 3035 proto.write(FRONT_OF_TASK, frontOfTask); 3036 if (app != null) { 3037 proto.write(PROC_ID, app.pid); 3038 } 3039 proto.write(TRANSLUCENT, !fullscreen); 3040 proto.end(token); 3041 } 3042 } 3043