1 /*
2  * Copyright (C) 2018 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.wm;
18 
19 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
21 import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED;
22 import static android.os.Build.VERSION_CODES.Q;
23 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
24 
25 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
26 import static com.android.internal.util.Preconditions.checkArgument;
27 import static com.android.server.am.ActivityManagerService.MY_PID;
28 import static com.android.server.wm.ActivityRecord.State.DESTROYED;
29 import static com.android.server.wm.ActivityRecord.State.DESTROYING;
30 import static com.android.server.wm.ActivityRecord.State.PAUSED;
31 import static com.android.server.wm.ActivityRecord.State.PAUSING;
32 import static com.android.server.wm.ActivityRecord.State.RESUMED;
33 import static com.android.server.wm.ActivityRecord.State.STARTED;
34 import static com.android.server.wm.ActivityRecord.State.STOPPING;
35 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
36 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
37 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
39 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
40 import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS;
41 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
42 
43 import android.Manifest;
44 import android.annotation.NonNull;
45 import android.annotation.Nullable;
46 import android.app.ActivityManager;
47 import android.app.ActivityThread;
48 import android.app.IApplicationThread;
49 import android.app.ProfilerInfo;
50 import android.app.servertransaction.ConfigurationChangeItem;
51 import android.content.Context;
52 import android.content.Intent;
53 import android.content.pm.ActivityInfo;
54 import android.content.pm.ApplicationInfo;
55 import android.content.pm.ServiceInfo;
56 import android.content.res.Configuration;
57 import android.os.Binder;
58 import android.os.Build;
59 import android.os.IBinder;
60 import android.os.LocaleList;
61 import android.os.Message;
62 import android.os.Process;
63 import android.os.RemoteException;
64 import android.util.ArraySet;
65 import android.util.Log;
66 import android.util.Slog;
67 import android.util.proto.ProtoOutputStream;
68 import android.view.IRemoteAnimationRunner;
69 
70 import com.android.internal.annotations.VisibleForTesting;
71 import com.android.internal.app.HeavyWeightSwitcherActivity;
72 import com.android.internal.protolog.common.ProtoLog;
73 import com.android.internal.util.function.pooled.PooledLambda;
74 import com.android.server.Watchdog;
75 import com.android.server.wm.ActivityTaskManagerService.HotPath;
76 
77 import java.io.IOException;
78 import java.io.PrintWriter;
79 import java.lang.ref.WeakReference;
80 import java.util.ArrayList;
81 import java.util.List;
82 
83 /**
84  * The Activity Manager (AM) package manages the lifecycle of processes in the system through
85  * ProcessRecord. However, it is important for the Window Manager (WM) package to be aware
86  * of the processes and their state since it affects how WM manages windows and activities. This
87  * class that allows the ProcessRecord object in the AM package to communicate important
88  * changes to its state to the WM package in a structured way. WM package also uses
89  * {@link WindowProcessListener} to request changes to the process state on the AM side.
90  * Note that public calls into this class are assumed to be originating from outside the
91  * window manager so the window manager lock is held and appropriate permissions are checked before
92  * calls are allowed to proceed.
93  */
94 public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer>
95         implements ConfigurationContainerListener {
96     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM;
97     private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
98     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
99 
100     // all about the first app in the process
101     final ApplicationInfo mInfo;
102     final String mName;
103     final int mUid;
104 
105     // The process of this application; 0 if none
106     private volatile int mPid;
107     // user of process.
108     final int mUserId;
109     // The owner of this window process controller object. Mainly for identification when we
110     // communicate back to the activity manager side.
111     public final Object mOwner;
112     // List of packages running in the process
113     final ArraySet<String> mPkgList = new ArraySet<>();
114     private final WindowProcessListener mListener;
115     private final ActivityTaskManagerService mAtm;
116     private final BackgroundLaunchProcessController mBgLaunchController;
117     // The actual proc...  may be null only if 'persistent' is true (in which case we are in the
118     // process of launching the app)
119     private IApplicationThread mThread;
120     // Currently desired scheduling class
121     private volatile int mCurSchedGroup;
122     // Currently computed process state
123     private volatile int mCurProcState = PROCESS_STATE_NONEXISTENT;
124     // Last reported process state;
125     private volatile int mRepProcState = PROCESS_STATE_NONEXISTENT;
126     // are we in the process of crashing?
127     private volatile boolean mCrashing;
128     // does the app have a not responding dialog?
129     private volatile boolean mNotResponding;
130     // always keep this application running?
131     private volatile boolean mPersistent;
132     // The ABI this process was launched with
133     private volatile String mRequiredAbi;
134     // Running any services that are foreground?
135     private volatile boolean mHasForegroundServices;
136     // Are there any client services with activities?
137     private volatile boolean mHasClientActivities;
138     // Is this process currently showing a non-activity UI that the user is interacting with?
139     // E.g. The status bar when it is expanded, but not when it is minimized. When true the process
140     // will be set to use the ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost performance.
141     private volatile boolean mHasTopUi;
142     // Is the process currently showing a non-activity UI that overlays on-top of activity UIs on
143     // screen. E.g. display a window of type
144     // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY When true the process will
145     // oom adj score will be set to ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance
146     // of the process getting killed.
147     private volatile boolean mHasOverlayUi;
148     // Want to clean up resources from showing UI?
149     private volatile boolean mPendingUiClean;
150     // The time we sent the last interaction event
151     private volatile long mInteractionEventTime;
152     // When we became foreground for interaction purposes
153     private volatile long mFgInteractionTime;
154     // When (uptime) the process last became unimportant
155     private volatile long mWhenUnimportant;
156     // was app launched for debugging?
157     private volatile boolean mDebugging;
158     // Active instrumentation running in process?
159     private volatile boolean mInstrumenting;
160     // If there is active instrumentation, this is the source
161     private volatile int mInstrumentationSourceUid = -1;
162     // Active instrumentation with background activity starts privilege running in process?
163     private volatile boolean mInstrumentingWithBackgroundActivityStartPrivileges;
164     // This process it perceptible by the user.
165     private volatile boolean mPerceptible;
166     // Set to true when process was launched with a wrapper attached
167     private volatile boolean mUsingWrapper;
168 
169     // Thread currently set for VR scheduling
170     int mVrThreadTid;
171 
172     // Whether this process has ever started a service with the BIND_INPUT_METHOD permission.
173     private volatile boolean mHasImeService;
174 
175     /** Whether {@link #mActivities} is not empty. */
176     private volatile boolean mHasActivities;
177     /** All activities running in the process (exclude destroying). */
178     private final ArrayList<ActivityRecord> mActivities = new ArrayList<>();
179     /** The activities will be removed but still belong to this process. */
180     private ArrayList<ActivityRecord> mInactiveActivities;
181     /** Whether {@link #mRecentTasks} is not empty. */
182     private volatile boolean mHasRecentTasks;
183     // any tasks this process had run root activities in
184     private final ArrayList<Task> mRecentTasks = new ArrayList<>();
185     // The most recent top-most activity that was resumed in the process for pre-Q app.
186     private ActivityRecord mPreQTopResumedActivity = null;
187     // The last time an activity was launched in the process
188     private volatile long mLastActivityLaunchTime;
189     // The last time an activity was finished in the process while the process participated
190     // in a visible task
191     private volatile long mLastActivityFinishTime;
192 
193     // Last configuration that was reported to the process.
194     private final Configuration mLastReportedConfiguration = new Configuration();
195     /** Whether the process configuration is waiting to be dispatched to the process. */
196     private boolean mHasPendingConfigurationChange;
197 
198     /**
199      * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
200      * registered.
201      */
202     @Nullable
203     private DisplayArea mDisplayArea;
204     private ActivityRecord mConfigActivityRecord;
205     // Whether the activity config override is allowed for this process.
206     private volatile boolean mIsActivityConfigOverrideAllowed = true;
207     /** Non-zero to pause dispatching process configuration change. */
208     private int mPauseConfigurationDispatchCount;
209 
210     /**
211      * Activities that hosts some UI drawn by the current process. The activities live
212      * in another process. This is used to check if the process is currently showing anything
213      * visible to the user.
214      */
215     @Nullable
216     private final ArrayList<ActivityRecord> mHostActivities = new ArrayList<>();
217 
218     /** Whether our process is currently running a {@link RecentsAnimation} */
219     private boolean mRunningRecentsAnimation;
220 
221     /** Whether our process is currently running a {@link IRemoteAnimationRunner} */
222     private boolean mRunningRemoteAnimation;
223 
224     /** List of "chained" processes that are running remote animations for this process */
225     private final ArrayList<WeakReference<WindowProcessController>> mRemoteAnimationDelegates =
226             new ArrayList<>();
227 
228     // The bits used for mActivityStateFlags.
229     private static final int ACTIVITY_STATE_FLAG_IS_VISIBLE = 1 << 16;
230     private static final int ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED = 1 << 17;
231     private static final int ACTIVITY_STATE_FLAG_IS_STOPPING = 1 << 18;
232     private static final int ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING = 1 << 19;
233     private static final int ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE = 1 << 20;
234     private static final int ACTIVITY_STATE_FLAG_HAS_RESUMED = 1 << 21;
235     private static final int ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK = 1 << 22;
236     private static final int ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER = 0x0000ffff;
237 
238     /**
239      * The state for oom-adjustment calculation. The higher 16 bits are the activity states, and the
240      * lower 16 bits are the task layer rank (see {@link Task#mLayerRank}). This field is written by
241      * window manager and read by activity manager.
242      */
243     private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
244 
WindowProcessController(@onNull ActivityTaskManagerService atm, @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner, @NonNull WindowProcessListener listener)245     public WindowProcessController(@NonNull ActivityTaskManagerService atm,
246             @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner,
247             @NonNull WindowProcessListener listener) {
248         mInfo = info;
249         mName = name;
250         mUid = uid;
251         mUserId = userId;
252         mOwner = owner;
253         mListener = listener;
254         mAtm = atm;
255         mBgLaunchController = new BackgroundLaunchProcessController(
256                 atm::hasActiveVisibleWindow, atm.getBackgroundActivityStartCallback());
257 
258         boolean isSysUiPackage = info.packageName.equals(
259                 mAtm.getSysUiServiceComponentLocked().getPackageName());
260         if (isSysUiPackage || mUid == Process.SYSTEM_UID) {
261             // This is a system owned process and should not use an activity config.
262             // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs.
263             mIsActivityConfigOverrideAllowed = false;
264         }
265 
266         onConfigurationChanged(atm.getGlobalConfiguration());
267         mAtm.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, mInfo.packageName);
268     }
269 
setPid(int pid)270     public void setPid(int pid) {
271         mPid = pid;
272     }
273 
getPid()274     public int getPid() {
275         return mPid;
276     }
277 
278     @HotPath(caller = HotPath.PROCESS_CHANGE)
setThread(IApplicationThread thread)279     public void setThread(IApplicationThread thread) {
280         synchronized (mAtm.mGlobalLockWithoutBoost) {
281             mThread = thread;
282             // In general this is called from attaching application, so the last configuration
283             // has been sent to client by {@link android.app.IApplicationThread#bindApplication}.
284             // If this process is system server, it is fine because system is booting and a new
285             // configuration will update when display is ready.
286             if (thread != null) {
287                 setLastReportedConfiguration(getConfiguration());
288             } else {
289                 // The process is inactive.
290                 mAtm.mVisibleActivityProcessTracker.removeProcess(this);
291             }
292         }
293     }
294 
getThread()295     IApplicationThread getThread() {
296         return mThread;
297     }
298 
hasThread()299     boolean hasThread() {
300         return mThread != null;
301     }
302 
setCurrentSchedulingGroup(int curSchedGroup)303     public void setCurrentSchedulingGroup(int curSchedGroup) {
304         mCurSchedGroup = curSchedGroup;
305     }
306 
getCurrentSchedulingGroup()307     int getCurrentSchedulingGroup() {
308         return mCurSchedGroup;
309     }
310 
setCurrentProcState(int curProcState)311     public void setCurrentProcState(int curProcState) {
312         mCurProcState = curProcState;
313     }
314 
getCurrentProcState()315     int getCurrentProcState() {
316         return mCurProcState;
317     }
318 
setReportedProcState(int repProcState)319     public void setReportedProcState(int repProcState) {
320         mRepProcState = repProcState;
321     }
322 
getReportedProcState()323     int getReportedProcState() {
324         return mRepProcState;
325     }
326 
setCrashing(boolean crashing)327     public void setCrashing(boolean crashing) {
328         mCrashing = crashing;
329     }
330 
isCrashing()331     boolean isCrashing() {
332         return mCrashing;
333     }
334 
setNotResponding(boolean notResponding)335     public void setNotResponding(boolean notResponding) {
336         mNotResponding = notResponding;
337     }
338 
isNotResponding()339     boolean isNotResponding() {
340         return mNotResponding;
341     }
342 
setPersistent(boolean persistent)343     public void setPersistent(boolean persistent) {
344         mPersistent = persistent;
345     }
346 
isPersistent()347     boolean isPersistent() {
348         return mPersistent;
349     }
350 
setHasForegroundServices(boolean hasForegroundServices)351     public void setHasForegroundServices(boolean hasForegroundServices) {
352         mHasForegroundServices = hasForegroundServices;
353     }
354 
hasForegroundServices()355     boolean hasForegroundServices() {
356         return mHasForegroundServices;
357     }
358 
hasForegroundActivities()359     boolean hasForegroundActivities() {
360         return mAtm.mTopApp == this || (mActivityStateFlags
361                 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED
362                         | ACTIVITY_STATE_FLAG_IS_STOPPING)) != 0;
363     }
364 
setHasClientActivities(boolean hasClientActivities)365     public void setHasClientActivities(boolean hasClientActivities) {
366         mHasClientActivities = hasClientActivities;
367     }
368 
hasClientActivities()369     boolean hasClientActivities() {
370         return mHasClientActivities;
371     }
372 
setHasTopUi(boolean hasTopUi)373     public void setHasTopUi(boolean hasTopUi) {
374         mHasTopUi = hasTopUi;
375     }
376 
hasTopUi()377     boolean hasTopUi() {
378         return mHasTopUi;
379     }
380 
setHasOverlayUi(boolean hasOverlayUi)381     public void setHasOverlayUi(boolean hasOverlayUi) {
382         mHasOverlayUi = hasOverlayUi;
383     }
384 
hasOverlayUi()385     boolean hasOverlayUi() {
386         return mHasOverlayUi;
387     }
388 
setPendingUiClean(boolean hasPendingUiClean)389     public void setPendingUiClean(boolean hasPendingUiClean) {
390         mPendingUiClean = hasPendingUiClean;
391     }
392 
hasPendingUiClean()393     boolean hasPendingUiClean() {
394         return mPendingUiClean;
395     }
396 
397     /** @return {@code true} if the process registered to a display area as a config listener. */
registeredForDisplayAreaConfigChanges()398     boolean registeredForDisplayAreaConfigChanges() {
399         return mDisplayArea != null;
400     }
401 
402     /** @return {@code true} if the process registered to an activity as a config listener. */
403     @VisibleForTesting
registeredForActivityConfigChanges()404     boolean registeredForActivityConfigChanges() {
405         return mConfigActivityRecord != null;
406     }
407 
postPendingUiCleanMsg(boolean pendingUiClean)408     void postPendingUiCleanMsg(boolean pendingUiClean) {
409         // Posting on handler so WM lock isn't held when we call into AM.
410         final Message m = PooledLambda.obtainMessage(
411                 WindowProcessListener::setPendingUiClean, mListener, pendingUiClean);
412         mAtm.mH.sendMessage(m);
413     }
414 
setInteractionEventTime(long interactionEventTime)415     public void setInteractionEventTime(long interactionEventTime) {
416         mInteractionEventTime = interactionEventTime;
417     }
418 
getInteractionEventTime()419     long getInteractionEventTime() {
420         return mInteractionEventTime;
421     }
422 
setFgInteractionTime(long fgInteractionTime)423     public void setFgInteractionTime(long fgInteractionTime) {
424         mFgInteractionTime = fgInteractionTime;
425     }
426 
getFgInteractionTime()427     long getFgInteractionTime() {
428         return mFgInteractionTime;
429     }
430 
setWhenUnimportant(long whenUnimportant)431     public void setWhenUnimportant(long whenUnimportant) {
432         mWhenUnimportant = whenUnimportant;
433     }
434 
getWhenUnimportant()435     long getWhenUnimportant() {
436         return mWhenUnimportant;
437     }
438 
setRequiredAbi(String requiredAbi)439     public void setRequiredAbi(String requiredAbi) {
440         mRequiredAbi = requiredAbi;
441     }
442 
getRequiredAbi()443     String getRequiredAbi() {
444         return mRequiredAbi;
445     }
446 
447     /**
448      * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
449      * registered.
450      */
451     @VisibleForTesting
452     @Nullable
getDisplayArea()453     DisplayArea getDisplayArea() {
454         return mDisplayArea;
455     }
456 
setDebugging(boolean debugging)457     public void setDebugging(boolean debugging) {
458         mDebugging = debugging;
459     }
460 
isDebugging()461     boolean isDebugging() {
462         return mDebugging;
463     }
464 
setUsingWrapper(boolean usingWrapper)465     public void setUsingWrapper(boolean usingWrapper) {
466         mUsingWrapper = usingWrapper;
467     }
468 
isUsingWrapper()469     boolean isUsingWrapper() {
470         return mUsingWrapper;
471     }
472 
hasEverLaunchedActivity()473     boolean hasEverLaunchedActivity() {
474         return mLastActivityLaunchTime > 0;
475     }
476 
setLastActivityLaunchTime(long launchTime)477     void setLastActivityLaunchTime(long launchTime) {
478         if (launchTime <= mLastActivityLaunchTime) {
479             if (launchTime < mLastActivityLaunchTime) {
480                 Slog.w(TAG,
481                         "Tried to set launchTime (" + launchTime + ") < mLastActivityLaunchTime ("
482                                 + mLastActivityLaunchTime + ")");
483             }
484             return;
485         }
486         mLastActivityLaunchTime = launchTime;
487     }
488 
setLastActivityFinishTimeIfNeeded(long finishTime)489     void setLastActivityFinishTimeIfNeeded(long finishTime) {
490         if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) {
491             return;
492         }
493         mLastActivityFinishTime = finishTime;
494     }
495 
496     /**
497      * @see BackgroundLaunchProcessController#addOrUpdateAllowBackgroundActivityStartsToken(Binder,
498      * IBinder)
499      */
addOrUpdateAllowBackgroundActivityStartsToken(Binder entity, @Nullable IBinder originatingToken)500     public void addOrUpdateAllowBackgroundActivityStartsToken(Binder entity,
501             @Nullable IBinder originatingToken) {
502         mBgLaunchController.addOrUpdateAllowBackgroundActivityStartsToken(entity, originatingToken);
503     }
504 
505     /** @see BackgroundLaunchProcessController#removeAllowBackgroundActivityStartsToken(Binder) */
removeAllowBackgroundActivityStartsToken(Binder entity)506     public void removeAllowBackgroundActivityStartsToken(Binder entity) {
507         mBgLaunchController.removeAllowBackgroundActivityStartsToken(entity);
508     }
509 
510     /**
511      * Is this WindowProcessController in the state of allowing background FGS start?
512      */
513     @HotPath(caller = HotPath.START_SERVICE)
areBackgroundFgsStartsAllowed()514     public boolean areBackgroundFgsStartsAllowed() {
515         return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesState(),
516                 true /* isCheckingForFgsStart */);
517     }
518 
areBackgroundActivityStartsAllowed(int appSwitchState)519     boolean areBackgroundActivityStartsAllowed(int appSwitchState) {
520         return areBackgroundActivityStartsAllowed(appSwitchState,
521                 false /* isCheckingForFgsStart */);
522     }
523 
areBackgroundActivityStartsAllowed(int appSwitchState, boolean isCheckingForFgsStart)524     private boolean areBackgroundActivityStartsAllowed(int appSwitchState,
525             boolean isCheckingForFgsStart) {
526         return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, mInfo.packageName,
527                 appSwitchState, isCheckingForFgsStart, hasActivityInVisibleTask(),
528                 mInstrumentingWithBackgroundActivityStartPrivileges,
529                 mAtm.getLastStopAppSwitchesTime(),
530                 mLastActivityLaunchTime, mLastActivityFinishTime);
531     }
532 
533     /**
534      * Returns whether this process is allowed to close system dialogs via a background activity
535      * start token that allows the close system dialogs operation (eg. notification).
536      */
canCloseSystemDialogsByToken()537     boolean canCloseSystemDialogsByToken() {
538         return mBgLaunchController.canCloseSystemDialogsByToken(mUid);
539     }
540 
setBoundClientUids(ArraySet<Integer> boundClientUids)541     public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
542         mBgLaunchController.setBoundClientUids(boundClientUids);
543     }
544 
545     /**
546      * Set instrumentation-related info.
547      *
548      * If {@code instrumenting} is {@code false}, {@code sourceUid} has to be -1.
549      */
setInstrumenting(boolean instrumenting, int sourceUid, boolean hasBackgroundActivityStartPrivileges)550     public void setInstrumenting(boolean instrumenting, int sourceUid,
551             boolean hasBackgroundActivityStartPrivileges) {
552         checkArgument(instrumenting || sourceUid == -1);
553         mInstrumenting = instrumenting;
554         mInstrumentationSourceUid = sourceUid;
555         mInstrumentingWithBackgroundActivityStartPrivileges = hasBackgroundActivityStartPrivileges;
556     }
557 
isInstrumenting()558     boolean isInstrumenting() {
559         return mInstrumenting;
560     }
561 
562     /** Returns the uid of the active instrumentation source if there is one, otherwise -1. */
getInstrumentationSourceUid()563     int getInstrumentationSourceUid() {
564         return mInstrumentationSourceUid;
565     }
566 
setPerceptible(boolean perceptible)567     public void setPerceptible(boolean perceptible) {
568         mPerceptible = perceptible;
569     }
570 
isPerceptible()571     boolean isPerceptible() {
572         return mPerceptible;
573     }
574 
575     @Override
getChildCount()576     protected int getChildCount() {
577         return 0;
578     }
579 
580     @Override
getChildAt(int index)581     protected ConfigurationContainer getChildAt(int index) {
582         return null;
583     }
584 
585     @Override
getParent()586     protected ConfigurationContainer getParent() {
587         // Returning RootWindowContainer as the parent, so that this process controller always
588         // has full configuration and overrides (e.g. from display) are always added on top of
589         // global config.
590         return mAtm.mRootWindowContainer;
591     }
592 
593     @HotPath(caller = HotPath.PROCESS_CHANGE)
addPackage(String packageName)594     public void addPackage(String packageName) {
595         synchronized (mAtm.mGlobalLockWithoutBoost) {
596             mPkgList.add(packageName);
597         }
598     }
599 
600     @HotPath(caller = HotPath.PROCESS_CHANGE)
clearPackageList()601     public void clearPackageList() {
602         synchronized (mAtm.mGlobalLockWithoutBoost) {
603             mPkgList.clear();
604         }
605     }
606 
addActivityIfNeeded(ActivityRecord r)607     void addActivityIfNeeded(ActivityRecord r) {
608         // even if we already track this activity, note down that it has been launched
609         setLastActivityLaunchTime(r.lastLaunchTime);
610         if (mActivities.contains(r)) {
611             return;
612         }
613         mActivities.add(r);
614         mHasActivities = true;
615         if (mInactiveActivities != null) {
616             mInactiveActivities.remove(r);
617         }
618         updateActivityConfigurationListener();
619     }
620 
621     /**
622      * Indicates that the given activity is no longer active in this process.
623      *
624      * @param r The running activity to be removed.
625      * @param keepAssociation {@code true} if the activity still belongs to this process but will
626      *                        be removed soon, e.g. destroying. From the perspective of process
627      *                        priority, the process is not important if it only contains activities
628      *                        that are being destroyed. But the association is still needed to
629      *                        ensure all activities are reachable from this process.
630      */
removeActivity(ActivityRecord r, boolean keepAssociation)631     void removeActivity(ActivityRecord r, boolean keepAssociation) {
632         if (keepAssociation) {
633             if (mInactiveActivities == null) {
634                 mInactiveActivities = new ArrayList<>();
635                 mInactiveActivities.add(r);
636             } else if (!mInactiveActivities.contains(r)) {
637                 mInactiveActivities.add(r);
638             }
639         } else if (mInactiveActivities != null) {
640             mInactiveActivities.remove(r);
641         }
642         mActivities.remove(r);
643         mHasActivities = !mActivities.isEmpty();
644         updateActivityConfigurationListener();
645     }
646 
clearActivities()647     void clearActivities() {
648         mInactiveActivities = null;
649         mActivities.clear();
650         mHasActivities = false;
651         updateActivityConfigurationListener();
652     }
653 
654     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
hasActivities()655     public boolean hasActivities() {
656         return mHasActivities;
657     }
658 
659     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
hasVisibleActivities()660     public boolean hasVisibleActivities() {
661         return (mActivityStateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0;
662     }
663 
hasActivityInVisibleTask()664     boolean hasActivityInVisibleTask() {
665         return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0;
666     }
667 
668     @HotPath(caller = HotPath.LRU_UPDATE)
hasActivitiesOrRecentTasks()669     public boolean hasActivitiesOrRecentTasks() {
670         return mHasActivities || mHasRecentTasks;
671     }
672 
673     @Nullable
getTopActivityDisplayArea()674     TaskDisplayArea getTopActivityDisplayArea() {
675         if (mActivities.isEmpty()) {
676             return null;
677         }
678 
679         final int lastIndex = mActivities.size() - 1;
680         ActivityRecord topRecord = mActivities.get(lastIndex);
681         TaskDisplayArea displayArea = topRecord.getDisplayArea();
682 
683         for (int index = lastIndex - 1; index >= 0; --index) {
684             ActivityRecord nextRecord = mActivities.get(index);
685             TaskDisplayArea nextDisplayArea = nextRecord.getDisplayArea();
686             if (nextRecord.compareTo(topRecord) > 0 && nextDisplayArea != null) {
687                 topRecord = nextRecord;
688                 displayArea = nextDisplayArea;
689             }
690         }
691 
692         return displayArea;
693     }
694 
695     /**
696      * Update the top resuming activity in process for pre-Q apps, only the top-most visible
697      * activities are allowed to be resumed per process.
698      * @return {@code true} if the activity is allowed to be resumed by compatibility
699      * restrictions, which the activity was the topmost visible activity in process or the app is
700      * targeting after Q. Note that non-focusable activity, in picture-in-picture mode for instance,
701      * does not count as a topmost activity.
702      */
updateTopResumingActivityInProcessIfNeeded(@onNull ActivityRecord activity)703     boolean updateTopResumingActivityInProcessIfNeeded(@NonNull ActivityRecord activity) {
704         if (mInfo.targetSdkVersion >= Q || mPreQTopResumedActivity == activity) {
705             return true;
706         }
707 
708         if (!activity.isAttached()) {
709             // No need to update if the activity hasn't attach to any display.
710             return false;
711         }
712 
713         boolean canUpdate = false;
714         final DisplayContent topDisplay =
715                 (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isAttached())
716                         ? mPreQTopResumedActivity.mDisplayContent
717                         : null;
718         // Update the topmost activity if current top activity is
719         // - not on any display OR
720         // - no longer visible OR
721         // - not focusable (in PiP mode for instance)
722         if (topDisplay == null
723                 || !mPreQTopResumedActivity.mVisibleRequested
724                 || !mPreQTopResumedActivity.isFocusable()) {
725             canUpdate = true;
726         }
727 
728         final DisplayContent display = activity.mDisplayContent;
729         // Update the topmost activity if the current top activity wasn't on top of the other one.
730         if (!canUpdate && topDisplay.compareTo(display) < 0) {
731             canUpdate = true;
732         }
733 
734         // Update the topmost activity if the activity has higher z-order than the current
735         // top-resumed activity.
736         if (!canUpdate) {
737             final ActivityRecord ar = topDisplay.getActivity(r -> r == activity,
738                     true /* traverseTopToBottom */, mPreQTopResumedActivity);
739             if (ar != null && ar != mPreQTopResumedActivity) {
740                 canUpdate = true;
741             }
742         }
743 
744         if (canUpdate) {
745             // Make sure the previous top activity in the process no longer be resumed.
746             if (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isState(RESUMED)) {
747                 final TaskFragment taskFrag = mPreQTopResumedActivity.getTaskFragment();
748                 if (taskFrag != null) {
749                     boolean userLeaving = taskFrag.shouldBeVisible(null);
750                     taskFrag.startPausing(userLeaving, false /* uiSleeping */,
751                             activity, "top-resumed-changed");
752                 }
753             }
754             mPreQTopResumedActivity = activity;
755         }
756         return canUpdate;
757     }
758 
stopFreezingActivities()759     public void stopFreezingActivities() {
760         synchronized (mAtm.mGlobalLock) {
761             int i = mActivities.size();
762             while (i > 0) {
763                 i--;
764                 mActivities.get(i).stopFreezingScreenLocked(true);
765             }
766         }
767     }
768 
finishActivities()769     void finishActivities() {
770         ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities);
771         for (int i = 0; i < activities.size(); i++) {
772             final ActivityRecord r = activities.get(i);
773             if (!r.finishing && r.isInRootTaskLocked()) {
774                 r.finishIfPossible("finish-heavy", true /* oomAdj */);
775             }
776         }
777     }
778 
isInterestingToUser()779     public boolean isInterestingToUser() {
780         synchronized (mAtm.mGlobalLock) {
781             final int size = mActivities.size();
782             for (int i = 0; i < size; i++) {
783                 ActivityRecord r = mActivities.get(i);
784                 if (r.isInterestingToUserLocked()) {
785                     return true;
786                 }
787             }
788             if (isEmbedded()) {
789                 return true;
790             }
791         }
792         return false;
793     }
794 
795     /**
796      * @return {@code true} if this process is rendering content on to a window shown by
797      * another process.
798      */
isEmbedded()799     private boolean isEmbedded() {
800         for (int i = mHostActivities.size() - 1; i >= 0; --i) {
801             final ActivityRecord r = mHostActivities.get(i);
802             if (r.isInterestingToUserLocked()) {
803                 return true;
804             }
805         }
806         return false;
807     }
808 
hasRunningActivity(String packageName)809     public boolean hasRunningActivity(String packageName) {
810         synchronized (mAtm.mGlobalLock) {
811             for (int i = mActivities.size() - 1; i >= 0; --i) {
812                 final ActivityRecord r = mActivities.get(i);
813                 if (packageName.equals(r.packageName)) {
814                     return true;
815                 }
816             }
817         }
818         return false;
819     }
820 
821     // TODO(b/199277065): Re-assess how app-specific locales are applied based on UXR
822     // TODO(b/199277729): Consider whether we need to add special casing for edge cases like
823     //  activity-embeddings etc.
updateAppSpecificSettingsForAllActivities(Integer nightMode, LocaleList localesOverride)824     void updateAppSpecificSettingsForAllActivities(Integer nightMode, LocaleList localesOverride) {
825         for (int i = mActivities.size() - 1; i >= 0; --i) {
826             final ActivityRecord r = mActivities.get(i);
827             if (r.applyAppSpecificConfig(nightMode, localesOverride) && r.mVisibleRequested) {
828                 r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */);
829             }
830         }
831     }
832 
clearPackagePreferredForHomeActivities()833     public void clearPackagePreferredForHomeActivities() {
834         synchronized (mAtm.mGlobalLock) {
835             for (int i = mActivities.size() - 1; i >= 0; --i) {
836                 final ActivityRecord r = mActivities.get(i);
837                 if (r.isActivityTypeHome()) {
838                     Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
839                     try {
840                         ActivityThread.getPackageManager()
841                                 .clearPackagePreferredActivities(r.packageName);
842                     } catch (RemoteException c) {
843                         // pm is in same process, this will never happen.
844                     }
845                 }
846             }
847         }
848     }
849 
hasStartedActivity(ActivityRecord launchedActivity)850     boolean hasStartedActivity(ActivityRecord launchedActivity) {
851         for (int i = mActivities.size() - 1; i >= 0; i--) {
852             final ActivityRecord activity = mActivities.get(i);
853             if (launchedActivity == activity) {
854                 continue;
855             }
856             if (!activity.stopped) {
857                 return true;
858             }
859         }
860         return false;
861     }
862 
hasResumedActivity()863     boolean hasResumedActivity() {
864         return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0;
865     }
866 
updateIntentForHeavyWeightActivity(Intent intent)867     void updateIntentForHeavyWeightActivity(Intent intent) {
868         if (mActivities.isEmpty()) {
869             return;
870         }
871         ActivityRecord hist = mActivities.get(0);
872         intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
873         intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().mTaskId);
874     }
875 
shouldKillProcessForRemovedTask(Task task)876     boolean shouldKillProcessForRemovedTask(Task task) {
877         for (int k = 0; k < mActivities.size(); k++) {
878             final ActivityRecord activity = mActivities.get(k);
879             if (!activity.stopped) {
880                 // Don't kill process(es) that has an activity not stopped.
881                 return false;
882             }
883             final Task otherTask = activity.getTask();
884             if (task.mTaskId != otherTask.mTaskId && otherTask.inRecents) {
885                 // Don't kill process(es) that has an activity in a different task that is
886                 // also in recents.
887                 return false;
888             }
889         }
890         return true;
891     }
892 
releaseSomeActivities(String reason)893     void releaseSomeActivities(String reason) {
894         // Examine all activities currently running in the process.
895         // Candidate activities that can be destroyed.
896         ArrayList<ActivityRecord> candidates = null;
897         if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + this);
898         for (int i = 0; i < mActivities.size(); i++) {
899             final ActivityRecord r = mActivities.get(i);
900             // First, if we find an activity that is in the process of being destroyed,
901             // then we just aren't going to do anything for now; we want things to settle
902             // down before we try to prune more activities.
903             if (r.finishing || r.isState(DESTROYING, DESTROYED)) {
904                 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r);
905                 return;
906             }
907             // Don't consider any activities that are currently not in a state where they
908             // can be destroyed.
909             if (r.mVisibleRequested || !r.stopped || !r.hasSavedState() || !r.isDestroyable()
910                     || r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING)) {
911                 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
912                 continue;
913             }
914 
915             if (r.getParent() != null) {
916                 if (candidates == null) {
917                     candidates = new ArrayList<>();
918                 }
919                 candidates.add(r);
920             }
921         }
922 
923         if (candidates != null) {
924             // Sort based on z-order in hierarchy.
925             candidates.sort(WindowContainer::compareTo);
926             // Release some older activities
927             int maxRelease = Math.max(candidates.size(), 1);
928             do {
929                 final ActivityRecord r = candidates.remove(0);
930                 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + r
931                         + " in state " + r.getState() + " for reason " + reason);
932                 r.destroyImmediately(reason);
933                 --maxRelease;
934             } while (maxRelease > 0);
935         }
936     }
937 
938     /**
939      * Returns display UI context list which there is any app window shows or starting activities
940      * int this process.
941      */
getDisplayContextsWithErrorDialogs(List<Context> displayContexts)942     public void getDisplayContextsWithErrorDialogs(List<Context> displayContexts) {
943         if (displayContexts == null) {
944             return;
945         }
946         synchronized (mAtm.mGlobalLock) {
947             final RootWindowContainer root = mAtm.mWindowManager.mRoot;
948             root.getDisplayContextsWithNonToastVisibleWindows(mPid, displayContexts);
949 
950             for (int i = mActivities.size() - 1; i >= 0; --i) {
951                 final ActivityRecord r = mActivities.get(i);
952                 final int displayId = r.getDisplayId();
953                 final Context c = root.getDisplayUiContext(displayId);
954 
955                 if (c != null && r.mVisibleRequested && !displayContexts.contains(c)) {
956                     displayContexts.add(c);
957                 }
958             }
959         }
960     }
961 
962     /** Adds an activity that hosts UI drawn by the current process. */
addHostActivity(ActivityRecord r)963     void addHostActivity(ActivityRecord r) {
964         if (mHostActivities.contains(r)) {
965             return;
966         }
967         mHostActivities.add(r);
968     }
969 
970     /** Removes an activity that hosts UI drawn by the current process. */
removeHostActivity(ActivityRecord r)971     void removeHostActivity(ActivityRecord r) {
972         mHostActivities.remove(r);
973     }
974 
975     public interface ComputeOomAdjCallback {
onVisibleActivity()976         void onVisibleActivity();
onPausedActivity()977         void onPausedActivity();
onStoppingActivity(boolean finishing)978         void onStoppingActivity(boolean finishing);
onOtherActivity()979         void onOtherActivity();
980     }
981 
982     /**
983      * Returns the minimum task layer rank. It should only be called if {@link #hasActivities}
984      * returns {@code true}.
985      */
986     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
computeOomAdjFromActivities(ComputeOomAdjCallback callback)987     public int computeOomAdjFromActivities(ComputeOomAdjCallback callback) {
988         final int flags = mActivityStateFlags;
989         if ((flags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) {
990             callback.onVisibleActivity();
991         } else if ((flags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) {
992             callback.onPausedActivity();
993         } else if ((flags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) {
994             callback.onStoppingActivity(
995                     (flags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0);
996         } else {
997             callback.onOtherActivity();
998         }
999         return flags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
1000     }
1001 
computeProcessActivityState()1002     void computeProcessActivityState() {
1003         // Since there could be more than one activities in a process record, we don't need to
1004         // compute the OomAdj with each of them, just need to find out the activity with the
1005         // "best" state, the order would be visible, pausing, stopping...
1006         ActivityRecord.State bestInvisibleState = DESTROYED;
1007         boolean allStoppingFinishing = true;
1008         boolean visible = false;
1009         int minTaskLayer = Integer.MAX_VALUE;
1010         int stateFlags = 0;
1011         final boolean wasResumed = hasResumedActivity();
1012         final boolean wasAnyVisible = (mActivityStateFlags
1013                 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
1014         for (int i = mActivities.size() - 1; i >= 0; i--) {
1015             final ActivityRecord r = mActivities.get(i);
1016             if (r.isVisible()) {
1017                 stateFlags |= ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE;
1018             }
1019             final Task task = r.getTask();
1020             if (task != null && task.mLayerRank != Task.LAYER_RANK_INVISIBLE) {
1021                 stateFlags |= ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK;
1022             }
1023             if (r.mVisibleRequested) {
1024                 if (r.isState(RESUMED)) {
1025                     stateFlags |= ACTIVITY_STATE_FLAG_HAS_RESUMED;
1026                 }
1027                 if (task != null && minTaskLayer > 0) {
1028                     final int layer = task.mLayerRank;
1029                     if (layer >= 0 && minTaskLayer > layer) {
1030                         minTaskLayer = layer;
1031                     }
1032                 }
1033                 visible = true;
1034                 // continue the loop, in case there are multiple visible activities in
1035                 // this process, we'd find out the one with the minimal layer, thus it'll
1036                 // get a higher adj score.
1037             } else if (!visible && bestInvisibleState != PAUSING) {
1038                 if (r.isState(PAUSING, PAUSED)) {
1039                     bestInvisibleState = PAUSING;
1040                 } else if (r.isState(STOPPING)) {
1041                     bestInvisibleState = STOPPING;
1042                     // Not "finishing" if any of activity isn't finishing.
1043                     allStoppingFinishing &= r.finishing;
1044                 }
1045             }
1046         }
1047 
1048         stateFlags |= minTaskLayer & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
1049         if (visible) {
1050             stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE;
1051         } else if (bestInvisibleState == PAUSING) {
1052             stateFlags |= ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED;
1053         } else if (bestInvisibleState == STOPPING) {
1054             stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING;
1055             if (allStoppingFinishing) {
1056                 stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING;
1057             }
1058         }
1059         mActivityStateFlags = stateFlags;
1060 
1061         final boolean anyVisible = (stateFlags
1062                 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
1063         if (!wasAnyVisible && anyVisible) {
1064             mAtm.mVisibleActivityProcessTracker.onAnyActivityVisible(this);
1065         } else if (wasAnyVisible && !anyVisible) {
1066             mAtm.mVisibleActivityProcessTracker.onAllActivitiesInvisible(this);
1067         } else if (wasAnyVisible && !wasResumed && hasResumedActivity()) {
1068             mAtm.mVisibleActivityProcessTracker.onActivityResumedWhileVisible(this);
1069         }
1070     }
1071 
1072     /** Called when the process has some oom related changes and it is going to update oom-adj. */
prepareOomAdjustment()1073     private void prepareOomAdjustment() {
1074         mAtm.mRootWindowContainer.rankTaskLayers();
1075         mAtm.mTaskSupervisor.computeProcessActivityStateBatch();
1076     }
1077 
computeRelaunchReason()1078     public int computeRelaunchReason() {
1079         synchronized (mAtm.mGlobalLock) {
1080             final int activitiesSize = mActivities.size();
1081             for (int i = activitiesSize - 1; i >= 0; i--) {
1082                 final ActivityRecord r = mActivities.get(i);
1083                 if (r.mRelaunchReason != RELAUNCH_REASON_NONE) {
1084                     return r.mRelaunchReason;
1085                 }
1086             }
1087         }
1088         return RELAUNCH_REASON_NONE;
1089     }
1090 
1091     /**
1092      * Get the current dispatching timeout. If instrumentation is currently taking place, return
1093      * a longer value. Shorter timeout is returned otherwise.
1094      * @return The timeout in milliseconds
1095      */
getInputDispatchingTimeoutMillis()1096     public long getInputDispatchingTimeoutMillis() {
1097         synchronized (mAtm.mGlobalLock) {
1098             return isInstrumenting() || isUsingWrapper()
1099                     ? INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS :
1100                     DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
1101         }
1102     }
1103 
clearProfilerIfNeeded()1104     void clearProfilerIfNeeded() {
1105         // Posting on handler so WM lock isn't held when we call into AM.
1106         mAtm.mH.sendMessage(PooledLambda.obtainMessage(
1107                 WindowProcessListener::clearProfilerIfNeeded, mListener));
1108     }
1109 
updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, boolean updateOomAdj, boolean addPendingTopUid)1110     void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
1111             boolean updateOomAdj, boolean addPendingTopUid) {
1112         if (addPendingTopUid) {
1113             addToPendingTop();
1114         }
1115         if (updateOomAdj) {
1116             prepareOomAdjustment();
1117         }
1118         // Posting on handler so WM lock isn't held when we call into AM.
1119         final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo,
1120                 mListener, updateServiceConnectionActivities, activityChange, updateOomAdj);
1121         mAtm.mH.sendMessage(m);
1122     }
1123 
1124     /** Makes the process have top state before oom-adj is computed from a posted message. */
addToPendingTop()1125     void addToPendingTop() {
1126         mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
1127     }
1128 
updateServiceConnectionActivities()1129     void updateServiceConnectionActivities() {
1130         // Posting on handler so WM lock isn't held when we call into AM.
1131         mAtm.mH.sendMessage(PooledLambda.obtainMessage(
1132                 WindowProcessListener::updateServiceConnectionActivities, mListener));
1133     }
1134 
setPendingUiCleanAndForceProcessStateUpTo(int newState)1135     void setPendingUiCleanAndForceProcessStateUpTo(int newState) {
1136         // Posting on handler so WM lock isn't held when we call into AM.
1137         final Message m = PooledLambda.obtainMessage(
1138                 WindowProcessListener::setPendingUiCleanAndForceProcessStateUpTo,
1139                 mListener, newState);
1140         mAtm.mH.sendMessage(m);
1141     }
1142 
isRemoved()1143     boolean isRemoved() {
1144         return mListener.isRemoved();
1145     }
1146 
shouldSetProfileProc()1147     private boolean shouldSetProfileProc() {
1148         return mAtm.mProfileApp != null && mAtm.mProfileApp.equals(mName)
1149                 && (mAtm.mProfileProc == null || mAtm.mProfileProc == this);
1150     }
1151 
createProfilerInfoIfNeeded()1152     ProfilerInfo createProfilerInfoIfNeeded() {
1153         final ProfilerInfo currentProfilerInfo = mAtm.mProfilerInfo;
1154         if (currentProfilerInfo == null || currentProfilerInfo.profileFile == null
1155                 || !shouldSetProfileProc()) {
1156             return null;
1157         }
1158         if (currentProfilerInfo.profileFd != null) {
1159             try {
1160                 currentProfilerInfo.profileFd = currentProfilerInfo.profileFd.dup();
1161             } catch (IOException e) {
1162                 currentProfilerInfo.closeFd();
1163             }
1164         }
1165         return new ProfilerInfo(currentProfilerInfo);
1166     }
1167 
onStartActivity(int topProcessState, ActivityInfo info)1168     void onStartActivity(int topProcessState, ActivityInfo info) {
1169         String packageName = null;
1170         if ((info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
1171                 || !"android".equals(info.packageName)) {
1172             // Don't add this if it is a platform component that is marked to run in multiple
1173             // processes, because this is actually part of the framework so doesn't make sense
1174             // to track as a separate apk in the process.
1175             packageName = info.packageName;
1176         }
1177         // update ActivityManagerService.PendingStartActivityUids list.
1178         if (topProcessState == ActivityManager.PROCESS_STATE_TOP) {
1179             mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
1180         }
1181         prepareOomAdjustment();
1182         // Posting the message at the front of queue so WM lock isn't held when we call into AM,
1183         // and the process state of starting activity can be updated quicker which will give it a
1184         // higher scheduling group.
1185         final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity,
1186                 mListener, topProcessState, shouldSetProfileProc(), packageName,
1187                 info.applicationInfo.longVersionCode);
1188         mAtm.mH.sendMessageAtFrontOfQueue(m);
1189     }
1190 
appDied(String reason)1191     void appDied(String reason) {
1192         // Posting on handler so WM lock isn't held when we call into AM.
1193         final Message m = PooledLambda.obtainMessage(
1194                 WindowProcessListener::appDied, mListener, reason);
1195         mAtm.mH.sendMessage(m);
1196     }
1197 
1198     /**
1199      * Clean up the activities belonging to this process.
1200      *
1201      * @return {@code true} if the process has any visible activity.
1202      */
handleAppDied()1203     boolean handleAppDied() {
1204         mAtm.mTaskSupervisor.removeHistoryRecords(this);
1205 
1206         boolean hasVisibleActivities = false;
1207         final boolean hasInactiveActivities =
1208                 mInactiveActivities != null && !mInactiveActivities.isEmpty();
1209         final ArrayList<ActivityRecord> activities =
1210                 (mHasActivities || hasInactiveActivities) ? new ArrayList<>() : mActivities;
1211         if (mHasActivities) {
1212             activities.addAll(mActivities);
1213         }
1214         if (hasInactiveActivities) {
1215             // Make sure that all activities in this process are handled.
1216             activities.addAll(mInactiveActivities);
1217         }
1218         if (isRemoved()) {
1219             // The package of the died process should be force-stopped, so make its activities as
1220             // finishing to prevent the process from being started again if the next top (or being
1221             // visible) activity also resides in the same process. This must be done before removal.
1222             for (int i = activities.size() - 1; i >= 0; i--) {
1223                 activities.get(i).makeFinishingLocked();
1224             }
1225         }
1226         for (int i = activities.size() - 1; i >= 0; i--) {
1227             final ActivityRecord r = activities.get(i);
1228             if (r.mVisibleRequested || r.isVisible()) {
1229                 // While an activity launches a new activity, it's possible that the old activity
1230                 // is already requested to be hidden (mVisibleRequested=false), but this visibility
1231                 // is not yet committed, so isVisible()=true.
1232                 hasVisibleActivities = true;
1233             }
1234 
1235             final TaskFragment taskFragment = r.getTaskFragment();
1236             if (taskFragment != null) {
1237                 // There may be a pausing activity that hasn't shown any window and was requested
1238                 // to be hidden. But pausing is also a visible state, it should be regarded as
1239                 // visible, so the caller can know the next activity should be resumed.
1240                 hasVisibleActivities |= taskFragment.handleAppDied(this);
1241             }
1242             r.handleAppDied();
1243         }
1244         clearRecentTasks();
1245         clearActivities();
1246 
1247         return hasVisibleActivities;
1248     }
1249 
registerDisplayAreaConfigurationListener(@ullable DisplayArea displayArea)1250     void registerDisplayAreaConfigurationListener(@Nullable DisplayArea displayArea) {
1251         if (displayArea == null || displayArea.containsListener(this)) {
1252             return;
1253         }
1254         unregisterConfigurationListeners();
1255         mDisplayArea = displayArea;
1256         displayArea.registerConfigurationChangeListener(this);
1257     }
1258 
1259     @VisibleForTesting
unregisterDisplayAreaConfigurationListener()1260     void unregisterDisplayAreaConfigurationListener() {
1261         if (mDisplayArea == null) {
1262             return;
1263         }
1264         mDisplayArea.unregisterConfigurationChangeListener(this);
1265         mDisplayArea = null;
1266         onMergedOverrideConfigurationChanged(Configuration.EMPTY);
1267     }
1268 
registerActivityConfigurationListener(ActivityRecord activityRecord)1269     void registerActivityConfigurationListener(ActivityRecord activityRecord) {
1270         if (activityRecord == null || activityRecord.containsListener(this)
1271                 // Check for the caller from outside of this class.
1272                 || !mIsActivityConfigOverrideAllowed) {
1273             return;
1274         }
1275         unregisterConfigurationListeners();
1276         mConfigActivityRecord = activityRecord;
1277         activityRecord.registerConfigurationChangeListener(this);
1278     }
1279 
unregisterActivityConfigurationListener()1280     private void unregisterActivityConfigurationListener() {
1281         if (mConfigActivityRecord == null) {
1282             return;
1283         }
1284         mConfigActivityRecord.unregisterConfigurationChangeListener(this);
1285         mConfigActivityRecord = null;
1286         onMergedOverrideConfigurationChanged(Configuration.EMPTY);
1287     }
1288 
1289     /**
1290      * A process can only register to one {@link WindowContainer} to listen to the override
1291      * configuration changes. Unregisters the existing listener if it has one before registers a
1292      * new one.
1293      */
unregisterConfigurationListeners()1294     private void unregisterConfigurationListeners() {
1295         unregisterActivityConfigurationListener();
1296         unregisterDisplayAreaConfigurationListener();
1297     }
1298 
1299     /**
1300      * Check if activity configuration override for the activity process needs an update and perform
1301      * if needed. By default we try to override the process configuration to match the top activity
1302      * config to increase app compatibility with multi-window and multi-display. The process will
1303      * always track the configuration of the non-finishing activity last added to the process.
1304      */
updateActivityConfigurationListener()1305     private void updateActivityConfigurationListener() {
1306         if (!mIsActivityConfigOverrideAllowed) {
1307             return;
1308         }
1309 
1310         for (int i = mActivities.size() - 1; i >= 0; i--) {
1311             final ActivityRecord activityRecord = mActivities.get(i);
1312             if (!activityRecord.finishing) {
1313                 // Eligible activity is found, update listener.
1314                 registerActivityConfigurationListener(activityRecord);
1315                 return;
1316             }
1317         }
1318 
1319         // No eligible activities found, let's remove the configuration listener.
1320         unregisterActivityConfigurationListener();
1321     }
1322 
1323     @Override
onConfigurationChanged(Configuration newGlobalConfig)1324     public void onConfigurationChanged(Configuration newGlobalConfig) {
1325         super.onConfigurationChanged(newGlobalConfig);
1326         updateConfiguration();
1327     }
1328 
1329     @Override
onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration)1330     public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
1331         super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
1332     }
1333 
1334     @Override
onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig)1335     public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) {
1336         super.onRequestedOverrideConfigurationChanged(mergedOverrideConfig);
1337     }
1338 
1339     @Override
resolveOverrideConfiguration(Configuration newParentConfig)1340     void resolveOverrideConfiguration(Configuration newParentConfig) {
1341         final Configuration requestedOverrideConfig = getRequestedOverrideConfiguration();
1342         if (requestedOverrideConfig.assetsSeq != ASSETS_SEQ_UNDEFINED
1343                 && newParentConfig.assetsSeq > requestedOverrideConfig.assetsSeq) {
1344             requestedOverrideConfig.assetsSeq = ASSETS_SEQ_UNDEFINED;
1345         }
1346         super.resolveOverrideConfiguration(newParentConfig);
1347         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
1348         // Make sure that we don't accidentally override the activity type.
1349         resolvedConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
1350         // Activity has an independent ActivityRecord#mConfigurationSeq. If this process registers
1351         // activity configuration, its config seq shouldn't go backwards by activity configuration.
1352         // Otherwise if other places send wpc.getConfiguration() to client, the configuration may
1353         // be ignored due to the seq is older.
1354         resolvedConfig.seq = newParentConfig.seq;
1355     }
1356 
updateConfiguration()1357     private void updateConfiguration() {
1358         final Configuration config = getConfiguration();
1359         if (mLastReportedConfiguration.diff(config) == 0) {
1360             // Nothing changed.
1361             if (Build.IS_DEBUGGABLE && mHasImeService) {
1362                 // TODO (b/135719017): Temporary log for debugging IME service.
1363                 Slog.w(TAG_CONFIGURATION, "Current config: " + config
1364                         + " unchanged for IME proc " + mName);
1365             }
1366             return;
1367         }
1368 
1369         if (mPauseConfigurationDispatchCount > 0) {
1370             mHasPendingConfigurationChange = true;
1371             return;
1372         }
1373         dispatchConfiguration(config);
1374     }
1375 
dispatchConfiguration(Configuration config)1376     void dispatchConfiguration(Configuration config) {
1377         mHasPendingConfigurationChange = false;
1378         if (mThread == null) {
1379             if (Build.IS_DEBUGGABLE && mHasImeService) {
1380                 // TODO (b/135719017): Temporary log for debugging IME service.
1381                 Slog.w(TAG_CONFIGURATION, "Unable to send config for IME proc " + mName
1382                         + ": no app thread");
1383             }
1384             return;
1385         }
1386         ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
1387                 config);
1388         if (Build.IS_DEBUGGABLE && mHasImeService) {
1389             // TODO (b/135719017): Temporary log for debugging IME service.
1390             Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config);
1391         }
1392 
1393         try {
1394             config.seq = mAtm.increaseConfigurationSeqLocked();
1395             mAtm.getLifecycleManager().scheduleTransaction(mThread,
1396                     ConfigurationChangeItem.obtain(config));
1397             setLastReportedConfiguration(config);
1398         } catch (Exception e) {
1399             Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change", e);
1400         }
1401     }
1402 
setLastReportedConfiguration(Configuration config)1403     void setLastReportedConfiguration(Configuration config) {
1404         mLastReportedConfiguration.setTo(config);
1405     }
1406 
getLastReportedConfiguration()1407     Configuration getLastReportedConfiguration() {
1408         return mLastReportedConfiguration;
1409     }
1410 
pauseConfigurationDispatch()1411     void pauseConfigurationDispatch() {
1412         mPauseConfigurationDispatchCount++;
1413     }
1414 
1415     /** Returns {@code true} if the configuration change is pending to dispatch. */
resumeConfigurationDispatch()1416     boolean resumeConfigurationDispatch() {
1417         if (mPauseConfigurationDispatchCount == 0) {
1418             return false;
1419         }
1420         mPauseConfigurationDispatchCount--;
1421         return mHasPendingConfigurationChange;
1422     }
1423 
updateAssetConfiguration(int assetSeq)1424     void updateAssetConfiguration(int assetSeq) {
1425         // Update the process override configuration directly if the process configuration will
1426         // not be override from its activities.
1427         if (!mHasActivities || !mIsActivityConfigOverrideAllowed) {
1428             Configuration overrideConfig = new Configuration(getRequestedOverrideConfiguration());
1429             overrideConfig.assetsSeq = assetSeq;
1430             onRequestedOverrideConfigurationChanged(overrideConfig);
1431             return;
1432         }
1433 
1434         // Otherwise, we can just update the activity override configuration.
1435         for (int i = mActivities.size() - 1; i >= 0; i--) {
1436             ActivityRecord r = mActivities.get(i);
1437             Configuration overrideConfig = new Configuration(r.getRequestedOverrideConfiguration());
1438             overrideConfig.assetsSeq = assetSeq;
1439             r.onRequestedOverrideConfigurationChanged(overrideConfig);
1440             if (r.mVisibleRequested) {
1441                 r.ensureActivityConfiguration(0, true);
1442             }
1443         }
1444     }
1445 
1446     /**
1447      * This is called for sending {@link android.app.servertransaction.LaunchActivityItem}.
1448      * The caller must call {@link #setLastReportedConfiguration} if the delivered configuration
1449      * is newer.
1450      */
prepareConfigurationForLaunchingActivity()1451     Configuration prepareConfigurationForLaunchingActivity() {
1452         final Configuration config = getConfiguration();
1453         if (mHasPendingConfigurationChange) {
1454             mHasPendingConfigurationChange = false;
1455             // The global configuration may not change, so the client process may have the same
1456             // config seq. This increment ensures that the client won't ignore the configuration.
1457             config.seq = mAtm.increaseConfigurationSeqLocked();
1458         }
1459         return config;
1460     }
1461 
1462     /** Returns the total time (in milliseconds) spent executing in both user and system code. */
getCpuTime()1463     public long getCpuTime() {
1464         return mListener.getCpuTime();
1465     }
1466 
addRecentTask(Task task)1467     void addRecentTask(Task task) {
1468         mRecentTasks.add(task);
1469         mHasRecentTasks = true;
1470     }
1471 
removeRecentTask(Task task)1472     void removeRecentTask(Task task) {
1473         mRecentTasks.remove(task);
1474         mHasRecentTasks = !mRecentTasks.isEmpty();
1475     }
1476 
1477     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
hasRecentTasks()1478     public boolean hasRecentTasks() {
1479         return mHasRecentTasks;
1480     }
1481 
clearRecentTasks()1482     void clearRecentTasks() {
1483         for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
1484             mRecentTasks.get(i).clearRootProcess();
1485         }
1486         mRecentTasks.clear();
1487         mHasRecentTasks = false;
1488     }
1489 
appEarlyNotResponding(String annotation, Runnable killAppCallback)1490     public void appEarlyNotResponding(String annotation, Runnable killAppCallback) {
1491         Runnable targetRunnable = null;
1492         synchronized (mAtm.mGlobalLock) {
1493             if (mAtm.mController == null) {
1494                 return;
1495             }
1496 
1497             try {
1498                 // 0 == continue, -1 = kill process immediately
1499                 int res = mAtm.mController.appEarlyNotResponding(mName, mPid, annotation);
1500                 if (res < 0 && mPid != MY_PID) {
1501                     targetRunnable = killAppCallback;
1502                 }
1503             } catch (RemoteException e) {
1504                 mAtm.mController = null;
1505                 Watchdog.getInstance().setActivityController(null);
1506             }
1507         }
1508         if (targetRunnable != null) {
1509             targetRunnable.run();
1510         }
1511     }
1512 
appNotResponding(String info, Runnable killAppCallback, Runnable serviceTimeoutCallback)1513     public boolean appNotResponding(String info, Runnable killAppCallback,
1514             Runnable serviceTimeoutCallback) {
1515         Runnable targetRunnable = null;
1516         synchronized (mAtm.mGlobalLock) {
1517             if (mAtm.mController == null) {
1518                 return false;
1519             }
1520 
1521             try {
1522                 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
1523                 int res = mAtm.mController.appNotResponding(mName, mPid, info);
1524                 if (res != 0) {
1525                     if (res < 0 && mPid != MY_PID) {
1526                         targetRunnable = killAppCallback;
1527                     } else {
1528                         targetRunnable = serviceTimeoutCallback;
1529                     }
1530                 }
1531             } catch (RemoteException e) {
1532                 mAtm.mController = null;
1533                 Watchdog.getInstance().setActivityController(null);
1534                 return false;
1535             }
1536         }
1537         if (targetRunnable != null) {
1538             // Execute runnable outside WM lock since the runnable will hold AM lock
1539             targetRunnable.run();
1540             return true;
1541         }
1542         return false;
1543     }
1544 
1545     /**
1546      * Called to notify {@link WindowProcessController} of a started service.
1547      *
1548      * @param serviceInfo information describing the started service.
1549      */
onServiceStarted(ServiceInfo serviceInfo)1550     public void onServiceStarted(ServiceInfo serviceInfo) {
1551         String permission = serviceInfo.permission;
1552         if (permission == null) {
1553             return;
1554         }
1555 
1556         // TODO: Audit remaining services for disabling activity override (Wallpaper, Dream, etc).
1557         switch (permission) {
1558             case Manifest.permission.BIND_INPUT_METHOD:
1559                 mHasImeService = true;
1560                 // Fall-through
1561             case Manifest.permission.BIND_ACCESSIBILITY_SERVICE:
1562             case Manifest.permission.BIND_VOICE_INTERACTION:
1563                 // We want to avoid overriding the config of these services with that of the
1564                 // activity as it could lead to incorrect display metrics. For ex, IME services
1565                 // expect their config to match the config of the display with the IME window
1566                 // showing.
1567                 // If the configuration has been overridden by previous activity, empty it.
1568                 mIsActivityConfigOverrideAllowed = false;
1569                 unregisterActivityConfigurationListener();
1570                 break;
1571             default:
1572                 break;
1573         }
1574     }
1575 
1576     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
onTopProcChanged()1577     public void onTopProcChanged() {
1578         if (mAtm.mVrController.isInterestingToSchedGroup()) {
1579             mAtm.mH.post(() -> {
1580                 synchronized (mAtm.mGlobalLock) {
1581                     mAtm.mVrController.onTopProcChangedLocked(this);
1582                 }
1583             });
1584         }
1585     }
1586 
1587     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
isHomeProcess()1588     public boolean isHomeProcess() {
1589         return this == mAtm.mHomeProcess;
1590     }
1591 
1592     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
isPreviousProcess()1593     public boolean isPreviousProcess() {
1594         return this == mAtm.mPreviousProcess;
1595     }
1596 
1597     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
isHeavyWeightProcess()1598     public boolean isHeavyWeightProcess() {
1599         return this == mAtm.mHeavyWeightProcess;
1600     }
1601 
setRunningRecentsAnimation(boolean running)1602     void setRunningRecentsAnimation(boolean running) {
1603         if (mRunningRecentsAnimation == running) {
1604             return;
1605         }
1606         mRunningRecentsAnimation = running;
1607         updateRunningRemoteOrRecentsAnimation();
1608     }
1609 
setRunningRemoteAnimation(boolean running)1610     void setRunningRemoteAnimation(boolean running) {
1611         if (mRunningRemoteAnimation == running) {
1612             return;
1613         }
1614         mRunningRemoteAnimation = running;
1615         updateRunningRemoteOrRecentsAnimation();
1616     }
1617 
1618     /**
1619      * Marks another process as a "delegate" animator. This means that process is doing some part
1620      * of a remote animation on behalf of this process.
1621      */
addRemoteAnimationDelegate(WindowProcessController delegate)1622     void addRemoteAnimationDelegate(WindowProcessController delegate) {
1623         if (!isRunningRemoteTransition()) {
1624             throw new IllegalStateException("Can't add a delegate to a process which isn't itself"
1625                     + " running a remote animation");
1626         }
1627         mRemoteAnimationDelegates.add(new WeakReference<>(delegate));
1628     }
1629 
updateRunningRemoteOrRecentsAnimation()1630     void updateRunningRemoteOrRecentsAnimation() {
1631         if (!isRunningRemoteTransition()) {
1632             // Clean-up any delegates
1633             for (int i = 0; i < mRemoteAnimationDelegates.size(); ++i) {
1634                 final WindowProcessController delegate = mRemoteAnimationDelegates.get(i).get();
1635                 if (delegate == null) continue;
1636                 delegate.setRunningRemoteAnimation(false);
1637                 delegate.setRunningRecentsAnimation(false);
1638             }
1639             mRemoteAnimationDelegates.clear();
1640         }
1641 
1642         // Posting on handler so WM lock isn't held when we call into AM.
1643         mAtm.mH.sendMessage(PooledLambda.obtainMessage(
1644                 WindowProcessListener::setRunningRemoteAnimation, mListener,
1645                 isRunningRemoteTransition()));
1646     }
1647 
isRunningRemoteTransition()1648     boolean isRunningRemoteTransition() {
1649         return mRunningRecentsAnimation || mRunningRemoteAnimation;
1650     }
1651 
1652     /** Adjusts scheduling group for animation. This method MUST NOT be called inside WM lock. */
setRunningAnimationUnsafe()1653     void setRunningAnimationUnsafe() {
1654         mListener.setRunningRemoteAnimation(true);
1655     }
1656 
1657     @Override
toString()1658     public String toString() {
1659         return mOwner != null ? mOwner.toString() : null;
1660     }
1661 
dump(PrintWriter pw, String prefix)1662     public void dump(PrintWriter pw, String prefix) {
1663         synchronized (mAtm.mGlobalLock) {
1664             if (mActivities.size() > 0) {
1665                 pw.print(prefix); pw.println("Activities:");
1666                 for (int i = 0; i < mActivities.size(); i++) {
1667                     pw.print(prefix); pw.print("  - "); pw.println(mActivities.get(i));
1668                 }
1669             }
1670 
1671             if (mRecentTasks.size() > 0) {
1672                 pw.println(prefix + "Recent Tasks:");
1673                 for (int i = 0; i < mRecentTasks.size(); i++) {
1674                     pw.println(prefix + "  - " + mRecentTasks.get(i));
1675                 }
1676             }
1677 
1678             if (mVrThreadTid != 0) {
1679                 pw.print(prefix); pw.print("mVrThreadTid="); pw.println(mVrThreadTid);
1680             }
1681 
1682             mBgLaunchController.dump(pw, prefix);
1683         }
1684         pw.println(prefix + " Configuration=" + getConfiguration());
1685         pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration());
1686         pw.println(prefix + " mLastReportedConfiguration=" + mLastReportedConfiguration);
1687 
1688         final int stateFlags = mActivityStateFlags;
1689         if (stateFlags != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
1690             pw.print(prefix + " mActivityStateFlags=");
1691             if ((stateFlags & ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE) != 0) {
1692                 pw.print("W|");
1693             }
1694             if ((stateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) {
1695                 pw.print("V|");
1696                 if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0) {
1697                     pw.print("R|");
1698                 }
1699             } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) {
1700                 pw.print("P|");
1701             } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) {
1702                 pw.print("S|");
1703                 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0) {
1704                     pw.print("F|");
1705                 }
1706             }
1707             final int taskLayer = stateFlags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
1708             if (taskLayer != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
1709                 pw.print("taskLayer=" + taskLayer);
1710             }
1711             pw.println();
1712         }
1713     }
1714 
dumpDebug(ProtoOutputStream proto, long fieldId)1715     void dumpDebug(ProtoOutputStream proto, long fieldId) {
1716         mListener.dumpDebug(proto, fieldId);
1717     }
1718 }
1719