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