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