Merge "Preserve old translations for changed strings.  DO NOT MERGE" into gingerbread
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7b15e3f..1dacea4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -817,7 +817,9 @@
                 <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
                 <action android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED" />
                 <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
-                <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" /> <!-- pick up misc changes -->
+                <action android:name="android.location.PROVIDERS_CHANGED" />
+                <!-- hack: using CLOSE_SYSTEM_DIALOGS to pick up (possible) sync changes -->
+                <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" />
             </intent-filter>
             <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" />
         </receiver>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e814951..a638a69 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1884,8 +1884,6 @@
     <string name="testing_phone_info">Phone information</string>
     <!-- In the Testing screen. The item title of the activity that shows a bunch of battery-related information.  -->
     <string name="testing_battery_info">Battery information</string>
-    <!-- In the Testing screen. The item title of the activity that shows a bunch of historical battery-related information.  -->
-    <string name="testing_battery_history">Battery history</string>
     <!-- Do not translate. In the Testing screen. The item title of the activity that shows a bunch of SIM-related operations.  -->
     <string name="testing_sim_toolkit">SIM toolkit</string>
 
diff --git a/res/xml/testing_settings.xml b/res/xml/testing_settings.xml
index 4b3ea0b..9c0a68b 100644
--- a/res/xml/testing_settings.xml
+++ b/res/xml/testing_settings.xml
@@ -33,13 +33,6 @@
 
 
     <PreferenceScreen
-            android:title="@string/testing_battery_history">
-        <intent android:action="android.intent.action.MAIN"
-                android:targetPackage="com.android.settings"
-                android:targetClass="com.android.settings.battery_history.BatteryHistory" />
-    </PreferenceScreen>
-
-    <PreferenceScreen
             android:title="@string/testing_usage_stats">
         <intent android:action="android.intent.action.MAIN"
                 android:targetPackage="com.android.settings"
