Skip to content

Commit 62c82e4

Browse files
author
Jeff Brown
committed
Make DreamManagerService more robust.
Clearly isolated the DreamManagerService and DreamController responsibilities. DreamManagerService contains just enough logic to manage the global synchronous behaviors. All of the asynchronous behaviors are in DreamController. Added a new PowerManager function called nap() to request the device to start napping. If it is a good time to nap, then the PowerManagerService will call startDream() on the DreamManagerService to start dreaming. Fixed a possible multi-user issue by explicitly tracking for which user a dream service is being started and stopping dreams when the current user changes. The user id is also passed to bindService() to ensure that the dream has the right environment. Fix interactions with docks and the UI mode manager. It is important that we always send the ACTION_DOCK_EVENT broadcast to the system so that it can configure audio routing and the like. When docked, the UI mode manager starts a dock app if there is one, otherwise it starts a dream. This change resolves issues with dreams started for reasons other than a user activity timeout. Bug: 7204211 Change-Id: I3193cc8190982c0836319176fa2e9c4dcad9c01f
1 parent cef440f commit 62c82e4

File tree

13 files changed

+615
-577
lines changed

13 files changed

+615
-577
lines changed

core/java/android/os/IPowerManager.aidl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ interface IPowerManager
3434
void userActivity(long time, int event, int flags);
3535
void wakeUp(long time);
3636
void goToSleep(long time, int reason);
37+
void nap(long time);
3738

3839
boolean isScreenOn();
3940
void reboot(String reason);

