ActivityRecord.java revision afb776d5447e19565c9a826a554911decb9ed92a
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        // Normally launch time counts from the point when the activity is resumed, to when the
1127        // first window is drawn. However the activity could become visible before it is resumed,
1128        // due to some other activity in the same task being launched. In this case we still need
1129        // to report launch time to unblock ActivityStarter.startActivityMayWait().
1130        if (displayStartTime == 0 && task != null && task.isLaunching) {
1131            displayStartTime = curTime;
1132        }
1133        if (displayStartTime != 0) {
1134            reportLaunchTimeLocked(curTime);
1135        }
1136        final ActivityStack stack = task.stack;
1137        if (fullyDrawnStartTime != 0 && stack != null) {
1138            final long thisTime = curTime - fullyDrawnStartTime;
1139            final long totalTime = stack.mFullyDrawnStartTime != 0
1140                    ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
1141            if (SHOW_ACTIVITY_START_TIME) {
1142                Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
1143                EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME,
1144                        userId, System.identityHashCode(this), shortComponentName,
1145                        thisTime, totalTime);
1146                StringBuilder sb = service.mStringBuilder;
1147                sb.setLength(0);
1148                sb.append("Fully drawn ");
1149                sb.append(shortComponentName);
1150                sb.append(": ");
1151                TimeUtils.formatDuration(thisTime, sb);
1152                if (thisTime != totalTime) {
1153                    sb.append(" (total ");
1154                    TimeUtils.formatDuration(totalTime, sb);
1155                    sb.append(")");
1156                }
1157                Log.i(TAG, sb.toString());
1158            }
1159            if (totalTime > 0) {
1160                //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
1161            }
1162            stack.mFullyDrawnStartTime = 0;
1163        }
1164        fullyDrawnStartTime = 0;
1165    }
1166
1167    private void reportLaunchTimeLocked(final long curTime) {
1168        final ActivityStack stack = task.stack;
1169        if (stack == null) {
1170            return;
1171        }
1172        final long thisTime = curTime - displayStartTime;
1173        final long totalTime = stack.mLaunchStartTime != 0
1174                ? (curTime - stack.mLaunchStartTime) : thisTime;
1175        if (SHOW_ACTIVITY_START_TIME) {
1176            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
1177            EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
1178                    userId, System.identityHashCode(this), shortComponentName,
1179                    thisTime, totalTime);
1180            StringBuilder sb = service.mStringBuilder;
1181            sb.setLength(0);
1182            sb.append("Displayed ");
1183            sb.append(shortComponentName);
1184            sb.append(": ");
1185            TimeUtils.formatDuration(thisTime, sb);
1186            if (thisTime != totalTime) {
1187                sb.append(" (total ");
1188                TimeUtils.formatDuration(totalTime, sb);
1189                sb.append(")");
1190            }
1191            Log.i(TAG, sb.toString());
1192        }
1193        mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
1194        if (totalTime > 0) {
1195            //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
1196        }
1197        displayStartTime = 0;
1198        task.isLaunching = false;
1199        stack.mLaunchStartTime = 0;
1200    }
1201
1202    void windowsDrawnLocked() {
1203        mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
1204        final long curTime = SystemClock.uptimeMillis();
1205        // Normally launch time counts from the point when the activity is resumed, to when the
1206        // first window is drawn. However the activity could become visible before it is resumed,
1207        // due to some other activity in the same task being launched. In this case we still need
1208        // to report launch time to unblock ActivityStarter.startActivityMayWait().
1209        if (displayStartTime == 0 && task != null && task.isLaunching) {
1210            displayStartTime = curTime;
1211        }
1212        if (displayStartTime != 0) {
1213            reportLaunchTimeLocked(curTime);
1214        }
1215        mStackSupervisor.sendWaitingVisibleReportLocked(this);
1216        startTime = 0;
1217        finishLaunchTickingLocked();
1218        if (task != null) {
1219            task.hasBeenVisible = true;
1220        }
1221    }
1222
1223    void windowsVisibleLocked() {
1224        mStackSupervisor.reportActivityVisibleLocked(this);
1225        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
1226        if (!nowVisible) {
1227            nowVisible = true;
1228            lastVisibleTime = SystemClock.uptimeMillis();
1229            if (!idle) {
1230                // Instead of doing the full stop routine here, let's just hide any activities
1231                // we now can, and let them stop when the normal idle happens.
1232                mStackSupervisor.processStoppingActivitiesLocked(false);
1233            } else {
1234                // If this activity was already idle, then we now need to make sure we perform
1235                // the full stop of any activities that are waiting to do so. This is because
1236                // we won't do that while they are still waiting for this one to become visible.
1237                final int size = mStackSupervisor.mWaitingVisibleActivities.size();
1238                if (size > 0) {
1239                    for (int i = 0; i < size; i++) {
1240                        ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
1241                        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
1242                    }
1243                    mStackSupervisor.mWaitingVisibleActivities.clear();
1244                    mStackSupervisor.scheduleIdleLocked();
1245                }
1246            }
1247            service.scheduleAppGcsLocked();
1248        }
1249    }
1250
1251    ActivityRecord getWaitingHistoryRecordLocked() {
1252        // First find the real culprit...  if this activity is waiting for
1253        // another activity to start or has stopped, then the key dispatching
1254        // timeout should not be caused by this.
1255        if (mStackSupervisor.mWaitingVisibleActivities.contains(this) || stopped) {
1256            final ActivityStack stack = mStackSupervisor.getFocusedStack();
1257            // Try to use the one which is closest to top.
1258            ActivityRecord r = stack.mResumedActivity;
1259            if (r == null) {
1260                r = stack.mPausingActivity;
1261            }
1262            if (r != null) {
1263                return r;
1264            }
1265        }
1266        return this;
1267    }
1268
1269    /**
1270     * This method will return true if the activity is either visible, is becoming visible, is
1271     * currently pausing, or is resumed.
1272     */
1273    public boolean isInterestingToUserLocked() {
1274        return visible || nowVisible || state == ActivityState.PAUSING ||
1275                state == ActivityState.RESUMED;
1276    }
1277
1278    public void setSleeping(boolean _sleeping) {
1279        if (sleeping == _sleeping) {
1280            return;
1281        }
1282        if (app != null && app.thread != null) {
1283            try {
1284                app.thread.scheduleSleeping(appToken, _sleeping);
1285                if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
1286                    mStackSupervisor.mGoingToSleepActivities.add(this);
1287                }
1288                sleeping = _sleeping;
1289            } catch (RemoteException e) {
1290                Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
1291            }
1292        }
1293    }
1294
1295    static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
1296        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1297        if (r == null) {
1298            return INVALID_TASK_ID;
1299        }
1300        final TaskRecord task = r.task;
1301        final int activityNdx = task.mActivities.indexOf(r);
1302        if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
1303            return INVALID_TASK_ID;
1304        }
1305        return task.taskId;
1306    }
1307
1308    static ActivityRecord isInStackLocked(IBinder token) {
1309        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1310        return (r != null) ? r.task.stack.isInStackLocked(r) : null;
1311    }
1312
1313    static ActivityStack getStackLocked(IBinder token) {
1314        final ActivityRecord r = ActivityRecord.isInStackLocked(token);
1315        if (r != null) {
1316            return r.task.stack;
1317        }
1318        return null;
1319    }
1320
1321    final boolean isDestroyable() {
1322        if (finishing || app == null || state == ActivityState.DESTROYING
1323                || state == ActivityState.DESTROYED) {
1324            // This would be redundant.
1325            return false;
1326        }
1327        if (task == null || task.stack == null || this == task.stack.mResumedActivity
1328                || this == task.stack.mPausingActivity || !haveState || !stopped) {
1329            // We're not ready for this kind of thing.
1330            return false;
1331        }
1332        if (visible) {
1333            // The user would notice this!
1334            return false;
1335        }
1336        return true;
1337    }
1338
1339    private static String createImageFilename(long createTime, int taskId) {
1340        return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
1341                TaskPersister.IMAGE_EXTENSION;
1342    }
1343
1344    void setTaskDescription(TaskDescription _taskDescription) {
1345        Bitmap icon;
1346        if (_taskDescription.getIconFilename() == null &&
1347                (icon = _taskDescription.getIcon()) != null) {
1348            final String iconFilename = createImageFilename(createTime, task.taskId);
1349            final File iconFile = new File(TaskPersister.getUserImagesDir(userId), iconFilename);
1350            final String iconFilePath = iconFile.getAbsolutePath();
1351            service.mRecentTasks.saveImage(icon, iconFilePath);
1352            _taskDescription.setIconFilename(iconFilePath);
1353        }
1354        taskDescription = _taskDescription;
1355    }
1356
1357    void setVoiceSessionLocked(IVoiceInteractionSession session) {
1358        voiceSession = session;
1359        pendingVoiceInteractionStart = false;
1360    }
1361
1362    void clearVoiceSessionLocked() {
1363        voiceSession = null;
1364        pendingVoiceInteractionStart = false;
1365    }
1366
1367    void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
1368        out.attribute(null, ATTR_ID, String.valueOf(createTime));
1369        out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
1370        if (launchedFromPackage != null) {
1371            out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
1372        }
1373        if (resolvedType != null) {
1374            out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
1375        }
1376        out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
1377        out.attribute(null, ATTR_USERID, String.valueOf(userId));
1378
1379        if (taskDescription != null) {
1380            taskDescription.saveToXml(out);
1381        }
1382
1383        out.startTag(null, TAG_INTENT);
1384        intent.saveToXml(out);
1385        out.endTag(null, TAG_INTENT);
1386
1387        if (isPersistable() && persistentState != null) {
1388            out.startTag(null, TAG_PERSISTABLEBUNDLE);
1389            persistentState.saveToXml(out);
1390            out.endTag(null, TAG_PERSISTABLEBUNDLE);
1391        }
1392    }
1393
1394    static ActivityRecord restoreFromXml(XmlPullParser in,
1395            ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
1396        Intent intent = null;
1397        PersistableBundle persistentState = null;
1398        int launchedFromUid = 0;
1399        String launchedFromPackage = null;
1400        String resolvedType = null;
1401        boolean componentSpecified = false;
1402        int userId = 0;
1403        long createTime = -1;
1404        final int outerDepth = in.getDepth();
1405        TaskDescription taskDescription = new TaskDescription();
1406
1407        for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
1408            final String attrName = in.getAttributeName(attrNdx);
1409            final String attrValue = in.getAttributeValue(attrNdx);
1410            if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
1411                        "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
1412            if (ATTR_ID.equals(attrName)) {
1413                createTime = Long.valueOf(attrValue);
1414            } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
1415                launchedFromUid = Integer.parseInt(attrValue);
1416            } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
1417                launchedFromPackage = attrValue;
1418            } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
1419                resolvedType = attrValue;
1420            } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
1421                componentSpecified = Boolean.valueOf(attrValue);
1422            } else if (ATTR_USERID.equals(attrName)) {
1423                userId = Integer.parseInt(attrValue);
1424            } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
1425                taskDescription.restoreFromXml(attrName, attrValue);
1426            } else {
1427                Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
1428            }
1429        }
1430
1431        int event;
1432        while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
1433                (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
1434            if (event == XmlPullParser.START_TAG) {
1435                final String name = in.getName();
1436                if (TaskPersister.DEBUG)
1437                        Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
1438                if (TAG_INTENT.equals(name)) {
1439                    intent = Intent.restoreFromXml(in);
1440                    if (TaskPersister.DEBUG)
1441                            Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
1442                } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
1443                    persistentState = PersistableBundle.restoreFromXml(in);
1444                    if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
1445                            "ActivityRecord: persistentState=" + persistentState);
1446                } else {
1447                    Slog.w(TAG, "restoreActivity: unexpected name=" + name);
1448                    XmlUtils.skipCurrentTag(in);
1449                }
1450            }
1451        }
1452
1453        if (intent == null) {
1454            throw new XmlPullParserException("restoreActivity error intent=" + intent);
1455        }
1456
1457        final ActivityManagerService service = stackSupervisor.mService;
1458        final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
1459                userId);
1460        if (aInfo == null) {
1461            throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
1462                    " resolvedType=" + resolvedType);
1463        }
1464        final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid,
1465                launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(),
1466                null, null, 0, componentSpecified, false, stackSupervisor, null, null);
1467
1468        r.persistentState = persistentState;
1469        r.taskDescription = taskDescription;
1470        r.createTime = createTime;
1471
1472        return r;
1473    }
1474
1475    private static String activityTypeToString(int type) {
1476        switch (type) {
1477            case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE";
1478            case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE";
1479            case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE";
1480            default: return Integer.toString(type);
1481        }
1482    }
1483
1484    @Override
1485    public String toString() {
1486        if (stringName != null) {
1487            return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
1488                    (finishing ? " f}" : "}");
1489        }
1490        StringBuilder sb = new StringBuilder(128);
1491        sb.append("ActivityRecord{");
1492        sb.append(Integer.toHexString(System.identityHashCode(this)));
1493        sb.append(" u");
1494        sb.append(userId);
1495        sb.append(' ');
1496        sb.append(intent.getComponent().flattenToShortString());
1497        stringName = sb.toString();
1498        return toString();
1499    }
1500}
1501