Merge "Update ambient shadow for TV." into lmp-dev
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 7e04ae8..92647f0 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -29,7 +29,6 @@
 import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.RemoteException;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Slog;
 import android.view.ActionMode;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 45a9dde..81705be 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -237,6 +237,9 @@
     String mStartPlatformVersion;
     String mEndPlatformVersion;
 
+    long mLastRecordedClockTime;
+    long mLastRecordedClockRealtime;
+
     long mUptime;
     long mUptimeStart;
     long mRealtime;
@@ -2271,6 +2274,8 @@
         if (dataSize == 0) {
             // The history is currently empty; we need it to start with a time stamp.
             cur.currentTime = System.currentTimeMillis();
+            mLastRecordedClockTime = cur.currentTime;
+            mLastRecordedClockRealtime = elapsedRealtimeMs;
             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_RESET, cur);
         }
         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
@@ -2439,6 +2444,8 @@
         mNumHistoryTagChars = 0;
         mHistoryBufferLastPos = -1;
         mHistoryOverflow = false;
+        mLastRecordedClockTime = 0;
+        mLastRecordedClockRealtime = 0;
     }
 
     public void updateTimeBasesLocked(boolean unplugged, boolean screenOff, long uptime,
@@ -2498,6 +2505,18 @@
         final long currentTime = System.currentTimeMillis();
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
+        if (isStartClockTimeValid()) {
+            // Has the time changed sufficiently that it is really worth recording?
+            if (mLastRecordedClockTime != 0) {
+                long expectedClockTime = mLastRecordedClockTime
+                        + (elapsedRealtime - mLastRecordedClockRealtime);
+                if (currentTime >= (expectedClockTime-500)
+                        && currentTime <= (expectedClockTime+500)) {
+                    // Not sufficiently changed, skip!
+                    return;
+                }
+            }
+        }
         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
         if (isStartClockTimeValid()) {
             mStartClockTime = currentTime;
@@ -6821,6 +6840,8 @@
             boolean reset) {
         mRecordingHistory = true;
         mHistoryCur.currentTime = System.currentTimeMillis();
+        mLastRecordedClockTime = mHistoryCur.currentTime;
+        mLastRecordedClockRealtime = elapsedRealtimeMs;
         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
                 mHistoryCur);
@@ -6834,6 +6855,8 @@
             final long uptimeMs) {
         if (mRecordingHistory) {
             mHistoryCur.currentTime = currentTime;
+            mLastRecordedClockTime = currentTime;
+            mLastRecordedClockRealtime = elapsedRealtimeMs;
             addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
                     mHistoryCur);
             mHistoryCur.currentTime = 0;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7599bf4..0e4f965 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1281,6 +1281,10 @@
          Doze dreams will run whenever the power manager is in a dozing state. -->
     <string name="config_dozeComponent"></string>
 
+    <!-- If true, the doze component is not started until after the screen has been
+         turned off and the screen off animation has been performed. -->
+    <bool name="config_dozeAfterScreenOff">false</bool>
+
     <!-- Power Management: Specifies whether to decouple the auto-suspend state of the
          device from the display on/off state.
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d69a0f2..e4ca36d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1536,6 +1536,7 @@
   <java-symbol type="bool" name="config_useAttentionLight" />
   <java-symbol type="bool" name="config_animateScreenLights" />
   <java-symbol type="bool" name="config_automatic_brightness_available" />
+  <java-symbol type="bool" name="config_dozeAfterScreenOff" />
   <java-symbol type="bool" name="config_enableActivityRecognitionHardwareOverlay" />
   <java-symbol type="bool" name="config_enableFusedLocationOverlay" />
   <java-symbol type="bool" name="config_enableHardwareFlpOverlay" />
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index f411e62..0aa7f352 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -121,7 +121,7 @@
                 new Intent(NOTIFICATION_PULSE_ACTION).setPackage(getPackageName()),
                 PendingIntent.FLAG_UPDATE_CURRENT);
         mDisplayStateWhenOn = mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON;
-        setDozeScreenState(mDisplayStateWhenOn);
+        mDisplayOff.run();
     }
 
     @Override
@@ -160,16 +160,6 @@
         mHandler.postDelayed(mDisplayOff, millis);
     }
 
