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