blob: 8813a61fc5fbd2c8bc7292403263c20571cbeca2 [file] [log] [blame]
John Spurlockf4f6b4c2012-08-25 12:08:03 -04001/*
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
Jeff Browncef440f2012-09-25 18:58:48 -070017package com.android.server.dreams;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040018
John Spurlockeb8d1be2014-06-25 17:46:15 -040019import static android.Manifest.permission.BIND_DREAM_SERVICE;
20
Jeff Brown62c82e42012-09-26 01:30:41 -070021import com.android.internal.util.DumpUtils;
Jeff Brown4ccb8232014-01-16 22:16:42 -080022import com.android.server.FgThread;
Jeff Brown567f7ca2014-01-30 23:38:03 -080023import com.android.server.SystemService;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040024
Jeff Brown567f7ca2014-01-30 23:38:03 -080025import android.Manifest;
Jeff Brown62c82e42012-09-26 01:30:41 -070026import android.app.ActivityManager;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040027import android.content.BroadcastReceiver;
28import android.content.ComponentName;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040032import android.content.pm.PackageManager;
John Spurlockbbdb0622012-12-10 18:15:07 -050033import android.content.pm.PackageManager.NameNotFoundException;
John Spurlockeb8d1be2014-06-25 17:46:15 -040034import android.content.pm.ServiceInfo;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040035import android.os.Binder;
Jeff Brown26875502014-01-30 21:47:47 -080036import android.os.Build;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040037import android.os.Handler;
38import android.os.IBinder;
Jeff Brown62c82e42012-09-26 01:30:41 -070039import android.os.Looper;
40import android.os.PowerManager;
Jeff Brown970d4132014-07-19 11:33:47 -070041import android.os.PowerManagerInternal;
Jeff Brown62c82e42012-09-26 01:30:41 -070042import android.os.SystemClock;
Jeff Brown26875502014-01-30 21:47:47 -080043import android.os.SystemProperties;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040044import android.os.UserHandle;
45import android.provider.Settings;
Jeff Brown567f7ca2014-01-30 23:38:03 -080046import android.service.dreams.DreamManagerInternal;
47import android.service.dreams.DreamService;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040048import android.service.dreams.IDreamManager;
Jeff Brown26875502014-01-30 21:47:47 -080049import android.text.TextUtils;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040050import android.util.Slog;
Jeff Brown970d4132014-07-19 11:33:47 -070051import android.view.Display;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040052
53import java.io.FileDescriptor;
54import java.io.PrintWriter;
John Spurlockbbdb0622012-12-10 18:15:07 -050055import java.util.ArrayList;
56import java.util.List;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040057
Jeff Brown62c82e42012-09-26 01:30:41 -070058import libcore.util.Objects;
59
John Spurlockf4f6b4c2012-08-25 12:08:03 -040060/**
61 * Service api for managing dreams.
62 *
63 * @hide
64 */
Jeff Brown567f7ca2014-01-30 23:38:03 -080065public final class DreamManagerService extends SystemService {
Dianne Hackborn40e9f292012-11-27 19:12:23 -080066 private static final boolean DEBUG = false;
Jeff Brown62c82e42012-09-26 01:30:41 -070067 private static final String TAG = "DreamManagerService";
John Spurlockf4f6b4c2012-08-25 12:08:03 -040068
69 private final Object mLock = new Object();
Jeff Brown62c82e42012-09-26 01:30:41 -070070
John Spurlockf4f6b4c2012-08-25 12:08:03 -040071 private final Context mContext;
Jeff Brown62c82e42012-09-26 01:30:41 -070072 private final DreamHandler mHandler;
73 private final DreamController mController;
74 private final PowerManager mPowerManager;
Jeff Brown970d4132014-07-19 11:33:47 -070075 private final PowerManagerInternal mPowerManagerInternal;
Jeff Brown26875502014-01-30 21:47:47 -080076 private final PowerManager.WakeLock mDozeWakeLock;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040077
Jeff Brown62c82e42012-09-26 01:30:41 -070078 private Binder mCurrentDreamToken;
79 private ComponentName mCurrentDreamName;
80 private int mCurrentDreamUserId;
81 private boolean mCurrentDreamIsTest;
Jeff Brown26875502014-01-30 21:47:47 -080082 private boolean mCurrentDreamCanDoze;
83 private boolean mCurrentDreamIsDozing;
Jeff Brownf6d46682014-07-17 22:44:20 -070084 private boolean mCurrentDreamIsWaking;
Jeff Brown970d4132014-07-19 11:33:47 -070085 private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
86 private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040087
Jeff Brown4ccb8232014-01-16 22:16:42 -080088 public DreamManagerService(Context context) {
Jeff Brown567f7ca2014-01-30 23:38:03 -080089 super(context);
John Spurlockf4f6b4c2012-08-25 12:08:03 -040090 mContext = context;
Jeff Brown4ccb8232014-01-16 22:16:42 -080091 mHandler = new DreamHandler(FgThread.get().getLooper());
Jeff Brown62c82e42012-09-26 01:30:41 -070092 mController = new DreamController(context, mHandler, mControllerListener);
93
94 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Jeff Brown970d4132014-07-19 11:33:47 -070095 mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
Jeff Brown26875502014-01-30 21:47:47 -080096 mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
John Spurlockf4f6b4c2012-08-25 12:08:03 -040097 }
98
Jeff Brown567f7ca2014-01-30 23:38:03 -080099 @Override
100 public void onStart() {
101 publishBinderService(DreamService.DREAM_SERVICE, new BinderService());
102 publishLocalService(DreamManagerInternal.class, new LocalService());
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400103 }
104
105 @Override
Jeff Brown567f7ca2014-01-30 23:38:03 -0800106 public void onBootPhase(int phase) {
107 if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
John Spurlockbf370992014-06-17 13:58:31 -0400108 if (Build.IS_DEBUGGABLE) {
109 SystemProperties.addChangeCallback(mSystemPropertiesChanged);
110 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800111 mContext.registerReceiver(new BroadcastReceiver() {
112 @Override
113 public void onReceive(Context context, Intent intent) {
114 synchronized (mLock) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700115 stopDreamLocked(false /*immediate*/);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800116 }
117 }
118 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
John Spurlockda5b6f22013-08-14 09:46:52 -0400119 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800120 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400121
Jeff Brown567f7ca2014-01-30 23:38:03 -0800122 private void dumpInternal(PrintWriter pw) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700123 pw.println("DREAM MANAGER (dumpsys dreams)");
124 pw.println();
Jeff Brown62c82e42012-09-26 01:30:41 -0700125 pw.println("mCurrentDreamToken=" + mCurrentDreamToken);
126 pw.println("mCurrentDreamName=" + mCurrentDreamName);
127 pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId);
128 pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest);
Jeff Brown26875502014-01-30 21:47:47 -0800129 pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze);
130 pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing);
Jeff Brownf6d46682014-07-17 22:44:20 -0700131 pw.println("mCurrentDreamIsWaking=" + mCurrentDreamIsWaking);
Jeff Brown970d4132014-07-19 11:33:47 -0700132 pw.println("mCurrentDreamDozeScreenState="
133 + Display.stateToString(mCurrentDreamDozeScreenState));
134 pw.println("mCurrentDreamDozeScreenBrightness=" + mCurrentDreamDozeScreenBrightness);
John Spurlockbf370992014-06-17 13:58:31 -0400135 pw.println("getDozeComponent()=" + getDozeComponent());
Jeff Brown62c82e42012-09-26 01:30:41 -0700136 pw.println();
137
138 DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
139 @Override
Dianne Hackbornae6688b2015-02-11 17:02:41 -0800140 public void dump(PrintWriter pw, String prefix) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700141 mController.dump(pw);
142 }
Dianne Hackbornae6688b2015-02-11 17:02:41 -0800143 }, pw, "", 200);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400144 }
145
Jeff Brown567f7ca2014-01-30 23:38:03 -0800146 private boolean isDreamingInternal() {
Jeff Brown62c82e42012-09-26 01:30:41 -0700147 synchronized (mLock) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700148 return mCurrentDreamToken != null && !mCurrentDreamIsTest
149 && !mCurrentDreamIsWaking;
Jeff Brown62c82e42012-09-26 01:30:41 -0700150 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400151 }
152
Jeff Brown567f7ca2014-01-30 23:38:03 -0800153 private void requestDreamInternal() {
154 // Ask the power manager to nap. It will eventually call back into
155 // startDream() if/when it is appropriate to start dreaming.
156 // Because napping could cause the screen to turn off immediately if the dream
157 // cannot be started, we keep one eye open and gently poke user activity.
158 long time = SystemClock.uptimeMillis();
159 mPowerManager.userActivity(time, true /*noChangeLights*/);
160 mPowerManager.nap(time);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400161 }
162
Jeff Brown567f7ca2014-01-30 23:38:03 -0800163 private void requestAwakenInternal() {
164 // Treat an explicit request to awaken as user activity so that the
165 // device doesn't immediately go to sleep if the timeout expired,
166 // for example when being undocked.
167 long time = SystemClock.uptimeMillis();
168 mPowerManager.userActivity(time, false /*noChangeLights*/);
Jeff Brownf6d46682014-07-17 22:44:20 -0700169 stopDreamInternal(false /*immediate*/);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800170 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400171
Jeff Brownf6d46682014-07-17 22:44:20 -0700172 private void finishSelfInternal(IBinder token, boolean immediate) {
Jeff Brown567f7ca2014-01-30 23:38:03 -0800173 if (DEBUG) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700174 Slog.d(TAG, "Dream finished: " + token + ", immediate=" + immediate);
Jeff Brown62c82e42012-09-26 01:30:41 -0700175 }
176
Jeff Brown567f7ca2014-01-30 23:38:03 -0800177 // Note that a dream finishing and self-terminating is not
178 // itself considered user activity. If the dream is ending because
179 // the user interacted with the device then user activity will already
180 // have been poked so the device will stay awake a bit longer.
181 // If the dream is ending on its own for other reasons and no wake
182 // locks are held and the user activity timeout has expired then the
183 // device may simply go to sleep.
184 synchronized (mLock) {
185 if (mCurrentDreamToken == token) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700186 stopDreamLocked(immediate);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400187 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400188 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400189 }
190
Jeff Brown567f7ca2014-01-30 23:38:03 -0800191 private void testDreamInternal(ComponentName dream, int userId) {
192 synchronized (mLock) {
Jeff Brown26875502014-01-30 21:47:47 -0800193 startDreamLocked(dream, true /*isTest*/, false /*canDoze*/, userId);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400194 }
195 }
196
Jeff Brown26875502014-01-30 21:47:47 -0800197 private void startDreamInternal(boolean doze) {
198 final int userId = ActivityManager.getCurrentUser();
John Spurlockeb8d1be2014-06-25 17:46:15 -0400199 final ComponentName dream = chooseDreamForUser(doze, userId);
Jeff Brown62c82e42012-09-26 01:30:41 -0700200 if (dream != null) {
201 synchronized (mLock) {
Jeff Brown26875502014-01-30 21:47:47 -0800202 startDreamLocked(dream, false /*isTest*/, doze, userId);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400203 }
204 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700205 }
206
Jeff Brownf6d46682014-07-17 22:44:20 -0700207 private void stopDreamInternal(boolean immediate) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700208 synchronized (mLock) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700209 stopDreamLocked(immediate);
Jeff Brown62c82e42012-09-26 01:30:41 -0700210 }
211 }
212
Jeff Brown970d4132014-07-19 11:33:47 -0700213 private void startDozingInternal(IBinder token, int screenState,
214 int screenBrightness) {
Jeff Brown26875502014-01-30 21:47:47 -0800215 if (DEBUG) {
Jeff Brown970d4132014-07-19 11:33:47 -0700216 Slog.d(TAG, "Dream requested to start dozing: " + token
217 + ", screenState=" + screenState
218 + ", screenBrightness=" + screenBrightness);
Jeff Brown26875502014-01-30 21:47:47 -0800219 }
220
221 synchronized (mLock) {
Jeff Brown970d4132014-07-19 11:33:47 -0700222 if (mCurrentDreamToken == token && mCurrentDreamCanDoze) {
223 mCurrentDreamDozeScreenState = screenState;
224 mCurrentDreamDozeScreenBrightness = screenBrightness;
225 mPowerManagerInternal.setDozeOverrideFromDreamManager(
226 screenState, screenBrightness);
227 if (!mCurrentDreamIsDozing) {
228 mCurrentDreamIsDozing = true;
229 mDozeWakeLock.acquire();
230 }
Jeff Brown26875502014-01-30 21:47:47 -0800231 }
232 }
233 }
234
235 private void stopDozingInternal(IBinder token) {
236 if (DEBUG) {
237 Slog.d(TAG, "Dream requested to stop dozing: " + token);
238 }
239
240 synchronized (mLock) {
241 if (mCurrentDreamToken == token && mCurrentDreamIsDozing) {
242 mCurrentDreamIsDozing = false;
243 mDozeWakeLock.release();
Jeff Brown970d4132014-07-19 11:33:47 -0700244 mPowerManagerInternal.setDozeOverrideFromDreamManager(
245 Display.STATE_UNKNOWN, PowerManager.BRIGHTNESS_DEFAULT);
Jeff Brown26875502014-01-30 21:47:47 -0800246 }
247 }
248 }
249
John Spurlockeb8d1be2014-06-25 17:46:15 -0400250 private ComponentName chooseDreamForUser(boolean doze, int userId) {
251 if (doze) {
John Spurlocka4215ce2014-08-04 14:50:38 -0400252 ComponentName dozeComponent = getDozeComponent(userId);
John Spurlockeb8d1be2014-06-25 17:46:15 -0400253 return validateDream(dozeComponent) ? dozeComponent : null;
254 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700255 ComponentName[] dreams = getDreamComponentsForUser(userId);
256 return dreams != null && dreams.length != 0 ? dreams[0] : null;
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400257 }
258
John Spurlockeb8d1be2014-06-25 17:46:15 -0400259 private boolean validateDream(ComponentName component) {
260 if (component == null) return false;
261 final ServiceInfo serviceInfo = getServiceInfo(component);
262 if (serviceInfo == null) {
263 Slog.w(TAG, "Dream " + component + " does not exist");
264 return false;
Dianne Hackborn955d8d62014-10-07 20:17:19 -0700265 } else if (serviceInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP
John Spurlockeb8d1be2014-06-25 17:46:15 -0400266 && !BIND_DREAM_SERVICE.equals(serviceInfo.permission)) {
267 Slog.w(TAG, "Dream " + component
268 + " is not available because its manifest is missing the " + BIND_DREAM_SERVICE
269 + " permission on the dream service declaration.");
270 return false;
271 }
272 return true;
273 }
274
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400275 private ComponentName[] getDreamComponentsForUser(int userId) {
276 String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Jeff Brown62c82e42012-09-26 01:30:41 -0700277 Settings.Secure.SCREENSAVER_COMPONENTS,
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400278 userId);
John Spurlockbbdb0622012-12-10 18:15:07 -0500279 ComponentName[] components = componentsFromString(names);
280
281 // first, ensure components point to valid services
282 List<ComponentName> validComponents = new ArrayList<ComponentName>();
283 if (components != null) {
284 for (ComponentName component : components) {
John Spurlockeb8d1be2014-06-25 17:46:15 -0400285 if (validateDream(component)) {
John Spurlockbbdb0622012-12-10 18:15:07 -0500286 validComponents.add(component);
John Spurlockbbdb0622012-12-10 18:15:07 -0500287 }
288 }
289 }
290
291 // fallback to the default dream component if necessary
292 if (validComponents.isEmpty()) {
Jeff Brown567f7ca2014-01-30 23:38:03 -0800293 ComponentName defaultDream = getDefaultDreamComponentForUser(userId);
John Spurlockbbdb0622012-12-10 18:15:07 -0500294 if (defaultDream != null) {
295 Slog.w(TAG, "Falling back to default dream " + defaultDream);
296 validComponents.add(defaultDream);
297 }
298 }
299 return validComponents.toArray(new ComponentName[validComponents.size()]);
300 }
301
Jeff Brown567f7ca2014-01-30 23:38:03 -0800302 private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
303 Settings.Secure.putStringForUser(mContext.getContentResolver(),
304 Settings.Secure.SCREENSAVER_COMPONENTS,
305 componentsToString(componentNames),
306 userId);
307 }
308
309 private ComponentName getDefaultDreamComponentForUser(int userId) {
310 String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
311 Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
312 userId);
313 return name == null ? null : ComponentName.unflattenFromString(name);
314 }
315
Jeff Brown26875502014-01-30 21:47:47 -0800316 private ComponentName getDozeComponent() {
John Spurlocka4215ce2014-08-04 14:50:38 -0400317 return getDozeComponent(ActivityManager.getCurrentUser());
318 }
319
320 private ComponentName getDozeComponent(int userId) {
Jeff Brown26875502014-01-30 21:47:47 -0800321 // Read the component from a system property to facilitate debugging.
322 // Note that for production devices, the dream should actually be declared in
323 // a config.xml resource.
324 String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
325 if (TextUtils.isEmpty(name)) {
326 // Read the component from a config.xml resource.
327 // The value should be specified in a resource overlay for the product.
328 name = mContext.getResources().getString(
329 com.android.internal.R.string.config_dozeComponent);
330 }
John Spurlocka4215ce2014-08-04 14:50:38 -0400331 boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
332 Settings.Secure.DOZE_ENABLED, 1, userId) != 0;
333 return TextUtils.isEmpty(name) || !enabled ? null : ComponentName.unflattenFromString(name);
Jeff Brown26875502014-01-30 21:47:47 -0800334 }
335
John Spurlockeb8d1be2014-06-25 17:46:15 -0400336 private ServiceInfo getServiceInfo(ComponentName name) {
John Spurlockbbdb0622012-12-10 18:15:07 -0500337 try {
John Spurlockeb8d1be2014-06-25 17:46:15 -0400338 return name != null ? mContext.getPackageManager().getServiceInfo(name, 0) : null;
John Spurlockbbdb0622012-12-10 18:15:07 -0500339 } catch (NameNotFoundException e) {
John Spurlockeb8d1be2014-06-25 17:46:15 -0400340 return null;
John Spurlockbbdb0622012-12-10 18:15:07 -0500341 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400342 }
343
Jeff Brown62c82e42012-09-26 01:30:41 -0700344 private void startDreamLocked(final ComponentName name,
Jeff Brown26875502014-01-30 21:47:47 -0800345 final boolean isTest, final boolean canDoze, final int userId) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700346 if (Objects.equal(mCurrentDreamName, name)
347 && mCurrentDreamIsTest == isTest
Jeff Brown26875502014-01-30 21:47:47 -0800348 && mCurrentDreamCanDoze == canDoze
Jeff Brown62c82e42012-09-26 01:30:41 -0700349 && mCurrentDreamUserId == userId) {
350 return;
351 }
352
Jeff Brownf6d46682014-07-17 22:44:20 -0700353 stopDreamLocked(true /*immediate*/);
Jeff Brown62c82e42012-09-26 01:30:41 -0700354
Jeff Brownf6d46682014-07-17 22:44:20 -0700355 Slog.i(TAG, "Entering dreamland.");
Jeff Brown62c82e42012-09-26 01:30:41 -0700356
357 final Binder newToken = new Binder();
358 mCurrentDreamToken = newToken;
359 mCurrentDreamName = name;
360 mCurrentDreamIsTest = isTest;
Jeff Brown26875502014-01-30 21:47:47 -0800361 mCurrentDreamCanDoze = canDoze;
Jeff Brown62c82e42012-09-26 01:30:41 -0700362 mCurrentDreamUserId = userId;
363
364 mHandler.post(new Runnable() {
365 @Override
366 public void run() {
Jeff Brown26875502014-01-30 21:47:47 -0800367 mController.startDream(newToken, name, isTest, canDoze, userId);
Jeff Brown62c82e42012-09-26 01:30:41 -0700368 }
369 });
370 }
371
Jeff Brownf6d46682014-07-17 22:44:20 -0700372 private void stopDreamLocked(final boolean immediate) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700373 if (mCurrentDreamToken != null) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700374 if (immediate) {
375 Slog.i(TAG, "Leaving dreamland.");
376 cleanupDreamLocked();
377 } else if (mCurrentDreamIsWaking) {
378 return; // already waking
379 } else {
380 Slog.i(TAG, "Gently waking up from dream.");
381 mCurrentDreamIsWaking = true;
382 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700383
384 mHandler.post(new Runnable() {
385 @Override
386 public void run() {
Jeff Brownf6d46682014-07-17 22:44:20 -0700387 mController.stopDream(immediate);
Jeff Brown62c82e42012-09-26 01:30:41 -0700388 }
389 });
390 }
391 }
392
393 private void cleanupDreamLocked() {
394 mCurrentDreamToken = null;
395 mCurrentDreamName = null;
396 mCurrentDreamIsTest = false;
Jeff Brown26875502014-01-30 21:47:47 -0800397 mCurrentDreamCanDoze = false;
Jeff Brown62c82e42012-09-26 01:30:41 -0700398 mCurrentDreamUserId = 0;
Jeff Brownf6d46682014-07-17 22:44:20 -0700399 mCurrentDreamIsWaking = false;
Jeff Brown26875502014-01-30 21:47:47 -0800400 if (mCurrentDreamIsDozing) {
401 mCurrentDreamIsDozing = false;
402 mDozeWakeLock.release();
403 }
Jeff Brown970d4132014-07-19 11:33:47 -0700404 mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
405 mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Jeff Brown62c82e42012-09-26 01:30:41 -0700406 }
407
408 private void checkPermission(String permission) {
409 if (mContext.checkCallingOrSelfPermission(permission)
410 != PackageManager.PERMISSION_GRANTED) {
411 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
412 + ", must have permission " + permission);
413 }
414 }
415
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400416 private static String componentsToString(ComponentName[] componentNames) {
417 StringBuilder names = new StringBuilder();
418 if (componentNames != null) {
419 for (ComponentName componentName : componentNames) {
420 if (names.length() > 0) {
421 names.append(',');
422 }
423 names.append(componentName.flattenToString());
424 }
425 }
426 return names.toString();
427 }
428
429 private static ComponentName[] componentsFromString(String names) {
John Spurlockf5df6892012-12-14 13:12:43 -0500430 if (names == null) {
431 return null;
432 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400433 String[] namesArray = names.split(",");
434 ComponentName[] componentNames = new ComponentName[namesArray.length];
435 for (int i = 0; i < namesArray.length; i++) {
436 componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
437 }
438 return componentNames;
439 }
440
Jeff Brown62c82e42012-09-26 01:30:41 -0700441 private final DreamController.Listener mControllerListener = new DreamController.Listener() {
442 @Override
443 public void onDreamStopped(Binder token) {
444 synchronized (mLock) {
445 if (mCurrentDreamToken == token) {
446 cleanupDreamLocked();
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400447 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400448 }
449 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700450 };
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400451
452 /**
453 * Handler for asynchronous operations performed by the dream manager.
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400454 * Ensures operations to {@link DreamController} are single-threaded.
455 */
Jeff Brown62c82e42012-09-26 01:30:41 -0700456 private final class DreamHandler extends Handler {
457 public DreamHandler(Looper looper) {
458 super(looper, null, true /*async*/);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400459 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400460 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800461
462 private final class BinderService extends IDreamManager.Stub {
463 @Override // Binder call
464 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
465 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
466 != PackageManager.PERMISSION_GRANTED) {
467 pw.println("Permission Denial: can't dump DreamManager from from pid="
468 + Binder.getCallingPid()
469 + ", uid=" + Binder.getCallingUid());
470 return;
471 }
472
473 final long ident = Binder.clearCallingIdentity();
474 try {
475 dumpInternal(pw);
476 } finally {
477 Binder.restoreCallingIdentity(ident);
478 }
479 }
480
481 @Override // Binder call
482 public ComponentName[] getDreamComponents() {
483 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
484
485 final int userId = UserHandle.getCallingUserId();
486 final long ident = Binder.clearCallingIdentity();
487 try {
488 return getDreamComponentsForUser(userId);
489 } finally {
490 Binder.restoreCallingIdentity(ident);
491 }
492 }
493
494 @Override // Binder call
495 public void setDreamComponents(ComponentName[] componentNames) {
496 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
497
498 final int userId = UserHandle.getCallingUserId();
499 final long ident = Binder.clearCallingIdentity();
500 try {
501 setDreamComponentsForUser(userId, componentNames);
502 } finally {
503 Binder.restoreCallingIdentity(ident);
504 }
505 }
506
507 @Override // Binder call
508 public ComponentName getDefaultDreamComponent() {
509 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
510
511 final int userId = UserHandle.getCallingUserId();
512 final long ident = Binder.clearCallingIdentity();
513 try {
514 return getDefaultDreamComponentForUser(userId);
515 } finally {
516 Binder.restoreCallingIdentity(ident);
517 }
518 }
519
520 @Override // Binder call
521 public boolean isDreaming() {
522 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
523
524 final long ident = Binder.clearCallingIdentity();
525 try {
526 return isDreamingInternal();
527 } finally {
528 Binder.restoreCallingIdentity(ident);
529 }
530 }
531
532 @Override // Binder call
533 public void dream() {
534 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
535
536 final long ident = Binder.clearCallingIdentity();
537 try {
538 requestDreamInternal();
539 } finally {
540 Binder.restoreCallingIdentity(ident);
541 }
542 }
543
544 @Override // Binder call
545 public void testDream(ComponentName dream) {
546 if (dream == null) {
547 throw new IllegalArgumentException("dream must not be null");
548 }
549 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
550
551 final int callingUserId = UserHandle.getCallingUserId();
552 final int currentUserId = ActivityManager.getCurrentUser();
553 if (callingUserId != currentUserId) {
554 // This check is inherently prone to races but at least it's something.
555 Slog.w(TAG, "Aborted attempt to start a test dream while a different "
556 + " user is active: callingUserId=" + callingUserId
557 + ", currentUserId=" + currentUserId);
558 return;
559 }
560 final long ident = Binder.clearCallingIdentity();
561 try {
562 testDreamInternal(dream, callingUserId);
563 } finally {
564 Binder.restoreCallingIdentity(ident);
565 }
566 }
567
568 @Override // Binder call
569 public void awaken() {
570 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
571
572 final long ident = Binder.clearCallingIdentity();
573 try {
574 requestAwakenInternal();
575 } finally {
576 Binder.restoreCallingIdentity(ident);
577 }
578 }
579
580 @Override // Binder call
Jeff Brownf6d46682014-07-17 22:44:20 -0700581 public void finishSelf(IBinder token, boolean immediate) {
Jeff Brown567f7ca2014-01-30 23:38:03 -0800582 // Requires no permission, called by Dream from an arbitrary process.
583 if (token == null) {
584 throw new IllegalArgumentException("token must not be null");
585 }
586
587 final long ident = Binder.clearCallingIdentity();
588 try {
Jeff Brownf6d46682014-07-17 22:44:20 -0700589 finishSelfInternal(token, immediate);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800590 } finally {
591 Binder.restoreCallingIdentity(ident);
592 }
593 }
Jeff Brown26875502014-01-30 21:47:47 -0800594
595 @Override // Binder call
Jeff Brown970d4132014-07-19 11:33:47 -0700596 public void startDozing(IBinder token, int screenState, int screenBrightness) {
Jeff Brown26875502014-01-30 21:47:47 -0800597 // Requires no permission, called by Dream from an arbitrary process.
598 if (token == null) {
599 throw new IllegalArgumentException("token must not be null");
600 }
601
602 final long ident = Binder.clearCallingIdentity();
603 try {
Jeff Brown970d4132014-07-19 11:33:47 -0700604 startDozingInternal(token, screenState, screenBrightness);
Jeff Brown26875502014-01-30 21:47:47 -0800605 } finally {
606 Binder.restoreCallingIdentity(ident);
607 }
608 }
609
610 @Override // Binder call
611 public void stopDozing(IBinder token) {
612 // Requires no permission, called by Dream from an arbitrary process.
613 if (token == null) {
614 throw new IllegalArgumentException("token must not be null");
615 }
616
617 final long ident = Binder.clearCallingIdentity();
618 try {
619 stopDozingInternal(token);
620 } finally {
621 Binder.restoreCallingIdentity(ident);
622 }
623 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800624 }
625
626 private final class LocalService extends DreamManagerInternal {
627 @Override
Jeff Brown26875502014-01-30 21:47:47 -0800628 public void startDream(boolean doze) {
629 startDreamInternal(doze);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800630 }
631
632 @Override
Jeff Brownf6d46682014-07-17 22:44:20 -0700633 public void stopDream(boolean immediate) {
634 stopDreamInternal(immediate);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800635 }
636
637 @Override
638 public boolean isDreaming() {
639 return isDreamingInternal();
640 }
641 }
Jeff Brown26875502014-01-30 21:47:47 -0800642
John Spurlockbf370992014-06-17 13:58:31 -0400643 private final Runnable mSystemPropertiesChanged = new Runnable() {
644 @Override
645 public void run() {
646 if (DEBUG) Slog.d(TAG, "System properties changed");
Jeff Brownf6d46682014-07-17 22:44:20 -0700647 synchronized (mLock) {
John Spurlockbf370992014-06-17 13:58:31 -0400648 if (mCurrentDreamName != null && mCurrentDreamCanDoze
649 && !mCurrentDreamName.equals(getDozeComponent())) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700650 // May have updated the doze component, wake up
Dianne Hackborn280a64e2015-07-13 14:48:08 -0700651 mPowerManager.wakeUp(SystemClock.uptimeMillis(),
652 "android.server.dreams:SYSPROP");
John Spurlockbf370992014-06-17 13:58:31 -0400653 }
654 }
655 }
656 };
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400657}