diff --git a/src/com/android/settings/applications/RunningServiceDetails.java b/src/com/android/settings/applications/RunningServiceDetails.java
index 6346ec2..b8dd10e 100644
--- a/src/com/android/settings/applications/RunningServiceDetails.java
+++ b/src/com/android/settings/applications/RunningServiceDetails.java
@@ -284,20 +284,13 @@
             switch (rpi.importanceReasonCode) {
                 case ActivityManager.RunningAppProcessInfo.REASON_PROVIDER_IN_USE:
                     textid = R.string.process_provider_in_use_description;
-                    List<ProviderInfo> providers = null;
-                    if (comp != null) {
-                        providers = getPackageManager()
-                                .queryContentProviders(comp.getPackageName(),
-                                        rpi.uid, 0);
-                    }
-                    if (providers != null) {
-                        for (int j=0; j<providers.size(); j++) {
-                            ProviderInfo prov = providers.get(j);
-                            if (comp.getClassName().equals(prov.name)) {
-                                label = RunningState.makeLabel(getPackageManager(),
-                                        prov.name, prov);
-                                break;
-                            }
+                    if (rpi.importanceReasonComponent != null) {
+                        try {
+                            ProviderInfo prov = getPackageManager().getProviderInfo(
+                                    rpi.importanceReasonComponent, 0);
+                            label = RunningState.makeLabel(getPackageManager(),
+                                    prov.name, prov);
+                        } catch (NameNotFoundException e) {
                         }
                     }
                     break;
diff --git a/src/com/android/settings/applications/RunningState.java b/src/com/android/settings/applications/RunningState.java
index 119742c..6d08c57 100644
--- a/src/com/android/settings/applications/RunningState.java
+++ b/src/com/android/settings/applications/RunningState.java
@@ -666,7 +666,7 @@
                 proc.mDependentProcesses.clear();
             }
             
-            if ((pi.flags&ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT) != 0) {
+            if ((pi.flags&ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE) != 0) {
                 if (!mHeavyProcesses.contains(proc)) {
                     changed = true;
                     mHeavyProcesses.add(proc);
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
index 4253c5d..55f492e 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.text.TextUtils;
+import android.os.PowerManager;
 
 /**
  * BluetoothPairingRequest is a receiver for any Bluetooth pairing request. It
@@ -61,9 +62,13 @@
             pairingIntent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
             pairingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
+            PowerManager powerManager =
+                    (PowerManager)context.getSystemService(Context.POWER_SERVICE);
             String deviceAddress = device != null ? device.getAddress() : null;
-            if (localManager.shouldShowDialogInForeground(deviceAddress)) {
-                // Since the BT-related activity is in the foreground, just open the dialog
+            if (powerManager.isScreenOn() &&
+                localManager.shouldShowDialogInForeground(deviceAddress)) {
+                // Since the screen is on and the BT-related activity is in the foreground,
+                // just open the dialog
                 context.startActivity(pairingIntent);
 
             } else {
@@ -88,6 +93,7 @@
                         res.getString(R.string.bluetooth_notif_message) + name,
                         pending);
                 notification.flags |= Notification.FLAG_AUTO_CANCEL;
+                notification.defaults |= Notification.DEFAULT_SOUND;
 
                 NotificationManager manager = (NotificationManager)
                         context.getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/src/com/android/settings/widget/SettingsAppWidgetProvider.java b/src/com/android/settings/widget/SettingsAppWidgetProvider.java
index 939e8e3..444b8d4 100644
--- a/src/com/android/settings/widget/SettingsAppWidgetProvider.java
+++ b/src/com/android/settings/widget/SettingsAppWidgetProvider.java
@@ -78,10 +78,12 @@
 
     private static final StateTracker sWifiState = new WifiStateTracker();
     private static final StateTracker sBluetoothState = new BluetoothStateTracker();
+    private static final StateTracker sGpsState = new GpsStateTracker();
+    private static final StateTracker sSyncState = new SyncStateTracker();
 
     /**
-     * The state machine for Wifi and Bluetooth toggling, tracking
-     * reality versus the user's intent.
+     * The state machine for a setting's toggling, tracking reality
+     * versus the user's intent.
      *
      * This is necessary because reality moves relatively slowly
      * (turning on &amp; off radio drivers), compared to user's
@@ -134,6 +136,59 @@
         }
 
         /**
+         * Return the ID of the main large image button for the setting.
+         */
+        public abstract int getButtonId();
+
+        /**
+         * Returns the small indicator image ID underneath the setting.
+         */
+        public abstract int getIndicatorId();
+
+        /**
+         * Returns the resource ID of the image to show as a function of
+         * the on-vs-off state.
+         */
+        public abstract int getButtonImageId(boolean on);
+
+        /**
+         * Updates the remote views depending on the state (off, on,
+         * turning off, turning on) of the setting.
+         */
+        public final void setImageViewResources(Context context, RemoteViews views) {
+            int buttonId = getButtonId();
+            int indicatorId = getIndicatorId();
+            switch (getTriState(context)) {
+                case STATE_DISABLED:
+                    views.setImageViewResource(buttonId, getButtonImageId(false));
+                    views.setImageViewResource(
+                        indicatorId, R.drawable.appwidget_settings_ind_off_l);
+                    break;
+                case STATE_ENABLED:
+                    views.setImageViewResource(buttonId, getButtonImageId(true));
+                    views.setImageViewResource(
+                        indicatorId, R.drawable.appwidget_settings_ind_on_l);
+                    break;
+                case STATE_INTERMEDIATE:
+                    // In the transitional state, the bottom green bar
+                    // shows the tri-state (on, off, transitioning), but
+                    // the top dark-gray-or-bright-white logo shows the
+                    // user's intent.  This is much easier to see in
+                    // sunlight.
+                    if (isTurningOn()) {
+                        views.setImageViewResource(buttonId, getButtonImageId(true));
+                        views.setImageViewResource(
+                            indicatorId, R.drawable.appwidget_settings_ind_mid_l);
+                    } else {
+                        views.setImageViewResource(buttonId, getButtonImageId(false));
+                        views.setImageViewResource(
+                            indicatorId, R.drawable.appwidget_settings_ind_off_l);
+                    }
+                    break;
+            }
+        }
+
+        /**
          * Update internal state from a broadcast state change.
          */
         public abstract void onActualStateChange(Context context, Intent intent);
@@ -236,6 +291,13 @@
      * Subclass of StateTracker to get/set Wifi state.
      */
     private static final class WifiStateTracker extends StateTracker {
+        public int getButtonId() { return R.id.img_wifi; }
+        public int getIndicatorId() { return R.id.ind_wifi; }
+        public int getButtonImageId(boolean on) {
+            return on ? R.drawable.ic_appwidget_settings_wifi_on
+                    : R.drawable.ic_appwidget_settings_wifi_off;
+        }
+
         @Override
         public int getActualState(Context context) {
             WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -247,7 +309,8 @@
 
         @Override
         protected void requestStateChange(Context context, final boolean desiredState) {
-            final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+            final WifiManager wifiManager =
+                    (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
             if (wifiManager == null) {
                 Log.d(TAG, "No wifiManager.");
                 return;
@@ -308,6 +371,12 @@
      * Subclass of StateTracker to get/set Bluetooth state.
      */
     private static final class BluetoothStateTracker extends StateTracker {
+        public int getButtonId() { return R.id.img_bluetooth; }
+        public int getIndicatorId() { return R.id.ind_bluetooth; }
+        public int getButtonImageId(boolean on) {
+            return on ? R.drawable.ic_appwidget_settings_bluetooth_on
+                    : R.drawable.ic_appwidget_settings_bluetooth_off;
+        }
 
         @Override
         public int getActualState(Context context) {
@@ -368,6 +437,120 @@
         }
     }
 
+    /**
+     * Subclass of StateTracker for GPS state.
+     */
+    private static final class GpsStateTracker extends StateTracker {
+        public int getButtonId() { return R.id.img_gps; }
+        public int getIndicatorId() { return R.id.ind_gps; }
+        public int getButtonImageId(boolean on) {
+            return on ? R.drawable.ic_appwidget_settings_gps_on
+                    : R.drawable.ic_appwidget_settings_gps_off;
+        }
+
+        @Override
+        public int getActualState(Context context) {
+            ContentResolver resolver = context.getContentResolver();
+            boolean on = Settings.Secure.isLocationProviderEnabled(
+                resolver, LocationManager.GPS_PROVIDER);
+            return on ? STATE_ENABLED : STATE_DISABLED;
+        }
+
+        @Override
+        public void onActualStateChange(Context context, Intent unused) {
+            // Note: the broadcast location providers changed intent
+            // doesn't include an extras bundles saying what the new value is.
+            setCurrentState(context, getActualState(context));
+        }
+
+        @Override
+        public void requestStateChange(final Context context, final boolean desiredState) {
+            final ContentResolver resolver = context.getContentResolver();
+            new AsyncTask<Void, Void, Boolean>() {
+                @Override
+                protected Boolean doInBackground(Void... args) {
+                    Settings.Secure.setLocationProviderEnabled(
+                        resolver,
+                        LocationManager.GPS_PROVIDER,
+                        desiredState);
+                    return desiredState;
+                }
+
+                @Override
+                protected void onPostExecute(Boolean result) {
+                    setCurrentState(
+                        context,
+                        result ? STATE_ENABLED : STATE_DISABLED);
+                    updateWidget(context);
+                }
+            }.execute();
+        }
+    }
+
+    /**
+     * Subclass of StateTracker for sync state.
+     */
+    private static final class SyncStateTracker extends StateTracker {
+        public int getButtonId() { return R.id.img_sync; }
+        public int getIndicatorId() { return R.id.ind_sync; }
+        public int getButtonImageId(boolean on) {
+            return on ? R.drawable.ic_appwidget_settings_sync_on
+                    : R.drawable.ic_appwidget_settings_sync_off;
+        }
+
+        @Override
+        public int getActualState(Context context) {
+            boolean on = getBackgroundDataState(context) &&
+                    ContentResolver.getMasterSyncAutomatically();
+            return on ? STATE_ENABLED : STATE_DISABLED;
+        }
+
+        @Override
+        public void onActualStateChange(Context context, Intent unused) {
+            // Well, ACTION_CLOSE_SYSTEM_DIALOGS fired.  So _maybe_
+            // the Sync settings changed.
+            // TODO: find something more reliable.
+            setCurrentState(context, getActualState(context));
+        }
+
+        @Override
+        public void requestStateChange(final Context context, final boolean desiredState) {
+            final ConnectivityManager connManager =
+                    (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+            final boolean backgroundData = getBackgroundDataState(context);
+            final boolean sync = ContentResolver.getMasterSyncAutomatically();
+
+            new AsyncTask<Void, Void, Boolean>() {
+                @Override
+                protected Boolean doInBackground(Void... args) {
+                    // Turning sync on.
+                    if (desiredState) {
+                        if (!backgroundData) {
+                            connManager.setBackgroundDataSetting(true);
+                        }
+                        if (!sync) {
+                            ContentResolver.setMasterSyncAutomatically(true);
+                        }
+                        return true;
+                    }
+
+                    // Turning sync off
+                    if (sync) {
+                        ContentResolver.setMasterSyncAutomatically(false);
+                    }
+                    return false;
+                }
+
+                @Override
+                protected void onPostExecute(Boolean result) {
+                    setCurrentState(
+                        context,
+                        result ? STATE_ENABLED : STATE_DISABLED);
+                    updateWidget(context);
+                }
+            }.execute();
+        }
+    }
 
     @Override
     public void onUpdate(Context context, AppWidgetManager appWidgetManager,
@@ -442,38 +625,11 @@
      * @param context
      */
     private static void updateButtons(RemoteViews views, Context context) {
-        switch (sWifiState.getTriState(context)) {
-            case STATE_DISABLED:
-                views.setImageViewResource(R.id.img_wifi,
-                                           R.drawable.ic_appwidget_settings_wifi_off);
-                views.setImageViewResource(R.id.ind_wifi,
-                                           R.drawable.appwidget_settings_ind_off_l);
-                break;
-            case STATE_ENABLED:
-                views.setImageViewResource(R.id.img_wifi,
-                                           R.drawable.ic_appwidget_settings_wifi_on);
-                views.setImageViewResource(R.id.ind_wifi,
-                                           R.drawable.appwidget_settings_ind_on_l);
-                break;
-            case STATE_INTERMEDIATE:
-                // In the transitional state, the bottom green bar
-                // shows the tri-state (on, off, transitioning), but
-                // the top dark-gray-or-bright-white logo shows the
-                // user's intent.  This is much easier to see in
-                // sunlight.
-                if (sWifiState.isTurningOn()) {
-                    views.setImageViewResource(R.id.img_wifi,
-                                               R.drawable.ic_appwidget_settings_wifi_on);
-                    views.setImageViewResource(R.id.ind_wifi,
-                                               R.drawable.appwidget_settings_ind_mid_l);
-                } else {
-                    views.setImageViewResource(R.id.img_wifi,
-                                               R.drawable.ic_appwidget_settings_wifi_off);
-                    views.setImageViewResource(R.id.ind_wifi,
-                                               R.drawable.appwidget_settings_ind_off_l);
-                }
-                break;
-        }
+        sWifiState.setImageViewResources(context, views);
+        sBluetoothState.setImageViewResources(context, views);
+        sGpsState.setImageViewResources(context, views);
+        sSyncState.setImageViewResources(context, views);
+
         if (getBrightnessMode(context)) {
             views.setImageViewResource(R.id.img_brightness,
                                        R.drawable.ic_appwidget_settings_brightness_auto);
@@ -490,52 +646,6 @@
             views.setImageViewResource(R.id.ind_brightness,
                                        R.drawable.appwidget_settings_ind_off_r);
         }
-        if (getSync(context)) {
-            views.setImageViewResource(R.id.img_sync, R.drawable.ic_appwidget_settings_sync_on);
-            views.setImageViewResource(R.id.ind_sync, R.drawable.appwidget_settings_ind_on_c);
-        } else {
-            views.setImageViewResource(R.id.img_sync, R.drawable.ic_appwidget_settings_sync_off);
-            views.setImageViewResource(R.id.ind_sync, R.drawable.appwidget_settings_ind_off_c);
-        }
-        if (getGpsState(context)) {
-            views.setImageViewResource(R.id.img_gps, R.drawable.ic_appwidget_settings_gps_on);
-            views.setImageViewResource(R.id.ind_gps, R.drawable.appwidget_settings_ind_on_c);
-        } else {
-            views.setImageViewResource(R.id.img_gps, R.drawable.ic_appwidget_settings_gps_off);
-            views.setImageViewResource(R.id.ind_gps, R.drawable.appwidget_settings_ind_off_c);
-        }
-        switch (sBluetoothState.getTriState(context)) {
-            case STATE_DISABLED:
-                views.setImageViewResource(R.id.img_bluetooth,
-                                           R.drawable.ic_appwidget_settings_bluetooth_off);
-                views.setImageViewResource(R.id.ind_bluetooth,
-                                           R.drawable.appwidget_settings_ind_off_c);
-                break;
-            case STATE_ENABLED:
-                views.setImageViewResource(R.id.img_bluetooth,
-                                           R.drawable.ic_appwidget_settings_bluetooth_on);
-                views.setImageViewResource(R.id.ind_bluetooth,
-                                           R.drawable.appwidget_settings_ind_on_c);
-                break;
-            case STATE_INTERMEDIATE:
-                // In the transitional state, the bottom green bar
-                // shows the tri-state (on, off, transitioning), but
-                // the top dark-gray-or-bright-white logo shows the
-                // user's intent.  This is much easier to see in
-                // sunlight.
-                if (sBluetoothState.isTurningOn()) {
-                    views.setImageViewResource(R.id.img_bluetooth,
-                                               R.drawable.ic_appwidget_settings_bluetooth_on);
-                    views.setImageViewResource(R.id.ind_bluetooth,
-                                               R.drawable.appwidget_settings_ind_mid_c);
-                } else {
-                    views.setImageViewResource(R.id.img_bluetooth,
-                                               R.drawable.ic_appwidget_settings_bluetooth_off);
-                    views.setImageViewResource(R.id.ind_bluetooth,
-                                               R.drawable.appwidget_settings_ind_off_c);
-                }
-                break;
-        }
     }
 
     /**
@@ -565,10 +675,19 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         super.onReceive(context, intent);
-        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
+        String action = intent.getAction();
+        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
             sWifiState.onActualStateChange(context, intent);
-        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
+        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
             sBluetoothState.onActualStateChange(context, intent);
+        } else if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(action)) {
+            sGpsState.onActualStateChange(context, intent);
+        } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
+            // Sadly, for lack of a "sync settings changed" intent,
+            // this is where we check where sync is enabled or not.
+            // It's not 100% reliable though as there are paths where
+            // this doesn't fire.
+            sSyncState.onActualStateChange(context, intent);
         } else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
             Uri data = intent.getData();
             int buttonId = Integer.parseInt(data.getSchemeSpecificPart());
@@ -577,9 +696,9 @@
             } else if (buttonId == BUTTON_BRIGHTNESS) {
                 toggleBrightness(context);
             } else if (buttonId == BUTTON_SYNC) {
-                toggleSync(context);
+                sSyncState.toggleState(context);
             } else if (buttonId == BUTTON_GPS) {
-                toggleGps(context);
+                sGpsState.toggleState(context);
             } else if (buttonId == BUTTON_BLUETOOTH) {
                 sBluetoothState.toggleState(context);
             }
@@ -607,77 +726,6 @@
     }
 
     /**
-     * Gets the state of auto-sync.
-     *
-     * @param context
-     * @return true if enabled
-     */
-    private static boolean getSync(Context context) {
-        boolean backgroundData = getBackgroundDataState(context);
-        boolean sync = ContentResolver.getMasterSyncAutomatically();
-        return backgroundData && sync;
-    }
-
-    /**
-     * Toggle auto-sync
-     *
-     * @param context
-     */
-    private void toggleSync(Context context) {
-        ConnectivityManager connManager =
-                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        boolean backgroundData = getBackgroundDataState(context);
-        boolean sync = ContentResolver.getMasterSyncAutomatically();
-
-        // four cases to handle:
-        // setting toggled from off to on:
-        // 1. background data was off, sync was off: turn on both
-        if (!backgroundData && !sync) {
-            connManager.setBackgroundDataSetting(true);
-            ContentResolver.setMasterSyncAutomatically(true);
-        }
-
-        // 2. background data was off, sync was on: turn on background data
-        if (!backgroundData && sync) {
-            connManager.setBackgroundDataSetting(true);
-        }
-
-        // 3. background data was on, sync was off: turn on sync
-        if (backgroundData && !sync) {
-            ContentResolver.setMasterSyncAutomatically(true);
-        }
-
-        // setting toggled from on to off:
-        // 4. background data was on, sync was on: turn off sync
-        if (backgroundData && sync) {
-            ContentResolver.setMasterSyncAutomatically(false);
-        }
-    }
-
-    /**
-     * Gets the state of GPS location.
-     *
-     * @param context
-     * @return true if enabled.
-     */
-    private static boolean getGpsState(Context context) {
-        ContentResolver resolver = context.getContentResolver();
-        return Settings.Secure.isLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER);
-    }
-
-    /**
-     * Toggles the state of GPS.
-     *
-     * @param context
-     */
-    private void toggleGps(Context context) {
-        ContentResolver resolver = context.getContentResolver();
-        boolean enabled = getGpsState(context);
-        Settings.Secure.setLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER,
-                !enabled);
-    }
-
-    /**
      * Gets state of brightness.
      *
      * @param context