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