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