auto import from //branches/cupcake/...@132276
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index c94bbb2..44baccc 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -103,6 +103,7 @@
             mFooterWrongText = intent.getCharSequenceExtra(FOOTER_WRONG_TEXT);
         }
 
+        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
         mLockPatternView.setOnPatternListener(mConfirmExistingLockPatternListener);
         updateStage(Stage.NeedToUnlock);
 
@@ -220,10 +221,9 @@
                 setResult(RESULT_OK);
                 finish();
             } else {
-                if (pattern.size() >= LockPatternUtils.MIN_LOCK_PATTERN_SIZE &&
+                if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL &&
                         ++mNumWrongConfirmAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
-                    long deadline = SystemClock.elapsedRealtime() + LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS;
-                    mLockPatternUtils.setLockoutAttemptDeadline(deadline);
+                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
                     handleAttemptLockout(deadline);
                 } else {
                     updateStage(Stage.NeedToUnlockWrong);
diff --git a/src/com/android/settings/GadgetPickActivity.java b/src/com/android/settings/GadgetPickActivity.java
index 408039a..840a6a5 100644
--- a/src/com/android/settings/GadgetPickActivity.java
+++ b/src/com/android/settings/GadgetPickActivity.java
@@ -59,8 +59,19 @@
     public void onListItemClick(ListView l, View v, int position, long id)
     {
         Intent intent = intentForPosition(position);
-        mGadgetManager.bindGadgetId(mGadgetId, intent.getComponent());
-        setResultData(RESULT_OK);
+        int result;
+        try {
+            mGadgetManager.bindGadgetId(mGadgetId, intent.getComponent());
+            result = RESULT_OK;
+        } catch (IllegalArgumentException e) {
+            // This is thrown if they're already bound, or otherwise somehow
+            // bogus.  Set the result to canceled, and exit.  The app *should*
+            // clean up at this point.  We could pass the error along, but
+            // it's not clear that that's useful -- the gadget will simply not
+            // appear.
+            result = RESULT_CANCELED;
+        }
+        setResultData(result);
         finish();
     }
     
diff --git a/src/com/android/settings/InstalledAppDetails.java b/src/com/android/settings/InstalledAppDetails.java
index d4dfe97..eee8b75 100644
--- a/src/com/android/settings/InstalledAppDetails.java
+++ b/src/com/android/settings/InstalledAppDetails.java
@@ -254,6 +254,7 @@
          // Cache section
          mCachePanel = findViewById(R.id.cache_panel);
          mCacheSize = (TextView) findViewById(R.id.cache_size_text);
+         mCacheSize.setText(mComputingStr);
          mClearCacheButton = (Button) findViewById(R.id.clear_cache_button);
          mForceStopButton = (Button) findViewById(R.id.force_stop_button);
          mForceStopButton.setOnClickListener(this);
@@ -332,7 +333,8 @@
             mTotalSize.setText(str);
             mAppSnippetSize.setText(str);
             mAppSize.setText(getSizeStr(newPs.codeSize));
-            mDataSize.setText(getSizeStr(newPs.dataSize+newPs.cacheSize));
+            mDataSize.setText(getSizeStr(newPs.dataSize));
+            mCacheSize.setText(getSizeStr(newPs.cacheSize));
         } else {
             long oldTot = mSizeInfo.cacheSize+mSizeInfo.codeSize+mSizeInfo.dataSize;
             if(newTot != oldTot) {
@@ -345,15 +347,20 @@
                 mAppSize.setText(getSizeStr(newPs.codeSize));
                 changed = true;
             }
-            if((newPs.dataSize != mSizeInfo.dataSize) || (newPs.cacheSize != mSizeInfo.cacheSize)) {
-                mDataSize.setText(getSizeStr(newPs.dataSize+newPs.cacheSize));
+            if(newPs.dataSize != mSizeInfo.dataSize) {
+                mDataSize.setText(getSizeStr(newPs.dataSize));
+                changed = true;
+            }
+            if(newPs.cacheSize != mSizeInfo.cacheSize) {
+                mCacheSize.setText(getSizeStr(newPs.cacheSize));
+                changed = true;
             }
             if(changed) {
                 mSizeInfo = newPs;
             }
         }
         
-        long data = mSizeInfo.dataSize+mSizeInfo.cacheSize;
+        long data = mSizeInfo.dataSize;
         // Disable button if data is 0
         if(mAppButtonState != AppButtonStates.NONE){
             mAppButton.setText(mAppButtonText);
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index b7ff28a..dbad45d 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -95,7 +95,6 @@
     private static final int MENU_ITEM_TOGGLE_DATA_ON_BOOT = 6;
 
     private TextView mImei;
-    private TextView mImsi;
     private TextView number;
     private TextView callState;
     private TextView operatorName;
@@ -407,7 +406,6 @@
         phone = PhoneFactory.getDefaultPhone();
 
         mImei = (TextView) findViewById(R.id.imei);
-        mImsi = (TextView) findViewById(R.id.imsi);
         number = (TextView) findViewById(R.id.number);
         callState = (TextView) findViewById(R.id.call);
         operatorName = (TextView) findViewById(R.id.operator);
@@ -786,10 +784,6 @@
         if (s == null) s = r.getString(R.string.radioInfo_unknown); 
         mImei.setText(s);
         
-        s = phone.getSubscriberId();
-        if (s == null) s = r.getString(R.string.radioInfo_unknown); 
-        mImsi.setText(s);
-
         s = phone.getLine1Number();
         if (s == null) s = r.getString(R.string.radioInfo_unknown); 
         number.setText(s);
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index a0a52a2..cd26492 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -45,7 +45,8 @@
     private static final String KEY_LOCK_ENABLED = "lockenabled";
     private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
     private static final String KEY_TACTILE_FEEDBACK_ENABLED = "tactilefeedback";
-    private static final int CONFIRM_PATTERN_REQUEST_CODE = 55;
+    private static final int CONFIRM_PATTERN_THEN_DISABLE_REQUEST_CODE = 55;
+    private static final int CONFIRM_PATTERN_THEN_ENABLE_REQUEST_CODE = 56;
 
     private LockPatternUtils mLockPatternUtils;
     private CheckBoxPreference mLockEnabled;
@@ -256,14 +257,24 @@
 
         @Override
         protected void onClick() {
-            if (isChecked() && mLockPatternUtils.savedPatternExists()) {
-                confirmPatternThenDisable();
+            if (mLockPatternUtils.savedPatternExists()) {
+                if (isChecked()) {
+                    confirmPatternThenDisable();
+                } else {
+                    confirmPatternThenEnable();
+                }
             } else {
                 super.onClick();
             }
         }
     }
 
+    private void confirmPatternThenEnable() {
+        final Intent intent = new Intent();
+        intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
+        startActivityForResult(intent, CONFIRM_PATTERN_THEN_ENABLE_REQUEST_CODE);
+    }
+
     /**
      * Launch screen to confirm the existing lock pattern.
      * @see #onActivityResult(int, int, android.content.Intent)
@@ -271,7 +282,7 @@
     private void confirmPatternThenDisable() {
         final Intent intent = new Intent();
         intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
-        startActivityForResult(intent, CONFIRM_PATTERN_REQUEST_CODE);
+        startActivityForResult(intent, CONFIRM_PATTERN_THEN_DISABLE_REQUEST_CODE);
     }
 
     /**
@@ -282,12 +293,12 @@
             Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
 
-        if (requestCode != CONFIRM_PATTERN_REQUEST_CODE) {
-            return;
-        }
+        final boolean resultOk = resultCode == Activity.RESULT_OK;
 
-        if (resultCode == Activity.RESULT_OK) {
-            mLockPatternUtils.setLockPatternEnabled(false);                
+        if ((requestCode == CONFIRM_PATTERN_THEN_DISABLE_REQUEST_CODE) && resultOk) {
+            mLockPatternUtils.setLockPatternEnabled(false);
+        } else if ((requestCode == CONFIRM_PATTERN_THEN_ENABLE_REQUEST_CODE) && resultOk) {
+            mLockPatternUtils.setLockPatternEnabled(true);
         }
     }
 }
diff --git a/src/com/android/settings/battery_history/BatteryHistory.java b/src/com/android/settings/battery_history/BatteryHistory.java
index 19302a5..4265ac6 100644
--- a/src/com/android/settings/battery_history/BatteryHistory.java
+++ b/src/com/android/settings/battery_history/BatteryHistory.java
@@ -18,7 +18,6 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -28,16 +27,19 @@
 
 import android.app.Activity;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.BatteryStats;
 import android.os.Bundle;
+import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.BatteryStats.Timer;
 import android.os.BatteryStats.Uid;
 import android.util.Log;
+import android.util.LogPrinter;
 import android.util.SparseArray;
 import android.view.KeyEvent;
 import android.view.View;
@@ -59,12 +61,15 @@
     // Must be in sync with the values in res/values/array.xml (id battery_history_type_spinner)
     private static final int CPU_USAGE = 0;
     private static final int NETWORK_USAGE = 1;
-    private static final int SENSOR_USAGE = 2;
-    private static final int SCREEN_ON = 3;
+    private static final int GPS_USAGE = 2;
+    private static final int SENSOR_USAGE = 3;
     private static final int WAKE_LOCKS = 4;
+    private static final int SCREEN_ON = 5;
 
-    // App names to use as labels for the shared UIDs that contain them
-    private final HashSet<String> mKnownApps = new HashSet<String>();
+    // Must be in sync with the values in res/values/array.xml (id battery_history_which_spinner)
+    private static final int UNPLUGGED = 0;
+    private static final int CURRENT = 1;
+    private static final int TOTAL = 2;
     
     private BatteryStats mStats;
     private int mWhich = BatteryStats.STATS_UNPLUGGED;
@@ -76,7 +81,11 @@
     private List<CpuUsage> mCpuUsage = new ArrayList<CpuUsage>();
     private List<NetworkUsage> mNetworkUsage = new ArrayList<NetworkUsage>();
     private List<SensorUsage> mSensorUsage = new ArrayList<SensorUsage>();
-    private long mScreenOnTime;
+    private List<SensorUsage> mGpsUsage = new ArrayList<SensorUsage>();
+    private List<WakelockUsage> mWakelockUsage = new ArrayList<WakelockUsage>();
+    
+    private boolean mHaveCpuUsage, mHaveNetworkUsage, mHaveSensorUsage,
+            mHaveWakelockUsage, mHaveScreenOnTime;
     
     private LinearLayout mGraphLayout;
     private LinearLayout mTextLayout;
@@ -131,7 +140,9 @@
     
     abstract class Graphable implements Comparable<Graphable> {        
         protected String mName;
+        protected String mNamePackage;
         protected boolean mUniqueName;
+        protected String[] mPackages;
         protected String[] mPackageNames;
         
         public abstract String getLabel();
@@ -155,22 +166,40 @@
         // Side effects: sets mName and mUniqueName
         void getNameForUid(int uid) {
             PackageManager pm = getPackageManager();
-            mPackageNames = pm.getPackagesForUid(uid);
+            mPackages = pm.getPackagesForUid(uid);
+            if (mPackages == null) {
+                mName = Integer.toString(uid);
+                mNamePackage = null;
+                return;
+            }
+            
+            mPackageNames = new String[mPackages.length];
+            System.arraycopy(mPackages, 0, mPackageNames, 0, mPackages.length);
+            
             // Convert package names to user-facing labels where possible
             for (int i = 0; i < mPackageNames.length; i++) {
                 mPackageNames[i] = BatteryHistory.getLabel(mPackageNames[i], pm);
             }
 
             if (mPackageNames.length == 1) {
+                mNamePackage = mPackages[0];
                 mName = mPackageNames[0];
                 mUniqueName = true;
             } else {
                 mName = getString(R.string.battery_history_uid, uid); // Default name
-                // If one of the names for this UID is in mKnownApps, use it
-                for (String name : mPackageNames) {
-                    if (mKnownApps.contains(name)) {
-                        mName = name;
-                        break;
+                // Look for an official name for this UID.
+                for (String name : mPackages) {
+                    try {
+                        PackageInfo pi = pm.getPackageInfo(name, 0);
+                        if (pi.sharedUserLabel != 0) {
+                            CharSequence nm = pm.getText(name,
+                                    pi.sharedUserLabel, pi.applicationInfo);
+                            if (nm != null) {
+                                mName = nm.toString();
+                                break;
+                            }
+                        }
+                    } catch (PackageManager.NameNotFoundException e) {
                     }
                 }
             }
@@ -178,12 +207,15 @@
     }
 
     class CpuUsage extends Graphable {
+        String mProcess;
         double[] mUsage;
         long mStarts;
         
-        public CpuUsage(String name, long userTime, long systemTime, long starts) {
+        public CpuUsage(int uid, String process, long userTime, long systemTime, long starts) {
+            getNameForUid(uid);
+            mProcess = process;
             PackageManager pm = BatteryHistory.this.getPackageManager();
-            mName = BatteryHistory.getLabel(name, pm);
+            mName = BatteryHistory.getLabel(process, pm);
             mUsage = new double[2];
             
             mUsage[0] = userTime;
@@ -204,7 +236,7 @@
         }
         
         public void getInfo(StringBuilder info) {
-            info.append(getString(R.string.battery_history_cpu_usage, mName));
+            info.append(getString(R.string.battery_history_cpu_usage, mProcess));
             info.append("\n\n");
             info.append(getString(R.string.battery_history_user_time));
             formatTime(mUsage[0] * 10, info);
@@ -273,19 +305,16 @@
     }
     
     class SensorUsage extends Graphable {
-        int mSensorNumber;
         double[] mUsage;
-        HashMap<Integer,Integer> mCounts;
+        int mCount;
         
-        public SensorUsage(int sensorNumber, String sensorName, long totalTime,
-                HashMap<Integer,Integer> counts) {
-            mName = sensorName;
-            mSensorNumber = sensorNumber;
+        public SensorUsage(int uid, long time, int count) {
+            getNameForUid(uid);
             
             mUsage = new double[1];
-            mUsage[0] = totalTime;
+            mUsage[0] = time;
             
-            mCounts = counts;
+            mCount = count;
         }
         
         public String getLabel() {
@@ -307,28 +336,42 @@
             info.append(getString(R.string.battery_history_total_time));
             formatTime(mUsage[0], info);
             info.append("\n\n");
+        }
+    }
+    
+    
+    class WakelockUsage extends Graphable {
+        double[] mUsage;
+        int mCount;
+        
+        public WakelockUsage(int uid, long time, int count) {
+            getNameForUid(uid);
             
-            PackageManager pm = getPackageManager();
-            String[] packageNames = null;
-            for (Map.Entry<Integer,Integer> ent : mCounts.entrySet()) {
-                int uid = ent.getKey().intValue();
-                int count = ent.getValue().intValue();
-                packageNames = pm.getPackagesForUid(uid).clone();
-                
-                if (packageNames.length == 1) {
-                    info.append(getString(R.string.battery_history_sensor_usage,
-                            count, packageNames[0]));
-                } else {
-                    info.append(getString(R.string.battery_history_sensor_usage_multi, count));
-                    info.append("\n");
-                    // Convert package names to user-facing labels where possible
-                    for (int i = 0; i < packageNames.length; i++) {
-                        info.append("    ");
-                        info.append(BatteryHistory.getLabel(packageNames[i], pm));
-                        info.append("\n");
-                    }
-                }
-            }
+            mUsage = new double[1];
+            mUsage[0] = time;
+            
+            mCount = count;
+        }
+        
+        public String getLabel() {
+            return mName;
+        }
+        
+        public double getSortValue() {
+            return mUsage[0];
+        }
+        
+        public double[] getValues() {
+            return mUsage;
+        }
+        
+        public void getInfo(StringBuilder info) {
+            info.append(getString(R.string.battery_history_wakelock));
+            info.append(mName);
+            info.append("\n\n");
+            info.append(getString(R.string.battery_history_total_time));
+            formatTime(mUsage[0], info);
+            info.append("\n\n");
         }
     }
     
@@ -337,8 +380,9 @@
             case CPU_USAGE: return mCpuUsage;
             case NETWORK_USAGE : return mNetworkUsage;
             case SENSOR_USAGE: return mSensorUsage;
+            case GPS_USAGE: return mGpsUsage;
+            case WAKE_LOCKS: return mWakelockUsage;
             case SCREEN_ON: return null;
-            case WAKE_LOCKS:
             default:
                 return (List<? extends Graphable>) null; // TODO
         }
@@ -363,6 +407,8 @@
     private void displayGraph() {
         Log.i(TAG, "displayGraph");
 
+        collectStatistics();
+        
         // Hide the UI and selectively enable it below
         mMessageText.setVisibility(View.GONE);
         for (int i = 0; i < mButtons.length; i++) {
@@ -446,7 +492,8 @@
                     long starts = ps.getStarts(mWhich);
 
                     if (userTime != 0 || systemTime != 0) {
-                        mCpuUsage.add(new CpuUsage(ent.getKey(), userTime, systemTime, starts));
+                        mCpuUsage.add(new CpuUsage(u.getUid(), ent.getKey(),
+                                userTime, systemTime, starts));
                     }
                 }
             }
@@ -471,17 +518,10 @@
         Collections.sort(mNetworkUsage);
     }
     
-    class SensorRecord {
-        String name;
-        long totalTime;
-        HashMap<Integer,Integer> counts = new HashMap<Integer,Integer>();
-    }
-    
     private void processSensorUsage() {
+        mGpsUsage.clear();
         mSensorUsage.clear();
         
-        HashMap<Integer,SensorRecord> records = new HashMap<Integer,SensorRecord>();
-        
         long uSecTime = SystemClock.elapsedRealtime() * 1000;
         final long uSecNow = mStats.getBatteryUptime(uSecTime);
         
@@ -492,61 +532,132 @@
             int uid = u.getUid();
             
             Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
+            long timeGps = 0;
+            int countGps = 0;
+            long timeOther = 0;
+            int countOther = 0;
             if (sensorStats.size() > 0) {
                 for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
                         : sensorStats.entrySet()) {
 
                     Uid.Sensor se = ent.getValue();
-                    String name = se.getName();
-                    int sensorNumber = ent.getKey();
+                    int handle = se.getHandle();
                     Timer timer = se.getSensorTime();
                     if (timer != null) {
                         // Convert from microseconds to milliseconds with rounding
                         long totalTime = (timer.getTotalTime(uSecNow, mWhich) + 500) / 1000;
                         int count = timer.getCount(mWhich);
-                        
-                        SensorRecord record = records.get(sensorNumber);
-                        if (record == null) {
-                            record = new SensorRecord();
-                        }
-                        record.name = name;
-                        record.totalTime += totalTime;
-                        Integer c = record.counts.get(uid);
-                        if (c == null) {
-                            record.counts.put(uid, count);
+                        if (handle == BatteryStats.Uid.Sensor.GPS) {
+                            timeGps += totalTime;
+                            countGps += count;
                         } else {
-                            record.counts.put(uid, c.intValue() + count);
+                            timeOther += totalTime;
+                            countOther += count;
                         }
-                        records.put(sensorNumber, record);
                     }
                 }
             }
+            
+            if (timeGps > 0) {
+                mGpsUsage.add(new SensorUsage(uid, timeGps, countGps));
+            }
+            if (timeOther > 0) {
+                mSensorUsage.add(new SensorUsage(uid, timeOther, countOther));
+            }
         }
         
-        for (Map.Entry<Integer,SensorRecord> record : records.entrySet()) {
-            int sensorNumber = record.getKey().intValue();
-            SensorRecord r = record.getValue();
-            mSensorUsage.add(new SensorUsage(sensorNumber, r.name, r.totalTime, r.counts));
-        }
+        Collections.sort(mGpsUsage);
         Collections.sort(mSensorUsage);
     }
     
+    private void processWakelockUsage() {
+        mWakelockUsage.clear();
+        
+        long uSecTime = SystemClock.elapsedRealtime() * 1000;
+        final long uSecNow = mStats.getBatteryUptime(uSecTime);
+        
+        SparseArray<? extends Uid> uidStats = mStats.getUidStats();
+        final int NU = uidStats.size();
+        for (int iu = 0; iu < NU; iu++) {
+            Uid u = uidStats.valueAt(iu);
+            int uid = u.getUid();
+            
+            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
+            long time = 0;
+            int count = 0;
+            if (wakelockStats.size() > 0) {
+                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
+                        : wakelockStats.entrySet()) {
+
+                    Uid.Wakelock wl = ent.getValue();
+                    Timer timer = wl.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
+                    if (timer != null) {
+                        // Convert from microseconds to milliseconds with rounding
+                        time += (timer.getTotalTime(uSecNow, mWhich) + 500) / 1000;
+                        count += timer.getCount(mWhich);
+                    }
+                }
+            }
+            
+            if (time > 0) {
+                mWakelockUsage.add(new WakelockUsage(uid, time, count));
+            }
+        }
+        
+        Collections.sort(mWakelockUsage);
+    }
+    
     private void processScreenOn() {
         // Do nothing
     }
     
     private void collectStatistics() {
-        processCpuUsage();
-        processNetworkUsage();
-        processSensorUsage();
-        processScreenOn();
+        if (mType == CPU_USAGE) {
+            if (!mHaveCpuUsage) {
+                mHaveCpuUsage = true;
+                processCpuUsage();
+            }
+        }
+        if (mType == NETWORK_USAGE) {
+            if (!mHaveNetworkUsage) {
+                mHaveNetworkUsage = true;
+                processNetworkUsage();
+            }
+        }
+        if (mType == GPS_USAGE || mType == SENSOR_USAGE) {
+            if (!mHaveSensorUsage) {
+                mHaveSensorUsage = true;
+                processSensorUsage();
+            }
+        }
+        if (mType == WAKE_LOCKS) {
+            if (!mHaveWakelockUsage) {
+                mHaveWakelockUsage = true;
+                processWakelockUsage();
+            }
+        }
+        if (mType == SCREEN_ON) {
+            if (!mHaveScreenOnTime) {
+                mHaveScreenOnTime = true;
+                processScreenOn();
+            }
+        }
     }
     
-    private void refresh() {
+    private void load() {
         try {
-            mStats = mBatteryInfo.getStatistics();
-            collectStatistics();
-            displayGraph();
+            byte[] data = mBatteryInfo.getStatistics();
+            Parcel parcel = Parcel.obtain();
+            //Log.i(TAG, "Got data: " + data.length + " bytes");
+            parcel.unmarshall(data, 0, data.length);
+            parcel.setDataPosition(0);
+            mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
+                    .createFromParcel(parcel);
+            //Log.i(TAG, "RECEIVED BATTERY INFO:");
+            //mStats.dumpLocked(new LogPrinter(Log.INFO, TAG));
+            
+            mHaveCpuUsage =  mHaveNetworkUsage =  mHaveSensorUsage
+                    = mHaveWakelockUsage = mHaveScreenOnTime = false;
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException:", e);
         }
@@ -571,6 +682,8 @@
     }
 
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        int oldWhich = mWhich;
+        
         if (parent.equals(mTypeSpinner)) {
             mType = position;
             switch (position) {
@@ -580,20 +693,39 @@
                 case NETWORK_USAGE:
                     mWhichSpinner.setEnabled(true);
                     break;
+                case GPS_USAGE:
+                    mWhichSpinner.setEnabled(true);
+                    break;
                 case SENSOR_USAGE:
                     mWhichSpinner.setEnabled(true);
                     break;
+                case WAKE_LOCKS:
+                    mWhichSpinner.setEnabled(true);
+                    break;
                 case SCREEN_ON:
                     mWhichSpinner.setEnabled(false);
                     break;
-                case WAKE_LOCKS:
-                    break;
             }
         } else if (parent.equals(mWhichSpinner)) {
-            mWhich = position;
+            switch (position) {
+                case UNPLUGGED:
+                    mWhich = BatteryStats.STATS_UNPLUGGED;
+                    break;
+                case CURRENT:
+                    mWhich = BatteryStats.STATS_CURRENT;
+                    break;
+                case TOTAL:
+                    mWhich = BatteryStats.STATS_TOTAL;
+                    break;
+            }
         }
         
-        refresh();
+        if (oldWhich != mWhich) {
+            mHaveCpuUsage =  mHaveNetworkUsage =  mHaveSensorUsage
+                    = mHaveWakelockUsage = mHaveScreenOnTime = false;
+        }
+        
+        displayGraph();
     }
 
     public void onNothingSelected(AdapterView<?> parent) {
@@ -601,16 +733,27 @@
     }
     
     @Override
+    public Object onRetainNonConfigurationInstance() {
+        BatteryStats stats = mStats;
+        mStats = null;
+        return stats;
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mStats != null) {
+            outState.putParcelable("stats", mStats);
+        }
+        outState.putInt("type", mType);
+        outState.putInt("which", mWhich);
+    }
+
+    @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         Log.i(TAG, "onCreate");
         
-        String knownApps = getString(R.string.battery_history_known_apps);
-        String[] knownAppNames = knownApps.split(";");
-        for (String name : knownAppNames) {
-            mKnownApps.add(name);
-        }
-        
         setContentView(R.layout.battery_history);
         
         mGraphLayout = (LinearLayout) findViewById(R.id.graphLayout);
@@ -639,7 +782,20 @@
             mButtons[i].setOnClickListener(this);
         }
         
-        mBatteryInfo = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
-        refresh();
+        mBatteryInfo = IBatteryStats.Stub.asInterface(
+                ServiceManager.getService("batteryinfo"));
+        
+        mStats = (BatteryStats)getLastNonConfigurationInstance();
+        if (icicle != null) {
+            if (mStats == null) {
+                mStats = (BatteryStats)icicle.getParcelable("stats");
+            }
+            mType = icicle.getInt("type");
+            mWhich = icicle.getInt("which");
+        }
+        if (mStats == null) {
+            load();
+        }
+        displayGraph();
     }
 }
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
index 009ba5e..ac25535 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
@@ -45,23 +45,23 @@
  */
 public class LocalBluetoothDevice implements Comparable<LocalBluetoothDevice> {
     private static final String TAG = "LocalBluetoothDevice";
-    
+
     private static final int CONTEXT_ITEM_CONNECT = Menu.FIRST + 1;
     private static final int CONTEXT_ITEM_DISCONNECT = Menu.FIRST + 2;
     private static final int CONTEXT_ITEM_UNPAIR = Menu.FIRST + 3;
     private static final int CONTEXT_ITEM_CONNECT_ADVANCED = Menu.FIRST + 4;
-    
+
     private final String mAddress;
     private String mName;
     private short mRssi;
     private int mBtClass = BluetoothClass.ERROR;
-    
+
     private List<Profile> mProfiles = new ArrayList<Profile>();
-    
+
     private boolean mVisible;
-    
+
     private final LocalBluetoothManager mLocalManager;
-    
+
     private List<Callback> mCallbacks = new ArrayList<Callback>();
 
     /**
@@ -69,22 +69,22 @@
      * error even if they all fail. This tracks that state.
      */
     private boolean mIsConnectingErrorPossible;
-    
+
     LocalBluetoothDevice(Context context, String address) {
         mLocalManager = LocalBluetoothManager.getInstance(context);
         if (mLocalManager == null) {
             throw new IllegalStateException(
                     "Cannot use LocalBluetoothDevice without Bluetooth hardware");
         }
-        
+
         mAddress = address;
-        
+
         fillData();
     }
-    
+
     public void onClicked() {
         int bondState = getBondState();
-        
+
         if (isConnected()) {
             askDisconnect();
         } else if (bondState == BluetoothDevice.BOND_BONDED) {
@@ -93,22 +93,22 @@
             pair();
         }
     }
-    
+
     public void disconnect() {
         for (Profile profile : mProfiles) {
             disconnect(profile);
         }
     }
-    
+
     public void disconnect(Profile profile) {
         LocalBluetoothProfileManager profileManager =
-                LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile); 
+                LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
         int status = profileManager.getConnectionStatus(mAddress);
         if (SettingsBtStatus.isConnectionStatusConnected(status)) {
             profileManager.disconnect(mAddress);
         }
     }
-    
+
     public void askDisconnect() {
         Context context = mLocalManager.getForegroundActivity();
         if (context == null) {
@@ -116,21 +116,21 @@
             disconnect();
             return;
         }
-        
+
         Resources res = context.getResources();
-        
+
         String name = getName();
         if (TextUtils.isEmpty(name)) {
             name = res.getString(R.string.bluetooth_device);
         }
         String message = res.getString(R.string.bluetooth_disconnect_blank, name);
-        
+
         DialogInterface.OnClickListener disconnectListener = new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int which) {
                 disconnect();
             }
         };
-        
+
         AlertDialog ad = new AlertDialog.Builder(context)
                 .setTitle(getName())
                 .setMessage(message)
@@ -138,10 +138,10 @@
                 .setNegativeButton(android.R.string.cancel, null)
                 .show();
     }
-    
+
     public void connect() {
         if (!ensurePaired()) return;
-        
+
         // Reset the only-show-one-error-dialog tracking variable
         mIsConnectingErrorPossible = true;
 
@@ -155,18 +155,18 @@
                 connectInt(profile);
             }
         }
