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