OSDN Git Service

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