• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CACHED_ACTIVITY;
20 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
24 import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED;
25 import static android.os.Build.VERSION_CODES.Q;
26 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
27 import static android.view.WindowManager.TRANSIT_CLOSE;
28 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
29 
30 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_CONFIGURATION;
31 import static com.android.internal.util.Preconditions.checkArgument;
32 import static com.android.server.am.ProcessList.INVALID_ADJ;
33 import static com.android.server.wm.ActivityRecord.State.DESTROYED;
34 import static com.android.server.wm.ActivityRecord.State.DESTROYING;
35 import static com.android.server.wm.ActivityRecord.State.PAUSED;
36 import static com.android.server.wm.ActivityRecord.State.PAUSING;
37 import static com.android.server.wm.ActivityRecord.State.RESUMED;
38 import static com.android.server.wm.ActivityRecord.State.STARTED;
39 import static com.android.server.wm.ActivityRecord.State.STOPPED;
40 import static com.android.server.wm.ActivityRecord.State.STOPPING;
41 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
42 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
43 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
44 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
45 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
46 import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS;
47 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
48 import static com.android.server.wm.WindowManagerService.MY_PID;
49 
50 import static java.util.Objects.requireNonNull;
51 
52 import android.Manifest;
53 import android.annotation.IntDef;
54 import android.annotation.NonNull;
55 import android.annotation.Nullable;
56 import android.app.ActivityManager;
57 import android.app.ActivityThread;
58 import android.app.BackgroundStartPrivileges;
59 import android.app.IApplicationThread;
60 import android.app.ProfilerInfo;
61 import android.app.servertransaction.ClientTransactionItem;
62 import android.app.servertransaction.ConfigurationChangeItem;
63 import android.content.ComponentName;
64 import android.content.Context;
65 import android.content.Intent;
66 import android.content.pm.ActivityInfo;
67 import android.content.pm.ApplicationInfo;
68 import android.content.pm.ServiceInfo;
69 import android.content.res.Configuration;
70 import android.os.Binder;
71 import android.os.Build;
72 import android.os.FactoryTest;
73 import android.os.LocaleList;
74 import android.os.Message;
75 import android.os.Process;
76 import android.os.RemoteException;
77 import android.os.SystemProperties;
78 import android.os.UserHandle;
79 import android.util.ArrayMap;
80 import android.util.Log;
81 import android.util.Slog;
82 import android.util.proto.ProtoOutputStream;
83 
84 import com.android.internal.annotations.GuardedBy;
85 import com.android.internal.annotations.VisibleForTesting;
86 import com.android.internal.app.HeavyWeightSwitcherActivity;
87 import com.android.internal.protolog.ProtoLog;
88 import com.android.internal.util.function.pooled.PooledLambda;
89 import com.android.server.Watchdog;
90 import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal;
91 import com.android.server.wm.ActivityTaskManagerService.HotPath;
92 import com.android.server.wm.BackgroundLaunchProcessController.BalCheckConfiguration;
93 
94 import java.io.IOException;
95 import java.io.PrintWriter;
96 import java.lang.annotation.Retention;
97 import java.lang.annotation.RetentionPolicy;
98 import java.util.ArrayList;
99 import java.util.List;
100 
101 /**
102  * The Activity Manager (AM) package manages the lifecycle of processes in the system through
103  * ProcessRecord. However, it is important for the Window Manager (WM) package to be aware
104  * of the processes and their state since it affects how WM manages windows and activities. This
105  * class that allows the ProcessRecord object in the AM package to communicate important
106  * changes to its state to the WM package in a structured way. WM package also uses
107  * {@link WindowProcessListener} to request changes to the process state on the AM side.
108  * Note that public calls into this class are assumed to be originating from outside the
109  * window manager so the window manager lock is held and appropriate permissions are checked before
110  * calls are allowed to proceed.
111  */
112 public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer>
113         implements ConfigurationContainerListener {
114     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM;
115     private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
116     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
117 
118     /**
119      * The max number of processes which can be top scheduling group if there are non-top visible
120      * freeform activities run in the process.
121      */
122     private static final int MAX_NUM_PERCEPTIBLE_FREEFORM =
123             SystemProperties.getInt("persist.wm.max_num_perceptible_freeform", 1);
124     /**
125      * If the visible area percentage of a resumed freeform task is greater than or equal to this
126      * ratio, its process will have a higher priority.
127      */
128     private static final int PERCEPTIBLE_FREEFORM_VISIBLE_RATIO = 90;
129 
130     private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 200;
131     private static final long RAPID_ACTIVITY_LAUNCH_MS = 500;
132     private static final long RESET_RAPID_ACTIVITY_LAUNCH_MS = 3 * RAPID_ACTIVITY_LAUNCH_MS;
133 
134     public static final int STOPPED_STATE_NOT_STOPPED = 0;
135     public static final int STOPPED_STATE_FIRST_LAUNCH = 1;
136     public static final int STOPPED_STATE_FORCE_STOPPED = 2;
137 
138     private int mRapidActivityLaunchCount;
139 
140     // all about the first app in the process
141     volatile ApplicationInfo mInfo;
142     final String mName;
143     final int mUid;
144 
145     // The process of this application; 0 if none
146     private volatile int mPid;
147     // user of process.
148     final int mUserId;
149     // The owner of this window process controller object. Mainly for identification when we
150     // communicate back to the activity manager side.
151     public final Object mOwner;
152     // List of packages running in the process
153     @GuardedBy("itself")
154     private final ArrayList<String> mPkgList = new ArrayList<>(1);
155     private final WindowProcessListener mListener;
156     private final ActivityTaskManagerService mAtm;
157     private final BackgroundLaunchProcessController mBgLaunchController;
158     // The actual proc...  may be null only if 'persistent' is true (in which case we are in the
159     // process of launching the app)
160     private IApplicationThread mThread;
161     // Currently desired scheduling class
162     private volatile int mCurSchedGroup;
163     // Currently computed process state
164     private volatile int mCurProcState = PROCESS_STATE_NONEXISTENT;
165     // Last reported process state;
166     private volatile int mRepProcState = PROCESS_STATE_NONEXISTENT;
167     // Currently computed oom adj score
168     private volatile int mCurAdj = INVALID_ADJ;
169     // are we in the process of crashing?
170     private volatile boolean mCrashing;
171     // does the app have a not responding dialog?
172     private volatile boolean mNotResponding;
173     // always keep this application running?
174     private volatile boolean mPersistent;
175     // The ABI this process was launched with
176     private volatile String mRequiredAbi;
177     // Running any services that are foreground?
178     private volatile boolean mHasForegroundServices;
179     // Are there any client services with activities?
180     private volatile boolean mHasClientActivities;
181     // Is this process currently showing a non-activity UI that the user is interacting with?
182     // E.g. The status bar when it is expanded, but not when it is minimized. When true the process
183     // will be set to use the ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost performance.
184     private volatile boolean mHasTopUi;
185     // Is the process currently showing a non-activity UI that overlays on-top of activity UIs on
186     // screen. E.g. display a window of type
187     // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY When true the process will
188     // oom adj score will be set to ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance
189     // of the process getting killed.
190     private volatile boolean mHasOverlayUi;
191     // Want to clean up resources from showing UI?
192     private volatile boolean mPendingUiClean;
193     // The time we sent the last interaction event
194     private volatile long mInteractionEventTime;
195     // When we became foreground for interaction purposes
196     private volatile long mFgInteractionTime;
197     // When (uptime) the process last became unimportant
198     private volatile long mWhenUnimportant;
199     // was app launched for debugging?
200     private volatile boolean mDebugging;
201     // Active instrumentation running in process?
202     private volatile boolean mInstrumenting;
203     // If there is active instrumentation, this is the source
204     private volatile int mInstrumentationSourceUid = -1;
205     // Active instrumentation with background activity starts privilege running in process?
206     private volatile boolean mInstrumentingWithBackgroundActivityStartPrivileges;
207     // This process it perceptible by the user.
208     private volatile boolean mPerceptible;
209     // Set to true when process was launched with a wrapper attached
210     private volatile boolean mUsingWrapper;
211 
212     /** Whether this process has ever completed ActivityThread#handleBindApplication. */
213     boolean mHasEverAttached;
214 
215     /** Non-null if this process may have a window. */
216     @Nullable
217     Session mWindowSession;
218 
219     // Thread currently set for VR scheduling
220     int mVrThreadTid;
221 
222     // Whether this process has ever started a service with the BIND_INPUT_METHOD permission.
223     private volatile boolean mHasImeService;
224 
225     /**
226      * Whether this process can use realtime prioirity (SCHED_FIFO) for its UI and render threads
227      * when this process is SCHED_GROUP_TOP_APP.
228      */
229     private final boolean mUseFifoUiScheduling;
230 
231     /** Whether {@link #mActivities} is not empty. */
232     private volatile boolean mHasActivities;
233     /** All activities running in the process (exclude destroying). */
234     private final ArrayList<ActivityRecord> mActivities = new ArrayList<>();
235     /** The activities will be removed but still belong to this process. */
236     private ArrayList<ActivityRecord> mInactiveActivities;
237     /** Whether {@link #mRecentTasks} is not empty. */
238     private volatile boolean mHasRecentTasks;
239     // any tasks this process had run root activities in
240     private final ArrayList<Task> mRecentTasks = new ArrayList<>();
241     // The most recent top-most activity that was resumed in the process for pre-Q app.
242     private ActivityRecord mPreQTopResumedActivity = null;
243     // The last time an activity was launched in the process
244     private volatile long mLastActivityLaunchTime;
245     // The last time an activity was finished in the process while the process participated
246     // in a visible task
247     private volatile long mLastActivityFinishTime;
248 
249     // Last configuration that was reported to the process.
250     private final Configuration mLastReportedConfiguration = new Configuration();
251     /** Whether the process configuration is waiting to be dispatched to the process. */
252     private boolean mHasPendingConfigurationChange;
253 
254     /** If the process state is in (<=) the cached state, then defer delivery of the config. */
255     private static final int CACHED_CONFIG_PROC_STATE = PROCESS_STATE_CACHED_ACTIVITY;
256     /** Whether {@link #mLastReportedConfiguration} is deferred by the cached state. */
257     private volatile boolean mHasCachedConfiguration;
258 
259     private int mLastTopActivityDeviceId = Context.DEVICE_ID_DEFAULT;
260     /**
261      * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
262      * registered.
263      */
264     @Nullable
265     private DisplayArea mDisplayArea;
266     private ActivityRecord mConfigActivityRecord;
267     // Whether the activity config override is allowed for this process.
268     private volatile boolean mIsActivityConfigOverrideAllowed = true;
269     /** Non-zero to pause dispatching process configuration change. */
270     private int mPauseConfigurationDispatchCount;
271 
272     /**
273      * Activities that hosts some UI drawn by the current process. The activities live
274      * in another process. This is used to check if the process is currently showing anything
275      * visible to the user.
276      */
277     private static final int REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY = 1;
278     /** The activity in a different process is embedded in a task created by this process. */
279     private static final int REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY = 1 << 1;
280 
281     /**
282      * Activities that run on different processes while this process shows something in these
283      * activities or the appearance of the activities are controlled by this process. The value of
284      * map is an array of size 1 to store the kinds of remote.
285      */
286     @Nullable
287     private ArrayMap<ActivityRecord, int[]> mRemoteActivities;
288 
289     /**
290      * It can be set for a running transition player ({@link android.window.ITransitionPlayer}) or
291      * remote animators (running {@link android.window.IRemoteTransition}).
292      */
293     static final int ANIMATING_REASON_REMOTE_ANIMATION = 1;
294     /** It is set for wakefulness transition. */
295     static final int ANIMATING_REASON_WAKEFULNESS_CHANGE = 1 << 1;
296 
297     @Retention(RetentionPolicy.SOURCE)
298     @IntDef({
299             ANIMATING_REASON_REMOTE_ANIMATION,
300             ANIMATING_REASON_WAKEFULNESS_CHANGE,
301     })
302     @interface AnimatingReason {}
303 
304     /**
305      * Non-zero if this process is currently running an important animation. This should be never
306      * set for system server.
307      */
308     @AnimatingReason
309     private int mAnimatingReasons;
310 
311     @Retention(RetentionPolicy.SOURCE)
312     @IntDef({
313             STOPPED_STATE_NOT_STOPPED,
314             STOPPED_STATE_FIRST_LAUNCH,
315             STOPPED_STATE_FORCE_STOPPED
316     })
317     public @interface StoppedState {}
318 
319     private volatile @StoppedState int mStoppedState;
320 
321     /**
322      * Whether the stopped state was logged for an activity start, as we don't want to log
323      * multiple times.
324      */
325     private volatile boolean mWasStoppedLogged;
326 
327     // The bits used for mActivityStateFlags.
328     public static final int ACTIVITY_STATE_FLAG_IS_VISIBLE = 1 << 16;
329     public static final int ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED = 1 << 17;
330     public static final int ACTIVITY_STATE_FLAG_IS_STOPPING = 1 << 18;
331     public static final int ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING = 1 << 19;
332     public static final int ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE = 1 << 20;
333     public static final int ACTIVITY_STATE_FLAG_HAS_RESUMED = 1 << 21;
334     public static final int ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK = 1 << 22;
335     public static final int ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN = 1 << 23;
336     public static final int ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM = 1 << 24;
337     public static final int ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE = 1 << 25;
338     public static final int ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER = 0x0000ffff;
339 
340     private static final int ACTIVITY_STATE_VISIBLE =
341             com.android.window.flags.Flags.useVisibleRequestedForProcessTracker()
342                     ? ACTIVITY_STATE_FLAG_IS_VISIBLE
343                     : ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE;
344 
345     /**
346      * The state for oom-adjustment calculation. The higher 16 bits are the activity states, and the
347      * lower 16 bits are the task layer rank (see {@link Task#mLayerRank}). This field is written by
348      * window manager and read by activity manager.
349      */
350     private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
351 
352     /**
353      * The most recent timestamp of when one of this process's stopped activities in a
354      * perceptible task became stopped. Written by window manager and read by activity manager.
355      */
356     private volatile long mPerceptibleTaskStoppedTimeMillis = Long.MIN_VALUE;
357 
WindowProcessController(@onNull ActivityTaskManagerService atm, @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner, @NonNull WindowProcessListener listener)358     public WindowProcessController(@NonNull ActivityTaskManagerService atm,
359             @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner,
360             @NonNull WindowProcessListener listener) {
361         mInfo = info;
362         mName = name;
363         mUid = uid;
364         mUserId = userId;
365         mOwner = owner;
366         mListener = listener;
367         mAtm = atm;
368         mBgLaunchController = new BackgroundLaunchProcessController(
369                 atm::hasActiveVisibleWindow, atm.getBackgroundActivityStartCallback());
370 
371         boolean isSysUiPackage = info.packageName.equals(
372                 mAtm.getSysUiServiceComponentLocked().getPackageName());
373         if (isSysUiPackage || UserHandle.getAppId(mUid) == Process.SYSTEM_UID) {
374             // This is a system owned process and should not use an activity config.
375             // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs.
376             mIsActivityConfigOverrideAllowed = false;
377         }
378         mUseFifoUiScheduling = com.android.window.flags.Flags.fifoPriorityForMajorUiProcesses()
379                 && (isSysUiPackage || mAtm.isCallerRecents(uid));
380     }
381 
setPid(int pid)382     public void setPid(int pid) {
383         mPid = pid;
384     }
385 
getPid()386     public int getPid() {
387         return mPid;
388     }
389 
390     @HotPath(caller = HotPath.PROCESS_CHANGE)
setThread(IApplicationThread thread)391     public void setThread(IApplicationThread thread) {
392         synchronized (mAtm.mGlobalLockWithoutBoost) {
393             mThread = thread;
394             // In general this is called from attaching application, so the last configuration
395             // has been sent to client by {@link android.app.IApplicationThread#bindApplication}.
396             // If this process is system server, it is fine because system is booting and a new
397             // configuration will update when display is ready.
398             if (thread != null) {
399                 setLastReportedConfiguration(getConfiguration());
400             } else {
401                 // The process is inactive.
402                 mAtm.mVisibleActivityProcessTracker.removeProcess(this);
403             }
404         }
405     }
406 
getThread()407     IApplicationThread getThread() {
408         return mThread;
409     }
410 
hasThread()411     boolean hasThread() {
412         return mThread != null;
413     }
414 
setCurrentSchedulingGroup(int curSchedGroup)415     public void setCurrentSchedulingGroup(int curSchedGroup) {
416         mCurSchedGroup = curSchedGroup;
417     }
418 
getCurrentSchedulingGroup()419     int getCurrentSchedulingGroup() {
420         return mCurSchedGroup;
421     }
422 
setCurrentProcState(int curProcState)423     public void setCurrentProcState(int curProcState) {
424         mCurProcState = curProcState;
425     }
426 
getCurrentProcState()427     int getCurrentProcState() {
428         return mCurProcState;
429     }
430 
setCurrentAdj(int curAdj)431     public void setCurrentAdj(int curAdj) {
432         mCurAdj = curAdj;
433     }
434 
getCurrentAdj()435     int getCurrentAdj() {
436         return mCurAdj;
437     }
438 
439     /**
440      * Sets the computed process state from the oom adjustment calculation. This is frequently
441      * called in activity manager's lock, so don't use window manager lock here.
442      */
443     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
setReportedProcState(int repProcState)444     public void setReportedProcState(int repProcState) {
445         final int prevProcState = mRepProcState;
446         mRepProcState = repProcState;
447 
448         // Deliver the cached config if the app changes from cached state to non-cached state.
449         final IApplicationThread thread = mThread;
450         if (prevProcState >= CACHED_CONFIG_PROC_STATE && repProcState < CACHED_CONFIG_PROC_STATE
451                 && thread != null && mHasCachedConfiguration) {
452             final ConfigurationChangeItem configurationChangeItem;
453             synchronized (mLastReportedConfiguration) {
454                 onConfigurationChangePreScheduled(mLastReportedConfiguration);
455                 configurationChangeItem = new ConfigurationChangeItem(
456                         mLastReportedConfiguration, mLastTopActivityDeviceId);
457             }
458             // Schedule immediately to make sure the app component (e.g. receiver, service) can get
459             // the latest configuration in their lifecycle callbacks (e.g. onReceive, onCreate).
460             try {
461                 // No WM lock here.
462                 mAtm.getLifecycleManager().scheduleTransactionItemNow(
463                         thread, configurationChangeItem);
464             } catch (Exception e) {
465                 // TODO(b/323801078): remove Exception when cleanup
466                 Slog.e(TAG_CONFIGURATION, "Failed to schedule ConfigurationChangeItem="
467                         + configurationChangeItem + " owner=" + mOwner, e);
468             }
469         }
470     }
471 
getReportedProcState()472     int getReportedProcState() {
473         return mRepProcState;
474     }
475 
setCrashing(boolean crashing)476     public void setCrashing(boolean crashing) {
477         mCrashing = crashing;
478     }
479 
handleAppCrash()480     boolean handleAppCrash() {
481         boolean hasVisibleActivity = false;
482         ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities);
483         for (int i = activities.size() - 1; i >= 0; --i) {
484             final ActivityRecord r = activities.get(i);
485             Slog.w(TAG, "  Force finishing activity "
486                     + r.mActivityComponent.flattenToShortString());
487             r.detachFromProcess();
488             if (r.isVisibleRequested()) {
489                 hasVisibleActivity = true;
490                 Task finishingTask = r.getTask();
491                 r.mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_CLOSE,
492                         TRANSIT_FLAG_APP_CRASHED, finishingTask);
493             }
494             r.destroyIfPossible("handleAppCrashed");
495         }
496         return hasVisibleActivity;
497     }
498 
isCrashing()499     boolean isCrashing() {
500         return mCrashing;
501     }
502 
setNotResponding(boolean notResponding)503     public void setNotResponding(boolean notResponding) {
504         mNotResponding = notResponding;
505     }
506 
isNotResponding()507     boolean isNotResponding() {
508         return mNotResponding;
509     }
510 
setPersistent(boolean persistent)511     public void setPersistent(boolean persistent) {
512         mPersistent = persistent;
513     }
514 
isPersistent()515     boolean isPersistent() {
516         return mPersistent;
517     }
518 
setHasForegroundServices(boolean hasForegroundServices)519     public void setHasForegroundServices(boolean hasForegroundServices) {
520         mHasForegroundServices = hasForegroundServices;
521     }
522 
hasForegroundServices()523     boolean hasForegroundServices() {
524         return mHasForegroundServices;
525     }
526 
hasForegroundActivities()527     boolean hasForegroundActivities() {
528         return mAtm.mTopApp == this || (mActivityStateFlags
529                 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED
530                         | ACTIVITY_STATE_FLAG_IS_STOPPING)) != 0;
531     }
532 
setHasClientActivities(boolean hasClientActivities)533     public void setHasClientActivities(boolean hasClientActivities) {
534         mHasClientActivities = hasClientActivities;
535     }
536 
hasClientActivities()537     boolean hasClientActivities() {
538         return mHasClientActivities;
539     }
540 
setHasTopUi(boolean hasTopUi)541     public void setHasTopUi(boolean hasTopUi) {
542         mHasTopUi = hasTopUi;
543     }
544 
hasTopUi()545     boolean hasTopUi() {
546         return mHasTopUi;
547     }
548 
setHasOverlayUi(boolean hasOverlayUi)549     public void setHasOverlayUi(boolean hasOverlayUi) {
550         mHasOverlayUi = hasOverlayUi;
551     }
552 
hasOverlayUi()553     boolean hasOverlayUi() {
554         return mHasOverlayUi;
555     }
556 
setPendingUiClean(boolean hasPendingUiClean)557     public void setPendingUiClean(boolean hasPendingUiClean) {
558         mPendingUiClean = hasPendingUiClean;
559     }
560 
hasPendingUiClean()561     boolean hasPendingUiClean() {
562         return mPendingUiClean;
563     }
564 
565     /** @return {@code true} if the process registered to a display area as a config listener. */
registeredForDisplayAreaConfigChanges()566     boolean registeredForDisplayAreaConfigChanges() {
567         return mDisplayArea != null;
568     }
569 
570     /** @return {@code true} if the process registered to an activity as a config listener. */
571     @VisibleForTesting
registeredForActivityConfigChanges()572     boolean registeredForActivityConfigChanges() {
573         return mConfigActivityRecord != null;
574     }
575 
postPendingUiCleanMsg(boolean pendingUiClean)576     void postPendingUiCleanMsg(boolean pendingUiClean) {
577         // Posting on handler so WM lock isn't held when we call into AM.
578         final Message m = PooledLambda.obtainMessage(
579                 WindowProcessListener::setPendingUiClean, mListener, pendingUiClean);
580         mAtm.mH.sendMessage(m);
581     }
582 
setInteractionEventTime(long interactionEventTime)583     public void setInteractionEventTime(long interactionEventTime) {
584         mInteractionEventTime = interactionEventTime;
585     }
586 
getInteractionEventTime()587     long getInteractionEventTime() {
588         return mInteractionEventTime;
589     }
590 
setFgInteractionTime(long fgInteractionTime)591     public void setFgInteractionTime(long fgInteractionTime) {
592         mFgInteractionTime = fgInteractionTime;
593     }
594 
getFgInteractionTime()595     long getFgInteractionTime() {
596         return mFgInteractionTime;
597     }
598 
setWhenUnimportant(long whenUnimportant)599     public void setWhenUnimportant(long whenUnimportant) {
600         mWhenUnimportant = whenUnimportant;
601     }
602 
getWhenUnimportant()603     long getWhenUnimportant() {
604         return mWhenUnimportant;
605     }
606 
setRequiredAbi(String requiredAbi)607     public void setRequiredAbi(String requiredAbi) {
608         mRequiredAbi = requiredAbi;
609     }
610 
getRequiredAbi()611     String getRequiredAbi() {
612         return mRequiredAbi;
613     }
614 
615     /**
616      * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
617      * registered.
618      */
619     @VisibleForTesting
620     @Nullable
getDisplayArea()621     DisplayArea getDisplayArea() {
622         return mDisplayArea;
623     }
624 
setDebugging(boolean debugging)625     public void setDebugging(boolean debugging) {
626         mDebugging = debugging;
627     }
628 
isDebugging()629     boolean isDebugging() {
630         return mDebugging;
631     }
632 
setUsingWrapper(boolean usingWrapper)633     public void setUsingWrapper(boolean usingWrapper) {
634         mUsingWrapper = usingWrapper;
635     }
636 
isUsingWrapper()637     boolean isUsingWrapper() {
638         return mUsingWrapper;
639     }
640 
hasEverLaunchedActivity()641     boolean hasEverLaunchedActivity() {
642         return mLastActivityLaunchTime > 0;
643     }
644 
setLastActivityLaunchTime(ActivityRecord r)645     void setLastActivityLaunchTime(ActivityRecord r) {
646         long launchTime = r.lastLaunchTime;
647         if (launchTime <= mLastActivityLaunchTime) {
648             if (launchTime < mLastActivityLaunchTime) {
649                 Slog.w(TAG,
650                         "Tried to set launchTime (" + launchTime + ") < mLastActivityLaunchTime ("
651                                 + mLastActivityLaunchTime + ")");
652             }
653             return;
654         }
655         updateRapidActivityLaunch(r, launchTime, mLastActivityLaunchTime);
656         mLastActivityLaunchTime = launchTime;
657     }
658 
updateRapidActivityLaunch(ActivityRecord r, long launchTime, long lastLaunchTime)659     void updateRapidActivityLaunch(ActivityRecord r, long launchTime, long lastLaunchTime) {
660         if (mInstrumenting || mDebugging || lastLaunchTime <= 0) {
661             return;
662         }
663 
664         final WindowProcessController caller = mAtm.mProcessMap.getProcess(r.launchedFromPid);
665         if (caller != null && caller.mInstrumenting) {
666             return;
667         }
668 
669         final long diff = launchTime - lastLaunchTime;
670         if (diff < RAPID_ACTIVITY_LAUNCH_MS) {
671             mRapidActivityLaunchCount++;
672         } else if (diff >= RESET_RAPID_ACTIVITY_LAUNCH_MS) {
673             mRapidActivityLaunchCount = 0;
674         }
675 
676         if (mRapidActivityLaunchCount > MAX_RAPID_ACTIVITY_LAUNCH_COUNT) {
677             mRapidActivityLaunchCount = 0;
678             final Task task = r.getTask();
679             Slog.w(TAG, "Removing task " + task.mTaskId + " because of rapid activity launch");
680             mAtm.mH.post(() -> {
681                 synchronized (mAtm.mGlobalLock) {
682                     task.removeImmediately("rapid-activity-launch");
683                 }
684                 mAtm.mAmInternal.killProcess(mName, mUid, "rapidActivityLaunch");
685             });
686         }
687     }
688 
setLastActivityFinishTimeIfNeeded(long finishTime)689     void setLastActivityFinishTimeIfNeeded(long finishTime) {
690         if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) {
691             return;
692         }
693         mLastActivityFinishTime = finishTime;
694     }
695 
696     /**
697      * @see BackgroundLaunchProcessController#addOrUpdateAllowBackgroundStartPrivileges(Binder,
698      * BackgroundStartPrivileges)
699      */
addOrUpdateBackgroundStartPrivileges(@onNull Binder entity, @NonNull BackgroundStartPrivileges backgroundStartPrivileges)700     public void addOrUpdateBackgroundStartPrivileges(@NonNull Binder entity,
701             @NonNull BackgroundStartPrivileges backgroundStartPrivileges) {
702         requireNonNull(entity, "entity");
703         requireNonNull(backgroundStartPrivileges, "backgroundStartPrivileges");
704         checkArgument(backgroundStartPrivileges.allowsAny(),
705                 "backgroundStartPrivileges does not allow anything");
706         mBgLaunchController.addOrUpdateAllowBackgroundStartPrivileges(entity,
707                 backgroundStartPrivileges);
708     }
709 
710     /** @see BackgroundLaunchProcessController#removeAllowBackgroundStartPrivileges(Binder) */
removeBackgroundStartPrivileges(@onNull Binder entity)711     public void removeBackgroundStartPrivileges(@NonNull Binder entity) {
712         requireNonNull(entity, "entity");
713         mBgLaunchController.removeAllowBackgroundStartPrivileges(entity);
714     }
715 
716     /**
717      * Is this WindowProcessController in the state of allowing background FGS start?
718      */
719     @HotPath(caller = HotPath.START_SERVICE)
areBackgroundFgsStartsAllowed()720     public boolean areBackgroundFgsStartsAllowed() {
721         return areBackgroundActivityStartsAllowed(
722                 mAtm.getBalAppSwitchesState(),
723                 BackgroundLaunchProcessController.CHECK_FOR_FGS_START).allows();
724     }
725 
areBackgroundActivityStartsAllowed( int appSwitchState, BalCheckConfiguration checkConfiguration)726     BackgroundActivityStartController.BalVerdict areBackgroundActivityStartsAllowed(
727             int appSwitchState, BalCheckConfiguration checkConfiguration) {
728         return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid,
729                 mInfo.packageName, appSwitchState, checkConfiguration,
730                 hasActivityInVisibleTask(), mInstrumentingWithBackgroundActivityStartPrivileges,
731                 mAtm.getLastStopAppSwitchesTime(),
732                 mLastActivityLaunchTime, mLastActivityFinishTime);
733     }
734 
735     /**
736      * Returns whether this process is allowed to close system dialogs via a background activity
737      * start token that allows the close system dialogs operation (eg. notification).
738      */
canCloseSystemDialogsByToken()739     boolean canCloseSystemDialogsByToken() {
740         return mBgLaunchController.canCloseSystemDialogsByToken(mUid);
741     }
742 
743     /**
744      * Clear all bound client Uids.
745      */
clearBoundClientUids()746     public void clearBoundClientUids() {
747         mBgLaunchController.clearBalOptInBoundClientUids();
748     }
749 
750     /**
751      * Add bound client Uid.
752      */
addBoundClientUid(int clientUid, String clientPackageName, long bindFlags)753     public void addBoundClientUid(int clientUid, String clientPackageName, long bindFlags) {
754         mBgLaunchController.addBoundClientUid(clientUid, clientPackageName, bindFlags);
755     }
756 
757     /**
758      * Set instrumentation-related info.
759      *
760      * If {@code instrumenting} is {@code false}, {@code sourceUid} has to be -1.
761      */
setInstrumenting(boolean instrumenting, int sourceUid, boolean hasBackgroundActivityStartPrivileges)762     public void setInstrumenting(boolean instrumenting, int sourceUid,
763             boolean hasBackgroundActivityStartPrivileges) {
764         checkArgument(instrumenting || sourceUid == -1);
765         mInstrumenting = instrumenting;
766         mInstrumentationSourceUid = sourceUid;
767         mInstrumentingWithBackgroundActivityStartPrivileges = hasBackgroundActivityStartPrivileges;
768     }
769 
isInstrumenting()770     boolean isInstrumenting() {
771         return mInstrumenting;
772     }
773 
774     /** Returns the uid of the active instrumentation source if there is one, otherwise -1. */
getInstrumentationSourceUid()775     int getInstrumentationSourceUid() {
776         return mInstrumentationSourceUid;
777     }
778 
setPerceptible(boolean perceptible)779     public void setPerceptible(boolean perceptible) {
780         mPerceptible = perceptible;
781     }
782 
isPerceptible()783     boolean isPerceptible() {
784         return mPerceptible;
785     }
786 
787     @Override
getChildCount()788     protected int getChildCount() {
789         return 0;
790     }
791 
792     @Override
getChildAt(int index)793     protected ConfigurationContainer getChildAt(int index) {
794         return null;
795     }
796 
797     @Override
getParent()798     protected ConfigurationContainer getParent() {
799         // Returning RootWindowContainer as the parent, so that this process controller always
800         // has full configuration and overrides (e.g. from display) are always added on top of
801         // global config.
802         return mAtm.mRootWindowContainer;
803     }
804 
805     @HotPath(caller = HotPath.PROCESS_CHANGE)
addPackage(String packageName)806     public void addPackage(String packageName) {
807         synchronized (mPkgList) {
808             if (!mPkgList.contains(packageName)) {
809                 mPkgList.add(packageName);
810             }
811         }
812     }
813 
814     @HotPath(caller = HotPath.PROCESS_CHANGE)
clearPackageList()815     public void clearPackageList() {
816         synchronized (mPkgList) {
817             mPkgList.clear();
818         }
819     }
820 
containsPackage(String packageName)821     boolean containsPackage(String packageName) {
822         synchronized (mPkgList) {
823             return mPkgList.contains(packageName);
824         }
825     }
826 
getPackageList()827     List<String> getPackageList() {
828         synchronized (mPkgList) {
829             return new ArrayList<>(mPkgList);
830         }
831     }
832 
addActivityIfNeeded(ActivityRecord r)833     void addActivityIfNeeded(ActivityRecord r) {
834         // even if we already track this activity, note down that it has been launched
835         setLastActivityLaunchTime(r);
836         if (mActivities.contains(r)) {
837             return;
838         }
839         mActivities.add(r);
840         mHasActivities = true;
841         if (mInactiveActivities != null) {
842             mInactiveActivities.remove(r);
843         }
844         updateActivityConfigurationListener();
845     }
846 
847     /**
848      * Indicates that the given activity is no longer active in this process.
849      *
850      * @param r The running activity to be removed.
851      * @param keepAssociation {@code true} if the activity still belongs to this process but will
852      *                        be removed soon, e.g. destroying. From the perspective of process
853      *                        priority, the process is not important if it only contains activities
854      *                        that are being destroyed. But the association is still needed to
855      *                        ensure all activities are reachable from this process.
856      */
removeActivity(ActivityRecord r, boolean keepAssociation)857     void removeActivity(ActivityRecord r, boolean keepAssociation) {
858         if (keepAssociation) {
859             if (mInactiveActivities == null) {
860                 mInactiveActivities = new ArrayList<>();
861                 mInactiveActivities.add(r);
862             } else if (!mInactiveActivities.contains(r)) {
863                 mInactiveActivities.add(r);
864             }
865         } else if (mInactiveActivities != null) {
866             mInactiveActivities.remove(r);
867         }
868         mActivities.remove(r);
869         mHasActivities = !mActivities.isEmpty();
870         updateActivityConfigurationListener();
871     }
872 
clearActivities()873     void clearActivities() {
874         mInactiveActivities = null;
875         mActivities.clear();
876         mHasActivities = false;
877         updateActivityConfigurationListener();
878     }
879 
880     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
hasActivities()881     public boolean hasActivities() {
882         return mHasActivities;
883     }
884 
885     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
hasVisibleActivities()886     public boolean hasVisibleActivities() {
887         return (mActivityStateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0;
888     }
889 
hasActivityInVisibleTask()890     boolean hasActivityInVisibleTask() {
891         return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0;
892     }
893 
894     @HotPath(caller = HotPath.LRU_UPDATE)
hasActivitiesOrRecentTasks()895     public boolean hasActivitiesOrRecentTasks() {
896         return mHasActivities || mHasRecentTasks;
897     }
898 
899     @Nullable
getTopActivityDisplayArea()900     TaskDisplayArea getTopActivityDisplayArea() {
901         if (mActivities.isEmpty()) {
902             return null;
903         }
904 
905         final int lastIndex = mActivities.size() - 1;
906         ActivityRecord topRecord = mActivities.get(lastIndex);
907         TaskDisplayArea displayArea = topRecord.getDisplayArea();
908 
909         for (int index = lastIndex - 1; index >= 0; --index) {
910             ActivityRecord nextRecord = mActivities.get(index);
911             TaskDisplayArea nextDisplayArea = nextRecord.getDisplayArea();
912             if (nextRecord.compareTo(topRecord) > 0 && nextDisplayArea != null) {
913                 topRecord = nextRecord;
914                 displayArea = nextDisplayArea;
915             }
916         }
917 
918         return displayArea;
919     }
920 
921     /**
922      * Update the top resuming activity in process for pre-Q apps, only the top-most visible
923      * activities are allowed to be resumed per process.
924      * @return {@code true} if the activity is allowed to be resumed by compatibility
925      * restrictions, which the activity was the topmost visible activity in process or the app is
926      * targeting after Q. Note that non-focusable activity, in picture-in-picture mode for instance,
927      * does not count as a topmost activity.
928      */
updateTopResumingActivityInProcessIfNeeded(@onNull ActivityRecord activity)929     boolean updateTopResumingActivityInProcessIfNeeded(@NonNull ActivityRecord activity) {
930         if (mInfo.targetSdkVersion >= Q || mPreQTopResumedActivity == activity) {
931             return true;
932         }
933 
934         if (!activity.isAttached()) {
935             // No need to update if the activity hasn't attach to any display.
936             return false;
937         }
938 
939         boolean canUpdate = false;
940         final DisplayContent topDisplay =
941                 (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isAttached())
942                         ? mPreQTopResumedActivity.mDisplayContent
943                         : null;
944         // Update the topmost activity if current top activity is
945         // - not on any display OR
946         // - no longer visible OR
947         // - not focusable (in PiP mode for instance)
948         if (topDisplay == null
949                 || !mPreQTopResumedActivity.isVisibleRequested()
950                 || !mPreQTopResumedActivity.isFocusable()) {
951             canUpdate = true;
952         }
953 
954         final DisplayContent display = activity.mDisplayContent;
955         // Update the topmost activity if the current top activity wasn't on top of the other one.
956         if (!canUpdate && topDisplay.compareTo(display) < 0) {
957             canUpdate = true;
958         }
959 
960         // Update the topmost activity if the activity has higher z-order than the current
961         // top-resumed activity.
962         if (!canUpdate) {
963             final ActivityRecord ar = topDisplay.getActivity(r -> r == activity,
964                     true /* traverseTopToBottom */, mPreQTopResumedActivity);
965             if (ar != null && ar != mPreQTopResumedActivity) {
966                 canUpdate = true;
967             }
968         }
969 
970         if (canUpdate) {
971             // Make sure the previous top activity in the process no longer be resumed.
972             if (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isState(RESUMED)) {
973                 final TaskFragment taskFrag = mPreQTopResumedActivity.getTaskFragment();
974                 if (taskFrag != null) {
975                     boolean userLeaving = taskFrag.shouldBeVisible(null);
976                     taskFrag.startPausing(userLeaving, false /* uiSleeping */,
977                             activity, "top-resumed-changed");
978                 }
979             }
980             mPreQTopResumedActivity = activity;
981         }
982         return canUpdate;
983     }
984 
985     // TODO(365884835): remove this method with external callers.
stopFreezingActivities()986     public void stopFreezingActivities() {
987     }
988 
finishActivities()989     void finishActivities() {
990         ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities);
991         for (int i = 0; i < activities.size(); i++) {
992             final ActivityRecord r = activities.get(i);
993             if (!r.finishing && r.isInRootTaskLocked()) {
994                 r.finishIfPossible("finish-heavy", true /* oomAdj */);
995             }
996         }
997     }
998 
isInterestingToUser()999     public boolean isInterestingToUser() {
1000         synchronized (mAtm.mGlobalLock) {
1001             final int size = mActivities.size();
1002             for (int i = 0; i < size; i++) {
1003                 ActivityRecord r = mActivities.get(i);
1004                 if (r.isInterestingToUserLocked()) {
1005                     return true;
1006                 }
1007             }
1008             if (hasEmbeddedWindow()) {
1009                 return true;
1010             }
1011         }
1012         return false;
1013     }
1014 
1015     /**
1016      * @return {@code true} if this process is rendering content on to a window shown by
1017      * another process.
1018      */
hasEmbeddedWindow()1019     private boolean hasEmbeddedWindow() {
1020         if (mRemoteActivities == null) return false;
1021         for (int i = mRemoteActivities.size() - 1; i >= 0; --i) {
1022             if ((mRemoteActivities.valueAt(i)[0] & REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY) == 0) {
1023                 continue;
1024             }
1025             final ActivityRecord r = mRemoteActivities.keyAt(i);
1026             if (r.isInterestingToUserLocked()) {
1027                 return true;
1028             }
1029         }
1030         return false;
1031     }
1032 
hasRunningActivity(String packageName)1033     public boolean hasRunningActivity(String packageName) {
1034         synchronized (mAtm.mGlobalLock) {
1035             for (int i = mActivities.size() - 1; i >= 0; --i) {
1036                 final ActivityRecord r = mActivities.get(i);
1037                 if (packageName.equals(r.packageName)) {
1038                     return true;
1039                 }
1040             }
1041         }
1042         return false;
1043     }
1044 
1045     // TODO(b/199277065): Re-assess how app-specific locales are applied based on UXR
1046     // TODO(b/199277729): Consider whether we need to add special casing for edge cases like
1047     //  activity-embeddings etc.
updateAppSpecificSettingsForAllActivitiesInPackage(String packageName, Integer nightMode, LocaleList localesOverride, @Configuration.GrammaticalGender int gender)1048     void updateAppSpecificSettingsForAllActivitiesInPackage(String packageName, Integer nightMode,
1049             LocaleList localesOverride, @Configuration.GrammaticalGender int gender) {
1050         for (int i = mActivities.size() - 1; i >= 0; --i) {
1051             final ActivityRecord r = mActivities.get(i);
1052             // Activities from other packages could be sharing this process. Only propagate updates
1053             // to those activities that are part of the package whose app-specific settings changed
1054             if (packageName.equals(r.packageName)
1055                     && r.applyAppSpecificConfig(nightMode, localesOverride, gender)
1056                     && r.isVisibleRequested()) {
1057                 r.ensureActivityConfiguration();
1058             }
1059         }
1060     }
1061 
clearPackagePreferredForHomeActivities()1062     public void clearPackagePreferredForHomeActivities() {
1063         synchronized (mAtm.mGlobalLock) {
1064             for (int i = mActivities.size() - 1; i >= 0; --i) {
1065                 final ActivityRecord r = mActivities.get(i);
1066                 if (r.isActivityTypeHome()) {
1067                     Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
1068                     try {
1069                         ActivityThread.getPackageManager()
1070                                 .clearPackagePreferredActivities(r.packageName);
1071                     } catch (RemoteException c) {
1072                         // pm is in same process, this will never happen.
1073                     }
1074                 }
1075             }
1076         }
1077     }
1078 
hasStartedActivity(ActivityRecord launchedActivity)1079     boolean hasStartedActivity(ActivityRecord launchedActivity) {
1080         for (int i = mActivities.size() - 1; i >= 0; i--) {
1081             final ActivityRecord activity = mActivities.get(i);
1082             if (launchedActivity == activity) {
1083                 continue;
1084             }
1085             if (!activity.mAppStopped) {
1086                 return true;
1087             }
1088         }
1089         return false;
1090     }
1091 
hasResumedActivity()1092     boolean hasResumedActivity() {
1093         return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0;
1094     }
1095 
updateIntentForHeavyWeightActivity(Intent intent)1096     void updateIntentForHeavyWeightActivity(Intent intent) {
1097         if (mActivities.isEmpty()) {
1098             return;
1099         }
1100         ActivityRecord hist = mActivities.get(0);
1101         intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
1102         intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().mTaskId);
1103     }
1104 
shouldKillProcessForRemovedTask(Task task)1105     boolean shouldKillProcessForRemovedTask(Task task) {
1106         for (int k = 0; k < mActivities.size(); k++) {
1107             final ActivityRecord activity = mActivities.get(k);
1108             if (!activity.mAppStopped) {
1109                 // Don't kill process(es) that has an activity not stopped.
1110                 return false;
1111             }
1112             final Task otherTask = activity.getTask();
1113             if (task.mTaskId != otherTask.mTaskId && otherTask.inRecents) {
1114                 // Don't kill process(es) that has an activity in a different task that is
1115                 // also in recents.
1116                 return false;
1117             }
1118         }
1119         return true;
1120     }
1121 
releaseSomeActivities(String reason)1122     void releaseSomeActivities(String reason) {
1123         // Examine all activities currently running in the process.
1124         // Candidate activities that can be destroyed.
1125         ArrayList<ActivityRecord> candidates = null;
1126         if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + this);
1127         for (int i = 0; i < mActivities.size(); i++) {
1128             final ActivityRecord r = mActivities.get(i);
1129             // First, if we find an activity that is in the process of being destroyed,
1130             // then we just aren't going to do anything for now; we want things to settle
1131             // down before we try to prune more activities.
1132             if (r.finishing || r.isState(DESTROYING, DESTROYED)) {
1133                 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r);
1134                 return;
1135             }
1136             // Don't consider any activities that are currently not in a state where they
1137             // can be destroyed.
1138             if (r.isVisibleRequested() || !r.mAppStopped || !r.hasSavedState() || !r.isDestroyable()
1139                     || r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING)) {
1140                 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
1141                 continue;
1142             }
1143 
1144             if (r.getParent() != null) {
1145                 if (candidates == null) {
1146                     candidates = new ArrayList<>();
1147                 }
1148                 candidates.add(r);
1149             }
1150         }
1151 
1152         if (candidates != null) {
1153             // Sort based on z-order in hierarchy.
1154             candidates.sort(WindowContainer::compareTo);
1155             // Release some older activities
1156             int maxRelease = Math.max(candidates.size(), 1);
1157             do {
1158                 final ActivityRecord r = candidates.remove(0);
1159                 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + r
1160                         + " in state " + r.getState() + " for reason " + reason);
1161                 r.destroyImmediately(reason);
1162                 --maxRelease;
1163             } while (maxRelease > 0);
1164         }
1165     }
1166 
1167     /**
1168      * Returns display UI context list which there is any app window shows or starting activities
1169      * in this process.
1170      */
getDisplayContextsWithErrorDialogs(List<Context> displayContexts)1171     public void getDisplayContextsWithErrorDialogs(List<Context> displayContexts) {
1172         if (displayContexts == null) {
1173             return;
1174         }
1175         synchronized (mAtm.mGlobalLock) {
1176             final RootWindowContainer root = mAtm.mWindowManager.mRoot;
1177             root.getDisplayContextsWithNonToastVisibleWindows(mPid, displayContexts);
1178 
1179             for (int i = mActivities.size() - 1; i >= 0; --i) {
1180                 final ActivityRecord r = mActivities.get(i);
1181                 final int displayId = r.getDisplayId();
1182                 final Context c = root.getDisplayUiContext(displayId);
1183 
1184                 if (c != null && r.isVisibleRequested() && !displayContexts.contains(c)) {
1185                     displayContexts.add(c);
1186                 }
1187             }
1188         }
1189     }
1190 
1191     /** Adds an activity that hosts UI drawn by the current process. */
addHostActivity(ActivityRecord r)1192     void addHostActivity(ActivityRecord r) {
1193         final int[] flags = getRemoteActivityFlags(r);
1194         flags[0] |= REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY;
1195     }
1196 
1197     /** Removes an activity that hosts UI drawn by the current process. */
removeHostActivity(ActivityRecord r)1198     void removeHostActivity(ActivityRecord r) {
1199         removeRemoteActivityFlags(r, REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY);
1200     }
1201 
1202     /** Adds an embedded activity in a different process to this process that organizes it. */
addEmbeddedActivity(ActivityRecord r)1203     void addEmbeddedActivity(ActivityRecord r) {
1204         final int[] flags = getRemoteActivityFlags(r);
1205         flags[0] |= REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY;
1206     }
1207 
1208     /** Removes an embedded activity which was added by {@link #addEmbeddedActivity}. */
removeEmbeddedActivity(ActivityRecord r)1209     void removeEmbeddedActivity(ActivityRecord r) {
1210         removeRemoteActivityFlags(r, REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY);
1211     }
1212 
getRemoteActivityFlags(ActivityRecord r)1213     private int[] getRemoteActivityFlags(ActivityRecord r) {
1214         if (mRemoteActivities == null) {
1215             mRemoteActivities = new ArrayMap<>();
1216         }
1217         int[] flags = mRemoteActivities.get(r);
1218         if (flags == null) {
1219             mRemoteActivities.put(r, flags = new int[1]);
1220         }
1221         return flags;
1222     }
1223 
removeRemoteActivityFlags(ActivityRecord r, int flags)1224     private void removeRemoteActivityFlags(ActivityRecord r, int flags) {
1225         if (mRemoteActivities == null) return;
1226         final int index = mRemoteActivities.indexOfKey(r);
1227         if (index < 0) return;
1228         final int[] currentFlags = mRemoteActivities.valueAt(index);
1229         currentFlags[0] &= ~flags;
1230         if (currentFlags[0] == 0) {
1231             mRemoteActivities.removeAt(index);
1232         }
1233     }
1234 
1235     /**
1236      * Returns the current ACTIVITY_STATE_FLAG_* of this process. It should only be called if
1237      * {@link #hasActivities} returns {@code true}.
1238      */
1239     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
getActivityStateFlags()1240     public int getActivityStateFlags() {
1241         return mActivityStateFlags;
1242     }
1243 
1244     /**
1245      * Returns the most recent timestamp when one of this process's stopped activities in a
1246      * perceptible task became stopped. It should only be called if {@link #hasActivities}
1247      * returns {@code true} and {@link #getActivityStateFlags} does not have any of
1248      * the ACTIVITY_STATE_FLAG_IS_(VISIBLE|PAUSING_OR_PAUSED|STOPPING) bit set.
1249      */
1250     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
getPerceptibleTaskStoppedTimeMillis()1251     public long getPerceptibleTaskStoppedTimeMillis() {
1252         return mPerceptibleTaskStoppedTimeMillis;
1253     }
1254 
computeProcessActivityState()1255     void computeProcessActivityState() {
1256         // Since there could be more than one activities in a process record, we don't need to
1257         // compute the OomAdj with each of them, just need to find out the activity with the
1258         // "best" state, the order would be visible, pausing, stopping...
1259         ActivityRecord.State bestInvisibleState = DESTROYED;
1260         boolean allStoppingFinishing = true;
1261         boolean visible = false;
1262         boolean hasResumedFreeform = false;
1263         int minTaskLayer = Integer.MAX_VALUE;
1264         int stateFlags = 0;
1265         int nonOccludedRatio = 0;
1266         long perceptibleTaskStoppedTimeMillis = Long.MIN_VALUE;
1267         final boolean wasResumed = hasResumedActivity();
1268         final boolean wasAnyVisible = (mActivityStateFlags & ACTIVITY_STATE_VISIBLE) != 0;
1269         for (int i = mActivities.size() - 1; i >= 0; i--) {
1270             final ActivityRecord r = mActivities.get(i);
1271             if (r.isVisible()) {
1272                 stateFlags |= ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE;
1273             }
1274             final Task task = r.getTask();
1275             if (task == null) {
1276                 Slog.e(TAG, "Unexpected detached " + r + " in " + this);
1277                 continue;
1278             }
1279             if (task.mLayerRank != Task.LAYER_RANK_INVISIBLE) {
1280                 stateFlags |= ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK;
1281             }
1282             final ActivityRecord.State state = r.getState();
1283             if (r.isVisibleRequested()) {
1284                 if (state == RESUMED) {
1285                     stateFlags |= ACTIVITY_STATE_FLAG_HAS_RESUMED;
1286                     final int windowingMode = r.getWindowingMode();
1287                     if (windowingMode == WINDOWING_MODE_MULTI_WINDOW
1288                             && com.android.window.flags.Flags
1289                                     .processPriorityPolicyForMultiWindowMode()
1290                             && task.hasAdjacentTask()) {
1291                         stateFlags |= ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN;
1292                     } else if (windowingMode == WINDOWING_MODE_FREEFORM) {
1293                         hasResumedFreeform = true;
1294                         nonOccludedRatio =
1295                                 Math.max(task.mNonOccludedFreeformAreaRatio, nonOccludedRatio);
1296                     }
1297                 }
1298                 if (minTaskLayer > 0) {
1299                     final int layer = task.mLayerRank;
1300                     if (layer >= 0 && minTaskLayer > layer) {
1301                         minTaskLayer = layer;
1302                     }
1303                 }
1304                 visible = true;
1305                 // continue the loop, in case there are multiple visible activities in
1306                 // this process, we'd find out the one with the minimal layer, thus it'll
1307                 // get a higher adj score.
1308             } else if (!visible && bestInvisibleState != PAUSING) {
1309                 if (state == PAUSING) {
1310                     bestInvisibleState = PAUSING;
1311                     // Treat PAUSING as visible in case the next activity in the same process has
1312                     // not yet been set as visible-requested.
1313                     if (com.android.window.flags.Flags.useVisibleRequestedForProcessTracker()
1314                             && r.isVisible()) {
1315                         stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE;
1316                     }
1317                 } else if (state == PAUSED) {
1318                     bestInvisibleState = PAUSED;
1319                 } else if (state == STOPPING) {
1320                     bestInvisibleState = STOPPING;
1321                     // Not "finishing" if any of activity isn't finishing.
1322                     allStoppingFinishing &= r.finishing;
1323                 } else if (bestInvisibleState == DESTROYED && state == STOPPED) {
1324                     if (task.mIsPerceptible) {
1325                         perceptibleTaskStoppedTimeMillis =
1326                                 Long.max(r.mStoppedTime, perceptibleTaskStoppedTimeMillis);
1327                     }
1328                 }
1329             }
1330         }
1331         if (mRemoteActivities != null) {
1332             // Make this process have visible state if its organizer embeds visible activities of
1333             // other process, so this process can be responsive for the organizer events.
1334             for (int i = mRemoteActivities.size() - 1; i >= 0; i--) {
1335                 if ((mRemoteActivities.valueAt(i)[0] & REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY) != 0
1336                         && mRemoteActivities.keyAt(i).isVisibleRequested()) {
1337                     stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE;
1338                 }
1339             }
1340         }
1341 
1342         if (hasResumedFreeform
1343                 && com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()
1344                 // Exclude task layer 1 because it is already the top most.
1345                 && minTaskLayer > 1) {
1346             if (minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM
1347                     || nonOccludedRatio >= PERCEPTIBLE_FREEFORM_VISIBLE_RATIO) {
1348                 stateFlags |= ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM;
1349             } else {
1350                 stateFlags |= ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE;
1351             }
1352         }
1353         stateFlags |= minTaskLayer & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
1354         if (visible) {
1355             stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE;
1356         } else if (bestInvisibleState == PAUSING || bestInvisibleState == PAUSED) {
1357             stateFlags |= ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED;
1358         } else if (bestInvisibleState == STOPPING) {
1359             stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING;
1360             if (allStoppingFinishing) {
1361                 stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING;
1362             }
1363         }
1364         mActivityStateFlags = stateFlags;
1365         mPerceptibleTaskStoppedTimeMillis = perceptibleTaskStoppedTimeMillis;
1366 
1367         final boolean anyVisible = (stateFlags & ACTIVITY_STATE_VISIBLE) != 0;
1368         if (!wasAnyVisible && anyVisible) {
1369             mAtm.mVisibleActivityProcessTracker.onAnyActivityVisible(this);
1370             mAtm.mWindowManager.onProcessActivityVisibilityChanged(mUid, true /*visible*/);
1371         } else if (wasAnyVisible && !anyVisible) {
1372             mAtm.mVisibleActivityProcessTracker.onAllActivitiesInvisible(this);
1373             mAtm.mWindowManager.onProcessActivityVisibilityChanged(mUid, false /*visible*/);
1374         } else if (wasAnyVisible && !wasResumed && hasResumedActivity()) {
1375             mAtm.mVisibleActivityProcessTracker.onActivityResumedWhileVisible(this);
1376         }
1377     }
1378 
1379     /** Called when the process has some oom related changes and it is going to update oom-adj. */
prepareOomAdjustment()1380     private void prepareOomAdjustment() {
1381         mAtm.mRootWindowContainer.rankTaskLayers();
1382         mAtm.mTaskSupervisor.computeProcessActivityStateBatch();
1383     }
1384 
computeRelaunchReason()1385     public int computeRelaunchReason() {
1386         synchronized (mAtm.mGlobalLock) {
1387             final int activitiesSize = mActivities.size();
1388             for (int i = activitiesSize - 1; i >= 0; i--) {
1389                 final ActivityRecord r = mActivities.get(i);
1390                 if (r.mRelaunchReason != RELAUNCH_REASON_NONE) {
1391                     return r.mRelaunchReason;
1392                 }
1393             }
1394         }
1395         return RELAUNCH_REASON_NONE;
1396     }
1397 
1398     /**
1399      * Get the current dispatching timeout. If instrumentation is currently taking place, return
1400      * a longer value. Shorter timeout is returned otherwise.
1401      * @return The timeout in milliseconds
1402      */
getInputDispatchingTimeoutMillis()1403     public long getInputDispatchingTimeoutMillis() {
1404         synchronized (mAtm.mGlobalLock) {
1405             return isInstrumenting() || isUsingWrapper()
1406                     ? INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS :
1407                     DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
1408         }
1409     }
1410 
clearProfilerIfNeeded()1411     void clearProfilerIfNeeded() {
1412         // Posting on handler so WM lock isn't held when we call into AM.
1413         mAtm.mH.sendMessage(PooledLambda.obtainMessage(
1414                 WindowProcessListener::clearProfilerIfNeeded, mListener));
1415     }
1416 
updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, boolean updateOomAdj, boolean addPendingTopUid)1417     void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
1418             boolean updateOomAdj, boolean addPendingTopUid) {
1419         if (addPendingTopUid) {
1420             addToPendingTop();
1421         }
1422         if (updateOomAdj) {
1423             prepareOomAdjustment();
1424         }
1425         // Posting on handler so WM lock isn't held when we call into AM.
1426         final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo,
1427                 mListener, updateServiceConnectionActivities, activityChange, updateOomAdj);
1428         mAtm.mH.sendMessage(m);
1429     }
1430 
1431     /** Refreshes oom adjustment and process state of this process. */
scheduleUpdateOomAdj()1432     void scheduleUpdateOomAdj() {
1433         mAtm.mH.sendMessage(PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo,
1434                 mListener, false /* updateServiceConnectionActivities */,
1435                 false /* activityChange */, true /* updateOomAdj */));
1436     }
1437 
1438     /** Makes the process have top state before oom-adj is computed from a posted message. */
addToPendingTop()1439     void addToPendingTop() {
1440         mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread);
1441     }
1442 
updateServiceConnectionActivities()1443     void updateServiceConnectionActivities() {
1444         // Posting on handler so WM lock isn't held when we call into AM.
1445         mAtm.mH.sendMessage(PooledLambda.obtainMessage(
1446                 WindowProcessListener::updateServiceConnectionActivities, mListener));
1447     }
1448 
setPendingUiCleanAndForceProcessStateUpTo(int newState)1449     void setPendingUiCleanAndForceProcessStateUpTo(int newState) {
1450         // Posting on handler so WM lock isn't held when we call into AM.
1451         final Message m = PooledLambda.obtainMessage(
1452                 WindowProcessListener::setPendingUiCleanAndForceProcessStateUpTo,
1453                 mListener, newState);
1454         mAtm.mH.sendMessage(m);
1455     }
1456 
isRemoved()1457     boolean isRemoved() {
1458         return mListener.isRemoved();
1459     }
1460 
shouldSetProfileProc()1461     private boolean shouldSetProfileProc() {
1462         return mAtm.mProfileApp != null && mAtm.mProfileApp.equals(mName)
1463                 && (mAtm.mProfileProc == null || mAtm.mProfileProc == this);
1464     }
1465 
createProfilerInfoIfNeeded()1466     ProfilerInfo createProfilerInfoIfNeeded() {
1467         final ProfilerInfo currentProfilerInfo = mAtm.mProfilerInfo;
1468         if (currentProfilerInfo == null || currentProfilerInfo.profileFile == null
1469                 || !shouldSetProfileProc()) {
1470             return null;
1471         }
1472         if (currentProfilerInfo.profileFd != null) {
1473             try {
1474                 currentProfilerInfo.profileFd = currentProfilerInfo.profileFd.dup();
1475             } catch (IOException e) {
1476                 currentProfilerInfo.closeFd();
1477             }
1478         }
1479         return new ProfilerInfo(currentProfilerInfo);
1480     }
1481 
onStartActivity(int topProcessState, ActivityInfo info)1482     void onStartActivity(int topProcessState, ActivityInfo info) {
1483         String packageName = null;
1484         if ((info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
1485                 || !"android".equals(info.packageName)) {
1486             // Don't add this if it is a platform component that is marked to run in multiple
1487             // processes, because this is actually part of the framework so doesn't make sense
1488             // to track as a separate apk in the process.
1489             packageName = info.packageName;
1490         }
1491         // update ActivityManagerService.PendingStartActivityUids list.
1492         if (topProcessState == ActivityManager.PROCESS_STATE_TOP) {
1493             mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread);
1494         }
1495         prepareOomAdjustment();
1496         // Posting the message at the front of queue so WM lock isn't held when we call into AM,
1497         // and the process state of starting activity can be updated quicker which will give it a
1498         // higher scheduling group.
1499         final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity,
1500                 mListener, topProcessState, shouldSetProfileProc(), packageName,
1501                 info.applicationInfo.longVersionCode);
1502         mAtm.mH.sendMessageAtFrontOfQueue(m);
1503     }
1504 
appDied(String reason)1505     void appDied(String reason) {
1506         // Posting on handler so WM lock isn't held when we call into AM.
1507         final Message m = PooledLambda.obtainMessage(
1508                 WindowProcessListener::appDied, mListener, reason);
1509         mAtm.mH.sendMessage(m);
1510     }
1511 
1512     /**
1513      * Clean up the activities belonging to this process.
1514      *
1515      * @return {@code true} if the process has any visible activity.
1516      */
handleAppDied()1517     boolean handleAppDied() {
1518         mAtm.mTaskSupervisor.removeHistoryRecords(this);
1519 
1520         boolean hasVisibleActivities = false;
1521         final boolean hasInactiveActivities =
1522                 mInactiveActivities != null && !mInactiveActivities.isEmpty();
1523         final ArrayList<ActivityRecord> activities =
1524                 (mHasActivities || hasInactiveActivities) ? new ArrayList<>() : mActivities;
1525         if (mHasActivities) {
1526             activities.addAll(mActivities);
1527         }
1528         if (hasInactiveActivities) {
1529             // Make sure that all activities in this process are handled.
1530             activities.addAll(mInactiveActivities);
1531         }
1532         if (isRemoved()) {
1533             // The package of the died process should be force-stopped, so make its activities as
1534             // finishing to prevent the process from being started again if the next top (or being
1535             // visible) activity also resides in the same process. This must be done before removal.
1536             for (int i = activities.size() - 1; i >= 0; i--) {
1537                 activities.get(i).makeFinishingLocked();
1538             }
1539         }
1540         for (int i = activities.size() - 1; i >= 0; i--) {
1541             final ActivityRecord r = activities.get(i);
1542             if (r.isVisibleRequested() || r.isVisible()) {
1543                 // While an activity launches a new activity, it's possible that the old activity
1544                 // is already requested to be hidden (mVisibleRequested=false), but this visibility
1545                 // is not yet committed, so isVisible()=true.
1546                 hasVisibleActivities = true;
1547             }
1548 
1549             final TaskFragment taskFragment = r.getTaskFragment();
1550             if (taskFragment != null) {
1551                 // There may be a pausing activity that hasn't shown any window and was requested
1552                 // to be hidden. But pausing is also a visible state, it should be regarded as
1553                 // visible, so the caller can know the next activity should be resumed.
1554                 hasVisibleActivities |= taskFragment.handleAppDied(this);
1555             }
1556             r.handleAppDied();
1557         }
1558         clearRecentTasks();
1559         clearActivities();
1560 
1561         return hasVisibleActivities;
1562     }
1563 
registerDisplayAreaConfigurationListener(@ullable DisplayArea displayArea)1564     void registerDisplayAreaConfigurationListener(@Nullable DisplayArea displayArea) {
1565         if (displayArea == null || displayArea.containsListener(this)) {
1566             return;
1567         }
1568         unregisterConfigurationListeners();
1569         mDisplayArea = displayArea;
1570         displayArea.registerConfigurationChangeListener(this);
1571     }
1572 
1573     @VisibleForTesting
unregisterDisplayAreaConfigurationListener()1574     void unregisterDisplayAreaConfigurationListener() {
1575         if (mDisplayArea == null) {
1576             return;
1577         }
1578         mDisplayArea.unregisterConfigurationChangeListener(this);
1579         mDisplayArea = null;
1580         onMergedOverrideConfigurationChanged(Configuration.EMPTY);
1581     }
1582 
registerActivityConfigurationListener(ActivityRecord activityRecord)1583     void registerActivityConfigurationListener(ActivityRecord activityRecord) {
1584         if (activityRecord == null || activityRecord.containsListener(this)
1585                 // Check for the caller from outside of this class.
1586                 || !mIsActivityConfigOverrideAllowed) {
1587             return;
1588         }
1589         unregisterConfigurationListeners();
1590         mConfigActivityRecord = activityRecord;
1591         activityRecord.registerConfigurationChangeListener(this);
1592         // If the process hasn't attached, make sure that prepareConfigurationForLaunchingActivity
1593         // will use the newer configuration sequence.
1594         if (mThread == null) {
1595             mHasPendingConfigurationChange = true;
1596         }
1597     }
1598 
unregisterActivityConfigurationListener()1599     private void unregisterActivityConfigurationListener() {
1600         if (mConfigActivityRecord == null) {
1601             return;
1602         }
1603         mConfigActivityRecord.unregisterConfigurationChangeListener(this);
1604         mConfigActivityRecord = null;
1605         onMergedOverrideConfigurationChanged(Configuration.EMPTY);
1606     }
1607 
1608     /**
1609      * A process can only register to one {@link WindowContainer} to listen to the override
1610      * configuration changes. Unregisters the existing listener if it has one before registers a
1611      * new one.
1612      */
unregisterConfigurationListeners()1613     private void unregisterConfigurationListeners() {
1614         unregisterActivityConfigurationListener();
1615         unregisterDisplayAreaConfigurationListener();
1616     }
1617 
1618     /**
1619      * Destroys the WindwoProcessController, after the process has been removed.
1620      */
destroy()1621     void destroy() {
1622         unregisterConfigurationListeners();
1623     }
1624 
1625     /**
1626      * Check if activity configuration override for the activity process needs an update and perform
1627      * if needed. By default we try to override the process configuration to match the top activity
1628      * config to increase app compatibility with multi-window and multi-display. The process will
1629      * always track the configuration of the non-finishing activity last added to the process.
1630      */
updateActivityConfigurationListener()1631     private void updateActivityConfigurationListener() {
1632         if (!mIsActivityConfigOverrideAllowed) {
1633             return;
1634         }
1635 
1636         for (int i = mActivities.size() - 1; i >= 0; i--) {
1637             final ActivityRecord activityRecord = mActivities.get(i);
1638             if (!activityRecord.finishing) {
1639                 // Eligible activity is found, update listener.
1640                 registerActivityConfigurationListener(activityRecord);
1641                 return;
1642             }
1643         }
1644 
1645         // No eligible activities found, let's remove the configuration listener.
1646         unregisterActivityConfigurationListener();
1647     }
1648 
1649     @Override
onConfigurationChanged(Configuration newGlobalConfig)1650     public void onConfigurationChanged(Configuration newGlobalConfig) {
1651         super.onConfigurationChanged(newGlobalConfig);
1652 
1653         // If deviceId for the top-activity changed, schedule passing it to the app process.
1654         boolean topActivityDeviceChanged = false;
1655         int deviceId = getTopActivityDeviceId();
1656         if (deviceId != mLastTopActivityDeviceId) {
1657             topActivityDeviceChanged = true;
1658             mLastTopActivityDeviceId = deviceId;
1659         }
1660 
1661         final Configuration config = getConfiguration();
1662         if (mLastReportedConfiguration.equals(config) & !topActivityDeviceChanged) {
1663             // Nothing changed.
1664             if (Build.IS_DEBUGGABLE && mHasImeService) {
1665                 // TODO (b/135719017): Temporary log for debugging IME service.
1666                 Slog.w(TAG_CONFIGURATION, "Current config: " + config
1667                         + " unchanged for IME proc " + mName);
1668             }
1669             return;
1670         }
1671 
1672         if (mPauseConfigurationDispatchCount > 0) {
1673             mHasPendingConfigurationChange = true;
1674             return;
1675         }
1676 
1677         dispatchConfiguration(config);
1678     }
1679 
getTopActivityDeviceId()1680     private int getTopActivityDeviceId() {
1681         ActivityRecord topActivity = getTopNonFinishingActivity();
1682         int updatedDeviceId = Context.DEVICE_ID_DEFAULT;
1683         if (topActivity != null && topActivity.mDisplayContent != null) {
1684             updatedDeviceId = mAtm.mTaskSupervisor.getDeviceIdForDisplayId(
1685                     topActivity.mDisplayContent.mDisplayId);
1686         }
1687         return updatedDeviceId;
1688     }
1689 
1690     @Nullable
getTopNonFinishingActivity()1691     private ActivityRecord getTopNonFinishingActivity() {
1692         if (mActivities.isEmpty()) {
1693             return null;
1694         }
1695         for (int i = mActivities.size() - 1; i >= 0; i--) {
1696             if (!mActivities.get(i).finishing) {
1697                 return mActivities.get(i);
1698             }
1699         }
1700         return null;
1701     }
1702 
1703     @Override
onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig)1704     public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) {
1705         super.onRequestedOverrideConfigurationChanged(mergedOverrideConfig);
1706     }
1707 
1708     @Override
resolveOverrideConfiguration(Configuration newParentConfig)1709     void resolveOverrideConfiguration(Configuration newParentConfig) {
1710         final Configuration requestedOverrideConfig = getRequestedOverrideConfiguration();
1711         if (requestedOverrideConfig.assetsSeq != ASSETS_SEQ_UNDEFINED
1712                 && newParentConfig.assetsSeq > requestedOverrideConfig.assetsSeq) {
1713             requestedOverrideConfig.assetsSeq = ASSETS_SEQ_UNDEFINED;
1714         }
1715         super.resolveOverrideConfiguration(newParentConfig);
1716         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
1717         // Make sure that we don't accidentally override the activity type.
1718         resolvedConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
1719         // Activity has an independent ActivityRecord#mConfigurationSeq. If this process registers
1720         // activity configuration, its config seq shouldn't go backwards by activity configuration.
1721         // Otherwise if other places send wpc.getConfiguration() to client, the configuration may
1722         // be ignored due to the seq is older.
1723         resolvedConfig.seq = newParentConfig.seq;
1724 
1725         if (mConfigActivityRecord != null) {
1726             // Let the activity decide whether to apply the size override.
1727             return;
1728         }
1729         final DisplayContent displayContent = mAtm.mWindowManager != null
1730                 ? mAtm.mWindowManager.getDefaultDisplayContentLocked()
1731                 : null;
1732         applySizeOverrideIfNeeded(
1733                 displayContent,
1734                 mInfo,
1735                 newParentConfig,
1736                 resolvedConfig,
1737                 false /* optsOutEdgeToEdge */,
1738                 false /* hasFixedRotationTransform */,
1739                 false /* hasCompatDisplayInsets */,
1740                 null /* task */);
1741     }
1742 
dispatchConfiguration(@onNull Configuration config)1743     void dispatchConfiguration(@NonNull Configuration config) {
1744         mHasPendingConfigurationChange = false;
1745         final IApplicationThread thread = mThread;
1746         if (thread == null) {
1747             if (Build.IS_DEBUGGABLE && mHasImeService) {
1748                 // TODO (b/135719017): Temporary log for debugging IME service.
1749                 Slog.w(TAG_CONFIGURATION, "Unable to send config for IME proc " + mName
1750                         + ": no app thread");
1751             }
1752             return;
1753         }
1754 
1755         config.seq = mAtm.increaseConfigurationSeqLocked();
1756         setLastReportedConfiguration(config);
1757 
1758         // A cached process doesn't have running application components, so it is unnecessary to
1759         // notify the configuration change. The last-reported-configuration is still set because
1760         // setReportedProcState() should not write any fields that require WM lock.
1761         if (mRepProcState >= CACHED_CONFIG_PROC_STATE) {
1762             mHasCachedConfiguration = true;
1763             // Because there are 2 volatile accesses in setReportedProcState(): mRepProcState and
1764             // mHasCachedConfiguration, check again in case mRepProcState is changed but hasn't
1765             // read the change of mHasCachedConfiguration.
1766             if (mRepProcState >= CACHED_CONFIG_PROC_STATE) {
1767                 return;
1768             }
1769         }
1770 
1771         onConfigurationChangePreScheduled(config);
1772         scheduleClientTransactionItem(
1773                 thread, new ConfigurationChangeItem(config, mLastTopActivityDeviceId));
1774     }
1775 
onConfigurationChangePreScheduled(@onNull Configuration config)1776     private void onConfigurationChangePreScheduled(@NonNull Configuration config) {
1777         ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
1778                 config);
1779         if (Build.IS_DEBUGGABLE && mHasImeService) {
1780             // TODO (b/135719017): Temporary log for debugging IME service.
1781             Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config);
1782         }
1783         mHasCachedConfiguration = false;
1784     }
1785 
1786     @VisibleForTesting
scheduleClientTransactionItem(@onNull ClientTransactionItem transactionItem)1787     void scheduleClientTransactionItem(@NonNull ClientTransactionItem transactionItem) {
1788         final IApplicationThread thread = mThread;
1789         if (thread == null) {
1790             if (Build.IS_DEBUGGABLE) {
1791                 Slog.w(TAG_CONFIGURATION, "Unable to send transaction to client proc " + mName
1792                         + ": no app thread");
1793             }
1794             return;
1795         }
1796         scheduleClientTransactionItem(thread, transactionItem);
1797     }
1798 
scheduleClientTransactionItem(@onNull IApplicationThread thread, @NonNull ClientTransactionItem transactionItem)1799     private void scheduleClientTransactionItem(@NonNull IApplicationThread thread,
1800             @NonNull ClientTransactionItem transactionItem) {
1801         try {
1802             if (mWindowSession != null && mWindowSession.hasWindow()) {
1803                 mAtm.getLifecycleManager().scheduleTransactionItem(thread, transactionItem);
1804             } else {
1805                 // Non-UI process can handle the change directly.
1806                 mAtm.getLifecycleManager().scheduleTransactionItemNow(thread, transactionItem);
1807             }
1808         } catch (RemoteException e) {
1809             // TODO(b/323801078): remove Exception when cleanup
1810             // Expected if the process has been killed.
1811             Slog.w(TAG_CONFIGURATION, "Failed for dead process. ClientTransactionItem="
1812                     + transactionItem + " owner=" + mOwner);
1813         }
1814     }
1815 
setLastReportedConfiguration(Configuration config)1816     void setLastReportedConfiguration(Configuration config) {
1817         // Synchronize for the access from setReportedProcState().
1818         synchronized (mLastReportedConfiguration) {
1819             mLastReportedConfiguration.setTo(config);
1820         }
1821     }
1822 
pauseConfigurationDispatch()1823     void pauseConfigurationDispatch() {
1824         mPauseConfigurationDispatchCount++;
1825     }
1826 
1827     /** Returns {@code true} if the configuration change is pending to dispatch. */
resumeConfigurationDispatch()1828     boolean resumeConfigurationDispatch() {
1829         if (mPauseConfigurationDispatchCount == 0) {
1830             return false;
1831         }
1832         mPauseConfigurationDispatchCount--;
1833         return mHasPendingConfigurationChange;
1834     }
1835 
updateAssetConfiguration(int assetSeq)1836     void updateAssetConfiguration(int assetSeq) {
1837         // Update the process override configuration directly if the process configuration will
1838         // not be override from its activities.
1839         if (!mHasActivities || !mIsActivityConfigOverrideAllowed) {
1840             Configuration overrideConfig = new Configuration(getRequestedOverrideConfiguration());
1841             overrideConfig.assetsSeq = assetSeq;
1842             onRequestedOverrideConfigurationChanged(overrideConfig);
1843             return;
1844         }
1845 
1846         // Otherwise, we can just update the activity override configuration.
1847         for (int i = mActivities.size() - 1; i >= 0; i--) {
1848             ActivityRecord r = mActivities.get(i);
1849             Configuration overrideConfig = new Configuration(r.getRequestedOverrideConfiguration());
1850             overrideConfig.assetsSeq = assetSeq;
1851             r.onRequestedOverrideConfigurationChanged(overrideConfig);
1852             r.updateApplicationInfo(mInfo);
1853             if (r.isVisibleRequested()) {
1854                 r.ensureActivityConfiguration();
1855             }
1856         }
1857     }
1858 
updateApplicationInfo(ApplicationInfo aInfo)1859     public void updateApplicationInfo(ApplicationInfo aInfo) {
1860         mInfo = aInfo;
1861     }
1862 
1863     /**
1864      * This is called for sending {@link android.app.servertransaction.LaunchActivityItem}.
1865      * The caller must call {@link #setLastReportedConfiguration} if the delivered configuration
1866      * is newer.
1867      */
prepareConfigurationForLaunchingActivity()1868     Configuration prepareConfigurationForLaunchingActivity() {
1869         final Configuration config = getConfiguration();
1870         if (mHasPendingConfigurationChange) {
1871             mHasPendingConfigurationChange = false;
1872             // The global configuration may not change, so the client process may have the same
1873             // config seq. This increment ensures that the client won't ignore the configuration.
1874             config.seq = mAtm.increaseConfigurationSeqLocked();
1875         }
1876         // LaunchActivityItem includes the latest process configuration.
1877         mHasCachedConfiguration = false;
1878         return config;
1879     }
1880 
1881     /** Returns the total time (in milliseconds) spent executing in both user and system code. */
getCpuTime()1882     public long getCpuTime() {
1883         return mListener.getCpuTime();
1884     }
1885 
addRecentTask(Task task)1886     void addRecentTask(Task task) {
1887         mRecentTasks.add(task);
1888         mHasRecentTasks = true;
1889     }
1890 
removeRecentTask(Task task)1891     void removeRecentTask(Task task) {
1892         mRecentTasks.remove(task);
1893         mHasRecentTasks = !mRecentTasks.isEmpty();
1894     }
1895 
1896     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
hasRecentTasks()1897     public boolean hasRecentTasks() {
1898         return mHasRecentTasks;
1899     }
1900 
clearRecentTasks()1901     void clearRecentTasks() {
1902         for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
1903             mRecentTasks.get(i).clearRootProcess();
1904         }
1905         mRecentTasks.clear();
1906         mHasRecentTasks = false;
1907     }
1908 
appEarlyNotResponding(String annotation, Runnable killAppCallback)1909     public void appEarlyNotResponding(String annotation, Runnable killAppCallback) {
1910         Runnable targetRunnable = null;
1911         synchronized (mAtm.mGlobalLock) {
1912             if (mAtm.mController == null) {
1913                 return;
1914             }
1915 
1916             try {
1917                 // 0 == continue, -1 = kill process immediately
1918                 int res = mAtm.mController.appEarlyNotResponding(mName, mPid, annotation);
1919                 if (res < 0 && mPid != MY_PID) {
1920                     targetRunnable = killAppCallback;
1921                 }
1922             } catch (RemoteException e) {
1923                 mAtm.mController = null;
1924                 Watchdog.getInstance().setActivityController(null);
1925             }
1926         }
1927         if (targetRunnable != null) {
1928             targetRunnable.run();
1929         }
1930     }
1931 
appNotResponding(String info, Runnable killAppCallback, Runnable serviceTimeoutCallback)1932     public boolean appNotResponding(String info, Runnable killAppCallback,
1933             Runnable serviceTimeoutCallback) {
1934         Runnable targetRunnable = null;
1935         synchronized (mAtm.mGlobalLock) {
1936             if (mAtm.mController == null) {
1937                 return false;
1938             }
1939 
1940             try {
1941                 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
1942                 int res = mAtm.mController.appNotResponding(mName, mPid, info);
1943                 if (res != 0) {
1944                     if (res < 0 && mPid != MY_PID) {
1945                         targetRunnable = killAppCallback;
1946                     } else {
1947                         targetRunnable = serviceTimeoutCallback;
1948                     }
1949                 }
1950             } catch (RemoteException e) {
1951                 mAtm.mController = null;
1952                 Watchdog.getInstance().setActivityController(null);
1953                 return false;
1954             }
1955         }
1956         if (targetRunnable != null) {
1957             // Execute runnable outside WM lock since the runnable will hold AM lock
1958             targetRunnable.run();
1959             return true;
1960         }
1961         return false;
1962     }
1963 
1964     /**
1965      * Called to notify {@link WindowProcessController} of a started service.
1966      *
1967      * @param serviceInfo information describing the started service.
1968      */
onServiceStarted(ServiceInfo serviceInfo)1969     public void onServiceStarted(ServiceInfo serviceInfo) {
1970         String permission = serviceInfo.permission;
1971         if (permission == null) {
1972             return;
1973         }
1974 
1975         // TODO: Audit remaining services for disabling activity override (Wallpaper, Dream, etc).
1976         switch (permission) {
1977             case Manifest.permission.BIND_INPUT_METHOD:
1978                 mHasImeService = true;
1979                 // Fall-through
1980             case Manifest.permission.BIND_ACCESSIBILITY_SERVICE:
1981             case Manifest.permission.BIND_VOICE_INTERACTION:
1982                 // We want to avoid overriding the config of these services with that of the
1983                 // activity as it could lead to incorrect display metrics. For ex, IME services
1984                 // expect their config to match the config of the display with the IME window
1985                 // showing.
1986                 // If the configuration has been overridden by previous activity, empty it.
1987                 mIsActivityConfigOverrideAllowed = false;
1988                 // The call to `onServiceStarted` is not guarded with WM lock.
1989                 mAtm.mH.post(() -> {
1990                     synchronized (mAtm.mGlobalLock) {
1991                         unregisterActivityConfigurationListener();
1992                     }
1993                 });
1994                 break;
1995             default:
1996                 break;
1997         }
1998     }
1999 
2000     /** Returns {@code true} if the process prefers to use fifo scheduling. */
useFifoUiScheduling()2001     public boolean useFifoUiScheduling() {
2002         return mUseFifoUiScheduling;
2003     }
2004 
2005     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
onTopProcChanged()2006     public void onTopProcChanged() {
2007         if (mAtm.mVrController.isInterestingToSchedGroup()) {
2008             mAtm.mH.post(() -> {
2009                 synchronized (mAtm.mGlobalLock) {
2010                     mAtm.mVrController.onTopProcChangedLocked(this);
2011                 }
2012             });
2013         }
2014     }
2015 
2016     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
isHomeProcess()2017     public boolean isHomeProcess() {
2018         return this == mAtm.mHomeProcess;
2019     }
2020 
2021     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
isShowingUiWhileDozing()2022     public boolean isShowingUiWhileDozing() {
2023         return this == mAtm.mVisibleDozeUiProcess;
2024     }
2025 
2026     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
isPreviousProcess()2027     public boolean isPreviousProcess() {
2028         return this == mAtm.mPreviousProcess;
2029     }
2030 
2031     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
isHeavyWeightProcess()2032     public boolean isHeavyWeightProcess() {
2033         return this == mAtm.mHeavyWeightProcess;
2034     }
2035 
2036     @HotPath(caller = HotPath.PROCESS_CHANGE)
isFactoryTestProcess()2037     public boolean isFactoryTestProcess() {
2038         final int factoryTestMode = mAtm.mFactoryTest;
2039         if (factoryTestMode == FactoryTest.FACTORY_TEST_OFF) {
2040             return false;
2041         }
2042         if (factoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
2043             final ComponentName topComponent = mAtm.mTopComponent;
2044             if (topComponent != null && mName.equals(topComponent.getPackageName())) {
2045                 return true;
2046             }
2047         }
2048         return factoryTestMode == FactoryTest.FACTORY_TEST_HIGH_LEVEL
2049                 && (mInfo.flags & ApplicationInfo.FLAG_FACTORY_TEST) != 0;
2050     }
2051 
2052     /** Sets the current stopped state of the app, which is reset as soon as metrics are logged */
setStoppedState(@toppedState int stoppedState)2053     public void setStoppedState(@StoppedState int stoppedState) {
2054         mStoppedState = stoppedState;
2055     }
2056 
getWasStoppedLogged()2057     boolean getWasStoppedLogged() {
2058         return mWasStoppedLogged;
2059     }
2060 
setWasStoppedLogged(boolean logged)2061     void setWasStoppedLogged(boolean logged) {
2062         mWasStoppedLogged = logged;
2063     }
2064 
2065     /** Returns whether the app had been force-stopped before this launch */
wasForceStopped()2066     public boolean wasForceStopped() {
2067         return mStoppedState == STOPPED_STATE_FORCE_STOPPED;
2068     }
2069 
2070     /** Returns whether this app is being launched for the first time since install */
wasFirstLaunch()2071     boolean wasFirstLaunch() {
2072         return mStoppedState == STOPPED_STATE_FIRST_LAUNCH;
2073     }
2074 
setRunningRemoteAnimation(boolean running)2075     void setRunningRemoteAnimation(boolean running) {
2076         if (running) {
2077             addAnimatingReason(ANIMATING_REASON_REMOTE_ANIMATION);
2078         } else {
2079             removeAnimatingReason(ANIMATING_REASON_REMOTE_ANIMATION);
2080         }
2081     }
2082 
addAnimatingReason(@nimatingReason int reason)2083     void addAnimatingReason(@AnimatingReason int reason) {
2084         final int prevReasons = mAnimatingReasons;
2085         mAnimatingReasons |= reason;
2086         if (prevReasons == 0) {
2087             setAnimating(true);
2088         }
2089     }
2090 
removeAnimatingReason(@nimatingReason int reason)2091     void removeAnimatingReason(@AnimatingReason int reason) {
2092         final int prevReasons = mAnimatingReasons;
2093         mAnimatingReasons &= ~reason;
2094         if (prevReasons != 0 && mAnimatingReasons == 0) {
2095             setAnimating(false);
2096         }
2097     }
2098 
2099     /** Applies the animating state to activity manager for updating process priority. */
setAnimating(boolean animating)2100     private void setAnimating(boolean animating) {
2101         // Posting on handler so WM lock isn't held when we call into AM.
2102         mAtm.mH.post(() -> mListener.setRunningRemoteAnimation(animating));
2103     }
2104 
isRunningRemoteTransition()2105     boolean isRunningRemoteTransition() {
2106         return (mAnimatingReasons & ANIMATING_REASON_REMOTE_ANIMATION) != 0;
2107     }
2108 
2109     /** Adjusts scheduling group for animation. This method MUST NOT be called inside WM lock. */
setRunningAnimationUnsafe()2110     void setRunningAnimationUnsafe() {
2111         mListener.setRunningRemoteAnimation(true);
2112     }
2113 
2114     @Override
toString()2115     public String toString() {
2116         return mOwner != null ? mOwner.toString() : null;
2117     }
2118 
dump(PrintWriter pw, String prefix)2119     public void dump(PrintWriter pw, String prefix) {
2120         synchronized (mAtm.mGlobalLock) {
2121             if (mActivities.size() > 0) {
2122                 pw.print(prefix); pw.println("Activities:");
2123                 for (int i = 0; i < mActivities.size(); i++) {
2124                     pw.print(prefix); pw.print("  - "); pw.println(mActivities.get(i));
2125                 }
2126             }
2127             if (mRemoteActivities != null && !mRemoteActivities.isEmpty()) {
2128                 pw.print(prefix); pw.println("Remote Activities:");
2129                 for (int i = mRemoteActivities.size() - 1; i >= 0; i--) {
2130                     pw.print(prefix); pw.print("  - ");
2131                     pw.print(mRemoteActivities.keyAt(i)); pw.print(" flags=");
2132                     final int flags = mRemoteActivities.valueAt(i)[0];
2133                     if ((flags & REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY) != 0) {
2134                         pw.print("host ");
2135                     }
2136                     if ((flags & REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY) != 0) {
2137                         pw.print("embedded");
2138                     }
2139                     pw.println();
2140                 }
2141             }
2142             if (mRecentTasks.size() > 0) {
2143                 pw.println(prefix + "Recent Tasks:");
2144                 for (int i = 0; i < mRecentTasks.size(); i++) {
2145                     pw.println(prefix + "  - " + mRecentTasks.get(i));
2146                 }
2147             }
2148 
2149             if (mVrThreadTid != 0) {
2150                 pw.print(prefix); pw.print("mVrThreadTid="); pw.println(mVrThreadTid);
2151             }
2152 
2153             mBgLaunchController.dump(pw, prefix);
2154         }
2155         pw.println(prefix + " Configuration=" + getConfiguration());
2156         pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration());
2157         pw.println(prefix + " mLastReportedConfiguration=" + (mHasCachedConfiguration
2158                 ? ("(cached) " + mLastReportedConfiguration) : mLastReportedConfiguration));
2159 
2160         final int animatingReasons = mAnimatingReasons;
2161         if (animatingReasons != 0) {
2162             pw.print(prefix + " mAnimatingReasons=");
2163             if ((animatingReasons & ANIMATING_REASON_REMOTE_ANIMATION) != 0) {
2164                 pw.print("remote-animation|");
2165             }
2166             if ((animatingReasons & ANIMATING_REASON_WAKEFULNESS_CHANGE) != 0) {
2167                 pw.print("wakefulness|");
2168             }
2169             pw.println();
2170         }
2171         if (mUseFifoUiScheduling) {
2172             pw.println(prefix + " mUseFifoUiScheduling=true");
2173         }
2174 
2175         final int stateFlags = mActivityStateFlags;
2176         if (stateFlags != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
2177             pw.print(prefix + " mActivityStateFlags=");
2178             if ((stateFlags & ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE) != 0) {
2179                 pw.print("W|");
2180             }
2181             if ((stateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) {
2182                 pw.print("V|");
2183                 if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0) {
2184                     pw.print("R|");
2185                     if ((stateFlags & ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN) != 0) {
2186                         pw.print("RS|");
2187                     }
2188                     if ((stateFlags & ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0) {
2189                         pw.print("PF|");
2190                     }
2191                 }
2192             } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) {
2193                 pw.print("P|");
2194             } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) {
2195                 pw.print("S|");
2196                 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0) {
2197                     pw.print("F|");
2198                 }
2199             }
2200             if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0) {
2201                 pw.print("VT|");
2202             }
2203             final int taskLayer = stateFlags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
2204             if (taskLayer != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
2205                 pw.print("taskLayer=" + taskLayer);
2206             }
2207             pw.println();
2208         }
2209     }
2210 
dumpDebug(ProtoOutputStream proto, long fieldId)2211     void dumpDebug(ProtoOutputStream proto, long fieldId) {
2212         mListener.dumpDebug(proto, fieldId);
2213     }
2214 
2215     @Override
setOverrideGender(Configuration requestsTmpConfig, int gender)2216     protected boolean setOverrideGender(Configuration requestsTmpConfig, int gender) {
2217         return applyConfigGenderOverride(requestsTmpConfig, gender,
2218                 mAtm.mGrammaticalManagerInternal, mUid);
2219     }
2220 
applyConfigGenderOverride(@onNull Configuration overrideConfig, @Configuration.GrammaticalGender int override, GrammaticalInflectionManagerInternal service, int uid)2221     static boolean applyConfigGenderOverride(@NonNull Configuration overrideConfig,
2222             @Configuration.GrammaticalGender int override,
2223             GrammaticalInflectionManagerInternal service, int uid) {
2224         final boolean canGetSystemValue = service != null
2225                 && service.canGetSystemGrammaticalGender(uid);
2226 
2227         // The priority here is as follows:
2228         // - app-specific override if set
2229         // - system value if allowed to see it
2230         // - global configuration otherwise
2231         final int targetValue = (override != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED)
2232                 ? override
2233                 : canGetSystemValue
2234                         ? Configuration.GRAMMATICAL_GENDER_UNDEFINED
2235                         : service != null
2236                                 ? service.getGrammaticalGenderFromDeveloperSettings()
2237                                 : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
2238         if (overrideConfig.getGrammaticalGenderRaw() == targetValue) {
2239             return false;
2240         }
2241         overrideConfig.setGrammaticalGender(targetValue);
2242         return true;
2243     }
2244 }
2245