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