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