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 
dump(PrintWriter pw, String prefix)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 
Token(ActivityRecord activity)317         Token(ActivityRecord activity) {
318             weakActivity = new WeakReference<ActivityRecord>(activity);
319         }
320 
windowsDrawn()321         @Override public void windowsDrawn() {
322             ActivityRecord activity = weakActivity.get();
323             if (activity != null) {
324                 activity.windowsDrawn();
325             }
326         }
327 
windowsVisible()328         @Override public void windowsVisible() {
329             ActivityRecord activity = weakActivity.get();
330             if (activity != null) {
331                 activity.windowsVisible();
332             }
333         }
334 
windowsGone()335         @Override public void windowsGone() {
336             ActivityRecord activity = weakActivity.get();
337             if (activity != null) {
338                 activity.windowsGone();
339             }
340         }
341 
keyDispatchingTimedOut(String reason)342         @Override public boolean keyDispatchingTimedOut(String reason) {
343             ActivityRecord activity = weakActivity.get();
344             return activity != null && activity.keyDispatchingTimedOut(reason);
345         }
346 
getKeyDispatchingTimeout()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
toString()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 
forToken(IBinder token)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 
isNotResolverActivity()376     boolean isNotResolverActivity() {
377         return !ResolverActivity.class.getName().equals(realActivity.getClassName());
378     }
379 
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, ActivityStackSupervisor supervisor, ActivityContainer container, Bundle options)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 
addNewIntentLocked(ReferrerIntent intent)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      */
deliverNewIntentLocked(int callingUid, Intent intent, String referrer)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 
updateOptionsLocked(Bundle options)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 
updateOptionsLocked(ActivityOptions options)689     void updateOptionsLocked(ActivityOptions options) {
690         if (options != null) {
691             if (pendingOptions != null) {
692                 pendingOptions.abort();
693             }
694             pendingOptions = options;
695         }
696     }
697 
applyOptionsLocked()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 
getOptionsForTargetActivityLocked()761     ActivityOptions getOptionsForTargetActivityLocked() {
762         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
763     }
764 
clearOptionsLocked()765     void clearOptionsLocked() {
766         if (pendingOptions != null) {
767             pendingOptions.abort();
768             pendingOptions = null;
769         }
770     }
771 
takeOptionsLocked()772     ActivityOptions takeOptionsLocked() {
773         ActivityOptions opts = pendingOptions;
774         pendingOptions = null;
775         return opts;
776     }
777 
removeUriPermissionsLocked()778     void removeUriPermissionsLocked() {
779         if (uriPermissions != null) {
780             uriPermissions.removeUriPermissionsLocked();
781             uriPermissions = null;
782         }
783     }
784 
pauseKeyDispatchingLocked()785     void pauseKeyDispatchingLocked() {
786         if (!keysPaused) {
787             keysPaused = true;
788             service.mWindowManager.pauseKeyDispatching(appToken);
789         }
790     }
791 
resumeKeyDispatchingLocked()792     void resumeKeyDispatchingLocked() {
793         if (keysPaused) {
794             keysPaused = false;
795             service.mWindowManager.resumeKeyDispatching(appToken);
796         }
797     }
798 
updateThumbnailLocked(Bitmap newThumbnail, CharSequence description)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 
startLaunchTickingLocked()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 
continueLaunchTickingLocked()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 
finishLaunchTickingLocked()832     void finishLaunchTickingLocked() {
833         launchTickTime = 0;
834         task.stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
835     }
836 
837     // IApplicationToken
838 
mayFreezeScreenLocked(ProcessRecord app)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 
startFreezingScreenLocked(ProcessRecord app, int configChanges)847     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
848         if (mayFreezeScreenLocked(app)) {
849             service.mWindowManager.startAppFreezingScreen(appToken, configChanges);
850         }
851     }
852 
stopFreezingScreenLocked(boolean force)853     public void stopFreezingScreenLocked(boolean force) {
854         if (force || frozenBeforeDestroy) {
855             frozenBeforeDestroy = false;
856             service.mWindowManager.stopAppFreezingScreen(appToken, force);
857         }
858     }
859 
reportFullyDrawnLocked()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 
reportLaunchTimeLocked(final long curTime)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 
windowsDrawn()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 
windowsVisible()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 
windowsGone()978     public void windowsGone() {
979         if (ActivityManagerService.DEBUG_SWITCH) Log.v(
980                 ActivityManagerService.TAG, "windowsGone(): " + this);
981         nowVisible = false;
982     }
983 
getWaitingHistoryRecordLocked()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 
keyDispatchingTimedOut(String reason)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. */
getKeyDispatchingTimeout()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      */
isInterestingToUserLocked()1027     public boolean isInterestingToUserLocked() {
1028         return visible || nowVisible || state == ActivityState.PAUSING ||
1029                 state == ActivityState.RESUMED;
1030     }
1031 
setSleeping(boolean _sleeping)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 
activityResumedLocked(IBinder token)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 
getTaskForActivityLocked(IBinder token, boolean onlyRoot)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 
isInStackLocked(IBinder token)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 
getStackLocked(IBinder token)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 
isDestroyable()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 
createImageFilename(long createTime, int taskId)1103     private static String createImageFilename(long createTime, int taskId) {
1104         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
1105                 TaskPersister.IMAGE_EXTENSION;
1106     }
1107 
setTaskDescription(TaskDescription _taskDescription)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 
saveToXml(XmlSerializer out)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 
restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)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 
activityTypeToString(int type)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
toString()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