Add Brightness setting for VR Mode.
This change saves and loads a different brightness setting when the user
goes in and out of VR Mode.
Test: runtests frameworks-core
Test: Turn vr mode on and change brightness (should remain separate from
normal brightness)
Bug: 30984614
Change-Id: If3c3e81b592e0c6fd037e5783559683e5cb58379
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 477ecdf..015345c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -577,6 +577,9 @@
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 @@
// 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 @@
}
// 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 @@
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
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 61c2eac..8673225 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -471,6 +471,16 @@
}
}
+ // 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 @@
}
}
+ 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("
diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/Light.java
index 0bab86b..b5ec603 100644
--- a/services/core/java/com/android/server/lights/Light.java
+++ b/services/core/java/com/android/server/lights/Light.java
@@ -46,4 +46,5 @@
public abstract void pulse();
public abstract void pulse(int color, int onMS);
public abstract void turnOff();
+ public abstract void setVrMode(boolean enabled);
}
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index bba0a50..e07156e 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -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.
@@ -17,18 +16,13 @@
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 @@
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 @@
@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 @@
@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 @@
}
}
- void enableLowPersistence() {
- synchronized(this) {
- setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_LOW_PERSISTENCE);
- mLocked = true;
- }
- }
+ @Override
+ public void setVrMode(boolean enabled) {
+ synchronized (this) {
+ if (mVrModeEnabled != enabled) {
+ mVrModeEnabled = enabled;
- void disableLowPersistence() {
- synchronized(this) {
- mLocked = false;
- setLightLocked(mLastColor, LIGHT_FLASH_NONE, 0, 0, mLastBrightnessMode);
+ 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 @@
}
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 @@
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 @@
}
}
+ private boolean shouldBeInLowPersistenceMode() {
+ return mVrModeEnabled && mUseLowPersistenceForVR;
+ }
+
private int mId;
private int mColor;
private int mMode;
@@ -149,7 +162,8 @@
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 @@
@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 @@
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) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f2ccac5..8aefebc 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -136,6 +136,8 @@
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 @@
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 @@
// 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 @@
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+ mScreenBrightnessForVrSettingDefault = pm.getDefaultScreenBrightnessForVrSetting();
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -640,6 +650,9 @@
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 @@
}
}
- 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 @@
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 @@
|| !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 @@
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 @@
// 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 @@
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 @@
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
+ ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
+ + ", mIsVrModeEnabled= " + mIsVrModeEnabled
+ ", sQuiescent=" + sQuiescent);
}
}
@@ -2220,6 +2249,10 @@
}
}
+ private boolean shouldBoostScreenBrightness() {
+ return !mIsVrModeEnabled && mScreenBrightnessBoostInProgress;
+ }
+
private static boolean isValidBrightness(int value) {
return value >= 0 && value <= 255;
}
@@ -2230,6 +2263,10 @@
}
private int getDesiredScreenPolicyLocked() {
+ if (mIsVrModeEnabled) {
+ return DisplayPowerRequest.POLICY_VR;
+ }
+
if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
return DisplayPowerRequest.POLICY_OFF;
}
@@ -2333,7 +2370,7 @@
};
private boolean shouldUseProximitySensorLocked() {
- return (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
+ return !mIsVrModeEnabled && (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
}
/**
@@ -3085,7 +3122,11 @@
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 @@
@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 @@
case Display.STATE_DOZE:
case Display.STATE_DOZE_SUSPEND:
case Display.STATE_ON:
+ case Display.STATE_VR:
break;
default:
screenState = Display.STATE_UNKNOWN;
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index cf7f1cb..2fd0603 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -103,16 +103,15 @@
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);