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