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