1 /*
2  * Copyright (C) 2020 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.devicestate;
18 
19 import static android.Manifest.permission.CONTROL_DEVICE_STATE;
20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
21 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
22 import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS;
23 import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP;
24 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
25 import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
26 import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
27 
28 import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_BASE_STATE;
29 import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_EMULATED_STATE;
30 import static com.android.server.devicestate.OverrideRequestController.FLAG_POWER_SAVE_ENABLED;
31 import static com.android.server.devicestate.OverrideRequestController.FLAG_THERMAL_CRITICAL;
32 import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
33 import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
34 import static com.android.server.devicestate.OverrideRequestController.STATUS_UNKNOWN;
35 
36 import android.annotation.IntDef;
37 import android.annotation.IntRange;
38 import android.annotation.NonNull;
39 import android.annotation.Nullable;
40 import android.app.ActivityManager;
41 import android.app.ActivityManagerInternal;
42 import android.app.IProcessObserver;
43 import android.content.Context;
44 import android.hardware.devicestate.DeviceState;
45 import android.hardware.devicestate.DeviceStateInfo;
46 import android.hardware.devicestate.DeviceStateManager;
47 import android.hardware.devicestate.DeviceStateManagerInternal;
48 import android.hardware.devicestate.IDeviceStateManager;
49 import android.hardware.devicestate.IDeviceStateManagerCallback;
50 import android.os.Binder;
51 import android.os.Handler;
52 import android.os.IBinder;
53 import android.os.RemoteException;
54 import android.os.ResultReceiver;
55 import android.os.ShellCallback;
56 import android.os.SystemProperties;
57 import android.os.Trace;
58 import android.util.Slog;
59 import android.util.SparseArray;
60 
61 import com.android.internal.R;
62 import com.android.internal.annotations.GuardedBy;
63 import com.android.internal.annotations.VisibleForTesting;
64 import com.android.internal.util.DumpUtils;
65 import com.android.internal.util.FrameworkStatsLog;
66 import com.android.server.DisplayThread;
67 import com.android.server.LocalServices;
68 import com.android.server.SystemService;
69 import com.android.server.statusbar.StatusBarManagerInternal;
70 import com.android.server.wm.ActivityTaskManagerInternal;
71 import com.android.server.wm.WindowProcessController;
72 
73 import java.io.FileDescriptor;
74 import java.io.PrintWriter;
75 import java.lang.annotation.Retention;
76 import java.lang.annotation.RetentionPolicy;
77 import java.util.ArrayList;
78 import java.util.Arrays;
79 import java.util.HashSet;
80 import java.util.List;
81 import java.util.Optional;
82 import java.util.Set;
83 import java.util.WeakHashMap;
84 
85 /**
86  * A system service that manages the state of a device with user-configurable hardware like a
87  * foldable phone.
88  * <p>
89  * Device state is an abstract concept that allows mapping the current state of the device to the
90  * state of the system. For example, system services (like
91  * {@link com.android.server.display.DisplayManagerService display manager} and
92  * {@link com.android.server.wm.WindowManagerService window manager}) and system UI may have
93  * different behaviors depending on the physical state of the device. This is useful for
94  * variable-state devices, like foldable or rollable devices, that can be configured by users into
95  * differing hardware states, which each may have a different expected use case.
96  * </p>
97  * <p>
98  * The {@link DeviceStateManagerService} is responsible for receiving state change requests from
99  * the {@link DeviceStateProvider} to modify the current device state and communicating with the
100  * {@link DeviceStatePolicy policy} to ensure the system is configured to match the requested state.
101  * </p>
102  * The service also provides the {@link DeviceStateManager} API allowing clients to listen for
103  * changes in device state and submit requests to override the device state provided by the
104  * {@link DeviceStateProvider}.
105  *
106  * @see DeviceStatePolicy
107  * @see DeviceStateManager
108  */
109 public final class DeviceStateManagerService extends SystemService {
110     private static final String TAG = "DeviceStateManagerService";
111     private static final boolean DEBUG = false;
112 
113     /** {@link DeviceState} to model an invalid device state */
114     // TODO(b/328314031): Investigate how we can remove this constant
115     private static final DeviceState INVALID_DEVICE_STATE = new DeviceState(
116             new DeviceState.Configuration.Builder(INVALID_DEVICE_STATE_IDENTIFIER,
117                     "INVALID").build());
118 
119     private final Object mLock = new Object();
120     // Handler on the {@link DisplayThread} used to dispatch calls to the policy and to registered
121     // callbacks though its handler (mHandler). Provides a guarantee of callback order when
122     // leveraging mHandler and also enables posting messages with the service lock held.
123     private final Handler mHandler;
124     @NonNull
125     private final DeviceStatePolicy mDeviceStatePolicy;
126     @NonNull
127     private final BinderService mBinderService;
128     @NonNull
129     private final OverrideRequestController mOverrideRequestController;
130     @NonNull
131     private final DeviceStateProviderListener mDeviceStateProviderListener;
132     @VisibleForTesting
133     @NonNull
134     public ActivityTaskManagerInternal mActivityTaskManagerInternal;
135 
136     // All supported device states keyed by identifier.
137     @GuardedBy("mLock")
138     private SparseArray<DeviceState> mDeviceStates = new SparseArray<>();
139 
140     // The current committed device state. Will be empty until the first device state provided by
141     // the DeviceStateProvider is committed.
142     @GuardedBy("mLock")
143     @NonNull
144     private Optional<DeviceState> mCommittedState = Optional.empty();
145     // The device state that is currently awaiting callback from the policy to be committed.
146     @GuardedBy("mLock")
147     @NonNull
148     private Optional<DeviceState> mPendingState = Optional.empty();
149     // Whether or not the policy is currently waiting to be notified of the current pending state.
150     @GuardedBy("mLock")
151     private boolean mIsPolicyWaitingForState = false;
152 
153     // The device state that is set by the DeviceStateProvider. Will be empty until the first
154     // callback from the provider and then will always contain the most recent value.
155     @GuardedBy("mLock")
156     @NonNull
157     private Optional<DeviceState> mBaseState = Optional.empty();
158 
159     // The current active override request. When set the device state specified here will take
160     // precedence over mBaseState.
161     @GuardedBy("mLock")
162     @NonNull
163     private Optional<OverrideRequest> mActiveOverride = Optional.empty();
164 
165     // The current active base state override request. When set the device state specified here will
166     // replace the value in mBaseState.
167     @GuardedBy("mLock")
168     @NonNull
169     private Optional<OverrideRequest> mActiveBaseStateOverride = Optional.empty();
170 
171     // List of processes registered to receive notifications about changes to device state and
172     // request status indexed by process id.
173     @GuardedBy("mLock")
174     private final SparseArray<ProcessRecord> mProcessRecords = new SparseArray<>();
175 
176     private Set<Integer> mDeviceStatesAvailableForAppRequests = new HashSet<>();
177 
178     private Set<Integer> mFoldedDeviceStates;
179 
180     @Nullable
181     private DeviceState mRearDisplayState;
182 
183     // TODO(259328837) Generalize for all pending feature requests in the future
184     @GuardedBy("mLock")
185     @Nullable
186     private OverrideRequest mRearDisplayPendingOverrideRequest;
187 
188     @VisibleForTesting
189     interface SystemPropertySetter {
setDebugTracingDeviceStateProperty(String value)190         void setDebugTracingDeviceStateProperty(String value);
191     }
192     @NonNull
193     private final SystemPropertySetter mSystemPropertySetter;
194 
195     @VisibleForTesting
196     final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
197         @Override
198         public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
199             synchronized (mLock) {
200                 if (!shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
201                     return;
202                 }
203 
204                 OverrideRequest request = mActiveOverride.get();
205                 if (pid != request.getPid() || uid != request.getUid()) {
206                     return;
207                 }
208                 if (!fg) {
209                     mOverrideRequestController.cancelRequest(request);
210                 }
211             }
212         }
213 
214         @Override
215         public void onProcessStarted(int pid, int processUid, int packageUid, String packageName,
216                 String processName) {}
217 
218         @Override
219         public void onProcessDied(int pid, int uid) {}
220 
221         @Override
222         public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {}
223     };
224     @VisibleForTesting
225     ActivityTaskManagerInternal.ScreenObserver mOverrideRequestScreenObserver =
226             new OverrideRequestScreenObserver();
227 
228     @NonNull
229     private final DeviceStateNotificationController mDeviceStateNotificationController;
230 
DeviceStateManagerService(@onNull Context context)231     public DeviceStateManagerService(@NonNull Context context) {
232         this(context, DeviceStatePolicy.Provider
233                 .fromResources(context.getResources())
234                 .instantiate(context));
235     }
236 
DeviceStateManagerService(@onNull Context context, @NonNull DeviceStatePolicy policy)237     private DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) {
238         this(context, policy, (value) -> {
239             SystemProperties.set("debug.tracing.device_state", value);
240         });
241     }
242 
243     @VisibleForTesting
DeviceStateManagerService(@onNull Context context, @NonNull DeviceStatePolicy policy, @NonNull SystemPropertySetter systemPropertySetter)244     DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy,
245             @NonNull SystemPropertySetter systemPropertySetter) {
246         super(context);
247         mSystemPropertySetter = systemPropertySetter;
248         // We use the DisplayThread because this service indirectly drives
249         // display (on/off) and window (position) events through its callbacks.
250         DisplayThread displayThread = DisplayThread.get();
251         mHandler = new Handler(displayThread.getLooper());
252         mOverrideRequestController = new OverrideRequestController(
253                 this::onOverrideRequestStatusChangedLocked);
254         mDeviceStatePolicy = policy;
255         mDeviceStateProviderListener = new DeviceStateProviderListener();
256         mDeviceStatePolicy.getDeviceStateProvider().setListener(mDeviceStateProviderListener);
257         mBinderService = new BinderService();
258         mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
259         mDeviceStateNotificationController = new DeviceStateNotificationController(
260                 context, mHandler,
261                 () -> {
262                     synchronized (mLock) {
263                         mActiveOverride.ifPresent(mOverrideRequestController::cancelRequest);
264                     }
265                 });
266     }
267 
268     @Override
onStart()269     public void onStart() {
270         publishBinderService(Context.DEVICE_STATE_SERVICE, mBinderService);
271         publishLocalService(DeviceStateManagerInternal.class, new LocalService());
272 
273         synchronized (mLock) {
274             readStatesAvailableForRequestFromApps();
275             mFoldedDeviceStates = readFoldedStates();
276         }
277 
278         mActivityTaskManagerInternal.registerScreenObserver(mOverrideRequestScreenObserver);
279         LocalServices.getService(ActivityManagerInternal.class).registerProcessObserver(
280                 mProcessObserver);
281     }
282 
283     @VisibleForTesting
getHandler()284     Handler getHandler() {
285         return mHandler;
286     }
287 
288     /**
289      * Returns the current state the system is in. Note that the system may be in the process of
290      * configuring a different state.
291      * <p>
292      * Note: This method will return {@link Optional#empty()} if called before the first state has
293      * been committed, otherwise it will return the last committed state.
294      *
295      * @see #getPendingState()
296      */
297     @NonNull
getCommittedState()298     Optional<DeviceState> getCommittedState() {
299         synchronized (mLock) {
300             return mCommittedState;
301         }
302     }
303 
304     /**
305      * Returns the state the system is currently configuring, or {@link Optional#empty()} if the
306      * system is not in the process of configuring a state.
307      */
308     @VisibleForTesting
309     @NonNull
getPendingState()310     Optional<DeviceState> getPendingState() {
311         synchronized (mLock) {
312             return mPendingState;
313         }
314     }
315 
316     /**
317      * Returns the base state. The service will configure the device to match the base state when
318      * there is no active request to override the base state.
319      * <p>
320      * Note: This method will return {@link Optional#empty()} if called before a base state is
321      * provided to the service by the {@link DeviceStateProvider}, otherwise it will return the
322      * most recent provided value.
323      *
324      * @see #getOverrideState()
325      */
326     @NonNull
getBaseState()327     Optional<DeviceState> getBaseState() {
328         synchronized (mLock) {
329             return mBaseState;
330         }
331     }
332 
333     /**
334      * Returns the current override state, or {@link Optional#empty()} if no override state is
335      * requested. If an override states is present, the returned state will take precedence over
336      * the base state returned from {@link #getBaseState()}.
337      */
338     @NonNull
getOverrideState()339     Optional<DeviceState> getOverrideState() {
340         synchronized (mLock) {
341             if (mActiveOverride.isPresent()) {
342                 return getStateLocked(mActiveOverride.get().getRequestedStateIdentifier());
343             }
344             return Optional.empty();
345         }
346     }
347 
348     /**
349      * Returns the current override base state, or {@link Optional#empty()} if no override state is
350      * requested. If an override base state is present, the returned state will be the same as
351      * the base state returned from {@link #getBaseState()}.
352      */
353     @NonNull
getOverrideBaseState()354     Optional<DeviceState> getOverrideBaseState() {
355         synchronized (mLock) {
356             if (mActiveBaseStateOverride.isPresent()) {
357                 return getStateLocked(mActiveBaseStateOverride.get().getRequestedStateIdentifier());
358             }
359             return Optional.empty();
360         }
361     }
362 
363     /** Returns the list of currently supported device states. */
getSupportedStates()364     List<DeviceState> getSupportedStates() {
365         synchronized (mLock) {
366             return getSupportedStatesLocked();
367         }
368     }
369 
370     /** Returns the list of currently supported device states */
371     @GuardedBy("mLock")
getSupportedStatesLocked()372     private List<DeviceState> getSupportedStatesLocked() {
373         List<DeviceState> supportedStates = new ArrayList<>(mDeviceStates.size());
374         for (int i = 0; i < mDeviceStates.size(); i++) {
375             supportedStates.add(i, mDeviceStates.valueAt(i));
376         }
377         return supportedStates;
378     }
379 
380     /** Returns the list of currently supported device state identifiers. */
getSupportedStateIdentifiersLocked()381     private int[] getSupportedStateIdentifiersLocked() {
382         int[] supportedStates = new int[mDeviceStates.size()];
383         for (int i = 0; i < supportedStates.length; i++) {
384             supportedStates[i] = mDeviceStates.valueAt(i).getIdentifier();
385         }
386         return supportedStates;
387     }
388 
389     /**
390      * Returns the current {@link DeviceStateInfo} of the device. If there has been no base state
391      * or committed state provided, {@link #INVALID_DEVICE_STATE} will be returned
392      * respectively. The supported states will always be included.
393      *
394      */
395     @GuardedBy("mLock")
396     @NonNull
getDeviceStateInfoLocked()397     private DeviceStateInfo getDeviceStateInfoLocked() {
398         final List<DeviceState> supportedStates = getSupportedStatesLocked();
399         final DeviceState baseState = mBaseState.orElse(INVALID_DEVICE_STATE);
400         final DeviceState currentState = mCommittedState.orElse(INVALID_DEVICE_STATE);
401 
402         return new DeviceStateInfo(new ArrayList<>(supportedStates), baseState,
403                 createMergedDeviceState(currentState, baseState));
404     }
405 
406     /**
407      * Returns a {@link DeviceState} with the combined properties of the current system state, as
408      * well as the physical property that corresponds to the base state (physical hardware state) of
409      * the device.
410      */
createMergedDeviceState(@ullable DeviceState committedState, @Nullable DeviceState baseState)411     private DeviceState createMergedDeviceState(@Nullable DeviceState committedState,
412             @Nullable DeviceState baseState) {
413         if (committedState.equals(INVALID_DEVICE_STATE)) {
414             return INVALID_DEVICE_STATE;
415         }
416 
417         Set<@DeviceState.DeviceStateProperties Integer> systemProperties =
418                 committedState.getConfiguration().getSystemProperties();
419 
420         Set<@DeviceState.DeviceStateProperties Integer> physicalProperties =
421                 baseState.getConfiguration().getPhysicalProperties();
422 
423         DeviceState.Configuration deviceStateConfiguration = new DeviceState.Configuration.Builder(
424                 committedState.getIdentifier(), committedState.getName())
425                 .setSystemProperties(systemProperties)
426                 .setPhysicalProperties(physicalProperties)
427                 .build();
428         return new DeviceState(deviceStateConfiguration);
429     }
430 
431     @VisibleForTesting
getBinderService()432     IDeviceStateManager getBinderService() {
433         return mBinderService;
434     }
435 
updateSupportedStates(DeviceState[] supportedDeviceStates, @DeviceStateProvider.SupportedStatesUpdatedReason int reason)436     private void updateSupportedStates(DeviceState[] supportedDeviceStates,
437             @DeviceStateProvider.SupportedStatesUpdatedReason int reason) {
438         synchronized (mLock) {
439             final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked();
440 
441             // Whether or not at least one device state has the flag FLAG_CANCEL_OVERRIDE_REQUESTS
442             // set. If set to true, the OverrideRequestController will be configured to allow sticky
443             // requests.
444             boolean hasTerminalDeviceState = false;
445             mDeviceStates.clear();
446             for (int i = 0; i < supportedDeviceStates.length; i++) {
447                 DeviceState state = supportedDeviceStates[i];
448                 if (state.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS)) {
449                     hasTerminalDeviceState = true;
450                 }
451                 mDeviceStates.put(state.getIdentifier(), state);
452             }
453 
454             mOverrideRequestController.setStickyRequestsAllowed(hasTerminalDeviceState);
455 
456             final int[] newStateIdentifiers = getSupportedStateIdentifiersLocked();
457             if (Arrays.equals(oldStateIdentifiers, newStateIdentifiers)) {
458                 return;
459             }
460 
461             mOverrideRequestController.handleNewSupportedStates(newStateIdentifiers, reason);
462             updatePendingStateLocked();
463 
464             setRearDisplayStateLocked();
465 
466             notifyDeviceStateInfoChangedAsync();
467 
468             mHandler.post(this::notifyPolicyIfNeeded);
469         }
470     }
471 
472     @GuardedBy("mLock")
setRearDisplayStateLocked()473     private void setRearDisplayStateLocked() {
474         int rearDisplayIdentifier = getContext().getResources().getInteger(
475                 R.integer.config_deviceStateRearDisplay);
476         if (rearDisplayIdentifier != INVALID_DEVICE_STATE_IDENTIFIER) {
477             mRearDisplayState = mDeviceStates.get(rearDisplayIdentifier);
478         }
479     }
480 
481     /**
482      * Returns {@code true} if the provided state is supported. Requires that
483      * {@link #mDeviceStates} is sorted prior to calling.
484      */
isSupportedStateLocked(int identifier)485     private boolean isSupportedStateLocked(int identifier) {
486         return mDeviceStates.contains(identifier);
487     }
488 
489     /**
490      * Returns the {@link DeviceState} with the supplied {@code identifier}, or {@code null} if
491      * there is no device state with the identifier.
492      */
493     @NonNull
getStateLocked(int identifier)494     private Optional<DeviceState> getStateLocked(int identifier) {
495         return Optional.ofNullable(mDeviceStates.get(identifier));
496     }
497 
498     /**
499      * Sets the base state.
500      *
501      * @throws IllegalArgumentException if the {@code identifier} is not a supported state.
502      *
503      * @see #isSupportedStateLocked(int)
504      */
setBaseState(int identifier)505     private void setBaseState(int identifier) {
506         synchronized (mLock) {
507             final Optional<DeviceState> baseStateOptional = getStateLocked(identifier);
508             if (baseStateOptional.isEmpty()) {
509                 throw new IllegalArgumentException("Base state is not supported");
510             }
511 
512             final DeviceState baseState = baseStateOptional.get();
513 
514             if (mBaseState.isPresent() && mBaseState.get().equals(baseState)) {
515                 // Base state hasn't changed. Nothing to do.
516                 return;
517             }
518             // There is a pending rear display request, so we check if the overlay should be closed
519             if (mRearDisplayPendingOverrideRequest != null) {
520                 handleRearDisplayBaseStateChangedLocked(identifier);
521             }
522             mBaseState = Optional.of(baseState);
523 
524             if (baseState.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS)) {
525                 mOverrideRequestController.cancelOverrideRequest();
526             }
527             mOverrideRequestController.handleBaseStateChanged(identifier);
528             updatePendingStateLocked();
529 
530             notifyDeviceStateInfoChangedAsync();
531 
532             mHandler.post(this::notifyPolicyIfNeeded);
533         }
534     }
535 
536     /**
537      * Tries to update the current pending state with the current requested state. Must call
538      * {@link #notifyPolicyIfNeeded()} to actually notify the policy that the state is being
539      * changed.
540      *
541      * @return {@code true} if the pending state has changed as a result of this call, {@code false}
542      * otherwise.
543      */
544     @GuardedBy("mLock")
updatePendingStateLocked()545     private boolean updatePendingStateLocked() {
546         if (mPendingState.isPresent()) {
547             // Have pending state, can not configure a new state until the state is committed.
548             return false;
549         }
550 
551         final DeviceState stateToConfigure;
552         if (mActiveOverride.isPresent()) {
553             stateToConfigure = getStateLocked(
554                     mActiveOverride.get().getRequestedStateIdentifier()).get();
555         } else if (mBaseState.isPresent()
556                 && isSupportedStateLocked(mBaseState.get().getIdentifier())) {
557             // Base state could have recently become unsupported after a change in supported states.
558             stateToConfigure = mBaseState.get();
559         } else {
560             stateToConfigure = null;
561         }
562 
563         if (stateToConfigure == null) {
564             // No currently requested state.
565             return false;
566         }
567 
568         if (mCommittedState.isPresent() && stateToConfigure.equals(mCommittedState.get())) {
569             // The state requesting to be committed already matches the current committed state.
570             return false;
571         }
572 
573         mPendingState = Optional.of(stateToConfigure);
574         mIsPolicyWaitingForState = true;
575         return true;
576     }
577 
578     /**
579      * Notifies the policy to configure the supplied state. Should not be called with {@link #mLock}
580      * held.
581      */
notifyPolicyIfNeeded()582     private void notifyPolicyIfNeeded() {
583         if (Thread.holdsLock(mLock)) {
584             Throwable error = new Throwable("Attempting to notify DeviceStatePolicy with service"
585                     + " lock held");
586             error.fillInStackTrace();
587             Slog.w(TAG, error);
588         }
589         int state;
590         synchronized (mLock) {
591             if (!mIsPolicyWaitingForState) {
592                 return;
593             }
594             mIsPolicyWaitingForState = false;
595             state = mPendingState.get().getIdentifier();
596         }
597 
598         if (DEBUG) {
599             Slog.d(TAG, "Notifying policy to configure state: " + state);
600         }
601         mDeviceStatePolicy.configureDeviceForState(state, this::commitPendingState);
602     }
603 
604     /**
605      * Commits the current pending state after a callback from the {@link DeviceStatePolicy}.
606      *
607      * <pre>
608      *              -------------    -----------              -------------
609      * Provider ->  | Requested | -> | Pending | -> Policy -> | Committed |
610      *              -------------    -----------              -------------
611      * </pre>
612      * <p>
613      * When a new state is requested it immediately enters the requested state. Once the policy is
614      * available to accept a new state, which could also be immediately if there is no current
615      * pending state at the point of request, the policy is notified and a callback is provided to
616      * trigger the state to be committed.
617      * </p>
618      */
commitPendingState()619     private void commitPendingState() {
620         synchronized (mLock) {
621             final DeviceState newState = mPendingState.get();
622             if (DEBUG) {
623                 Slog.d(TAG, "Committing state: " + newState);
624             }
625 
626             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_STATE_CHANGED,
627                     newState.getIdentifier(), !mCommittedState.isPresent());
628             String traceString = newState.getIdentifier() + ":" + newState.getName();
629             Trace.instantForTrack(
630                     Trace.TRACE_TAG_SYSTEM_SERVER, "DeviceStateChanged", traceString);
631             mSystemPropertySetter.setDebugTracingDeviceStateProperty(traceString);
632 
633             mCommittedState = Optional.of(newState);
634             mPendingState = Optional.empty();
635             updatePendingStateLocked();
636 
637             // Notify callbacks of a change.
638             notifyDeviceStateInfoChangedAsync();
639 
640             // The top request could have come in while the service was awaiting callback
641             // from the policy. In that case we only set it to active if it matches the
642             // current committed state, otherwise it will be set to active when its
643             // requested state is committed.
644             OverrideRequest activeRequest = mActiveOverride.orElse(null);
645             if (activeRequest != null
646                     && activeRequest.getRequestedStateIdentifier() == newState.getIdentifier()) {
647                 ProcessRecord processRecord = mProcessRecords.get(activeRequest.getPid());
648                 if (processRecord != null) {
649                     processRecord.notifyRequestActiveAsync(activeRequest.getToken());
650                 }
651             }
652 
653             // Try to configure the next state if needed.
654             mHandler.post(this::notifyPolicyIfNeeded);
655         }
656     }
657 
notifyDeviceStateInfoChangedAsync()658     private void notifyDeviceStateInfoChangedAsync() {
659         synchronized (mLock) {
660             if (mPendingState.isPresent()) {
661                 Slog.i(TAG,
662                         "Cannot notify device state info change when pending state is present.");
663                 return;
664             }
665 
666             if (!mBaseState.isPresent() || !mCommittedState.isPresent()) {
667                 Slog.e(TAG, "Cannot notify device state info change before the initial state has"
668                         + " been committed.");
669                 return;
670             }
671 
672             if (mProcessRecords.size() == 0) {
673                 return;
674             }
675 
676             ArrayList<ProcessRecord> registeredProcesses = new ArrayList<>();
677             for (int i = 0; i < mProcessRecords.size(); i++) {
678                 registeredProcesses.add(mProcessRecords.valueAt(i));
679             }
680 
681             DeviceStateInfo info = getDeviceStateInfoLocked();
682 
683             for (int i = 0; i < registeredProcesses.size(); i++) {
684                 registeredProcesses.get(i).notifyDeviceStateInfoAsync(info);
685             }
686         }
687     }
688 
689     @GuardedBy("mLock")
onOverrideRequestStatusChangedLocked(@onNull OverrideRequest request, @OverrideRequestController.RequestStatus int status, @OverrideRequestController.StatusChangedFlag int flags)690     private void onOverrideRequestStatusChangedLocked(@NonNull OverrideRequest request,
691             @OverrideRequestController.RequestStatus int status,
692             @OverrideRequestController.StatusChangedFlag int flags) {
693         if (request.getRequestType() == OVERRIDE_REQUEST_TYPE_BASE_STATE) {
694             switch (status) {
695                 case STATUS_ACTIVE:
696                     enableBaseStateRequestLocked(request);
697                     return;
698                 case STATUS_CANCELED:
699                     if (mActiveBaseStateOverride.isPresent()
700                             && mActiveBaseStateOverride.get() == request) {
701                         mActiveBaseStateOverride = Optional.empty();
702                     }
703                     break;
704                 case STATUS_UNKNOWN: // same as default
705                 default:
706                     throw new IllegalArgumentException("Unknown request status: " + status);
707             }
708         } else if (request.getRequestType() == OVERRIDE_REQUEST_TYPE_EMULATED_STATE) {
709             switch (status) {
710                 case STATUS_ACTIVE:
711                     mActiveOverride = Optional.of(request);
712                     mDeviceStateNotificationController.showStateActiveNotificationIfNeeded(
713                             request.getRequestedStateIdentifier(), request.getUid());
714                     break;
715                 case STATUS_CANCELED:
716                     if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
717                         mActiveOverride = Optional.empty();
718                         mDeviceStateNotificationController.cancelNotification(
719                                 request.getRequestedStateIdentifier());
720                         if ((flags & FLAG_THERMAL_CRITICAL) == FLAG_THERMAL_CRITICAL) {
721                             mDeviceStateNotificationController
722                                     .showThermalCriticalNotificationIfNeeded(
723                                             request.getRequestedStateIdentifier());
724                         } else if ((flags & FLAG_POWER_SAVE_ENABLED) == FLAG_POWER_SAVE_ENABLED) {
725                             mDeviceStateNotificationController
726                                     .showPowerSaveNotificationIfNeeded(
727                                             request.getRequestedStateIdentifier());
728                         }
729                     }
730                     break;
731                 case STATUS_UNKNOWN: // same as default
732                 default:
733                     throw new IllegalArgumentException("Unknown request status: " + status);
734             }
735         } else {
736             throw new IllegalArgumentException(
737                     "Unknown OverrideRest type: " + request.getRequestType());
738         }
739 
740         boolean updatedPendingState = updatePendingStateLocked();
741 
742         ProcessRecord processRecord = mProcessRecords.get(request.getPid());
743         if (processRecord == null) {
744             // If the process is no longer registered with the service, for example if it has died,
745             // there is no need to notify it of a change in request status.
746             mHandler.post(this::notifyPolicyIfNeeded);
747             return;
748         }
749 
750         if (status == STATUS_ACTIVE) {
751             if (!updatedPendingState && !mPendingState.isPresent()) {
752                 // If the pending state was not updated and there is not currently a pending state
753                 // then this newly active request will never be notified of a change in state.
754                 // Schedule the notification now.
755                 processRecord.notifyRequestActiveAsync(request.getToken());
756             }
757         } else {
758             processRecord.notifyRequestCanceledAsync(request.getToken());
759         }
760 
761         mHandler.post(this::notifyPolicyIfNeeded);
762     }
763 
764     /**
765      * Sets the new base state of the device and notifies the process that made the base state
766      * override request that the request is now active.
767      */
768     @GuardedBy("mLock")
enableBaseStateRequestLocked(OverrideRequest request)769     private void enableBaseStateRequestLocked(OverrideRequest request) {
770         setBaseState(request.getRequestedStateIdentifier());
771         mActiveBaseStateOverride = Optional.of(request);
772         ProcessRecord processRecord = mProcessRecords.get(request.getPid());
773         processRecord.notifyRequestActiveAsync(request.getToken());
774     }
775 
registerProcess(int pid, IDeviceStateManagerCallback callback)776     private void registerProcess(int pid, IDeviceStateManagerCallback callback) {
777         synchronized (mLock) {
778             if (mProcessRecords.contains(pid)) {
779                 throw new SecurityException("The calling process has already registered an"
780                         + " IDeviceStateManagerCallback.");
781             }
782 
783             ProcessRecord record = new ProcessRecord(callback, pid, this::handleProcessDied,
784                     mHandler);
785             try {
786                 callback.asBinder().linkToDeath(record, 0);
787             } catch (RemoteException ex) {
788                 throw new RuntimeException(ex);
789             }
790             mProcessRecords.put(pid, record);
791 
792             // Callback clients should not be notified of invalid device states, so calls to
793             // #getDeviceStateInfoLocked should be gated on checks if a committed state is present
794             // before getting the device state info.
795             DeviceStateInfo currentInfo = mCommittedState.isPresent()
796                     ? getDeviceStateInfoLocked() : null;
797             if (currentInfo != null) {
798                 // If there is not a committed state we'll wait to notify the process of the initial
799                 // value.
800                 record.notifyDeviceStateInfoAsync(currentInfo);
801             }
802         }
803     }
804 
handleProcessDied(ProcessRecord processRecord)805     private void handleProcessDied(ProcessRecord processRecord) {
806         synchronized (mLock) {
807             mProcessRecords.remove(processRecord.mPid);
808             mOverrideRequestController.handleProcessDied(processRecord.mPid);
809 
810             if (shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
811                 OverrideRequest request = mActiveOverride.get();
812                 mOverrideRequestController.cancelRequest(request);
813             }
814         }
815     }
816 
requestStateInternal(int state, int flags, int callingPid, int callingUid, @NonNull IBinder token, boolean hasControlDeviceStatePermission)817     private void requestStateInternal(int state, int flags, int callingPid, int callingUid,
818             @NonNull IBinder token, boolean hasControlDeviceStatePermission) {
819         synchronized (mLock) {
820             final ProcessRecord processRecord = mProcessRecords.get(callingPid);
821             if (processRecord == null) {
822                 throw new IllegalStateException("Process " + callingPid
823                         + " has no registered callback.");
824             }
825 
826             if (mOverrideRequestController.hasRequest(token,
827                     OVERRIDE_REQUEST_TYPE_EMULATED_STATE)) {
828                 throw new IllegalStateException("Request has already been made for the supplied"
829                         + " token: " + token);
830             }
831 
832             final Optional<DeviceState> deviceState = getStateLocked(state);
833             if (!deviceState.isPresent()) {
834                 throw new IllegalArgumentException("Requested state: " + state
835                         + " is not supported.");
836             }
837 
838             OverrideRequest request = new OverrideRequest(token, callingPid, callingUid,
839                     deviceState.get(), flags, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
840 
841             // If we don't have the CONTROL_DEVICE_STATE permission, we want to show the overlay
842             if (!hasControlDeviceStatePermission && mRearDisplayState != null
843                     && state == mRearDisplayState.getIdentifier()) {
844                 showRearDisplayEducationalOverlayLocked(request);
845             } else {
846                 mOverrideRequestController.addRequest(request);
847             }
848         }
849     }
850 
851     /**
852      * If we get a request to enter rear display  mode, we need to display an educational
853      * overlay to let the user know what will happen. This calls into the
854      * {@link StatusBarManagerInternal} to notify SystemUI to display the educational dialog.
855      */
856     @GuardedBy("mLock")
showRearDisplayEducationalOverlayLocked(@onNull OverrideRequest request)857     private void showRearDisplayEducationalOverlayLocked(@NonNull OverrideRequest request) {
858         mRearDisplayPendingOverrideRequest = request;
859 
860         StatusBarManagerInternal statusBar =
861                 LocalServices.getService(StatusBarManagerInternal.class);
862         if (statusBar != null) {
863             statusBar.showRearDisplayDialog(mBaseState.get().getIdentifier());
864         }
865     }
866 
cancelStateRequestInternal(int callingPid)867     private void cancelStateRequestInternal(int callingPid) {
868         synchronized (mLock) {
869             final ProcessRecord processRecord = mProcessRecords.get(callingPid);
870             if (processRecord == null) {
871                 throw new IllegalStateException("Process " + callingPid
872                         + " has no registered callback.");
873             }
874             mActiveOverride.ifPresent(mOverrideRequestController::cancelRequest);
875         }
876     }
877 
requestBaseStateOverrideInternal(int state, int flags, int callingPid, int callingUid, @NonNull IBinder token)878     private void requestBaseStateOverrideInternal(int state, int flags, int callingPid,
879             int callingUid, @NonNull IBinder token) {
880         synchronized (mLock) {
881             final Optional<DeviceState> deviceState = getStateLocked(state);
882             if (!deviceState.isPresent()) {
883                 throw new IllegalArgumentException("Requested state: " + state
884                         + " is not supported.");
885             }
886 
887             final ProcessRecord processRecord = mProcessRecords.get(callingPid);
888             if (processRecord == null) {
889                 throw new IllegalStateException("Process " + callingPid
890                         + " has no registered callback.");
891             }
892 
893             if (mOverrideRequestController.hasRequest(token,
894                     OVERRIDE_REQUEST_TYPE_BASE_STATE)) {
895                 throw new IllegalStateException("Request has already been made for the supplied"
896                         + " token: " + token);
897             }
898 
899             OverrideRequest request = new OverrideRequest(token, callingPid, callingUid,
900                     deviceState.get(), flags, OVERRIDE_REQUEST_TYPE_BASE_STATE);
901             mOverrideRequestController.addBaseStateRequest(request);
902         }
903     }
904 
cancelBaseStateOverrideInternal(int callingPid)905     private void cancelBaseStateOverrideInternal(int callingPid) {
906         synchronized (mLock) {
907             final ProcessRecord processRecord = mProcessRecords.get(callingPid);
908             if (processRecord == null) {
909                 throw new IllegalStateException("Process " + callingPid
910                         + " has no registered callback.");
911             }
912             setBaseState(mDeviceStateProviderListener.mCurrentBaseState);
913         }
914     }
915 
916     /**
917      * Adds the rear display state request to the {@link OverrideRequestController} if the
918      * educational overlay was closed in a way that should enable the feature, and cancels the
919      * request if it was dismissed in a way that should cancel the feature.
920      */
onStateRequestOverlayDismissedInternal(boolean shouldCancelRequest)921     private void onStateRequestOverlayDismissedInternal(boolean shouldCancelRequest) {
922         synchronized (mLock) {
923             if (mRearDisplayPendingOverrideRequest != null) {
924                 if (shouldCancelRequest) {
925                     ProcessRecord processRecord = mProcessRecords.get(
926                             mRearDisplayPendingOverrideRequest.getPid());
927                     processRecord.notifyRequestCanceledAsync(
928                             mRearDisplayPendingOverrideRequest.getToken());
929                 } else {
930                     mOverrideRequestController.addRequest(mRearDisplayPendingOverrideRequest);
931                 }
932                 mRearDisplayPendingOverrideRequest = null;
933             }
934         }
935     }
936 
dumpInternal(PrintWriter pw)937     private void dumpInternal(PrintWriter pw) {
938         pw.println("DEVICE STATE MANAGER (dumpsys device_state)");
939 
940         synchronized (mLock) {
941             pw.println("  mCommittedState=" + mCommittedState);
942             pw.println("  mPendingState=" + mPendingState);
943             pw.println("  mBaseState=" + mBaseState);
944             pw.println("  mOverrideState=" + getOverrideState());
945 
946             final int processCount = mProcessRecords.size();
947             pw.println();
948             pw.println("Registered processes: size=" + processCount);
949             for (int i = 0; i < processCount; i++) {
950                 ProcessRecord processRecord = mProcessRecords.valueAt(i);
951                 pw.println("  " + i + ": mPid=" + processRecord.mPid);
952             }
953 
954             mOverrideRequestController.dumpInternal(pw);
955             pw.println();
956 
957             mDeviceStatePolicy.dump(pw, /* args= */ null);
958         }
959     }
960 
961     /**
962      * Allow top processes to request or cancel a device state change. If the calling process ID is
963      * not the top app, then check if this process holds the
964      * {@link android.Manifest.permission.CONTROL_DEVICE_STATE} permission. If the calling process
965      * is the top app, check to verify they are requesting a state we've deemed to be able to be
966      * available for an app process to request. States that can be requested are based around
967      * features that we've created that require specific device state overrides.
968      * @param callingPid Process ID that is requesting this state change
969      * @param state state that is being requested.
970      */
assertCanRequestDeviceState(int callingPid, int callingUid, int state)971     private void assertCanRequestDeviceState(int callingPid, int callingUid, int state) {
972         final boolean isTopApp = isTopApp(callingPid);
973         final boolean isForegroundApp = isForegroundApp(callingPid, callingUid);
974         final boolean isStateAvailableForAppRequests = isStateAvailableForAppRequests(state);
975 
976         final boolean canRequestState = isTopApp
977                 && isForegroundApp
978                 && isStateAvailableForAppRequests;
979 
980         if (!canRequestState) {
981             getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
982                     "Permission required to request device state, "
983                             + "or the call must come from the top app "
984                             + "and be a device state that is available for apps to request.");
985         }
986     }
987 
988     /**
989      * Checks if the process can control the device state. If the calling process ID is
990      * not the top app, then check if this process holds the CONTROL_DEVICE_STATE permission.
991      *
992      * @param callingPid Process ID that is requesting this state change
993      * @param callingUid UID that is requesting this state change
994      */
assertCanControlDeviceState(int callingPid, int callingUid)995     private void assertCanControlDeviceState(int callingPid, int callingUid) {
996         final boolean isTopApp = isTopApp(callingPid);
997         final boolean isForegroundApp = isForegroundApp(callingPid, callingUid);
998 
999         final boolean canControlState = isTopApp && isForegroundApp;
1000 
1001         if (!canControlState) {
1002             getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
1003                     "Permission required to request device state, "
1004                             + "or the call must come from the top app.");
1005         }
1006     }
1007 
1008     /**
1009      * Checks if the caller is in the foreground. Note that callers may be the top app as returned
1010      * from {@link #isTopApp(int)}, but not be in the foreground. For example, keyguard may be on
1011      * top of the top app.
1012      */
isForegroundApp(int callingPid, int callingUid)1013     private boolean isForegroundApp(int callingPid, int callingUid) {
1014         try {
1015             final List<ActivityManager.RunningAppProcessInfo> procs =
1016                     ActivityManager.getService().getRunningAppProcesses();
1017             for (int i = 0; i < procs.size(); i++) {
1018                 ActivityManager.RunningAppProcessInfo proc = procs.get(i);
1019                 if (proc.pid == callingPid && proc.uid == callingUid
1020                         && proc.importance <= IMPORTANCE_FOREGROUND) {
1021                     return true;
1022                 }
1023             }
1024         } catch (RemoteException e) {
1025             Slog.w(TAG, "am.getRunningAppProcesses() failed", e);
1026         }
1027         return false;
1028     }
1029 
isTopApp(int callingPid)1030     private boolean isTopApp(int callingPid) {
1031         final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
1032         return topApp != null && topApp.getPid() == callingPid;
1033     }
1034 
isStateAvailableForAppRequests(int state)1035     private boolean isStateAvailableForAppRequests(int state) {
1036         synchronized (mLock) {
1037             return mDeviceStatesAvailableForAppRequests.contains(state);
1038         }
1039     }
1040 
1041     /**
1042      * Adds device state values that are available to be requested by the top level app.
1043      */
1044     @GuardedBy("mLock")
readStatesAvailableForRequestFromApps()1045     private void readStatesAvailableForRequestFromApps() {
1046         String[] availableAppStatesConfigIdentifiers = getContext().getResources()
1047                 .getStringArray(R.array.config_deviceStatesAvailableForAppRequests);
1048         for (int i = 0; i < availableAppStatesConfigIdentifiers.length; i++) {
1049             String identifierToFetch = availableAppStatesConfigIdentifiers[i];
1050             int configValueIdentifier = getContext().getResources()
1051                     .getIdentifier(identifierToFetch, "integer", "android");
1052             int state = getContext().getResources().getInteger(configValueIdentifier);
1053             if (isValidState(state)) {
1054                 mDeviceStatesAvailableForAppRequests.add(state);
1055             } else {
1056                 Slog.e(TAG, "Invalid device state was found in the configuration file. State id: "
1057                         + state);
1058             }
1059         }
1060     }
1061 
readFoldedStates()1062     private Set<Integer> readFoldedStates() {
1063         Set<Integer> foldedStates = new HashSet<>();
1064         int[] mFoldedStatesArray = getContext().getResources().getIntArray(
1065                 com.android.internal.R.array.config_foldedDeviceStates);
1066         for (int i = 0; i < mFoldedStatesArray.length; i++) {
1067             foldedStates.add(mFoldedStatesArray[i]);
1068         }
1069         return foldedStates;
1070     }
1071 
1072     @GuardedBy("mLock")
isValidState(int state)1073     private boolean isValidState(int state) {
1074         for (int i = 0; i < mDeviceStates.size(); i++) {
1075             if (state == mDeviceStates.valueAt(i).getIdentifier()) {
1076                 return true;
1077             }
1078         }
1079         return false;
1080     }
1081 
1082     /**
1083      * If the device is being opened, in response to the rear display educational overlay, we should
1084      * dismiss the overlay and enter the mode.
1085      */
1086     @GuardedBy("mLock")
handleRearDisplayBaseStateChangedLocked(int newBaseState)1087     private void handleRearDisplayBaseStateChangedLocked(int newBaseState) {
1088         if (isDeviceOpeningLocked(newBaseState)) {
1089             onStateRequestOverlayDismissedInternal(false);
1090         }
1091     }
1092 
1093     /**
1094      * Determines if the device is being opened and if we are going from a folded state to a
1095      * non-folded state.
1096      */
1097     @GuardedBy("mLock")
isDeviceOpeningLocked(int newBaseState)1098     private boolean isDeviceOpeningLocked(int newBaseState) {
1099         return mBaseState.filter(
1100                 deviceState -> mFoldedDeviceStates.contains(deviceState.getIdentifier())
1101                         && !mFoldedDeviceStates.contains(newBaseState)).isPresent();
1102     }
1103 
1104     private final class DeviceStateProviderListener implements DeviceStateProvider.Listener {
1105         @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
1106         int mCurrentBaseState;
1107 
1108         @Override
onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates, @DeviceStateProvider.SupportedStatesUpdatedReason int reason)1109         public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates,
1110                 @DeviceStateProvider.SupportedStatesUpdatedReason int reason) {
1111             if (newDeviceStates.length == 0) {
1112                 throw new IllegalArgumentException("Supported device states must not be empty");
1113             }
1114             updateSupportedStates(newDeviceStates, reason);
1115         }
1116 
1117         @Override
onStateChanged( @ntRangefrom = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier)1118         public void onStateChanged(
1119                 @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
1120                         MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier) {
1121             if (identifier < MINIMUM_DEVICE_STATE_IDENTIFIER
1122                     || identifier > MAXIMUM_DEVICE_STATE_IDENTIFIER) {
1123                 throw new IllegalArgumentException("Invalid identifier: " + identifier);
1124             }
1125 
1126             mCurrentBaseState = identifier;
1127             setBaseState(identifier);
1128         }
1129     }
1130 
1131     private static final class ProcessRecord implements IBinder.DeathRecipient {
1132         public interface DeathListener {
onProcessDied(ProcessRecord record)1133             void onProcessDied(ProcessRecord record);
1134         }
1135 
1136         private static final int STATUS_ACTIVE = 0;
1137 
1138         private static final int STATUS_SUSPENDED = 1;
1139 
1140         private static final int STATUS_CANCELED = 2;
1141 
1142         @IntDef(prefix = {"STATUS_"}, value = {
1143                 STATUS_ACTIVE,
1144                 STATUS_SUSPENDED,
1145                 STATUS_CANCELED
1146         })
1147         @Retention(RetentionPolicy.SOURCE)
1148         private @interface RequestStatus {}
1149 
1150         private final IDeviceStateManagerCallback mCallback;
1151         private final int mPid;
1152         private final DeathListener mDeathListener;
1153         private final Handler mHandler;
1154 
1155         private final WeakHashMap<IBinder, Integer> mLastNotifiedStatus = new WeakHashMap<>();
1156 
ProcessRecord(IDeviceStateManagerCallback callback, int pid, DeathListener deathListener, Handler handler)1157         ProcessRecord(IDeviceStateManagerCallback callback, int pid, DeathListener deathListener,
1158                 Handler handler) {
1159             mCallback = callback;
1160             mPid = pid;
1161             mDeathListener = deathListener;
1162             mHandler = handler;
1163         }
1164 
1165         @Override
binderDied()1166         public void binderDied() {
1167             mDeathListener.onProcessDied(this);
1168         }
1169 
notifyDeviceStateInfoAsync(@onNull DeviceStateInfo info)1170         public void notifyDeviceStateInfoAsync(@NonNull DeviceStateInfo info) {
1171             mHandler.post(() -> {
1172                 boolean tracingEnabled = Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER);
1173                 if (tracingEnabled) { // To avoid creating the string when not needed.
1174                     Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER,
1175                             "notifyDeviceStateInfoAsync(pid=" + mPid + ")");
1176                 }
1177                 try {
1178                     mCallback.onDeviceStateInfoChanged(info);
1179                 } catch (RemoteException ex) {
1180                     Slog.w(TAG, "Failed to notify process " + mPid + " that device state changed.",
1181                             ex);
1182                 }
1183                 finally {
1184                     if (tracingEnabled) {
1185                         Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
1186                     }
1187                 }
1188             });
1189         }
1190 
notifyRequestActiveAsync(IBinder token)1191         public void notifyRequestActiveAsync(IBinder token) {
1192             @RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
1193             if (lastStatus != null
1194                     && (lastStatus == STATUS_ACTIVE || lastStatus == STATUS_CANCELED)) {
1195                 return;
1196             }
1197 
1198             mLastNotifiedStatus.put(token, STATUS_ACTIVE);
1199             mHandler.post(() -> {
1200                 try {
1201                     mCallback.onRequestActive(token);
1202                 } catch (RemoteException ex) {
1203                     Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
1204                             ex);
1205                 }
1206             });
1207         }
1208 
notifyRequestCanceledAsync(IBinder token)1209         public void notifyRequestCanceledAsync(IBinder token) {
1210             @RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
1211             if (lastStatus != null && lastStatus == STATUS_CANCELED) {
1212                 return;
1213             }
1214 
1215             mLastNotifiedStatus.put(token, STATUS_CANCELED);
1216             mHandler.post(() -> {
1217                 try {
1218                     mCallback.onRequestCanceled(token);
1219                 } catch (RemoteException ex) {
1220                     Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
1221                             ex);
1222                 }
1223             });
1224         }
1225     }
1226 
1227     /** Implementation of {@link IDeviceStateManager} published as a binder service. */
1228     private final class BinderService extends IDeviceStateManager.Stub {
1229 
1230         @Override // Binder call
getDeviceStateInfo()1231         public DeviceStateInfo getDeviceStateInfo() {
1232             synchronized (mLock) {
1233                 return getDeviceStateInfoLocked();
1234             }
1235         }
1236 
1237         @Override // Binder call
registerCallback(IDeviceStateManagerCallback callback)1238         public void registerCallback(IDeviceStateManagerCallback callback) {
1239             if (callback == null) {
1240                 throw new IllegalArgumentException("Device state callback must not be null.");
1241             }
1242 
1243             final int callingPid = Binder.getCallingPid();
1244             final long token = Binder.clearCallingIdentity();
1245             try {
1246                 registerProcess(callingPid, callback);
1247             } finally {
1248                 Binder.restoreCallingIdentity(token);
1249             }
1250         }
1251 
1252         @Override // Binder call
requestState(IBinder token, int state, int flags)1253         public void requestState(IBinder token, int state, int flags) {
1254             final int callingPid = Binder.getCallingPid();
1255             final int callingUid = Binder.getCallingUid();
1256             // Allow top processes to request a device state change
1257             // If the calling process ID is not the top app, then we check if this process
1258             // holds a permission to CONTROL_DEVICE_STATE
1259             assertCanRequestDeviceState(callingPid, callingUid, state);
1260 
1261             if (token == null) {
1262                 throw new IllegalArgumentException("Request token must not be null.");
1263             }
1264 
1265             boolean hasControlStatePermission = getContext().checkCallingOrSelfPermission(
1266                     CONTROL_DEVICE_STATE) == PERMISSION_GRANTED;
1267 
1268             final long callingIdentity = Binder.clearCallingIdentity();
1269             try {
1270                 requestStateInternal(state, flags, callingPid, callingUid, token,
1271                         hasControlStatePermission);
1272             } finally {
1273                 Binder.restoreCallingIdentity(callingIdentity);
1274             }
1275         }
1276 
1277         @Override // Binder call
cancelStateRequest()1278         public void cancelStateRequest() {
1279             final int callingPid = Binder.getCallingPid();
1280             final int callingUid = Binder.getCallingUid();
1281             // Allow top processes to cancel a device state change
1282             // If the calling process ID is not the top app, then we check if this process
1283             // holds a permission to CONTROL_DEVICE_STATE
1284             assertCanControlDeviceState(callingPid, callingUid);
1285 
1286             final long callingIdentity = Binder.clearCallingIdentity();
1287             try {
1288                 cancelStateRequestInternal(callingPid);
1289             } finally {
1290                 Binder.restoreCallingIdentity(callingIdentity);
1291             }
1292         }
1293 
1294         @Override // Binder call
requestBaseStateOverride(IBinder token, int state, int flags)1295         public void requestBaseStateOverride(IBinder token, int state, int flags) {
1296             final int callingPid = Binder.getCallingPid();
1297             final int callingUid = Binder.getCallingUid();
1298             getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
1299                     "Permission required to control base state of device.");
1300 
1301             if (token == null) {
1302                 throw new IllegalArgumentException("Request token must not be null.");
1303             }
1304 
1305             final long callingIdentity = Binder.clearCallingIdentity();
1306             try {
1307                 requestBaseStateOverrideInternal(state, flags, callingPid, callingUid, token);
1308             } finally {
1309                 Binder.restoreCallingIdentity(callingIdentity);
1310             }
1311         }
1312 
1313         @Override // Binder call
cancelBaseStateOverride()1314         public void cancelBaseStateOverride() {
1315             final int callingPid = Binder.getCallingPid();
1316             getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
1317                     "Permission required to control base state of device.");
1318 
1319             final long callingIdentity = Binder.clearCallingIdentity();
1320             try {
1321                 cancelBaseStateOverrideInternal(callingPid);
1322             } finally {
1323                 Binder.restoreCallingIdentity(callingIdentity);
1324             }
1325         }
1326 
1327         @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
1328         @Override // Binder call
onStateRequestOverlayDismissed(boolean shouldCancelRequest)1329         public void onStateRequestOverlayDismissed(boolean shouldCancelRequest) {
1330 
1331             onStateRequestOverlayDismissed_enforcePermission();
1332 
1333             final long callingIdentity = Binder.clearCallingIdentity();
1334             try {
1335                 onStateRequestOverlayDismissedInternal(shouldCancelRequest);
1336             } finally {
1337                 Binder.restoreCallingIdentity(callingIdentity);
1338             }
1339         }
1340 
1341         @Override // Binder call
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver result)1342         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
1343                 String[] args, ShellCallback callback, ResultReceiver result) {
1344             new DeviceStateManagerShellCommand(DeviceStateManagerService.this)
1345                     .exec(this, in, out, err, args, callback, result);
1346         }
1347 
1348         @Override // Binder call
dump(FileDescriptor fd, final PrintWriter pw, String[] args)1349         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1350             if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
1351 
1352             final long token = Binder.clearCallingIdentity();
1353             try {
1354                 dumpInternal(pw);
1355             } finally {
1356                 Binder.restoreCallingIdentity(token);
1357             }
1358         }
1359     }
1360 
1361     /** Implementation of {@link DeviceStateManagerInternal} published as a local service. */
1362     private final class LocalService extends DeviceStateManagerInternal {
1363         @Override
getSupportedStateIdentifiers()1364         public int[] getSupportedStateIdentifiers() {
1365             synchronized (mLock) {
1366                 return getSupportedStateIdentifiersLocked();
1367             }
1368         }
1369     }
1370 
1371     @GuardedBy("mLock")
shouldCancelOverrideRequestWhenRequesterNotOnTop()1372     private boolean shouldCancelOverrideRequestWhenRequesterNotOnTop() {
1373         if (mActiveOverride.isEmpty()) {
1374             return false;
1375         }
1376         int identifier = mActiveOverride.get().getRequestedStateIdentifier();
1377         DeviceState deviceState = mDeviceStates.get(identifier);
1378         return deviceState.hasProperty(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
1379     }
1380 
1381     private class OverrideRequestScreenObserver implements
1382             ActivityTaskManagerInternal.ScreenObserver {
1383 
1384         @Override
onAwakeStateChanged(boolean isAwake)1385         public void onAwakeStateChanged(boolean isAwake) {
1386             synchronized (mLock) {
1387                 if (!isAwake && shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
1388                     mOverrideRequestController.cancelRequest(mActiveOverride.get());
1389                 }
1390             }
1391         }
1392 
1393         @Override
onKeyguardStateChanged(boolean isShowing)1394         public void onKeyguardStateChanged(boolean isShowing) {
1395             synchronized (mLock) {
1396                 if (isShowing && shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
1397                     mOverrideRequestController.cancelRequest(mActiveOverride.get());
1398                 }
1399             }
1400         }
1401     }
1402 }
1403