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