OSDN Git Service

Add Brightness setting for VR Mode.
authorSantos Cordon <santoscordon@google.com>
Tue, 20 Sep 2016 22:50:35 +0000 (15:50 -0700)
committerSantos Cordon <santoscordon@google.com>
Thu, 22 Dec 2016 20:27:51 +0000 (12:27 -0800)
This change saves and loads a different brightness setting when the user
goes in and out of VR Mode.

Bug: 30984614
Change-Id: Ie5578bbd6ea346f0eb34fe4abbfd604a5d7c0c93

14 files changed:
core/java/android/hardware/display/DisplayManagerInternal.java
core/java/android/os/PowerManager.java
core/java/android/provider/Settings.java
core/java/android/view/Display.java
core/res/res/values/config.xml
core/res/res/values/symbols.xml
packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
proto/src/metrics_constants.proto
services/core/java/com/android/server/display/DisplayPowerController.java
services/core/java/com/android/server/display/LocalDisplayAdapter.java
services/core/java/com/android/server/lights/Light.java
services/core/java/com/android/server/lights/LightsService.java
services/core/java/com/android/server/power/PowerManagerService.java
services/core/jni/com_android_server_lights_LightsService.cpp

index 13ba6cc..aea1258 100644 (file)
@@ -167,6 +167,8 @@ public abstract class DisplayManagerInternal {
         public static final int POLICY_DIM = 2;
         // Policy: Make the screen bright as usual.
         public static final int POLICY_BRIGHT = 3;
+        // Policy: Keep the screen and display optimized for VR mode.
+        public static final int POLICY_VR = 4;
 
         // The basic overall policy to apply: off, doze, dim or bright.
         public int policy;
@@ -233,6 +235,10 @@ public abstract class DisplayManagerInternal {
             return policy == POLICY_BRIGHT || policy == POLICY_DIM;
         }
 
+        public boolean isVr() {
+            return policy == POLICY_VR;
+        }
+
         public void copyFrom(DisplayPowerRequest other) {
             policy = other.policy;
             useProximitySensor = other.useProximitySensor;
@@ -301,6 +307,8 @@ public abstract class DisplayManagerInternal {
                     return "DIM";
                 case POLICY_BRIGHT:
                     return "BRIGHT";
+                case POLICY_VR:
+                    return "VR";
                 default:
                     return Integer.toString(policy);
             }
index 9d04929..dff0a28 100644 (file)
@@ -49,23 +49,23 @@ import android.util.Log;
  * <i>These levels are mutually exclusive - you may only specify one of them.</i>
  *
  * <table>
- *     <tr><th>Flag Value</th> 
+ *     <tr><th>Flag Value</th>
  *     <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
  *
  *     <tr><td>{@link #PARTIAL_WAKE_LOCK}</td>
- *         <td>On*</td> <td>Off</td> <td>Off</td> 
+ *         <td>On*</td> <td>Off</td> <td>Off</td>
  *     </tr>
- *     
+ *
  *     <tr><td>{@link #SCREEN_DIM_WAKE_LOCK}</td>
- *         <td>On</td> <td>Dim</td> <td>Off</td> 
+ *         <td>On</td> <td>Dim</td> <td>Off</td>
  *     </tr>
  *
  *     <tr><td>{@link #SCREEN_BRIGHT_WAKE_LOCK}</td>
- *         <td>On</td> <td>Bright</td> <td>Off</td> 
+ *         <td>On</td> <td>Bright</td> <td>Off</td>
  *     </tr>
- *     
+ *
  *     <tr><td>{@link #FULL_WAKE_LOCK}</td>
- *         <td>On</td> <td>Bright</td> <td>Bright</td> 
+ *         <td>On</td> <td>Bright</td> <td>Bright</td>
  *     </tr>
  * </table>
  * </p><p>
@@ -85,13 +85,13 @@ import android.util.Log;
  *         the illumination to remain on once it turns on (e.g. from user activity).  This flag
  *         will force the screen and/or keyboard to turn on immediately, when the WakeLock is
  *         acquired.  A typical use would be for notifications which are important for the user to
- *         see immediately.</td> 
+ *         see immediately.</td>
  *     </tr>
- *     
+ *
  *     <tr><td>{@link #ON_AFTER_RELEASE}</td>
  *         <td>If this flag is set, the user activity timer will be reset when the WakeLock is
- *         released, causing the illumination to remain on a bit longer.  This can be used to 
- *         reduce flicker if you are cycling between wake lock conditions.</td> 
+ *         released, causing the illumination to remain on a bit longer.  This can be used to
+ *         reduce flicker if you are cycling between wake lock conditions.</td>
  *     </tr>
  * </table>
  * <p>
@@ -479,6 +479,35 @@ public final class PowerManager {
     }
 
     /**
+     * Gets the minimum supported screen brightness setting for VR Mode.
+     * @hide
+     */
+    public int getMinimumScreenBrightnessForVrSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessForVrSettingMinimum);
+    }
+
+    /**
+     * Gets the maximum supported screen brightness setting for VR Mode.
+     * The screen may be allowed to become dimmer than this value but
+     * this is the maximum value that can be set by the user.
+     * @hide
+     */
+    public int getMaximumScreenBrightnessForVrSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessForVrSettingMaximum);
+    }
+
+    /**
+     * Gets the default screen brightness for VR setting.
+     * @hide
+     */
+    public int getDefaultScreenBrightnessForVrSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault);
+    }
+
+    /**
      * Returns true if the twilight service should be used to adjust screen brightness
      * policy.  This setting is experimental and disabled by default.
      * @hide
index 43590c7..8dee276 100755 (executable)
@@ -2889,6 +2889,15 @@ public final class Settings {
                 new InclusiveIntegerRangeValidator(0, 255);
 
         /**
+         * The screen backlight brightness between 0 and 255.
+         * @hide
+         */
+        public static final String SCREEN_BRIGHTNESS_FOR_VR = "screen_brightness_for_vr";
+
+        private static final Validator SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR =
+                new InclusiveIntegerRangeValidator(0, 255);
+
+        /**
          * Control whether to enable automatic brightness mode.
          */
         public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
@@ -3882,6 +3891,7 @@ public final class Settings {
             VALIDATORS.put(DIM_SCREEN, DIM_SCREEN_VALIDATOR);
             VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);
             VALIDATORS.put(SCREEN_BRIGHTNESS, SCREEN_BRIGHTNESS_VALIDATOR);
+            VALIDATORS.put(SCREEN_BRIGHTNESS_FOR_VR, SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR);
             VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR);
             VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR);
             VALIDATORS.put(MUTE_STREAMS_AFFECTED, MUTE_STREAMS_AFFECTED_VALIDATOR);
