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