-        
+
         if (!hasAtLeastOnePreferredProfile) {
             connectAndPreferAllProfiles();
         }
     }
-    
+
     private void connectAndPreferAllProfiles() {
         if (!ensurePaired()) return;
-        
+
         // Reset the only-show-one-error-dialog tracking variable
         mIsConnectingErrorPossible = true;
-        
+
         Context context = mLocalManager.getContext();
         for (Profile profile : mProfiles) {
             LocalBluetoothProfileManager profileManager =
@@ -175,18 +175,18 @@
             connectInt(profile);
         }
     }
-    
+
     public void connect(Profile profile) {
         // Reset the only-show-one-error-dialog tracking variable
         mIsConnectingErrorPossible = true;
         connectInt(profile);
     }
-    
+
     public void connectInt(Profile profile) {
         if (!ensurePaired()) return;
-        
+
         LocalBluetoothProfileManager profileManager =
-                LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile); 
+                LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
         int status = profileManager.getConnectionStatus(mAddress);
         if (!SettingsBtStatus.isConnectionStatusConnected(status)) {
             if (profileManager.connect(mAddress) != BluetoothDevice.RESULT_SUCCESS) {
@@ -194,15 +194,15 @@
             }
         }
     }
-    
+
     public void showConnectingError() {
         if (!mIsConnectingErrorPossible) return;
         mIsConnectingErrorPossible = false;
-        
+
         mLocalManager.showError(mAddress, R.string.bluetooth_error_title,
                 R.string.bluetooth_connecting_error_message);
     }
