• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (Objects.equals(mCurrentDreamName, name)
398                 && mCurrentDreamIsTest == isTest
399                 && mCurrentDreamCanDoze == canDoze
400                 && mCurrentDreamUserId == userId) {
401             Slog.i(TAG, "Already in target dream.");
402             return;
403         }
404 
405         stopDreamLocked(true /*immediate*/, "starting new dream");
406 
407         Slog.i(TAG, "Entering dreamland.");
408 
409         final Binder newToken = new Binder();
410         mCurrentDreamToken = newToken;
411         mCurrentDreamName = name;
412         mCurrentDreamIsTest = isTest;
413         mCurrentDreamCanDoze = canDoze;
414         mCurrentDreamUserId = userId;
415 
416         PowerManager.WakeLock wakeLock = mPowerManager
417                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
418         mHandler.post(wakeLock.wrap(() -> {
419             mAtmInternal.notifyDreamStateChanged(true);
420             if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
421                 mUiEventLogger.log(DreamManagerEvent.DREAM_START);
422             }
423             mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock);
424         }));
425     }
426 
stopDreamLocked(final boolean immediate, String reason)427     private void stopDreamLocked(final boolean immediate, String reason) {
428         if (mCurrentDreamToken != null) {
429             if (immediate) {
430                 Slog.i(TAG, "Leaving dreamland.");
431                 cleanupDreamLocked();
432             } else if (mCurrentDreamIsWaking) {
433                 return; // already waking
434             } else {
435                 Slog.i(TAG, "Gently waking up from dream.");
436                 mCurrentDreamIsWaking = true;
437             }
438 
439             mHandler.post(new Runnable() {
440                 @Override
441                 public void run() {
442                     Slog.i(TAG, "Performing gentle wake from dream.");
443                     mController.stopDream(immediate, reason);
444                 }
445             });
446         }
447     }
448 
cleanupDreamLocked()449     private void cleanupDreamLocked() {
450         if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
451             mUiEventLogger.log(DreamManagerEvent.DREAM_STOP);
452         }
453         mCurrentDreamToken = null;
454         mCurrentDreamName = null;
455         mCurrentDreamIsTest = false;
456         mCurrentDreamCanDoze = false;
457         mCurrentDreamUserId = 0;
458         mCurrentDreamIsWaking = false;
459         if (mCurrentDreamIsDozing) {
460             mCurrentDreamIsDozing = false;
461             mDozeWakeLock.release();
462         }
463         mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
464         mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
465         mAtmInternal.notifyDreamStateChanged(false);
466     }
467 
checkPermission(String permission)468     private void checkPermission(String permission) {
469         if (mContext.checkCallingOrSelfPermission(permission)
470                 != PackageManager.PERMISSION_GRANTED) {
471             throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
472                     + ", must have permission " + permission);
473         }
474     }
475 
writePulseGestureEnabled()476     private void writePulseGestureEnabled() {
477         ComponentName name = getDozeComponent();
478         boolean dozeEnabled = validateDream(name);
479         LocalServices.getService(InputManagerInternal.class).setPulseGestureEnabled(dozeEnabled);
480     }
481 
componentsToString(ComponentName[] componentNames)482     private static String componentsToString(ComponentName[] componentNames) {
483         StringBuilder names = new StringBuilder();
484         if (componentNames != null) {
485             for (ComponentName componentName : componentNames) {
486                 if (names.length() > 0) {
487                     names.append(',');
488                 }
489                 names.append(componentName.flattenToString());
490             }
491         }
492         return names.toString();
493     }
494 
componentsFromString(String names)495     private static ComponentName[] componentsFromString(String names) {
496         if (names == null) {
497             return null;
498         }
499         String[] namesArray = names.split(",");
500         ComponentName[] componentNames = new ComponentName[namesArray.length];
501         for (int i = 0; i < namesArray.length; i++) {
502             componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
503         }
504         return componentNames;
505     }
506 
507     private final DreamController.Listener mControllerListener = new DreamController.Listener() {
508         @Override
509         public void onDreamStopped(Binder token) {
510             synchronized (mLock) {
511                 if (mCurrentDreamToken == token) {
512                     cleanupDreamLocked();
513                 }
514             }
515         }
516     };
517 
518     private final ContentObserver mDozeEnabledObserver = new ContentObserver(null) {
519         @Override
520         public void onChange(boolean selfChange) {
521             writePulseGestureEnabled();
522         }
523     };
524 
525     /**
526      * Handler for asynchronous operations performed by the dream manager.
527      * Ensures operations to {@link DreamController} are single-threaded.
528      */
529     private final class DreamHandler extends Handler {
DreamHandler(Looper looper)530         public DreamHandler(Looper looper) {
531             super(looper, null, true /*async*/);
532         }
533     }
534 
535     private final class BinderService extends IDreamManager.Stub {
536         @Override // Binder call
dump(FileDescriptor fd, PrintWriter pw, String[] args)537         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
538             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
539             final long ident = Binder.clearCallingIdentity();
540             try {
541                 dumpInternal(pw);
542             } finally {
543                 Binder.restoreCallingIdentity(ident);
544             }
545         }
546 
547         @Override // Binder call
getDreamComponents()548         public ComponentName[] getDreamComponents() {
549             return getDreamComponentsForUser(UserHandle.getCallingUserId());
550         }
551 
552         @Override // Binder call
getDreamComponentsForUser(int userId)553         public ComponentName[] getDreamComponentsForUser(int userId) {
554             checkPermission(android.Manifest.permission.READ_DREAM_STATE);
555             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
556                     Binder.getCallingUid(), userId, false, true, "getDreamComponents", null);
557 
558             final long ident = Binder.clearCallingIdentity();
559             try {
560                 return DreamManagerService.this.getDreamComponentsForUser(userId);
561             } finally {
562                 Binder.restoreCallingIdentity(ident);
563             }
564         }
565 
566         @Override // Binder call
setDreamComponents(ComponentName[] componentNames)567         public void setDreamComponents(ComponentName[] componentNames) {
568             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
569 
570             final int userId = UserHandle.getCallingUserId();
571             final long ident = Binder.clearCallingIdentity();
572             try {
573                 setDreamComponentsForUser(userId, componentNames);
574             } finally {
575                 Binder.restoreCallingIdentity(ident);
576             }
577         }
578 
579         @Override // Binder call
setDreamComponentsForUser(int userId, ComponentName[] componentNames)580         public void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
581             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
582             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
583                     Binder.getCallingUid(), userId, false, true, "setDreamComponents", null);
584 
585             final long ident = Binder.clearCallingIdentity();
586             try {
587                 DreamManagerService.this.setDreamComponentsForUser(userId, componentNames);
588             } finally {
589                 Binder.restoreCallingIdentity(ident);
590             }
591         }
592 
593         @Override // Binder call
getDefaultDreamComponentForUser(int userId)594         public ComponentName getDefaultDreamComponentForUser(int userId) {
595             checkPermission(android.Manifest.permission.READ_DREAM_STATE);
596             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
597                     Binder.getCallingUid(), userId, false, true, "getDefaultDreamComponent", null);
598 
599             final long ident = Binder.clearCallingIdentity();
600             try {
601                 return DreamManagerService.this.getDefaultDreamComponentForUser(userId);
602             } finally {
603                 Binder.restoreCallingIdentity(ident);
604             }
605         }
606 
607         @Override // Binder call
isDreaming()608         public boolean isDreaming() {
609             checkPermission(android.Manifest.permission.READ_DREAM_STATE);
610 
611             final long ident = Binder.clearCallingIdentity();
612             try {
613                 return isDreamingInternal();
614             } finally {
615                 Binder.restoreCallingIdentity(ident);
616             }
617         }
618 
619         @Override // Binder call
dream()620         public void dream() {
621             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
622 
623             final long ident = Binder.clearCallingIdentity();
624             try {
625                 requestDreamInternal();
626             } finally {
627                 Binder.restoreCallingIdentity(ident);
628             }
629         }
630 
631         @Override // Binder call
testDream(int userId, ComponentName dream)632         public void testDream(int userId, ComponentName dream) {
633             if (dream == null) {
634                 throw new IllegalArgumentException("dream must not be null");
635             }
636             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
637             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
638                     Binder.getCallingUid(), userId, false, true, "testDream", null);
639 
640             final int currentUserId = ActivityManager.getCurrentUser();
641             if (userId != currentUserId) {
642                 // This check is inherently prone to races but at least it's something.
643                 Slog.w(TAG, "Aborted attempt to start a test dream while a different "
644                         + " user is active: userId=" + userId
645                         + ", currentUserId=" + currentUserId);
646                 return;
647             }
648             final long ident = Binder.clearCallingIdentity();
649             try {
650                 testDreamInternal(dream, userId);
651             } finally {
652                 Binder.restoreCallingIdentity(ident);
653             }
654         }
655 
656         @Override // Binder call
awaken()657         public void awaken() {
658             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
659 
660             final long ident = Binder.clearCallingIdentity();
661             try {
662                 requestAwakenInternal();
663             } finally {
664                 Binder.restoreCallingIdentity(ident);
665             }
666         }
667 
668         @Override // Binder call
finishSelf(IBinder token, boolean immediate)669         public void finishSelf(IBinder token, boolean immediate) {
670             // Requires no permission, called by Dream from an arbitrary process.
671             if (token == null) {
672                 throw new IllegalArgumentException("token must not be null");
673             }
674 
675             final long ident = Binder.clearCallingIdentity();
676             try {
677                 finishSelfInternal(token, immediate);
678             } finally {
679                 Binder.restoreCallingIdentity(ident);
680             }
681         }
682 
683         @Override // Binder call
startDozing(IBinder token, int screenState, int screenBrightness)684         public void startDozing(IBinder token, int screenState, int screenBrightness) {
685             // Requires no permission, called by Dream from an arbitrary process.
686             if (token == null) {
687                 throw new IllegalArgumentException("token must not be null");
688             }
689 
690             final long ident = Binder.clearCallingIdentity();
691             try {
692                 startDozingInternal(token, screenState, screenBrightness);
693             } finally {
694                 Binder.restoreCallingIdentity(ident);
695             }
696         }
697 
698         @Override // Binder call
stopDozing(IBinder token)699         public void stopDozing(IBinder token) {
700             // Requires no permission, called by Dream from an arbitrary process.
701             if (token == null) {
702                 throw new IllegalArgumentException("token must not be null");
703             }
704 
705             final long ident = Binder.clearCallingIdentity();
706             try {
707                 stopDozingInternal(token);
708             } finally {
709                 Binder.restoreCallingIdentity(ident);
710             }
711         }
712 
713         @Override // Binder call
forceAmbientDisplayEnabled(boolean enabled)714         public void forceAmbientDisplayEnabled(boolean enabled) {
715             checkPermission(android.Manifest.permission.DEVICE_POWER);
716 
717             final long ident = Binder.clearCallingIdentity();
718             try {
719                 forceAmbientDisplayEnabledInternal(enabled);
720             } finally {
721                 Binder.restoreCallingIdentity(ident);
722             }
723         }
724     }
725 
726     private final class LocalService extends DreamManagerInternal {
727         @Override
startDream(boolean doze)728         public void startDream(boolean doze) {
729             startDreamInternal(doze);
730         }
731 
732         @Override
stopDream(boolean immediate)733         public void stopDream(boolean immediate) {
734             stopDreamInternal(immediate, "requested stopDream");
735         }
736 
737         @Override
isDreaming()738         public boolean isDreaming() {
739             return isDreamingInternal();
740         }
741 
742         @Override
getActiveDreamComponent(boolean doze)743         public ComponentName getActiveDreamComponent(boolean doze) {
744             return getActiveDreamComponentInternal(doze);
745         }
746     }
747 
748     private final Runnable mSystemPropertiesChanged = new Runnable() {
749         @Override
750         public void run() {
751             if (DEBUG) Slog.d(TAG, "System properties changed");
752             synchronized (mLock) {
753                 if (mCurrentDreamName != null && mCurrentDreamCanDoze
754                         && !mCurrentDreamName.equals(getDozeComponent())) {
755                     // May have updated the doze component, wake up
756                     mPowerManager.wakeUp(SystemClock.uptimeMillis(),
757                             "android.server.dreams:SYSPROP");
758                 }
759             }
760         }
761     };
762 }
763