OSDN Git Service

Make Power Control widget a bit more responsive.
[android-x86/packages-apps-Settings.git] / src / com / android / settings / widget / SettingsAppWidgetProvider.java
1 /*
2  * Copyright (C) 2009 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.settings.widget;
18
19 import android.app.PendingIntent;
20 import android.appwidget.AppWidgetManager;
21 import android.appwidget.AppWidgetProvider;
22 import android.bluetooth.BluetoothAdapter;
23 import android.content.ComponentName;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.content.IContentService;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.location.LocationManager;
30 import android.net.ConnectivityManager;
31 import android.net.Uri;
32 import android.net.wifi.WifiManager;
33 import android.os.AsyncTask;
34 import android.os.IPowerManager;
35 import android.os.RemoteException;
36 import android.os.ServiceManager;
37 import android.provider.Settings;
38 import android.util.Log;
39 import android.widget.RemoteViews;
40 import com.android.settings.R;
41 import com.android.settings.bluetooth.LocalBluetoothManager;
42
43 /**
44  * Provides control of power-related settings from a widget.
45  */
46 public class SettingsAppWidgetProvider extends AppWidgetProvider {
47     static final String TAG = "SettingsAppWidgetProvider";
48
49     static final ComponentName THIS_APPWIDGET =
50             new ComponentName("com.android.settings",
51                     "com.android.settings.widget.SettingsAppWidgetProvider");
52
53     private static LocalBluetoothManager sLocalBluetoothManager = null;
54
55     private static final int BUTTON_WIFI = 0;
56     private static final int BUTTON_BRIGHTNESS = 1;
57     private static final int BUTTON_SYNC = 2;
58     private static final int BUTTON_GPS = 3;
59     private static final int BUTTON_BLUETOOTH = 4;
60
61     // This widget keeps track of two sets of states:
62     // "3-state": STATE_DISABLED, STATE_ENABLED, STATE_INTERMEDIATE
63     // "5-state": STATE_DISABLED, STATE_ENABLED, STATE_TURNING_ON, STATE_TURNING_OFF, STATE_UNKNOWN
64     private static final int STATE_DISABLED = 0;
65     private static final int STATE_ENABLED = 1;
66     private static final int STATE_TURNING_ON = 2;
67     private static final int STATE_TURNING_OFF = 3;
68     private static final int STATE_UNKNOWN = 4;
69     private static final int STATE_INTERMEDIATE = 5;
70
71
72     /**
73      * Minimum and maximum brightnesses.  Don't go to 0 since that makes the display unusable
74      */
75     private static final int MINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 10;
76     private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;
77     private static final int DEFAULT_BACKLIGHT = (int) (android.os.Power.BRIGHTNESS_ON * 0.4f);
78
79     private static final StateTracker sWifiState = new WifiStateTracker();
80     private static final StateTracker sBluetoothState = new BluetoothStateTracker();
81
82     /**
83      * The state machine for Wifi and Bluetooth toggling, tracking
84      * reality versus the user's intent.
85      *
86      * This is necessary because reality moves relatively slowly
87      * (turning on & off radio drivers), compared to user's
88      * expectations.
89      */
90     private abstract static class StateTracker {
91         // Is the state in the process of changing?
92         private boolean mInTransition = false;
93         private Boolean mActualState = null;  // initially not set
94         private Boolean mIntendedState = null;  // initially not set
95
96         // Did a toggle request arrive while a state update was
97         // already in-flight?  If so, the mIntendedState needs to be
98         // requested when the other one is done, unless we happened to
99         // arrive at that state already.
100         private boolean mDeferredStateChangeRequestNeeded = false;
101
102         /**
103          * User pressed a button to change the state.  Something
104          * should immediately appear to the user afterwards, even if
105          * we effectively do nothing.  Their press must be heard.
106          */
107         public final void toggleState(Context context) {
108             int currentState = getTriState(context);
109             boolean newState = false;
110             switch (currentState) {
111                 case STATE_ENABLED:
112                     newState = false;
113                     break;
114                 case STATE_DISABLED:
115                     newState = true;
116                     break;
117                 case STATE_INTERMEDIATE:
118                     if (mIntendedState != null) {
119                         newState = !mIntendedState;
120                     }
121                     break;
122             }
123             mIntendedState = newState;
124             if (mInTransition) {
125                 // We don't send off a transition request if we're
126                 // already transitioning.  Makes our state tracking
127                 // easier, and is probably nicer on lower levels.
128                 // (even though they should be able to take it...)
129                 mDeferredStateChangeRequestNeeded = true;
130             } else {
131                 mInTransition = true;
132                 requestStateChange(context, newState);
133             }
134         }
135
136         /**
137          * Update internal state from a broadcast state change.
138          */
139         public abstract void onActualStateChange(Context context, Intent intent);
140
141         /**
142          * Sets the value that we're now in.  To be called from onActualStateChange.
143          *
144          * @param newState one of STATE_DISABLED, STATE_ENABLED, STATE_TURNING_ON,
145          *                 STATE_TURNING_OFF, STATE_UNKNOWN
146          */
147         protected final void setCurrentState(Context context, int newState) {
148             final boolean wasInTransition = mInTransition;
149             switch (newState) {
150                 case STATE_DISABLED:
151                     mInTransition = false;
152                     mActualState = false;
153                     break;
154                 case STATE_ENABLED:
155                     mInTransition = false;
156                     mActualState = true;
157                     break;
158                 case STATE_TURNING_ON:
159                     mInTransition = true;
160                     mActualState = false;
161                     break;
162                 case STATE_TURNING_OFF:
163                     mInTransition = true;
164                     mActualState = true;
165                     break;
166             }
167
168             if (wasInTransition && !mInTransition) {
169                 if (mDeferredStateChangeRequestNeeded) {
170                     Log.v(TAG, "processing deferred state change");
171                     if (mActualState != null && mIntendedState != null &&
172                         mIntendedState.equals(mActualState)) {
173                         Log.v(TAG, "... but intended state matches, so no changes.");
174                     } else if (mIntendedState != null) {
175                         mInTransition = true;
176                         requestStateChange(context, mIntendedState);
177                     }
178                     mDeferredStateChangeRequestNeeded = false;
179                 }
180             }
181         }
182
183
184         /**
185          * If we're in a transition mode, this returns true if we're
186          * transitioning towards being enabled.
187          */
188         public final boolean isTurningOn() {
189             return mIntendedState != null && mIntendedState;
190         }
191
192         /**
193          * Returns simplified 3-state value from underlying 5-state.
194          *
195          * @param context
196          * @return STATE_ENABLED, STATE_DISABLED, or STATE_INTERMEDIATE
197          */
198         public final int getTriState(Context context) {
199             if (mInTransition) {
200                 // If we know we just got a toggle request recently
201                 // (which set mInTransition), don't even ask the
202                 // underlying interface for its state.  We know we're
203                 // changing.  This avoids blocking the UI thread
204                 // during UI refresh post-toggle if the underlying
205                 // service state accessor has coarse locking on its
206                 // state (to be fixed separately).
207                 return STATE_INTERMEDIATE;
208             }
209             switch (getActualState(context)) {
210                 case STATE_DISABLED:
211                     return STATE_DISABLED;
212                 case STATE_ENABLED:
213                     return STATE_ENABLED;
214                 default:
215                     return STATE_INTERMEDIATE;
216             }
217         }
218
219         /**
220          * Gets underlying actual state.
221          *
222          * @param context
223          * @return STATE_ENABLED, STATE_DISABLED, STATE_ENABLING, STATE_DISABLING,
224          *         or or STATE_UNKNOWN.
225          */
226         public abstract int getActualState(Context context);
227
228         /**
229          * Actually make the desired change to the underlying radio
230          * API.
231          */
232         protected abstract void requestStateChange(Context context, boolean desiredState);
233     }
234
235     /**
236      * Subclass of StateTracker to get/set Wifi state.
237      */
238     private static final class WifiStateTracker extends StateTracker {
239         @Override
240         public int getActualState(Context context) {
241             WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
242             if (wifiManager != null) {
243                 return wifiStateToFiveState(wifiManager.getWifiState());
244             }
245             return STATE_UNKNOWN;
246         }
247
248         @Override
249         protected void requestStateChange(Context context, final boolean desiredState) {
250             final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
251             if (wifiManager == null) {
252                 Log.d(TAG, "No wifiManager.");
253                 return;
254             }
255
256             // Actually request the wifi change and persistent
257             // settings write off the UI thread, as it can take a
258             // user-noticeable amount of time, especially if there's
259             // disk contention.
260             new AsyncTask<Void, Void, Void>() {
261                 @Override
262                 protected Void doInBackground(Void... args) {
263                     /**
264                      * Disable tethering if enabling Wifi
265                      */
266                     int wifiApState = wifiManager.getWifiApState();
267                     if (desiredState && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
268                                          (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
269                         wifiManager.setWifiApEnabled(null, false);
270                     }
271
272                     wifiManager.setWifiEnabled(desiredState);
273                     return null;
274                 }
275             }.execute();
276         }
277
278         @Override
279         public void onActualStateChange(Context context, Intent intent) {
280             if (!WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
281                 return;
282             }
283             int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1);
284             setCurrentState(context, wifiStateToFiveState(wifiState));
285         }
286
287         /**
288          * Converts WifiManager's state values into our
289          * Wifi/Bluetooth-common state values.
290          */
291         private static int wifiStateToFiveState(int wifiState) {
292             switch (wifiState) {
293                 case WifiManager.WIFI_STATE_DISABLED:
294                     return STATE_DISABLED;
295                 case WifiManager.WIFI_STATE_ENABLED:
296                     return STATE_ENABLED;
297                 case WifiManager.WIFI_STATE_DISABLING:
298                     return STATE_TURNING_OFF;
299                 case WifiManager.WIFI_STATE_ENABLING:
300                     return STATE_TURNING_ON;
301                 default:
302                     return STATE_UNKNOWN;
303             }
304         }
305     }
306
307     /**
308      * Subclass of StateTracker to get/set Bluetooth state.
309      */
310     private static final class BluetoothStateTracker extends StateTracker {
311
312         @Override
313         public int getActualState(Context context) {
314             if (sLocalBluetoothManager == null) {
315                 sLocalBluetoothManager = LocalBluetoothManager.getInstance(context);
316                 if (sLocalBluetoothManager == null) {
317                     return STATE_UNKNOWN;  // On emulator?
318                 }
319             }
320             return bluetoothStateToFiveState(sLocalBluetoothManager.getBluetoothState());
321         }
322
323         @Override
324         protected void requestStateChange(Context context, final boolean desiredState) {
325             if (sLocalBluetoothManager == null) {
326                 Log.d(TAG, "No LocalBluetoothManager");
327                 return;
328             }
329             // Actually request the Bluetooth change and persistent
330             // settings write off the UI thread, as it can take a
331             // user-noticeable amount of time, especially if there's
332             // disk contention.
333             new AsyncTask<Void, Void, Void>() {
334                 @Override
335                 protected Void doInBackground(Void... args) {
336                     sLocalBluetoothManager.setBluetoothEnabled(desiredState);
337                     return null;
338                 }
339             }.execute();
340         }
341
342         @Override
343         public void onActualStateChange(Context context, Intent intent) {
344             if (!BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
345                 return;
346             }
347             int bluetoothState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
348             setCurrentState(context, bluetoothStateToFiveState(bluetoothState));
349         }
350
351         /**
352          * Converts BluetoothAdapter's state values into our
353          * Wifi/Bluetooth-common state values.
354          */
355         private static int bluetoothStateToFiveState(int bluetoothState) {
356             switch (bluetoothState) {
357                 case BluetoothAdapter.STATE_OFF:
358                     return STATE_DISABLED;
359                 case BluetoothAdapter.STATE_ON:
360                     return STATE_ENABLED;
361                 case BluetoothAdapter.STATE_TURNING_ON:
362                     return STATE_TURNING_ON;
363                 case BluetoothAdapter.STATE_TURNING_OFF:
364                     return STATE_TURNING_OFF;
365                 default:
366                     return STATE_UNKNOWN;
367             }
368         }
369     }
370
371
372     @Override
373     public void onUpdate(Context context, AppWidgetManager appWidgetManager,
374             int[] appWidgetIds) {
375         // Update each requested appWidgetId
376         RemoteViews view = buildUpdate(context, -1);
377
378         for (int i = 0; i < appWidgetIds.length; i++) {
379             appWidgetManager.updateAppWidget(appWidgetIds[i], view);
380         }
381     }
382
383     @Override
384     public void onEnabled(Context context) {
385         PackageManager pm = context.getPackageManager();
386         pm.setComponentEnabledSetting(
387                 new ComponentName("com.android.settings", ".widget.SettingsAppWidgetProvider"),
388                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
389                 PackageManager.DONT_KILL_APP);
390     }
391
392     @Override
393     public void onDisabled(Context context) {
394         Class clazz = com.android.settings.widget.SettingsAppWidgetProvider.class;
395         PackageManager pm = context.getPackageManager();
396         pm.setComponentEnabledSetting(
397                 new ComponentName("com.android.settings", ".widget.SettingsAppWidgetProvider"),
398                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
399                 PackageManager.DONT_KILL_APP);
400     }
401
402     /**
403      * Load image for given widget and build {@link RemoteViews} for it.
404      */
405     static RemoteViews buildUpdate(Context context, int appWidgetId) {
406         RemoteViews views = new RemoteViews(context.getPackageName(),
407                 R.layout.widget);
408         views.setOnClickPendingIntent(R.id.btn_wifi, getLaunchPendingIntent(context, appWidgetId,
409                 BUTTON_WIFI));
410         views.setOnClickPendingIntent(R.id.btn_brightness,
411                 getLaunchPendingIntent(context,
412                         appWidgetId, BUTTON_BRIGHTNESS));
413         views.setOnClickPendingIntent(R.id.btn_sync,
414                 getLaunchPendingIntent(context,
415                         appWidgetId, BUTTON_SYNC));
416         views.setOnClickPendingIntent(R.id.btn_gps,
417                 getLaunchPendingIntent(context, appWidgetId, BUTTON_GPS));
418         views.setOnClickPendingIntent(R.id.btn_bluetooth,
419                 getLaunchPendingIntent(context,
420                         appWidgetId, BUTTON_BLUETOOTH));
421
422         updateButtons(views, context);
423         return views;
424     }
425
426     /**
427      * Updates the widget when something changes, or when a button is pushed.
428      *
429      * @param context
430      */
431     public static void updateWidget(Context context) {
432         RemoteViews views = buildUpdate(context, -1);
433         // Update specific list of appWidgetIds if given, otherwise default to all
434         final AppWidgetManager gm = AppWidgetManager.getInstance(context);
435         gm.updateAppWidget(THIS_APPWIDGET, views);
436     }
437
438     /**
439      * Updates the buttons based on the underlying states of wifi, etc.
440      *
441      * @param views   The RemoteViews to update.
442      * @param context
443      */
444     private static void updateButtons(RemoteViews views, Context context) {
445         switch (sWifiState.getTriState(context)) {
446             case STATE_DISABLED:
447                 views.setImageViewResource(R.id.img_wifi,
448                                            R.drawable.ic_appwidget_settings_wifi_off);
449                 views.setImageViewResource(R.id.ind_wifi,
450                                            R.drawable.appwidget_settings_ind_off_l);
451                 break;
452             case STATE_ENABLED:
453                 views.setImageViewResource(R.id.img_wifi,
454                                            R.drawable.ic_appwidget_settings_wifi_on);
455                 views.setImageViewResource(R.id.ind_wifi,
456                                            R.drawable.appwidget_settings_ind_on_l);
457                 break;
458             case STATE_INTERMEDIATE:
459                 // In the transitional state, the bottom green bar
460                 // shows the tri-state (on, off, transitioning), but
461                 // the top dark-gray-or-bright-white logo shows the
462                 // user's intent.  This is much easier to see in
463                 // sunlight.
464                 if (sWifiState.isTurningOn()) {
465                     views.setImageViewResource(R.id.img_wifi,
466                                                R.drawable.ic_appwidget_settings_wifi_on);
467                     views.setImageViewResource(R.id.ind_wifi,
468                                                R.drawable.appwidget_settings_ind_mid_l);
469                 } else {
470                     views.setImageViewResource(R.id.img_wifi,
471                                                R.drawable.ic_appwidget_settings_wifi_off);
472                     views.setImageViewResource(R.id.ind_wifi,
473                                                R.drawable.appwidget_settings_ind_off_l);
474                 }
475                 break;
476         }
477         if (getBrightnessMode(context)) {
478             views.setImageViewResource(R.id.img_brightness,
479                                        R.drawable.ic_appwidget_settings_brightness_auto);
480             views.setImageViewResource(R.id.ind_brightness,
481                                        R.drawable.appwidget_settings_ind_on_r);
482         } else if (getBrightness(context)) {
483             views.setImageViewResource(R.id.img_brightness,
484                                        R.drawable.ic_appwidget_settings_brightness_on);
485             views.setImageViewResource(R.id.ind_brightness,
486                                        R.drawable.appwidget_settings_ind_on_r);
487         } else {
488             views.setImageViewResource(R.id.img_brightness,
489                                        R.drawable.ic_appwidget_settings_brightness_off);
490             views.setImageViewResource(R.id.ind_brightness,
491                                        R.drawable.appwidget_settings_ind_off_r);
492         }
493         if (getSync(context)) {
494             views.setImageViewResource(R.id.img_sync, R.drawable.ic_appwidget_settings_sync_on);
495             views.setImageViewResource(R.id.ind_sync, R.drawable.appwidget_settings_ind_on_c);
496         } else {
497             views.setImageViewResource(R.id.img_sync, R.drawable.ic_appwidget_settings_sync_off);
498             views.setImageViewResource(R.id.ind_sync, R.drawable.appwidget_settings_ind_off_c);
499         }
500         if (getGpsState(context)) {
501             views.setImageViewResource(R.id.img_gps, R.drawable.ic_appwidget_settings_gps_on);
502             views.setImageViewResource(R.id.ind_gps, R.drawable.appwidget_settings_ind_on_c);
503         } else {
504             views.setImageViewResource(R.id.img_gps, R.drawable.ic_appwidget_settings_gps_off);
505             views.setImageViewResource(R.id.ind_gps, R.drawable.appwidget_settings_ind_off_c);
506         }
507         switch (sBluetoothState.getTriState(context)) {
508             case STATE_DISABLED:
509                 views.setImageViewResource(R.id.img_bluetooth,
510                                            R.drawable.ic_appwidget_settings_bluetooth_off);
511                 views.setImageViewResource(R.id.ind_bluetooth,
512                                            R.drawable.appwidget_settings_ind_off_c);
513                 break;
514             case STATE_ENABLED:
515                 views.setImageViewResource(R.id.img_bluetooth,
516                                            R.drawable.ic_appwidget_settings_bluetooth_on);
517                 views.setImageViewResource(R.id.ind_bluetooth,
518                                            R.drawable.appwidget_settings_ind_on_c);
519                 break;
520             case STATE_INTERMEDIATE:
521                 // In the transitional state, the bottom green bar
522                 // shows the tri-state (on, off, transitioning), but
523                 // the top dark-gray-or-bright-white logo shows the
524                 // user's intent.  This is much easier to see in
525                 // sunlight.
526                 if (sBluetoothState.isTurningOn()) {
527                     views.setImageViewResource(R.id.img_bluetooth,
528                                                R.drawable.ic_appwidget_settings_bluetooth_on);
529                     views.setImageViewResource(R.id.ind_bluetooth,
530                                                R.drawable.appwidget_settings_ind_mid_c);
531                 } else {
532                     views.setImageViewResource(R.id.img_bluetooth,
533                                                R.drawable.ic_appwidget_settings_bluetooth_off);
534                     views.setImageViewResource(R.id.ind_bluetooth,
535                                                R.drawable.appwidget_settings_ind_off_c);
536                 }
537                 break;
538         }
539     }
540
541     /**
542      * Creates PendingIntent to notify the widget of a button click.
543      *
544      * @param context
545      * @param appWidgetId
546      * @return
547      */
548     private static PendingIntent getLaunchPendingIntent(Context context, int appWidgetId,
549             int buttonId) {
550         Intent launchIntent = new Intent();
551         launchIntent.setClass(context, SettingsAppWidgetProvider.class);
552         launchIntent.addCategory(Intent.CATEGORY_ALTERNATIVE);
553         launchIntent.setData(Uri.parse("custom:" + buttonId));
554         PendingIntent pi = PendingIntent.getBroadcast(context, 0 /* no requestCode */,
555                 launchIntent, 0 /* no flags */);
556         return pi;
557     }
558
559     /**
560      * Receives and processes a button pressed intent or state change.
561      *
562      * @param context
563      * @param intent  Indicates the pressed button.
564      */
565     @Override
566     public void onReceive(Context context, Intent intent) {
567         super.onReceive(context, intent);
568         if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
569             sWifiState.onActualStateChange(context, intent);
570         } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
571             sBluetoothState.onActualStateChange(context, intent);
572         } else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
573             Uri data = intent.getData();
574             int buttonId = Integer.parseInt(data.getSchemeSpecificPart());
575             if (buttonId == BUTTON_WIFI) {
576                 sWifiState.toggleState(context);
577             } else if (buttonId == BUTTON_BRIGHTNESS) {
578                 toggleBrightness(context);
579             } else if (buttonId == BUTTON_SYNC) {
580                 toggleSync(context);
581             } else if (buttonId == BUTTON_GPS) {
582                 toggleGps(context);
583             } else if (buttonId == BUTTON_BLUETOOTH) {
584                 sBluetoothState.toggleState(context);
585             }
586         } else {
587             // Don't fall-through to updating the widget.  The Intent
588             // was something unrelated or that our super class took
589             // care of.
590             return;
591         }
592
593         // State changes fall through
594         updateWidget(context);
595     }
596
597     /**
598      * Gets the state of background data.
599      *
600      * @param context
601      * @return true if enabled
602      */
603     private static boolean getBackgroundDataState(Context context) {
604         ConnectivityManager connManager =
605                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
606         return connManager.getBackgroundDataSetting();
607     }
608
609     /**
610      * Gets the state of auto-sync.
611      *
612      * @param context
613      * @return true if enabled
614      */
615     private static boolean getSync(Context context) {
616         boolean backgroundData = getBackgroundDataState(context);
617         boolean sync = ContentResolver.getMasterSyncAutomatically();
618         return backgroundData && sync;
619     }
620
621     /**
622      * Toggle auto-sync
623      *
624      * @param context
625      */
626     private void toggleSync(Context context) {
627         ConnectivityManager connManager =
628                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
629         boolean backgroundData = getBackgroundDataState(context);
630         boolean sync = ContentResolver.getMasterSyncAutomatically();
631
632         // four cases to handle:
633         // setting toggled from off to on:
634         // 1. background data was off, sync was off: turn on both
635         if (!backgroundData && !sync) {
636             connManager.setBackgroundDataSetting(true);
637             ContentResolver.setMasterSyncAutomatically(true);
638         }
639
640         // 2. background data was off, sync was on: turn on background data
641         if (!backgroundData && sync) {
642             connManager.setBackgroundDataSetting(true);
643         }
644
645         // 3. background data was on, sync was off: turn on sync
646         if (backgroundData && !sync) {
647             ContentResolver.setMasterSyncAutomatically(true);
648         }
649
650         // setting toggled from on to off:
651         // 4. background data was on, sync was on: turn off sync
652         if (backgroundData && sync) {
653             ContentResolver.setMasterSyncAutomatically(false);
654         }
655     }
656
657     /**
658      * Gets the state of GPS location.
659      *
660      * @param context
661      * @return true if enabled.
662      */
663     private static boolean getGpsState(Context context) {
664         ContentResolver resolver = context.getContentResolver();
665         return Settings.Secure.isLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER);
666     }
667
668     /**
669      * Toggles the state of GPS.
670      *
671      * @param context
672      */
673     private void toggleGps(Context context) {
674         ContentResolver resolver = context.getContentResolver();
675         boolean enabled = getGpsState(context);
676         Settings.Secure.setLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER,
677                 !enabled);
678     }
679
680     /**
681      * Gets state of brightness.
682      *
683      * @param context
684      * @return true if more than moderately bright.
685      */
686     private static boolean getBrightness(Context context) {
687         try {
688             IPowerManager power = IPowerManager.Stub.asInterface(
689                     ServiceManager.getService("power"));
690             if (power != null) {
691                 int brightness = Settings.System.getInt(context.getContentResolver(),
692                         Settings.System.SCREEN_BRIGHTNESS);
693                 return brightness > 100;
694             }
695         } catch (Exception e) {
696             Log.d(TAG, "getBrightness: " + e);
697         }
698         return false;
699     }
700
701     /**
702      * Gets state of brightness mode.
703      *
704      * @param context
705      * @return true if auto brightness is on.
706      */
707     private static boolean getBrightnessMode(Context context) {
708         try {
709             IPowerManager power = IPowerManager.Stub.asInterface(
710                     ServiceManager.getService("power"));
711             if (power != null) {
712                 int brightnessMode = Settings.System.getInt(context.getContentResolver(),
713                         Settings.System.SCREEN_BRIGHTNESS_MODE);
714                 return brightnessMode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
715             }
716         } catch (Exception e) {
717             Log.d(TAG, "getBrightnessMode: " + e);
718         }
719         return false;
720     }
721
722     /**
723      * Increases or decreases the brightness.
724      *
725      * @param context
726      */
727     private void toggleBrightness(Context context) {
728         try {
729             IPowerManager power = IPowerManager.Stub.asInterface(
730                     ServiceManager.getService("power"));
731             if (power != null) {
732                 ContentResolver cr = context.getContentResolver();
733                 int brightness = Settings.System.getInt(cr,
734                         Settings.System.SCREEN_BRIGHTNESS);
735                 int brightnessMode = Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
736                 //Only get brightness setting if available
737                 if (context.getResources().getBoolean(
738                         com.android.internal.R.bool.config_automatic_brightness_available)) {
739                     brightnessMode = Settings.System.getInt(cr,
740                             Settings.System.SCREEN_BRIGHTNESS_MODE);
741                 }
742
743                 // Rotate AUTO -> MINIMUM -> DEFAULT -> MAXIMUM
744                 // Technically, not a toggle...
745                 if (brightnessMode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) {
746                     brightness = MINIMUM_BACKLIGHT;
747                     brightnessMode = Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
748                 } else if (brightness < DEFAULT_BACKLIGHT) {
749                     brightness = DEFAULT_BACKLIGHT;
750                 } else if (brightness < MAXIMUM_BACKLIGHT) {
751                     brightness = MAXIMUM_BACKLIGHT;
752                 } else {
753                     brightnessMode = Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
754                     brightness = MINIMUM_BACKLIGHT;
755                 }
756
757                 if (context.getResources().getBoolean(
758                         com.android.internal.R.bool.config_automatic_brightness_available)) {
759                     // Set screen brightness mode (automatic or manual)
760                     Settings.System.putInt(context.getContentResolver(),
761                             Settings.System.SCREEN_BRIGHTNESS_MODE,
762                             brightnessMode);
763                 } else {
764                     // Make sure we set the brightness if automatic mode isn't available
765                     brightnessMode = Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
766                 }
767                 if (brightnessMode == Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL) {
768                     power.setBacklightBrightness(brightness);
769                     Settings.System.putInt(cr, Settings.System.SCREEN_BRIGHTNESS, brightness);
770                 }
771             }
772         } catch (RemoteException e) {
773             Log.d(TAG, "toggleBrightness: " + e);
774         } catch (Settings.SettingNotFoundException e) {
775             Log.d(TAG, "toggleBrightness: " + e);
776         }
777     }
778 }