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 com.android.server.am.ActivityManagerDebugConfig.*; 20 import static com.android.server.am.TaskRecord.INVALID_TASK_ID; 21 22 import android.app.ActivityManager.TaskDescription; 23 import android.app.PendingIntent; 24 import android.os.PersistableBundle; 25 import android.os.Trace; 26 27 import com.android.internal.app.ResolverActivity; 28 import com.android.internal.content.ReferrerIntent; 29 import com.android.internal.util.XmlUtils; 30 import com.android.server.AttributeCache; 31 import com.android.server.am.ActivityStack.ActivityState; 32 import com.android.server.am.ActivityStackSupervisor.ActivityContainer; 33 34 import android.app.ActivityOptions; 35 import android.app.ResultInfo; 36 import android.content.ComponentName; 37 import android.content.Intent; 38 import android.content.pm.ActivityInfo; 39 import android.content.pm.ApplicationInfo; 40 import android.content.res.CompatibilityInfo; 41 import android.content.res.Configuration; 42 import android.graphics.Bitmap; 43 import android.graphics.Rect; 44 import android.os.Build; 45 import android.os.Bundle; 46 import android.os.IBinder; 47 import android.os.Message; 48 import android.os.Process; 49 import android.os.RemoteException; 50 import android.os.SystemClock; 51 import android.os.UserHandle; 52 import android.util.EventLog; 53 import android.util.Log; 54 import android.util.Slog; 55 import android.util.TimeUtils; 56 import android.view.IApplicationToken; 57 import android.view.WindowManager; 58 59 import org.xmlpull.v1.XmlPullParser; 60 import org.xmlpull.v1.XmlPullParserException; 61 import org.xmlpull.v1.XmlSerializer; 62 63 import java.io.IOException; 64 import java.io.PrintWriter; 65 import java.lang.ref.WeakReference; 66 import java.util.ArrayList; 67 import java.util.HashSet; 68 import java.util.Objects; 69 70 /** 71 * An entry in the history stack, representing an activity. 72 */ 73 final class ActivityRecord { 74 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM; 75 private static final String TAG_STATES = TAG + POSTFIX_STATES; 76 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; 77 private static final String TAG_THUMBNAILS = TAG + POSTFIX_THUMBNAILS; 78 79 private static final boolean SHOW_ACTIVITY_START_TIME = true; 80 final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents"; 81 82 private static final String ATTR_ID = "id"; 83 private static final String TAG_INTENT = "intent"; 84 private static final String ATTR_USERID = "user_id"; 85 private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle"; 86 private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid"; 87 private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package"; 88 private static final String ATTR_RESOLVEDTYPE = "resolved_type"; 89 private static final String ATTR_COMPONENTSPECIFIED = "component_specified"; 90 static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_"; 91 92 final ActivityManagerService service; // owner 93 final IApplicationToken.Stub appToken; // window manager token 94 final ActivityInfo info; // all about me 95 final ApplicationInfo appInfo; // information about activity's app 96 final int launchedFromUid; // always the uid who started the activity. 97 final String launchedFromPackage; // always the package who started the activity. 98 final int userId; // Which user is this running for? 99 final Intent intent; // the original intent that generated us 100 final ComponentName realActivity; // the intent component, or target of an alias. 101 final String shortComponentName; // the short component name of the intent 102 final String resolvedType; // as per original caller; 103 final String packageName; // the package implementing intent's component 104 final String processName; // process where this component wants to run 105 final String taskAffinity; // as per ActivityInfo.taskAffinity 106 final boolean stateNotNeeded; // As per ActivityInfo.flags 107 boolean fullscreen; // covers the full screen? 108 final boolean noDisplay; // activity is not displayed? 109 final boolean componentSpecified; // did caller specifiy an explicit component? 110 final boolean rootVoiceInteraction; // was this the root activity of a voice interaction? 111 112 static final int APPLICATION_ACTIVITY_TYPE = 0; 113 static final int HOME_ACTIVITY_TYPE = 1; 114 static final int RECENTS_ACTIVITY_TYPE = 2; 115 int mActivityType; 116 117 CharSequence nonLocalizedLabel; // the label information from the package mgr. 118 int labelRes; // the label information from the package mgr. 119 int icon; // resource identifier of activity's icon. 120 int logo; // resource identifier of activity's logo. 121 int theme; // resource identifier of activity's theme. 122 int realTheme; // actual theme resource we will use, never 0. 123 int windowFlags; // custom window flags for preview window. 124 TaskRecord task; // the task this is in. 125 long createTime = System.currentTimeMillis(); 126 long displayStartTime; // when we started launching this activity 127 long fullyDrawnStartTime; // when we started launching this activity 128 long startTime; // last time this activity was started 129 long lastVisibleTime; // last time this activity became visible 130 long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity 131 long pauseTime; // last time we started pausing the activity 132 long launchTickTime; // base time for launch tick messages 133 Configuration configuration; // configuration activity was last running in 134 // Overridden configuration by the activity stack 135 // WARNING: Reference points to {@link ActivityStack#mOverrideConfig}, so its internal state 136 // should never be altered directly. 137 Configuration stackConfigOverride; 138 CompatibilityInfo compat;// last used compatibility mode 139 ActivityRecord resultTo; // who started this entry, so will get our reply 140 final String resultWho; // additional identifier for use by resultTo. 141 final int requestCode; // code given by requester (resultTo) 142 ArrayList<ResultInfo> results; // pending ActivityResult objs we have received 143 HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act 144 ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode 145 ActivityOptions pendingOptions; // most recently given options 146 ActivityOptions returningOptions; // options that are coming back via convertToTranslucent 147 AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity 148 HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold 149 UriPermissionOwner uriPermissions; // current special URI access perms. 150 ProcessRecord app; // if non-null, hosting application 151 ActivityState state; // current state we are in 152 Bundle icicle; // last saved activity state 153 PersistableBundle persistentState; // last persistently saved activity state 154 boolean frontOfTask; // is this the root activity of its task? 155 boolean launchFailed; // set if a launched failed, to abort on 2nd try 156 boolean haveState; // have we gotten the last activity state? 157 boolean stopped; // is activity pause finished? 158 boolean delayedResume; // not yet resumed because of stopped app switches? 159 boolean finishing; // activity in pending finish list? 160 boolean configDestroy; // need to destroy due to config change? 161 int configChangeFlags; // which config values have changed 162 boolean keysPaused; // has key dispatching been paused for it? 163 int launchMode; // the launch mode activity attribute. 164 boolean visible; // does this activity's window need to be shown? 165 boolean sleeping; // have we told the activity to sleep? 166 boolean nowVisible; // is this activity's window visible? 167 boolean idle; // has the activity gone idle? 168 boolean hasBeenLaunched;// has this activity ever been launched? 169 boolean frozenBeforeDestroy;// has been frozen but not yet destroyed. 170 boolean immersive; // immersive mode (don't interrupt if possible) 171 boolean forceNewConfig; // force re-create with new config next time 172 int launchCount; // count of launches since last state 173 long lastLaunchTime; // time of last lauch of this activity 174 ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>(); 175 176 String stringName; // for caching of toString(). 177 178 private boolean inHistory; // are we in the history stack? 179 final ActivityStackSupervisor mStackSupervisor; 180 boolean mStartingWindowShown = false; 181 ActivityContainer mInitialActivityContainer; 182 183 TaskDescription taskDescription; // the recents information for this activity 184 boolean mLaunchTaskBehind; // this activity is actively being launched with 185 // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed. 186 dump(PrintWriter pw, String prefix)187 void dump(PrintWriter pw, String prefix) { 188 final long now = SystemClock.uptimeMillis(); 189 pw.print(prefix); pw.print("packageName="); pw.print(packageName); 190 pw.print(" processName="); pw.println(processName); 191 pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid); 192 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage); 193 pw.print(" userId="); pw.println(userId); 194 pw.print(prefix); pw.print("app="); pw.println(app); 195 pw.print(prefix); pw.println(intent.toInsecureStringWithClip()); 196 pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask); 197 pw.print(" task="); pw.println(task); 198 pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity); 199 pw.print(prefix); pw.print("realActivity="); 200 pw.println(realActivity.flattenToShortString()); 201 if (appInfo != null) { 202 pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir); 203 if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) { 204 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir); 205 } 206 pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir); 207 } 208 pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded); 209 pw.print(" componentSpecified="); pw.print(componentSpecified); 210 pw.print(" mActivityType="); pw.println(mActivityType); 211 if (rootVoiceInteraction) { 212 pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction); 213 } 214 pw.print(prefix); pw.print("compat="); pw.print(compat); 215 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes)); 216 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); 217 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme)); 218 pw.print(prefix); pw.print("config="); pw.println(configuration); 219 pw.print(prefix); pw.print("stackConfigOverride="); pw.println(stackConfigOverride); 220 if (resultTo != null || resultWho != null) { 221 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo); 222 pw.print(" resultWho="); pw.print(resultWho); 223 pw.print(" resultCode="); pw.println(requestCode); 224 } 225 if (taskDescription != null) { 226 final String iconFilename = taskDescription.getIconFilename(); 227 if (iconFilename != null || taskDescription.getLabel() != null || 228 taskDescription.getPrimaryColor() != 0) { 229 pw.print(prefix); pw.print("taskDescription:"); 230 pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename()); 231 pw.print(" label=\""); pw.print(taskDescription.getLabel()); 232 pw.print("\""); 233 pw.print(" color="); 234 pw.println(Integer.toHexString(taskDescription.getPrimaryColor())); 235 } 236 if (iconFilename == null && taskDescription.getIcon() != null) { 237 pw.print(prefix); pw.println("taskDescription contains Bitmap"); 238 } 239 } 240 if (results != null) { 241 pw.print(prefix); pw.print("results="); pw.println(results); 242 } 243 if (pendingResults != null && pendingResults.size() > 0) { 244 pw.print(prefix); pw.println("Pending Results:"); 245 for (WeakReference<PendingIntentRecord> wpir : pendingResults) { 246 PendingIntentRecord pir = wpir != null ? wpir.get() : null; 247 pw.print(prefix); pw.print(" - "); 248 if (pir == null) { 249 pw.println("null"); 250 } else { 251 pw.println(pir); 252 pir.dump(pw, prefix + " "); 253 } 254 } 255 } 256 if (newIntents != null && newIntents.size() > 0) { 257 pw.print(prefix); pw.println("Pending New Intents:"); 258 for (int i=0; i<newIntents.size(); i++) { 259 Intent intent = newIntents.get(i); 260 pw.print(prefix); pw.print(" - "); 261 if (intent == null) { 262 pw.println("null"); 263 } else { 264 pw.println(intent.toShortString(false, true, false, true)); 265 } 266 } 267 } 268 if (pendingOptions != null) { 269 pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions); 270 } 271 if (appTimeTracker != null) { 272 appTimeTracker.dumpWithHeader(pw, prefix, false); 273 } 274 if (uriPermissions != null) { 275 uriPermissions.dump(pw, prefix); 276 } 277 pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed); 278 pw.print(" launchCount="); pw.print(launchCount); 279 pw.print(" lastLaunchTime="); 280 if (lastLaunchTime == 0) pw.print("0"); 281 else TimeUtils.formatDuration(lastLaunchTime, now, pw); 282 pw.println(); 283 pw.print(prefix); pw.print("haveState="); pw.print(haveState); 284 pw.print(" icicle="); pw.println(icicle); 285 pw.print(prefix); pw.print("state="); pw.print(state); 286 pw.print(" stopped="); pw.print(stopped); 287 pw.print(" delayedResume="); pw.print(delayedResume); 288 pw.print(" finishing="); pw.println(finishing); 289 pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused); 290 pw.print(" inHistory="); pw.print(inHistory); 291 pw.print(" visible="); pw.print(visible); 292 pw.print(" sleeping="); pw.print(sleeping); 293 pw.print(" idle="); pw.println(idle); 294 pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen); 295 pw.print(" noDisplay="); pw.print(noDisplay); 296 pw.print(" immersive="); pw.print(immersive); 297 pw.print(" launchMode="); pw.println(launchMode); 298 pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy); 299 pw.print(" forceNewConfig="); pw.println(forceNewConfig); 300 pw.print(prefix); pw.print("mActivityType="); 301 pw.println(activityTypeToString(mActivityType)); 302 if (displayStartTime != 0 || startTime != 0) { 303 pw.print(prefix); pw.print("displayStartTime="); 304 if (displayStartTime == 0) pw.print("0"); 305 else TimeUtils.formatDuration(displayStartTime, now, pw); 306 pw.print(" startTime="); 307 if (startTime == 0) pw.print("0"); 308 else TimeUtils.formatDuration(startTime, now, pw); 309 pw.println(); 310 } 311 final boolean waitingVisible = mStackSupervisor.mWaitingVisibleActivities.contains(this); 312 if (lastVisibleTime != 0 || waitingVisible || nowVisible) { 313 pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible); 314 pw.print(" nowVisible="); pw.print(nowVisible); 315 pw.print(" lastVisibleTime="); 316 if (lastVisibleTime == 0) pw.print("0"); 317 else TimeUtils.formatDuration(lastVisibleTime, now, pw); 318 pw.println(); 319 } 320 if (configDestroy || configChangeFlags != 0) { 321 pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy); 322 pw.print(" configChangeFlags="); 323 pw.println(Integer.toHexString(configChangeFlags)); 324 } 325 if (connections != null) { 326 pw.print(prefix); pw.print("connections="); pw.println(connections); 327 } 328 } 329 330 static class Token extends IApplicationToken.Stub { 331 private final WeakReference<ActivityRecord> weakActivity; 332 private final ActivityManagerService mService; 333 Token(ActivityRecord activity, ActivityManagerService service)334 Token(ActivityRecord activity, ActivityManagerService service) { 335 weakActivity = new WeakReference<>(activity); 336 mService = service; 337 } 338 339 @Override windowsDrawn()340 public void windowsDrawn() { 341 synchronized (mService) { 342 ActivityRecord r = tokenToActivityRecordLocked(this); 343 if (r != null) { 344 r.windowsDrawnLocked(); 345 } 346 } 347 } 348 349 @Override windowsVisible()350 public void windowsVisible() { 351 synchronized (mService) { 352 ActivityRecord r = tokenToActivityRecordLocked(this); 353 if (r != null) { 354 r.windowsVisibleLocked(); 355 } 356 } 357 } 358 359 @Override windowsGone()360 public void windowsGone() { 361 synchronized (mService) { 362 ActivityRecord r = tokenToActivityRecordLocked(this); 363 if (r != null) { 364 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + r); 365 r.nowVisible = false; 366 return; 367 } 368 } 369 } 370 371 @Override keyDispatchingTimedOut(String reason)372 public boolean keyDispatchingTimedOut(String reason) { 373 ActivityRecord r; 374 ActivityRecord anrActivity; 375 ProcessRecord anrApp; 376 synchronized (mService) { 377 r = tokenToActivityRecordLocked(this); 378 if (r == null) { 379 return false; 380 } 381 anrActivity = r.getWaitingHistoryRecordLocked(); 382 anrApp = r != null ? r.app : null; 383 } 384 return mService.inputDispatchingTimedOut(anrApp, anrActivity, r, false, reason); 385 } 386 387 @Override getKeyDispatchingTimeout()388 public long getKeyDispatchingTimeout() { 389 synchronized (mService) { 390 ActivityRecord r = tokenToActivityRecordLocked(this); 391 if (r == null) { 392 return 0; 393 } 394 r = r.getWaitingHistoryRecordLocked(); 395 return ActivityManagerService.getInputDispatchingTimeoutLocked(r); 396 } 397 } 398 tokenToActivityRecordLocked(Token token)399 private static final ActivityRecord tokenToActivityRecordLocked(Token token) { 400 if (token == null) { 401 return null; 402 } 403 ActivityRecord r = token.weakActivity.get(); 404 if (r == null || r.task == null || r.task.stack == null) { 405 return null; 406 } 407 return r; 408 } 409 410 @Override toString()411 public String toString() { 412 StringBuilder sb = new StringBuilder(128); 413 sb.append("Token{"); 414 sb.append(Integer.toHexString(System.identityHashCode(this))); 415 sb.append(' '); 416 sb.append(weakActivity.get()); 417 sb.append('}'); 418 return sb.toString(); 419 } 420 } 421 forTokenLocked(IBinder token)422 static ActivityRecord forTokenLocked(IBinder token) { 423 try { 424 return Token.tokenToActivityRecordLocked((Token)token); 425 } catch (ClassCastException e) { 426 Slog.w(TAG, "Bad activity token: " + token, e); 427 return null; 428 } 429 } 430 isNotResolverActivity()431 boolean isNotResolverActivity() { 432 return !ResolverActivity.class.getName().equals(realActivity.getClassName()); 433 } 434 ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified, boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor, ActivityContainer container, Bundle options)435 ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, 436 int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, 437 ActivityInfo aInfo, Configuration _configuration, 438 ActivityRecord _resultTo, String _resultWho, int _reqCode, 439 boolean _componentSpecified, boolean _rootVoiceInteraction, 440 ActivityStackSupervisor supervisor, 441 ActivityContainer container, Bundle options) { 442 service = _service; 443 appToken = new Token(this, service); 444 info = aInfo; 445 launchedFromUid = _launchedFromUid; 446 launchedFromPackage = _launchedFromPackage; 447 userId = UserHandle.getUserId(aInfo.applicationInfo.uid); 448 intent = _intent; 449 shortComponentName = _intent.getComponent().flattenToShortString(); 450 resolvedType = _resolvedType; 451 componentSpecified = _componentSpecified; 452 rootVoiceInteraction = _rootVoiceInteraction; 453 configuration = _configuration; 454 stackConfigOverride = (container != null) 455 ? container.mStack.mOverrideConfig : Configuration.EMPTY; 456 resultTo = _resultTo; 457 resultWho = _resultWho; 458 requestCode = _reqCode; 459 state = ActivityState.INITIALIZING; 460 frontOfTask = false; 461 launchFailed = false; 462 stopped = false; 463 delayedResume = false; 464 finishing = false; 465 configDestroy = false; 466 keysPaused = false; 467 inHistory = false; 468 visible = true; 469 nowVisible = false; 470 idle = false; 471 hasBeenLaunched = false; 472 mStackSupervisor = supervisor; 473 mInitialActivityContainer = container; 474 if (options != null) { 475 pendingOptions = new ActivityOptions(options); 476 mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind(); 477 PendingIntent usageReport = pendingOptions.getUsageTimeReport(); 478 if (usageReport != null) { 479 appTimeTracker = new AppTimeTracker(usageReport); 480 } 481 } 482 483 // This starts out true, since the initial state of an activity 484 // is that we have everything, and we shouldn't never consider it 485 // lacking in state to be removed if it dies. 486 haveState = true; 487 488 if (aInfo != null) { 489 if (aInfo.targetActivity == null 490 || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE 491 || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) { 492 realActivity = _intent.getComponent(); 493 } else { 494 realActivity = new ComponentName(aInfo.packageName, 495 aInfo.targetActivity); 496 } 497 taskAffinity = aInfo.taskAffinity; 498 stateNotNeeded = (aInfo.flags& 499 ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0; 500 appInfo = aInfo.applicationInfo; 501 nonLocalizedLabel = aInfo.nonLocalizedLabel; 502 labelRes = aInfo.labelRes; 503 if (nonLocalizedLabel == null && labelRes == 0) { 504 ApplicationInfo app = aInfo.applicationInfo; 505 nonLocalizedLabel = app.nonLocalizedLabel; 506 labelRes = app.labelRes; 507 } 508 icon = aInfo.getIconResource(); 509 logo = aInfo.getLogoResource(); 510 theme = aInfo.getThemeResource(); 511 realTheme = theme; 512 if (realTheme == 0) { 513 realTheme = aInfo.applicationInfo.targetSdkVersion 514 < Build.VERSION_CODES.HONEYCOMB 515 ? android.R.style.Theme 516 : android.R.style.Theme_Holo; 517 } 518 if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { 519 windowFlags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 520 } 521 if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0 522 && _caller != null 523 && (aInfo.applicationInfo.uid == Process.SYSTEM_UID 524 || aInfo.applicationInfo.uid == _caller.info.uid)) { 525 processName = _caller.processName; 526 } else { 527 processName = aInfo.processName; 528 } 529 530 if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) { 531 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 532 } 533 534 packageName = aInfo.applicationInfo.packageName; 535 launchMode = aInfo.launchMode; 536 537 AttributeCache.Entry ent = AttributeCache.instance().get(packageName, 538 realTheme, com.android.internal.R.styleable.Window, userId); 539 final boolean translucent = ent != null && (ent.array.getBoolean( 540 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 541 || (!ent.array.hasValue( 542 com.android.internal.R.styleable.Window_windowIsTranslucent) 543 && ent.array.getBoolean( 544 com.android.internal.R.styleable.Window_windowSwipeToDismiss, 545 false))); 546 fullscreen = ent != null && !ent.array.getBoolean( 547 com.android.internal.R.styleable.Window_windowIsFloating, false) 548 && !translucent; 549 noDisplay = ent != null && ent.array.getBoolean( 550 com.android.internal.R.styleable.Window_windowNoDisplay, false); 551 552 if ((!_componentSpecified || _launchedFromUid == Process.myUid() 553 || _launchedFromUid == 0) && 554 Intent.ACTION_MAIN.equals(_intent.getAction()) && 555 _intent.hasCategory(Intent.CATEGORY_HOME) && 556 _intent.getCategories().size() == 1 && 557 _intent.getData() == null && 558 _intent.getType() == null && 559 (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && 560 isNotResolverActivity()) { 561 // This sure looks like a home activity! 562 mActivityType = HOME_ACTIVITY_TYPE; 563 } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) { 564 mActivityType = RECENTS_ACTIVITY_TYPE; 565 } else { 566 mActivityType = APPLICATION_ACTIVITY_TYPE; 567 } 568 569 immersive = (aInfo.flags & ActivityInfo.FLAG_IMMERSIVE) != 0; 570 } else { 571 realActivity = null; 572 taskAffinity = null; 573 stateNotNeeded = false; 574 appInfo = null; 575 processName = null; 576 packageName = null; 577 fullscreen = true; 578 noDisplay = false; 579 mActivityType = APPLICATION_ACTIVITY_TYPE; 580 immersive = false; 581 } 582 } 583 584 void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) { 585 if (task != null && task.removeActivity(this) && task != newTask && task.stack != null) { 586 task.stack.removeTask(task, "setTask"); 587 } 588 task = newTask; 589 setTaskToAffiliateWith(taskToAffiliateWith); 590 } 591 592 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) { 593 if (taskToAffiliateWith != null && 594 launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE && 595 launchMode != ActivityInfo.LAUNCH_SINGLE_TASK) { 596 task.setTaskToAffiliateWith(taskToAffiliateWith); 597 } 598 } 599 600 boolean changeWindowTranslucency(boolean toOpaque) { 601 if (fullscreen == toOpaque) { 602 return false; 603 } 604 605 // Keep track of the number of fullscreen activities in this task. 606 task.numFullscreen += toOpaque ? +1 : -1; 607 608 fullscreen = toOpaque; 609 return true; 610 } 611 612 void putInHistory() { 613 if (!inHistory) { 614 inHistory = true; 615 } 616 } 617 618 void takeFromHistory() { 619 if (inHistory) { 620 inHistory = false; 621 if (task != null && !finishing) { 622 task = null; 623 } 624 clearOptionsLocked(); 625 } 626 } 627 628 boolean isInHistory() { 629 return inHistory; 630 } 631 632 boolean isInStackLocked() { 633 return task != null && task.stack != null && task.stack.isInStackLocked(this) != null; 634 } 635 636 boolean isHomeActivity() { 637 return mActivityType == HOME_ACTIVITY_TYPE; 638 } 639 640 boolean isRecentsActivity() { 641 return mActivityType == RECENTS_ACTIVITY_TYPE; 642 } 643 644 boolean isApplicationActivity() { 645 return mActivityType == APPLICATION_ACTIVITY_TYPE; 646 } 647 648 boolean isPersistable() { 649 return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || 650 info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) && 651 (intent == null || 652 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0); 653 } 654 655 void makeFinishingLocked() { 656 if (!finishing) { 657 if (task != null && task.stack != null 658 && this == task.stack.getVisibleBehindActivity()) { 659 // A finishing activity should not remain as visible in the background 660 mStackSupervisor.requestVisibleBehindLocked(this, false); 661 } 662 finishing = true; 663 if (stopped) { 664 clearOptionsLocked(); 665 } 666 } 667 } 668 669 UriPermissionOwner getUriPermissionsLocked() { 670 if (uriPermissions == null) { 671 uriPermissions = new UriPermissionOwner(service, this); 672 } 673 return uriPermissions; 674 } 675 676 void addResultLocked(ActivityRecord from, String resultWho, 677 int requestCode, int resultCode, 678 Intent resultData) { 679 ActivityResult r = new ActivityResult(from, resultWho, 680 requestCode, resultCode, resultData); 681 if (results == null) { 682 results = new ArrayList<ResultInfo>(); 683 } 684 results.add(r); 685 } 686 687 void removeResultsLocked(ActivityRecord from, String resultWho, 688 int requestCode) { 689 if (results != null) { 690 for (int i=results.size()-1; i>=0; i--) { 691 ActivityResult r = (ActivityResult)results.get(i); 692 if (r.mFrom != from) continue; 693 if (r.mResultWho == null) { 694 if (resultWho != null) continue; 695 } else { 696 if (!r.mResultWho.equals(resultWho)) continue; 697 } 698 if (r.mRequestCode != requestCode) continue; 699 700 results.remove(i); 701 } 702 } 703 } 704 addNewIntentLocked(ReferrerIntent intent)705 void addNewIntentLocked(ReferrerIntent intent) { 706 if (newIntents == null) { 707 newIntents = new ArrayList<>(); 708 } 709 newIntents.add(intent); 710 } 711 712 /** 713 * Deliver a new Intent to an existing activity, so that its onNewIntent() 714 * method will be called at the proper time. 715 */ deliverNewIntentLocked(int callingUid, Intent intent, String referrer)716 final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) { 717 // The activity now gets access to the data associated with this Intent. 718 service.grantUriPermissionFromIntentLocked(callingUid, packageName, 719 intent, getUriPermissionsLocked(), userId); 720 // We want to immediately deliver the intent to the activity if 721 // it is currently the top resumed activity... however, if the 722 // device is sleeping, then all activities are stopped, so in that 723 // case we will deliver it if this is the current top activity on its 724 // stack. 725 final ReferrerIntent rintent = new ReferrerIntent(intent, referrer); 726 boolean unsent = true; 727 if ((state == ActivityState.RESUMED 728 || (service.isSleeping() && task.stack != null 729 && task.stack.topRunningActivityLocked(null) == this)) 730 && app != null && app.thread != null) { 731 try { 732 ArrayList<ReferrerIntent> ar = new ArrayList<>(1); 733 ar.add(rintent); 734 app.thread.scheduleNewIntent(ar, appToken); 735 unsent = false; 736 } catch (RemoteException e) { 737 Slog.w(TAG, "Exception thrown sending new intent to " + this, e); 738 } catch (NullPointerException e) { 739 Slog.w(TAG, "Exception thrown sending new intent to " + this, e); 740 } 741 } 742 if (unsent) { 743 addNewIntentLocked(rintent); 744 } 745 } 746 updateOptionsLocked(Bundle options)747 void updateOptionsLocked(Bundle options) { 748 if (options != null) { 749 if (pendingOptions != null) { 750 pendingOptions.abort(); 751 } 752 pendingOptions = new ActivityOptions(options); 753 } 754 } 755 updateOptionsLocked(ActivityOptions options)756 void updateOptionsLocked(ActivityOptions options) { 757 if (options != null) { 758 if (pendingOptions != null) { 759 pendingOptions.abort(); 760 } 761 pendingOptions = options; 762 } 763 } 764 applyOptionsLocked()765 void applyOptionsLocked() { 766 if (pendingOptions != null 767 && pendingOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) { 768 final int animationType = pendingOptions.getAnimationType(); 769 switch (animationType) { 770 case ActivityOptions.ANIM_CUSTOM: 771 service.mWindowManager.overridePendingAppTransition( 772 pendingOptions.getPackageName(), 773 pendingOptions.getCustomEnterResId(), 774 pendingOptions.getCustomExitResId(), 775 pendingOptions.getOnAnimationStartListener()); 776 break; 777 case ActivityOptions.ANIM_CLIP_REVEAL: 778 service.mWindowManager.overridePendingAppTransitionClipReveal( 779 pendingOptions.getStartX(), pendingOptions.getStartY(), 780 pendingOptions.getWidth(), pendingOptions.getHeight()); 781 if (intent.getSourceBounds() == null) { 782 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 783 pendingOptions.getStartY(), 784 pendingOptions.getStartX()+pendingOptions.getWidth(), 785 pendingOptions.getStartY()+pendingOptions.getHeight())); 786 } 787 break; 788 case ActivityOptions.ANIM_SCALE_UP: 789 service.mWindowManager.overridePendingAppTransitionScaleUp( 790 pendingOptions.getStartX(), pendingOptions.getStartY(), 791 pendingOptions.getWidth(), pendingOptions.getHeight()); 792 if (intent.getSourceBounds() == null) { 793 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 794 pendingOptions.getStartY(), 795 pendingOptions.getStartX()+pendingOptions.getWidth(), 796 pendingOptions.getStartY()+pendingOptions.getHeight())); 797 } 798 break; 799 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP: 800 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN: 801 boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP); 802 service.mWindowManager.overridePendingAppTransitionThumb( 803 pendingOptions.getThumbnail(), 804 pendingOptions.getStartX(), pendingOptions.getStartY(), 805 pendingOptions.getOnAnimationStartListener(), 806 scaleUp); 807 if (intent.getSourceBounds() == null) { 808 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 809 pendingOptions.getStartY(), 810 pendingOptions.getStartX() 811 + pendingOptions.getThumbnail().getWidth(), 812 pendingOptions.getStartY() 813 + pendingOptions.getThumbnail().getHeight())); 814 } 815 break; 816 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP: 817 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: 818 service.mWindowManager.overridePendingAppTransitionAspectScaledThumb( 819 pendingOptions.getThumbnail(), 820 pendingOptions.getStartX(), pendingOptions.getStartY(), 821 pendingOptions.getWidth(), pendingOptions.getHeight(), 822 pendingOptions.getOnAnimationStartListener(), 823 (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP)); 824 if (intent.getSourceBounds() == null) { 825 intent.setSourceBounds(new Rect(pendingOptions.getStartX(), 826 pendingOptions.getStartY(), 827 pendingOptions.getStartX() + pendingOptions.getWidth(), 828 pendingOptions.getStartY() + pendingOptions.getHeight())); 829 } 830 break; 831 default: 832 Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType); 833 break; 834 } 835 pendingOptions = null; 836 } 837 } 838 getOptionsForTargetActivityLocked()839 ActivityOptions getOptionsForTargetActivityLocked() { 840 return pendingOptions != null ? pendingOptions.forTargetActivity() : null; 841 } 842 clearOptionsLocked()843 void clearOptionsLocked() { 844 if (pendingOptions != null) { 845 pendingOptions.abort(); 846 pendingOptions = null; 847 } 848 } 849 takeOptionsLocked()850 ActivityOptions takeOptionsLocked() { 851 ActivityOptions opts = pendingOptions; 852 pendingOptions = null; 853 return opts; 854 } 855 removeUriPermissionsLocked()856 void removeUriPermissionsLocked() { 857 if (uriPermissions != null) { 858 uriPermissions.removeUriPermissionsLocked(); 859 uriPermissions = null; 860 } 861 } 862 pauseKeyDispatchingLocked()863 void pauseKeyDispatchingLocked() { 864 if (!keysPaused) { 865 keysPaused = true; 866 service.mWindowManager.pauseKeyDispatching(appToken); 867 } 868 } 869 resumeKeyDispatchingLocked()870 void resumeKeyDispatchingLocked() { 871 if (keysPaused) { 872 keysPaused = false; 873 service.mWindowManager.resumeKeyDispatching(appToken); 874 } 875 } 876 updateThumbnailLocked(Bitmap newThumbnail, CharSequence description)877 void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) { 878 if (newThumbnail != null) { 879 if (DEBUG_THUMBNAILS) Slog.i(TAG_THUMBNAILS, 880 "Setting thumbnail of " + this + " to " + newThumbnail); 881 boolean thumbnailUpdated = task.setLastThumbnail(newThumbnail); 882 if (thumbnailUpdated && isPersistable()) { 883 mStackSupervisor.mService.notifyTaskPersisterLocked(task, false); 884 } 885 } 886 task.lastDescription = description; 887 } 888 startLaunchTickingLocked()889 void startLaunchTickingLocked() { 890 if (ActivityManagerService.IS_USER_BUILD) { 891 return; 892 } 893 if (launchTickTime == 0) { 894 launchTickTime = SystemClock.uptimeMillis(); 895 continueLaunchTickingLocked(); 896 } 897 } 898 continueLaunchTickingLocked()899 boolean continueLaunchTickingLocked() { 900 if (launchTickTime == 0) { 901 return false; 902 } 903 904 final ActivityStack stack = task.stack; 905 if (stack == null) { 906 return false; 907 } 908 909 Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this); 910 stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG); 911 stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK); 912 return true; 913 } 914 finishLaunchTickingLocked()915 void finishLaunchTickingLocked() { 916 launchTickTime = 0; 917 final ActivityStack stack = task.stack; 918 if (stack != null) { 919 stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG); 920 } 921 } 922 923 // IApplicationToken 924 mayFreezeScreenLocked(ProcessRecord app)925 public boolean mayFreezeScreenLocked(ProcessRecord app) { 926 // Only freeze the screen if this activity is currently attached to 927 // an application, and that application is not blocked or unresponding. 928 // In any other case, we can't count on getting the screen unfrozen, 929 // so it is best to leave as-is. 930 return app != null && !app.crashing && !app.notResponding; 931 } 932 startFreezingScreenLocked(ProcessRecord app, int configChanges)933 public void startFreezingScreenLocked(ProcessRecord app, int configChanges) { 934 if (mayFreezeScreenLocked(app)) { 935 service.mWindowManager.startAppFreezingScreen(appToken, configChanges); 936 } 937 } 938 stopFreezingScreenLocked(boolean force)939 public void stopFreezingScreenLocked(boolean force) { 940 if (force || frozenBeforeDestroy) { 941 frozenBeforeDestroy = false; 942 service.mWindowManager.stopAppFreezingScreen(appToken, force); 943 } 944 } 945 reportFullyDrawnLocked()946 public void reportFullyDrawnLocked() { 947 final long curTime = SystemClock.uptimeMillis(); 948 if (displayStartTime != 0) { 949 reportLaunchTimeLocked(curTime); 950 } 951 final ActivityStack stack = task.stack; 952 if (fullyDrawnStartTime != 0 && stack != null) { 953 final long thisTime = curTime - fullyDrawnStartTime; 954 final long totalTime = stack.mFullyDrawnStartTime != 0 955 ? (curTime - stack.mFullyDrawnStartTime) : thisTime; 956 if (SHOW_ACTIVITY_START_TIME) { 957 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0); 958 EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME, 959 userId, System.identityHashCode(this), shortComponentName, 960 thisTime, totalTime); 961 StringBuilder sb = service.mStringBuilder; 962 sb.setLength(0); 963 sb.append("Fully drawn "); 964 sb.append(shortComponentName); 965 sb.append(": "); 966 TimeUtils.formatDuration(thisTime, sb); 967 if (thisTime != totalTime) { 968 sb.append(" (total "); 969 TimeUtils.formatDuration(totalTime, sb); 970 sb.append(")"); 971 } 972 Log.i(TAG, sb.toString()); 973 } 974 if (totalTime > 0) { 975 //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime); 976 } 977 stack.mFullyDrawnStartTime = 0; 978 } 979 fullyDrawnStartTime = 0; 980 } 981 reportLaunchTimeLocked(final long curTime)982 private void reportLaunchTimeLocked(final long curTime) { 983 final ActivityStack stack = task.stack; 984 if (stack == null) { 985 return; 986 } 987 final long thisTime = curTime - displayStartTime; 988 final long totalTime = stack.mLaunchStartTime != 0 989 ? (curTime - stack.mLaunchStartTime) : thisTime; 990 if (SHOW_ACTIVITY_START_TIME) { 991 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0); 992 EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME, 993 userId, System.identityHashCode(this), shortComponentName, 994 thisTime, totalTime); 995 StringBuilder sb = service.mStringBuilder; 996 sb.setLength(0); 997 sb.append("Displayed "); 998 sb.append(shortComponentName); 999 sb.append(": "); 1000 TimeUtils.formatDuration(thisTime, sb); 1001 if (thisTime != totalTime) { 1002 sb.append(" (total "); 1003 TimeUtils.formatDuration(totalTime, sb); 1004 sb.append(")"); 1005 } 1006 Log.i(TAG, sb.toString()); 1007 } 1008 mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime); 1009 if (totalTime > 0) { 1010 //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime); 1011 } 1012 displayStartTime = 0; 1013 stack.mLaunchStartTime = 0; 1014 } 1015 windowsDrawnLocked()1016 void windowsDrawnLocked() { 1017 if (displayStartTime != 0) { 1018 reportLaunchTimeLocked(SystemClock.uptimeMillis()); 1019 } 1020 mStackSupervisor.sendWaitingVisibleReportLocked(this); 1021 startTime = 0; 1022 finishLaunchTickingLocked(); 1023 if (task != null) { 1024 task.hasBeenVisible = true; 1025 } 1026 } 1027 windowsVisibleLocked()1028 void windowsVisibleLocked() { 1029 mStackSupervisor.reportActivityVisibleLocked(this); 1030 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this); 1031 if (!nowVisible) { 1032 nowVisible = true; 1033 lastVisibleTime = SystemClock.uptimeMillis(); 1034 if (!idle) { 1035 // Instead of doing the full stop routine here, let's just hide any activities 1036 // we now can, and let them stop when the normal idle happens. 1037 mStackSupervisor.processStoppingActivitiesLocked(false); 1038 } else { 1039 // If this activity was already idle, then we now need to make sure we perform 1040 // the full stop of any activities that are waiting to do so. This is because 1041 // we won't do that while they are still waiting for this one to become visible. 1042 final int size = mStackSupervisor.mWaitingVisibleActivities.size(); 1043 if (size > 0) { 1044 for (int i = 0; i < size; i++) { 1045 ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i); 1046 if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r); 1047 } 1048 mStackSupervisor.mWaitingVisibleActivities.clear(); 1049 mStackSupervisor.scheduleIdleLocked(); 1050 } 1051 } 1052 service.scheduleAppGcsLocked(); 1053 } 1054 } 1055 getWaitingHistoryRecordLocked()1056 ActivityRecord getWaitingHistoryRecordLocked() { 1057 // First find the real culprit... if this activity is waiting for 1058 // another activity to start or has stopped, then the key dispatching 1059 // timeout should not be caused by this. 1060 if (mStackSupervisor.mWaitingVisibleActivities.contains(this) || stopped) { 1061 final ActivityStack stack = mStackSupervisor.getFocusedStack(); 1062 // Try to use the one which is closest to top. 1063 ActivityRecord r = stack.mResumedActivity; 1064 if (r == null) { 1065 r = stack.mPausingActivity; 1066 } 1067 if (r != null) { 1068 return r; 1069 } 1070 } 1071 return this; 1072 } 1073 1074 /** 1075 * This method will return true if the activity is either visible, is becoming visible, is 1076 * currently pausing, or is resumed. 1077 */ isInterestingToUserLocked()1078 public boolean isInterestingToUserLocked() { 1079 return visible || nowVisible || state == ActivityState.PAUSING || 1080 state == ActivityState.RESUMED; 1081 } 1082 setSleeping(boolean _sleeping)1083 public void setSleeping(boolean _sleeping) { 1084 if (sleeping == _sleeping) { 1085 return; 1086 } 1087 if (app != null && app.thread != null) { 1088 try { 1089 app.thread.scheduleSleeping(appToken, _sleeping); 1090 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) { 1091 mStackSupervisor.mGoingToSleepActivities.add(this); 1092 } 1093 sleeping = _sleeping; 1094 } catch (RemoteException e) { 1095 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e); 1096 } 1097 } 1098 } 1099 activityResumedLocked(IBinder token)1100 static void activityResumedLocked(IBinder token) { 1101 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1102 if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r); 1103 r.icicle = null; 1104 r.haveState = false; 1105 } 1106 getTaskForActivityLocked(IBinder token, boolean onlyRoot)1107 static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) { 1108 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1109 if (r == null) { 1110 return INVALID_TASK_ID; 1111 } 1112 final TaskRecord task = r.task; 1113 final int activityNdx = task.mActivities.indexOf(r); 1114 if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) { 1115 return INVALID_TASK_ID; 1116 } 1117 return task.taskId; 1118 } 1119 isInStackLocked(IBinder token)1120 static ActivityRecord isInStackLocked(IBinder token) { 1121 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1122 return (r != null) ? r.task.stack.isInStackLocked(r) : null; 1123 } 1124 getStackLocked(IBinder token)1125 static ActivityStack getStackLocked(IBinder token) { 1126 final ActivityRecord r = ActivityRecord.isInStackLocked(token); 1127 if (r != null) { 1128 return r.task.stack; 1129 } 1130 return null; 1131 } 1132 isDestroyable()1133 final boolean isDestroyable() { 1134 if (finishing || app == null || state == ActivityState.DESTROYING 1135 || state == ActivityState.DESTROYED) { 1136 // This would be redundant. 1137 return false; 1138 } 1139 if (task == null || task.stack == null || this == task.stack.mResumedActivity 1140 || this == task.stack.mPausingActivity || !haveState || !stopped) { 1141 // We're not ready for this kind of thing. 1142 return false; 1143 } 1144 if (visible) { 1145 // The user would notice this! 1146 return false; 1147 } 1148 return true; 1149 } 1150 createImageFilename(long createTime, int taskId)1151 private static String createImageFilename(long createTime, int taskId) { 1152 return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime + 1153 TaskPersister.IMAGE_EXTENSION; 1154 } 1155 setTaskDescription(TaskDescription _taskDescription)1156 void setTaskDescription(TaskDescription _taskDescription) { 1157 Bitmap icon; 1158 if (_taskDescription.getIconFilename() == null && 1159 (icon = _taskDescription.getIcon()) != null) { 1160 final String iconFilename = createImageFilename(createTime, task.taskId); 1161 mStackSupervisor.mService.mTaskPersister.saveImage(icon, iconFilename); 1162 _taskDescription.setIconFilename(iconFilename); 1163 } 1164 taskDescription = _taskDescription; 1165 } 1166 saveToXml(XmlSerializer out)1167 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException { 1168 out.attribute(null, ATTR_ID, String.valueOf(createTime)); 1169 out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid)); 1170 if (launchedFromPackage != null) { 1171 out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage); 1172 } 1173 if (resolvedType != null) { 1174 out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType); 1175 } 1176 out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified)); 1177 out.attribute(null, ATTR_USERID, String.valueOf(userId)); 1178 1179 if (taskDescription != null) { 1180 taskDescription.saveToXml(out); 1181 } 1182 1183 out.startTag(null, TAG_INTENT); 1184 intent.saveToXml(out); 1185 out.endTag(null, TAG_INTENT); 1186 1187 if (isPersistable() && persistentState != null) { 1188 out.startTag(null, TAG_PERSISTABLEBUNDLE); 1189 persistentState.saveToXml(out); 1190 out.endTag(null, TAG_PERSISTABLEBUNDLE); 1191 } 1192 } 1193 restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)1194 static ActivityRecord restoreFromXml(XmlPullParser in, 1195 ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException { 1196 Intent intent = null; 1197 PersistableBundle persistentState = null; 1198 int launchedFromUid = 0; 1199 String launchedFromPackage = null; 1200 String resolvedType = null; 1201 boolean componentSpecified = false; 1202 int userId = 0; 1203 long createTime = -1; 1204 final int outerDepth = in.getDepth(); 1205 TaskDescription taskDescription = new TaskDescription(); 1206 1207 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) { 1208 final String attrName = in.getAttributeName(attrNdx); 1209 final String attrValue = in.getAttributeValue(attrNdx); 1210 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, 1211 "ActivityRecord: attribute name=" + attrName + " value=" + attrValue); 1212 if (ATTR_ID.equals(attrName)) { 1213 createTime = Long.valueOf(attrValue); 1214 } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) { 1215 launchedFromUid = Integer.valueOf(attrValue); 1216 } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) { 1217 launchedFromPackage = attrValue; 1218 } else if (ATTR_RESOLVEDTYPE.equals(attrName)) { 1219 resolvedType = attrValue; 1220 } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) { 1221 componentSpecified = Boolean.valueOf(attrValue); 1222 } else if (ATTR_USERID.equals(attrName)) { 1223 userId = Integer.valueOf(attrValue); 1224 } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) { 1225 taskDescription.restoreFromXml(attrName, attrValue); 1226 } else { 1227 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName); 1228 } 1229 } 1230 1231 int event; 1232 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) && 1233 (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) { 1234 if (event == XmlPullParser.START_TAG) { 1235 final String name = in.getName(); 1236 if (TaskPersister.DEBUG) 1237 Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name); 1238 if (TAG_INTENT.equals(name)) { 1239 intent = Intent.restoreFromXml(in); 1240 if (TaskPersister.DEBUG) 1241 Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent); 1242 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) { 1243 persistentState = PersistableBundle.restoreFromXml(in); 1244 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, 1245 "ActivityRecord: persistentState=" + persistentState); 1246 } else { 1247 Slog.w(TAG, "restoreActivity: unexpected name=" + name); 1248 XmlUtils.skipCurrentTag(in); 1249 } 1250 } 1251 } 1252 1253 if (intent == null) { 1254 throw new XmlPullParserException("restoreActivity error intent=" + intent); 1255 } 1256 1257 final ActivityManagerService service = stackSupervisor.mService; 1258 final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null, 1259 userId); 1260 if (aInfo == null) { 1261 throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent + 1262 " resolvedType=" + resolvedType); 1263 } 1264 final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid, 1265 launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(), 1266 null, null, 0, componentSpecified, false, stackSupervisor, null, null); 1267 1268 r.persistentState = persistentState; 1269 r.taskDescription = taskDescription; 1270 r.createTime = createTime; 1271 1272 return r; 1273 } 1274 activityTypeToString(int type)1275 private static String activityTypeToString(int type) { 1276 switch (type) { 1277 case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE"; 1278 case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE"; 1279 case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE"; 1280 default: return Integer.toString(type); 1281 } 1282 } 1283 1284 @Override toString()1285 public String toString() { 1286 if (stringName != null) { 1287 return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) + 1288 (finishing ? " f}" : "}"); 1289 } 1290 StringBuilder sb = new StringBuilder(128); 1291 sb.append("ActivityRecord{"); 1292 sb.append(Integer.toHexString(System.identityHashCode(this))); 1293 sb.append(" u"); 1294 sb.append(userId); 1295 sb.append(' '); 1296 sb.append(intent.getComponent().flattenToShortString()); 1297 stringName = sb.toString(); 1298 return toString(); 1299 } 1300 } 1301