diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 7a2b840ae9a5420164b9d4773a51fda6d6744fb4..cd0fb44ac753fc5b3241b2b4decc36ca2e520550 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -481,7 +481,8 @@ public final class PowerManager { BRIGHTNESS_CONSTRAINT_TYPE_DOZE, BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR, BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR, - BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR + BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR, + BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_BUTTON }) @Retention(RetentionPolicy.SOURCE) public @interface BrightnessConstraint{} @@ -533,6 +534,12 @@ public final class PowerManager { */ public static final int BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR = 7; + /** + * Brightness constraint type: minimum allowed value. + * @hide + */ + public static final int BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_BUTTON = 8; + /** * @hide */ diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index eb18b96e255b389ea38cb38f4190b0f8280ea824..fca3e76541d0fdaaa473aeea9a6304666b4784f2 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -107,6 +107,16 @@ public abstract class PowerManagerInternal { */ public abstract void setScreenBrightnessOverrideFromWindowManager(float brightness); + /** + * Used by the window manager to override the button brightness based on the + * current foreground activity. + * + * This method must only be called by the window manager. + * + * @param brightness The overridden brightness, or Float.NaN to disable the override. + */ + public abstract void setButtonBrightnessOverrideFromWindowManager(float brightness); + /** * Used by the window manager to override the user activity timeout based on the * current foreground activity. It can only be used to make the timeout shorter diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 75784308fe81b2482007155d36e00b5c636ec341..179833112c508499cf2e3269e7315c481443c97d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10781,6 +10781,21 @@ public final class Settings { public static final int RING_HOME_BUTTON_BEHAVIOR_DEFAULT = RING_HOME_BUTTON_BEHAVIOR_DO_NOTHING; + /** + * The time in ms to keep the button backlight on after pressing a button. + * A value of 0 will keep the buttons on for as long as the screen is on. + * @hide + */ + public static final String BUTTON_BACKLIGHT_TIMEOUT = "button_backlight_timeout"; + + /** + * The button brightness to be used while the screen is on or after a button press, + * depending on the value of {@link BUTTON_BACKLIGHT_TIMEOUT}. + * Valid value range is between 0 and {@link PowerManager#getMaximumButtonBrightness()} + * @hide + */ + public static final String BUTTON_BRIGHTNESS = "button_brightness"; + /** * These entries are considered common between the personal and the managed profile, * since the managed profile doesn't get to change them. diff --git a/core/res/res/values/lmodroid_config.xml b/core/res/res/values/lmodroid_config.xml index 8a4c2db6b9502245761bca450513c69f87ca146d..282af1ccd99ea13b0211c562bf97d5ef98876840 100644 --- a/core/res/res/values/lmodroid_config.xml +++ b/core/res/res/values/lmodroid_config.xml @@ -142,4 +142,12 @@ (without "Focus" state) instead of Dual-stage. --> <bool name="config_singleStageCameraKey">false</bool> + <!-- Button backlight control. Possible values are: + 0 - Not supported + 1 - Supported, but only on/off mode + 2 - Supported with variable brightness control + --> + <integer name="config_deviceSupportsButtonBrightnessControl">0</integer> + <dimen name="config_buttonBrightnessSettingDefaultFloat">1.0</dimen> + </resources> diff --git a/core/res/res/values/lmodroid_symbols.xml b/core/res/res/values/lmodroid_symbols.xml index e53fcf0eb92bba364cfb8f8272ff3254cb662077..e787bfc4cff5d313161a710adf3191b6bec41a32 100644 --- a/core/res/res/values/lmodroid_symbols.xml +++ b/core/res/res/values/lmodroid_symbols.xml @@ -59,4 +59,8 @@ <!-- Camera key type --> <java-symbol type="bool" name="config_singleStageCameraKey" /> + <!-- Button backlight --> + <java-symbol type="integer" name="config_deviceSupportsButtonBrightnessControl" /> + <java-symbol type="dimen" name="config_buttonBrightnessSettingDefaultFloat" /> + </resources> diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 22dd2c05c1578f79f0389eca7f971e57a5f1e49b..489faaefd2b8968a042416fc424b51fc12a48a2e 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -68,6 +68,8 @@ import com.android.server.display.utils.SensorUtils; import com.android.server.display.whitebalance.DisplayWhiteBalanceController; import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory; import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings; +import com.android.server.lights.LightsManager; +import com.android.server.lights.LogicalLight; import com.android.server.policy.WindowManagerPolicy; import java.io.PrintWriter; @@ -164,6 +166,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Nullable private final IBatteryStats mBatteryStats; + // The lights service. + private final LightsManager mLights; + // The sensor manager. private final SensorManager mSensorManager; @@ -459,6 +464,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); mHandler = new DisplayControllerHandler(handler.getLooper()); + mLights = LocalServices.getService(LightsManager.class); if (mDisplayId == Display.DEFAULT_DISPLAY) { mBatteryStats = BatteryStatsService.getService(); @@ -1123,6 +1129,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (state == Display.STATE_OFF) { brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT; mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF); + LogicalLight buttonsLight = mLights.getLight(LightsManager.LIGHT_ID_BUTTONS); + if (buttonsLight != null) { + buttonsLight.setBrightness(brightnessState); + } + } + + // Disable button lights when dozing + if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) { + LogicalLight buttonsLight = mLights.getLight(LightsManager.LIGHT_ID_BUTTONS); + if (buttonsLight != null) { + buttonsLight.setBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT); + } } // Always use the VR brightness when in the VR state. diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 14fd18f053f6e00e8202605b312bf80f3d6ec6ab..aa04a957de612075ef7d78dccd8be446b5bb1ce8 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -19,6 +19,7 @@ package com.android.server.power; import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.policyToString; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT; +import static android.os.PowerManager.BRIGHTNESS_OFF_FLOAT; import static android.os.PowerManager.GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF; import static android.os.PowerManager.GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED; import static android.os.PowerManager.WAKE_REASON_DISPLAY_GROUP_ADDED; @@ -275,6 +276,8 @@ public final class PowerManagerService extends SystemService private static final float PROXIMITY_NEAR_THRESHOLD = 5.0f; + private static final int DEFAULT_BUTTON_ON_DURATION = 5 * 1000; + private final Context mContext; private final ServiceThread mHandlerThread; private final Handler mHandler; @@ -304,6 +307,10 @@ public final class PowerManagerService extends SystemService private SettingsObserver mSettingsObserver; private DreamManagerInternal mDreamManager; private LogicalLight mAttentionLight; + private LogicalLight mButtonsLight; + + private int mButtonTimeout; + private float mButtonBrightness; private InattentiveSleepWarningController mInattentiveSleepWarningOverlayController; private final AmbientDisplaySuppressionController mAmbientDisplaySuppressionController; @@ -563,6 +570,9 @@ public final class PowerManagerService extends SystemService public final float mScreenBrightnessMaximumVr; public final float mScreenBrightnessDefaultVr; + // Button brightness + public final float mButtonBrightnessDefault; + // Value we store for tracking face down behavior. private boolean mIsFaceDown = false; private long mLastFlipTime = 0L; @@ -571,6 +581,11 @@ public final class PowerManagerService extends SystemService // One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants. private int mScreenBrightnessModeSetting; + // The button brightness setting override from the window manager + // to allow the current foreground activity to override the button brightness. + private float mButtonBrightnessOverrideFromWindowManager = + PowerManager.BRIGHTNESS_INVALID_FLOAT; + // The screen brightness setting override from the window manager // to allow the current foreground activity to override the brightness. private float mScreenBrightnessOverrideFromWindowManager = @@ -1071,6 +1086,10 @@ public final class PowerManagerService extends SystemService mScreenBrightnessDefaultVr = vrDef; } + mButtonBrightnessDefault = mContext.getResources().getFloat( + com.android.internal.R.dimen + .config_buttonBrightnessSettingDefaultFloat); + synchronized (mLock) { mWakeLockSuspendBlocker = mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks"); @@ -1186,6 +1205,7 @@ public final class PowerManagerService extends SystemService mLightsManager = getLocalService(LightsManager.class); mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION); + mButtonsLight = mLightsManager.getLight(LightsManager.LIGHT_ID_BUTTONS); // Initialize display power management. mDisplayManagerInternal.initPowerManagement( @@ -1266,6 +1286,12 @@ public final class PowerManagerService extends SystemService resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.FORCE_SHOW_NAVBAR), false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.BUTTON_BRIGHTNESS), + false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.BUTTON_BACKLIGHT_TIMEOUT), + false, mSettingsObserver, UserHandle.USER_ALL); IVrManager vrManager = IVrManager.Stub.asInterface(getBinderService(Context.VR_SERVICE)); if (vrManager != null) { try { @@ -1412,6 +1438,13 @@ public final class PowerManagerService extends SystemService Settings.System.FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; + mButtonTimeout = Settings.Secure.getIntForUser(resolver, + Settings.Secure.BUTTON_BACKLIGHT_TIMEOUT, + DEFAULT_BUTTON_ON_DURATION, UserHandle.USER_CURRENT); + mButtonBrightness = Settings.Secure.getFloatForUser(resolver, + Settings.Secure.BUTTON_BRIGHTNESS, mButtonBrightnessDefault, + UserHandle.USER_CURRENT); + mDirty |= DIRTY_SETTINGS; } @@ -2615,10 +2648,43 @@ public final class PowerManagerService extends SystemService groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; + if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) { + if (mButtonsLight != null) { + float buttonBrightness = BRIGHTNESS_OFF_FLOAT; + if (!mForceNavbar) { + if (isValidBrightness( + mButtonBrightnessOverrideFromWindowManager)) { + if (mButtonBrightnessOverrideFromWindowManager > + PowerManager.BRIGHTNESS_MIN) { + buttonBrightness = + mButtonBrightnessOverrideFromWindowManager; + } + } else if (isValidButtonBrightness(mButtonBrightness)) { + buttonBrightness = mButtonBrightness; + } + } + + if (mButtonTimeout != 0 && + now > lastUserActivityTime + mButtonTimeout) { + mButtonsLight.setBrightness(BRIGHTNESS_OFF_FLOAT); + } else { + mButtonsLight.setBrightness(buttonBrightness); + if (buttonBrightness != BRIGHTNESS_OFF_FLOAT && + mButtonTimeout != 0) { + groupNextTimeout = now + mButtonTimeout; + } + } + } + } } else { groupNextTimeout = lastUserActivityTime + screenOffTimeout; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; + if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) { + if (mButtonsLight != null) { + mButtonsLight.setBrightness(BRIGHTNESS_OFF_FLOAT); + } + } } } } @@ -3340,6 +3406,10 @@ public final class PowerManagerService extends SystemService return value >= PowerManager.BRIGHTNESS_MIN && value <= PowerManager.BRIGHTNESS_MAX; } + private static boolean isValidButtonBrightness(float value) { + return value > PowerManager.BRIGHTNESS_MIN && value <= PowerManager.BRIGHTNESS_MAX; + } + @VisibleForTesting int getDesiredScreenPolicyLocked(int groupId) { final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId); @@ -4000,6 +4070,17 @@ public final class PowerManagerService extends SystemService } } + private void setButtonBrightnessOverrideFromWindowManagerInternal(float brightness) { + synchronized (mLock) { + if (!BrightnessSynchronizer.floatEquals(mButtonBrightnessOverrideFromWindowManager, + brightness)) { + mButtonBrightnessOverrideFromWindowManager = brightness; + mDirty |= DIRTY_SETTINGS; + updatePowerStateLocked(); + } + } + } + private void setScreenBrightnessOverrideFromWindowManagerInternal(float brightness) { synchronized (mLock) { if (!BrightnessSynchronizer.floatEquals(mScreenBrightnessOverrideFromWindowManager, @@ -4306,7 +4387,11 @@ public final class PowerManagerService extends SystemService + mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced=" + isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() + ")"); pw.println(" mStayOnWhilePluggedInSetting=" + mStayOnWhilePluggedInSetting); + pw.println(" mButtonTimeout=" + mButtonTimeout); + pw.println(" mButtonBrightness=" + mButtonBrightness); pw.println(" mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting); + pw.println(" mButtonBrightnessOverrideFromWindowManager=" + + mButtonBrightnessOverrideFromWindowManager); pw.println(" mScreenBrightnessOverrideFromWindowManager=" + mScreenBrightnessOverrideFromWindowManager); pw.println(" mUserActivityTimeoutOverrideFromWindowManager=" @@ -5458,6 +5543,8 @@ public final class PowerManagerService extends SystemService return mScreenBrightnessMaximumVr; case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR: return mScreenBrightnessDefaultVr; + case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_BUTTON: + return mButtonBrightnessDefault; default: return PowerManager.BRIGHTNESS_INVALID_FLOAT; } @@ -6110,6 +6197,18 @@ public final class PowerManagerService extends SystemService @VisibleForTesting final class LocalService extends PowerManagerInternal { + @Override + public void setButtonBrightnessOverrideFromWindowManager(float screenBrightness) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); + + final long ident = Binder.clearCallingIdentity(); + try { + setButtonBrightnessOverrideFromWindowManagerInternal(screenBrightness); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + @Override public void setScreenBrightnessOverrideFromWindowManager(float screenBrightness) { if (screenBrightness < PowerManager.BRIGHTNESS_MIN diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index fbc8f73b53b00183f1d53d7118874cb2936c0b18..1a71744c6d4d28d2d0417fc9039344e7ad9d787f 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -177,6 +177,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> implements DisplayManager.DisplayListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM; + private static final int SET_BUTTON_BRIGHTNESS_OVERRIDE = 0; private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1; private static final int SET_USER_ACTIVITY_TIMEOUT = 2; static final String TAG_TASKS = TAG + POSTFIX_TASKS; @@ -185,6 +186,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> private Object mLastWindowFreezeSource = null; private Session mHoldScreen = null; + private float mButtonBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT; private float mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT; private long mUserActivityTimeout = -1; private boolean mUpdateRotation = false; @@ -848,6 +850,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } mHoldScreen = null; + mButtonBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT; mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT; mUserActivityTimeout = -1; mObscureApplicationContentOnSecondaryDisplays = false; @@ -968,13 +971,21 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mWmService.setHoldScreenLocked(mHoldScreen); if (!mWmService.mDisplayFrozen) { - final float brightnessOverride = mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN + final float buttonBrightnessOverride = + mButtonBrightnessOverride < PowerManager.BRIGHTNESS_MIN + || mButtonBrightnessOverride > PowerManager.BRIGHTNESS_MAX + ? PowerManager.BRIGHTNESS_INVALID_FLOAT : mButtonBrightnessOverride; + final float screenBrightnessOverride = + mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN || mScreenBrightnessOverride > PowerManager.BRIGHTNESS_MAX ? PowerManager.BRIGHTNESS_INVALID_FLOAT : mScreenBrightnessOverride; - int brightnessFloatAsIntBits = Float.floatToIntBits(brightnessOverride); + int buttonBrightnessFloatAsIntBits = Float.floatToIntBits(buttonBrightnessOverride); + int screenBrightnessFloatAsIntBits = Float.floatToIntBits(screenBrightnessOverride); // Post these on a handler such that we don't call into power manager service while // holding the window manager lock to avoid lock contention with power manager lock. - mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightnessFloatAsIntBits, + mHandler.obtainMessage(SET_BUTTON_BRIGHTNESS_OVERRIDE, buttonBrightnessFloatAsIntBits, + 0).sendToTarget(); + mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, screenBrightnessFloatAsIntBits, 0).sendToTarget(); mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget(); } @@ -1151,6 +1162,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> + "has FLAG_KEEP_SCREEN_ON!!! called by%s", w, Debug.getCallers(10)); } + if (!syswin && w.mAttrs.buttonBrightness >= 0 + && Float.isNaN(mButtonBrightnessOverride)) { + mButtonBrightnessOverride = w.mAttrs.buttonBrightness; + } if (!syswin && w.mAttrs.screenBrightness >= 0 && Float.isNaN(mScreenBrightnessOverride)) { mScreenBrightnessOverride = w.mAttrs.screenBrightness; @@ -1223,6 +1238,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> @Override public void handleMessage(Message msg) { switch (msg.what) { + case SET_BUTTON_BRIGHTNESS_OVERRIDE: + mWmService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( + Float.intBitsToFloat(msg.arg1)); + break; case SET_SCREEN_BRIGHTNESS_OVERRIDE: mWmService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( Float.intBitsToFloat(msg.arg1));