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 } 779