core/java/android/os/PowerManager.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ public static void validateWakeLockParameters(int levelAndFlags, String tag) {
426426
* </p>
427427
*
428428
* @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
429-
* time base. This timestamp is used to correctly order the user activity with
429+
* time base. This timestamp is used to correctly order the user activity request with
430430
* other power management functions. It should be set
431431
* to the timestamp of the input event that caused the user activity.
432432
* @param noChangeLights If true, does not cause the keyboard backlight to turn on
@@ -457,7 +457,7 @@ public void userActivity(long when, boolean noChangeLights) {
457457
*
458458
* @param time The time when the request to go to sleep was issued, in the
459459
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
460-
* order the user activity with other power management functions. It should be set
460+
* order the go to sleep request with other power management functions. It should be set
461461
* to the timestamp of the input event that caused the request to go to sleep.
462462
*
463463
* @see #userActivity
@@ -481,7 +481,7 @@ public void goToSleep(long time) {
481481
*
482482
* @param time The time when the request to wake up was issued, in the
483483
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
484-
* order the user activity with other power management functions. It should be set
484+
* order the wake up request with other power management functions. It should be set
485485
* to the timestamp of the input event that caused the request to wake up.
486486
*
487487
* @see #userActivity
@@ -494,6 +494,34 @@ public void wakeUp(long time) {
494494
}
495495
}
496496

497+
/**
498+
* Forces the device to start napping.
499+
* <p>
500+
* If the device is currently awake, starts dreaming, otherwise does nothing.
501+
* When the dream ends or if the dream cannot be started, the device will
502+
* either wake up or go to sleep depending on whether there has been recent
503+
* user activity.
504+
* </p><p>
505+
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
506+
* </p>
507+
*
508+
* @param time The time when the request to nap was issued, in the
509+
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
510+
* order the nap request with other power management functions. It should be set
511+
* to the timestamp of the input event that caused the request to nap.
512+
*
513+
* @see #wakeUp
514+
* @see #goToSleep
515+
*
516+
* @hide
517+
*/
518+
public void nap(long time) {
519+
try {
520+
mService.nap(time);
521+
} catch (RemoteException e) {
522+
}
523+
}
524+
497525
/**
498526
* Sets the brightness of the backlights (screen, keyboard, button).
499527
* <p>

core/java/android/service/dreams/Dream.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ public class Dream extends Service implements Window.Callback {
7171
private final static boolean DEBUG = true;
7272
private final String TAG = Dream.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
7373

74+
/**
75+
* The name of the dream manager service.
76+
* @hide
77+
*/
78+
public static final String DREAM_SERVICE = "dreams";
79+
7480
/**
7581
* Used with {@link Intent#ACTION_MAIN} to declare the necessary intent-filter for a dream.
7682
*
@@ -499,7 +505,7 @@ public void onDestroy() {
499505
// end public api
500506

501507
private void loadSandman() {
502-
mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
508+
mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
503509
}
504510

505511
private final void attach(IBinder windowToken) {
@@ -584,7 +590,7 @@ private void finishInternal() {
584590
mFinished = true;
585591

586592
if (mSandman != null) {
587-
mSandman.awakenSelf(mWindowToken);
593+
mSandman.finishSelf(mWindowToken);
588594
} else {
589595
Slog.w(TAG, "No dream manager found");
590596
}

core/java/android/service/dreams/IDreamManager.aidl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ interface IDreamManager {
3030
ComponentName getDefaultDreamComponent();
3131
void testDream(in ComponentName componentName);
3232
boolean isDreaming();
33-
void awakenSelf(in IBinder token);
33+
void finishSelf(in IBinder token);
3434
}

packages/SystemUI/src/com/android/systemui/Somnambulator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.content.Intent;
2121
import android.os.RemoteException;
2222
import android.os.ServiceManager;
23+
import android.service.dreams.Dream;
2324
import android.service.dreams.IDreamManager;
2425
import android.util.Slog;
2526

@@ -45,7 +46,7 @@ public void onStart() {
4546
setResult(RESULT_OK, resultIntent);
4647
} else {
4748
IDreamManager somnambulist = IDreamManager.Stub.asInterface(
48-
ServiceManager.checkService("dreams"));
49+
ServiceManager.checkService(Dream.DREAM_SERVICE));
4950
if (somnambulist != null) {
5051
try {
5152
Slog.v("Somnambulator", "Dreaming by user request.");

packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import android.os.SystemClock;
4646
import android.os.UserHandle;
4747
import android.provider.Settings;
48+
import android.service.dreams.Dream;
4849
import android.service.dreams.IDreamManager;
4950
import android.util.DisplayMetrics;
5051
import android.util.Log;
@@ -262,7 +263,7 @@ public void start() {
262263
.getDefaultDisplay();
263264

264265
mDreamManager = IDreamManager.Stub.asInterface(
265-
ServiceManager.checkService("dreams"));
266+
ServiceManager.checkService(Dream.DREAM_SERVICE));
266267

267268
super.start(); // calls createAndAddWindows()
268269

services/java/com/android/server/DockObserver.java

Lines changed: 20 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
package com.android.server;
1818

19-
import static android.provider.Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK;
20-
import static android.provider.Settings.Secure.SCREENSAVER_ENABLED;
21-
2219
import android.content.ContentResolver;
2320
import android.content.Context;
2421
import android.content.Intent;
@@ -27,16 +24,12 @@
2724
import android.media.RingtoneManager;
2825
import android.net.Uri;
2926
import android.os.Handler;
30-
import android.os.Looper;
3127
import android.os.Message;
32-
import android.os.RemoteException;
33-
import android.os.ServiceManager;
3428
import android.os.PowerManager;
3529
import android.os.SystemClock;
3630
import android.os.UEventObserver;
3731
import android.os.UserHandle;
3832
import android.provider.Settings;
39-
import android.service.dreams.IDreamManager;
4033
import android.util.Log;
4134
import android.util.Slog;
4235

@@ -48,14 +41,10 @@
4841
*/
4942
final class DockObserver extends UEventObserver {
5043
private static final String TAG = DockObserver.class.getSimpleName();
51-
private static final boolean LOG = false;
5244

5345
private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
5446
private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
5547

56-
private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
57-
private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
58-
5948
private static final int MSG_DOCK_STATE_CHANGED = 0;
6049

6150
private final Object mLock = new Object();
@@ -66,11 +55,16 @@ final class DockObserver extends UEventObserver {
6655
private boolean mSystemReady;
6756

6857
private final Context mContext;
58+
private final PowerManager mPowerManager;
59+
private final PowerManager.WakeLock mWakeLock;
6960

7061
public DockObserver(Context context) {
7162
mContext = context;
72-
init(); // set initial status
7363

64+
mPowerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
65+
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
66+
67+
init(); // set initial status
7468
startObserving(DOCK_UEVENT_MATCH);
7569
}
7670

@@ -87,17 +81,9 @@ public void onUEvent(UEventObserver.UEvent event) {
8781
mPreviousDockState = mDockState;
8882
mDockState = newState;
8983
if (mSystemReady) {
90-
// Don't force screen on when undocking from the desk dock.
91-
// The change in power state will do this anyway.
92-
// FIXME - we should be configurable.
93-
if ((mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK
94-
&& mPreviousDockState != Intent.EXTRA_DOCK_STATE_LE_DESK
95-
&& mPreviousDockState != Intent.EXTRA_DOCK_STATE_HE_DESK) ||
96-
mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
97-
PowerManager pm =
98-
(PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
99-
pm.wakeUp(SystemClock.uptimeMillis());
100-
}
84+
// Wake up immediately when docked or undocked.
85+
mPowerManager.wakeUp(SystemClock.uptimeMillis());
86+
10187
updateLocked();
10288
}
10389
}
@@ -138,15 +124,16 @@ void systemReady() {
138124
}
139125

140126
private void updateLocked() {
127+
mWakeLock.acquire();
141128
mHandler.sendEmptyMessage(MSG_DOCK_STATE_CHANGED);
142129
}
143130

144131
private void handleDockStateChange() {
145132
synchronized (mLock) {
146133
Slog.i(TAG, "Dock state changed: " + mDockState);
147134

135+
// Skip the dock intent if not yet provisioned.
148136
final ContentResolver cr = mContext.getContentResolver();
149-
150137
if (Settings.Global.getInt(cr,
151138
Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
152139
Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
@@ -158,16 +145,8 @@ private void handleDockStateChange() {
158145
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
159146
intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
160147

161-
// Check if this is Bluetooth Dock
162-
// TODO(BT): Get Dock address.
163-
// String address = null;
164-
// if (address != null) {
165-
// intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
166-
// BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
167-
// }
168-
169-
// User feedback to confirm dock connection. Particularly
170-
// useful for flaky contact pins...
148+
// Play a sound to provide feedback to confirm dock connection.
149+
// Particularly useful for flaky contact pins...
171150
if (Settings.Global.getInt(cr,
172151
Settings.Global.DOCK_SOUNDS_ENABLED, 1) == 1) {
173152
String whichSound = null;
@@ -204,42 +183,14 @@ private void handleDockStateChange() {
204183
}
205184
}
206185

207-
IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
208-
if (mgr != null) {
209-
// dreams feature enabled
210-
boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED;
211-
if (undocked) {
212-
try {
213-
if (mgr.isDreaming()) {
214-
mgr.awaken();
215-
}
216-
} catch (RemoteException e) {
217-
Slog.w(TAG, "Unable to awaken!", e);
218-
}
219-
} else {
220-
if (isScreenSaverEnabled(mContext) && isScreenSaverActivatedOnDock(mContext)) {
221-
try {
222-
mgr.dream();
223-
} catch (RemoteException e) {
224-
Slog.w(TAG, "Unable to dream!", e);
225-
}
226-
}
227-
}
228-
} else {
229-
// dreams feature not enabled, send legacy intent
230-
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
231-
}
232-
}
233-
}
186+
// Send the dock event intent.
187+
// There are many components in the system watching for this so as to
188+
// adjust audio routing, screen orientation, etc.
189+
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
234190

235-
private static boolean isScreenSaverEnabled(Context context) {
236-
return Settings.Secure.getInt(context.getContentResolver(),
237-
SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED) != 0;
238-
}
239-
240-
private static boolean isScreenSaverActivatedOnDock(Context context) {
241-
return Settings.Secure.getInt(context.getContentResolver(),
242-
SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK) != 0;
191+
// Release the wake lock that was acquired when the message was posted.
192+
mWakeLock.release();
193+
}
243194
}
244195

245196
private final Handler mHandler = new Handler(true /*async*/) {

services/java/com/android/server/SystemServer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import android.os.SystemClock;
3939
import android.os.SystemProperties;
4040
import android.server.search.SearchManagerService;
41+
import android.service.dreams.Dream;
4142
import android.util.DisplayMetrics;
4243
import android.util.EventLog;
4344
import android.util.Log;
@@ -739,8 +740,8 @@ public void run() {
739740
try {
740741
Slog.i(TAG, "Dreams Service");
741742
// Dreams (interactive idle-time views, a/k/a screen savers)
742-
dreamy = new DreamManagerService(context);
743-
ServiceManager.addService("dreams", dreamy);
743+
dreamy = new DreamManagerService(context, wmHandler);
744+
ServiceManager.addService(Dream.DREAM_SERVICE, dreamy);
744745
} catch (Throwable e) {
745746
reportWtf("starting DreamManagerService", e);
746747
}
@@ -811,7 +812,7 @@ public void run() {
811812
context.getResources().updateConfiguration(config, metrics);
812813

813814
try {
814-
power.systemReady(twilight);
815+
power.systemReady(twilight, dreamy);
815816
} catch (Throwable e) {
816817
reportWtf("making Power Manager Service ready", e);
817818
}

0 commit comments

Comments
 (0)