diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ff7288310c8c3b990ef70a3cdf9eaf7a403f846f..9801a0394ffa779f51d02b3484f89b0aec782150 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5647,6 +5647,13 @@ public final class Settings { */ public static final String FORCE_SHOW_NAVBAR = "force_show_navbar"; + /** + * Whether to control brightness from status bar + * 0 = 0ff, 1 = on + * @hide + */ + public static final String STATUS_BAR_BRIGHTNESS_CONTROL = "status_bar_brightness_control"; + /** * Whether to take partial screenshot with volume down + power click. * @hide diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 28c379480f5da022d69dc925cc0ccb20c3110994..46e6fb45d3219544276e860ba96025df9cb11f48 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -70,8 +70,10 @@ import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.PointF; +import android.hardware.display.DisplayManager; import android.metrics.LogMaker; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -94,6 +96,7 @@ import android.util.Log; import android.util.MathUtils; import android.util.Slog; import android.view.Display; +import android.view.HapticFeedbackConstants; import android.view.IRemoteAnimationRunner; import android.view.IWindowManager; import android.view.KeyEvent; @@ -101,6 +104,7 @@ import android.view.MotionEvent; import android.view.RemoteAnimationAdapter; import android.view.ThreadedRenderer; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.WindowInsetsController.Appearance; import android.view.WindowManager; @@ -273,6 +277,10 @@ public class StatusBar extends SystemUI implements private static final String FORCE_SHOW_NAVBAR = "customsystem:" + Settings.System.FORCE_SHOW_NAVBAR; + public static final String SCREEN_BRIGHTNESS_MODE = + "system:" + Settings.System.SCREEN_BRIGHTNESS_MODE; + private static final String STATUS_BAR_BRIGHTNESS_CONTROL = + "customsystem:" + Settings.System.STATUS_BAR_BRIGHTNESS_CONTROL; private static final String BANNER_ACTION_CANCEL = "com.android.systemui.statusbar.banner_action_cancel"; @@ -297,6 +305,7 @@ public class StatusBar extends SystemUI implements private static final int MSG_OPEN_SETTINGS_PANEL = 1002; private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; + private static final int MSG_LONG_PRESS_BRIGHTNESS_CHANGE = 1004; // 1020-1040 reserved for BaseStatusBar // Time after we abort the launch transition. @@ -309,6 +318,10 @@ public class StatusBar extends SystemUI implements */ private static final int HINT_RESET_DELAY_MS = 1200; + private static final float BRIGHTNESS_CONTROL_PADDING = 0.15f; + private static final int BRIGHTNESS_CONTROL_LONG_PRESS_TIMEOUT = 750; // ms + private static final int BRIGHTNESS_CONTROL_LINGER_THRESHOLD = 20; + public static final int FADE_KEYGUARD_START_DELAY = 100; public static final int FADE_KEYGUARD_DURATION = 300; public static final int FADE_KEYGUARD_DURATION_PULSING = 96; @@ -553,6 +566,18 @@ public class StatusBar extends SystemUI implements private StatusBarComponent mStatusBarComponent; + private DisplayManager mDisplayManager; + + private int mMinBrightness; + private int mInitialTouchX; + private int mInitialTouchY; + private int mLinger; + private int mQuickQsOffsetHeight; + private boolean mAutomaticBrightness; + private boolean mBrightnessControl; + private boolean mBrightnessChanged; + private boolean mJustPeeked; + // Flags for disabling the status bar // Two variables becaseu the first one evidently ran out of room for new flags. private int mDisabled1 = 0; @@ -920,6 +945,8 @@ public class StatusBar extends SystemUI implements data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel)); mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT, id -> onLaunchTransitionTimeout()); + mMessageRouter.subscribeTo(MSG_LONG_PRESS_BRIGHTNESS_CHANGE, + id -> onLongPressBrightnessChange()); } @Override @@ -951,6 +978,10 @@ public class StatusBar extends SystemUI implements } mTunerService.addTunable(this, FORCE_SHOW_NAVBAR); + mTunerService.addTunable(this, SCREEN_BRIGHTNESS_MODE); + mTunerService.addTunable(this, STATUS_BAR_BRIGHTNESS_CONTROL); + + mDisplayManager = mContext.getSystemService(DisplayManager.class); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mDreamManager = IDreamManager.Stub.asInterface( @@ -1144,6 +1175,9 @@ public class StatusBar extends SystemUI implements mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener()); mWallpaperController.setRootView(mNotificationShadeWindowView); + mMinBrightness = mContext.getResources().getInteger( + com.android.internal.R.integer.config_screenBrightnessDim); + // TODO: Deal with the ugliness that comes from having some of the statusbar broken out // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. NotificationListContainer notifListContainer = @@ -2120,6 +2154,96 @@ public class StatusBar extends SystemUI implements } } + private void adjustBrightness(int x) { + mBrightnessChanged = true; + float raw = ((float) x) / getDisplayWidth(); + + // Add a padding to the brightness control on both sides to + // make it easier to reach min/max brightness + float padded = Math.min(1.0f - BRIGHTNESS_CONTROL_PADDING, + Math.max(BRIGHTNESS_CONTROL_PADDING, raw)); + float value = (padded - BRIGHTNESS_CONTROL_PADDING) / + (1 - (2.0f * BRIGHTNESS_CONTROL_PADDING)); + if (mAutomaticBrightness) { + float adj = (2 * value) - 1; + adj = Math.max(adj, -1); + adj = Math.min(adj, 1); + final float val = adj; + mDisplayManager.setTemporaryAutoBrightnessAdjustment(val); + AsyncTask.execute(new Runnable() { + public void run() { + Settings.System.putFloatForUser(mContext.getContentResolver(), + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, val, + UserHandle.USER_CURRENT); + } + }); + } else { + int newBrightness = mMinBrightness + (int) Math.round(value * + (PowerManager.BRIGHTNESS_ON - mMinBrightness)); + newBrightness = Math.min(newBrightness, PowerManager.BRIGHTNESS_ON); + newBrightness = Math.max(newBrightness, mMinBrightness); + final int val = newBrightness; + mDisplayManager.setTemporaryBrightness(mDisplayId, val); + AsyncTask.execute(new Runnable() { + @Override + public void run() { + Settings.System.putIntForUser(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS, val, + UserHandle.USER_CURRENT); + } + }); + } + } + + private void brightnessControl(MotionEvent event) { + final int action = event.getAction(); + final int x = (int) event.getRawX(); + final int y = (int) event.getRawY(); + mQuickQsOffsetHeight = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.quick_qs_offset_height); + if (action == MotionEvent.ACTION_DOWN) { + if (y < mQuickQsOffsetHeight) { + mLinger = 0; + mInitialTouchX = x; + mInitialTouchY = y; + mJustPeeked = true; + mMessageRouter.cancelMessages(MSG_LONG_PRESS_BRIGHTNESS_CHANGE); + mMessageRouter.sendMessageDelayed(MSG_LONG_PRESS_BRIGHTNESS_CHANGE, + BRIGHTNESS_CONTROL_LONG_PRESS_TIMEOUT); + } + } else if (action == MotionEvent.ACTION_MOVE) { + if (y < mQuickQsOffsetHeight && mJustPeeked) { + if (mLinger > BRIGHTNESS_CONTROL_LINGER_THRESHOLD) { + adjustBrightness(x); + } else { + final int xDiff = Math.abs(x - mInitialTouchX); + final int yDiff = Math.abs(y - mInitialTouchY); + final int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); + if (xDiff > yDiff) { + mLinger++; + } + if (xDiff > touchSlop || yDiff > touchSlop) { + mMessageRouter.cancelMessages(MSG_LONG_PRESS_BRIGHTNESS_CHANGE); + } + } + } else { + if (y > mQuickQsOffsetHeight) { + mJustPeeked = false; + } + mMessageRouter.cancelMessages(MSG_LONG_PRESS_BRIGHTNESS_CHANGE); + } + } else if (action == MotionEvent.ACTION_UP + || action == MotionEvent.ACTION_CANCEL) { + mMessageRouter.cancelMessages(MSG_LONG_PRESS_BRIGHTNESS_CHANGE); + } + } + + void onLongPressBrightnessChange() { + mStatusBarView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + adjustBrightness(mInitialTouchX); + mLinger = BRIGHTNESS_CONTROL_LINGER_THRESHOLD + 1; + } + /** Called when a touch event occurred on {@link PhoneStatusBarView}. */ public void onTouchEvent(MotionEvent event) { // TODO(b/202981994): Move this touch debugging to a central location. (Right now, it's @@ -2149,12 +2273,26 @@ public class StatusBar extends SystemUI implements mGestureRec.add(event); } + if (mBrightnessControl) { + brightnessControl(event); + if ((mDisabled1 & StatusBarManager.DISABLE_EXPAND) != 0) { + return; + } + } + + final boolean upOrCancel = + event.getAction() == MotionEvent.ACTION_UP || + event.getAction() == MotionEvent.ACTION_CANCEL; + if (mStatusBarWindowState == WINDOW_STATE_SHOWING) { - final boolean upOrCancel = - event.getAction() == MotionEvent.ACTION_UP || - event.getAction() == MotionEvent.ACTION_CANCEL; setInteracting(StatusBarManager.WINDOW_STATUS_BAR, !upOrCancel || mExpandedVisible); } + if (mBrightnessChanged && upOrCancel) { + mBrightnessChanged = false; + if (mJustPeeked && mExpandedVisible) { + mNotificationPanelViewController.fling(10, false); + } + } } boolean isSameStatusBarState(int state) { @@ -4193,6 +4331,12 @@ public class StatusBar extends SystemUI implements mNavigationBarController.onDisplayRemoved(mDisplayId); } } + } else if (SCREEN_BRIGHTNESS_MODE.equals(key)) { + mAutomaticBrightness = Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC == + TunerService.parseInteger(newValue, + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + } else if (STATUS_BAR_BRIGHTNESS_CONTROL.equals(key)) { + mBrightnessControl = TunerService.parseIntegerSwitch(newValue, false); } } // End Extra BaseStatusBarMethods. diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java index 390f8f7dd2724129e2ad28ba83f2db360ef87bcd..f4c4760d2bf3dae906e82623c2af2e8f6e0f70b1 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java @@ -43,6 +43,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.qs.QSTileHost; import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.util.leak.LeakDetector; @@ -70,7 +71,8 @@ public class TunerServiceImpl extends TunerService { QSTileHost.TILES_SETTING, Settings.Secure.DOZE_ALWAYS_ON, Settings.Secure.MEDIA_CONTROLS_RESUME, - Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION + Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, + StatusBar.SCREEN_BRIGHTNESS_MODE, }; private final Observer mObserver = new Observer();