-    public void startDozing() {
-        if (DEBUG) Log.d(mTag, "startDozing mDreaming=" + mDreaming);
-        if (!mDreaming) {
-            Log.w(mTag, "Not dozing, no longer dreaming");
-            return;
-        }
-
-        super.startDozing();
-    }
-
     @Override
     public void onDreamingStopped() {
         if (DEBUG) Log.d(mTag, "onDreamingStopped isDozing=" + isDozing());
@@ -180,24 +170,8 @@
             mWakeLock.release();
         }
         listenForPulseSignals(false);
-        stopDozing();
         dozingStopped();
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
-        super.onDetachedFromWindow();
-
-        dozingStopped();
-    }
-
-    @Override
-    public void onDestroy() {
-        if (DEBUG) Log.d(mTag, "onDestroy");
-        super.onDestroy();
-
-        dozingStopped();
+        mHandler.removeCallbacks(mDisplayOff);
     }
 
     private void requestDoze() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 3bdae47..e6db2c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -4079,7 +4079,6 @@
         @Override
         public void requestDoze(DozeService dozeService) {
             if (dozeService == null) return;
-            dozeService.stayAwake(PROCESSING_TIME);
             mHandler.obtainMessage(H.REQUEST_DOZE, dozeService).sendToTarget();
         }
 
@@ -4094,7 +4093,6 @@
         @Override
         public void dozingStopped(DozeService dozeService) {
             if (dozeService == null) return;
-            dozeService.stayAwake(PROCESSING_TIME);
             mHandler.obtainMessage(H.DOZING_STOPPED, dozeService).sendToTarget();
         }
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 8c342dd..b4009ca 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -497,9 +497,11 @@
         // We might override this below based on other factors.
         int state;
         int brightness = PowerManager.BRIGHTNESS_DEFAULT;
+        boolean performScreenOffTransition = false;
         switch (mPowerRequest.policy) {
             case DisplayPowerRequest.POLICY_OFF:
                 state = Display.STATE_OFF;
+                performScreenOffTransition = true;
                 break;
             case DisplayPowerRequest.POLICY_DOZE:
                 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
@@ -515,6 +517,7 @@
                 state = Display.STATE_ON;
                 break;
         }
