Ensure that dreams show while docked.

Fixed a race between the UiModeManagerService and PowerManagerService
both of which are trying to wake the device when docked / powered.

Bug: 7281240
Change-Id: Ia41fef48f17f2a2eb56549437d295f9a86c95af2
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index d1af2b0..e9e3163 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -37,6 +37,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.dreams.DreamService;
@@ -90,6 +91,8 @@
     private NotificationManager mNotificationManager;
 
     private StatusBarManager mStatusBarManager;
+
+    private final PowerManager mPowerManager;
     private final PowerManager.WakeLock mWakeLock;
 
     static Intent buildHomeIntent(String category) {
@@ -163,8 +166,8 @@
         mContext.registerReceiver(mBatteryReceiver,
                 new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
 
-        PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
+        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
 
         mConfiguration.setToDefaults();
 
@@ -502,7 +505,17 @@
             try {
                 IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
                         ServiceManager.getService(DreamService.DREAM_SERVICE));
-                dreamManagerService.dream();
+                if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
+                    // Wake up.
+                    // The power manager will wake up the system when it starts receiving power
+                    // but there is a race between that happening and the UI mode manager
+                    // starting a dream.  We want the system to already be awake
+                    // by the time this happens.  Otherwise the dream may not start.
+                    mPowerManager.wakeUp(SystemClock.uptimeMillis());
+
+                    // Dream.
+                    dreamManagerService.dream();
+                }
             } catch (RemoteException ex) {
                 Slog.e(TAG, "Could not start dream when docked.", ex);
             }
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index f584302..abbae5b 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -1078,41 +1078,51 @@
     }
 
     private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(boolean wasPowered, int oldPlugType) {
-        if (mWakeUpWhenPluggedOrUnpluggedConfig) {
-            // FIXME: Need more accurate detection of wireless chargers.
-            //
-            // We are unable to accurately detect whether the device is resting on the
-            // charger unless it is actually receiving power.  This causes us some grief
-            // because the device might not appear to be plugged into the wireless charger
-            // unless it actually charging.
-            //
-            // To avoid spuriously waking the screen, we apply a special policy to
-            // wireless chargers.
-            //
-            // 1. Don't wake the device when unplugged from wireless charger because
-            //    it might be that the device is still resting on the wireless charger
-            //    but is not receiving power anymore because the battery is full.
-            //
-            // 2. Don't wake the device when plugged into a wireless charger if the
-            //    battery already appears to be mostly full.  This situation may indicate
-            //    that the device was resting on the charger the whole time and simply
-            //    wasn't receiving power because the battery was full.  We can't tell
-            //    whether the device was just placed on the charger or whether it has
-            //    been there for half of the night slowly discharging until it hit
-            //    the point where it needed to start charging again.
-            if (wasPowered && !mIsPowered
-                    && oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
-                return false;
-            }
-            if (!wasPowered && mIsPowered
-                    && mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
-                    && mBatteryService.getBatteryLevel() >=
-                            WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) {
-                return false;
-            }
-            return true;
+        // Don't wake when powered unless configured to do so.
+        if (!mWakeUpWhenPluggedOrUnpluggedConfig) {
+            return false;
         }
-        return false;
+
+        // FIXME: Need more accurate detection of wireless chargers.
+        //
+        // We are unable to accurately detect whether the device is resting on the
+        // charger unless it is actually receiving power.  This causes us some grief
+        // because the device might not appear to be plugged into the wireless charger
+        // unless it actually charging.
+        //
+        // To avoid spuriously waking the screen, we apply a special policy to
+        // wireless chargers.
+        //
+        // 1. Don't wake the device when unplugged from wireless charger because
+        //    it might be that the device is still resting on the wireless charger
+        //    but is not receiving power anymore because the battery is full.
+        //
+        // 2. Don't wake the device when plugged into a wireless charger if the
+        //    battery already appears to be mostly full.  This situation may indicate
+        //    that the device was resting on the charger the whole time and simply
+        //    wasn't receiving power because the battery was full.  We can't tell
+        //    whether the device was just placed on the charger or whether it has
+        //    been there for half of the night slowly discharging until it hit
+        //    the point where it needed to start charging again.
+        if (wasPowered && !mIsPowered
+                && oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
+            return false;
+        }
+        if (!wasPowered && mIsPowered
+                && mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
+                && mBatteryService.getBatteryLevel() >=
+                        WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) {
+            return false;
+        }
+
+        // If already dreaming and becoming powered, then don't wake.
+        if (mIsPowered && (mWakefulness == WAKEFULNESS_NAPPING
+                || mWakefulness == WAKEFULNESS_DREAMING)) {
+            return false;
+        }
+
+        // Otherwise wake up!
+        return true;
     }
 
     /**