Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.systemui.settings; |
| 18 | |
| 19 | import android.content.ContentResolver; |
| 20 | import android.content.Context; |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 21 | import android.database.ContentObserver; |
| 22 | import android.net.Uri; |
| 23 | import android.os.AsyncTask; |
| 24 | import android.os.Handler; |
| 25 | import android.os.IPowerManager; |
| 26 | import android.os.PowerManager; |
| 27 | import android.os.RemoteException; |
| 28 | import android.os.ServiceManager; |
| 29 | import android.os.UserHandle; |
| 30 | import android.provider.Settings; |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 31 | import android.widget.ImageView; |
| 32 | |
Jason Monk | 97b87a9 | 2015-06-23 15:04:44 -0400 | [diff] [blame^] | 33 | import com.android.internal.logging.MetricsLogger; |
| 34 | |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 35 | import java.util.ArrayList; |
| 36 | |
| 37 | public class BrightnessController implements ToggleSlider.Listener { |
| 38 | private static final String TAG = "StatusBar.BrightnessController"; |
John Spurlock | 6d20526 | 2014-06-10 19:26:14 -0400 | [diff] [blame] | 39 | private static final boolean SHOW_AUTOMATIC_ICON = false; |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 40 | |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 41 | /** |
| 42 | * {@link android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ} uses the range [-1, 1]. |
| 43 | * Using this factor, it is converted to [0, BRIGHTNESS_ADJ_RESOLUTION] for the SeekBar. |
| 44 | */ |
Adrian Roos | 27a2ce2 | 2015-06-02 13:44:46 -0700 | [diff] [blame] | 45 | private static final float BRIGHTNESS_ADJ_RESOLUTION = 2048; |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 46 | |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 47 | private final int mMinimumBacklight; |
| 48 | private final int mMaximumBacklight; |
| 49 | |
| 50 | private final Context mContext; |
| 51 | private final ImageView mIcon; |
| 52 | private final ToggleSlider mControl; |
| 53 | private final boolean mAutomaticAvailable; |
| 54 | private final IPowerManager mPower; |
| 55 | private final CurrentUserTracker mUserTracker; |
| 56 | private final Handler mHandler; |
| 57 | private final BrightnessObserver mBrightnessObserver; |
| 58 | |
| 59 | private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks = |
| 60 | new ArrayList<BrightnessStateChangeCallback>(); |
| 61 | |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 62 | private boolean mAutomatic; |
Jorim Jaggi | 3f48f46 | 2014-07-08 16:53:29 +0200 | [diff] [blame] | 63 | private boolean mListening; |
Adrian Roos | b7ebbde | 2014-08-15 20:11:38 +0200 | [diff] [blame] | 64 | private boolean mExternalChange; |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 65 | |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 66 | public interface BrightnessStateChangeCallback { |
| 67 | public void onBrightnessLevelChanged(); |
| 68 | } |
| 69 | |
| 70 | /** ContentObserver to watch brightness **/ |
| 71 | private class BrightnessObserver extends ContentObserver { |
| 72 | |
| 73 | private final Uri BRIGHTNESS_MODE_URI = |
| 74 | Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE); |
| 75 | private final Uri BRIGHTNESS_URI = |
| 76 | Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 77 | private final Uri BRIGHTNESS_ADJ_URI = |
| 78 | Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ); |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 79 | |
| 80 | public BrightnessObserver(Handler handler) { |
| 81 | super(handler); |
| 82 | } |
| 83 | |
| 84 | @Override |
| 85 | public void onChange(boolean selfChange) { |
| 86 | onChange(selfChange, null); |
| 87 | } |
| 88 | |
| 89 | @Override |
| 90 | public void onChange(boolean selfChange, Uri uri) { |
| 91 | if (selfChange) return; |
Adrian Roos | b7ebbde | 2014-08-15 20:11:38 +0200 | [diff] [blame] | 92 | try { |
| 93 | mExternalChange = true; |
| 94 | if (BRIGHTNESS_MODE_URI.equals(uri)) { |
| 95 | updateMode(); |
| 96 | updateSlider(); |
| 97 | } else if (BRIGHTNESS_URI.equals(uri) && !mAutomatic) { |
| 98 | updateSlider(); |
| 99 | } else if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) { |
| 100 | updateSlider(); |
| 101 | } else { |
| 102 | updateMode(); |
| 103 | updateSlider(); |
| 104 | } |
| 105 | for (BrightnessStateChangeCallback cb : mChangeCallbacks) { |
| 106 | cb.onBrightnessLevelChanged(); |
| 107 | } |
| 108 | } finally { |
| 109 | mExternalChange = false; |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 110 | } |
| 111 | } |
| 112 | |
| 113 | public void startObserving() { |
| 114 | final ContentResolver cr = mContext.getContentResolver(); |
| 115 | cr.unregisterContentObserver(this); |
| 116 | cr.registerContentObserver( |
| 117 | BRIGHTNESS_MODE_URI, |
| 118 | false, this, UserHandle.USER_ALL); |
| 119 | cr.registerContentObserver( |
| 120 | BRIGHTNESS_URI, |
| 121 | false, this, UserHandle.USER_ALL); |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 122 | cr.registerContentObserver( |
| 123 | BRIGHTNESS_ADJ_URI, |
| 124 | false, this, UserHandle.USER_ALL); |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | public void stopObserving() { |
| 128 | final ContentResolver cr = mContext.getContentResolver(); |
| 129 | cr.unregisterContentObserver(this); |
| 130 | } |
| 131 | |
| 132 | } |
| 133 | |
| 134 | public BrightnessController(Context context, ImageView icon, ToggleSlider control) { |
| 135 | mContext = context; |
| 136 | mIcon = icon; |
| 137 | mControl = control; |
| 138 | mHandler = new Handler(); |
| 139 | mUserTracker = new CurrentUserTracker(mContext) { |
| 140 | @Override |
| 141 | public void onUserSwitched(int newUserId) { |
| 142 | updateMode(); |
| 143 | updateSlider(); |
| 144 | } |
| 145 | }; |
| 146 | mBrightnessObserver = new BrightnessObserver(mHandler); |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 147 | |
| 148 | PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); |
| 149 | mMinimumBacklight = pm.getMinimumScreenBrightnessSetting(); |
| 150 | mMaximumBacklight = pm.getMaximumScreenBrightnessSetting(); |
| 151 | |
| 152 | mAutomaticAvailable = context.getResources().getBoolean( |
| 153 | com.android.internal.R.bool.config_automatic_brightness_available); |
| 154 | mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power")); |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | public void addStateChangedCallback(BrightnessStateChangeCallback cb) { |
| 158 | mChangeCallbacks.add(cb); |
| 159 | } |
| 160 | |
| 161 | public boolean removeStateChangedCallback(BrightnessStateChangeCallback cb) { |
| 162 | return mChangeCallbacks.remove(cb); |
| 163 | } |
| 164 | |
| 165 | @Override |
| 166 | public void onInit(ToggleSlider control) { |
| 167 | // Do nothing |
| 168 | } |
| 169 | |
Jorim Jaggi | f056e35 | 2014-05-11 23:09:22 +0200 | [diff] [blame] | 170 | public void registerCallbacks() { |
Jorim Jaggi | 3f48f46 | 2014-07-08 16:53:29 +0200 | [diff] [blame] | 171 | if (mListening) { |
| 172 | return; |
| 173 | } |
Alan Viverette | 5a39949 | 2014-07-14 16:19:38 -0700 | [diff] [blame] | 174 | |
Jorim Jaggi | f056e35 | 2014-05-11 23:09:22 +0200 | [diff] [blame] | 175 | mBrightnessObserver.startObserving(); |
| 176 | mUserTracker.startTracking(); |
| 177 | |
Alan Viverette | 5a39949 | 2014-07-14 16:19:38 -0700 | [diff] [blame] | 178 | // Update the slider and mode before attaching the listener so we don't |
| 179 | // receive the onChanged notifications for the initial values. |
Jorim Jaggi | f056e35 | 2014-05-11 23:09:22 +0200 | [diff] [blame] | 180 | updateMode(); |
| 181 | updateSlider(); |
| 182 | |
| 183 | mControl.setOnChangedListener(this); |
Alan Viverette | 5a39949 | 2014-07-14 16:19:38 -0700 | [diff] [blame] | 184 | mListening = true; |
Jorim Jaggi | f056e35 | 2014-05-11 23:09:22 +0200 | [diff] [blame] | 185 | } |
| 186 | |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 187 | /** Unregister all call backs, both to and from the controller */ |
| 188 | public void unregisterCallbacks() { |
Jorim Jaggi | 3f48f46 | 2014-07-08 16:53:29 +0200 | [diff] [blame] | 189 | if (!mListening) { |
| 190 | return; |
| 191 | } |
Alan Viverette | 5a39949 | 2014-07-14 16:19:38 -0700 | [diff] [blame] | 192 | |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 193 | mBrightnessObserver.stopObserving(); |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 194 | mUserTracker.stopTracking(); |
Jorim Jaggi | f056e35 | 2014-05-11 23:09:22 +0200 | [diff] [blame] | 195 | mControl.setOnChangedListener(null); |
Alan Viverette | 5a39949 | 2014-07-14 16:19:38 -0700 | [diff] [blame] | 196 | mListening = false; |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 197 | } |
| 198 | |
Adrian Roos | 5fd872e | 2014-08-12 17:28:58 +0200 | [diff] [blame] | 199 | @Override |
Jason Monk | 97b87a9 | 2015-06-23 15:04:44 -0400 | [diff] [blame^] | 200 | public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value, |
| 201 | boolean stopTracking) { |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 202 | updateIcon(mAutomatic); |
Adrian Roos | b7ebbde | 2014-08-15 20:11:38 +0200 | [diff] [blame] | 203 | if (mExternalChange) return; |
| 204 | |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 205 | if (!mAutomatic) { |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 206 | final int val = value + mMinimumBacklight; |
Jason Monk | 97b87a9 | 2015-06-23 15:04:44 -0400 | [diff] [blame^] | 207 | if (stopTracking) { |
| 208 | MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS, val); |
| 209 | } |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 210 | setBrightness(val); |
| 211 | if (!tracking) { |
| 212 | AsyncTask.execute(new Runnable() { |
| 213 | public void run() { |
| 214 | Settings.System.putIntForUser(mContext.getContentResolver(), |
| 215 | Settings.System.SCREEN_BRIGHTNESS, val, |
| 216 | UserHandle.USER_CURRENT); |
| 217 | } |
| 218 | }); |
| 219 | } |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 220 | } else { |
| 221 | final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1; |
Jason Monk | 97b87a9 | 2015-06-23 15:04:44 -0400 | [diff] [blame^] | 222 | if (stopTracking) { |
| 223 | MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS_AUTO, value); |
| 224 | } |
Adrian Roos | 6e2d465 | 2014-05-14 20:01:43 +0200 | [diff] [blame] | 225 | setBrightnessAdj(adj); |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 226 | if (!tracking) { |
| 227 | AsyncTask.execute(new Runnable() { |
| 228 | public void run() { |
| 229 | Settings.System.putFloatForUser(mContext.getContentResolver(), |
| 230 | Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj, |
| 231 | UserHandle.USER_CURRENT); |
| 232 | } |
| 233 | }); |
| 234 | } |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 235 | } |
| 236 | |
| 237 | for (BrightnessStateChangeCallback cb : mChangeCallbacks) { |
| 238 | cb.onBrightnessLevelChanged(); |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | private void setMode(int mode) { |
| 243 | Settings.System.putIntForUser(mContext.getContentResolver(), |
| 244 | Settings.System.SCREEN_BRIGHTNESS_MODE, mode, |
| 245 | mUserTracker.getCurrentUserId()); |
| 246 | } |
| 247 | |
| 248 | private void setBrightness(int brightness) { |
| 249 | try { |
| 250 | mPower.setTemporaryScreenBrightnessSettingOverride(brightness); |
| 251 | } catch (RemoteException ex) { |
| 252 | } |
| 253 | } |
| 254 | |
Adrian Roos | 6e2d465 | 2014-05-14 20:01:43 +0200 | [diff] [blame] | 255 | private void setBrightnessAdj(float adj) { |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 256 | try { |
| 257 | mPower.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(adj); |
| 258 | } catch (RemoteException ex) { |
| 259 | } |
| 260 | } |
| 261 | |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 262 | private void updateIcon(boolean automatic) { |
| 263 | if (mIcon != null) { |
John Spurlock | 6d20526 | 2014-06-10 19:26:14 -0400 | [diff] [blame] | 264 | mIcon.setImageResource(automatic && SHOW_AUTOMATIC_ICON ? |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 265 | com.android.systemui.R.drawable.ic_qs_brightness_auto_on : |
| 266 | com.android.systemui.R.drawable.ic_qs_brightness_auto_off); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | /** Fetch the brightness mode from the system settings and update the icon */ |
| 271 | private void updateMode() { |
| 272 | if (mAutomaticAvailable) { |
| 273 | int automatic; |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 274 | automatic = Settings.System.getIntForUser(mContext.getContentResolver(), |
| 275 | Settings.System.SCREEN_BRIGHTNESS_MODE, |
| 276 | Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, |
| 277 | UserHandle.USER_CURRENT); |
Adrian Roos | 6e2d465 | 2014-05-14 20:01:43 +0200 | [diff] [blame] | 278 | mAutomatic = automatic != Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL; |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 279 | updateIcon(mAutomatic); |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 280 | } else { |
| 281 | mControl.setChecked(false); |
| 282 | updateIcon(false /*automatic*/); |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | /** Fetch the brightness from the system settings and update the slider */ |
| 287 | private void updateSlider() { |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 288 | if (mAutomatic) { |
| 289 | float value = Settings.System.getFloatForUser(mContext.getContentResolver(), |
| 290 | Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0, |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 291 | UserHandle.USER_CURRENT); |
Adrian Roos | daf7d41 | 2014-05-13 14:55:09 +0200 | [diff] [blame] | 292 | mControl.setMax((int) BRIGHTNESS_ADJ_RESOLUTION); |
| 293 | mControl.setValue((int) ((value + 1) * BRIGHTNESS_ADJ_RESOLUTION / 2f)); |
| 294 | } else { |
| 295 | int value; |
| 296 | value = Settings.System.getIntForUser(mContext.getContentResolver(), |
| 297 | Settings.System.SCREEN_BRIGHTNESS, mMaximumBacklight, |
| 298 | UserHandle.USER_CURRENT); |
| 299 | mControl.setMax(mMaximumBacklight - mMinimumBacklight); |
| 300 | mControl.setValue(value - mMinimumBacklight); |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 301 | } |
Michael Wright | 0087a14 | 2013-02-05 16:29:39 -0800 | [diff] [blame] | 302 | } |
| 303 | |
| 304 | } |