• 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.ActivityManagerService.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.Configuration;
28 import android.graphics.Bitmap;
29 import android.os.Bundle;
30 import android.os.Message;
31 import android.os.Process;
32 import android.os.SystemClock;
33 import android.util.EventLog;
34 import android.util.Log;
35 import android.view.IApplicationToken;
36 
37 import java.io.PrintWriter;
38 import java.lang.ref.WeakReference;
39 import java.util.ArrayList;
40 import java.util.HashSet;
41 
42 /**
43  * An entry in the history stack, representing an activity.
44  */
45 class HistoryRecord extends IApplicationToken.Stub {
46     final ActivityManagerService service; // owner
47     final ActivityInfo info; // all about me
48     final int launchedFromUid; // always the uid who started the activity.
49     final Intent intent;    // the original intent that generated us
50     final ComponentName realActivity;  // the intent component, or target of an alias.
51     final String shortComponentName; // the short component name of the intent
52     final String resolvedType; // as per original caller;
53     final String packageName; // the package implementing intent's component
54     final String processName; // process where this component wants to run
55     final String taskAffinity; // as per ActivityInfo.taskAffinity
56     final boolean stateNotNeeded; // As per ActivityInfo.flags
57     final boolean fullscreen;     // covers the full screen?
58     final boolean componentSpecified;  // did caller specifiy an explicit component?
59     final boolean isHomeActivity; // do we consider this to be a home activity?
60     final String baseDir;   // where activity source (resources etc) located
61     final String resDir;   // where public activity source (public resources etc) located
62     final String dataDir;   // where activity data should go
63     CharSequence nonLocalizedLabel;  // the label information from the package mgr.
64     int labelRes;           // the label information from the package mgr.
65     int icon;               // resource identifier of activity's icon.
66     int theme;              // resource identifier of activity's theme.
67     TaskRecord task;        // the task this is in.
68     long startTime;         // when we starting launching this activity
69     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
70     Configuration configuration; // configuration activity was last running in
71     HistoryRecord resultTo; // who started this entry, so will get our reply
72     final String resultWho; // additional identifier for use by resultTo.
73     final int requestCode;  // code given by requester (resultTo)
74     ArrayList results;      // pending ActivityResult objs we have received
75     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
76     ArrayList newIntents;   // any pending new intents for single-top mode
77     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
78     HashSet<UriPermission> readUriPermissions; // special access to reading uris.
79     HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
80     ProcessRecord app;  // if non-null, hosting application
81     Bitmap thumbnail;       // icon representation of paused screen
82     CharSequence description; // textual description of paused screen
83     ActivityManagerService.ActivityState state;    // current state we are in
84     Bundle  icicle;         // last saved activity state
85     boolean frontOfTask;    // is this the root activity of its task?
86     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
87     boolean haveState;      // have we gotten the last activity state?
88     boolean stopped;        // is activity pause finished?
89     boolean delayedResume;  // not yet resumed because of stopped app switches?
90     boolean finishing;      // activity in pending finish list?
91     boolean configDestroy;  // need to destroy due to config change?
92     int configChangeFlags;  // which config values have changed
93     boolean keysPaused;     // has key dispatching been paused for it?
94     boolean inHistory;      // are we in the history stack?
95     boolean persistent;     // requested to be persistent?
96     int launchMode;         // the launch mode activity attribute.
97     boolean visible;        // does this activity's window need to be shown?
98     boolean waitingVisible; // true if waiting for a new act to become vis
99     boolean nowVisible;     // is this activity's window visible?
100     boolean thumbnailNeeded;// has someone requested a thumbnail?
101     boolean idle;           // has the activity gone idle?
102     boolean hasBeenLaunched;// has this activity ever been launched?
103     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
104 
105     String stringName;      // for caching of toString().
106 
dump(PrintWriter pw, String prefix)107     void dump(PrintWriter pw, String prefix) {
108         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
109                 pw.print(" processName="); pw.println(processName);
110         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
111                 pw.print(" app="); pw.println(app);
112         pw.print(prefix); pw.println(intent);
113         pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
114                 pw.print(" task="); pw.println(task);
115         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
116         pw.print(prefix); pw.print("realActivity=");
117                 pw.println(realActivity.flattenToShortString());
118         pw.print(prefix); pw.print("base="); pw.print(baseDir);
119                 if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir);
120                 pw.print(" data="); pw.println(dataDir);
121         pw.print(prefix); pw.print("labelRes=0x");
122                 pw.print(Integer.toHexString(labelRes));
123                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
124                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
125         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
126                 pw.print(" componentSpecified="); pw.print(componentSpecified);
127                 pw.print(" isHomeActivity="); pw.println(isHomeActivity);
128         pw.print(prefix); pw.print("configuration="); pw.println(configuration);
129         if (resultTo != null || resultWho != null) {
130             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
131                     pw.print(" resultWho="); pw.print(resultWho);
132                     pw.print(" resultCode="); pw.println(requestCode);
133         }
134         if (results != null) {
135             pw.print(prefix); pw.print("results="); pw.println(results);
136         }
137         if (pendingResults != null) {
138             pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
139         }
140         if (readUriPermissions != null) {
141             pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
142         }
143         if (writeUriPermissions != null) {
144             pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
145         }
146         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
147                 pw.print(" haveState="); pw.print(haveState);
148                 pw.print(" icicle="); pw.println(icicle);
149         pw.print(prefix); pw.print("state="); pw.print(state);
150                 pw.print(" stopped="); pw.print(stopped);
151                 pw.print(" delayedResume="); pw.print(delayedResume);
152                 pw.print(" finishing="); pw.println(finishing);
153         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
154                 pw.print(" inHistory="); pw.print(inHistory);
155                 pw.print(" persistent="); pw.print(persistent);
156                 pw.print(" launchMode="); pw.println(launchMode);
157         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
158                 pw.print(" visible="); pw.print(visible);
159                 pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
160                 pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
161                 pw.print(" idle="); pw.println(idle);
162         if (waitingVisible || nowVisible) {
163             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
164                     pw.print(" nowVisible="); pw.println(nowVisible);
165         }
166         if (configDestroy || configChangeFlags != 0) {
167             pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
168                     pw.print(" configChangeFlags=");
169                     pw.println(Integer.toHexString(configChangeFlags));
170         }
171         if (connections != null) {
172             pw.print(prefix); pw.print("connections="); pw.println(connections);
173         }
174     }
175 
HistoryRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromUid, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, HistoryRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified)176     HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
177             int _launchedFromUid, Intent _intent, String _resolvedType,
178             ActivityInfo aInfo, Configuration _configuration,
179             HistoryRecord _resultTo, String _resultWho, int _reqCode,
180             boolean _componentSpecified) {
181         service = _service;
182         info = aInfo;
183         launchedFromUid = _launchedFromUid;
184         intent = _intent;
185         shortComponentName = _intent.getComponent().flattenToShortString();
186         resolvedType = _resolvedType;
187         componentSpecified = _componentSpecified;
188         configuration = _configuration;
189         resultTo = _resultTo;
190         resultWho = _resultWho;
191         requestCode = _reqCode;
192         state = ActivityManagerService.ActivityState.INITIALIZING;
193         frontOfTask = false;
194         launchFailed = false;
195         haveState = false;
196         stopped = false;
197         delayedResume = false;
198         finishing = false;
199         configDestroy = false;
200         keysPaused = false;
201         inHistory = false;
202         persistent = false;
203         visible = true;
204         waitingVisible = false;
205         nowVisible = false;
206         thumbnailNeeded = false;
207         idle = false;
208         hasBeenLaunched = false;
209 
210         if (aInfo != null) {
211             if (aInfo.targetActivity == null
212                     || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
213                     || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
214                 realActivity = _intent.getComponent();
215             } else {
216                 realActivity = new ComponentName(aInfo.packageName,
217                         aInfo.targetActivity);
218             }
219             taskAffinity = aInfo.taskAffinity;
220             stateNotNeeded = (aInfo.flags&
221                     ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0;
222             baseDir = aInfo.applicationInfo.sourceDir;
223             resDir = aInfo.applicationInfo.publicSourceDir;
224             dataDir = aInfo.applicationInfo.dataDir;
225             nonLocalizedLabel = aInfo.nonLocalizedLabel;
226             labelRes = aInfo.labelRes;
227             if (nonLocalizedLabel == null && labelRes == 0) {
228                 ApplicationInfo app = aInfo.applicationInfo;
229                 nonLocalizedLabel = app.nonLocalizedLabel;
230                 labelRes = app.labelRes;
231             }
232             icon = aInfo.getIconResource();
233             theme = aInfo.getThemeResource();
234             if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
235                     && _caller != null
236                     && (aInfo.applicationInfo.uid == Process.SYSTEM_UID
237                             || aInfo.applicationInfo.uid == _caller.info.uid)) {
238                 processName = _caller.processName;
239             } else {
240                 processName = aInfo.processName;
241             }
242 
243             if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) {
244                 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
245             }
246 
247             packageName = aInfo.applicationInfo.packageName;
248             launchMode = aInfo.launchMode;
249 
250             AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
251                     theme != 0 ? theme : android.R.style.Theme,
252                     com.android.internal.R.styleable.Window);
253             fullscreen = ent != null && !ent.array.getBoolean(
254                     com.android.internal.R.styleable.Window_windowIsFloating, false)
255                     && !ent.array.getBoolean(
256                     com.android.internal.R.styleable.Window_windowIsTranslucent, false);
257 
258             if (!_componentSpecified || _launchedFromUid == Process.myUid()
259                     || _launchedFromUid == 0) {
260                 // If we know the system has determined the component, then
261                 // we can consider this to be a home activity...
262                 if (Intent.ACTION_MAIN.equals(_intent.getAction()) &&
263                         _intent.hasCategory(Intent.CATEGORY_HOME) &&
264                         _intent.getCategories().size() == 1 &&
265                         _intent.getData() == null &&
266                         _intent.getType() == null &&
267                         (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
268                         !"android".equals(realActivity.getClassName())) {
269                     // This sure looks like a home activity!
270                     // Note the last check is so we don't count the resolver
271                     // activity as being home...  really, we don't care about
272                     // doing anything special with something that comes from
273                     // the core framework package.
274                     isHomeActivity = true;
275                 } else {
276                     isHomeActivity = false;
277                 }
278             } else {
279                 isHomeActivity = false;
280             }
281         } else {
282             realActivity = null;
283             taskAffinity = null;
284             stateNotNeeded = false;
285             baseDir = null;
286             resDir = null;
287             dataDir = null;
288             processName = null;
289             packageName = null;
290             fullscreen = true;
291             isHomeActivity = false;
292         }
293     }
294 
addResultLocked(HistoryRecord from, String resultWho, int requestCode, int resultCode, Intent resultData)295     void addResultLocked(HistoryRecord from, String resultWho,
296             int requestCode, int resultCode,
297             Intent resultData) {
298         ActivityResult r = new ActivityResult(from, resultWho,
299         		requestCode, resultCode, resultData);
300         if (results == null) {
301             results = new ArrayList();
302         }
303         results.add(r);
304     }
305 
removeResultsLocked(HistoryRecord from, String resultWho, int requestCode)306     void removeResultsLocked(HistoryRecord from, String resultWho,
307             int requestCode) {
308         if (results != null) {
309             for (int i=results.size()-1; i>=0; i--) {
310                 ActivityResult r = (ActivityResult)results.get(i);
311                 if (r.mFrom != from) continue;
312                 if (r.mResultWho == null) {
313                     if (resultWho != null) continue;
314                 } else {
315                     if (!r.mResultWho.equals(resultWho)) continue;
316                 }
317                 if (r.mRequestCode != requestCode) continue;
318 
319                 results.remove(i);
320             }
321         }
322     }
323 
addNewIntentLocked(Intent intent)324     void addNewIntentLocked(Intent intent) {
325         if (newIntents == null) {
326             newIntents = new ArrayList();
327         }
328         newIntents.add(intent);
329     }
330 
pauseKeyDispatchingLocked()331     void pauseKeyDispatchingLocked() {
332         if (!keysPaused) {
333             keysPaused = true;
334             service.mWindowManager.pauseKeyDispatching(this);
335         }
336     }
337 
resumeKeyDispatchingLocked()338     void resumeKeyDispatchingLocked() {
339         if (keysPaused) {
340             keysPaused = false;
341             service.mWindowManager.resumeKeyDispatching(this);
342         }
343     }
344 
345     // IApplicationToken
346 
mayFreezeScreenLocked(ProcessRecord app)347     public boolean mayFreezeScreenLocked(ProcessRecord app) {
348         // Only freeze the screen if this activity is currently attached to
349         // an application, and that application is not blocked or unresponding.
350         // In any other case, we can't count on getting the screen unfrozen,
351         // so it is best to leave as-is.
352         return app == null || (!app.crashing && !app.notResponding);
353     }
354 
startFreezingScreenLocked(ProcessRecord app, int configChanges)355     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
356         if (mayFreezeScreenLocked(app)) {
357             service.mWindowManager.startAppFreezingScreen(this, configChanges);
358         }
359     }
360 
stopFreezingScreenLocked(boolean force)361     public void stopFreezingScreenLocked(boolean force) {
362         if (force || frozenBeforeDestroy) {
363             frozenBeforeDestroy = false;
364             service.mWindowManager.stopAppFreezingScreen(this, force);
365         }
366     }
367 
windowsVisible()368     public void windowsVisible() {
369         synchronized(service) {
370             if (startTime != 0) {
371                 final long curTime = SystemClock.uptimeMillis();
372                 final long thisTime = curTime - startTime;
373                 final long totalTime = service.mInitialStartTime != 0
374                         ? (curTime - service.mInitialStartTime) : thisTime;
375                 if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
376                     EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
377                             System.identityHashCode(this), shortComponentName,
378                             thisTime, totalTime);
379                     StringBuilder sb = service.mStringBuilder;
380                     sb.setLength(0);
381                     sb.append("Displayed activity ");
382                     sb.append(shortComponentName);
383                     sb.append(": ");
384                     sb.append(thisTime);
385                     sb.append(" ms (total ");
386                     sb.append(totalTime);
387                     sb.append(" ms)");
388                     Log.i(ActivityManagerService.TAG, sb.toString());
389                 }
390                 if (totalTime > 0) {
391                     service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
392                 }
393                 startTime = 0;
394                 service.mInitialStartTime = 0;
395             }
396             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
397                     ActivityManagerService.TAG, "windowsVisible(): " + this);
398             if (!nowVisible) {
399                 nowVisible = true;
400                 if (!idle) {
401                     // Instead of doing the full stop routine here, let's just
402                     // hide any activities we now can, and let them stop when
403                     // the normal idle happens.
404                     service.processStoppingActivitiesLocked(false);
405                 } else {
406                     // If this activity was already idle, then we now need to
407                     // make sure we perform the full stop of any activities
408                     // that are waiting to do so.  This is because we won't
409                     // do that while they are still waiting for this one to
410                     // become visible.
411                     final int N = service.mWaitingVisibleActivities.size();
412                     if (N > 0) {
413                         for (int i=0; i<N; i++) {
414                             HistoryRecord r = (HistoryRecord)
415                                 service.mWaitingVisibleActivities.get(i);
416                             r.waitingVisible = false;
417                             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
418                                     ActivityManagerService.TAG,
419                                     "Was waiting for visible: " + r);
420                         }
421                         service.mWaitingVisibleActivities.clear();
422                         Message msg = Message.obtain();
423                         msg.what = ActivityManagerService.IDLE_NOW_MSG;
424                         service.mHandler.sendMessage(msg);
425                     }
426                 }
427                 service.scheduleAppGcsLocked();
428             }
429         }
430     }
431 
windowsGone()432     public void windowsGone() {
433         if (ActivityManagerService.DEBUG_SWITCH) Log.v(
434                 ActivityManagerService.TAG, "windowsGone(): " + this);
435         nowVisible = false;
436     }
437 
getWaitingHistoryRecordLocked()438     private HistoryRecord getWaitingHistoryRecordLocked() {
439         // First find the real culprit...  if we are waiting
440         // for another app to start, then we have paused dispatching
441         // for this activity.
442         HistoryRecord r = this;
443         if (r.waitingVisible) {
444             // Hmmm, who might we be waiting for?
445             r = service.mResumedActivity;
446             if (r == null) {
447                 r = service.mPausingActivity;
448             }
449             // Both of those null?  Fall back to 'this' again
450             if (r == null) {
451                 r = this;
452             }
453         }
454 
455         return r;
456     }
457 
keyDispatchingTimedOut()458     public boolean keyDispatchingTimedOut() {
459         synchronized(service) {
460             HistoryRecord r = getWaitingHistoryRecordLocked();
461             if (r != null && r.app != null) {
462                 if (r.app.debugging) {
463                     return false;
464                 }
465 
466                 if (service.mDidDexOpt) {
467                     // Give more time since we were dexopting.
468                     service.mDidDexOpt = false;
469                     return false;
470                 }
471 
472                 if (r.app.instrumentationClass == null) {
473                     service.appNotRespondingLocked(r.app, r, this,
474                             "keyDispatchingTimedOut");
475                 } else {
476                     Bundle info = new Bundle();
477                     info.putString("shortMsg", "keyDispatchingTimedOut");
478                     info.putString("longMsg", "Timed out while dispatching key event");
479                     service.finishInstrumentationLocked(
480                             r.app, Activity.RESULT_CANCELED, info);
481                 }
482             }
483             return true;
484         }
485     }
486 
487     /** Returns the key dispatching timeout for this application token. */
getKeyDispatchingTimeout()488     public long getKeyDispatchingTimeout() {
489         synchronized(service) {
490             HistoryRecord r = getWaitingHistoryRecordLocked();
491             if (r == null || r.app == null
492                     || r.app.instrumentationClass == null) {
493                 return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
494             }
495 
496             return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
497         }
498     }
499 
500     /**
501      * This method will return true if the activity is either visible, is becoming visible, is
502      * currently pausing, or is resumed.
503      */
isInterestingToUserLocked()504     public boolean isInterestingToUserLocked() {
505         return visible || nowVisible || state == ActivityState.PAUSING ||
506                 state == ActivityState.RESUMED;
507      }
508 
509 
toString()510     public String toString() {
511         if (stringName != null) {
512             return stringName;
513         }
514         StringBuilder sb = new StringBuilder(128);
515         sb.append("HistoryRecord{");
516         sb.append(Integer.toHexString(System.identityHashCode(this)));
517         sb.append(' ');
518         sb.append(intent.getComponent().flattenToShortString());
519         sb.append('}');
520         return stringName = sb.toString();
521     }
522 }
523