index 3beb00f..b37ea8e 100644 (file)
@@ -282,6 +282,15 @@ public final class Display {
      */
     public static final int STATE_DOZE_SUSPEND = 4;
 
+    /**
+     * Display state: The display is on and optimized for VR mode.
+     *
+     * @see #getState
+     * @see android.os.PowerManager#isInteractive
+     * @hide
+     */
+    public static final int STATE_VR = 5;
+
     /* The color mode constants defined below must be kept in sync with the ones in
      * system/graphics.h */
 
@@ -866,7 +875,8 @@ public final class Display {
      * Gets the state of the display, such as whether it is on or off.
      *
      * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON},
-     * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or {@link #STATE_UNKNOWN}.
+     * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or
+     * {@link #STATE_UNKNOWN}.
      */
     public int getState() {
         synchronized (this) {
@@ -982,6 +992,8 @@ public final class Display {
                 return "DOZE";
             case STATE_DOZE_SUSPEND:
                 return "DOZE_SUSPEND";
+            case STATE_VR:
+                return "VR";
             default:
                 return Integer.toString(state);
         }
index 5967c69..ad979ef 100644 (file)
          Must be in the range specified by minimum and maximum. -->
     <integer name="config_screenBrightnessSettingDefault">102</integer>
 
+    <!-- Default screen brightness for VR setting. -->
+    <integer name="config_screenBrightnessForVrSettingDefault">86</integer>
+
+    <!-- Minimum screen brightness setting allowed for VR. Device panels start increasing pulse
+         width as brightness decreases below this theshold. -->
+    <integer name="config_screenBrightnessForVrSettingMinimum">79</integer>
+
+    <!-- Maximum screen brightness setting allowed for VR. -->
+    <integer name="config_screenBrightnessForVrSettingMaximum">255</integer>
+
     <!-- Screen brightness used to dim the screen while dozing in a very low power state.
          May be less than the minimum allowed brightness setting
          that can be set by the user. -->
index ac502e0..c71bd02 100644 (file)
   <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" />
   <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" />
   <java-symbol type="integer" name="config_screenBrightnessSettingDefault" />
+  <java-symbol type="integer" name="config_screenBrightnessForVrSettingDefault" />
+  <java-symbol type="integer" name="config_screenBrightnessForVrSettingMaximum" />
+  <java-symbol type="integer" name="config_screenBrightnessForVrSettingMinimum" />
   <java-symbol type="integer" name="config_screenBrightnessDark" />
   <java-symbol type="integer" name="config_screenBrightnessDim" />
   <java-symbol type="integer" name="config_screenBrightnessDoze" />
index e8039c3..3059a05 100644 (file)
@@ -30,6 +30,9 @@ import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.util.Log;
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
@@ -52,9 +55,12 @@ public class BrightnessController implements ToggleSlider.Listener {
     private static final int MSG_SET_CHECKED = 2;
     private static final int MSG_ATTACH_LISTENER = 3;
     private static final int MSG_DETACH_LISTENER = 4;
+    private static final int MSG_VR_MODE_CHANGED = 5;
 
     private final int mMinimumBacklight;
     private final int mMaximumBacklight;
+    private final int mMinimumBacklightForVr;
+    private final int mMaximumBacklightForVr;
 
     private final Context mContext;
     private final ImageView mIcon;
@@ -62,6 +68,7 @@ public class BrightnessController implements ToggleSlider.Listener {
     private final boolean mAutomaticAvailable;
     private final IPowerManager mPower;
     private final CurrentUserTracker mUserTracker;
+    private final IVrManager mVrManager;
 
     private Handler mBackgroundHandler;
     private final BrightnessObserver mBrightnessObserver;
@@ -69,7 +76,8 @@ public class BrightnessController implements ToggleSlider.Listener {
     private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
             new ArrayList<BrightnessStateChangeCallback>();
 
-    private volatile boolean mAutomatic;
+    private volatile boolean mAutomatic;  // Brightness adjusted automatically using ambient light.
+    private volatile boolean mIsVrModeEnabled;
     private boolean mListening;
     private boolean mExternalChange;
 
@@ -84,6 +92,8 @@ public class BrightnessController implements ToggleSlider.Listener {
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
         private final Uri BRIGHTNESS_URI =
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
+        private final Uri BRIGHTNESS_FOR_VR_URI =
+                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);
         private final Uri BRIGHTNESS_ADJ_URI =
                 Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);
 
@@ -105,6 +115,8 @@ public class BrightnessController implements ToggleSlider.Listener {
                 mBackgroundHandler.post(mUpdateSliderRunnable);
             } else if (BRIGHTNESS_URI.equals(uri) && !mAutomatic) {
                 mBackgroundHandler.post(mUpdateSliderRunnable);
+            } else if (BRIGHTNESS_FOR_VR_URI.equals(uri)) {
+                mBackgroundHandler.post(mUpdateSliderRunnable);
             } else if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {
                 mBackgroundHandler.post(mUpdateSliderRunnable);
             } else {
@@ -126,6 +138,9 @@ public class BrightnessController implements ToggleSlider.Listener {
                     BRIGHTNESS_URI,
                     false, this, UserHandle.USER_ALL);
             cr.registerContentObserver(
+                    BRIGHTNESS_FOR_VR_URI,
+                    false, this, UserHandle.USER_ALL);
+            cr.registerContentObserver(
                     BRIGHTNESS_ADJ_URI,
                     false, this, UserHandle.USER_ALL);
         }
@@ -191,7 +206,14 @@ public class BrightnessController implements ToggleSlider.Listener {
     private final Runnable mUpdateSliderRunnable = new Runnable() {
         @Override
         public void run() {
-            if (mAutomatic) {
+            if (mIsVrModeEnabled) {
+                int value = Settings.System.getIntForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mMaximumBacklight,
+                        UserHandle.USER_CURRENT);
+                mHandler.obtainMessage(MSG_UPDATE_SLIDER,
+                        mMaximumBacklightForVr - mMinimumBacklightForVr,
+                        value - mMinimumBacklightForVr).sendToTarget();
+            } else if (mAutomatic) {
                 float value = Settings.System.getFloatForUser(mContext.getContentResolver(),
                         Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0,
                         UserHandle.USER_CURRENT);
@@ -208,6 +230,14 @@ public class BrightnessController implements ToggleSlider.Listener {
         }
     };
 
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+        @Override
+        public void onVrStateChanged(boolean enabled) {
+            mHandler.obtainMessage(MSG_VR_MODE_CHANGED, enabled ? 1 : 0, 0)
+                    .sendToTarget();
+        }
+    };
+
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -230,6 +260,9 @@ public class BrightnessController implements ToggleSlider.Listener {
                     case MSG_DETACH_LISTENER:
                         mControl.setOnChangedListener(null);
                         break;
+                    case MSG_VR_MODE_CHANGED:
+                        updateVrMode(msg.arg1 != 0);
+                        break;
                     default:
                         super.handleMessage(msg);
                 }
@@ -256,10 +289,13 @@ public class BrightnessController implements ToggleSlider.Listener {
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
         mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
+        mMinimumBacklightForVr = pm.getMinimumScreenBrightnessForVrSetting();
+        mMaximumBacklightForVr = pm.getMaximumScreenBrightnessForVrSetting();
 
         mAutomaticAvailable = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available);
         mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
+        mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
     }
 
     public void setBackgroundLooper(Looper backgroundLooper) {
@@ -284,6 +320,15 @@ public class BrightnessController implements ToggleSlider.Listener {
             return;
         }
 
+        if (mVrManager != null) {
+            try {
+                mVrManager.registerListener(mVrStateCallbacks);
+                mIsVrModeEnabled = mVrManager.getVrModeState();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to register VR mode state listener: ", e);
+            }
+        }
+
         mBackgroundHandler.post(mStartListeningRunnable);
         mListening = true;
     }
@@ -294,6 +339,14 @@ public class BrightnessController implements ToggleSlider.Listener {
             return;
         }
 
+        if (mVrManager != null) {
+            try {
+                mVrManager.unregisterListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
+            }
+        }
+
         mBackgroundHandler.post(mStopListeningRunnable);
         mListening = false;
     }
@@ -304,7 +357,22 @@ public class BrightnessController implements ToggleSlider.Listener {
         updateIcon(mAutomatic);
         if (mExternalChange) return;
 
-        if (!mAutomatic) {
+        if (mIsVrModeEnabled) {
+            final int val = value + mMinimumBacklightForVr;
+            if (stopTracking) {
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_FOR_VR, val);
+            }
+            setBrightness(val);
+            if (!tracking) {
+                AsyncTask.execute(new Runnable() {
+                        public void run() {
+                            Settings.System.putIntForUser(mContext.getContentResolver(),
+                                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR, val,
+                                    UserHandle.USER_CURRENT);
+                        }
+                    });
+            }
+        } else if (!mAutomatic) {
             final int val = value + mMinimumBacklight;
             if (stopTracking) {
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
@@ -368,4 +436,11 @@ public class BrightnessController implements ToggleSlider.Listener {
                     com.android.systemui.R.drawable.ic_qs_brightness_auto_off);
         }
     }
+
+    private void updateVrMode(boolean isEnabled) {
+        if (mIsVrModeEnabled != isEnabled) {
+            mIsVrModeEnabled = isEnabled;
+            mBackgroundHandler.post(mUpdateSliderRunnable);
+        }
+    }
 }
index eed7e70..df22320 100644 (file)
@@ -3105,6 +3105,12 @@ message MetricsEvent {
     // PACKAGE: The package name of the app the permission was revoked for
     ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBER = 739;
 
+    // ACTION: QS Brightness Slider (with auto brightness disabled, and VR enabled)
+    //   SUBTYPE: slider value
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    ACTION_BRIGHTNESS_FOR_VR = 498;
+
     // ACTION: A captive portal was detected during network validation
     // CATEGORY: NOTIFICATION
     // OS: N-MR2
index 477ecdf..015345c 100644 (file)
@@ -577,6 +577,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                     brightness = mPowerRequest.dozeScreenBrightness;
                 }
                 break;
+            case DisplayPowerRequest.POLICY_VR:
+                state = Display.STATE_VR;
+                break;
             case DisplayPowerRequest.POLICY_DIM:
             case DisplayPowerRequest.POLICY_BRIGHT:
             default:
@@ -618,6 +621,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
         // Animate the screen state change unless already animating.
         // The transition may be deferred, so after this point we will use the
         // actual state instead of the desired one.
+        final int oldState = mPowerState.getScreenState();
         animateScreenStateChange(state, performScreenOffTransition);
         state = mPowerState.getScreenState();
 
@@ -717,9 +721,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
         }
 
         // Animate the screen brightness when the screen is on or dozing.
-        // Skip the animation when the screen is off or suspended.
+        // Skip the animation when the screen is off or suspended or transition to/from VR.
         if (!mPendingScreenOff) {
-            if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
+            boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
+            if ((state == Display.STATE_ON || state == Display.STATE_DOZE) && !wasOrWillBeInVr) {
                 animateScreenBrightness(brightness,
                         slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
             } else {
@@ -903,6 +908,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                 mPowerState.setColorFadeLevel(1.0f);
                 mPowerState.dismissColorFade();
             }
+        } else if (target == Display.STATE_VR) {
+            // Wait for brightness animation to complete beforehand when entering VR
+            // from screen on to prevent a perceptible jump because brightness may operate
+            // differently when the display is configured for dozing.
+            if (mScreenBrightnessRampAnimator.isAnimating()
+                    && mPowerState.getScreenState() == Display.STATE_ON) {
+                return;
+            }
+
+            // Set screen state.
+            if (!setScreenState(Display.STATE_VR)) {
+                return; // screen on blocked
+            }
+
+            // Dismiss the black surface without fanfare.
+            mPowerState.setColorFadeLevel(1.0f);
+            mPowerState.dismissColorFade();
         } else if (target == Display.STATE_DOZE) {
             // Want screen dozing.
             // Wait for brightness animation to complete beforehand when entering doze
index 61c2eac..8673225 100644 (file)
@@ -471,6 +471,16 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                             }
                         }
 
+                        // If the state change was from or to VR, then we need to tell the light
+                        // so that it can apply appropriate VR brightness settings. This should
+                        // happen prior to changing the brightness but also if there is no
+                        // brightness change at all.
+                        if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
+                                currentState != state) {
+                            setVrMode(state == Display.STATE_VR);
+                        }
+
+
                         // Apply brightness changes given that we are in a non-suspended state.
                         if (brightnessChanged) {
                             setDisplayBrightness(brightness);
@@ -482,6 +492,15 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                         }
                     }
 
+                    private void setVrMode(boolean isVrEnabled) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "setVrMode("
+                                    + "id=" + displayId
+                                    + ", state=" + Display.stateToString(state) + ")");
+                        }
+                        mBacklight.setVrMode(isVrEnabled);
+                    }
+
                     private void setDisplayState(int state) {
                         if (DEBUG) {
                             Slog.d(TAG, "setDisplayState("
index 0bab86b..b5ec603 100644 (file)
@@ -46,4 +46,5 @@ public abstract class Light {
     public abstract void pulse();
     public abstract void pulse(int color, int onMS);
     public abstract void turnOff();
+    public abstract void setVrMode(boolean enabled);
 }
index bba0a50..e07156e 100644 (file)
@@ -1,5 +1,4 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
+/* * Copyright (C) 2008 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 package com.android.server.lights;
 
 import com.android.server.SystemService;
-import com.android.server.vr.VrManagerService;
 
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
-import android.os.RemoteException;
 import android.os.Trace;
-import android.os.UserHandle;
 import android.provider.Settings;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
 import android.util.Slog;
 
 public class LightsService extends SystemService {
@@ -36,7 +30,6 @@ public class LightsService extends SystemService {
     static final boolean DEBUG = false;
 
     final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
-    private boolean mVrModeEnabled;
 
     private final class LightImpl extends Light {
 
@@ -52,6 +45,13 @@ public class LightsService extends SystemService {
         @Override
         public void setBrightness(int brightness, int brightnessMode) {
             synchronized (this) {
+                // LOW_PERSISTENCE cannot be manually set
+                if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
+                    Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mId +
+                            ": brightness=0x" + Integer.toHexString(brightness));
+                    return;
+                }
+
                 int color = brightness & 0x000000ff;
                 color = 0xff000000 | (color << 16) | (color << 8) | color;
                 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
@@ -80,11 +80,9 @@ public class LightsService extends SystemService {
         @Override
         public void pulse(int color, int onMS) {
             synchronized (this) {
-                if (mBrightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
-                    return;
-                }
                 if (mColor == 0 && !mFlashing) {
-                    setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
+                    setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000,
+                            BRIGHTNESS_MODE_USER);
                     mColor = 0;
                     mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
                 }
@@ -98,17 +96,23 @@ public class LightsService extends SystemService {
             }
         }
 
-        void enableLowPersistence() {
-            synchronized(this) {
-                setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_LOW_PERSISTENCE);
-                mLocked = true;
-            }
-        }
-
-        void disableLowPersistence() {
-            synchronized(this) {
-                mLocked = false;
-                setLightLocked(mLastColor, LIGHT_FLASH_NONE, 0, 0, mLastBrightnessMode);
+        @Override
+        public void setVrMode(boolean enabled) {
+            synchronized (this) {
+                if (mVrModeEnabled != enabled) {
+                    mVrModeEnabled = enabled;
+
+                    mUseLowPersistenceForVR =
+                            (getVrDisplayMode() == Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE);
+                    if (shouldBeInLowPersistenceMode()) {
+                        mLastBrightnessMode = mBrightnessMode;
+                    }
+
+                    // NOTE: We do not trigger a call to setLightLocked here.  We do not know the
+                    // current brightness or other values when leaving VR so we avoid any incorrect
+                    // jumps. The code that calls this method will immediately issue a brightness
+                    // update which is when the change will occur.
+                }
             }
         }
 
@@ -119,7 +123,13 @@ public class LightsService extends SystemService {
         }
 
         private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
-            if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
+            if (shouldBeInLowPersistenceMode()) {
+                brightnessMode = BRIGHTNESS_MODE_LOW_PERSISTENCE;
+            } else if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
+                brightnessMode = mLastBrightnessMode;
+            }
+
+            if ((color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
                     mBrightnessMode != brightnessMode)) {
                 if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
                         + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
@@ -128,7 +138,6 @@ public class LightsService extends SystemService {
                 mMode = mode;
                 mOnMS = onMS;
                 mOffMS = offMS;
-                mLastBrightnessMode = mBrightnessMode;
                 mBrightnessMode = brightnessMode;
                 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
                         + Integer.toHexString(color) + ")");
@@ -140,6 +149,10 @@ public class LightsService extends SystemService {
             }
         }
 
+        private boolean shouldBeInLowPersistenceMode() {
+            return mVrModeEnabled && mUseLowPersistenceForVR;
+        }
+
         private int mId;
         private int mColor;
         private int mMode;
@@ -149,7 +162,8 @@ public class LightsService extends SystemService {
         private int mBrightnessMode;
         private int mLastBrightnessMode;
         private int mLastColor;
-        private boolean mLocked;
+        private boolean mVrModeEnabled;
+        private boolean mUseLowPersistenceForVR;
     }
 
     public LightsService(Context context) {
@@ -167,17 +181,6 @@ public class LightsService extends SystemService {
 
     @Override
     public void onBootPhase(int phase) {
-        if (phase == PHASE_SYSTEM_SERVICES_READY) {
-            IVrManager vrManager =
-                    (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
-            if (vrManager != null) {
-                try {
-                    vrManager.registerListener(mVrStateCallbacks);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Failed to register VR mode state listener: " + e);
-                }
-            }
-        }
     }
 
     private int getVrDisplayMode() {
@@ -188,30 +191,6 @@ public class LightsService extends SystemService {
                 currentUser);
     }
 
-    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
-        @Override
-        public void onVrStateChanged(boolean enabled) throws RemoteException {
-            LightImpl l = mLights[LightsManager.LIGHT_ID_BACKLIGHT];
-            int vrDisplayMode = getVrDisplayMode();
-
-            // User leaves VR mode before altering display settings.
-            if (enabled && vrDisplayMode == Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE) {
-                if (!mVrModeEnabled) {
-                    if (DEBUG)
-                        Slog.v(TAG, "VR mode enabled, setting brightness to low persistence");
-                    l.enableLowPersistence();
-                    mVrModeEnabled = true;
-                }
-            } else {
-                if (mVrModeEnabled) {
-                    if (DEBUG) Slog.v(TAG, "VR mode disabled, resetting brightnes");
-                    l.disableLowPersistence();
-                    mVrModeEnabled = false;
-                }
-            }
-        }
-    };
-
     private final LightsManager mService = new LightsManager() {
         @Override
         public Light getLight(int id) {
index f2ccac5..26788b3 100644 (file)
@@ -136,6 +136,8 @@ public final class PowerManagerService extends SystemService
     private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
     // Dirty bit: sQuiescent changed
     private static final int DIRTY_QUIESCENT = 1 << 12;
+    // Dirty bit: VR Mode enabled changed
+    private static final int DIRTY_VR_MODE_CHANGED = 1 << 13;
 
     // Summarizes the state of all active wakelocks.
     private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -413,11 +415,15 @@ public final class PowerManagerService extends SystemService
     private int mScreenBrightnessSettingMinimum;
     private int mScreenBrightnessSettingMaximum;
     private int mScreenBrightnessSettingDefault;
+    private int mScreenBrightnessForVrSettingDefault;
 
     // The screen brightness setting, from 0 to 255.
     // Use -1 if no value has been set.
     private int mScreenBrightnessSetting;
 
+    // The screen brightness setting, from 0 to 255, to be used while in VR Mode.
+    private int mScreenBrightnessForVrSetting;
+
     // The screen auto-brightness adjustment setting, from -1 to 1.
     // Use 0 if there is no adjustment.
     private float mScreenAutoBrightnessAdjustmentSetting;
@@ -511,6 +517,9 @@ public final class PowerManagerService extends SystemService
     // True if brightness should be affected by twilight.
     private boolean mBrightnessUseTwilight;
 
+    // True if we are currently in VR Mode.
+    private boolean mIsVrModeEnabled;
+
     private native void nativeInit();
 
     private static native void nativeAcquireSuspendBlocker(String name);
@@ -594,6 +603,7 @@ public final class PowerManagerService extends SystemService
             mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
             mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
             mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+            mScreenBrightnessForVrSettingDefault = pm.getDefaultScreenBrightnessForVrSetting();
 
             SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
 
@@ -640,6 +650,9 @@ public final class PowerManagerService extends SystemService
                     Settings.System.SCREEN_BRIGHTNESS),
                     false, mSettingsObserver, UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.SCREEN_BRIGHTNESS_MODE),
                     false, mSettingsObserver, UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
@@ -773,11 +786,17 @@ public final class PowerManagerService extends SystemService
             }
         }
 
-        final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
+        final int oldScreenBrightnessSetting = getCurrentBrightnessSettingLocked();
+
+        mScreenBrightnessForVrSetting = Settings.System.getIntForUser(resolver,
+                Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mScreenBrightnessForVrSettingDefault,
+                UserHandle.USER_CURRENT);
+
         mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
                 Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
                 UserHandle.USER_CURRENT);
-        if (oldScreenBrightnessSetting != mScreenBrightnessSetting) {
+
+        if (oldScreenBrightnessSetting != getCurrentBrightnessSettingLocked()) {
             mTemporaryScreenBrightnessSettingOverride = -1;
         }
 
@@ -811,6 +830,10 @@ public final class PowerManagerService extends SystemService
         mDirty |= DIRTY_SETTINGS;
     }
 
+    private int getCurrentBrightnessSettingLocked() {
+        return mIsVrModeEnabled ? mScreenBrightnessForVrSetting : mScreenBrightnessSetting;
+    }
+
     private void postAfterBootCompleted(Runnable r) {
         if (mBootCompleted) {
             BackgroundThread.getHandler().post(r);
@@ -2069,6 +2092,7 @@ public final class PowerManagerService extends SystemService
                 || !mDreamsSupportedConfig
                 || !mDreamsEnabledSetting
                 || !mDisplayPowerRequest.isBrightOrDim()
+                || !mDisplayPowerRequest.isVr()
                 || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
                         | USER_ACTIVITY_SCREEN_DIM | USER_ACTIVITY_SCREEN_DREAM)) == 0
                 || !mBootCompleted) {
@@ -2113,7 +2137,8 @@ public final class PowerManagerService extends SystemService
         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_BRIGHTNESS_BOOST | DIRTY_QUIESCENT)) != 0) {
+                | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
+                DIRTY_QUIESCENT)) != 0) {
             mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
 
             // Determine appropriate screen brightness and auto-brightness adjustments.
@@ -2127,6 +2152,9 @@ public final class PowerManagerService extends SystemService
                 // bootloader brightness and the default brightness to be identical.
                 autoBrightness = false;
                 brightnessSetByUser = false;
+            } else if (mIsVrModeEnabled) {
+                screenBrightness = mScreenBrightnessForVrSetting;
+                autoBrightness = false;
             } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                 screenBrightness = mScreenBrightnessOverrideFromWindowManager;
                 autoBrightness = false;
@@ -2160,7 +2188,7 @@ public final class PowerManagerService extends SystemService
             mDisplayPowerRequest.useAutoBrightness = autoBrightness;
             mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
             mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
-            mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
+            mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
             mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
 
             if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
@@ -2191,6 +2219,7 @@ public final class PowerManagerService extends SystemService
                         + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
                         + ", mBootCompleted=" + mBootCompleted
                         + ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
+                        + ", mIsVrModeEnabled= " + mIsVrModeEnabled
                         + ", sQuiescent=" + sQuiescent);
             }
         }
@@ -2220,6 +2249,10 @@ public final class PowerManagerService extends SystemService
         }
     }
 
+    private boolean shouldBoostScreenBrightness() {
+        return !mIsVrModeEnabled && mScreenBrightnessBoostInProgress;
+    }
+
     private static boolean isValidBrightness(int value) {
         return value >= 0 && value <= 255;
     }
@@ -2230,6 +2263,10 @@ public final class PowerManagerService extends SystemService
     }
 
     private int getDesiredScreenPolicyLocked() {
+        if (mIsVrModeEnabled) {
+            return DisplayPowerRequest.POLICY_VR;
+        }
+
         if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
             return DisplayPowerRequest.POLICY_OFF;
         }
@@ -2333,7 +2370,7 @@ public final class PowerManagerService extends SystemService
     };
 
     private boolean shouldUseProximitySensorLocked() {
-        return (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
+        return !mIsVrModeEnabled && (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
     }
 
     /**
@@ -3085,7 +3122,11 @@ public final class PowerManagerService extends SystemService
             pw.println("  mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
             pw.println("  mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
             pw.println("  mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
+            pw.println("  mScreenBrightnessForVrSettingDefault="
+                    + mScreenBrightnessForVrSettingDefault);
+            pw.println("  mScreenBrightnessForVrSetting=" + mScreenBrightnessForVrSetting);
             pw.println("  mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
+            pw.println("  mIsVrModeEnabled=" + mIsVrModeEnabled);
 
             final int sleepTimeout = getSleepTimeoutLocked();
             final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
@@ -3223,6 +3264,14 @@ public final class PowerManagerService extends SystemService
         @Override
         public void onVrStateChanged(boolean enabled) {
             powerHintInternal(PowerHint.VR_MODE, enabled ? 1 : 0);
+
+            synchronized (mLock) {
+                if (mIsVrModeEnabled != enabled) {
+                    mIsVrModeEnabled = enabled;
+                    mDirty |= DIRTY_VR_MODE_CHANGED;
+                    updatePowerStateLocked();
+                }
+            }
         }
     };
 
@@ -3975,6 +4024,7 @@ public final class PowerManagerService extends SystemService
                 case Display.STATE_DOZE:
                 case Display.STATE_DOZE_SUSPEND:
                 case Display.STATE_ON:
+                case Display.STATE_VR:
                     break;
                 default:
                     screenState = Display.STATE_UNKNOWN;
index a3ab8f6..c7c0e9a 100644 (file)
@@ -103,16 +103,15 @@ static void setLight_native(
         state.flashMode = Flash::NONE;
     } else {
         // Only set non-brightness settings when not in low-persistence mode
-        state.color = colorARGB;
         state.flashMode = flash;
         state.flashOnMs = onMS;
         state.flashOffMs = offMS;
     }
 
+    state.color = colorARGB;
     state.brightnessMode = brightness;
 
     Status status;
-
     {
         ALOGD_IF_SLOW(50, "Excessive delay setting light");
         Return<Status> ret = gLight->setLight(type, state);