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