-    
+
     private boolean ensurePaired() {
         if (getBondState() == BluetoothDevice.BOND_NOT_BONDED) {
             pair();
@@ -250,7 +250,7 @@
 
         dispatchAttributesChanged();
     }
-    
+
     public String getAddress() {
         return mAddress;
     }
@@ -258,20 +258,20 @@
     public String getName() {
         return mName;
     }
-    
+
     public void refreshName() {
         fetchName();
         dispatchAttributesChanged();
     }
-    
+
     private void fetchName() {
         mName = mLocalManager.getBluetoothManager().getRemoteName(mAddress);
-        
+
         if (TextUtils.isEmpty(mName)) {
             mName = mAddress;
         }
     }
-    
+
     public void refresh() {
         dispatchAttributesChanged();
     }
@@ -297,10 +297,10 @@
             dispatchAttributesChanged();
         }
     }
-    
+
     /**
      * Checks whether we are connected to this device (any profile counts).
-     * 
+     *
      * @return Whether it is connected.
      */
     public boolean isConnected() {
@@ -311,26 +311,26 @@
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     public boolean isBusy() {
         for (Profile profile : mProfiles) {
             int status = LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile)
-                    .getConnectionStatus(mAddress); 
+                    .getConnectionStatus(mAddress);
             if (SettingsBtStatus.isConnectionStatusBusy(status)) {
                 return true;
             }
         }
-        
+
         if (getBondState() == BluetoothDevice.BOND_BONDING) {
             return true;
         }
-        
+
         return false;
     }
