1 /* 2 * Copyright (C) 2012 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.dreams; 18 19 import static android.Manifest.permission.BIND_DREAM_SERVICE; 20 21 import android.app.ActivityManager; 22 import android.content.BroadcastReceiver; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.pm.PackageManager; 28 import android.content.pm.PackageManager.NameNotFoundException; 29 import android.content.pm.ServiceInfo; 30 import android.database.ContentObserver; 31 import android.hardware.display.AmbientDisplayConfiguration; 32 import android.hardware.input.InputManagerInternal; 33 import android.os.Binder; 34 import android.os.Build; 35 import android.os.Handler; 36 import android.os.IBinder; 37 import android.os.Looper; 38 import android.os.PowerManager; 39 import android.os.PowerManagerInternal; 40 import android.os.SystemClock; 41 import android.os.SystemProperties; 42 import android.os.UserHandle; 43 import android.provider.Settings; 44 import android.service.dreams.DreamManagerInternal; 45 import android.service.dreams.DreamService; 46 import android.service.dreams.IDreamManager; 47 import android.util.Slog; 48 import android.view.Display; 49 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.logging.UiEvent; 52 import com.android.internal.logging.UiEventLogger; 53 import com.android.internal.logging.UiEventLoggerImpl; 54 import com.android.internal.util.DumpUtils; 55 import com.android.server.FgThread; 56 import com.android.server.LocalServices; 57 import com.android.server.SystemService; 58 import com.android.server.wm.ActivityTaskManagerInternal; 59 60 import java.io.FileDescriptor; 61 import java.io.PrintWriter; 62 import java.util.ArrayList; 63 import java.util.List; 64 import java.util.Objects; 65 66 /** 67 * Service api for managing dreams. 68 * 69 * @hide 70 */ 71 public final class DreamManagerService extends SystemService { 72 private static final boolean DEBUG = false; 73 private static final String TAG = "DreamManagerService"; 74 75 private final Object mLock = new Object(); 76 77 private final Context mContext; 78 private final DreamHandler mHandler; 79 private final DreamController mController; 80 private final PowerManager mPowerManager; 81 private final PowerManagerInternal mPowerManagerInternal; 82 private final PowerManager.WakeLock mDozeWakeLock; 83 private final ActivityTaskManagerInternal mAtmInternal; 84 private final UiEventLogger mUiEventLogger; 85 private final ComponentName mAmbientDisplayComponent; 86 87 private Binder mCurrentDreamToken; 88 private ComponentName mCurrentDreamName; 89 private int mCurrentDreamUserId; 90 private boolean mCurrentDreamIsTest; 91 private boolean mCurrentDreamCanDoze; 92 private boolean mCurrentDreamIsDozing; 93 private boolean mCurrentDreamIsWaking; 94 private boolean mForceAmbientDisplayEnabled; 95 private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN; 96 private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; 97 98 private AmbientDisplayConfiguration mDozeConfig; 99 100 @VisibleForTesting 101 public enum DreamManagerEvent implements UiEventLogger.UiEventEnum { 102 @UiEvent(doc = "The screensaver has started.") 103 DREAM_START(577), 104 105 @UiEvent(doc = "The screensaver has stopped.") 106 DREAM_STOP(578); 107 108 private final int mId; 109 DreamManagerEvent(int id)110 DreamManagerEvent(int id) { 111 mId = id; 112 } 113 114 @Override getId()115 public int getId() { 116 return mId; 117 } 118 } 119 DreamManagerService(Context context)120 public DreamManagerService(Context context) { 121 super(context); 122 mContext = context; 123 mHandler = new DreamHandler(FgThread.get().getLooper()); 124 mController = new DreamController(context, mHandler, mControllerListener); 125 126 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 127 mPowerManagerInternal = getLocalService(PowerManagerInternal.class); 128 mAtmInternal = getLocalService(ActivityTaskManagerInternal.class); 129 mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG); 130 mDozeConfig = new AmbientDisplayConfiguration(mContext); 131 mUiEventLogger = new UiEventLoggerImpl(); 132 AmbientDisplayConfiguration adc = new AmbientDisplayConfiguration(mContext); 133 mAmbientDisplayComponent = ComponentName.unflattenFromString(adc.ambientDisplayComponent()); 134 } 135 136 @Override onStart()137 public void onStart() { 138 publishBinderService(DreamService.DREAM_SERVICE, new BinderService()); 139 publishLocalService(DreamManagerInternal.class, new LocalService()); 140 } 141 142 @Override onBootPhase(int phase)143 public void onBootPhase(int phase) { 144 if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 145 if (Build.IS_DEBUGGABLE) { 146 SystemProperties.addChangeCallback(mSystemPropertiesChanged); 147 } 148 mContext.registerReceiver(new BroadcastReceiver() { 149 @Override 150 public void onReceive(Context context, Intent intent) { 151 writePulseGestureEnabled(); 152 synchronized (mLock) { 153 stopDreamLocked(false /*immediate*/, "user switched"); 154 } 155 } 156 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); 157 mContext.getContentResolver().registerContentObserver( 158 Settings.Secure.getUriFor(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE), false, 159 mDozeEnabledObserver, UserHandle.USER_ALL); 160 writePulseGestureEnabled(); 161 } 162 } 163 dumpInternal(PrintWriter pw)164 private void dumpInternal(PrintWriter pw) { 165 pw.println("DREAM MANAGER (dumpsys dreams)"); 166 pw.println(); 167 pw.println("mCurrentDreamToken=" + mCurrentDreamToken); 168 pw.println("mCurrentDreamName=" + mCurrentDreamName); 169 pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId); 170 pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest); 171 pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze); 172 pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing); 173 pw.println("mCurrentDreamIsWaking=" + mCurrentDreamIsWaking); 174 pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled); 175 pw.println("mCurrentDreamDozeScreenState=" 176 + Display.stateToString(mCurrentDreamDozeScreenState)); 177 pw.println("mCurrentDreamDozeScreenBrightness=" + mCurrentDreamDozeScreenBrightness); 178 pw.println("getDozeComponent()=" + getDozeComponent()); 179 pw.println(); 180 181 DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() { 182 @Override 183 public void dump(PrintWriter pw, String prefix) { 184 mController.dump(pw); 185 } 186 }, pw, "", 200); 187 } 188 isDreamingInternal()189 private boolean isDreamingInternal() { 190 synchronized (mLock) { 191 return mCurrentDreamToken != null && !mCurrentDreamIsTest 192 && !mCurrentDreamIsWaking; 193 } 194 } 195 requestDreamInternal()196 private void requestDreamInternal() { 197 // Ask the power manager to nap. It will eventually call back into 198 // startDream() if/when it is appropriate to start dreaming. 199 // Because napping could cause the screen to turn off immediately if the dream 200 // cannot be started, we keep one eye open and gently poke user activity. 201 long time = SystemClock.uptimeMillis(); 202 mPowerManager.userActivity(time, true /*noChangeLights*/); 203 mPowerManager.nap(time); 204 } 205 requestAwakenInternal()206 private void requestAwakenInternal() { 207 // Treat an explicit request to awaken as user activity so that the 208 // device doesn't immediately go to sleep if the timeout expired, 209 // for example when being undocked. 210 long time = SystemClock.uptimeMillis(); 211 mPowerManager.userActivity(time, false /*noChangeLights*/); 212 stopDreamInternal(false /*immediate*/, "request awaken"); 213 } 214 finishSelfInternal(IBinder token, boolean immediate)215 private void finishSelfInternal(IBinder token, boolean immediate) { 216 if (DEBUG) { 217 Slog.d(TAG, "Dream finished: " + token + ", immediate=" + immediate); 218 } 219 220 // Note that a dream finishing and self-terminating is not 221 // itself considered user activity. If the dream is ending because 222 // the user interacted with the device then user activity will already 223 // have been poked so the device will stay awake a bit longer. 224 // If the dream is ending on its own for other reasons and no wake 225 // locks are held and the user activity timeout has expired then the 226 // device may simply go to sleep. 227 synchronized (mLock) { 228 if (mCurrentDreamToken == token) { 229 stopDreamLocked(immediate, "finished self"); 230 } 231 } 232 } 233 testDreamInternal(ComponentName dream, int userId)234 private void testDreamInternal(ComponentName dream, int userId) { 235 synchronized (mLock) { 236 startDreamLocked(dream, true /*isTest*/, false /*canDoze*/, userId); 237 } 238 } 239 startDreamInternal(boolean doze)240 private void startDreamInternal(boolean doze) { 241 final int userId = ActivityManager.getCurrentUser(); 242 final ComponentName dream = chooseDreamForUser(doze, userId); 243 if (dream != null) { 244 synchronized (mLock) { 245 startDreamLocked(dream, false /*isTest*/, doze, userId); 246 } 247 } 248 } 249 stopDreamInternal(boolean immediate, String reason)250 private void stopDreamInternal(boolean immediate, String reason) { 251 synchronized (mLock) { 252 stopDreamLocked(immediate, reason); 253 } 254 } 255 startDozingInternal(IBinder token, int screenState, int screenBrightness)256 private void startDozingInternal(IBinder token, int screenState, 257 int screenBrightness) { 258 if (DEBUG) { 259 Slog.d(TAG, "Dream requested to start dozing: " + token 260 + ", screenState=" + screenState 261 + ", screenBrightness=" + screenBrightness); 262 } 263 264 synchronized (mLock) { 265 if (mCurrentDreamToken == token && mCurrentDreamCanDoze) { 266 mCurrentDreamDozeScreenState = screenState; 267 mCurrentDreamDozeScreenBrightness = screenBrightness; 268 mPowerManagerInternal.setDozeOverrideFromDreamManager( 269 screenState, screenBrightness); 270 if (!mCurrentDreamIsDozing) { 271 mCurrentDreamIsDozing = true; 272 mDozeWakeLock.acquire(); 273 } 274 } 275 } 276 } 277 stopDozingInternal(IBinder token)278 private void stopDozingInternal(IBinder token) { 279 if (DEBUG) { 280 Slog.d(TAG, "Dream requested to stop dozing: " + token); 281 } 282 283 synchronized (mLock) { 284 if (mCurrentDreamToken == token && mCurrentDreamIsDozing) { 285 mCurrentDreamIsDozing = false; 286 mDozeWakeLock.release(); 287 mPowerManagerInternal.setDozeOverrideFromDreamManager( 288 Display.STATE_UNKNOWN, PowerManager.BRIGHTNESS_DEFAULT); 289 } 290 } 291 } 292 forceAmbientDisplayEnabledInternal(boolean enabled)293 private void forceAmbientDisplayEnabledInternal(boolean enabled) { 294 if (DEBUG) { 295 Slog.d(TAG, "Force ambient display enabled: " + enabled); 296 } 297 298 synchronized (mLock) { 299 mForceAmbientDisplayEnabled = enabled; 300 } 301 } 302 getActiveDreamComponentInternal(boolean doze)303 private ComponentName getActiveDreamComponentInternal(boolean doze) { 304 return chooseDreamForUser(doze, ActivityManager.getCurrentUser()); 305 } 306 chooseDreamForUser(boolean doze, int userId)307 private ComponentName chooseDreamForUser(boolean doze, int userId) { 308 if (doze) { 309 ComponentName dozeComponent = getDozeComponent(userId); 310 return validateDream(dozeComponent) ? dozeComponent : null; 311 } 312 ComponentName[] dreams = getDreamComponentsForUser(userId); 313 return dreams != null && dreams.length != 0 ? dreams[0] : null; 314 } 315 validateDream(ComponentName component)316 private boolean validateDream(ComponentName component) { 317 if (component == null) return false; 318 final ServiceInfo serviceInfo = getServiceInfo(component); 319 if (serviceInfo == null) { 320 Slog.w(TAG, "Dream " + component + " does not exist"); 321 return false; 322 } else if (serviceInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP 323 && !BIND_DREAM_SERVICE.equals(serviceInfo.permission)) { 324 Slog.w(TAG, "Dream " + component 325 + " is not available because its manifest is missing the " + BIND_DREAM_SERVICE 326 + " permission on the dream service declaration."); 327 return false; 328 } 329 return true; 330 } 331 getDreamComponentsForUser(int userId)332 private ComponentName[] getDreamComponentsForUser(int userId) { 333 String names = Settings.Secure.getStringForUser(mContext.getContentResolver(), 334 Settings.Secure.SCREENSAVER_COMPONENTS, 335 userId); 336 ComponentName[] components = componentsFromString(names); 337 338 // first, ensure components point to valid services 339 List<ComponentName> validComponents = new ArrayList<ComponentName>(); 340 if (components != null) { 341 for (ComponentName component : components) { 342 if (validateDream(component)) { 343 validComponents.add(component); 344 } 345 } 346 } 347 348 // fallback to the default dream component if necessary 349 if (validComponents.isEmpty()) { 350 ComponentName defaultDream = getDefaultDreamComponentForUser(userId); 351 if (defaultDream != null) { 352 Slog.w(TAG, "Falling back to default dream " + defaultDream); 353 validComponents.add(defaultDream); 354 } 355 } 356 return validComponents.toArray(new ComponentName[validComponents.size()]); 357 } 358 setDreamComponentsForUser(int userId, ComponentName[] componentNames)359 private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) { 360 Settings.Secure.putStringForUser(mContext.getContentResolver(), 361 Settings.Secure.SCREENSAVER_COMPONENTS, 362 componentsToString(componentNames), 363 userId); 364 } 365 getDefaultDreamComponentForUser(int userId)366 private ComponentName getDefaultDreamComponentForUser(int userId) { 367 String name = Settings.Secure.getStringForUser(mContext.getContentResolver(), 368 Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, 369 userId); 370 return name == null ? null : ComponentName.unflattenFromString(name); 371 } 372 getDozeComponent()373 private ComponentName getDozeComponent() { 374 return getDozeComponent(ActivityManager.getCurrentUser()); 375 } 376 getDozeComponent(int userId)377 private ComponentName getDozeComponent(int userId) { 378 if (mForceAmbientDisplayEnabled || mDozeConfig.enabled(userId)) { 379 return ComponentName.unflattenFromString(mDozeConfig.ambientDisplayComponent()); 380 } else { 381 return null; 382 } 383 384 } 385 getServiceInfo(ComponentName name)386 private ServiceInfo getServiceInfo(ComponentName name) { 387 try { 388 return name != null ? mContext.getPackageManager().getServiceInfo(name, 389 PackageManager.MATCH_DEBUG_TRIAGED_MISSING) : null; 390 } catch (NameNotFoundException e) { 391 return null; 392 } 393 } 394 startDreamLocked(final ComponentName name, final boolean isTest, final boolean canDoze, final int userId)395 private void startDreamLocked(final ComponentName name, 396 final boolean isTest, final boolean canDoze, final int userId) { 397 if (!mCurrentDreamIsWaking 398 && Objects.equals(mCurrentDreamName, name) 399 && mCurrentDreamIsTest == isTest 400 && mCurrentDreamCanDoze == canDoze 401 && mCurrentDreamUserId == userId) { 402 Slog.i(TAG, "Already in target dream."); 403 return; 404 } 405 406 stopDreamLocked(true /*immediate*/, "starting new dream"); 407 408 Slog.i(TAG, "Entering dreamland."); 409 410 final Binder newToken = new Binder(); 411 mCurrentDreamToken = newToken; 412 mCurrentDreamName = name; 413 mCurrentDreamIsTest = isTest; 414 mCurrentDreamCanDoze = canDoze; 415 mCurrentDreamUserId = userId; 416 417 PowerManager.WakeLock wakeLock = mPowerManager 418 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream"); 419 mHandler.post(wakeLock.wrap(() -> { 420 mAtmInternal.notifyDreamStateChanged(true); 421 if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) { 422 mUiEventLogger.log(DreamManagerEvent.DREAM_START); 423 } 424 mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock); 425 })); 426 } 427 stopDreamLocked(final boolean immediate, String reason)428 private void stopDreamLocked(final boolean immediate, String reason) { 429 if (mCurrentDreamToken != null) { 430 if (immediate) { 431 Slog.i(TAG, "Leaving dreamland."); 432 cleanupDreamLocked(); 433 } else if (mCurrentDreamIsWaking) { 434 return; // already waking 435 } else { 436 Slog.i(TAG, "Gently waking up from dream."); 437 mCurrentDreamIsWaking = true; 438 } 439 440 mHandler.post(new Runnable() { 441 @Override 442 public void run() { 443 Slog.i(TAG, "Performing gentle wake from dream."); 444 mController.stopDream(immediate, reason); 445 } 446 }); 447 } 448 } 449 cleanupDreamLocked()450 private void cleanupDreamLocked() { 451 if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) { 452 mUiEventLogger.log(DreamManagerEvent.DREAM_STOP); 453 } 454 mCurrentDreamToken = null; 455 mCurrentDreamName = null; 456 mCurrentDreamIsTest = false; 457 mCurrentDreamCanDoze = false; 458 mCurrentDreamUserId = 0; 459 mCurrentDreamIsWaking = false; 460 if (mCurrentDreamIsDozing) { 461 mCurrentDreamIsDozing = false; 462 mDozeWakeLock.release(); 463 } 464 mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN; 465 mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; 466 mAtmInternal.notifyDreamStateChanged(false); 467 } 468 checkPermission(String permission)469 private void checkPermission(String permission) { 470 if (mContext.checkCallingOrSelfPermission(permission) 471 != PackageManager.PERMISSION_GRANTED) { 472 throw new SecurityException("Access denied to process: " + Binder.getCallingPid() 473 + ", must have permission " + permission); 474 } 475 } 476 writePulseGestureEnabled()477 private void writePulseGestureEnabled() { 478 ComponentName name = getDozeComponent(); 479 boolean dozeEnabled = validateDream(name); 480 LocalServices.getService(InputManagerInternal.class).setPulseGestureEnabled(dozeEnabled); 481 } 482 componentsToString(ComponentName[] componentNames)483 private static String componentsToString(ComponentName[] componentNames) { 484 StringBuilder names = new StringBuilder(); 485 if (componentNames != null) { 486 for (ComponentName componentName : componentNames) { 487 if (names.length() > 0) { 488 names.append(','); 489 } 490 names.append(componentName.flattenToString()); 491 } 492 } 493 return names.toString(); 494 } 495 componentsFromString(String names)496 private static ComponentName[] componentsFromString(String names) { 497 if (names == null) { 498 return null; 499 } 500 String[] namesArray = names.split(","); 501 ComponentName[] componentNames = new ComponentName[namesArray.length]; 502 for (int i = 0; i < namesArray.length; i++) { 503 componentNames[i] = ComponentName.unflattenFromString(namesArray[i]); 504 } 505 return componentNames; 506 } 507 508 private final DreamController.Listener mControllerListener = new DreamController.Listener() { 509 @Override 510 public void onDreamStopped(Binder token) { 511 synchronized (mLock) { 512 if (mCurrentDreamToken == token) { 513 cleanupDreamLocked(); 514 } 515 } 516 } 517 }; 518 519 private final ContentObserver mDozeEnabledObserver = new ContentObserver(null) { 520 @Override 521 public void onChange(boolean selfChange) { 522 writePulseGestureEnabled(); 523 } 524 }; 525 526 /** 527 * Handler for asynchronous operations performed by the dream manager. 528 * Ensures operations to {@link DreamController} are single-threaded. 529 */ 530 private final class DreamHandler extends Handler { DreamHandler(Looper looper)531 public DreamHandler(Looper looper) { 532 super(looper, null, true /*async*/); 533 } 534 } 535 536 private final class BinderService extends IDreamManager.Stub { 537 @Override // Binder call dump(FileDescriptor fd, PrintWriter pw, String[] args)538 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 539 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 540 final long ident = Binder.clearCallingIdentity(); 541 try { 542 dumpInternal(pw); 543 } finally { 544 Binder.restoreCallingIdentity(ident); 545 } 546 } 547 548 @Override // Binder call getDreamComponents()549 public ComponentName[] getDreamComponents() { 550 return getDreamComponentsForUser(UserHandle.getCallingUserId()); 551 } 552 553 @Override // Binder call getDreamComponentsForUser(int userId)554 public ComponentName[] getDreamComponentsForUser(int userId) { 555 checkPermission(android.Manifest.permission.READ_DREAM_STATE); 556 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 557 Binder.getCallingUid(), userId, false, true, "getDreamComponents", null); 558 559 final long ident = Binder.clearCallingIdentity(); 560 try { 561 return DreamManagerService.this.getDreamComponentsForUser(userId); 562 } finally { 563 Binder.restoreCallingIdentity(ident); 564 } 565 } 566 567 @Override // Binder call setDreamComponents(ComponentName[] componentNames)568 public void setDreamComponents(ComponentName[] componentNames) { 569 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); 570 571 final int userId = UserHandle.getCallingUserId(); 572 final long ident = Binder.clearCallingIdentity(); 573 try { 574 setDreamComponentsForUser(userId, componentNames); 575 } finally { 576 Binder.restoreCallingIdentity(ident); 577 } 578 } 579 580 @Override // Binder call setDreamComponentsForUser(int userId, ComponentName[] componentNames)581 public void setDreamComponentsForUser(int userId, ComponentName[] componentNames) { 582 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); 583 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 584 Binder.getCallingUid(), userId, false, true, "setDreamComponents", null); 585 586 final long ident = Binder.clearCallingIdentity(); 587 try { 588 DreamManagerService.this.setDreamComponentsForUser(userId, componentNames); 589 } finally { 590 Binder.restoreCallingIdentity(ident); 591 } 592 } 593 594 @Override // Binder call getDefaultDreamComponentForUser(int userId)595 public ComponentName getDefaultDreamComponentForUser(int userId) { 596 checkPermission(android.Manifest.permission.READ_DREAM_STATE); 597 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 598 Binder.getCallingUid(), userId, false, true, "getDefaultDreamComponent", null); 599 600 final long ident = Binder.clearCallingIdentity(); 601 try { 602 return DreamManagerService.this.getDefaultDreamComponentForUser(userId); 603 } finally { 604 Binder.restoreCallingIdentity(ident); 605 } 606 } 607 608 @Override // Binder call isDreaming()609 public boolean isDreaming() { 610 checkPermission(android.Manifest.permission.READ_DREAM_STATE); 611 612 final long ident = Binder.clearCallingIdentity(); 613 try { 614 return isDreamingInternal(); 615 } finally { 616 Binder.restoreCallingIdentity(ident); 617 } 618 } 619 620 @Override // Binder call dream()621 public void dream() { 622 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); 623 624 final long ident = Binder.clearCallingIdentity(); 625 try { 626 requestDreamInternal(); 627 } finally { 628 Binder.restoreCallingIdentity(ident); 629 } 630 } 631 632 @Override // Binder call testDream(int userId, ComponentName dream)633 public void testDream(int userId, ComponentName dream) { 634 if (dream == null) { 635 throw new IllegalArgumentException("dream must not be null"); 636 } 637 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); 638 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 639 Binder.getCallingUid(), userId, false, true, "testDream", null); 640 641 final int currentUserId = ActivityManager.getCurrentUser(); 642 if (userId != currentUserId) { 643 // This check is inherently prone to races but at least it's something. 644 Slog.w(TAG, "Aborted attempt to start a test dream while a different " 645 + " user is active: userId=" + userId 646 + ", currentUserId=" + currentUserId); 647 return; 648 } 649 final long ident = Binder.clearCallingIdentity(); 650 try { 651 testDreamInternal(dream, userId); 652 } finally { 653 Binder.restoreCallingIdentity(ident); 654 } 655 } 656 657 @Override // Binder call awaken()658 public void awaken() { 659 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); 660 661 final long ident = Binder.clearCallingIdentity(); 662 try { 663 requestAwakenInternal(); 664 } finally { 665 Binder.restoreCallingIdentity(ident); 666 } 667 } 668 669 @Override // Binder call finishSelf(IBinder token, boolean immediate)670 public void finishSelf(IBinder token, boolean immediate) { 671 // Requires no permission, called by Dream from an arbitrary process. 672 if (token == null) { 673 throw new IllegalArgumentException("token must not be null"); 674 } 675 676 final long ident = Binder.clearCallingIdentity(); 677 try { 678 finishSelfInternal(token, immediate); 679 } finally { 680 Binder.restoreCallingIdentity(ident); 681 } 682 } 683 684 @Override // Binder call startDozing(IBinder token, int screenState, int screenBrightness)685 public void startDozing(IBinder token, int screenState, int screenBrightness) { 686 // Requires no permission, called by Dream from an arbitrary process. 687 if (token == null) { 688 throw new IllegalArgumentException("token must not be null"); 689 } 690 691 final long ident = Binder.clearCallingIdentity(); 692 try { 693 startDozingInternal(token, screenState, screenBrightness); 694 } finally { 695 Binder.restoreCallingIdentity(ident); 696 } 697 } 698 699 @Override // Binder call stopDozing(IBinder token)700 public void stopDozing(IBinder token) { 701 // Requires no permission, called by Dream from an arbitrary process. 702 if (token == null) { 703 throw new IllegalArgumentException("token must not be null"); 704 } 705 706 final long ident = Binder.clearCallingIdentity(); 707 try { 708 stopDozingInternal(token); 709 } finally { 710 Binder.restoreCallingIdentity(ident); 711 } 712 } 713 714 @Override // Binder call forceAmbientDisplayEnabled(boolean enabled)715 public void forceAmbientDisplayEnabled(boolean enabled) { 716 checkPermission(android.Manifest.permission.DEVICE_POWER); 717 718 final long ident = Binder.clearCallingIdentity(); 719 try { 720 forceAmbientDisplayEnabledInternal(enabled); 721 } finally { 722 Binder.restoreCallingIdentity(ident); 723 } 724 } 725 } 726 727 private final class LocalService extends DreamManagerInternal { 728 @Override startDream(boolean doze)729 public void startDream(boolean doze) { 730 startDreamInternal(doze); 731 } 732 733 @Override stopDream(boolean immediate)734 public void stopDream(boolean immediate) { 735 stopDreamInternal(immediate, "requested stopDream"); 736 } 737 738 @Override isDreaming()739 public boolean isDreaming() { 740 return isDreamingInternal(); 741 } 742 743 @Override getActiveDreamComponent(boolean doze)744 public ComponentName getActiveDreamComponent(boolean doze) { 745 return getActiveDreamComponentInternal(doze); 746 } 747 } 748 749 private final Runnable mSystemPropertiesChanged = new Runnable() { 750 @Override 751 public void run() { 752 if (DEBUG) Slog.d(TAG, "System properties changed"); 753 synchronized (mLock) { 754 if (mCurrentDreamName != null && mCurrentDreamCanDoze 755 && !mCurrentDreamName.equals(getDozeComponent())) { 756 // May have updated the doze component, wake up 757 mPowerManager.wakeUp(SystemClock.uptimeMillis(), 758 "android.server.dreams:SYSPROP"); 759 } 760 } 761 } 762 }; 763 } 764