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