blob: fd2f8a151f85a221e3b33ff9e9f5a2d489e34889 [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
Jeff Brown62c82e42012-09-26 01:30:41 -070019import com.android.internal.util.DumpUtils;
Jeff Brown4ccb8232014-01-16 22:16:42 -080020import com.android.server.FgThread;
Jeff Brown567f7ca2014-01-30 23:38:03 -080021import com.android.server.SystemService;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040022
Jeff Brown567f7ca2014-01-30 23:38:03 -080023import android.Manifest;
Jeff Brown62c82e42012-09-26 01:30:41 -070024import android.app.ActivityManager;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040025import android.content.BroadcastReceiver;
26import android.content.ComponentName;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040030import android.content.pm.PackageManager;
John Spurlockbbdb0622012-12-10 18:15:07 -050031import android.content.pm.PackageManager.NameNotFoundException;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040032import android.os.Binder;
Jeff Brown26875502014-01-30 21:47:47 -080033import android.os.Build;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040034import android.os.Handler;
35import android.os.IBinder;
Jeff Brown62c82e42012-09-26 01:30:41 -070036import android.os.Looper;
37import android.os.PowerManager;
38import android.os.SystemClock;
Jeff Brown26875502014-01-30 21:47:47 -080039import android.os.SystemProperties;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040040import android.os.UserHandle;
41import android.provider.Settings;
Jeff Brown567f7ca2014-01-30 23:38:03 -080042import android.service.dreams.DreamManagerInternal;
43import android.service.dreams.DreamService;
Jeff Brown26875502014-01-30 21:47:47 -080044import android.service.dreams.IDozeHardware;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040045import android.service.dreams.IDreamManager;
Jeff Brown26875502014-01-30 21:47:47 -080046import android.text.TextUtils;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040047import android.util.Slog;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040048
49import java.io.FileDescriptor;
50import java.io.PrintWriter;
John Spurlockbbdb0622012-12-10 18:15:07 -050051import java.util.ArrayList;
52import java.util.List;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040053
Jeff Brown62c82e42012-09-26 01:30:41 -070054import libcore.util.Objects;
55
John Spurlockf4f6b4c2012-08-25 12:08:03 -040056/**
57 * Service api for managing dreams.
58 *
59 * @hide
60 */
Jeff Brown567f7ca2014-01-30 23:38:03 -080061public final class DreamManagerService extends SystemService {
Dianne Hackborn40e9f292012-11-27 19:12:23 -080062 private static final boolean DEBUG = false;
Jeff Brown62c82e42012-09-26 01:30:41 -070063 private static final String TAG = "DreamManagerService";
John Spurlockf4f6b4c2012-08-25 12:08:03 -040064
65 private final Object mLock = new Object();
Jeff Brown62c82e42012-09-26 01:30:41 -070066
John Spurlockf4f6b4c2012-08-25 12:08:03 -040067 private final Context mContext;
Jeff Brown62c82e42012-09-26 01:30:41 -070068 private final DreamHandler mHandler;
69 private final DreamController mController;
70 private final PowerManager mPowerManager;
Jeff Brown26875502014-01-30 21:47:47 -080071 private final PowerManager.WakeLock mDozeWakeLock;
72 private final McuHal mMcuHal; // synchronized on self
John Spurlockf4f6b4c2012-08-25 12:08:03 -040073
Jeff Brown62c82e42012-09-26 01:30:41 -070074 private Binder mCurrentDreamToken;
75 private ComponentName mCurrentDreamName;
76 private int mCurrentDreamUserId;
77 private boolean mCurrentDreamIsTest;
Jeff Brown26875502014-01-30 21:47:47 -080078 private boolean mCurrentDreamCanDoze;
79 private boolean mCurrentDreamIsDozing;
80 private DozeHardwareWrapper mCurrentDreamDozeHardware;
John Spurlockf4f6b4c2012-08-25 12:08:03 -040081
Jeff Brown4ccb8232014-01-16 22:16:42 -080082 public DreamManagerService(Context context) {
Jeff Brown567f7ca2014-01-30 23:38:03 -080083 super(context);
John Spurlockf4f6b4c2012-08-25 12:08:03 -040084 mContext = context;
Jeff Brown4ccb8232014-01-16 22:16:42 -080085 mHandler = new DreamHandler(FgThread.get().getLooper());
Jeff Brown62c82e42012-09-26 01:30:41 -070086 mController = new DreamController(context, mHandler, mControllerListener);
87
88 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Jeff Brown26875502014-01-30 21:47:47 -080089 mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
90
91 mMcuHal = McuHal.open();
92 if (mMcuHal != null) {
93 mMcuHal.reset();
94 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -040095 }
96
Jeff Brown567f7ca2014-01-30 23:38:03 -080097 @Override
98 public void onStart() {
99 publishBinderService(DreamService.DREAM_SERVICE, new BinderService());
100 publishLocalService(DreamManagerInternal.class, new LocalService());
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400101 }
102
103 @Override
Jeff Brown567f7ca2014-01-30 23:38:03 -0800104 public void onBootPhase(int phase) {
105 if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
106 mContext.registerReceiver(new BroadcastReceiver() {
107 @Override
108 public void onReceive(Context context, Intent intent) {
109 synchronized (mLock) {
110 stopDreamLocked();
111 }
112 }
113 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
John Spurlockda5b6f22013-08-14 09:46:52 -0400114 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800115 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400116
Jeff Brown567f7ca2014-01-30 23:38:03 -0800117 private void dumpInternal(PrintWriter pw) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700118 pw.println("DREAM MANAGER (dumpsys dreams)");
119 pw.println();
120
Jeff Brown26875502014-01-30 21:47:47 -0800121 pw.println("mMcuHal=" + mMcuHal);
122 pw.println();
Jeff Brown62c82e42012-09-26 01:30:41 -0700123 pw.println("mCurrentDreamToken=" + mCurrentDreamToken);
124 pw.println("mCurrentDreamName=" + mCurrentDreamName);
125 pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId);
126 pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest);
Jeff Brown26875502014-01-30 21:47:47 -0800127 pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze);
128 pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing);
129 pw.println("mCurrentDreamDozeHardware=" + mCurrentDreamDozeHardware);
Jeff Brown62c82e42012-09-26 01:30:41 -0700130 pw.println();
131
132 DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
133 @Override
134 public void dump(PrintWriter pw) {
135 mController.dump(pw);
136 }
137 }, pw, 200);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400138 }
139
Jeff Brown567f7ca2014-01-30 23:38:03 -0800140 private boolean isDreamingInternal() {
Jeff Brown62c82e42012-09-26 01:30:41 -0700141 synchronized (mLock) {
142 return mCurrentDreamToken != null && !mCurrentDreamIsTest;
143 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400144 }
145
Jeff Brown567f7ca2014-01-30 23:38:03 -0800146 private void requestDreamInternal() {
147 // Ask the power manager to nap. It will eventually call back into
148 // startDream() if/when it is appropriate to start dreaming.
149 // Because napping could cause the screen to turn off immediately if the dream
150 // cannot be started, we keep one eye open and gently poke user activity.
151 long time = SystemClock.uptimeMillis();
152 mPowerManager.userActivity(time, true /*noChangeLights*/);
153 mPowerManager.nap(time);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400154 }
155
Jeff Brown567f7ca2014-01-30 23:38:03 -0800156 private void requestAwakenInternal() {
157 // Treat an explicit request to awaken as user activity so that the
158 // device doesn't immediately go to sleep if the timeout expired,
159 // for example when being undocked.
160 long time = SystemClock.uptimeMillis();
161 mPowerManager.userActivity(time, false /*noChangeLights*/);
162 stopDreamInternal();
163 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400164
Jeff Brown567f7ca2014-01-30 23:38:03 -0800165 private void finishSelfInternal(IBinder token) {
166 if (DEBUG) {
167 Slog.d(TAG, "Dream finished: " + token);
Jeff Brown62c82e42012-09-26 01:30:41 -0700168 }
169
Jeff Brown567f7ca2014-01-30 23:38:03 -0800170 // Note that a dream finishing and self-terminating is not
171 // itself considered user activity. If the dream is ending because
172 // the user interacted with the device then user activity will already
173 // have been poked so the device will stay awake a bit longer.
174 // If the dream is ending on its own for other reasons and no wake
175 // locks are held and the user activity timeout has expired then the
176 // device may simply go to sleep.
177 synchronized (mLock) {
178 if (mCurrentDreamToken == token) {
179 stopDreamLocked();
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400180 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400181 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400182 }
183
Jeff Brown567f7ca2014-01-30 23:38:03 -0800184 private void testDreamInternal(ComponentName dream, int userId) {
185 synchronized (mLock) {
Jeff Brown26875502014-01-30 21:47:47 -0800186 startDreamLocked(dream, true /*isTest*/, false /*canDoze*/, userId);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400187 }
188 }
189
Jeff Brown26875502014-01-30 21:47:47 -0800190 private void startDreamInternal(boolean doze) {
191 final int userId = ActivityManager.getCurrentUser();
192 final ComponentName dream = doze ? getDozeComponent() : chooseDreamForUser(userId);
Jeff Brown62c82e42012-09-26 01:30:41 -0700193 if (dream != null) {
194 synchronized (mLock) {
Jeff Brown26875502014-01-30 21:47:47 -0800195 startDreamLocked(dream, false /*isTest*/, doze, userId);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400196 }
197 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700198 }
199
Jeff Brown567f7ca2014-01-30 23:38:03 -0800200 private void stopDreamInternal() {
Jeff Brown62c82e42012-09-26 01:30:41 -0700201 synchronized (mLock) {
202 stopDreamLocked();
203 }
204 }
205
Jeff Brown26875502014-01-30 21:47:47 -0800206 private void startDozingInternal(IBinder token) {
207 if (DEBUG) {
208 Slog.d(TAG, "Dream requested to start dozing: " + token);
209 }
210
211 synchronized (mLock) {
212 if (mCurrentDreamToken == token && mCurrentDreamCanDoze
213 && !mCurrentDreamIsDozing) {
214 mCurrentDreamIsDozing = true;
215 mDozeWakeLock.acquire();
216 }
217 }
218 }
219
220 private void stopDozingInternal(IBinder token) {
221 if (DEBUG) {
222 Slog.d(TAG, "Dream requested to stop dozing: " + token);
223 }
224
225 synchronized (mLock) {
226 if (mCurrentDreamToken == token && mCurrentDreamIsDozing) {
227 mCurrentDreamIsDozing = false;
228 mDozeWakeLock.release();
229 }
230 }
231 }
232
233 private IDozeHardware getDozeHardwareInternal(IBinder token) {
234 synchronized (mLock) {
235 if (mCurrentDreamToken == token && mCurrentDreamCanDoze
236 && mCurrentDreamDozeHardware == null && mMcuHal != null) {
237 mCurrentDreamDozeHardware = new DozeHardwareWrapper();
238 return mCurrentDreamDozeHardware;
239 }
240 return null;
241 }
242 }
243
Jeff Brown62c82e42012-09-26 01:30:41 -0700244 private ComponentName chooseDreamForUser(int userId) {
245 ComponentName[] dreams = getDreamComponentsForUser(userId);
246 return dreams != null && dreams.length != 0 ? dreams[0] : null;
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400247 }
248
249 private ComponentName[] getDreamComponentsForUser(int userId) {
250 String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Jeff Brown62c82e42012-09-26 01:30:41 -0700251 Settings.Secure.SCREENSAVER_COMPONENTS,
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400252 userId);
John Spurlockbbdb0622012-12-10 18:15:07 -0500253 ComponentName[] components = componentsFromString(names);
254
255 // first, ensure components point to valid services
256 List<ComponentName> validComponents = new ArrayList<ComponentName>();
257 if (components != null) {
258 for (ComponentName component : components) {
259 if (serviceExists(component)) {
260 validComponents.add(component);
261 } else {
262 Slog.w(TAG, "Dream " + component + " does not exist");
263 }
264 }
265 }
266
267 // fallback to the default dream component if necessary
268 if (validComponents.isEmpty()) {
Jeff Brown567f7ca2014-01-30 23:38:03 -0800269 ComponentName defaultDream = getDefaultDreamComponentForUser(userId);
John Spurlockbbdb0622012-12-10 18:15:07 -0500270 if (defaultDream != null) {
271 Slog.w(TAG, "Falling back to default dream " + defaultDream);
272 validComponents.add(defaultDream);
273 }
274 }
275 return validComponents.toArray(new ComponentName[validComponents.size()]);
276 }
277
Jeff Brown567f7ca2014-01-30 23:38:03 -0800278 private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
279 Settings.Secure.putStringForUser(mContext.getContentResolver(),
280 Settings.Secure.SCREENSAVER_COMPONENTS,
281 componentsToString(componentNames),
282 userId);
283 }
284
285 private ComponentName getDefaultDreamComponentForUser(int userId) {
286 String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
287 Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
288 userId);
289 return name == null ? null : ComponentName.unflattenFromString(name);
290 }
291
Jeff Brown26875502014-01-30 21:47:47 -0800292 private ComponentName getDozeComponent() {
293 // Read the component from a system property to facilitate debugging.
294 // Note that for production devices, the dream should actually be declared in
295 // a config.xml resource.
296 String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
297 if (TextUtils.isEmpty(name)) {
298 // Read the component from a config.xml resource.
299 // The value should be specified in a resource overlay for the product.
300 name = mContext.getResources().getString(
301 com.android.internal.R.string.config_dozeComponent);
302 }
303 return TextUtils.isEmpty(name) ? null : ComponentName.unflattenFromString(name);
304 }
305
John Spurlockbbdb0622012-12-10 18:15:07 -0500306 private boolean serviceExists(ComponentName name) {
307 try {
308 return name != null && mContext.getPackageManager().getServiceInfo(name, 0) != null;
309 } catch (NameNotFoundException e) {
310 return false;
311 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400312 }
313
Jeff Brown62c82e42012-09-26 01:30:41 -0700314 private void startDreamLocked(final ComponentName name,
Jeff Brown26875502014-01-30 21:47:47 -0800315 final boolean isTest, final boolean canDoze, final int userId) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700316 if (Objects.equal(mCurrentDreamName, name)
317 && mCurrentDreamIsTest == isTest
Jeff Brown26875502014-01-30 21:47:47 -0800318 && mCurrentDreamCanDoze == canDoze
Jeff Brown62c82e42012-09-26 01:30:41 -0700319 && mCurrentDreamUserId == userId) {
320 return;
321 }
322
323 stopDreamLocked();
324
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800325 if (DEBUG) Slog.i(TAG, "Entering dreamland.");
Jeff Brown62c82e42012-09-26 01:30:41 -0700326
327 final Binder newToken = new Binder();
328 mCurrentDreamToken = newToken;
329 mCurrentDreamName = name;
330 mCurrentDreamIsTest = isTest;
Jeff Brown26875502014-01-30 21:47:47 -0800331 mCurrentDreamCanDoze = canDoze;
Jeff Brown62c82e42012-09-26 01:30:41 -0700332 mCurrentDreamUserId = userId;
333
334 mHandler.post(new Runnable() {
335 @Override
336 public void run() {
Jeff Brown26875502014-01-30 21:47:47 -0800337 mController.startDream(newToken, name, isTest, canDoze, userId);
Jeff Brown62c82e42012-09-26 01:30:41 -0700338 }
339 });
340 }
341
342 private void stopDreamLocked() {
343 if (mCurrentDreamToken != null) {
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800344 if (DEBUG) Slog.i(TAG, "Leaving dreamland.");
Jeff Brown62c82e42012-09-26 01:30:41 -0700345
346 cleanupDreamLocked();
347
348 mHandler.post(new Runnable() {
349 @Override
350 public void run() {
351 mController.stopDream();
352 }
353 });
354 }
355 }
356
357 private void cleanupDreamLocked() {
358 mCurrentDreamToken = null;
359 mCurrentDreamName = null;
360 mCurrentDreamIsTest = false;
Jeff Brown26875502014-01-30 21:47:47 -0800361 mCurrentDreamCanDoze = false;
Jeff Brown62c82e42012-09-26 01:30:41 -0700362 mCurrentDreamUserId = 0;
Jeff Brown26875502014-01-30 21:47:47 -0800363 if (mCurrentDreamIsDozing) {
364 mCurrentDreamIsDozing = false;
365 mDozeWakeLock.release();
366 }
367 if (mCurrentDreamDozeHardware != null) {
368 mCurrentDreamDozeHardware.release();
369 mCurrentDreamDozeHardware = null;
370 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700371 }
372
373 private void checkPermission(String permission) {
374 if (mContext.checkCallingOrSelfPermission(permission)
375 != PackageManager.PERMISSION_GRANTED) {
376 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
377 + ", must have permission " + permission);
378 }
379 }
380
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400381 private static String componentsToString(ComponentName[] componentNames) {
382 StringBuilder names = new StringBuilder();
383 if (componentNames != null) {
384 for (ComponentName componentName : componentNames) {
385 if (names.length() > 0) {
386 names.append(',');
387 }
388 names.append(componentName.flattenToString());
389 }
390 }
391 return names.toString();
392 }
393
394 private static ComponentName[] componentsFromString(String names) {
John Spurlockf5df6892012-12-14 13:12:43 -0500395 if (names == null) {
396 return null;
397 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400398 String[] namesArray = names.split(",");
399 ComponentName[] componentNames = new ComponentName[namesArray.length];
400 for (int i = 0; i < namesArray.length; i++) {
401 componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
402 }
403 return componentNames;
404 }
405
Jeff Brown62c82e42012-09-26 01:30:41 -0700406 private final DreamController.Listener mControllerListener = new DreamController.Listener() {
407 @Override
408 public void onDreamStopped(Binder token) {
409 synchronized (mLock) {
410 if (mCurrentDreamToken == token) {
411 cleanupDreamLocked();
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400412 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400413 }
414 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700415 };
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400416
417 /**
418 * Handler for asynchronous operations performed by the dream manager.
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400419 * Ensures operations to {@link DreamController} are single-threaded.
420 */
Jeff Brown62c82e42012-09-26 01:30:41 -0700421 private final class DreamHandler extends Handler {
422 public DreamHandler(Looper looper) {
423 super(looper, null, true /*async*/);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400424 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400425 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800426
427 private final class BinderService extends IDreamManager.Stub {
428 @Override // Binder call
429 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
430 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
431 != PackageManager.PERMISSION_GRANTED) {
432 pw.println("Permission Denial: can't dump DreamManager from from pid="
433 + Binder.getCallingPid()
434 + ", uid=" + Binder.getCallingUid());
435 return;
436 }
437
438 final long ident = Binder.clearCallingIdentity();
439 try {
440 dumpInternal(pw);
441 } finally {
442 Binder.restoreCallingIdentity(ident);
443 }
444 }
445
446 @Override // Binder call
447 public ComponentName[] getDreamComponents() {
448 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
449
450 final int userId = UserHandle.getCallingUserId();
451 final long ident = Binder.clearCallingIdentity();
452 try {
453 return getDreamComponentsForUser(userId);
454 } finally {
455 Binder.restoreCallingIdentity(ident);
456 }
457 }
458
459 @Override // Binder call
460 public void setDreamComponents(ComponentName[] componentNames) {
461 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
462
463 final int userId = UserHandle.getCallingUserId();
464 final long ident = Binder.clearCallingIdentity();
465 try {
466 setDreamComponentsForUser(userId, componentNames);
467 } finally {
468 Binder.restoreCallingIdentity(ident);
469 }
470 }
471
472 @Override // Binder call
473 public ComponentName getDefaultDreamComponent() {
474 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
475
476 final int userId = UserHandle.getCallingUserId();
477 final long ident = Binder.clearCallingIdentity();
478 try {
479 return getDefaultDreamComponentForUser(userId);
480 } finally {
481 Binder.restoreCallingIdentity(ident);
482 }
483 }
484
485 @Override // Binder call
486 public boolean isDreaming() {
487 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
488
489 final long ident = Binder.clearCallingIdentity();
490 try {
491 return isDreamingInternal();
492 } finally {
493 Binder.restoreCallingIdentity(ident);
494 }
495 }
496
497 @Override // Binder call
498 public void dream() {
499 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
500
501 final long ident = Binder.clearCallingIdentity();
502 try {
503 requestDreamInternal();
504 } finally {
505 Binder.restoreCallingIdentity(ident);
506 }
507 }
508
509 @Override // Binder call
510 public void testDream(ComponentName dream) {
511 if (dream == null) {
512 throw new IllegalArgumentException("dream must not be null");
513 }
514 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
515
516 final int callingUserId = UserHandle.getCallingUserId();
517 final int currentUserId = ActivityManager.getCurrentUser();
518 if (callingUserId != currentUserId) {
519 // This check is inherently prone to races but at least it's something.
520 Slog.w(TAG, "Aborted attempt to start a test dream while a different "
521 + " user is active: callingUserId=" + callingUserId
522 + ", currentUserId=" + currentUserId);
523 return;
524 }
525 final long ident = Binder.clearCallingIdentity();
526 try {
527 testDreamInternal(dream, callingUserId);
528 } finally {
529 Binder.restoreCallingIdentity(ident);
530 }
531 }
532
533 @Override // Binder call
534 public void awaken() {
535 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
536
537 final long ident = Binder.clearCallingIdentity();
538 try {
539 requestAwakenInternal();
540 } finally {
541 Binder.restoreCallingIdentity(ident);
542 }
543 }
544
545 @Override // Binder call
546 public void finishSelf(IBinder token) {
547 // Requires no permission, called by Dream from an arbitrary process.
548 if (token == null) {
549 throw new IllegalArgumentException("token must not be null");
550 }
551
552 final long ident = Binder.clearCallingIdentity();
553 try {
554 finishSelfInternal(token);
555 } finally {
556 Binder.restoreCallingIdentity(ident);
557 }
558 }
Jeff Brown26875502014-01-30 21:47:47 -0800559
560 @Override // Binder call
561 public void startDozing(IBinder token) {
562 // Requires no permission, called by Dream from an arbitrary process.
563 if (token == null) {
564 throw new IllegalArgumentException("token must not be null");
565 }
566
567 final long ident = Binder.clearCallingIdentity();
568 try {
569 startDozingInternal(token);
570 } finally {
571 Binder.restoreCallingIdentity(ident);
572 }
573 }
574
575 @Override // Binder call
576 public void stopDozing(IBinder token) {
577 // Requires no permission, called by Dream from an arbitrary process.
578 if (token == null) {
579 throw new IllegalArgumentException("token must not be null");
580 }
581
582 final long ident = Binder.clearCallingIdentity();
583 try {
584 stopDozingInternal(token);
585 } finally {
586 Binder.restoreCallingIdentity(ident);
587 }
588 }
589
590 @Override // Binder call
591 public IDozeHardware getDozeHardware(IBinder token) {
592 // Requires no permission, called by Dream from an arbitrary process.
593 if (token == null) {
594 throw new IllegalArgumentException("token must not be null");
595 }
596
597 final long ident = Binder.clearCallingIdentity();
598 try {
599 return getDozeHardwareInternal(token);
600 } finally {
601 Binder.restoreCallingIdentity(ident);
602 }
603 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800604 }
605
606 private final class LocalService extends DreamManagerInternal {
607 @Override
Jeff Brown26875502014-01-30 21:47:47 -0800608 public void startDream(boolean doze) {
609 startDreamInternal(doze);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800610 }
611
612 @Override
613 public void stopDream() {
614 stopDreamInternal();
615 }
616
617 @Override
618 public boolean isDreaming() {
619 return isDreamingInternal();
620 }
621 }
Jeff Brown26875502014-01-30 21:47:47 -0800622
623 private final class DozeHardwareWrapper extends IDozeHardware.Stub {
624 private boolean mReleased;
625
626 public void release() {
627 synchronized (mMcuHal) {
628 if (!mReleased) {
629 mReleased = true;
630 mMcuHal.reset();
631 }
632 }
633 }
634
635 @Override // Binder call
636 public byte[] sendMessage(String msg, byte[] arg) {
637 if (msg == null) {
638 throw new IllegalArgumentException("msg must not be null");
639 }
640
641 final long ident = Binder.clearCallingIdentity();
642 try {
643 synchronized (mMcuHal) {
644 if (mReleased) {
645 throw new IllegalStateException("This operation cannot be performed "
646 + "because the dream has ended.");
647 }
648 return mMcuHal.sendMessage(msg, arg);
649 }
650 } finally {
651 Binder.restoreCallingIdentity(ident);
652 }
653 }
654 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400655}