blob: 15e92f48890f4754d7d8c23d4724a6dbffd1351e [file] [log] [blame]
Michael Wright0087a142013-02-05 16:29:39 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.settings;
18
Michael Wrightd8460232018-01-16 18:04:59 +000019import android.animation.ValueAnimator;
Michael Wright0087a142013-02-05 16:29:39 -080020import android.content.ContentResolver;
21import android.content.Context;
Michael Wright0087a142013-02-05 16:29:39 -080022import android.database.ContentObserver;
Michael Wrightd8460232018-01-16 18:04:59 +000023import android.hardware.display.DisplayManager;
Michael Wright0087a142013-02-05 16:29:39 -080024import android.net.Uri;
25import android.os.AsyncTask;
26import android.os.Handler;
27import android.os.IPowerManager;
Jorim Jaggic6da82f2016-08-02 16:11:25 +020028import android.os.Looper;
29import android.os.Message;
Michael Wright0087a142013-02-05 16:29:39 -080030import android.os.PowerManager;
31import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.os.UserHandle;
yuemingweb2bf7d182018-01-23 16:05:08 +000034import android.os.UserManager;
Michael Wright0087a142013-02-05 16:29:39 -080035import android.provider.Settings;
Santos Cordon3107d292016-09-20 15:50:35 -070036import android.service.vr.IVrManager;
37import android.service.vr.IVrStateCallbacks;
38import android.util.Log;
Michael Wright0087a142013-02-05 16:29:39 -080039import android.widget.ImageView;
40
Jason Monk97b87a92015-06-23 15:04:44 -040041import com.android.internal.logging.MetricsLogger;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010042import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
yuemingweb2bf7d182018-01-23 16:05:08 +000043import com.android.settingslib.RestrictedLockUtils;
Jason Monk9c7844c2017-01-18 15:21:53 -050044import com.android.systemui.Dependency;
Jason Monk97b87a92015-06-23 15:04:44 -040045
Michael Wright0087a142013-02-05 16:29:39 -080046import java.util.ArrayList;
47
48public class BrightnessController implements ToggleSlider.Listener {
49 private static final String TAG = "StatusBar.BrightnessController";
John Spurlock6d205262014-06-10 19:26:14 -040050 private static final boolean SHOW_AUTOMATIC_ICON = false;
Michael Wright0087a142013-02-05 16:29:39 -080051
Michael Wrightd8460232018-01-16 18:04:59 +000052 private static final int SLIDER_ANIMATION_DURATION = 3000;
Adrian Roosdaf7d412014-05-13 14:55:09 +020053
Jorim Jaggic6da82f2016-08-02 16:11:25 +020054 private static final int MSG_UPDATE_ICON = 0;
55 private static final int MSG_UPDATE_SLIDER = 1;
56 private static final int MSG_SET_CHECKED = 2;
57 private static final int MSG_ATTACH_LISTENER = 3;
58 private static final int MSG_DETACH_LISTENER = 4;
Santos Cordon3107d292016-09-20 15:50:35 -070059 private static final int MSG_VR_MODE_CHANGED = 5;
Jorim Jaggic6da82f2016-08-02 16:11:25 +020060
Michael Wright0087a142013-02-05 16:29:39 -080061 private final int mMinimumBacklight;
62 private final int mMaximumBacklight;
Santos Cordon3107d292016-09-20 15:50:35 -070063 private final int mMinimumBacklightForVr;
64 private final int mMaximumBacklightForVr;
Michael Wright0087a142013-02-05 16:29:39 -080065
66 private final Context mContext;
67 private final ImageView mIcon;
68 private final ToggleSlider mControl;
69 private final boolean mAutomaticAvailable;
Michael Wrightd8460232018-01-16 18:04:59 +000070 private final DisplayManager mDisplayManager;
Michael Wright0087a142013-02-05 16:29:39 -080071 private final CurrentUserTracker mUserTracker;
Santos Cordon3107d292016-09-20 15:50:35 -070072 private final IVrManager mVrManager;
Jorim Jaggic6da82f2016-08-02 16:11:25 +020073
Jason Monk9c7844c2017-01-18 15:21:53 -050074 private final Handler mBackgroundHandler;
Michael Wright0087a142013-02-05 16:29:39 -080075 private final BrightnessObserver mBrightnessObserver;
76
77 private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
78 new ArrayList<BrightnessStateChangeCallback>();
79
Santos Cordon3107d292016-09-20 15:50:35 -070080 private volatile boolean mAutomatic; // Brightness adjusted automatically using ambient light.
81 private volatile boolean mIsVrModeEnabled;
Jorim Jaggi3f48f462014-07-08 16:53:29 +020082 private boolean mListening;
Adrian Roosb7ebbde2014-08-15 20:11:38 +020083 private boolean mExternalChange;
Michael Wrightd8460232018-01-16 18:04:59 +000084 private boolean mControlInitialized;
85
86 private ValueAnimator mSliderAnimator;
Adrian Roosdaf7d412014-05-13 14:55:09 +020087
Michael Wright0087a142013-02-05 16:29:39 -080088 public interface BrightnessStateChangeCallback {
89 public void onBrightnessLevelChanged();
90 }
91
92 /** ContentObserver to watch brightness **/
93 private class BrightnessObserver extends ContentObserver {
94
95 private final Uri BRIGHTNESS_MODE_URI =
96 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
97 private final Uri BRIGHTNESS_URI =
98 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
Santos Cordon3107d292016-09-20 15:50:35 -070099 private final Uri BRIGHTNESS_FOR_VR_URI =
100 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);
Michael Wright0087a142013-02-05 16:29:39 -0800101
102 public BrightnessObserver(Handler handler) {
103 super(handler);
104 }
105
106 @Override
107 public void onChange(boolean selfChange) {
108 onChange(selfChange, null);
109 }
110
111 @Override
112 public void onChange(boolean selfChange, Uri uri) {
113 if (selfChange) return;
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200114
115 if (BRIGHTNESS_MODE_URI.equals(uri)) {
116 mBackgroundHandler.post(mUpdateModeRunnable);
117 mBackgroundHandler.post(mUpdateSliderRunnable);
Michael Wrightd8460232018-01-16 18:04:59 +0000118 } else if (BRIGHTNESS_URI.equals(uri)) {
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200119 mBackgroundHandler.post(mUpdateSliderRunnable);
Santos Cordon3107d292016-09-20 15:50:35 -0700120 } else if (BRIGHTNESS_FOR_VR_URI.equals(uri)) {
121 mBackgroundHandler.post(mUpdateSliderRunnable);
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200122 } else {
123 mBackgroundHandler.post(mUpdateModeRunnable);
124 mBackgroundHandler.post(mUpdateSliderRunnable);
125 }
126 for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
127 cb.onBrightnessLevelChanged();
Michael Wright0087a142013-02-05 16:29:39 -0800128 }
129 }
130
131 public void startObserving() {
132 final ContentResolver cr = mContext.getContentResolver();
133 cr.unregisterContentObserver(this);
134 cr.registerContentObserver(
135 BRIGHTNESS_MODE_URI,
136 false, this, UserHandle.USER_ALL);
137 cr.registerContentObserver(
138 BRIGHTNESS_URI,
139 false, this, UserHandle.USER_ALL);
Adrian Roosdaf7d412014-05-13 14:55:09 +0200140 cr.registerContentObserver(
Santos Cordon3107d292016-09-20 15:50:35 -0700141 BRIGHTNESS_FOR_VR_URI,
142 false, this, UserHandle.USER_ALL);
Michael Wright0087a142013-02-05 16:29:39 -0800143 }
144
145 public void stopObserving() {
146 final ContentResolver cr = mContext.getContentResolver();
147 cr.unregisterContentObserver(this);
148 }
149
150 }
151
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200152 private final Runnable mStartListeningRunnable = new Runnable() {
153 @Override
154 public void run() {
155 mBrightnessObserver.startObserving();
156 mUserTracker.startTracking();
157
158 // Update the slider and mode before attaching the listener so we don't
159 // receive the onChanged notifications for the initial values.
160 mUpdateModeRunnable.run();
161 mUpdateSliderRunnable.run();
162
163 mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
164 }
165 };
166
167 private final Runnable mStopListeningRunnable = new Runnable() {
168 @Override
169 public void run() {
170 mBrightnessObserver.stopObserving();
171 mUserTracker.stopTracking();
172
173 mHandler.sendEmptyMessage(MSG_DETACH_LISTENER);
174 }
175 };
176
177 /**
178 * Fetch the brightness mode from the system settings and update the icon. Should be called from
179 * background thread.
180 */
181 private final Runnable mUpdateModeRunnable = new Runnable() {
182 @Override
183 public void run() {
184 if (mAutomaticAvailable) {
185 int automatic;
186 automatic = Settings.System.getIntForUser(mContext.getContentResolver(),
187 Settings.System.SCREEN_BRIGHTNESS_MODE,
188 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
189 UserHandle.USER_CURRENT);
190 mAutomatic = automatic != Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
191 mHandler.obtainMessage(MSG_UPDATE_ICON, mAutomatic ? 1 : 0).sendToTarget();
192 } else {
193 mHandler.obtainMessage(MSG_SET_CHECKED, 0).sendToTarget();
194 mHandler.obtainMessage(MSG_UPDATE_ICON, 0 /* automatic */).sendToTarget();
195 }
196 }
197 };
198
199 /**
200 * Fetch the brightness from the system settings and update the slider. Should be called from
201 * background thread.
202 */
203 private final Runnable mUpdateSliderRunnable = new Runnable() {
204 @Override
205 public void run() {
Santos Cordon3107d292016-09-20 15:50:35 -0700206 if (mIsVrModeEnabled) {
207 int value = Settings.System.getIntForUser(mContext.getContentResolver(),
208 Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mMaximumBacklight,
209 UserHandle.USER_CURRENT);
210 mHandler.obtainMessage(MSG_UPDATE_SLIDER,
211 mMaximumBacklightForVr - mMinimumBacklightForVr,
212 value - mMinimumBacklightForVr).sendToTarget();
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200213 } else {
214 int value;
215 value = Settings.System.getIntForUser(mContext.getContentResolver(),
216 Settings.System.SCREEN_BRIGHTNESS, mMaximumBacklight,
217 UserHandle.USER_CURRENT);
218 mHandler.obtainMessage(MSG_UPDATE_SLIDER, mMaximumBacklight - mMinimumBacklight,
219 value - mMinimumBacklight).sendToTarget();
220 }
221 }
222 };
223
Santos Cordon3107d292016-09-20 15:50:35 -0700224 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
225 @Override
226 public void onVrStateChanged(boolean enabled) {
227 mHandler.obtainMessage(MSG_VR_MODE_CHANGED, enabled ? 1 : 0, 0)
228 .sendToTarget();
229 }
230 };
231
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200232 private final Handler mHandler = new Handler() {
233 @Override
234 public void handleMessage(Message msg) {
235 mExternalChange = true;
236 try {
237 switch (msg.what) {
238 case MSG_UPDATE_ICON:
239 updateIcon(msg.arg1 != 0);
240 break;
241 case MSG_UPDATE_SLIDER:
242 mControl.setMax(msg.arg1);
Michael Wrightd8460232018-01-16 18:04:59 +0000243 animateSliderTo(msg.arg2);
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200244 break;
245 case MSG_SET_CHECKED:
246 mControl.setChecked(msg.arg1 != 0);
247 break;
248 case MSG_ATTACH_LISTENER:
249 mControl.setOnChangedListener(BrightnessController.this);
250 break;
251 case MSG_DETACH_LISTENER:
252 mControl.setOnChangedListener(null);
Jorim Jaggi4adee262016-09-21 14:49:46 -0700253 break;
Santos Cordon3107d292016-09-20 15:50:35 -0700254 case MSG_VR_MODE_CHANGED:
255 updateVrMode(msg.arg1 != 0);
256 break;
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200257 default:
258 super.handleMessage(msg);
259 }
260 } finally {
261 mExternalChange = false;
262 }
263 }
264 };
265
Michael Wright0087a142013-02-05 16:29:39 -0800266 public BrightnessController(Context context, ImageView icon, ToggleSlider control) {
267 mContext = context;
268 mIcon = icon;
269 mControl = control;
Jason Monk9c7844c2017-01-18 15:21:53 -0500270 mBackgroundHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
Michael Wright0087a142013-02-05 16:29:39 -0800271 mUserTracker = new CurrentUserTracker(mContext) {
272 @Override
273 public void onUserSwitched(int newUserId) {
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200274 mBackgroundHandler.post(mUpdateModeRunnable);
275 mBackgroundHandler.post(mUpdateSliderRunnable);
Michael Wright0087a142013-02-05 16:29:39 -0800276 }
277 };
278 mBrightnessObserver = new BrightnessObserver(mHandler);
Michael Wright0087a142013-02-05 16:29:39 -0800279
280 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
281 mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
282 mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
Santos Cordon3107d292016-09-20 15:50:35 -0700283 mMinimumBacklightForVr = pm.getMinimumScreenBrightnessForVrSetting();
284 mMaximumBacklightForVr = pm.getMaximumScreenBrightnessForVrSetting();
Michael Wright0087a142013-02-05 16:29:39 -0800285
286 mAutomaticAvailable = context.getResources().getBoolean(
287 com.android.internal.R.bool.config_automatic_brightness_available);
Michael Wrightd8460232018-01-16 18:04:59 +0000288 mDisplayManager = context.getSystemService(DisplayManager.class);
Craig Donner8deb67c2017-02-07 18:10:32 -0800289 mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
290 Context.VR_SERVICE));
Michael Wright0087a142013-02-05 16:29:39 -0800291 }
292
293 public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
294 mChangeCallbacks.add(cb);
295 }
296
297 public boolean removeStateChangedCallback(BrightnessStateChangeCallback cb) {
298 return mChangeCallbacks.remove(cb);
299 }
300
301 @Override
302 public void onInit(ToggleSlider control) {
303 // Do nothing
304 }
305
Jorim Jaggif056e352014-05-11 23:09:22 +0200306 public void registerCallbacks() {
Jorim Jaggi3f48f462014-07-08 16:53:29 +0200307 if (mListening) {
308 return;
309 }
Alan Viverette5a399492014-07-14 16:19:38 -0700310
Santos Cordon3107d292016-09-20 15:50:35 -0700311 if (mVrManager != null) {
312 try {
313 mVrManager.registerListener(mVrStateCallbacks);
314 mIsVrModeEnabled = mVrManager.getVrModeState();
315 } catch (RemoteException e) {
316 Log.e(TAG, "Failed to register VR mode state listener: ", e);
317 }
318 }
319
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200320 mBackgroundHandler.post(mStartListeningRunnable);
Alan Viverette5a399492014-07-14 16:19:38 -0700321 mListening = true;
Jorim Jaggif056e352014-05-11 23:09:22 +0200322 }
323
Michael Wright0087a142013-02-05 16:29:39 -0800324 /** Unregister all call backs, both to and from the controller */
325 public void unregisterCallbacks() {
Jorim Jaggi3f48f462014-07-08 16:53:29 +0200326 if (!mListening) {
327 return;
328 }
Alan Viverette5a399492014-07-14 16:19:38 -0700329
Santos Cordon3107d292016-09-20 15:50:35 -0700330 if (mVrManager != null) {
331 try {
332 mVrManager.unregisterListener(mVrStateCallbacks);
333 } catch (RemoteException e) {
334 Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
335 }
336 }
337
Jorim Jaggic6da82f2016-08-02 16:11:25 +0200338 mBackgroundHandler.post(mStopListeningRunnable);
Alan Viverette5a399492014-07-14 16:19:38 -0700339 mListening = false;
Michael Wright0087a142013-02-05 16:29:39 -0800340 }
341
Adrian Roos5fd872e2014-08-12 17:28:58 +0200342 @Override
Muyuan Li3b0f8922016-04-18 19:27:29 -0700343 public void onChanged(ToggleSlider toggleSlider, boolean tracking, boolean automatic,
344 int value, boolean stopTracking) {
Adrian Roosdaf7d412014-05-13 14:55:09 +0200345 updateIcon(mAutomatic);
Adrian Roosb7ebbde2014-08-15 20:11:38 +0200346 if (mExternalChange) return;
347
Michael Wrightd8460232018-01-16 18:04:59 +0000348 if (mSliderAnimator != null) {
349 mSliderAnimator.cancel();
350 }
351
Santos Cordon3107d292016-09-20 15:50:35 -0700352 if (mIsVrModeEnabled) {
353 final int val = value + mMinimumBacklightForVr;
354 if (stopTracking) {
355 MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_FOR_VR, val);
356 }
357 setBrightness(val);
358 if (!tracking) {
359 AsyncTask.execute(new Runnable() {
360 public void run() {
361 Settings.System.putIntForUser(mContext.getContentResolver(),
362 Settings.System.SCREEN_BRIGHTNESS_FOR_VR, val,
363 UserHandle.USER_CURRENT);
364 }
365 });
366 }
Michael Wrightd8460232018-01-16 18:04:59 +0000367 } else {
Michael Wright0087a142013-02-05 16:29:39 -0800368 final int val = value + mMinimumBacklight;
Jason Monk97b87a92015-06-23 15:04:44 -0400369 if (stopTracking) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500370 MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
Jason Monk97b87a92015-06-23 15:04:44 -0400371 }
Michael Wright0087a142013-02-05 16:29:39 -0800372 setBrightness(val);
373 if (!tracking) {
374 AsyncTask.execute(new Runnable() {
375 public void run() {
376 Settings.System.putIntForUser(mContext.getContentResolver(),
377 Settings.System.SCREEN_BRIGHTNESS, val,
378 UserHandle.USER_CURRENT);
379 }
380 });
381 }
382 }
383
384 for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
385 cb.onBrightnessLevelChanged();
386 }
387 }
388
yuemingweb2bf7d182018-01-23 16:05:08 +0000389 public void checkRestrictionAndSetEnabled() {
390 mBackgroundHandler.post(new Runnable() {
391 @Override
392 public void run() {
393 ((ToggleSliderView)mControl).setEnforcedAdmin(
394 RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
395 UserManager.DISALLOW_CONFIG_BRIGHTNESS,
396 mUserTracker.getCurrentUserId()));
397 }
398 });
399 }
400
Michael Wright0087a142013-02-05 16:29:39 -0800401 private void setMode(int mode) {
402 Settings.System.putIntForUser(mContext.getContentResolver(),
403 Settings.System.SCREEN_BRIGHTNESS_MODE, mode,
404 mUserTracker.getCurrentUserId());
405 }
406
407 private void setBrightness(int brightness) {
Michael Wrightd8460232018-01-16 18:04:59 +0000408 mDisplayManager.setTemporaryBrightness(brightness);
Michael Wright0087a142013-02-05 16:29:39 -0800409 }
410
Adrian Roos6e2d4652014-05-14 20:01:43 +0200411 private void setBrightnessAdj(float adj) {
Michael Wrightd8460232018-01-16 18:04:59 +0000412 mDisplayManager.setTemporaryAutoBrightnessAdjustment(adj);
Adrian Roosdaf7d412014-05-13 14:55:09 +0200413 }
414
Michael Wright0087a142013-02-05 16:29:39 -0800415 private void updateIcon(boolean automatic) {
416 if (mIcon != null) {
John Spurlock6d205262014-06-10 19:26:14 -0400417 mIcon.setImageResource(automatic && SHOW_AUTOMATIC_ICON ?
Michael Wright0087a142013-02-05 16:29:39 -0800418 com.android.systemui.R.drawable.ic_qs_brightness_auto_on :
419 com.android.systemui.R.drawable.ic_qs_brightness_auto_off);
420 }
421 }
Santos Cordon3107d292016-09-20 15:50:35 -0700422
423 private void updateVrMode(boolean isEnabled) {
424 if (mIsVrModeEnabled != isEnabled) {
425 mIsVrModeEnabled = isEnabled;
426 mBackgroundHandler.post(mUpdateSliderRunnable);
427 }
428 }
Michael Wrightd8460232018-01-16 18:04:59 +0000429
430 private void animateSliderTo(int target) {
431 if (!mControlInitialized) {
432 // Don't animate the first value since it's default state isn't meaningful to users.
433 mControl.setValue(target);
434 mControlInitialized = true;
435 }
436 if (mSliderAnimator != null && mSliderAnimator.isStarted()) {
437 mSliderAnimator.cancel();
438 }
439 mSliderAnimator = ValueAnimator.ofInt(mControl.getValue(), target);
440 mSliderAnimator.addUpdateListener((ValueAnimator animation) -> {
441 mExternalChange = true;
442 mControl.setValue((int)animation.getAnimatedValue());
443 mExternalChange = false;
444 });
445 mSliderAnimator.setDuration(SLIDER_ANIMATION_DURATION);
446 mSliderAnimator.start();
447 }
Michael Wright0087a142013-02-05 16:29:39 -0800448}