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