+        assert(state != Display.STATE_UNKNOWN);
 
         // Apply the proximity sensor.
         if (mProximitySensor != null) {
@@ -691,7 +694,7 @@
             // Wait for previous on animation to complete beforehand.
             unblockScreenOn();
             if (!mColorFadeOnAnimator.isStarted()) {
-                if (mPowerRequest.policy == DisplayPowerRequest.POLICY_OFF) {
+                if (performScreenOffTransition) {
                     // Perform screen off animation.
                     if (!mColorFadeOffAnimator.isStarted()) {
                         if (mPowerState.getColorFadeLevel() == 0.0f) {
@@ -934,8 +937,8 @@
         pw.println("  mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
         pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
         pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
-        pw.println("  mUseSoftwareAutoBrightnessConfig="
-                + mUseSoftwareAutoBrightnessConfig);
+        pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
+        pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
 
         mHandler.runWithScissors(new Runnable() {
             @Override
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 0a4b3bc..eeebe04 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -20,8 +20,8 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.EventLogTags;
-import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
+import com.android.server.SystemService;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
@@ -55,7 +55,6 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.SystemService;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.WorkSource;
@@ -78,7 +77,7 @@
  * The power manager service is responsible for coordinating power management
  * functions on the device.
  */
-public final class PowerManagerService extends com.android.server.SystemService
+public final class PowerManagerService extends SystemService
         implements Watchdog.Monitor {
     private static final String TAG = "PowerManagerService";
 
@@ -329,6 +328,9 @@
     // True if dreams should be activated on dock.
     private boolean mDreamsActivateOnDockSetting;
 
+    // True if doze should not be started until after the screen off transition.
+    private boolean mDozeAfterScreenOffConfig;
+
     // The minimum screen off timeout, in milliseconds.
     private int mMinimumScreenOffTimeoutConfig;
 
@@ -603,6 +605,8 @@
                 com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered);
         mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
                 com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
+        mDozeAfterScreenOffConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dozeAfterScreenOff);
         mMinimumScreenOffTimeoutConfig = resources.getInteger(
                 com.android.internal.R.integer.config_minimumScreenOffTimeout);
         mMaximumScreenDimDurationConfig = resources.getInteger(
@@ -1242,16 +1246,18 @@
                 }
             }
 
-            // Phase 2: Update dreams and display power state.
-            updateDreamLocked(dirtyPhase2);
-            updateDisplayPowerStateLocked(dirtyPhase2);
+            // Phase 2: Update display power state.
+            boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
 
-            // Phase 3: Send notifications, if needed.
+            // Phase 3: Update dream state (depends on display ready signal).
+            updateDreamLocked(dirtyPhase2, displayBecameReady);
+
+            // Phase 4: Send notifications, if needed.
             if (mDisplayReady) {
                 finishInteractiveStateChangeLocked();
             }
 
-            // Phase 4: Update suspend blocker.
+            // Phase 5: Update suspend blocker.
             // Because we might release the last suspend blocker here, we need to make sure
             // we finished everything else first!
             updateSuspendBlockerLocked();
@@ -1603,7 +1609,7 @@
     /**
      * Determines whether to post a message to the sandman to update the dream state.
      */
-    private void updateDreamLocked(int dirty) {
+    private void updateDreamLocked(int dirty, boolean displayBecameReady) {
         if ((dirty & (DIRTY_WAKEFULNESS
                 | DIRTY_USER_ACTIVITY
                 | DIRTY_WAKE_LOCKS
@@ -1612,8 +1618,10 @@
                 | DIRTY_IS_POWERED
                 | DIRTY_STAY_ON
                 | DIRTY_PROXIMITY_POSITIVE
-                | DIRTY_BATTERY_STATE)) != 0) {
-            scheduleSandmanLocked();
+                | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
+            if (mDisplayReady) {
+                scheduleSandmanLocked();
+            }
         }
     }
 
@@ -1640,7 +1648,7 @@
         synchronized (mLock) {
             mSandmanScheduled = false;
             wakefulness = mWakefulness;
-            if (mSandmanSummoned) {
+            if (mSandmanSummoned && mDisplayReady) {
                 startDreaming = ((wakefulness == WAKEFULNESS_DREAMING && canDreamLocked())
                         || wakefulness == WAKEFULNESS_DOZING);
                 mSandmanSummoned = false;
@@ -1772,8 +1780,11 @@
      * has been updated so we come back here to double-check and finish up.
      *
      * This function recalculates the display power state each time.
+     *
+     * @return True if the display became ready.
      */
-    private void updateDisplayPowerStateLocked(int dirty) {
+    private boolean updateDisplayPowerStateLocked(int dirty) {
+        final boolean oldDisplayReady = mDisplayReady;
         if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                 | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
                 | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
@@ -1839,6 +1850,7 @@
                         + ", mBootCompleted=" + mBootCompleted);
             }
         }
+        return mDisplayReady && !oldDisplayReady;
     }
 
     private static boolean isValidBrightness(int value) {
@@ -1855,8 +1867,15 @@
             return DisplayPowerRequest.POLICY_OFF;
         }
 
-        if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
-            return DisplayPowerRequest.POLICY_DOZE;
+        if (mWakefulness == WAKEFULNESS_DOZING) {
+            if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
+                return DisplayPowerRequest.POLICY_DOZE;
+            }
+            if (mDozeAfterScreenOffConfig) {
+                return DisplayPowerRequest.POLICY_OFF;
+            }
+            // Fall through and preserve the current screen policy if not configured to
+            // doze after screen off.  This causes the screen off transition to be skipped.
         }
 
         if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
@@ -2326,6 +2345,7 @@
             pw.println("  mDreamsEnabledSetting=" + mDreamsEnabledSetting);
             pw.println("  mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
             pw.println("  mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
+            pw.println("  mDozeAfterScreenOffConfig=" + mDozeAfterScreenOffConfig);
             pw.println("  mLowPowerModeSetting=" + mLowPowerModeSetting);
             pw.println("  mAutoLowPowerModeEnabled=" + mAutoLowPowerModeEnabled);
             pw.println("  mAutoLowPowerModeSnoozing=" + mAutoLowPowerModeSnoozing);