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 android.service.dreams;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.PowerManager;
23 import android.os.RemoteException;
24 import android.os.ServiceManager;
25 import android.os.SystemClock;
26 import android.os.UserHandle;
27 import android.provider.Settings;
28 import android.util.Slog;
29 
30 /**
31  * Internal helper for launching dreams to ensure consistency between the
32  * <code>UiModeManagerService</code> system service and the <code>Somnambulator</code> activity.
33  *
34  * @hide
35  */
36 public final class Sandman {
37     private static final String TAG = "Sandman";
38 
39     // The component name of a special dock app that merely launches a dream.
40     // We don't want to launch this app when docked because it causes an unnecessary
41     // activity transition.  We just want to start the dream.
42     private static final ComponentName SOMNAMBULATOR_COMPONENT =
43             new ComponentName("com.android.systemui", "com.android.systemui.Somnambulator");
44 
45 
46     // The sandman is eternal.  No one instantiates him.
Sandman()47     private Sandman() {
48     }
49 
50     /**
51      * Returns true if the specified dock app intent should be started.
52      * False if we should dream instead, if appropriate.
53      */
shouldStartDockApp(Context context, Intent intent)54     public static boolean shouldStartDockApp(Context context, Intent intent) {
55         ComponentName name = intent.resolveActivity(context.getPackageManager());
56         return name != null && !name.equals(SOMNAMBULATOR_COMPONENT);
57     }
58 
59     /**
60      * Starts a dream manually.
61      */
startDreamByUserRequest(Context context)62     public static void startDreamByUserRequest(Context context) {
63         startDream(context, false);
64     }
65 
66     /**
67      * Starts a dream when docked if the system has been configured to do so,
68      * otherwise does nothing.
69      */
startDreamWhenDockedIfAppropriate(Context context)70     public static void startDreamWhenDockedIfAppropriate(Context context) {
71         if (!isScreenSaverEnabled(context)
72                 || !isScreenSaverActivatedOnDock(context)) {
73             Slog.i(TAG, "Dreams currently disabled for docks.");
74             return;
75         }
76 
77         startDream(context, true);
78     }
79 
startDream(Context context, boolean docked)80     private static void startDream(Context context, boolean docked) {
81         try {
82             IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
83                     ServiceManager.getService(DreamService.DREAM_SERVICE));
84             if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
85                 if (docked) {
86                     Slog.i(TAG, "Activating dream while docked.");
87 
88                     // Wake up.
89                     // The power manager will wake up the system automatically when it starts
90                     // receiving power from a dock but there is a race between that happening
91                     // and the UI mode manager starting a dream.  We want the system to already
92                     // be awake by the time this happens.  Otherwise the dream may not start.
93                     PowerManager powerManager =
94                             context.getSystemService(PowerManager.class);
95                     powerManager.wakeUp(SystemClock.uptimeMillis(),
96                             PowerManager.WAKE_REASON_PLUGGED_IN,
97                             "android.service.dreams:DREAM");
98                 } else {
99                     Slog.i(TAG, "Activating dream by user request.");
100                 }
101 
102                 // Dream.
103                 dreamManagerService.dream();
104             }
105         } catch (RemoteException ex) {
106             Slog.e(TAG, "Could not start dream when docked.", ex);
107         }
108     }
109 
isScreenSaverEnabled(Context context)110     private static boolean isScreenSaverEnabled(Context context) {
111         int def = context.getResources().getBoolean(
112                 com.android.internal.R.bool.config_dreamsEnabledByDefault) ? 1 : 0;
113         return Settings.Secure.getIntForUser(context.getContentResolver(),
114                 Settings.Secure.SCREENSAVER_ENABLED, def,
115                 UserHandle.USER_CURRENT) != 0;
116     }
117 
isScreenSaverActivatedOnDock(Context context)118     private static boolean isScreenSaverActivatedOnDock(Context context) {
119         int def = context.getResources().getBoolean(
120                 com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault) ? 1 : 0;
121         return Settings.Secure.getIntForUser(context.getContentResolver(),
122                 Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, def,
123                 UserHandle.USER_CURRENT) != 0;
124     }
125 }
126