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 static android.app.ActivityManager.StackId;
20 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
21 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
22 import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
23 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
24 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
25 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
26 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
27 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
28 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_THUMBNAILS;
29 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
30 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
31 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS;
32 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
33 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
34 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
35 
36 import android.app.ActivityManager.TaskDescription;
37 import android.app.ActivityOptions;
38 import android.app.PendingIntent;
39 import android.app.ResultInfo;
40 import android.content.ComponentName;
41 import android.content.Intent;
42 import android.content.pm.ActivityInfo;
43 import android.content.pm.ApplicationInfo;
44 import android.content.res.CompatibilityInfo;
45 import android.content.res.Configuration;
46 import android.graphics.Bitmap;
47 import android.graphics.Rect;
48 import android.os.Build;
49 import android.os.Bundle;
50 import android.os.IBinder;
51 import android.os.Message;
52 import android.os.PersistableBundle;
53 import android.os.Process;
54 import android.os.RemoteException;
55 import android.os.SystemClock;
56 import android.os.Trace;
57 import android.os.UserHandle;
58 import android.service.voice.IVoiceInteractionSession;
59 import android.util.EventLog;
60 import android.util.Log;
61 import android.util.Slog;
62 import android.util.TimeUtils;
63 import android.view.AppTransitionAnimationSpec;
64 import android.view.IApplicationToken;
65 import android.view.WindowManager;
66 
67 import com.android.internal.app.ResolverActivity;
68 import com.android.internal.content.ReferrerIntent;
69 import com.android.internal.util.XmlUtils;
70 import com.android.server.AttributeCache;
71 import com.android.server.am.ActivityStack.ActivityState;
72 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
73 
74 import java.io.File;
75 import java.io.IOException;
76 import java.io.PrintWriter;
77 import java.lang.ref.WeakReference;
78 import java.util.ArrayList;
79 import java.util.Arrays;
80 import java.util.HashSet;
81 import java.util.Objects;
82 
83 import org.xmlpull.v1.XmlPullParser;
84 import org.xmlpull.v1.XmlPullParserException;
85 import org.xmlpull.v1.XmlSerializer;
86 
87 /**
88  * An entry in the history stack, representing an activity.
89  */
90 final class ActivityRecord {
91     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
92     private static final String TAG_STATES = TAG + POSTFIX_STATES;
93     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
94     private static final String TAG_THUMBNAILS = TAG + POSTFIX_THUMBNAILS;
95 
96     private static final boolean SHOW_ACTIVITY_START_TIME = true;
97     final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
98 
99     private static final String ATTR_ID = "id";
100     private static final String TAG_INTENT = "intent";
101     private static final String ATTR_USERID = "user_id";
102     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
103     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
104     private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
105     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
106     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
107     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
108 
109     final ActivityManagerService service; // owner
110     final IApplicationToken.Stub appToken; // window manager token
111     final ActivityInfo info; // all about me
112     final ApplicationInfo appInfo; // information about activity's app
113     final int launchedFromUid; // always the uid who started the activity.
114     final String launchedFromPackage; // always the package who started the activity.
115     final int userId;          // Which user is this running for?
116     final Intent intent;    // the original intent that generated us
117     final ComponentName realActivity;  // the intent component, or target of an alias.
118     final String shortComponentName; // the short component name of the intent
119     final String resolvedType; // as per original caller;
120     final String packageName; // the package implementing intent's component
121     final String processName; // process where this component wants to run
122     final String taskAffinity; // as per ActivityInfo.taskAffinity
123     final boolean stateNotNeeded; // As per ActivityInfo.flags
124     boolean fullscreen; // covers the full screen?
125     final boolean noDisplay;  // activity is not displayed?
126     final boolean componentSpecified;  // did caller specify an explicit component?
127     final boolean rootVoiceInteraction;  // was this the root activity of a voice interaction?
128 
129     static final int APPLICATION_ACTIVITY_TYPE = 0;
130     static final int HOME_ACTIVITY_TYPE = 1;
131     static final int RECENTS_ACTIVITY_TYPE = 2;
132     int mActivityType;
133 
134     CharSequence nonLocalizedLabel;  // the label information from the package mgr.
135     int labelRes;           // the label information from the package mgr.
136     int icon;               // resource identifier of activity's icon.
137     int logo;               // resource identifier of activity's logo.
138     int theme;              // resource identifier of activity's theme.
139     int realTheme;          // actual theme resource we will use, never 0.
140     int windowFlags;        // custom window flags for preview window.
141     TaskRecord task;        // the task this is in.
142     long createTime = System.currentTimeMillis();
143     long displayStartTime;  // when we started launching this activity
144     long fullyDrawnStartTime; // when we started launching this activity
145     long startTime;         // last time this activity was started
146     long lastVisibleTime;   // last time this activity became visible
147     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
148     long pauseTime;         // last time we started pausing the activity
149     long launchTickTime;    // base time for launch tick messages
150     Configuration configuration; // configuration activity was last running in
151     // Overridden configuration by the activity task
152     // WARNING: Reference points to {@link TaskRecord#mOverrideConfig}, so its internal state
153     // should never be altered directly.
154     Configuration taskConfigOverride;
155     CompatibilityInfo compat;// last used compatibility mode
156     ActivityRecord resultTo; // who started this entry, so will get our reply
157     final String resultWho; // additional identifier for use by resultTo.
158     final int requestCode;  // code given by requester (resultTo)
159     ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
160     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
161     ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
162     ActivityOptions pendingOptions; // most recently given options
163     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
164     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
165     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
166     UriPermissionOwner uriPermissions; // current special URI access perms.
167     ProcessRecord app;      // if non-null, hosting application
168     ActivityState state;    // current state we are in
169     Bundle  icicle;         // last saved activity state
170     PersistableBundle persistentState; // last persistently saved activity state
171     boolean frontOfTask;    // is this the root activity of its task?
172     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
173     boolean haveState;      // have we gotten the last activity state?
174     boolean stopped;        // is activity pause finished?
175     boolean delayedResume;  // not yet resumed because of stopped app switches?
176     boolean finishing;      // activity in pending finish list?
177     boolean deferRelaunchUntilPaused;   // relaunch of activity is being deferred until pause is
178                                         // completed
179     boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
180     int configChangeFlags;  // which config values have changed
181     boolean keysPaused;     // has key dispatching been paused for it?
182     int launchMode;         // the launch mode activity attribute.
183     boolean visible;        // does this activity's window need to be shown?
184     boolean sleeping;       // have we told the activity to sleep?
185     boolean nowVisible;     // is this activity's window visible?
186     boolean idle;           // has the activity gone idle?
187     boolean hasBeenLaunched;// has this activity ever been launched?
188     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
189     boolean immersive;      // immersive mode (don't interrupt if possible)
190     boolean forceNewConfig; // force re-create with new config next time
191     int launchCount;        // count of launches since last state
192     long lastLaunchTime;    // time of last launch of this activity
193     ComponentName requestedVrComponent; // the requested component for handling VR mode.
194     ArrayList<ActivityContainer> mChildContainers = new ArrayList<>();
195 
196     String stringName;      // for caching of toString().
197 
198     private boolean inHistory;  // are we in the history stack?
199     final ActivityStackSupervisor mStackSupervisor;
200 
201     static final int STARTING_WINDOW_NOT_SHOWN = 0;
202     static final int STARTING_WINDOW_SHOWN = 1;
203     static final int STARTING_WINDOW_REMOVED = 2;
204     int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
205     boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
206 
207     boolean mUpdateTaskThumbnailWhenHidden;
208     ActivityContainer mInitialActivityContainer;
209 
210     TaskDescription taskDescription; // the recents information for this activity
211     boolean mLaunchTaskBehind; // this activity is actively being launched with
212         // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
213 
214     // These configurations are collected from application's resources based on size-sensitive
215     // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
216     // and drawable-sw400dp will be added to both as 400.
217     private int[] mVerticalSizeConfigurations;
218     private int[] mHorizontalSizeConfigurations;
219     private int[] mSmallestSizeConfigurations;
220 
221     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
222     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
223 
startingWindowStateToString(int state)224     private static String startingWindowStateToString(int state) {
225         switch (state) {
226             case STARTING_WINDOW_NOT_SHOWN:
227                 return "STARTING_WINDOW_NOT_SHOWN";
228             case STARTING_WINDOW_SHOWN:
229                 return "STARTING_WINDOW_SHOWN";
230             case STARTING_WINDOW_REMOVED:
231                 return "STARTING_WINDOW_REMOVED";
232             default:
233                 return "unknown state=" + state;
234         }
235     }
236 
dump(PrintWriter pw, String prefix)237     void dump(PrintWriter pw, String prefix) {
238         final long now = SystemClock.uptimeMillis();
239         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
240                 pw.print(" processName="); pw.println(processName);
241         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
242                 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
243                 pw.print(" userId="); pw.println(userId);
244         pw.print(prefix); pw.print("app="); pw.println(app);
245         pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
246         pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
247                 pw.print(" task="); pw.println(task);
248         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
249         pw.print(prefix); pw.print("realActivity=");
250                 pw.println(realActivity.flattenToShortString());
251         if (appInfo != null) {
252             pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
253             if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
254                 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
255             }
256             pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
257             if (appInfo.splitSourceDirs != null) {
258                 pw.print(prefix); pw.print("splitDir=");
259                         pw.println(Arrays.toString(appInfo.splitSourceDirs));
260             }
261         }
262         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
263                 pw.print(" componentSpecified="); pw.print(componentSpecified);
264                 pw.print(" mActivityType="); pw.println(mActivityType);
265         if (rootVoiceInteraction) {
266             pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
267         }
268         pw.print(prefix); pw.print("compat="); pw.print(compat);
269                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
270                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
271                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
272         pw.print(prefix); pw.print("config="); pw.println(configuration);
273         pw.print(prefix); pw.print("taskConfigOverride="); pw.println(taskConfigOverride);
274         if (resultTo != null || resultWho != null) {
275             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
276                     pw.print(" resultWho="); pw.print(resultWho);
277                     pw.print(" resultCode="); pw.println(requestCode);
278         }
279         if (taskDescription != null) {
280             final String iconFilename = taskDescription.getIconFilename();
281             if (iconFilename != null || taskDescription.getLabel() != null ||
282                     taskDescription.getPrimaryColor() != 0) {
283                 pw.print(prefix); pw.print("taskDescription:");
284                         pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
285                         pw.print(" label=\""); pw.print(taskDescription.getLabel());
286                                 pw.print("\"");
287                         pw.print(" color=");
288                         pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
289             }
290             if (iconFilename == null && taskDescription.getIcon() != null) {
291                 pw.print(prefix); pw.println("taskDescription contains Bitmap");
292             }
293         }
294         if (results != null) {
295             pw.print(prefix); pw.print("results="); pw.println(results);
296         }
297         if (pendingResults != null && pendingResults.size() > 0) {
298             pw.print(prefix); pw.println("Pending Results:");
299             for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
300                 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
301                 pw.print(prefix); pw.print("  - ");
302                 if (pir == null) {
303                     pw.println("null");
304                 } else {
305                     pw.println(pir);
306                     pir.dump(pw, prefix + "    ");
307                 }
308             }
309         }
310         if (newIntents != null && newIntents.size() > 0) {
311             pw.print(prefix); pw.println("Pending New Intents:");
312             for (int i=0; i<newIntents.size(); i++) {
313                 Intent intent = newIntents.get(i);
314                 pw.print(prefix); pw.print("  - ");
315                 if (intent == null) {
316                     pw.println("null");
317                 } else {
318                     pw.println(intent.toShortString(false, true, false, true));
319                 }
320             }
321         }
322         if (pendingOptions != null) {
323             pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
324         }
325         if (appTimeTracker != null) {
326             appTimeTracker.dumpWithHeader(pw, prefix, false);
327         }
328         if (uriPermissions != null) {
329             uriPermissions.dump(pw, prefix);
330         }
331         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
332                 pw.print(" launchCount="); pw.print(launchCount);
333                 pw.print(" lastLaunchTime=");
334                 if (lastLaunchTime == 0) pw.print("0");
335                 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
336                 pw.println();
337         pw.print(prefix); pw.print("haveState="); pw.print(haveState);
338                 pw.print(" icicle="); pw.println(icicle);
339         pw.print(prefix); pw.print("state="); pw.print(state);
340                 pw.print(" stopped="); pw.print(stopped);
341                 pw.print(" delayedResume="); pw.print(delayedResume);
342                 pw.print(" finishing="); pw.println(finishing);
343         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
344                 pw.print(" inHistory="); pw.print(inHistory);
345                 pw.print(" visible="); pw.print(visible);
346                 pw.print(" sleeping="); pw.print(sleeping);
347                 pw.print(" idle="); pw.print(idle);
348                 pw.print(" mStartingWindowState=");
349                 pw.println(startingWindowStateToString(mStartingWindowState));
350         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
351                 pw.print(" noDisplay="); pw.print(noDisplay);
352                 pw.print(" immersive="); pw.print(immersive);
353                 pw.print(" launchMode="); pw.println(launchMode);
354         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
355                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
356         pw.print(prefix); pw.print("mActivityType=");
357                 pw.println(activityTypeToString(mActivityType));
358         if (requestedVrComponent != null) {
359             pw.print(prefix);
360             pw.print("requestedVrComponent=");
361             pw.println(requestedVrComponent);
362         }
363         if (displayStartTime != 0 || startTime != 0) {
364             pw.print(prefix); pw.print("displayStartTime=");
365                     if (displayStartTime == 0) pw.print("0");
366                     else TimeUtils.formatDuration(displayStartTime, now, pw);
367                     pw.print(" startTime=");
368                     if (startTime == 0) pw.print("0");
369                     else TimeUtils.formatDuration(startTime, now, pw);
370                     pw.println();
371         }
372         final boolean waitingVisible = mStackSupervisor.mWaitingVisibleActivities.contains(this);
373         if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
374             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
375                     pw.print(" nowVisible="); pw.print(nowVisible);
376                     pw.print(" lastVisibleTime=");
377                     if (lastVisibleTime == 0) pw.print("0");
378                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
379                     pw.println();
380         }
381         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
382             pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
383                     pw.print(" configChangeFlags=");
384                     pw.println(Integer.toHexString(configChangeFlags));
385         }
386         if (connections != null) {
387             pw.print(prefix); pw.print("connections="); pw.println(connections);
388         }
389         if (info != null) {
390             pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
391         }
392     }
393 
crossesHorizontalSizeThreshold(int firstDp, int secondDp)394     public boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
395         return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
396     }
397 
crossesVerticalSizeThreshold(int firstDp, int secondDp)398     public boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
399         return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
400     }
401 
crossesSmallestSizeThreshold(int firstDp, int secondDp)402     public boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
403         return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
404     }
405 
406     /**
407      * The purpose of this method is to decide whether the activity needs to be relaunched upon
408      * changing its size. In most cases the activities don't need to be relaunched, if the resize
409      * is small, all the activity content has to do is relayout itself within new bounds. There are
410      * cases however, where the activity's content would be completely changed in the new size and
411      * the full relaunch is required.
412      *
413      * The activity will report to us vertical and horizontal thresholds after which a relaunch is
414      * required. These thresholds are collected from the application resource qualifiers. For
415      * example, if application has layout-w600dp resource directory, then it needs a relaunch when
416      * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
417      * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
418      * of the threshold.
419      */
crossesSizeThreshold(int[] thresholds, int firstDp, int secondDp)420     private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
421             int secondDp) {
422         if (thresholds == null) {
423             return false;
424         }
425         for (int i = thresholds.length - 1; i >= 0; i--) {
426             final int threshold = thresholds[i];
427             if ((firstDp < threshold && secondDp >= threshold)
428                     || (firstDp >= threshold && secondDp < threshold)) {
429                 return true;
430             }
431         }
432         return false;
433     }
434 
setSizeConfigurations(int[] horizontalSizeConfiguration, int[] verticalSizeConfigurations, int[] smallestSizeConfigurations)435     public void setSizeConfigurations(int[] horizontalSizeConfiguration,
436             int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
437         mHorizontalSizeConfigurations = horizontalSizeConfiguration;
438         mVerticalSizeConfigurations = verticalSizeConfigurations;
439         mSmallestSizeConfigurations = smallestSizeConfigurations;
440     }
441 
scheduleConfigurationChanged(Configuration config, boolean reportToActivity)442     void scheduleConfigurationChanged(Configuration config, boolean reportToActivity) {
443         if (app == null || app.thread == null) {
444             return;
445         }
446         try {
447             // Make sure fontScale is always equal to global. For fullscreen apps, config is
448             // the shared EMPTY config, which has default fontScale of 1.0. We don't want it
449             // to be applied as an override config.
450             Configuration overrideConfig = new Configuration(config);
451             overrideConfig.fontScale = service.mConfiguration.fontScale;
452 
453             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
454                     "reportToActivity=" + reportToActivity + " and config: " + overrideConfig);
455 
456             app.thread.scheduleActivityConfigurationChanged(
457                     appToken, overrideConfig, reportToActivity);
458         } catch (RemoteException e) {
459             // If process died, whatever.
460         }
461     }
462 
scheduleMultiWindowModeChanged()463     void scheduleMultiWindowModeChanged() {
464         if (task == null || task.stack == null || app == null || app.thread == null) {
465             return;
466         }
467         try {
468             // An activity is considered to be in multi-window mode if its task isn't fullscreen.
469             app.thread.scheduleMultiWindowModeChanged(appToken, !task.mFullscreen);
470         } catch (Exception e) {
471             // If process died, I don't care.
472         }
473     }
474 
schedulePictureInPictureModeChanged()475     void schedulePictureInPictureModeChanged() {
476         if (task == null || task.stack == null || app == null || app.thread == null) {
477             return;
478         }
479         try {
480             app.thread.schedulePictureInPictureModeChanged(
481                     appToken, task.stack.mStackId == PINNED_STACK_ID);
482         } catch (Exception e) {
483             // If process died, no one cares.
484         }
485     }
486 
isFreeform()487     boolean isFreeform() {
488         return task != null && task.stack != null
489                 && task.stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
490     }
491 
492     static class Token extends IApplicationToken.Stub {
493         private final WeakReference<ActivityRecord> weakActivity;
494         private final ActivityManagerService mService;
495 
Token(ActivityRecord activity, ActivityManagerService service)496         Token(ActivityRecord activity, ActivityManagerService service) {
497             weakActivity = new WeakReference<>(activity);
498             mService = service;
499         }
500 
501         @Override
windowsDrawn()502         public void windowsDrawn() {
503             synchronized (mService) {
504                 ActivityRecord r = tokenToActivityRecordLocked(this);
505                 if (r != null) {
506                     r.windowsDrawnLocked();
507                 }
508             }
509         }
510 
511         @Override
windowsVisible()512         public void windowsVisible() {
513             synchronized (mService) {
514                 ActivityRecord r = tokenToActivityRecordLocked(this);
515                 if (r != null) {
516                     r.windowsVisibleLocked();
517                 }
518             }
519         }
520 
521         @Override
windowsGone()522         public void windowsGone() {
523             synchronized (mService) {
524                 ActivityRecord r = tokenToActivityRecordLocked(this);
525                 if (r != null) {
526                     if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + r);
527                     r.nowVisible = false;
528                     return;
529                 }
530             }
531         }
532 
533         @Override
keyDispatchingTimedOut(String reason)534         public boolean keyDispatchingTimedOut(String reason) {
535             ActivityRecord r;
536             ActivityRecord anrActivity;
537             ProcessRecord anrApp;
538             synchronized (mService) {
539                 r = tokenToActivityRecordLocked(this);
540                 if (r == null) {
541                     return false;
542                 }
543                 anrActivity = r.getWaitingHistoryRecordLocked();
544                 anrApp = r != null ? r.app : null;
545             }
546             return mService.inputDispatchingTimedOut(anrApp, anrActivity, r, false, reason);
547         }
548 
549         @Override
getKeyDispatchingTimeout()550         public long getKeyDispatchingTimeout() {
551             synchronized (mService) {
552                 ActivityRecord r = tokenToActivityRecordLocked(this);
553                 if (r == null) {
554                     return 0;
555                 }
556                 r = r.getWaitingHistoryRecordLocked();
557                 return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
558             }
559         }
560 
tokenToActivityRecordLocked(Token token)561         private static final ActivityRecord tokenToActivityRecordLocked(Token token) {
562             if (token == null) {
563                 return null;
564             }
565             ActivityRecord r = token.weakActivity.get();
566             if (r == null || r.task == null || r.task.stack == null) {
567                 return null;
568             }
569             return r;
570         }
571 
572         @Override
toString()573         public String toString() {
574             StringBuilder sb = new StringBuilder(128);
575             sb.append("Token{");
576             sb.append(Integer.toHexString(System.identityHashCode(this)));
577             sb.append(' ');
578             sb.append(weakActivity.get());
579             sb.append('}');
580             return sb.toString();
581         }
582     }
583 
forTokenLocked(IBinder token)584     static ActivityRecord forTokenLocked(IBinder token) {
585         try {
586             return Token.tokenToActivityRecordLocked((Token)token);
587         } catch (ClassCastException e) {
588             Slog.w(TAG, "Bad activity token: " + token, e);
589             return null;
590         }
591     }
592 
isResolverActivity()593     boolean isResolverActivity() {
594         return ResolverActivity.class.getName().equals(realActivity.getClassName());
595     }
596 
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified, boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor, ActivityContainer container, ActivityOptions options, ActivityRecord sourceRecord)597     ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
598             int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
599             ActivityInfo aInfo, Configuration _configuration,
600             ActivityRecord _resultTo, String _resultWho, int _reqCode,
601             boolean _componentSpecified, boolean _rootVoiceInteraction,
602             ActivityStackSupervisor supervisor,
603             ActivityContainer container, ActivityOptions options, ActivityRecord sourceRecord) {
604         service = _service;
605         appToken = new Token(this, service);
606         info = aInfo;
607         launchedFromUid = _launchedFromUid;
608         launchedFromPackage = _launchedFromPackage;
609         userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
610         intent = _intent;
611         shortComponentName = _intent.getComponent().flattenToShortString();
612         resolvedType = _resolvedType;
613         componentSpecified = _componentSpecified;
614         rootVoiceInteraction = _rootVoiceInteraction;
615         configuration = _configuration;
616         taskConfigOverride = Configuration.EMPTY;
617         resultTo = _resultTo;
618         resultWho = _resultWho;
619         requestCode = _reqCode;
620         state = ActivityState.INITIALIZING;
621         frontOfTask = false;
622         launchFailed = false;
623         stopped = false;
624         delayedResume = false;
625         finishing = false;
626         deferRelaunchUntilPaused = false;
627         keysPaused = false;
628         inHistory = false;
629         visible = false;
630         nowVisible = false;
631         idle = false;
632         hasBeenLaunched = false;
633         mStackSupervisor = supervisor;
634         mInitialActivityContainer = container;
635         if (options != null) {
636             pendingOptions = options;
637             mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
638             PendingIntent usageReport = pendingOptions.getUsageTimeReport();
639             if (usageReport != null) {
640                 appTimeTracker = new AppTimeTracker(usageReport);
641             }
642         }
643 
644         // This starts out true, since the initial state of an activity
645         // is that we have everything, and we shouldn't never consider it
646         // lacking in state to be removed if it dies.
647         haveState = true;
648 
649         if (aInfo != null) {
650             // If the class name in the intent doesn't match that of the target, this is
651             // probably an alias. We have to create a new ComponentName object to keep track
652             // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
653             if (aInfo.targetActivity == null
654                     || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
655                     && (aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
656                     || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP))) {
657                 realActivity = _intent.getComponent();
658             } else {
659                 realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity);
660             }
661             taskAffinity = aInfo.taskAffinity;
662             stateNotNeeded = (aInfo.flags&
663                     ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0;
664             appInfo = aInfo.applicationInfo;
665             nonLocalizedLabel = aInfo.nonLocalizedLabel;
666             labelRes = aInfo.labelRes;
667             if (nonLocalizedLabel == null && labelRes == 0) {
668                 ApplicationInfo app = aInfo.applicationInfo;
669                 nonLocalizedLabel = app.nonLocalizedLabel;
670                 labelRes = app.labelRes;
671             }
672             icon = aInfo.getIconResource();
673             logo = aInfo.getLogoResource();
674             theme = aInfo.getThemeResource();
675             realTheme = theme;
676             if (realTheme == 0) {
677                 realTheme = aInfo.applicationInfo.targetSdkVersion
678                         < Build.VERSION_CODES.HONEYCOMB
679                         ? android.R.style.Theme
680                         : android.R.style.Theme_Holo;
681             }
682             if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
683                 windowFlags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
684             }
685             if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
686                     && _caller != null
687                     && (aInfo.applicationInfo.uid == Process.SYSTEM_UID
688                             || aInfo.applicationInfo.uid == _caller.info.uid)) {
689                 processName = _caller.processName;
690             } else {
691                 processName = aInfo.processName;
692             }
693 
694             if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) {
695                 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
696             }
697 
698             packageName = aInfo.applicationInfo.packageName;
699             launchMode = aInfo.launchMode;
700 
701             AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
702                     realTheme, com.android.internal.R.styleable.Window, userId);
703             final boolean translucent = ent != null && (ent.array.getBoolean(
704                     com.android.internal.R.styleable.Window_windowIsTranslucent, false)
705                     || (!ent.array.hasValue(
706                             com.android.internal.R.styleable.Window_windowIsTranslucent)
707                             && ent.array.getBoolean(
708                                     com.android.internal.R.styleable.Window_windowSwipeToDismiss,
709                                             false)));
710             fullscreen = ent != null && !ent.array.getBoolean(
711                     com.android.internal.R.styleable.Window_windowIsFloating, false)
712                     && !translucent;
713             noDisplay = ent != null && ent.array.getBoolean(
714                     com.android.internal.R.styleable.Window_windowNoDisplay, false);
715 
716             setActivityType(_componentSpecified, _launchedFromUid, _intent, sourceRecord);
717 
718             immersive = (aInfo.flags & ActivityInfo.FLAG_IMMERSIVE) != 0;
719 
720             requestedVrComponent = (aInfo.requestedVrComponent == null) ?
721                     null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
722         } else {
723             realActivity = null;
724             taskAffinity = null;
725             stateNotNeeded = false;
726             appInfo = null;
727             processName = null;
728             packageName = null;
729             fullscreen = true;
730             noDisplay = false;
731             mActivityType = APPLICATION_ACTIVITY_TYPE;
732             immersive = false;
733             requestedVrComponent  = null;
734         }
735     }
736 
737     private boolean isHomeIntent(Intent intent) {
738         return Intent.ACTION_MAIN.equals(intent.getAction())
739                 && intent.hasCategory(Intent.CATEGORY_HOME)
740                 && intent.getCategories().size() == 1
741                 && intent.getData() == null
742                 && intent.getType() == null;
743     }
744 
745     private boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
746         if (uid == Process.myUid() || uid == 0) {
747             // System process can launch home activity.
748             return true;
749         }
750         // Resolver activity can launch home activity.
751         return sourceRecord != null && sourceRecord.isResolverActivity();
752     }
753 
754     private void setActivityType(boolean componentSpecified,
755             int launchedFromUid, Intent intent, ActivityRecord sourceRecord) {
756         if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
757                 && isHomeIntent(intent) && !isResolverActivity()) {
758             // This sure looks like a home activity!
759             mActivityType = HOME_ACTIVITY_TYPE;
760         } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
761             mActivityType = RECENTS_ACTIVITY_TYPE;
762         } else {
763             mActivityType = APPLICATION_ACTIVITY_TYPE;
764         }
765     }
766 
767     void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
768         if (task != null && task.removeActivity(this) && task != newTask && task.stack != null) {
769             task.stack.removeTask(task, "setTask");
770         }
771         task = newTask;
772         setTaskToAffiliateWith(taskToAffiliateWith);
773     }
774 
775     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
776         if (taskToAffiliateWith != null &&
777                 launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE &&
778                 launchMode != ActivityInfo.LAUNCH_SINGLE_TASK) {
779             task.setTaskToAffiliateWith(taskToAffiliateWith);
780         }
781     }
782 
783     boolean changeWindowTranslucency(boolean toOpaque) {
784         if (fullscreen == toOpaque) {
785             return false;
786         }
787 
788         // Keep track of the number of fullscreen activities in this task.
789         task.numFullscreen += toOpaque ? +1 : -1;
790 
791         fullscreen = toOpaque;
792         return true;
793     }
794 
795     void putInHistory() {
796         if (!inHistory) {
797             inHistory = true;
798         }
799     }
800 
801     void takeFromHistory() {
802         if (inHistory) {
803             inHistory = false;
804             if (task != null && !finishing) {
805                 task = null;
806             }
807             clearOptionsLocked();
808         }
809     }
810 
811     boolean isInHistory() {
812         return inHistory;
813     }
814 
815     boolean isInStackLocked() {
816         return task != null && task.stack != null && task.stack.isInStackLocked(this) != null;
817     }
818 
819     boolean isHomeActivity() {
820         return mActivityType == HOME_ACTIVITY_TYPE;
821     }
822 
823     boolean isRecentsActivity() {
824         return mActivityType == RECENTS_ACTIVITY_TYPE;
825     }
826 
827     boolean isApplicationActivity() {
828         return mActivityType == APPLICATION_ACTIVITY_TYPE;
829     }
830 
831     boolean isPersistable() {
832         return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY ||
833                 info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) &&
834                 (intent == null ||
835                         (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
836     }
837 
838     boolean isFocusable() {
839         return StackId.canReceiveKeys(task.stack.mStackId) || isAlwaysFocusable();
840     }
841 
842     boolean isResizeable() {
843         return !isHomeActivity() && ActivityInfo.isResizeableMode(info.resizeMode);
844     }
845 
846     boolean isResizeableOrForced() {
847         return !isHomeActivity() && (isResizeable() || service.mForceResizableActivities);
848     }
849 
850     boolean isNonResizableOrForced() {
851         return !isHomeActivity() && info.resizeMode != RESIZE_MODE_RESIZEABLE
852                 && info.resizeMode != RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
853     }
854 
855     boolean supportsPictureInPicture() {
856         return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
857     }
858 
859     boolean canGoInDockedStack() {
860         return !isHomeActivity()
861                 && (isResizeableOrForced() || info.resizeMode == RESIZE_MODE_CROP_WINDOWS);
862     }
863 
864     boolean isAlwaysFocusable() {
865         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
866     }
867 
868     void makeFinishingLocked() {
869         if (!finishing) {
870             if (task != null && task.stack != null
871                     && this == task.stack.getVisibleBehindActivity()) {
872                 // A finishing activity should not remain as visible in the background
873                 mStackSupervisor.requestVisibleBehindLocked(this, false);
874             }
875             finishing = true;
876             if (stopped) {
877                 clearOptionsLocked();
878             }
879         }
880     }
881 
882     UriPermissionOwner getUriPermissionsLocked() {
883         if (uriPermissions == null) {
884             uriPermissions = new UriPermissionOwner(service, this);
885         }
886         return uriPermissions;
887     }
888 
889     void addResultLocked(ActivityRecord from, String resultWho,
890             int requestCode, int resultCode,
891             Intent resultData) {
892         ActivityResult r = new ActivityResult(from, resultWho,
893                 requestCode, resultCode, resultData);
894         if (results == null) {
895             results = new ArrayList<ResultInfo>();
896         }
897         results.add(r);
898     }
899 
900     void removeResultsLocked(ActivityRecord from, String resultWho,
901             int requestCode) {
902         if (results != null) {
903             for (int i=results.size()-1; i>=0; i--) {
904                 ActivityResult r = (ActivityResult)results.get(i);
905                 if (r.mFrom != from) continue;
906                 if (r.mResultWho == null) {
907                     if (resultWho != null) continue;
908                 } else {
909                     if (!r.mResultWho.equals(resultWho)) continue;
910                 }
911                 if (r.mRequestCode != requestCode) continue;
912 
913                 results.remove(i);
914             }
915         }
916     }
917 
addNewIntentLocked(ReferrerIntent intent)918     void addNewIntentLocked(ReferrerIntent intent) {
919         if (newIntents == null) {
920             newIntents = new ArrayList<>();
921         }
922         newIntents.add(intent);
923     }
924 
925     /**
926      * Deliver a new Intent to an existing activity, so that its onNewIntent()
927      * method will be called at the proper time.
928      */
deliverNewIntentLocked(int callingUid, Intent intent, String referrer)929     final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
930         // The activity now gets access to the data associated with this Intent.
931         service.grantUriPermissionFromIntentLocked(callingUid, packageName,
932                 intent, getUriPermissionsLocked(), userId);
933         // We want to immediately deliver the intent to the activity if
934         // it is currently the top resumed activity...  however, if the
935         // device is sleeping, then all activities are stopped, so in that
936         // case we will deliver it if this is the current top activity on its
937         // stack.
938         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
939         boolean unsent = true;
940         if ((state == ActivityState.RESUMED
941                 || (service.isSleepingLocked() && task.stack != null
942                     && task.stack.topRunningActivityLocked() == this))
943                 && app != null && app.thread != null) {
944             try {
945                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
946                 ar.add(rintent);
947                 app.thread.scheduleNewIntent(ar, appToken);
948                 unsent = false;
949             } catch (RemoteException e) {
950                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
951             } catch (NullPointerException e) {
952                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
953             }
954         }
955         if (unsent) {
956             addNewIntentLocked(rintent);
957         }
958     }
959 
updateOptionsLocked(ActivityOptions options)960     void updateOptionsLocked(ActivityOptions options) {
961         if (options != null) {
962             if (pendingOptions != null) {
963                 pendingOptions.abort();
964             }
965             pendingOptions = options;
966         }
967     }
968 
applyOptionsLocked()969     void applyOptionsLocked() {
970         if (pendingOptions != null
971                 && pendingOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
972             final int animationType = pendingOptions.getAnimationType();
973             switch (animationType) {
974                 case ActivityOptions.ANIM_CUSTOM:
975                     service.mWindowManager.overridePendingAppTransition(
976                             pendingOptions.getPackageName(),
977                             pendingOptions.getCustomEnterResId(),
978                             pendingOptions.getCustomExitResId(),
979                             pendingOptions.getOnAnimationStartListener());
980                     break;
981                 case ActivityOptions.ANIM_CLIP_REVEAL:
982                     service.mWindowManager.overridePendingAppTransitionClipReveal(
983                             pendingOptions.getStartX(), pendingOptions.getStartY(),
984                             pendingOptions.getWidth(), pendingOptions.getHeight());
985                     if (intent.getSourceBounds() == null) {
986                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
987                                 pendingOptions.getStartY(),
988                                 pendingOptions.getStartX()+pendingOptions.getWidth(),
989                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
990                     }
991                     break;
992                 case ActivityOptions.ANIM_SCALE_UP:
993                     service.mWindowManager.overridePendingAppTransitionScaleUp(
994                             pendingOptions.getStartX(), pendingOptions.getStartY(),
995                             pendingOptions.getWidth(), pendingOptions.getHeight());
996                     if (intent.getSourceBounds() == null) {
997                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
998                                 pendingOptions.getStartY(),
999                                 pendingOptions.getStartX()+pendingOptions.getWidth(),
1000                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
1001                     }
1002                     break;
1003                 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
1004                 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
1005                     boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
1006                     service.mWindowManager.overridePendingAppTransitionThumb(
1007                             pendingOptions.getThumbnail(),
1008                             pendingOptions.getStartX(), pendingOptions.getStartY(),
1009                             pendingOptions.getOnAnimationStartListener(),
1010                             scaleUp);
1011                     if (intent.getSourceBounds() == null) {
1012                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1013                                 pendingOptions.getStartY(),
1014                                 pendingOptions.getStartX()
1015                                         + pendingOptions.getThumbnail().getWidth(),
1016                                 pendingOptions.getStartY()
1017                                         + pendingOptions.getThumbnail().getHeight()));
1018                     }
1019                     break;
1020                 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
1021                 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
1022                     final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
1023                     if (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
1024                             && specs != null) {
1025                         service.mWindowManager.overridePendingAppTransitionMultiThumb(
1026                                 specs, pendingOptions.getOnAnimationStartListener(),
1027                                 pendingOptions.getAnimationFinishedListener(), false);
1028                     } else {
1029                         service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
1030                                 pendingOptions.getThumbnail(),
1031                                 pendingOptions.getStartX(), pendingOptions.getStartY(),
1032                                 pendingOptions.getWidth(), pendingOptions.getHeight(),
1033                                 pendingOptions.getOnAnimationStartListener(),
1034                                 (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
1035                         if (intent.getSourceBounds() == null) {
1036                             intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1037                                     pendingOptions.getStartY(),
1038                                     pendingOptions.getStartX() + pendingOptions.getWidth(),
1039                                     pendingOptions.getStartY() + pendingOptions.getHeight()));
1040                         }
1041                     }
1042                     break;
1043                 default:
1044                     Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
1045                     break;
1046             }
1047             pendingOptions = null;
1048         }
1049     }
1050 
getOptionsForTargetActivityLocked()1051     ActivityOptions getOptionsForTargetActivityLocked() {
1052         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
1053     }
1054 
clearOptionsLocked()1055     void clearOptionsLocked() {
1056         if (pendingOptions != null) {
1057             pendingOptions.abort();
1058             pendingOptions = null;
1059         }
1060     }
1061 
takeOptionsLocked()1062     ActivityOptions takeOptionsLocked() {
1063         ActivityOptions opts = pendingOptions;
1064         pendingOptions = null;
1065         return opts;
1066     }
1067 
removeUriPermissionsLocked()1068     void removeUriPermissionsLocked() {
1069         if (uriPermissions != null) {
1070             uriPermissions.removeUriPermissionsLocked();
1071             uriPermissions = null;
1072         }
1073     }
1074 
pauseKeyDispatchingLocked()1075     void pauseKeyDispatchingLocked() {
1076         if (!keysPaused) {
1077             keysPaused = true;
1078             service.mWindowManager.pauseKeyDispatching(appToken);
1079         }
1080     }
1081 
resumeKeyDispatchingLocked()1082     void resumeKeyDispatchingLocked() {
1083         if (keysPaused) {
1084             keysPaused = false;
1085             service.mWindowManager.resumeKeyDispatching(appToken);
1086         }
1087     }
1088 
updateThumbnailLocked(Bitmap newThumbnail, CharSequence description)1089     void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) {
1090         if (newThumbnail != null) {
1091             if (DEBUG_THUMBNAILS) Slog.i(TAG_THUMBNAILS,
1092                     "Setting thumbnail of " + this + " to " + newThumbnail);
1093             boolean thumbnailUpdated = task.setLastThumbnailLocked(newThumbnail);
1094             if (thumbnailUpdated && isPersistable()) {
1095                 mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
1096             }
1097         }
1098         task.lastDescription = description;
1099     }
1100 
startLaunchTickingLocked()1101     void startLaunchTickingLocked() {
1102         if (ActivityManagerService.IS_USER_BUILD) {
1103             return;
1104         }
1105         if (launchTickTime == 0) {
1106             launchTickTime = SystemClock.uptimeMillis();
1107             continueLaunchTickingLocked();
1108         }
1109     }
1110 
continueLaunchTickingLocked()1111     boolean continueLaunchTickingLocked() {
1112         if (launchTickTime == 0) {
1113             return false;
1114         }
1115 
1116         final ActivityStack stack = task.stack;
1117         if (stack == null) {
1118             return false;
1119         }
1120 
1121         Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
1122         stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
1123         stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
1124         return true;
1125     }
1126 
finishLaunchTickingLocked()1127     void finishLaunchTickingLocked() {
1128         launchTickTime = 0;
1129         final ActivityStack stack = task.stack;
1130         if (stack != null) {
1131             stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
1132         }
1133     }
1134 
1135     // IApplicationToken
1136 
mayFreezeScreenLocked(ProcessRecord app)1137     public boolean mayFreezeScreenLocked(ProcessRecord app) {
1138         // Only freeze the screen if this activity is currently attached to
1139         // an application, and that application is not blocked or unresponding.
1140         // In any other case, we can't count on getting the screen unfrozen,
1141         // so it is best to leave as-is.
1142         return app != null && !app.crashing && !app.notResponding;
1143     }
1144 
startFreezingScreenLocked(ProcessRecord app, int configChanges)1145     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
1146         if (mayFreezeScreenLocked(app)) {
1147             service.mWindowManager.startAppFreezingScreen(appToken, configChanges);
1148         }
1149     }
1150 
stopFreezingScreenLocked(boolean force)1151     public void stopFreezingScreenLocked(boolean force) {
1152         if (force || frozenBeforeDestroy) {
1153             frozenBeforeDestroy = false;
1154             service.mWindowManager.stopAppFreezingScreen(appToken, force);
1155         }
1156     }
1157 
reportFullyDrawnLocked()1158     public void reportFullyDrawnLocked() {
1159         final long curTime = SystemClock.uptimeMillis();
1160         if (displayStartTime != 0) {
1161             reportLaunchTimeLocked(curTime);
1162         }
1163         final ActivityStack stack = task.stack;
1164         if (fullyDrawnStartTime != 0 && stack != null) {
1165             final long thisTime = curTime - fullyDrawnStartTime;
1166             final long totalTime = stack.mFullyDrawnStartTime != 0
1167                     ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
1168             if (SHOW_ACTIVITY_START_TIME) {
1169                 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
1170                 EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME,
1171                         userId, System.identityHashCode(this), shortComponentName,
1172                         thisTime, totalTime);
1173                 StringBuilder sb = service.mStringBuilder;
1174                 sb.setLength(0);
1175                 sb.append("Fully drawn ");
1176                 sb.append(shortComponentName);
1177                 sb.append(": ");
1178                 TimeUtils.formatDuration(thisTime, sb);
1179                 if (thisTime != totalTime) {
1180                     sb.append(" (total ");
1181                     TimeUtils.formatDuration(totalTime, sb);
1182                     sb.append(")");
1183                 }
1184                 Log.i(TAG, sb.toString());
1185             }
1186             if (totalTime > 0) {
1187                 //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
1188             }
1189             stack.mFullyDrawnStartTime = 0;
1190         }
1191         fullyDrawnStartTime = 0;
1192     }
1193 
reportLaunchTimeLocked(final long curTime)1194     private void reportLaunchTimeLocked(final long curTime) {
1195         final ActivityStack stack = task.stack;
1196         if (stack == null) {
1197             return;
1198         }
1199         final long thisTime = curTime - displayStartTime;
1200         final long totalTime = stack.mLaunchStartTime != 0
1201                 ? (curTime - stack.mLaunchStartTime) : thisTime;
1202         if (SHOW_ACTIVITY_START_TIME) {
1203             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
1204             EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
1205                     userId, System.identityHashCode(this), shortComponentName,
1206                     thisTime, totalTime);
1207             StringBuilder sb = service.mStringBuilder;
1208             sb.setLength(0);
1209             sb.append("Displayed ");
1210             sb.append(shortComponentName);
1211             sb.append(": ");
1212             TimeUtils.formatDuration(thisTime, sb);
1213             if (thisTime != totalTime) {
1214                 sb.append(" (total ");
1215                 TimeUtils.formatDuration(totalTime, sb);
1216                 sb.append(")");
1217             }
1218             Log.i(TAG, sb.toString());
1219         }
1220         mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
1221         if (totalTime > 0) {
1222             //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
1223         }
1224         displayStartTime = 0;
1225         stack.mLaunchStartTime = 0;
1226     }
1227 
windowsDrawnLocked()1228     void windowsDrawnLocked() {
1229         mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
1230         if (displayStartTime != 0) {
1231             reportLaunchTimeLocked(SystemClock.uptimeMillis());
1232         }
1233         mStackSupervisor.sendWaitingVisibleReportLocked(this);
1234         startTime = 0;
1235         finishLaunchTickingLocked();
1236         if (task != null) {
1237             task.hasBeenVisible = true;
1238         }
1239     }
1240 
windowsVisibleLocked()1241     void windowsVisibleLocked() {
1242         mStackSupervisor.reportActivityVisibleLocked(this);
1243         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
1244         if (!nowVisible) {
1245             nowVisible = true;
1246             lastVisibleTime = SystemClock.uptimeMillis();
1247             if (!idle) {
1248                 // Instead of doing the full stop routine here, let's just hide any activities
1249                 // we now can, and let them stop when the normal idle happens.
1250                 mStackSupervisor.processStoppingActivitiesLocked(false);
1251             } else {
1252                 // If this activity was already idle, then we now need to make sure we perform
1253                 // the full stop of any activities that are waiting to do so. This is because
1254                 // we won't do that while they are still waiting for this one to become visible.
1255                 final int size = mStackSupervisor.mWaitingVisibleActivities.size();
1256                 if (size > 0) {
1257                     for (int i = 0; i < size; i++) {
1258                         ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
1259                         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
1260                     }
1261                     mStackSupervisor.mWaitingVisibleActivities.clear();
1262                     mStackSupervisor.scheduleIdleLocked();
1263                 }
1264             }
1265             service.scheduleAppGcsLocked();
1266         }
1267     }
1268 
getWaitingHistoryRecordLocked()1269     ActivityRecord getWaitingHistoryRecordLocked() {
1270         // First find the real culprit...  if this activity is waiting for
1271         // another activity to start or has stopped, then the key dispatching
1272         // timeout should not be caused by this.
1273         if (mStackSupervisor.mWaitingVisibleActivities.contains(this) || stopped) {
1274             final ActivityStack stack = mStackSupervisor.getFocusedStack();
1275             // Try to use the one which is closest to top.
1276             ActivityRecord r = stack.mResumedActivity;
1277             if (r == null) {
1278                 r = stack.mPausingActivity;
1279             }
1280             if (r != null) {
1281                 return r;
1282             }
1283         }
1284         return this;
1285     }
1286 
1287     /**
1288      * This method will return true if the activity is either visible, is becoming visible, is
1289      * currently pausing, or is resumed.
1290      */
isInterestingToUserLocked()1291     public boolean isInterestingToUserLocked() {
1292         return visible || nowVisible || state == ActivityState.PAUSING ||
1293                 state == ActivityState.RESUMED;
1294     }
1295 
setSleeping(boolean _sleeping)1296     public void setSleeping(boolean _sleeping) {
1297         if (sleeping == _sleeping) {
1298             return;
1299         }
1300         if (app != null && app.thread != null) {
1301             try {
1302                 app.thread.scheduleSleeping(appToken, _sleeping);
1303                 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
1304                     mStackSupervisor.mGoingToSleepActivities.add(this);
1305                 }
1306                 sleeping = _sleeping;
1307             } catch (RemoteException e) {
1308                 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
1309             }
1310         }
1311     }
1312 
getTaskForActivityLocked(IBinder token, boolean onlyRoot)1313     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
1314         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1315         if (r == null) {
1316             return INVALID_TASK_ID;
1317         }
1318         final TaskRecord task = r.task;
1319         final int activityNdx = task.mActivities.indexOf(r);
1320         if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
1321             return INVALID_TASK_ID;
1322         }
1323         return task.taskId;
1324     }
1325 
isInStackLocked(IBinder token)1326     static ActivityRecord isInStackLocked(IBinder token) {
1327         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1328         return (r != null) ? r.task.stack.isInStackLocked(r) : null;
1329     }
1330 
getStackLocked(IBinder token)1331     static ActivityStack getStackLocked(IBinder token) {
1332         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
1333         if (r != null) {
1334             return r.task.stack;
1335         }
1336         return null;
1337     }
1338 
isDestroyable()1339     final boolean isDestroyable() {
1340         if (finishing || app == null || state == ActivityState.DESTROYING
1341                 || state == ActivityState.DESTROYED) {
1342             // This would be redundant.
1343             return false;
1344         }
1345         if (task == null || task.stack == null || this == task.stack.mResumedActivity
1346                 || this == task.stack.mPausingActivity || !haveState || !stopped) {
1347             // We're not ready for this kind of thing.
1348             return false;
1349         }
1350         if (visible) {
1351             // The user would notice this!
1352             return false;
1353         }
1354         return true;
1355     }
1356 
createImageFilename(long createTime, int taskId)1357     private static String createImageFilename(long createTime, int taskId) {
1358         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
1359                 TaskPersister.IMAGE_EXTENSION;
1360     }
1361 
setTaskDescription(TaskDescription _taskDescription)1362     void setTaskDescription(TaskDescription _taskDescription) {
1363         Bitmap icon;
1364         if (_taskDescription.getIconFilename() == null &&
1365                 (icon = _taskDescription.getIcon()) != null) {
1366             final String iconFilename = createImageFilename(createTime, task.taskId);
1367             final File iconFile = new File(TaskPersister.getUserImagesDir(userId), iconFilename);
1368             final String iconFilePath = iconFile.getAbsolutePath();
1369             service.mRecentTasks.saveImage(icon, iconFilePath);
1370             _taskDescription.setIconFilename(iconFilePath);
1371         }
1372         taskDescription = _taskDescription;
1373     }
1374 
setVoiceSessionLocked(IVoiceInteractionSession session)1375     void setVoiceSessionLocked(IVoiceInteractionSession session) {
1376         voiceSession = session;
1377         pendingVoiceInteractionStart = false;
1378     }
1379 
clearVoiceSessionLocked()1380     void clearVoiceSessionLocked() {
1381         voiceSession = null;
1382         pendingVoiceInteractionStart = false;
1383     }
1384 
showStartingWindow(ActivityRecord prev, boolean createIfNeeded)1385     void showStartingWindow(ActivityRecord prev, boolean createIfNeeded) {
1386         final CompatibilityInfo compatInfo =
1387                 service.compatibilityInfoForPackageLocked(info.applicationInfo);
1388         final boolean shown = service.mWindowManager.setAppStartingWindow(
1389                 appToken, packageName, theme, compatInfo, nonLocalizedLabel, labelRes, icon,
1390                 logo, windowFlags, prev != null ? prev.appToken : null, createIfNeeded);
1391         if (shown) {
1392             mStartingWindowState = STARTING_WINDOW_SHOWN;
1393         }
1394     }
1395 
saveToXml(XmlSerializer out)1396     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
1397         out.attribute(null, ATTR_ID, String.valueOf(createTime));
1398         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
1399         if (launchedFromPackage != null) {
1400             out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
1401         }
1402         if (resolvedType != null) {
1403             out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
1404         }
1405         out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
1406         out.attribute(null, ATTR_USERID, String.valueOf(userId));
1407 
1408         if (taskDescription != null) {
1409             taskDescription.saveToXml(out);
1410         }
1411 
1412         out.startTag(null, TAG_INTENT);
1413         intent.saveToXml(out);
1414         out.endTag(null, TAG_INTENT);
1415 
1416         if (isPersistable() && persistentState != null) {
1417             out.startTag(null, TAG_PERSISTABLEBUNDLE);
1418             persistentState.saveToXml(out);
1419             out.endTag(null, TAG_PERSISTABLEBUNDLE);
1420         }
1421     }
1422 
restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)1423     static ActivityRecord restoreFromXml(XmlPullParser in,
1424             ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
1425         Intent intent = null;
1426         PersistableBundle persistentState = null;
1427         int launchedFromUid = 0;
1428         String launchedFromPackage = null;
1429         String resolvedType = null;
1430         boolean componentSpecified = false;
1431         int userId = 0;
1432         long createTime = -1;
1433         final int outerDepth = in.getDepth();
1434         TaskDescription taskDescription = new TaskDescription();
1435 
1436         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
1437             final String attrName = in.getAttributeName(attrNdx);
1438             final String attrValue = in.getAttributeValue(attrNdx);
1439             if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
1440                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
1441             if (ATTR_ID.equals(attrName)) {
1442                 createTime = Long.valueOf(attrValue);
1443             } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
1444                 launchedFromUid = Integer.parseInt(attrValue);
1445             } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
1446                 launchedFromPackage = attrValue;
1447             } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
1448                 resolvedType = attrValue;
1449             } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
1450                 componentSpecified = Boolean.valueOf(attrValue);
1451             } else if (ATTR_USERID.equals(attrName)) {
1452                 userId = Integer.parseInt(attrValue);
1453             } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
1454                 taskDescription.restoreFromXml(attrName, attrValue);
1455             } else {
1456                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
1457             }
1458         }
1459 
1460         int event;
1461         while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
1462                 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
1463             if (event == XmlPullParser.START_TAG) {
1464                 final String name = in.getName();
1465                 if (TaskPersister.DEBUG)
1466                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
1467                 if (TAG_INTENT.equals(name)) {
1468                     intent = Intent.restoreFromXml(in);
1469                     if (TaskPersister.DEBUG)
1470                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
1471                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
1472                     persistentState = PersistableBundle.restoreFromXml(in);
1473                     if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
1474                             "ActivityRecord: persistentState=" + persistentState);
1475                 } else {
1476                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
1477                     XmlUtils.skipCurrentTag(in);
1478                 }
1479             }
1480         }
1481 
1482         if (intent == null) {
1483             throw new XmlPullParserException("restoreActivity error intent=" + intent);
1484         }
1485 
1486         final ActivityManagerService service = stackSupervisor.mService;
1487         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
1488                 userId);
1489         if (aInfo == null) {
1490             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
1491                     " resolvedType=" + resolvedType);
1492         }
1493         final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid,
1494                 launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(),
1495                 null, null, 0, componentSpecified, false, stackSupervisor, null, null, null);
1496 
1497         r.persistentState = persistentState;
1498         r.taskDescription = taskDescription;
1499         r.createTime = createTime;
1500 
1501         return r;
1502     }
1503 
activityTypeToString(int type)1504     private static String activityTypeToString(int type) {
1505         switch (type) {
1506             case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE";
1507             case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE";
1508             case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE";
1509             default: return Integer.toString(type);
1510         }
1511     }
1512 
1513     @Override
toString()1514     public String toString() {
1515         if (stringName != null) {
1516             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
1517                     (finishing ? " f}" : "}");
1518         }
1519         StringBuilder sb = new StringBuilder(128);
1520         sb.append("ActivityRecord{");
1521         sb.append(Integer.toHexString(System.identityHashCode(this)));
1522         sb.append(" u");
1523         sb.append(userId);
1524         sb.append(' ');
1525         sb.append(intent.getComponent().flattenToShortString());
1526         stringName = sb.toString();
1527         return toString();
1528     }
1529 }
1530