blob: 1f6616ee07353810f8a749d351a706199c20294c [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 {
Jeff Sharkey60328372016-03-30 20:42:46 -0600338 return name != null ? mContext.getPackageManager().getServiceInfo(name,
339 PackageManager.MATCH_DEBUG_TRIAGED_MISSING) : null;
John Spurlockbbdb0622012-12-10 18:15:07 -0500340 } catch (NameNotFoundException e) {
John Spurlockeb8d1be2014-06-25 17:46:15 -0400341 return null;
John Spurlockbbdb0622012-12-10 18:15:07 -0500342 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400343 }
344
Jeff Brown62c82e42012-09-26 01:30:41 -0700345 private void startDreamLocked(final ComponentName name,
Jeff Brown26875502014-01-30 21:47:47 -0800346 final boolean isTest, final boolean canDoze, final int userId) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700347 if (Objects.equal(mCurrentDreamName, name)
348 && mCurrentDreamIsTest == isTest
Jeff Brown26875502014-01-30 21:47:47 -0800349 && mCurrentDreamCanDoze == canDoze
Jeff Brown62c82e42012-09-26 01:30:41 -0700350 && mCurrentDreamUserId == userId) {
351 return;
352 }
353
Jeff Brownf6d46682014-07-17 22:44:20 -0700354 stopDreamLocked(true /*immediate*/);
Jeff Brown62c82e42012-09-26 01:30:41 -0700355
Jeff Brownf6d46682014-07-17 22:44:20 -0700356 Slog.i(TAG, "Entering dreamland.");
Jeff Brown62c82e42012-09-26 01:30:41 -0700357
358 final Binder newToken = new Binder();
359 mCurrentDreamToken = newToken;
360 mCurrentDreamName = name;
361 mCurrentDreamIsTest = isTest;
Jeff Brown26875502014-01-30 21:47:47 -0800362 mCurrentDreamCanDoze = canDoze;
Jeff Brown62c82e42012-09-26 01:30:41 -0700363 mCurrentDreamUserId = userId;
364
365 mHandler.post(new Runnable() {
366 @Override
367 public void run() {
Jeff Brown26875502014-01-30 21:47:47 -0800368 mController.startDream(newToken, name, isTest, canDoze, userId);
Jeff Brown62c82e42012-09-26 01:30:41 -0700369 }
370 });
371 }
372
Jeff Brownf6d46682014-07-17 22:44:20 -0700373 private void stopDreamLocked(final boolean immediate) {
Jeff Brown62c82e42012-09-26 01:30:41 -0700374 if (mCurrentDreamToken != null) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700375 if (immediate) {
376 Slog.i(TAG, "Leaving dreamland.");
377 cleanupDreamLocked();
378 } else if (mCurrentDreamIsWaking) {
379 return; // already waking
380 } else {
381 Slog.i(TAG, "Gently waking up from dream.");
382 mCurrentDreamIsWaking = true;
383 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700384
385 mHandler.post(new Runnable() {
386 @Override
387 public void run() {
Jeff Brownf6d46682014-07-17 22:44:20 -0700388 mController.stopDream(immediate);
Jeff Brown62c82e42012-09-26 01:30:41 -0700389 }
390 });
391 }
392 }
393
394 private void cleanupDreamLocked() {
395 mCurrentDreamToken = null;
396 mCurrentDreamName = null;
397 mCurrentDreamIsTest = false;
Jeff Brown26875502014-01-30 21:47:47 -0800398 mCurrentDreamCanDoze = false;
Jeff Brown62c82e42012-09-26 01:30:41 -0700399 mCurrentDreamUserId = 0;
Jeff Brownf6d46682014-07-17 22:44:20 -0700400 mCurrentDreamIsWaking = false;
Jeff Brown26875502014-01-30 21:47:47 -0800401 if (mCurrentDreamIsDozing) {
402 mCurrentDreamIsDozing = false;
403 mDozeWakeLock.release();
404 }
Jeff Brown970d4132014-07-19 11:33:47 -0700405 mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
406 mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Jeff Brown62c82e42012-09-26 01:30:41 -0700407 }
408
409 private void checkPermission(String permission) {
410 if (mContext.checkCallingOrSelfPermission(permission)
411 != PackageManager.PERMISSION_GRANTED) {
412 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
413 + ", must have permission " + permission);
414 }
415 }
416
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400417 private static String componentsToString(ComponentName[] componentNames) {
418 StringBuilder names = new StringBuilder();
419 if (componentNames != null) {
420 for (ComponentName componentName : componentNames) {
421 if (names.length() > 0) {
422 names.append(',');
423 }
424 names.append(componentName.flattenToString());
425 }
426 }
427 return names.toString();
428 }
429
430 private static ComponentName[] componentsFromString(String names) {
John Spurlockf5df6892012-12-14 13:12:43 -0500431 if (names == null) {
432 return null;
433 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400434 String[] namesArray = names.split(",");
435 ComponentName[] componentNames = new ComponentName[namesArray.length];
436 for (int i = 0; i < namesArray.length; i++) {
437 componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
438 }
439 return componentNames;
440 }
441
Jeff Brown62c82e42012-09-26 01:30:41 -0700442 private final DreamController.Listener mControllerListener = new DreamController.Listener() {
443 @Override
444 public void onDreamStopped(Binder token) {
445 synchronized (mLock) {
446 if (mCurrentDreamToken == token) {
447 cleanupDreamLocked();
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400448 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400449 }
450 }
Jeff Brown62c82e42012-09-26 01:30:41 -0700451 };
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400452
453 /**
454 * Handler for asynchronous operations performed by the dream manager.
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400455 * Ensures operations to {@link DreamController} are single-threaded.
456 */
Jeff Brown62c82e42012-09-26 01:30:41 -0700457 private final class DreamHandler extends Handler {
458 public DreamHandler(Looper looper) {
459 super(looper, null, true /*async*/);
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400460 }
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400461 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800462
463 private final class BinderService extends IDreamManager.Stub {
464 @Override // Binder call
465 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
466 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
467 != PackageManager.PERMISSION_GRANTED) {
468 pw.println("Permission Denial: can't dump DreamManager from from pid="
469 + Binder.getCallingPid()
470 + ", uid=" + Binder.getCallingUid());
471 return;
472 }
473
474 final long ident = Binder.clearCallingIdentity();
475 try {
476 dumpInternal(pw);
477 } finally {
478 Binder.restoreCallingIdentity(ident);
479 }
480 }
481
482 @Override // Binder call
483 public ComponentName[] getDreamComponents() {
484 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
485
486 final int userId = UserHandle.getCallingUserId();
487 final long ident = Binder.clearCallingIdentity();
488 try {
489 return getDreamComponentsForUser(userId);
490 } finally {
491 Binder.restoreCallingIdentity(ident);
492 }
493 }
494
495 @Override // Binder call
496 public void setDreamComponents(ComponentName[] componentNames) {
497 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
498
499 final int userId = UserHandle.getCallingUserId();
500 final long ident = Binder.clearCallingIdentity();
501 try {
502 setDreamComponentsForUser(userId, componentNames);
503 } finally {
504 Binder.restoreCallingIdentity(ident);
505 }
506 }
507
508 @Override // Binder call
509 public ComponentName getDefaultDreamComponent() {
510 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
511
512 final int userId = UserHandle.getCallingUserId();
513 final long ident = Binder.clearCallingIdentity();
514 try {
515 return getDefaultDreamComponentForUser(userId);
516 } finally {
517 Binder.restoreCallingIdentity(ident);
518 }
519 }
520
521 @Override // Binder call
522 public boolean isDreaming() {
523 checkPermission(android.Manifest.permission.READ_DREAM_STATE);
524
525 final long ident = Binder.clearCallingIdentity();
526 try {
527 return isDreamingInternal();
528 } finally {
529 Binder.restoreCallingIdentity(ident);
530 }
531 }
532
533 @Override // Binder call
534 public void dream() {
535 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
536
537 final long ident = Binder.clearCallingIdentity();
538 try {
539 requestDreamInternal();
540 } finally {
541 Binder.restoreCallingIdentity(ident);
542 }
543 }
544
545 @Override // Binder call
546 public void testDream(ComponentName dream) {
547 if (dream == null) {
548 throw new IllegalArgumentException("dream must not be null");
549 }
550 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
551
552 final int callingUserId = UserHandle.getCallingUserId();
553 final int currentUserId = ActivityManager.getCurrentUser();
554 if (callingUserId != currentUserId) {
555 // This check is inherently prone to races but at least it's something.
556 Slog.w(TAG, "Aborted attempt to start a test dream while a different "
557 + " user is active: callingUserId=" + callingUserId
558 + ", currentUserId=" + currentUserId);
559 return;
560 }
561 final long ident = Binder.clearCallingIdentity();
562 try {
563 testDreamInternal(dream, callingUserId);
564 } finally {
565 Binder.restoreCallingIdentity(ident);
566 }
567 }
568
569 @Override // Binder call
570 public void awaken() {
571 checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
572
573 final long ident = Binder.clearCallingIdentity();
574 try {
575 requestAwakenInternal();
576 } finally {
577 Binder.restoreCallingIdentity(ident);
578 }
579 }
580
581 @Override // Binder call
Jeff Brownf6d46682014-07-17 22:44:20 -0700582 public void finishSelf(IBinder token, boolean immediate) {
Jeff Brown567f7ca2014-01-30 23:38:03 -0800583 // Requires no permission, called by Dream from an arbitrary process.
584 if (token == null) {
585 throw new IllegalArgumentException("token must not be null");
586 }
587
588 final long ident = Binder.clearCallingIdentity();
589 try {
Jeff Brownf6d46682014-07-17 22:44:20 -0700590 finishSelfInternal(token, immediate);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800591 } finally {
592 Binder.restoreCallingIdentity(ident);
593 }
594 }
Jeff Brown26875502014-01-30 21:47:47 -0800595
596 @Override // Binder call
Jeff Brown970d4132014-07-19 11:33:47 -0700597 public void startDozing(IBinder token, int screenState, int screenBrightness) {
Jeff Brown26875502014-01-30 21:47:47 -0800598 // Requires no permission, called by Dream from an arbitrary process.
599 if (token == null) {
600 throw new IllegalArgumentException("token must not be null");
601 }
602
603 final long ident = Binder.clearCallingIdentity();
604 try {
Jeff Brown970d4132014-07-19 11:33:47 -0700605 startDozingInternal(token, screenState, screenBrightness);
Jeff Brown26875502014-01-30 21:47:47 -0800606 } finally {
607 Binder.restoreCallingIdentity(ident);
608 }
609 }
610
611 @Override // Binder call
612 public void stopDozing(IBinder token) {
613 // Requires no permission, called by Dream from an arbitrary process.
614 if (token == null) {
615 throw new IllegalArgumentException("token must not be null");
616 }
617
618 final long ident = Binder.clearCallingIdentity();
619 try {
620 stopDozingInternal(token);
621 } finally {
622 Binder.restoreCallingIdentity(ident);
623 }
624 }
Jeff Brown567f7ca2014-01-30 23:38:03 -0800625 }
626
627 private final class LocalService extends DreamManagerInternal {
628 @Override
Jeff Brown26875502014-01-30 21:47:47 -0800629 public void startDream(boolean doze) {
630 startDreamInternal(doze);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800631 }
632
633 @Override
Jeff Brownf6d46682014-07-17 22:44:20 -0700634 public void stopDream(boolean immediate) {
635 stopDreamInternal(immediate);
Jeff Brown567f7ca2014-01-30 23:38:03 -0800636 }
637
638 @Override
639 public boolean isDreaming() {
640 return isDreamingInternal();
641 }
642 }
Jeff Brown26875502014-01-30 21:47:47 -0800643
John Spurlockbf370992014-06-17 13:58:31 -0400644 private final Runnable mSystemPropertiesChanged = new Runnable() {
645 @Override
646 public void run() {
647 if (DEBUG) Slog.d(TAG, "System properties changed");
Jeff Brownf6d46682014-07-17 22:44:20 -0700648 synchronized (mLock) {
John Spurlockbf370992014-06-17 13:58:31 -0400649 if (mCurrentDreamName != null && mCurrentDreamCanDoze
650 && !mCurrentDreamName.equals(getDozeComponent())) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700651 // May have updated the doze component, wake up
Dianne Hackborn280a64e2015-07-13 14:48:08 -0700652 mPowerManager.wakeUp(SystemClock.uptimeMillis(),
653 "android.server.dreams:SYSPROP");
John Spurlockbf370992014-06-17 13:58:31 -0400654 }
655 }
656 }
657 };
John Spurlockf4f6b4c2012-08-25 12:08:03 -0400658}