-    
+
     public int getBtClassDrawable() {
 
         // First try looking at profiles
@@ -339,7 +339,7 @@
         } else if (mProfiles.contains(Profile.HEADSET)) {
             return R.drawable.ic_bt_headset_hfp;
         }
-        
+
         // Fallback on class
         switch (BluetoothClass.Device.Major.getDeviceMajor(mBtClass)) {
         case BluetoothClass.Device.Major.COMPUTER:
@@ -347,7 +347,7 @@
 
         case BluetoothClass.Device.Major.PHONE:
             return R.drawable.ic_bt_cellphone;
-            
+
         default:
             return 0;
         }
@@ -370,19 +370,19 @@
         fetchBtClass();
         dispatchAttributesChanged();
     }
-    
+
     public int getSummary() {
         // TODO: clean up
         int oneOffSummary = getOneOffSummary();
         if (oneOffSummary != 0) {
             return oneOffSummary;
         }
-        
+
         for (Profile profile : mProfiles) {
             LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
                     .getProfileManager(mLocalManager, profile);
             int connectionStatus = profileManager.getConnectionStatus(mAddress);
-            
+
             if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus) ||
                     connectionStatus == SettingsBtStatus.CONNECTION_STATUS_CONNECTING ||
                     connectionStatus == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING) {
@@ -396,17 +396,17 @@
     /**
      * We have special summaries when particular profiles are connected. This
      * checks for those states and returns an applicable summary.
-     * 
-     * @return A one-off summary that is applicable for the current state, or 0. 
+     *
+     * @return A one-off summary that is applicable for the current state, or 0.
      */
     private int getOneOffSummary() {
         boolean isA2dpConnected = false, isHeadsetConnected = false, isConnecting = false;
-        
+
         if (mProfiles.contains(Profile.A2DP)) {
             LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
                     .getProfileManager(mLocalManager, Profile.A2DP);
             isConnecting = profileManager.getConnectionStatus(mAddress) ==
-                    SettingsBtStatus.CONNECTION_STATUS_CONNECTING; 
+                    SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
             isA2dpConnected = profileManager.isConnected(mAddress);
         }
 
@@ -414,10 +414,10 @@
             LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
                     .getProfileManager(mLocalManager, Profile.HEADSET);
             isConnecting |= profileManager.getConnectionStatus(mAddress) ==
-                    SettingsBtStatus.CONNECTION_STATUS_CONNECTING; 
+                    SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
             isHeadsetConnected = profileManager.isConnected(mAddress);
         }
-        
+
         if (isConnecting) {
             // If any of these important profiles is connecting, prefer that
             return SettingsBtStatus.getConnectionStatusSummary(
@@ -432,7 +432,7 @@
             return 0;
         }
     }
-    
+
     public List<Profile> getProfiles() {
         return new ArrayList<Profile>(mProfiles);
     }
@@ -440,13 +440,13 @@
     public void onCreateContextMenu(ContextMenu menu) {
         // No context menu if it is busy (none of these items are applicable if busy)
         if (isBusy()) return;
-        
+
         int bondState = getBondState();
         boolean isConnected = isConnected();
         boolean hasProfiles = mProfiles.size() > 0;
-        
+
         menu.setHeaderTitle(getName());
-        
+
         if (isConnected) {
             menu.add(0, CONTEXT_ITEM_DISCONNECT, 0, R.string.bluetooth_device_context_disconnect);
         } else if (hasProfiles) {
@@ -456,7 +456,7 @@
                     : R.string.bluetooth_device_context_connect;
             menu.add(0, CONTEXT_ITEM_CONNECT, 0, connectString);
         }
-        
+
         if (bondState == BluetoothDevice.BOND_BONDED) {
             // For unpair action, show either "Unpair" or "Disconnect & unpair"
             int unpairString = isConnected
@@ -472,7 +472,7 @@
 
     /**
      * Called when a context menu item is clicked.
-     * 
+     *
      * @param item The item that was clicked.
      */
     public void onContextItemSelected(MenuItem item) {
@@ -480,15 +480,16 @@
             case CONTEXT_ITEM_DISCONNECT:
                 disconnect();
                 break;
-                
+
             case CONTEXT_ITEM_CONNECT:
                 connect();
                 break;
-                
+
             case CONTEXT_ITEM_UNPAIR:
+                mLocalManager.getBluetoothManager().disconnectRemoteDeviceAcl(mAddress);
                 unpair();
                 break;
-                
+
             case CONTEXT_ITEM_CONNECT_ADVANCED:
                 Intent intent = new Intent();
                 // Need an activity context to open this in our task
@@ -510,13 +511,13 @@
             mCallbacks.add(callback);
         }
     }
-    
+
     public void unregisterCallback(Callback callback) {
         synchronized (mCallbacks) {
             mCallbacks.remove(callback);
         }
     }
-    
+
     private void dispatchAttributesChanged() {
         synchronized (mCallbacks) {
             for (Callback callback : mCallbacks) {
@@ -524,7 +525,7 @@
             }
         }
     }
-    
+
     @Override
     public String toString() {
         return mAddress;
@@ -535,7 +536,7 @@
         if ((o == null) || !(o instanceof LocalBluetoothDevice)) {
             throw new ClassCastException();
         }
-        
+
         return mAddress.equals(((LocalBluetoothDevice) o).mAddress);
     }
 
@@ -543,14 +544,14 @@
     public int hashCode() {
         return mAddress.hashCode();
     }
-    
+
     public int compareTo(LocalBluetoothDevice another) {
-        int comparison;        
-        
+        int comparison;
+
         // Connected above not connected
         comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0);
         if (comparison != 0) return comparison;
-        
+
         // Paired above not paired
         comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) -
             (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0);
@@ -559,11 +560,11 @@
         // Visible above not visible
         comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0);
         if (comparison != 0) return comparison;
-        
+
         // Stronger signal above weaker signal
         comparison = another.mRssi - mRssi;
         if (comparison != 0) return comparison;
-        
+
         // Fallback on name
         return getName().compareTo(another.getName());
     }
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index 98aa12b..4132ed5 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -52,7 +52,6 @@
  * # Network
  * # Roaming
  * # IMEI
- * # IMSI
  * # Network type
  * # Signal Strength
  * # Battery Strength  : TODO
@@ -190,7 +189,6 @@
         setSummaryText("imei_sv",
                 ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
                         .getDeviceSoftwareVersion());
-        setSummaryText("imsi", mPhone.getSubscriberId());
         setSummaryText("number", mPhone.getLine1Number());
 
         mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);