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