• Home
  • 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 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
23 
24 import static com.android.server.wm.ActivityInterceptorCallback.DREAM_MANAGER_ORDERED_ID;
25 
26 import android.annotation.IntDef;
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.app.ActivityManager;
30 import android.app.IAppTask;
31 import android.app.TaskInfo;
32 import android.content.BroadcastReceiver;
33 import android.content.ComponentName;
34 import android.content.ContentResolver;
35 import android.content.Context;
36 import android.content.Intent;
37 import android.content.IntentFilter;
38 import android.content.pm.ActivityInfo;
39 import android.content.pm.PackageManager;
40 import android.content.pm.PackageManager.NameNotFoundException;
41 import android.content.pm.PackageManagerInternal;
42 import android.content.pm.ServiceInfo;
43 import android.database.ContentObserver;
44 import android.hardware.display.AmbientDisplayConfiguration;
45 import android.net.Uri;
46 import android.os.BatteryManager;
47 import android.os.Binder;
48 import android.os.Build;
49 import android.os.Handler;
50 import android.os.IBinder;
51 import android.os.Looper;
52 import android.os.PowerManager;
53 import android.os.PowerManagerInternal;
54 import android.os.RemoteException;
55 import android.os.ResultReceiver;
56 import android.os.ShellCallback;
57 import android.os.SystemClock;
58 import android.os.SystemProperties;
59 import android.os.UserHandle;
60 import android.os.UserManager;
61 import android.provider.Settings;
62 import android.service.dreams.DreamManagerInternal;
63 import android.service.dreams.DreamService;
64 import android.service.dreams.IDreamManager;
65 import android.util.Slog;
66 import android.view.Display;
67 
68 import com.android.internal.R;
69 import com.android.internal.annotations.GuardedBy;
70 import com.android.internal.logging.UiEventLogger;
71 import com.android.internal.logging.UiEventLoggerImpl;
72 import com.android.internal.util.DumpUtils;
73 import com.android.server.FgThread;
74 import com.android.server.LocalServices;
75 import com.android.server.SystemService;
76 import com.android.server.input.InputManagerInternal;
77 import com.android.server.pm.UserManagerInternal;
78 import com.android.server.wm.ActivityInterceptorCallback;
79 import com.android.server.wm.ActivityTaskManagerInternal;
80 
81 import java.io.FileDescriptor;
82 import java.io.PrintWriter;
83 import java.lang.annotation.Retention;
84 import java.lang.annotation.RetentionPolicy;
85 import java.util.ArrayList;
86 import java.util.List;
87 import java.util.Objects;
88 import java.util.concurrent.CopyOnWriteArrayList;
89 import java.util.function.Consumer;
90 
91 /**
92  * Service api for managing dreams.
93  *
94  * @hide
95  */
96 public final class DreamManagerService extends SystemService {
97     private static final boolean DEBUG = false;
98     private static final String TAG = "DreamManagerService";
99 
100     private static final String DOZE_WAKE_LOCK_TAG = "dream:doze";
101     private static final String DREAM_WAKE_LOCK_TAG = "dream:dream";
102 
103     /** Constants for the when to activate dreams. */
104     @Retention(RetentionPolicy.SOURCE)
105     @IntDef({DREAM_ON_DOCK, DREAM_ON_CHARGE, DREAM_ON_DOCK_OR_CHARGE})
106     public @interface WhenToDream {}
107     private static final int DREAM_DISABLED = 0x0;
108     private static final int DREAM_ON_DOCK = 0x1;
109     private static final int DREAM_ON_CHARGE = 0x2;
110     private static final int DREAM_ON_DOCK_OR_CHARGE = 0x3;
111 
112     private final Object mLock = new Object();
113 
114     private final Context mContext;
115     private final DreamHandler mHandler;
116     private final DreamController mController;
117     private final PowerManager mPowerManager;
118     private final PowerManagerInternal mPowerManagerInternal;
119     private final PowerManager.WakeLock mDozeWakeLock;
120     private final ActivityTaskManagerInternal mAtmInternal;
121     private final PackageManagerInternal mPmInternal;
122     private final UserManager mUserManager;
123     private final UiEventLogger mUiEventLogger;
124     private final DreamUiEventLogger mDreamUiEventLogger;
125     private final ComponentName mAmbientDisplayComponent;
126     private final boolean mDismissDreamOnActivityStart;
127     private final boolean mDreamsOnlyEnabledForDockUser;
128     private final boolean mDreamsEnabledByDefaultConfig;
129     private final boolean mDreamsActivatedOnChargeByDefault;
130     private final boolean mDreamsActivatedOnDockByDefault;
131     private final boolean mKeepDreamingWhenUnpluggingDefault;
132     private final boolean mDreamsDisabledByAmbientModeSuppressionConfig;
133 
134     private final CopyOnWriteArrayList<DreamManagerInternal.DreamManagerStateListener>
135             mDreamManagerStateListeners = new CopyOnWriteArrayList<>();
136 
137     @GuardedBy("mLock")
138     private DreamRecord mCurrentDream;
139 
140     private boolean mForceAmbientDisplayEnabled;
141     private SettingsObserver mSettingsObserver;
142     private boolean mDreamsEnabledSetting;
143     @WhenToDream private int mWhenToDream;
144     private boolean mIsDocked;
145     private boolean mIsCharging;
146 
147     // A temporary dream component that, when present, takes precedence over user configured dream
148     // component.
149     private ComponentName mSystemDreamComponent;
150 
151     private ComponentName mDreamOverlayServiceName;
152 
153     private final AmbientDisplayConfiguration mDozeConfig;
154     private final ActivityInterceptorCallback mActivityInterceptorCallback =
155             new ActivityInterceptorCallback() {
156                 @Nullable
157                 @Override
158                 public ActivityInterceptResult onInterceptActivityLaunch(@NonNull
159                         ActivityInterceptorInfo info) {
160                     return null;
161                 }
162 
163                 @Override
164                 public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo,
165                         ActivityInterceptorInfo info) {
166                     final int activityType = taskInfo.getActivityType();
167                     final boolean activityAllowed = activityType == ACTIVITY_TYPE_HOME
168                             || activityType == ACTIVITY_TYPE_DREAM
169                             || activityType == ACTIVITY_TYPE_ASSISTANT;
170 
171                     boolean shouldRequestAwaken;
172                     synchronized (mLock) {
173                         shouldRequestAwaken = mCurrentDream != null && !mCurrentDream.isWaking
174                                 && !mCurrentDream.isDozing && !activityAllowed;
175                     }
176 
177                     if (shouldRequestAwaken) {
178                         requestAwakenInternal(
179                                 "stopping dream due to activity start: " + activityInfo.name);
180                     }
181                 }
182             };
183 
184     private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() {
185         @Override
186         public void onReceive(Context context, Intent intent) {
187             mIsCharging = (BatteryManager.ACTION_CHARGING.equals(intent.getAction()));
188         }
189     };
190 
191     private final BroadcastReceiver mDockStateReceiver = new BroadcastReceiver() {
192         @Override
193         public void onReceive(Context context, Intent intent) {
194             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
195                 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
196                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
197                 mIsDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
198             }
199         }
200     };
201 
202     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)203         SettingsObserver(Handler handler) {
204             super(handler);
205         }
206 
207         @Override
onChange(boolean selfChange, Uri uri)208         public void onChange(boolean selfChange, Uri uri) {
209             updateWhenToDreamSettings();
210         }
211     }
212 
DreamManagerService(Context context)213     public DreamManagerService(Context context) {
214         super(context);
215         mContext = context;
216         mHandler = new DreamHandler(FgThread.get().getLooper());
217         mController = new DreamController(context, mHandler, mControllerListener);
218 
219         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
220         mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
221         mAtmInternal = getLocalService(ActivityTaskManagerInternal.class);
222         mPmInternal = getLocalService(PackageManagerInternal.class);
223         mUserManager = context.getSystemService(UserManager.class);
224         mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, DOZE_WAKE_LOCK_TAG);
225         mDozeConfig = new AmbientDisplayConfiguration(mContext);
226         mUiEventLogger = new UiEventLoggerImpl();
227         mDreamUiEventLogger = new DreamUiEventLoggerImpl(
228                 mContext.getResources().getStringArray(R.array.config_loggable_dream_prefixes));
229         AmbientDisplayConfiguration adc = new AmbientDisplayConfiguration(mContext);
230         mAmbientDisplayComponent = ComponentName.unflattenFromString(adc.ambientDisplayComponent());
231         mDreamsOnlyEnabledForDockUser =
232                 mContext.getResources().getBoolean(R.bool.config_dreamsOnlyEnabledForDockUser);
233         mDismissDreamOnActivityStart = mContext.getResources().getBoolean(
234                 R.bool.config_dismissDreamOnActivityStart);
235 
236         mDreamsEnabledByDefaultConfig = mContext.getResources().getBoolean(
237                 com.android.internal.R.bool.config_dreamsEnabledByDefault);
238         mDreamsActivatedOnChargeByDefault = mContext.getResources().getBoolean(
239                 com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
240         mDreamsActivatedOnDockByDefault = mContext.getResources().getBoolean(
241                 com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
242         mSettingsObserver = new SettingsObserver(mHandler);
243         mKeepDreamingWhenUnpluggingDefault = mContext.getResources().getBoolean(
244                 com.android.internal.R.bool.config_keepDreamingWhenUnplugging);
245         mDreamsDisabledByAmbientModeSuppressionConfig = mContext.getResources().getBoolean(
246                 com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
247 
248     }
249 
250     @Override
onStart()251     public void onStart() {
252         publishBinderService(DreamService.DREAM_SERVICE, new BinderService());
253         publishLocalService(DreamManagerInternal.class, new LocalService());
254     }
255 
256     @Override
onBootPhase(int phase)257     public void onBootPhase(int phase) {
258         if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
259             if (Build.IS_DEBUGGABLE) {
260                 SystemProperties.addChangeCallback(mSystemPropertiesChanged);
261             }
262 
263             mContext.getContentResolver().registerContentObserver(
264                     Settings.Secure.getUriFor(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE), false,
265                     mDozeEnabledObserver, UserHandle.USER_ALL);
266             writePulseGestureEnabled();
267 
268             if (mDismissDreamOnActivityStart) {
269                 mAtmInternal.registerActivityStartInterceptor(
270                         DREAM_MANAGER_ORDERED_ID,
271                         mActivityInterceptorCallback);
272             }
273 
274             mContext.registerReceiver(
275                     mDockStateReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT));
276             IntentFilter chargingIntentFilter = new IntentFilter();
277             chargingIntentFilter.addAction(BatteryManager.ACTION_CHARGING);
278             chargingIntentFilter.addAction(BatteryManager.ACTION_DISCHARGING);
279             mContext.registerReceiver(mChargingReceiver, chargingIntentFilter);
280 
281             mSettingsObserver = new SettingsObserver(mHandler);
282             mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
283                             Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
284                     false, mSettingsObserver, UserHandle.USER_ALL);
285             mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
286                             Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
287                     false, mSettingsObserver, UserHandle.USER_ALL);
288             mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
289                             Settings.Secure.SCREENSAVER_ENABLED),
290                     false, mSettingsObserver, UserHandle.USER_ALL);
291 
292             // We don't get an initial broadcast for the batter state, so we have to initialize
293             // directly from BatteryManager.
294             mIsCharging = mContext.getSystemService(BatteryManager.class).isCharging();
295 
296             updateWhenToDreamSettings();
297         }
298     }
299 
300     @Override
onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)301     public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
302         updateWhenToDreamSettings();
303 
304         mHandler.post(() -> {
305             writePulseGestureEnabled();
306             synchronized (mLock) {
307                 stopDreamLocked(false /*immediate*/, "user switched");
308             }
309         });
310     }
311 
dumpInternal(PrintWriter pw)312     private void dumpInternal(PrintWriter pw) {
313         synchronized (mLock) {
314             pw.println("DREAM MANAGER (dumpsys dreams)");
315             pw.println();
316             pw.println("mCurrentDream=" + mCurrentDream);
317             pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled);
318             pw.println("mDreamsOnlyEnabledForDockUser=" + mDreamsOnlyEnabledForDockUser);
319             pw.println("mDreamsEnabledSetting=" + mDreamsEnabledSetting);
320             pw.println("mDreamsActivatedOnDockByDefault=" + mDreamsActivatedOnDockByDefault);
321             pw.println("mDreamsActivatedOnChargeByDefault=" + mDreamsActivatedOnChargeByDefault);
322             pw.println("mIsDocked=" + mIsDocked);
323             pw.println("mIsCharging=" + mIsCharging);
324             pw.println("mWhenToDream=" + mWhenToDream);
325             pw.println("mKeepDreamingWhenUnpluggingDefault=" + mKeepDreamingWhenUnpluggingDefault);
326             pw.println("getDozeComponent()=" + getDozeComponent());
327             pw.println("mDreamOverlayServiceName=" + mDreamOverlayServiceName.flattenToString());
328             pw.println();
329 
330             DumpUtils.dumpAsync(mHandler, (pw1, prefix) -> mController.dump(pw1), pw, "", 200);
331         }
332     }
333 
updateWhenToDreamSettings()334     private void updateWhenToDreamSettings() {
335         synchronized (mLock) {
336             final ContentResolver resolver = mContext.getContentResolver();
337 
338             final int activateWhenCharging = (Settings.Secure.getIntForUser(resolver,
339                     Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
340                     mDreamsActivatedOnChargeByDefault ? 1 : 0,
341                     UserHandle.USER_CURRENT) != 0) ? DREAM_ON_CHARGE : DREAM_DISABLED;
342             final int activateWhenDocked = (Settings.Secure.getIntForUser(resolver,
343                     Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
344                     mDreamsActivatedOnDockByDefault ? 1 : 0,
345                     UserHandle.USER_CURRENT) != 0) ? DREAM_ON_DOCK : DREAM_DISABLED;
346             mWhenToDream = activateWhenCharging + activateWhenDocked;
347 
348             mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
349                     Settings.Secure.SCREENSAVER_ENABLED,
350                     mDreamsEnabledByDefaultConfig ? 1 : 0,
351                     UserHandle.USER_CURRENT) != 0);
352         }
353     }
354 
reportKeepDreamingWhenUnpluggingChanged(boolean keepDreaming)355     private void reportKeepDreamingWhenUnpluggingChanged(boolean keepDreaming) {
356         notifyDreamStateListeners(
357                 listener -> listener.onKeepDreamingWhenUnpluggingChanged(keepDreaming));
358     }
359 
reportDreamingStarted()360     private void reportDreamingStarted() {
361         notifyDreamStateListeners(listener -> listener.onDreamingStarted());
362     }
363 
reportDreamingStopped()364     private void reportDreamingStopped() {
365         notifyDreamStateListeners(listener -> listener.onDreamingStopped());
366     }
367 
notifyDreamStateListeners( Consumer<DreamManagerInternal.DreamManagerStateListener> notifier)368     private void notifyDreamStateListeners(
369             Consumer<DreamManagerInternal.DreamManagerStateListener> notifier) {
370         mHandler.post(() -> {
371             for (DreamManagerInternal.DreamManagerStateListener listener
372                     : mDreamManagerStateListeners) {
373                 notifier.accept(listener);
374             }
375         });
376     }
377 
378     /** Whether a real dream is occurring. */
isDreamingInternal()379     private boolean isDreamingInternal() {
380         synchronized (mLock) {
381             return mCurrentDream != null && !mCurrentDream.isPreview
382                     && !mCurrentDream.isWaking;
383         }
384     }
385 
386     /** Whether a doze is occurring. */
isDozingInternal()387     private boolean isDozingInternal() {
388         synchronized (mLock) {
389             return mCurrentDream != null && mCurrentDream.isDozing;
390         }
391     }
392 
393     /** Whether a real dream, or a dream preview is occurring. */
isDreamingOrInPreviewInternal()394     private boolean isDreamingOrInPreviewInternal() {
395         synchronized (mLock) {
396             return mCurrentDream != null && !mCurrentDream.isWaking;
397         }
398     }
399 
400     /** Whether dreaming can start given user settings and the current dock/charge state. */
canStartDreamingInternal(boolean isScreenOn)401     private boolean canStartDreamingInternal(boolean isScreenOn) {
402         synchronized (mLock) {
403             // Can't start dreaming if we are already dreaming.
404             if (isScreenOn && isDreamingInternal()) {
405                 return false;
406             }
407 
408             if (!mDreamsEnabledSetting) {
409                 return false;
410             }
411 
412             if (!dreamsEnabledForUser(ActivityManager.getCurrentUser())) {
413                 return false;
414             }
415 
416             if (!mUserManager.isUserUnlocked()) {
417                 return false;
418             }
419 
420             if (mDreamsDisabledByAmbientModeSuppressionConfig
421                     && mPowerManagerInternal.isAmbientDisplaySuppressed()) {
422                 // Don't dream if Bedtime (or something else) is suppressing ambient.
423                 Slog.i(TAG, "Can't start dreaming because ambient is suppressed.");
424                 return false;
425             }
426 
427             if ((mWhenToDream & DREAM_ON_CHARGE) == DREAM_ON_CHARGE) {
428                 return mIsCharging;
429             }
430 
431             if ((mWhenToDream & DREAM_ON_DOCK) == DREAM_ON_DOCK) {
432                 return mIsDocked;
433             }
434 
435             return false;
436         }
437     }
438 
requestStartDreamFromShell()439     protected void requestStartDreamFromShell() {
440         requestDreamInternal();
441     }
442 
requestDreamInternal()443     private void requestDreamInternal() {
444         // Ask the power manager to nap.  It will eventually call back into
445         // startDream() if/when it is appropriate to start dreaming.
446         // Because napping could cause the screen to turn off immediately if the dream
447         // cannot be started, we keep one eye open and gently poke user activity.
448         long time = SystemClock.uptimeMillis();
449         mPowerManager.userActivity(time, /* noChangeLights= */ true);
450         mPowerManagerInternal.nap(time, /* allowWake= */ true);
451     }
452 
requestAwakenInternal(String reason)453     private void requestAwakenInternal(String reason) {
454         // Treat an explicit request to awaken as user activity so that the
455         // device doesn't immediately go to sleep if the timeout expired,
456         // for example when being undocked.
457         long time = SystemClock.uptimeMillis();
458         mPowerManager.userActivity(time, false /*noChangeLights*/);
459         stopDreamInternal(false /*immediate*/, reason);
460     }
461 
finishSelfInternal(IBinder token, boolean immediate)462     private void finishSelfInternal(IBinder token, boolean immediate) {
463         if (DEBUG) {
464             Slog.d(TAG, "Dream finished: " + token + ", immediate=" + immediate);
465         }
466 
467         // Note that a dream finishing and self-terminating is not
468         // itself considered user activity.  If the dream is ending because
469         // the user interacted with the device then user activity will already
470         // have been poked so the device will stay awake a bit longer.
471         // If the dream is ending on its own for other reasons and no wake
472         // locks are held and the user activity timeout has expired then the
473         // device may simply go to sleep.
474         synchronized (mLock) {
475             if (mCurrentDream != null && mCurrentDream.token == token) {
476                 stopDreamLocked(immediate, "finished self");
477             }
478         }
479     }
480 
testDreamInternal(ComponentName dream, int userId)481     private void testDreamInternal(ComponentName dream, int userId) {
482         synchronized (mLock) {
483             startDreamLocked(dream, true /*isPreviewMode*/, false /*canDoze*/, userId,
484                     "test dream" /*reason*/);
485         }
486     }
487 
startDreamInternal(boolean doze, String reason)488     private void startDreamInternal(boolean doze, String reason) {
489         final int userId = ActivityManager.getCurrentUser();
490         final ComponentName dream = chooseDreamForUser(doze, userId);
491         if (dream != null) {
492             synchronized (mLock) {
493                 startDreamLocked(dream, false /*isPreviewMode*/, doze, userId, reason);
494             }
495         }
496     }
497 
requestStopDreamFromShell()498     protected void requestStopDreamFromShell() {
499         stopDreamInternal(false, "stopping dream from shell");
500     }
501 
stopDreamInternal(boolean immediate, String reason)502     private void stopDreamInternal(boolean immediate, String reason) {
503         synchronized (mLock) {
504             stopDreamLocked(immediate, reason);
505         }
506     }
507 
startDozingInternal(IBinder token, int screenState, int screenBrightness)508     private void startDozingInternal(IBinder token, int screenState,
509             int screenBrightness) {
510         if (DEBUG) {
511             Slog.d(TAG, "Dream requested to start dozing: " + token
512                     + ", screenState=" + screenState
513                     + ", screenBrightness=" + screenBrightness);
514         }
515 
516         synchronized (mLock) {
517             if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.canDoze) {
518                 mCurrentDream.dozeScreenState = screenState;
519                 mCurrentDream.dozeScreenBrightness = screenBrightness;
520                 mPowerManagerInternal.setDozeOverrideFromDreamManager(
521                         screenState, screenBrightness);
522                 if (!mCurrentDream.isDozing) {
523                     mCurrentDream.isDozing = true;
524                     mDozeWakeLock.acquire();
525                 }
526             }
527         }
528     }
529 
stopDozingInternal(IBinder token)530     private void stopDozingInternal(IBinder token) {
531         if (DEBUG) {
532             Slog.d(TAG, "Dream requested to stop dozing: " + token);
533         }
534 
535         synchronized (mLock) {
536             if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.isDozing) {
537                 mCurrentDream.isDozing = false;
538                 mDozeWakeLock.release();
539                 mPowerManagerInternal.setDozeOverrideFromDreamManager(
540                         Display.STATE_UNKNOWN, PowerManager.BRIGHTNESS_DEFAULT);
541             }
542         }
543     }
544 
forceAmbientDisplayEnabledInternal(boolean enabled)545     private void forceAmbientDisplayEnabledInternal(boolean enabled) {
546         if (DEBUG) {
547             Slog.d(TAG, "Force ambient display enabled: " + enabled);
548         }
549 
550         synchronized (mLock) {
551             mForceAmbientDisplayEnabled = enabled;
552         }
553     }
554 
555     /**
556      * If doze is true, returns the doze component for the user.
557      * Otherwise, returns the system dream component, if present.
558      * Otherwise, returns the first valid user configured dream component.
559      */
chooseDreamForUser(boolean doze, int userId)560     private ComponentName chooseDreamForUser(boolean doze, int userId) {
561         if (doze) {
562             ComponentName dozeComponent = getDozeComponent(userId);
563             return validateDream(dozeComponent) ? dozeComponent : null;
564         }
565 
566         if (mSystemDreamComponent != null) {
567             return mSystemDreamComponent;
568         }
569 
570         ComponentName[] dreams = getDreamComponentsForUser(userId);
571         return dreams != null && dreams.length != 0 ? dreams[0] : null;
572     }
573 
validateDream(ComponentName component)574     private boolean validateDream(ComponentName component) {
575         if (component == null) return false;
576         final ServiceInfo serviceInfo = getServiceInfo(component);
577         if (serviceInfo == null) {
578             Slog.w(TAG, "Dream " + component + " does not exist");
579             return false;
580         } else if (serviceInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP
581                 && !BIND_DREAM_SERVICE.equals(serviceInfo.permission)) {
582             Slog.w(TAG, "Dream " + component
583                     + " is not available because its manifest is missing the " + BIND_DREAM_SERVICE
584                     + " permission on the dream service declaration.");
585             return false;
586         }
587         return true;
588     }
589 
getDreamComponentsForUser(int userId)590     private ComponentName[] getDreamComponentsForUser(int userId) {
591         if (!dreamsEnabledForUser(userId)) {
592             // Don't return any dream components if the user is not allowed to dream.
593             return null;
594         }
595 
596         String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
597                 Settings.Secure.SCREENSAVER_COMPONENTS,
598                 userId);
599         ComponentName[] components = componentsFromString(names);
600 
601         // first, ensure components point to valid services
602         List<ComponentName> validComponents = new ArrayList<>();
603         if (components != null) {
604             for (ComponentName component : components) {
605                 if (validateDream(component)) {
606                     validComponents.add(component);
607                 }
608             }
609         }
610 
611         // fallback to the default dream component if necessary
612         if (validComponents.isEmpty()) {
613             ComponentName defaultDream = getDefaultDreamComponentForUser(userId);
614             if (defaultDream != null) {
615                 Slog.w(TAG, "Falling back to default dream " + defaultDream);
616                 validComponents.add(defaultDream);
617             }
618         }
619         return validComponents.toArray(new ComponentName[validComponents.size()]);
620     }
621 
setDreamComponentsForUser(int userId, ComponentName[] componentNames)622     private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
623         Settings.Secure.putStringForUser(mContext.getContentResolver(),
624                 Settings.Secure.SCREENSAVER_COMPONENTS,
625                 componentsToString(componentNames),
626                 userId);
627     }
628 
setSystemDreamComponentInternal(ComponentName componentName)629     private void setSystemDreamComponentInternal(ComponentName componentName) {
630         synchronized (mLock) {
631             if (Objects.equals(mSystemDreamComponent, componentName)) {
632                 return;
633             }
634 
635             mSystemDreamComponent = componentName;
636             reportKeepDreamingWhenUnpluggingChanged(shouldKeepDreamingWhenUnplugging());
637             // Switch dream if currently dreaming and not dozing.
638             if (isDreamingInternal() && !isDozingInternal()) {
639                 startDreamInternal(false /*doze*/, (mSystemDreamComponent == null ? "clear" : "set")
640                         + " system dream component" /*reason*/);
641             }
642         }
643     }
644 
shouldKeepDreamingWhenUnplugging()645     private boolean shouldKeepDreamingWhenUnplugging() {
646         return mKeepDreamingWhenUnpluggingDefault && mSystemDreamComponent == null;
647     }
648 
getDefaultDreamComponentForUser(int userId)649     private ComponentName getDefaultDreamComponentForUser(int userId) {
650         String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
651                 Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
652                 userId);
653         return name == null ? null : ComponentName.unflattenFromString(name);
654     }
655 
getDozeComponent()656     private ComponentName getDozeComponent() {
657         return getDozeComponent(ActivityManager.getCurrentUser());
658     }
659 
getDozeComponent(int userId)660     private ComponentName getDozeComponent(int userId) {
661         if (mForceAmbientDisplayEnabled || mDozeConfig.enabled(userId)) {
662             return ComponentName.unflattenFromString(mDozeConfig.ambientDisplayComponent());
663         } else {
664             return null;
665         }
666 
667     }
668 
dreamsEnabledForUser(int userId)669     private boolean dreamsEnabledForUser(int userId) {
670         if (!mDreamsOnlyEnabledForDockUser) return true;
671         if (userId < 0) return false;
672         final int mainUserId = LocalServices.getService(UserManagerInternal.class).getMainUserId();
673         return userId == mainUserId;
674     }
675 
getServiceInfo(ComponentName name)676     private ServiceInfo getServiceInfo(ComponentName name) {
677         try {
678             return name != null ? mContext.getPackageManager().getServiceInfo(name,
679                     PackageManager.MATCH_DEBUG_TRIAGED_MISSING) : null;
680         } catch (NameNotFoundException e) {
681             return null;
682         }
683     }
684 
685     @GuardedBy("mLock")
startDreamLocked(final ComponentName name, final boolean isPreviewMode, final boolean canDoze, final int userId, final String reason)686     private void startDreamLocked(final ComponentName name,
687             final boolean isPreviewMode, final boolean canDoze, final int userId,
688             final String reason) {
689         if (mCurrentDream != null
690                 && !mCurrentDream.isWaking
691                 && Objects.equals(mCurrentDream.name, name)
692                 && mCurrentDream.isPreview == isPreviewMode
693                 && mCurrentDream.canDoze == canDoze
694                 && mCurrentDream.userId == userId) {
695             Slog.i(TAG, "Already in target dream.");
696             return;
697         }
698 
699         Slog.i(TAG, "Entering dreamland.");
700 
701         if (mCurrentDream != null && mCurrentDream.isDozing) {
702             stopDozingInternal(mCurrentDream.token);
703         }
704 
705         mCurrentDream = new DreamRecord(name, userId, isPreviewMode, canDoze);
706 
707         if (!mCurrentDream.name.equals(mAmbientDisplayComponent)) {
708             // TODO(b/213906448): Remove when metrics based on new atom are fully rolled out.
709             mUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_START);
710             mDreamUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_START,
711                     mCurrentDream.name.flattenToString());
712         }
713 
714         PowerManager.WakeLock wakeLock = mPowerManager
715                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, DREAM_WAKE_LOCK_TAG);
716         final Binder dreamToken = mCurrentDream.token;
717         mHandler.post(wakeLock.wrap(() -> {
718             mAtmInternal.notifyActiveDreamChanged(name);
719             mController.startDream(dreamToken, name, isPreviewMode, canDoze, userId, wakeLock,
720                     mDreamOverlayServiceName, reason);
721         }));
722     }
723 
724     @GuardedBy("mLock")
stopDreamLocked(final boolean immediate, String reason)725     private void stopDreamLocked(final boolean immediate, String reason) {
726         if (mCurrentDream != null) {
727             if (immediate) {
728                 Slog.i(TAG, "Leaving dreamland.");
729                 cleanupDreamLocked();
730             } else if (mCurrentDream.isWaking) {
731                 return; // already waking
732             } else {
733                 Slog.i(TAG, "Gently waking up from dream.");
734                 mCurrentDream.isWaking = true;
735             }
736 
737             mHandler.post(() -> mController.stopDream(immediate, reason));
738         }
739     }
740 
741     @GuardedBy("mLock")
cleanupDreamLocked()742     private void cleanupDreamLocked() {
743         mHandler.post(() -> mAtmInternal.notifyActiveDreamChanged(null));
744 
745         if (mCurrentDream == null) {
746             return;
747         }
748 
749         if (!mCurrentDream.name.equals(mAmbientDisplayComponent)) {
750             // TODO(b/213906448): Remove when metrics based on new atom are fully rolled out.
751             mUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_STOP);
752             mDreamUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_STOP,
753                     mCurrentDream.name.flattenToString());
754         }
755         if (mCurrentDream.isDozing) {
756             mDozeWakeLock.release();
757         }
758         mCurrentDream = null;
759     }
760 
checkPermission(String permission)761     private void checkPermission(String permission) {
762         if (mContext.checkCallingOrSelfPermission(permission)
763                 != PackageManager.PERMISSION_GRANTED) {
764             throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
765                     + ", must have permission " + permission);
766         }
767     }
768 
writePulseGestureEnabled()769     private void writePulseGestureEnabled() {
770         ComponentName name = getDozeComponent();
771         boolean dozeEnabled = validateDream(name);
772         LocalServices.getService(InputManagerInternal.class).setPulseGestureEnabled(dozeEnabled);
773     }
774 
componentsToString(ComponentName[] componentNames)775     private static String componentsToString(ComponentName[] componentNames) {
776         if (componentNames == null) {
777             return null;
778         }
779         StringBuilder names = new StringBuilder();
780         for (ComponentName componentName : componentNames) {
781             if (names.length() > 0) {
782                 names.append(',');
783             }
784             names.append(componentName.flattenToString());
785         }
786         return names.toString();
787     }
788 
componentsFromString(String names)789     private static ComponentName[] componentsFromString(String names) {
790         if (names == null) {
791             return null;
792         }
793         String[] namesArray = names.split(",");
794         ComponentName[] componentNames = new ComponentName[namesArray.length];
795         for (int i = 0; i < namesArray.length; i++) {
796             componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
797         }
798         return componentNames;
799     }
800 
801     private final DreamController.Listener mControllerListener = new DreamController.Listener() {
802         @Override
803         public void onDreamStarted(Binder token) {
804             // Note that this event is distinct from DreamManagerService#startDreamLocked as it
805             // tracks the DreamService attach point from DreamController, closest to the broadcast
806             // of ACTION_DREAMING_STARTED.
807 
808             reportDreamingStarted();
809         }
810 
811         @Override
812         public void onDreamStopped(Binder token) {
813             synchronized (mLock) {
814                 if (mCurrentDream != null && mCurrentDream.token == token) {
815                     cleanupDreamLocked();
816                 }
817             }
818 
819             reportDreamingStopped();
820         }
821     };
822 
823     private final ContentObserver mDozeEnabledObserver = new ContentObserver(null) {
824         @Override
825         public void onChange(boolean selfChange) {
826             writePulseGestureEnabled();
827         }
828     };
829 
830     /**
831      * Handler for asynchronous operations performed by the dream manager.
832      * Ensures operations to {@link DreamController} are single-threaded.
833      */
834     private static final class DreamHandler extends Handler {
DreamHandler(Looper looper)835         public DreamHandler(Looper looper) {
836             super(looper, null, true /*async*/);
837         }
838     }
839 
840     private final class BinderService extends IDreamManager.Stub {
841         @Override // Binder call
dump(FileDescriptor fd, PrintWriter pw, String[] args)842         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
843             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
844             final long ident = Binder.clearCallingIdentity();
845             try {
846                 dumpInternal(pw);
847             } finally {
848                 Binder.restoreCallingIdentity(ident);
849             }
850         }
851 
onShellCommand(@ullable FileDescriptor in, @Nullable FileDescriptor out, @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver)852         public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
853                 @Nullable FileDescriptor err,
854                 @NonNull String[] args, @Nullable ShellCallback callback,
855                 @NonNull ResultReceiver resultReceiver) throws RemoteException {
856             new DreamShellCommand(DreamManagerService.this)
857                     .exec(this, in, out, err, args, callback, resultReceiver);
858         }
859 
860         @Override // Binder call
getDreamComponents()861         public ComponentName[] getDreamComponents() {
862             return getDreamComponentsForUser(UserHandle.getCallingUserId());
863         }
864 
865         @Override // Binder call
getDreamComponentsForUser(int userId)866         public ComponentName[] getDreamComponentsForUser(int userId) {
867             checkPermission(android.Manifest.permission.READ_DREAM_STATE);
868             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
869                     Binder.getCallingUid(), userId, false, true, "getDreamComponents", null);
870 
871             final long ident = Binder.clearCallingIdentity();
872             try {
873                 return DreamManagerService.this.getDreamComponentsForUser(userId);
874             } finally {
875                 Binder.restoreCallingIdentity(ident);
876             }
877         }
878 
879         @Override // Binder call
setDreamComponents(ComponentName[] componentNames)880         public void setDreamComponents(ComponentName[] componentNames) {
881             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
882 
883             final int userId = UserHandle.getCallingUserId();
884             final long ident = Binder.clearCallingIdentity();
885             try {
886                 setDreamComponentsForUser(userId, componentNames);
887             } finally {
888                 Binder.restoreCallingIdentity(ident);
889             }
890         }
891 
892         @Override // Binder call
setDreamComponentsForUser(int userId, ComponentName[] componentNames)893         public void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
894             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
895             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
896                     Binder.getCallingUid(), userId, false, true, "setDreamComponents", null);
897 
898             final long ident = Binder.clearCallingIdentity();
899             try {
900                 DreamManagerService.this.setDreamComponentsForUser(userId, componentNames);
901             } finally {
902                 Binder.restoreCallingIdentity(ident);
903             }
904         }
905 
906         @Override // Binder call
setSystemDreamComponent(ComponentName componentName)907         public void setSystemDreamComponent(ComponentName componentName) {
908             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
909 
910             final long ident = Binder.clearCallingIdentity();
911             try {
912                 DreamManagerService.this.setSystemDreamComponentInternal(componentName);
913             } finally {
914                 Binder.restoreCallingIdentity(ident);
915             }
916         }
917 
918         @Override // Binder call
registerDreamOverlayService(ComponentName overlayComponent)919         public void registerDreamOverlayService(ComponentName overlayComponent) {
920             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
921 
922             // Store the overlay service component so that it can be passed to the dream when it is
923             // invoked.
924             mDreamOverlayServiceName = overlayComponent;
925         }
926 
927         @Override // Binder call
getDefaultDreamComponentForUser(int userId)928         public ComponentName getDefaultDreamComponentForUser(int userId) {
929             checkPermission(android.Manifest.permission.READ_DREAM_STATE);
930             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
931                     Binder.getCallingUid(), userId, false, true, "getDefaultDreamComponent", null);
932 
933             final long ident = Binder.clearCallingIdentity();
934             try {
935                 return DreamManagerService.this.getDefaultDreamComponentForUser(userId);
936             } finally {
937                 Binder.restoreCallingIdentity(ident);
938             }
939         }
940 
941         @Override // Binder call
isDreaming()942         public boolean isDreaming() {
943             checkPermission(android.Manifest.permission.READ_DREAM_STATE);
944 
945             final long ident = Binder.clearCallingIdentity();
946             try {
947                 return isDreamingInternal();
948             } finally {
949                 Binder.restoreCallingIdentity(ident);
950             }
951         }
952 
953         @Override // Binder call
isDreamingOrInPreview()954         public boolean isDreamingOrInPreview() {
955             checkPermission(android.Manifest.permission.READ_DREAM_STATE);
956 
957             final long ident = Binder.clearCallingIdentity();
958             try {
959                 return isDreamingOrInPreviewInternal();
960             } finally {
961                 Binder.restoreCallingIdentity(ident);
962             }
963         }
964 
965 
966         @Override // Binder call
dream()967         public void dream() {
968             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
969 
970             final long ident = Binder.clearCallingIdentity();
971             try {
972                 requestDreamInternal();
973             } finally {
974                 Binder.restoreCallingIdentity(ident);
975             }
976         }
977 
978         @Override // Binder call
testDream(int userId, ComponentName dream)979         public void testDream(int userId, ComponentName dream) {
980             if (dream == null) {
981                 throw new IllegalArgumentException("dream must not be null");
982             }
983             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
984             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
985                     Binder.getCallingUid(), userId, false, true, "testDream", null);
986 
987             final int currentUserId = ActivityManager.getCurrentUser();
988             if (userId != currentUserId) {
989                 // This check is inherently prone to races but at least it's something.
990                 Slog.w(TAG, "Aborted attempt to start a test dream while a different "
991                         + " user is active: userId=" + userId
992                         + ", currentUserId=" + currentUserId);
993                 return;
994             }
995             final long ident = Binder.clearCallingIdentity();
996             try {
997                 testDreamInternal(dream, userId);
998             } finally {
999                 Binder.restoreCallingIdentity(ident);
1000             }
1001         }
1002 
1003         @Override // Binder call
awaken()1004         public void awaken() {
1005             checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
1006 
1007             final long ident = Binder.clearCallingIdentity();
1008             try {
1009                 requestAwakenInternal("request awaken");
1010             } finally {
1011                 Binder.restoreCallingIdentity(ident);
1012             }
1013         }
1014 
1015         @Override // Binder call
finishSelf(IBinder token, boolean immediate)1016         public void finishSelf(IBinder token, boolean immediate) {
1017             // Requires no permission, called by Dream from an arbitrary process.
1018             if (token == null) {
1019                 throw new IllegalArgumentException("token must not be null");
1020             }
1021 
1022             final long ident = Binder.clearCallingIdentity();
1023             try {
1024                 finishSelfInternal(token, immediate);
1025             } finally {
1026                 Binder.restoreCallingIdentity(ident);
1027             }
1028         }
1029 
1030         @Override // Binder call
startDozing(IBinder token, int screenState, int screenBrightness)1031         public void startDozing(IBinder token, int screenState, int screenBrightness) {
1032             // Requires no permission, called by Dream from an arbitrary process.
1033             if (token == null) {
1034                 throw new IllegalArgumentException("token must not be null");
1035             }
1036 
1037             final long ident = Binder.clearCallingIdentity();
1038             try {
1039                 startDozingInternal(token, screenState, screenBrightness);
1040             } finally {
1041                 Binder.restoreCallingIdentity(ident);
1042             }
1043         }
1044 
1045         @Override // Binder call
stopDozing(IBinder token)1046         public void stopDozing(IBinder token) {
1047             // Requires no permission, called by Dream from an arbitrary process.
1048             if (token == null) {
1049                 throw new IllegalArgumentException("token must not be null");
1050             }
1051 
1052             final long ident = Binder.clearCallingIdentity();
1053             try {
1054                 stopDozingInternal(token);
1055             } finally {
1056                 Binder.restoreCallingIdentity(ident);
1057             }
1058         }
1059 
1060         @Override // Binder call
forceAmbientDisplayEnabled(boolean enabled)1061         public void forceAmbientDisplayEnabled(boolean enabled) {
1062             checkPermission(android.Manifest.permission.DEVICE_POWER);
1063 
1064             final long ident = Binder.clearCallingIdentity();
1065             try {
1066                 forceAmbientDisplayEnabledInternal(enabled);
1067             } finally {
1068                 Binder.restoreCallingIdentity(ident);
1069             }
1070         }
1071 
1072         @Override // Binder call
startDreamActivity(@onNull Intent intent)1073         public void startDreamActivity(@NonNull Intent intent) {
1074             final int callingUid = Binder.getCallingUid();
1075             final int callingPid = Binder.getCallingPid();
1076             // We post here, because startDreamActivity and setDreamAppTask have to run
1077             // synchronously and DreamController#setDreamAppTask has to run on mHandler.
1078             mHandler.post(() -> {
1079                 final Binder dreamToken;
1080                 final String dreamPackageName;
1081                 synchronized (mLock) {
1082                     if (mCurrentDream == null) {
1083                         Slog.e(TAG, "Attempt to start DreamActivity, but the device is not "
1084                                 + "dreaming. Aborting without starting the DreamActivity.");
1085                         return;
1086                     }
1087                     dreamToken = mCurrentDream.token;
1088                     dreamPackageName = mCurrentDream.name.getPackageName();
1089                 }
1090 
1091                 if (!canLaunchDreamActivity(dreamPackageName, intent.getPackage(),
1092                             callingUid)) {
1093                     Slog.e(TAG, "The dream activity can be started only when the device is dreaming"
1094                             + " and only by the active dream package.");
1095                     return;
1096                 }
1097 
1098                 final IAppTask appTask = mAtmInternal.startDreamActivity(intent, callingUid,
1099                         callingPid);
1100                 if (appTask == null) {
1101                     Slog.e(TAG, "Could not start dream activity.");
1102                     stopDreamInternal(true, "DreamActivity not started");
1103                     return;
1104                 }
1105                 mController.setDreamAppTask(dreamToken, appTask);
1106             });
1107         }
1108 
canLaunchDreamActivity(String dreamPackageName, String packageName, int callingUid)1109         boolean canLaunchDreamActivity(String dreamPackageName, String packageName,
1110                 int callingUid) {
1111             if (dreamPackageName == null || packageName == null) {
1112                 Slog.e(TAG, "Cannot launch dream activity due to invalid state. dream component= "
1113                         + dreamPackageName + ", packageName=" + packageName);
1114                 return false;
1115             }
1116             if (!mPmInternal.isSameApp(packageName, callingUid, UserHandle.getUserId(callingUid))) {
1117                 Slog.e(TAG, "Cannot launch dream activity because package="
1118                         + packageName + " does not match callingUid=" + callingUid);
1119                 return false;
1120             }
1121             if (packageName.equals(dreamPackageName)) {
1122                 return true;
1123             }
1124             Slog.e(TAG, "Dream packageName does not match active dream. Package " + packageName
1125                     + " does not match " + dreamPackageName);
1126             return false;
1127         }
1128 
1129     }
1130 
1131     private final class LocalService extends DreamManagerInternal {
1132         @Override
startDream(boolean doze, String reason)1133         public void startDream(boolean doze, String reason) {
1134             startDreamInternal(doze, reason);
1135         }
1136 
1137         @Override
stopDream(boolean immediate, String reason)1138         public void stopDream(boolean immediate, String reason) {
1139             stopDreamInternal(immediate, reason);
1140         }
1141 
1142         @Override
isDreaming()1143         public boolean isDreaming() {
1144             return isDreamingInternal();
1145         }
1146 
1147         @Override
canStartDreaming(boolean isScreenOn)1148         public boolean canStartDreaming(boolean isScreenOn) {
1149             return canStartDreamingInternal(isScreenOn);
1150         }
1151 
1152         @Override
requestDream()1153         public void requestDream() {
1154             requestDreamInternal();
1155         }
1156 
1157         @Override
registerDreamManagerStateListener(DreamManagerStateListener listener)1158         public void registerDreamManagerStateListener(DreamManagerStateListener listener) {
1159             mDreamManagerStateListeners.add(listener);
1160             // Initialize the listener's state.
1161             listener.onKeepDreamingWhenUnpluggingChanged(shouldKeepDreamingWhenUnplugging());
1162         }
1163 
1164         @Override
unregisterDreamManagerStateListener(DreamManagerStateListener listener)1165         public void unregisterDreamManagerStateListener(DreamManagerStateListener listener) {
1166             mDreamManagerStateListeners.remove(listener);
1167         }
1168     }
1169 
1170     private static final class DreamRecord {
1171         public final Binder token = new Binder();
1172         public final ComponentName name;
1173         public final int userId;
1174         public final boolean isPreview;
1175         public final boolean canDoze;
1176         public boolean isDozing = false;
1177         public boolean isWaking = false;
1178         public int dozeScreenState = Display.STATE_UNKNOWN;
1179         public int dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
1180 
DreamRecord(ComponentName name, int userId, boolean isPreview, boolean canDoze)1181         DreamRecord(ComponentName name, int userId, boolean isPreview, boolean canDoze) {
1182             this.name = name;
1183             this.userId = userId;
1184             this.isPreview = isPreview;
1185             this.canDoze = canDoze;
1186         }
1187 
1188         @Override
toString()1189         public String toString() {
1190             return "DreamRecord{"
1191                     + "token=" + token
1192                     + ", name=" + name
1193                     + ", userId=" + userId
1194                     + ", isPreview=" + isPreview
1195                     + ", canDoze=" + canDoze
1196                     + ", isDozing=" + isDozing
1197                     + ", isWaking=" + isWaking
1198                     + ", dozeScreenState=" + dozeScreenState
1199                     + ", dozeScreenBrightness=" + dozeScreenBrightness
1200                     + '}';
1201         }
1202     }
1203 
1204     private final Runnable mSystemPropertiesChanged = new Runnable() {
1205         @Override
1206         public void run() {
1207             if (DEBUG) Slog.d(TAG, "System properties changed");
1208             synchronized (mLock) {
1209                 if (mCurrentDream != null &&  mCurrentDream.name != null && mCurrentDream.canDoze
1210                         && !mCurrentDream.name.equals(getDozeComponent())) {
1211                     // May have updated the doze component, wake up
1212                     mPowerManager.wakeUp(SystemClock.uptimeMillis(),
1213                             "android.server.dreams:SYSPROP");
1214                 }
1215             }
1216         }
1217     };
1218 }
1219