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