Merge change 7913 into donut

* changes:
  Reorganize message posting when updating sizes and resources. Rather than posting a message for each package, post a message for  a set of packages(8) so that we don't end up posting too many messages and making the UI non-responsive by keeping the Handler too busy. We just pass the loaded info as a map in the message object. Changes to back ground threads that compute sizes and load resources.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2092321..1500d8b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -127,6 +127,7 @@
         </activity>
 
         <activity android:name=".vpn.VpnSettings"
+                android:configChanges="orientation|keyboardHidden"
                 android:launchMode="singleTask">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -136,8 +137,12 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".vpn.VpnTypeSelection"></activity>
-        <activity android:name=".vpn.VpnEditor"></activity>
+        <activity android:name=".vpn.VpnTypeSelection"
+                android:configChanges="orientation|keyboardHidden">
+        </activity>
+        <activity android:name=".vpn.VpnEditor"
+                android:configChanges="orientation|keyboardHidden">
+        </activity>
 
         <activity android:name="DateTimeSettings" android:label="@string/date_and_time"
                 >
@@ -270,6 +275,7 @@
         </activity>
 
         <activity android:name="SecuritySettings" android:label="@string/security_settings_title"
+                android:configChanges="orientation|keyboardHidden"
                 android:clearTaskOnLaunch="true"
                 >
             <intent-filter>
diff --git a/res/layout/cstor_name_credential_dialog_view.xml b/res/layout/cstor_name_credential_dialog_view.xml
index e5ccb36..33688bd 100644
--- a/res/layout/cstor_name_credential_dialog_view.xml
+++ b/res/layout/cstor_name_credential_dialog_view.xml
@@ -46,6 +46,22 @@
                 android:layout_height="wrap_content"
                 android:singleLine="True"/>
 
+        <LinearLayout android:id="@+id/cstor_credential_password_container"
+                xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:padding="0dip">
+            <TextView android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/cstor_credential_password" />
+            <EditText android:id="@+id/cstor_credential_password"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:password="True"
+                    android:singleLine="True"/>
+        </LinearLayout>
+
         <TextView android:id="@+id/cstor_credential_info_title"
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"
diff --git a/res/layout/power_usage_action_item.xml b/res/layout/power_usage_action_item.xml
new file mode 100644
index 0000000..7b81ec1
--- /dev/null
+++ b/res/layout/power_usage_action_item.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingLeft="4dip"
+    android:focusable="true"
+    android:orientation="vertical"
+    android:paddingRight="?android:attr/scrollbarSize">
+
+    <TextView android:id="@+id/summary"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="2dip"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+    <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+        <!-- Spacer -->
+        <View
+                android:id="@+id/buttons_spacer_left"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.7"
+                android:visibility="invisible" />
+
+        <Button
+                android:id="@+id/action_button"
+                android:layout_width="150dip"
+                android:paddingRight="6dip"
+                android:layout_weight="0.3"
+                android:layout_height="wrap_content"/>
+    </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/power_usage_details.xml b/res/layout/power_usage_details.xml
index ea7cfb3..f7485ee 100644
--- a/res/layout/power_usage_details.xml
+++ b/res/layout/power_usage_details.xml
@@ -103,43 +103,18 @@
         </LinearLayout>
 
         <LinearLayout
-            android:id="@+id/controls_section"
+            android:id="@+id/controls"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
             <TextView
-                android:id="@+id/controls_section_title"
+                android:id="@+id/controls_title"
                 style="?android:attr/listSeparatorTextViewStyle"
                 android:layout_marginTop="6dip"
                 android:text="@string/controls_subtitle" />
-            
-            <RelativeLayout
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content">
 
-                <Button
-                    android:id="@+id/action_button1"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginLeft="6dip"
-                    android:layout_marginTop="6dip"
-                    android:layout_marginBottom="6dip"
-                    android:layout_marginRight="6dip"
-                    android:layout_alignParentLeft="true"
-                    android:layout_weight="1"/>
-                <Button
-                    android:id="@+id/action_button2"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginLeft="6dip"
-                    android:layout_marginTop="6dip"
-                    android:layout_marginBottom="6dip"
-                    android:layout_marginRight="6dip"
-                    android:layout_alignParentRight="true"
-                    android:layout_weight="1"/>
-
-            </RelativeLayout>
+            <!-- Controls go here ... -->
 
         </LinearLayout>
                     
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index ebc7a85..4318c37 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"Nastavte jas displeje"</string>
     <string name="screen_timeout">"Interval vypnutí obrazovky"</string>
     <string name="screen_timeout_summary">"Upravte prodlevu, po které se obrazovka automaticky vypne"</string>
-    <string name="compatibility_mode_title">"Režim kompatibility"</string>
-    <string name="compatibility_mode_summary_on">"Spustit starší aplikace v režimu kompatibility. Akce vyžaduje restartování."</string>
-    <string name="compatibility_mode_summary_off">"Spustit starší aplikace v režimu kompatibility. Akce vyžaduje restartování."</string>
     <string name="sim_lock_settings">"Nastavení zámku karty SIM"</string>
     <string name="sim_lock_settings_category">"Nastavení zámku karty SIM"</string>
     <string name="sim_lock_settings_title">"Zámek karty SIM"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index c852419..9171acb 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Juster skærmens lysstyrke"</string>
     <string name="screen_timeout">"Timeout for skærmen"</string>
     <string name="screen_timeout_summary">"Juster forsinkelsen, inden skærmen slukkes automatisk"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Indstillinger for lås af SIM-kort"</string>
     <string name="sim_lock_settings_category">"Opsæt SIM-kortlås"</string>
     <string name="sim_lock_settings_title">"SIM-kortlås"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index f5742ea..da1cc44 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"Helligkeit des Bildschirms anpassen"</string>
     <string name="screen_timeout">"Display-Timeout"</string>
     <string name="screen_timeout_summary">"Verzögerung vor automatischer Bildschirmabschaltung anpassen"</string>
-    <string name="compatibility_mode_title">"Kompatibilitätsmodus"</string>
-    <string name="compatibility_mode_summary_on">"Ältere Anwendungen im Kompatibilitätsmodus ausführen. Neustart erforderlich."</string>
-    <string name="compatibility_mode_summary_off">"Ältere Anwendungen im Kompatibilitätsmodus ausführen. Neustart erforderlich."</string>
     <string name="sim_lock_settings">"Einstellungen"</string>
     <string name="sim_lock_settings_category">"SIM-Sperrung einrichten"</string>
     <string name="sim_lock_settings_title">"SIM-Kartensperrung"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 77cbc58..4b48799 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Ρύθμιση της φωτεινότητας της οθόνης"</string>
     <string name="screen_timeout">"Λήξη ορίου χρόνου οθόνης"</string>
     <string name="screen_timeout_summary">"Προσαρμόστε τον χρόνο που πρέπει να παρέλθει πριν από την αυτόματη απενεργοποίηση της οθόνης."</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Ρυθμίσεις κλειδώματος κάρτας SIM"</string>
     <string name="sim_lock_settings_category">"Ορισμός κλειδώματος κάρτας SIM"</string>
     <string name="sim_lock_settings_title">"Κλείδωμα κάρτας SIM"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 239c342..029a308 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Ajustar el brillo de la pantalla"</string>
     <string name="screen_timeout">"Tiempo de espera de la pantalla"</string>
     <string name="screen_timeout_summary">"Ajustar el tiempo de demora para que la pantalla se apague automáticamente"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Configuración de bloqueo de la tarjeta SIM"</string>
     <string name="sim_lock_settings_category">"Establecer bloqueo de la tarjeta SIM"</string>
     <string name="sim_lock_settings_title">"Bloqueo de la tarjeta SIM"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index e5f34ba..ad85dbb 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"Ajustar el brillo de la pantalla"</string>
     <string name="screen_timeout">"Tiempo espera pantalla"</string>
     <string name="screen_timeout_summary">"Ajustar el tiempo de retraso antes de que la pantalla se apague automáticamente"</string>
-    <string name="compatibility_mode_title">"Modo de compatibilidad"</string>
-    <string name="compatibility_mode_summary_on">"Permite ejecutar aplicaciones antiguas en modo de compatibilidad. Es necesario reiniciar."</string>
-    <string name="compatibility_mode_summary_off">"Permite ejecutar aplicaciones antiguas en modo de compatibilidad. Es necesario reiniciar."</string>
     <string name="sim_lock_settings">"Configuración de bloqueo de tarjeta SIM"</string>
     <string name="sim_lock_settings_category">"Bloqueo de tarjeta SIM"</string>
     <string name="sim_lock_settings_title">"Bloqueo de tarjeta SIM"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 5bdb1ec..c1d4893 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"Régler la luminosité de l\'écran"</string>
     <string name="screen_timeout">"Mise en veille de l\'écran"</string>
     <string name="screen_timeout_summary">"Définir le délai avant la mise hors tension automatique de l\'écran"</string>
-    <string name="compatibility_mode_title">"Mode de compatibilité"</string>
-    <string name="compatibility_mode_summary_on">"Exécuter les applications plus anciennes en mode de compatibilité. Nécessite un redémarrage du système."</string>
-    <string name="compatibility_mode_summary_off">"Exécuter les applications plus anciennes en mode de compatibilité. Nécessite un redémarrage du système."</string>
     <string name="sim_lock_settings">"Paramètres de blocage carte SIM"</string>
     <string name="sim_lock_settings_category">"Configurer blocage SIM"</string>
     <string name="sim_lock_settings_title">"Blocage de la carte SIM"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 0c6e6e6..c44159f 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"Regola la luminosità dello schermo"</string>
     <string name="screen_timeout">"Timeout schermo"</string>
     <string name="screen_timeout_summary">"Regola il tempo che deve trascorrere prima che lo schermo si spenga automaticamente"</string>
-    <string name="compatibility_mode_title">"Modalità Compatibilità"</string>
-    <string name="compatibility_mode_summary_on">"Esegui applicazioni meno recenti in modalità Compatibilità. Richiede il riavvio."</string>
-    <string name="compatibility_mode_summary_off">"Esegui applicazioni meno recenti in modalità Compatibilità. Richiede il riavvio."</string>
     <string name="sim_lock_settings">"Impostazioni blocco SIM"</string>
     <string name="sim_lock_settings_category">"Impostazioni blocco SIM"</string>
     <string name="sim_lock_settings_title">"Blocco della SIM"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 663fb95..acc1fa9 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -440,12 +440,6 @@
     <string name="brightness_summary">"画面の明るさを調整する"</string>
     <string name="screen_timeout">"バックライト消灯"</string>
     <string name="screen_timeout_summary">"画面バックライトを自動消灯するまでの時間"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"SIMカードロック設定"</string>
     <string name="sim_lock_settings_category">"SIMカードロック設定"</string>
     <string name="sim_lock_settings_title">"SIMカードロック"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 7dae36d..aad6553 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"화면 밝기 조정"</string>
     <string name="screen_timeout">"화면 시간제한"</string>
     <string name="screen_timeout_summary">"화면 자동 꺼짐 시간 간격 조정"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"SIM 카드 잠금 설정"</string>
     <string name="sim_lock_settings_category">"SIM 카드 잠금 설정"</string>
     <string name="sim_lock_settings_title">"SIM 카드 잠금"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index c73c7ee..60f5b12 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -440,12 +440,6 @@
     <string name="brightness_summary">"Juster skjermens lysstyrke"</string>
     <string name="screen_timeout">"Skjermsparer"</string>
     <string name="screen_timeout_summary">"Juster hvor lang tid som skal gå før skjermen slås av automatisk"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Innstillinger for SIM-kort-lås"</string>
     <string name="sim_lock_settings_category">"Sett opp SIM-kort-lås"</string>
     <string name="sim_lock_settings_title">"SIM-kort-lås"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 71b10d7..24fbd82 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"Helderheid van het scherm aanpassen"</string>
     <string name="screen_timeout">"Time-out scherm"</string>
     <string name="screen_timeout_summary">"De vertraging voor het automatisch uitschakelen van het scherm aanpassen"</string>
-    <string name="compatibility_mode_title">"Compatibiliteitsmodus"</string>
-    <string name="compatibility_mode_summary_on">"Oudere toepassingen uitvoeren in compatibiliteitsmodus. Het apparaat moet hiervoor opnieuw worden opgestart."</string>
-    <string name="compatibility_mode_summary_off">"Oudere toepassingen uitvoeren in compatibiliteitsmodus. Het apparaat moet hiervoor opnieuw worden opgestart."</string>
     <string name="sim_lock_settings">"Instellingen SIM-kaartvergrendeling"</string>
     <string name="sim_lock_settings_category">"SIM-kaartvergrendeling instellen"</string>
     <string name="sim_lock_settings_title">"SIM-kaartvergrendeling"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 328bb6a..cbdee07 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"Dostosuj jasność ekranu"</string>
     <string name="screen_timeout">"Wygaszanie ekranu"</string>
     <string name="screen_timeout_summary">"Dostosuj opóźnienie automatycznego wyłączenia ekranu"</string>
-    <string name="compatibility_mode_title">"Tryb zgodności"</string>
-    <string name="compatibility_mode_summary_on">"Uruchamiaj starsze aplikacje w trybie zgodności. Ta opcja wymaga ponownego uruchomienia."</string>
-    <string name="compatibility_mode_summary_off">"Uruchamiaj starsze aplikacje w trybie zgodności. Ta opcja wymaga ponownego uruchomienia."</string>
     <string name="sim_lock_settings">"Ustawienia blokady karty SIM"</string>
     <string name="sim_lock_settings_category">"Ustaw blokadę SIM"</string>
     <string name="sim_lock_settings_title">"Blokada karty SIM"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 32b3ab9..a3acade 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Ajustar o brilho do ecrã"</string>
     <string name="screen_timeout">"Tempo limite do ecrã"</string>
     <string name="screen_timeout_summary">"Ajustar o tempo limite até à desactivação automática do ecrã"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Definições de bloqueio do cartão SIM"</string>
     <string name="sim_lock_settings_category">"Configurar bloqueio do cartão SIM"</string>
     <string name="sim_lock_settings_title">"Bloqueio do cartão SIM"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index b96bbdc..e741141 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Ajustar o brilho da tela"</string>
     <string name="screen_timeout">"Tempo limite da tela"</string>
     <string name="screen_timeout_summary">"Ajuste depois de quanto tempo a tela será desligada automaticamente"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Configurações de bloqueio do cartão SIM"</string>
     <string name="sim_lock_settings_category">"Configurar bloqueio do cartão SIM"</string>
     <string name="sim_lock_settings_title">"Bloqueio do cartão SIM"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 7dd352b..f465add 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Настроить яркость экрана"</string>
     <string name="screen_timeout">"Время отключения экрана"</string>
     <string name="screen_timeout_summary">"Выбрать интервал до автоматического отключения экрана"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Настройки блокировки SIM-карты"</string>
     <string name="sim_lock_settings_category">"Настроить блокировку SIM-карты"</string>
     <string name="sim_lock_settings_title">"Блокировка SIM-карты"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 988ef8c..94294f5 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Ändra skärmens ljusstyrka"</string>
     <string name="screen_timeout">"Skärmens tidsgräns"</string>
     <string name="screen_timeout_summary">"Justera fördröjningen innan skärmen stängs av automatiskt"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"Låsinställningar för SIM-kort"</string>
     <string name="sim_lock_settings_category">"Ställ in lås för SIM-kort"</string>
     <string name="sim_lock_settings_title">"Lås för SIM-kort"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 84d95a7..8e5bb12 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"Ekranın parlaklığını ayarla"</string>
     <string name="screen_timeout">"Ekran zaman aşımı"</string>
     <string name="screen_timeout_summary">"Ekran otomatik olarak kapanmadan önceki gecikmeyi ayarla"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"SIM kart kilit ayarları"</string>
     <string name="sim_lock_settings_category">"SIM kart kilidini ayarla"</string>
     <string name="sim_lock_settings_title">"SIM kart kilidi"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index f3a503a..a990f93 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -438,12 +438,6 @@
     <string name="brightness_summary">"调整屏幕亮度"</string>
     <string name="screen_timeout">"屏幕待机"</string>
     <string name="screen_timeout_summary">"调整屏幕自动关闭前的延迟"</string>
-    <!-- no translation found for compatibility_mode_title (2809863666656220144) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_on (5152752781240489958) -->
-    <skip />
-    <!-- no translation found for compatibility_mode_summary_off (2826410352749339514) -->
-    <skip />
     <string name="sim_lock_settings">"SIM 卡锁定设置"</string>
     <string name="sim_lock_settings_category">"设置 SIM 卡锁定"</string>
     <string name="sim_lock_settings_title">"SIM 卡锁定"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index d9e9f3f..d1f1296 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -406,9 +406,6 @@
     <string name="brightness_summary">"調整螢幕亮度"</string>
     <string name="screen_timeout">"螢幕逾時"</string>
     <string name="screen_timeout_summary">"調整螢幕自動關閉前的延遲時間"</string>
-    <string name="compatibility_mode_title">"相容性模式"</string>
-    <string name="compatibility_mode_summary_on">"在相容性模式中執行版本較舊的應用程式 (必須重新開機)。"</string>
-    <string name="compatibility_mode_summary_off">"在相容性模式中執行版本較舊的應用程式 (必須重新開機)。"</string>
     <string name="sim_lock_settings">"SIM 卡鎖定設定"</string>
     <string name="sim_lock_settings_category">"設定 SIM 卡鎖定"</string>
     <string name="sim_lock_settings_title">"SIM 卡鎖定"</string>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index a470acc..6ec90ca 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -255,4 +255,17 @@
         <item>2</item>
     </string-array>
 
+    <!-- Locales in this list are displayed with the corresponding
+         name from special_locale_names instead of using the name
+         from Locale.getDisplayName(). -->
+    <string-array translatable="false" name="special_locale_codes">
+        <item>zh_CN</item>
+        <item>zh_TW</item>
+    </string-array>
+
+    <string-array translatable="false" name="special_locale_names">
+        <item>中文(简体)</item>
+        <item>中文 (繁體)</item>
+    </string-array>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f7d76a4..c891979 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -890,13 +890,6 @@
     <!-- Sound & display settings screen, setting option summary to change screen timeout -->
     <string name="screen_timeout_summary">Adjust the delay before the screen automatically turns off</string>
 
-    <!-- Sound & display settings screen, compatibility mode check box label -->
-    <string name="compatibility_mode_title">Compatibility Mode</string>
-    <!-- Sound & display settings screen, compatibility mode option summary text when check box is selected -->
-    <string name="compatibility_mode_summary_on">Run older apps in Compatibility mode. This require rebooting. </string>
-    <!-- Sound & display settings screen, compatibility mode option summary text when check box is clear -->
-    <string name="compatibility_mode_summary_off">Run older apps in Compatibility mode. This require rebooting. </string>
-
     <!-- SIM lock settings title -->
     <string name="sim_lock_settings">SIM card lock settings</string>
     <!-- Security & location settings screen, setting option name -->
@@ -1658,6 +1651,8 @@
     <string name="battery_since_reset">Battery use since reset</string>
     <!-- Battery usage duration -->
     <string name="battery_stats_duration"><xliff:g id="time">%1$s</xliff:g> since unplugged</string>
+    <!-- Battery usage during last unplugged period -->
+    <string name="battery_stats_last_duration">@string/menu_stats_last_unplugged</string>
     <!-- CPU awake time title -->
     <string name="awake">Device awake time</string>
     <!-- Wifi on time -->
@@ -1707,7 +1702,9 @@
     <!-- Label for Video usage time -->
     <string name="usage_type_video">Video</string>
     <!-- Label for time that a feature has been on -->
-    <string name="usage_type_on_time">On time</string>
+    <string name="usage_type_on_time">Time on</string>
+    <!-- Label for time that there was no cell coverage -->
+    <string name="usage_type_no_coverage">Time without a signal</string>
     <!-- Label for force stop action -->
     <string name="battery_action_stop">Force stop</string>
     <!-- Label for app details action -->
@@ -1754,7 +1751,7 @@
     <!-- Suggestion for exploring application info to stop or uninstall -->
     <string name="battery_sugg_apps_info">Stop or uninstall the application</string>
     <!-- Suggestion for getting apps to consume less power due to GPS-->
-    <string name="battery_sugg_apps_gps">Turn off GPS when you're not using it</string>
+    <string name="battery_sugg_apps_gps">"Turn off GPS when you're not using it"</string>
     <!-- Suggestion for getting apps to consume less power -->
     <string name="battery_sugg_apps_settings">The application may offer settings to reduce battery use</string>
 
@@ -1968,6 +1965,8 @@
     <!-- Description for the credential name input box -->
     <string name="cstor_credential_name">Certificate name:</string>
     <!-- Title of the credential info -->
+    <!-- Description for the credential password input box -->
+    <string name="cstor_credential_password">Password to extract the certificate:</string>
     <string name="cstor_credential_info">Certificate details:</string>
     <string name="cstor_name_credential_hint">The name can contain only letters and numbers.</string>
 
@@ -1991,12 +1990,12 @@
     <string name="cstor_password_verification_error">Please enter the password again. The password must have at least 8 characters and must not contain spaces.</string>
     <string name="cstor_name_empty_error">Please enter a name.</string>
     <string name="cstor_name_char_error">Please enter a name that contains only letters and numbers.</string>
+    <string name="cstor_storage_error">Unable to save the certificate. Click OK to retry.</string>
 
     <!-- toast message -->
     <string name="cstor_is_enabled">Credential storage is enabled.</string>
     <!-- toast message -->
     <string name="cstor_is_added">%s is added.</string>
-    <string name="cstor_add_error">Failed to add %s.</string>
 
     <!-- Sound settings screen, setting check box label -->
     <string name="emergency_tone_title">Emergency tone</string>
diff --git a/res/xml/sound_and_display_settings.xml b/res/xml/sound_and_display_settings.xml
index 223e52a..639204a 100644
--- a/res/xml/sound_and_display_settings.xml
+++ b/res/xml/sound_and_display_settings.xml
@@ -130,12 +130,6 @@
                 android:persistent="false"
                 android:entries="@array/screen_timeout_entries"
                 android:entryValues="@array/screen_timeout_values" />
-
-        <CheckBoxPreference
-                android:key="compatibility_mode"
-                android:title="@string/compatibility_mode_title"
-                android:summaryOn="@string/compatibility_mode_summary_on"
-                android:summaryOff="@string/compatibility_mode_summary_off" />
     </PreferenceCategory>
 
 </PreferenceScreen>   
diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
index b2dcee2..2ead31b 100644
--- a/src/com/android/settings/CreateShortcut.java
+++ b/src/com/android/settings/CreateShortcut.java
@@ -17,6 +17,8 @@
         Intent shortcutIntent = intentForPosition(position);
         shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
         Intent intent = new Intent();
+        intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
+                Intent.ShortcutIconResource.fromContext(this, R.drawable.ic_launcher_settings));
         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, itemForPosition(position).label);
         setResult(RESULT_OK, intent);
diff --git a/src/com/android/settings/LocalePicker.java b/src/com/android/settings/LocalePicker.java
index 39fb6fa..d31e82c 100644
--- a/src/com/android/settings/LocalePicker.java
+++ b/src/com/android/settings/LocalePicker.java
@@ -39,6 +39,8 @@
     private static final String TAG = "LocalePicker";
 
     Loc[] mLocales;
+    String[] mSpecialLocaleCodes;
+    String[] mSpecialLocaleNames;
 
     private static class Loc implements Comparable {
         static Collator sCollator = Collator.getInstance();
@@ -70,6 +72,9 @@
         super.onCreate(icicle);
         setContentView(getContentView());
 
+        mSpecialLocaleCodes = getResources().getStringArray(R.array.special_locale_codes);
+        mSpecialLocaleNames = getResources().getStringArray(R.array.special_locale_names);
+
         String[] locales = getAssets().getLocales();
         Arrays.sort(locales);
 
@@ -98,15 +103,13 @@
                             language)) {
                         Log.v(TAG, "backing up and fixing "+
                                 preprocess[finalSize-1].label+" to "+
-                                preprocess[finalSize-1].locale.
-                                getDisplayName(l));
+                                getDisplayName(preprocess[finalSize-1].locale));
                         preprocess[finalSize-1].label = toTitleCase(
-                                preprocess[finalSize-1].
-                                locale.getDisplayName(l));
+                                getDisplayName(preprocess[finalSize-1].locale));
                         Log.v(TAG, "  and adding "+
-                                toTitleCase(l.getDisplayName(l)));
+                                toTitleCase(getDisplayName(l)));
                         preprocess[finalSize++] =
-                                new Loc(toTitleCase(l.getDisplayName(l)), l);
+                                new Loc(toTitleCase(getDisplayName(l)), l);
                     } else {
                         String displayName;
                         if (s.equals("zz_ZZ")) {
@@ -140,6 +143,18 @@
         return Character.toUpperCase(s.charAt(0)) + s.substring(1);
     }
 
+    private String getDisplayName(Locale l) {
+        String code = l.toString();
+
+        for (int i = 0; i < mSpecialLocaleCodes.length; i++) {
+            if (mSpecialLocaleCodes[i].equals(code)) {
+                return mSpecialLocaleNames[i];
+            }
+        }
+
+        return l.getDisplayName(l);
+    }
+
     @Override
     public void onResume() {
         super.onResume();
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index d3c0783..63d88d3 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -37,6 +37,7 @@
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
 import android.provider.Settings;
+import android.security.CertTool;
 import android.security.Keystore;
 import android.text.Html;
 import android.text.TextUtils;
@@ -515,16 +516,6 @@
             mAccessCheckBox.setChecked(false);
         }
 
-        private void addCredential() {
-            String formatString = mCstorAddCredentialHelper.saveToStorage() < 0
-                    ? getString(R.string.cstor_add_error)
-                    : getString(R.string.cstor_is_added);
-            String message = String.format(formatString,
-                    mCstorAddCredentialHelper.getName());
-            Toast.makeText(SecuritySettings.this, message, Toast.LENGTH_SHORT)
-                    .show();
-        }
-
         public void onCancel(DialogInterface dialog) {
             if (mCstorAddCredentialHelper != null) {
                 // release the object here so that it doesn't get triggerred in
@@ -567,13 +558,22 @@
             } else {
                 removeDialog(mDialogId);
 
+                if (mDialogId == CSTOR_UNLOCK_DIALOG) {
+                    mAccessCheckBox.setChecked(isCstorUnlocked());
+                }
+
                 if (mCstorAddCredentialHelper != null) {
                     if (!isCstorInitialized()) {
                         showDialog(CSTOR_INIT_DIALOG);
                     } else if (!isCstorUnlocked()) {
                         showDialog(CSTOR_UNLOCK_DIALOG);
                     } else {
-                        addCredential();
+                        String formatString =
+                                getString(R.string.cstor_is_added);
+                        String message = String.format(formatString,
+                                mCstorAddCredentialHelper.getName());
+                        Toast.makeText(SecuritySettings.this, message,
+                                Toast.LENGTH_SHORT).show();
                         finish();
                     }
                 } else if (mSpecialIntent != null) {
@@ -614,6 +614,26 @@
             }
 
             mCstorAddCredentialHelper.setName(name);
+
+            if (mCstorAddCredentialHelper.isPkcs12Keystore()) {
+                String password = getText(R.id.cstor_credential_password);
+                if (TextUtils.isEmpty(password)) {
+                    showError(R.string.cstor_password_empty_error);
+                    return false;
+                }
+
+                mCstorAddCredentialHelper.setPassword(password);
+            }
+
+            if (mCstorAddCredentialHelper.saveToStorage() < 0) {
+                if (mCstorAddCredentialHelper.isPkcs12Keystore()) {
+                    showError(R.string.cstor_password_error);
+                } else {
+                    showError(R.string.cstor_storage_error);
+                }
+                return false;
+            }
+
             return true;
         }
 
@@ -865,6 +885,9 @@
             mView = View.inflate(SecuritySettings.this,
                     R.layout.cstor_name_credential_dialog_view, null);
             hideError();
+            if (!mCstorAddCredentialHelper.isPkcs12Keystore()) {
+                hide(R.id.cstor_credential_password_container);
+            }
 
             setText(R.id.cstor_credential_name_title,
                     R.string.cstor_credential_name);
@@ -891,6 +914,7 @@
         private List<String> mNamespaceList;
         private String mDescription;
         private String mName;
+        private String mPassword;
 
         CstorAddCredentialHelper(Intent intent) {
             parse(intent);
@@ -900,6 +924,10 @@
             return mTypeName;
         }
 
+        boolean isPkcs12Keystore() {
+            return CertTool.TITLE_PKCS12_KEYSTORE.equals(mTypeName);
+        }
+
         CharSequence getDescription() {
             return Html.fromHtml(mDescription);
         }
@@ -912,12 +940,26 @@
             return mName;
         }
 
+        void setPassword(String password) {
+            mPassword = password;
+        }
+
+        String getPassword() {
+            return mPassword;
+        }
+
         int saveToStorage() {
-            Keystore ks = Keystore.getInstance();
-            for (int i = 0, count = mItemList.size(); i < count; i++) {
-                byte[] blob = mItemList.get(i);
-                int ret = ks.put(mNamespaceList.get(i), mName, new String(blob));
-                if (ret < 0) return ret;
+            if (isPkcs12Keystore()) {
+                return CertTool.getInstance().addPkcs12Keystore(
+                        mItemList.get(0), mPassword, mName);
+            } else {
+                Keystore ks = Keystore.getInstance();
+                for (int i = 0, count = mItemList.size(); i < count; i++) {
+                    byte[] blob = mItemList.get(i);
+                    int ret = ks.put(mNamespaceList.get(i), mName,
+                            new String(blob));
+                    if (ret < 0) return ret;
+                }
             }
             return 0;
         }
diff --git a/src/com/android/settings/SoundAndDisplaySettings.java b/src/com/android/settings/SoundAndDisplaySettings.java
index 8e7411c..4417f24 100644
--- a/src/com/android/settings/SoundAndDisplaySettings.java
+++ b/src/com/android/settings/SoundAndDisplaySettings.java
@@ -55,7 +55,6 @@
     private static final String KEY_ANIMATIONS = "animations";
     private static final String KEY_ACCELEROMETER = "accelerometer";
     private static final String KEY_PLAY_MEDIA_NOTIFICATION_SOUNDS = "play_media_notification_sounds";
-    private static final String KEY_COMPATIBILITY_MODE = "compatibility_mode";
     private static final String KEY_EMERGENCY_TONE ="emergency_tone";
     
     private CheckBoxPreference mSilent;
@@ -76,7 +75,6 @@
     private CheckBoxPreference mSoundEffects;
     private CheckBoxPreference mAnimations;
     private CheckBoxPreference mAccelerometer;
-    private CheckBoxPreference mCompatibilityMode;
     private float[] mAnimationScales;
     
     private AudioManager mAudioManager;
@@ -124,10 +122,6 @@
         mAnimations.setPersistent(false);
         mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER);
         mAccelerometer.setPersistent(false);
-        mCompatibilityMode = (CheckBoxPreference) findPreference(KEY_COMPATIBILITY_MODE);
-        mCompatibilityMode.setPersistent(false);
-        mCompatibilityMode.setChecked(Settings.System.getInt(resolver,
-                Settings.System.COMPATIBILITY_MODE, 1) != 0);
         
         ListPreference screenTimeoutPreference =
             (ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
@@ -269,10 +263,6 @@
             Settings.System.putInt(getContentResolver(),
                     Settings.System.ACCELEROMETER_ROTATION,
                     mAccelerometer.isChecked() ? 1 : 0);
-        } else if (preference == mCompatibilityMode) {
-            Settings.System.putInt(getContentResolver(),
-                    Settings.System.COMPATIBILITY_MODE,
-                    mCompatibilityMode.isChecked() ? 1 : 0);
         }
         return true;
     }
diff --git a/src/com/android/settings/TextToSpeechSettings.java b/src/com/android/settings/TextToSpeechSettings.java
index 88bfc67..789368a 100644
--- a/src/com/android/settings/TextToSpeechSettings.java
+++ b/src/com/android/settings/TextToSpeechSettings.java
@@ -58,8 +58,8 @@
 
     private static final String LOCALE_DELIMITER = "-";
 
-    // TODO move this to android.speech.tts.TextToSpeech.Engine
-    private static final String FALLBACK_TTS_DEFAULT_SYNTH = "com.svox.pico";
+    private static final String FALLBACK_TTS_DEFAULT_SYNTH =
+            TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_SYNTH;
 
     private Preference         mPlayExample = null;
     private Preference         mInstallData = null;
@@ -280,6 +280,7 @@
                 Log.v(TAG, "Voice data check passed");
                 if (mTts == null) {
                     mTts = new TextToSpeech(this, this);
+                    mTts.setLanguage(Locale.getDefault());
                 }
             } else {
                 Log.v(TAG, "Voice data check failed");
@@ -319,6 +320,9 @@
             Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, mDefaultLocVariant);
             Log.v(TAG, "TTS default lang/country/variant set to "
                     + mDefaultLanguage + "/" + mDefaultCountry + "/" + mDefaultLocVariant);
+            if (mTts != null) {
+                mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry));
+            }
         }
 
         return true;
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index e78e041..737627a 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -60,12 +61,13 @@
         R.string.battery_desc_display,
         R.string.battery_desc_apps
     };
-    
+
     public static final int ACTION_DISPLAY_SETTINGS = 1;
     public static final int ACTION_WIFI_SETTINGS = 2;
     public static final int ACTION_BLUETOOTH_SETTINGS = 3;
     public static final int ACTION_WIRELESS_SETTINGS = 4;
-    public static final int ACTION_APP_DETAILS = 6;
+    public static final int ACTION_APP_DETAILS = 5;
+    public static final int ACTION_SECURITY_SETTINGS = 6;
 
     public static final int USAGE_SINCE_UNPLUGGED = 1;
     public static final int USAGE_SINCE_RESET = 2;
@@ -80,6 +82,7 @@
     public static final String EXTRA_DETAIL_VALUES = "values"; // Array of doubles
     public static final String EXTRA_DRAIN_TYPE = "drainType"; // DrainType
     public static final String EXTRA_ICON_PACKAGE = "iconPackage"; // String
+    public static final String EXTRA_NO_COVERAGE = "noCoverage";
     public static final String EXTRA_ICON_ID = "iconId"; // Int
 
     private static final boolean DEBUG = true;
@@ -90,16 +93,16 @@
     private double[] mValues;
     private TextView mTitleView;
     private ViewGroup mDetailsParent;
+    private ViewGroup mControlsParent;
     private long mStartTime;
     private DrainType mDrainType;
-    private int mAction1;
-    private int mAction2;
     private PercentageBar mGauge;
     private Drawable mAppIcon;
+    private double mNoCoverage; // Percentage of time that there was no coverage
+
+    private boolean mUsesGps;
 
     private static final String TAG = "PowerUsageDetail";
-    private Button mButton1;
-    private Button mButton2;
     private String[] mPackages;
 
     @Override
@@ -128,6 +131,7 @@
         mUsageSince = intent.getIntExtra(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
         mUid = intent.getIntExtra(EXTRA_UID, 0);
         mDrainType = (DrainType) intent.getSerializableExtra(EXTRA_DRAIN_TYPE);
+        mNoCoverage = intent.getDoubleExtra(EXTRA_NO_COVERAGE, 0);
         String iconPackage = intent.getStringExtra(EXTRA_ICON_PACKAGE);
         int iconId = intent.getIntExtra(EXTRA_ICON_ID, 0);
         if (!TextUtils.isEmpty(iconPackage)) {
@@ -167,8 +171,46 @@
 
         ImageView iconImage = (ImageView) findViewById(R.id.icon);
         iconImage.setImageDrawable(mAppIcon);
-        
+
         mDetailsParent = (ViewGroup) findViewById(R.id.details);
+        mControlsParent = (ViewGroup) findViewById(R.id.controls);
+
+        fillDetailsSection();
+        fillPackagesSection(mUid);
+        fillControlsSection(mUid);
+    }
+
+    public void onClick(View v) {
+        doAction((Integer) v.getTag());
+    }
+
+    private void doAction(int action) {
+        switch (action) {
+            case ACTION_DISPLAY_SETTINGS:
+                startActivity(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
+                break;
+            case ACTION_WIFI_SETTINGS:
+                startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
+                break;
+            case ACTION_BLUETOOTH_SETTINGS:
+                startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
+                break;
+            case ACTION_WIRELESS_SETTINGS:
+                startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
+                break;
+            case ACTION_APP_DETAILS:
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setClass(this, InstalledAppDetails.class);
+                intent.putExtra("com.android.settings.ApplicationPkgName", mPackages[0]);
+                startActivity(intent);
+                break;
+            case ACTION_SECURITY_SETTINGS:
+                startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
+                break;
+        }
+    }
+
+    private void fillDetailsSection() {
         LayoutInflater inflater = getLayoutInflater();
         if (mTypes != null && mValues != null) {
             for (int i = 0; i < mTypes.length; i++) {
@@ -181,6 +223,12 @@
                     case R.string.usage_type_data_send:
                         value = Utils.formatBytes(this, mValues[i]);
                         break;
+                    case R.string.usage_type_no_coverage:
+                        value = String.format("%d%%", (int) Math.floor(mValues[i]));
+                        break;
+                    case R.string.usage_type_gps:
+                        mUsesGps = true;
+                        // Fall through
                     default:
                         value = Utils.formatElapsedTime(this, mValues[i]);
                 }
@@ -193,41 +241,9 @@
                 valueView.setText(value);
             }
         }
-
-        fillPackagesSection(mUid);
-        fillControlsSection(mUid);
-    }
-
-    public void onClick(View v) {
-        int action = v == mButton1 ? mAction1 : mAction2;
-        doAction(action);
-    }
-
-    private void doAction(int action) {
-        switch (action) {
-            case ACTION_DISPLAY_SETTINGS:
-                startActivity(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
-                break;
-            case ACTION_WIFI_SETTINGS:
-                startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
-                break;
-            case ACTION_BLUETOOTH_SETTINGS:
-                startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
-                break;
-            case ACTION_APP_DETAILS:
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setClass(this, InstalledAppDetails.class);
-                intent.putExtra("com.android.settings.ApplicationPkgName", mPackages[0]);
-                startActivity(intent);
-                break;
-        }
     }
 
     private void fillControlsSection(int uid) {
-        String label1 = null;
-        String label2 = null;
-        mAction1 = 0;
-        mAction2 = 0;
         PackageManager pm = getPackageManager();
         String[] packages = pm.getPackagesForUid(uid);
         PackageInfo pi = null;
@@ -237,43 +253,66 @@
         ApplicationInfo ai = pi != null? pi.applicationInfo : null;
         boolean isSystem = ai != null? (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0 : false;
 
-        if (uid < 1000 || !isSystem) { 
-            switch (mDrainType) {
-                case APP:
-                    //label1 = getString(R.string.battery_action_stop);
-                    if (packages != null) {
-                        label2 = getString(R.string.battery_action_app_details);
-                        mAction2 = ACTION_APP_DETAILS;
-                    }
-                    break;
-                case SCREEN:
-                    label2 = getString(R.string.battery_action_display);
-                    mAction2 = ACTION_DISPLAY_SETTINGS;
-                    break;
-                case WIFI:
-                    label2 = getString(R.string.battery_action_wifi);
-                    mAction2 = ACTION_WIRELESS_SETTINGS;
-                    break;
-                case BLUETOOTH:
-                    //label2 = getString(R.string.battery_action_bluetooth);
-                    //mAction2 = ACTION_BLUETOOTH_SETTINGS;
-                    break;
-            }
+        boolean removeHeader = true;
+        switch (mDrainType) {
+            case APP:
+                // If it is a Java application and it's not a system application
+                if (packages != null && !isSystem) {
+                    addControl(R.string.battery_action_app_details,
+                            R.string.battery_sugg_apps_info, ACTION_APP_DETAILS);
+                    removeHeader = false;
+                    // If the application has a settings screen, jump to  that
+                    // TODO:
+                }
+                if (mUsesGps) {
+                    addControl(R.string.security_settings_title,
+                            R.string.battery_sugg_apps_gps, ACTION_SECURITY_SETTINGS);
+                    removeHeader = false;
+                }
+                break;
+            case SCREEN:
+                addControl(R.string.sound_and_display_settings,
+                        R.string.battery_sugg_display,
+                        ACTION_DISPLAY_SETTINGS);
+                removeHeader = false;
+                break;
+            case WIFI:
+                addControl(R.string.wifi_settings,
+                        R.string.battery_sugg_wifi,
+                        ACTION_WIFI_SETTINGS);
+                removeHeader = false;
+                break;
+            case BLUETOOTH:
+                addControl(R.string.bluetooth_settings,
+                        R.string.battery_sugg_bluetooth_basic,
+                        ACTION_BLUETOOTH_SETTINGS);
+                removeHeader = false;
+                break;
+            case CELL:
+                if (mNoCoverage > 10) {
+                    addControl(R.string.radio_controls_title,
+                            R.string.battery_sugg_radio,
+                            ACTION_WIRELESS_SETTINGS);
+                    removeHeader = false;
+                }
+                break;
         }
-        mButton1 = (Button) findViewById(R.id.action_button1);
-        mButton2 = (Button) findViewById(R.id.action_button2);
-        mButton1.setOnClickListener(this);
-        mButton2.setOnClickListener(this);
-        if (label1 == null) {
-            mButton1.setVisibility(View.GONE);
-        } else {
-            mButton1.setText(label1);
+        if (removeHeader) {
+            mControlsParent.setVisibility(View.GONE);
         }
-        if (label2 == null) {
-            findViewById(R.id.controls_section).setVisibility(View.GONE);
-        } else {
-            mButton2.setText(label2);
-        }
+    }
+
+    private void addControl(int title, int summary, int action) {
+        final Resources res = getResources();
+        LayoutInflater inflater = getLayoutInflater();
+        ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_action_item,null);
+        mControlsParent.addView(item);
+        Button actionButton = (Button) item.findViewById(R.id.action_button);
+        TextView summaryView = (TextView) item.findViewById(R.id.summary);
+        actionButton.setText(res.getString(title));
+        summaryView.setText(res.getString(summary));
+        actionButton.setOnClickListener(this);
+        actionButton.setTag(new Integer(action));
     }
 
     private void removePackagesSection() {
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 8df0919..3dc9914 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -80,9 +80,6 @@
 
     private double mMaxPower = 1;
     private double mTotalPower;
-
-    private boolean mScaleByMax = true;
-
     private PowerProfile mPowerProfile;
 
     private HashMap<String,UidToDetail> mUidCache = new HashMap<String,UidToDetail>();
@@ -137,15 +134,19 @@
                 Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
         intent.putExtra(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
         intent.putExtra(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
+        intent.putExtra(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent);
         if (sipper.uidObj != null) {
             intent.putExtra(PowerUsageDetail.EXTRA_UID, sipper.uidObj.getUid());
         }
         intent.putExtra(PowerUsageDetail.EXTRA_DRAIN_TYPE, sipper.drainType);
+
+        int[] types;
+        double[] values;
         switch (sipper.drainType) {
             case APP:
             {
                 Uid uid = sipper.uidObj;
-                int[] types = new int[] {
+                types = new int[] {
                     R.string.usage_type_cpu,
                     R.string.usage_type_cpu_foreground,
                     R.string.usage_type_gps,
@@ -154,7 +155,7 @@
                     R.string.usage_type_audio,
                     R.string.usage_type_video,
                 };
-                double[] values = new double[] {
+                values = new double[] {
                     sipper.cpuTime,
                     sipper.cpuFgTime,
                     sipper.gpsTime,
@@ -163,23 +164,33 @@
                     0,
                     0
                 };
-                intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
-                intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
 
             }
             break;
+            case CELL:
+            {
+                types = new int[] {
+                    R.string.usage_type_on_time,
+                    R.string.usage_type_no_coverage
+                };
+                values = new double[] {
+                    sipper.usageTime,
+                    sipper.noCoveragePercent
+                };
+            }
+            break;
             default:
             {
-                int[] types = new int[] {
+                types = new int[] {
                     R.string.usage_type_on_time
                 };
-                double[] values = new double[] {
+                values = new double[] {
                     sipper.usageTime
                 };
-                intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
-                intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
             }
         }
+        intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
+        intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
         startActivity(intent);
 
         return super.onPreferenceTreeClick(preferenceScreen, preference);
@@ -243,19 +254,19 @@
         mAppListGroup.setOrderingAsAdded(false);
 
         Collections.sort(mUsageList);
-        for (BatterySipper g : mUsageList) {
-            if (g.getSortValue() < MIN_POWER_THRESHOLD) continue;
-            double percent =  ((g.getSortValue() / mTotalPower) * 100);
-            if (percent < 1) continue;
-            PowerGaugePreference pref = new PowerGaugePreference(this, g.getIcon(), g);
-            double scaleByMax = (g.getSortValue() * 100) / mMaxPower;
-            g.percent = percent;
-            pref.setTitle(g.name);
-            pref.setPercent(percent);
-            pref.setOrder(Integer.MAX_VALUE - (int) g.getSortValue()); // Invert the order
-            pref.setGaugeValue(mScaleByMax ? scaleByMax : percent);
-            if (g.uidObj != null) {
-                pref.setKey(Integer.toString(g.uidObj.getUid()));
+        for (BatterySipper sipper : mUsageList) {
+            if (sipper.getSortValue() < MIN_POWER_THRESHOLD) continue;
+            final double percentOfTotal =  ((sipper.getSortValue() / mTotalPower) * 100);
+            if (percentOfTotal < 1) continue;
+            PowerGaugePreference pref = new PowerGaugePreference(this, sipper.getIcon(), sipper);
+            double percentOfMax = (sipper.getSortValue() * 100) / mMaxPower;
+            sipper.percent = percentOfTotal;
+            pref.setTitle(sipper.name);
+            pref.setPercent(percentOfTotal);
+            pref.setOrder(Integer.MAX_VALUE - (int) sipper.getSortValue()); // Invert the order
+            pref.setGaugeValue(percentOfMax);
+            if (sipper.uidObj != null) {
+                pref.setKey(Integer.toString(sipper.uidObj.getUid()));
             }
             mAppListGroup.addPreference(pref);
             if (mAppListGroup.getPreferenceCount() > MAX_ITEMS_TO_LIST) break;
@@ -275,7 +286,9 @@
 
     private void updateStatsPeriod(long duration) {
         String durationString = Utils.formatElapsedTime(this, duration / 1000);
-        String label = getString(R.string.battery_stats_duration, durationString);
+        String label = getString(mStats.isOnBattery()
+                ? R.string.battery_stats_duration
+                : R.string.battery_stats_last_duration, durationString);
         setTitle(label);
     }
 
@@ -415,8 +428,13 @@
                     * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
             signalTimeMs += strengthTimeMs;
         }
-        addEntry(getString(R.string.power_cell), DrainType.CELL, signalTimeMs,
+        BatterySipper bs =
+                addEntry(getString(R.string.power_cell), DrainType.CELL, signalTimeMs,
                 android.R.drawable.ic_menu_sort_by_size, power);
+        if (signalTimeMs != 0) {
+            bs.noCoveragePercent = mStats.getPhoneSignalStrengthTime(0, uSecNow, mStatsType)
+                    / 1000 * 100.0 / signalTimeMs;
+        }
     }
 
     private void addWiFiUsage(long uSecNow) {
@@ -441,6 +459,10 @@
         long btOnTimeMs = mStats.getBluetoothOnTime(uSecNow, mStatsType) / 1000;
         double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
                 / 1000;
+        int btPingCount = mStats.getBluetoothPingCount();
+        btPower += (btPingCount
+                * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD)) / 1000;
+
         addEntry(getString(R.string.power_bluetooth), DrainType.IDLE, btOnTimeMs,
                 com.android.internal.R.drawable.ic_volume_bluetooth_in_call, btPower);
     }
@@ -456,7 +478,7 @@
                 mStats.getMobileTcpBytesSent(mStatsType);
         final long wifiData = mStats.getTotalTcpBytesReceived(mStatsType) +
                 mStats.getTotalTcpBytesSent(mStatsType) - mobileData;
-        final long radioDataUptimeMs = mStats.getRadioDataUptimeMs();
+        final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
         final long mobileBps = radioDataUptimeMs != 0
                 ? mobileData * 8 * 1000 / radioDataUptimeMs
                 : MOBILE_BPS;
@@ -488,13 +510,15 @@
         addRadioUsage(uSecNow);
     }
 
-    private void addEntry(String label, DrainType drainType, long time, int iconId, double power) {
+    private BatterySipper addEntry(String label, DrainType drainType, long time, int iconId,
+            double power) {
         if (power > mMaxPower) mMaxPower = power;
         mTotalPower += power;
         BatterySipper bs = new BatterySipper(label, drainType, iconId, null, new double[] {power});
         bs.usageTime = time;
         bs.iconId = iconId;
         mUsageList.add(bs);
+        return bs;
     }
 
     private void load() {
@@ -523,6 +547,7 @@
         long gpsTime;
         long cpuFgTime;
         double percent;
+        double noCoveragePercent;
         String defaultPackageName;
 
         BatterySipper(String label, DrainType drainType, int iconId, Uid uid, double[] values) {
@@ -533,7 +558,6 @@
                 icon = getResources().getDrawable(iconId);
             }
             if (values != null) value = values[0];
-            //if (uid > 0 && (mLabel == null || mIcon == null) // TODO:
             if ((label == null || iconId == 0) && uid != null) {
                 getQuickNameIconForUid(uid);
             }
@@ -631,9 +655,9 @@
                 // Look for an official name for this UID.
                 for (String pkgName : packages) {
                     try {
-                        PackageInfo pi = pm.getPackageInfo(pkgName, 0);
+                        final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
                         if (pi.sharedUserLabel != 0) {
-                            CharSequence nm = pm.getText(pkgName,
+                            final CharSequence nm = pm.getText(pkgName,
                                     pi.sharedUserLabel, pi.applicationInfo);
                             if (nm != null) {
                                 name = nm.toString();
diff --git a/src/com/android/settings/vpn/AuthenticationActor.java b/src/com/android/settings/vpn/AuthenticationActor.java
index a05cfa7..0228934 100644
--- a/src/com/android/settings/vpn/AuthenticationActor.java
+++ b/src/com/android/settings/vpn/AuthenticationActor.java
@@ -26,6 +26,7 @@
 import android.net.vpn.VpnManager;
 import android.net.vpn.VpnProfile;
 import android.net.vpn.VpnState;
+import android.os.ConditionVariable;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.text.TextUtils;
@@ -42,7 +43,6 @@
  */
 public class AuthenticationActor implements VpnProfileActor {
     private static final String TAG = AuthenticationActor.class.getName();
-    private static final int ONE_SECOND = 1000; // ms
 
     private Context mContext;
     private VpnProfile mProfile;
@@ -175,27 +175,31 @@
 
     //@Override
     public void checkStatus() {
+        final ConditionVariable cv = new ConditionVariable();
+        cv.close();
         ServiceConnection c = new ServiceConnection() {
             public synchronized void onServiceConnected(ComponentName className,
                     IBinder service) {
+                cv.open();
                 try {
                     IVpnService.Stub.asInterface(service).checkStatus(mProfile);
                 } catch (RemoteException e) {
                     Log.e(TAG, "checkStatus()", e);
                     broadcastConnectivity(VpnState.IDLE);
                 } finally {
-                    notify();
+                    mContext.unbindService(this);
                 }
             }
 
             public void onServiceDisconnected(ComponentName className) {
-                // do nothing
+                cv.open();
+                broadcastConnectivity(VpnState.IDLE);
+                mContext.unbindService(this);
             }
         };
         if (bindService(c)) {
             // wait for a second, let status propagate
-            wait(c, ONE_SECOND);
-            mContext.unbindService(c);
+            if (!cv.block(1000)) broadcastConnectivity(VpnState.IDLE);
         }
     }
 
@@ -211,14 +215,6 @@
         mVpnManager.broadcastConnectivity(mProfile.getName(), s, errorCode);
     }
 
-    private void wait(Object o, int ms) {
-        synchronized (o) {
-            try {
-                o.wait(ms);
-            } catch (Exception e) {}
-        }
-    }
-
     private void setSavedUsername(String name) throws IOException {
         if (!name.equals(mProfile.getSavedUsername())) {
             mProfile.setSavedUsername(name);
diff --git a/src/com/android/settings/vpn/VpnEditor.java b/src/com/android/settings/vpn/VpnEditor.java
index 1d419ea..b4dc2b6 100644
--- a/src/com/android/settings/vpn/VpnEditor.java
+++ b/src/com/android/settings/vpn/VpnEditor.java
@@ -31,6 +31,7 @@
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceGroup;
 import android.text.TextUtils;
+import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -85,10 +86,9 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case MENU_SAVE:
-                if (validateAndSetResult()) {
-                    finish();
-                }
+                if (validateAndSetResult()) finish();
                 return true;
+
             case MENU_CANCEL:
                 showCancellationConfirmDialog();
                 return true;
@@ -96,6 +96,16 @@
         return super.onOptionsItemSelected(item);
     }
 
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK:
+                if (validateAndSetResult()) finish();
+                return true;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
     private void initViewFor(VpnProfile profile) {
         setTitle(profile);
         mProfileEditor.loadPreferencesTo(getPreferenceScreen());
diff --git a/src/com/android/settings/vpn/VpnProfileEditor.java b/src/com/android/settings/vpn/VpnProfileEditor.java
index a1cdc76..bf2e57d 100644
--- a/src/com/android/settings/vpn/VpnProfileEditor.java
+++ b/src/com/android/settings/vpn/VpnProfileEditor.java
@@ -25,6 +25,7 @@
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.PreferenceGroup;
+import android.text.InputType;
 import android.text.TextUtils;
 import android.text.method.PasswordTransformationMethod;
 
@@ -32,6 +33,9 @@
  * The common class for editing {@link VpnProfile}.
  */
 class VpnProfileEditor {
+    static final String SECRET_SET_INDICATOR =
+            new String(new byte[] {(byte) 1, (byte) 0});
+
     private static final String KEY_VPN_NAME = "vpn_name";
 
     private EditTextPreference mName;
@@ -95,7 +99,7 @@
      * Creates a preference for users to input domain suffices.
      */
     protected EditTextPreference createDomainSufficesPreference(Context c) {
-        mDomainSuffices = createEditTextPreference(c,
+        EditTextPreference pref = mDomainSuffices = createEditTextPreference(c,
                 R.string.vpn_dns_search_list_title,
                 R.string.vpn_dns_search_list,
                 mProfile.getDomainSuffices(),
@@ -108,11 +112,12 @@
                         return true;
                     }
                 });
-        return mDomainSuffices;
+        pref.getEditText().setInputType(InputType.TYPE_TEXT_VARIATION_URI);
+        return pref;
     }
 
     private Preference createServerNamePreference(Context c) {
-        mServerName = createEditTextPreference(c,
+        EditTextPreference pref = mServerName = createEditTextPreference(c,
                 R.string.vpn_vpn_server_title,
                 R.string.vpn_vpn_server,
                 mProfile.getServerName(),
@@ -125,7 +130,8 @@
                         return true;
                     }
                 });
-        return mServerName;
+        pref.getEditText().setInputType(InputType.TYPE_TEXT_VARIATION_URI);
+        return pref;
     }
 
     protected EditTextPreference createEditTextPreference(Context c, int titleId,
@@ -147,9 +153,10 @@
         EditTextPreference pref = new EditTextPreference(c);
         pref.setTitle(titleId);
         pref.setDialogTitle(titleId);
+        pref.getEditText().setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
         pref.getEditText().setTransformationMethod(
                 new PasswordTransformationMethod());
-        pref.setText(value);
+        pref.setText(TextUtils.isEmpty(value) ? "" : SECRET_SET_INDICATOR);
         setSecretSummary(pref, fieldNameId, value);
         pref.setPersistent(true);
         pref.setOnPreferenceChangeListener(listener);
diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java
index 1446164..f0e71f7 100644
--- a/src/com/android/settings/vpn/VpnSettings.java
+++ b/src/com/android/settings/vpn/VpnSettings.java
@@ -18,13 +18,17 @@
 
 import com.android.settings.R;
 import com.android.settings.SecuritySettings;
+import static com.android.settings.vpn.VpnProfileEditor.SECRET_SET_INDICATOR;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
+import android.content.ComponentName;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.ServiceConnection;
+import android.net.vpn.IVpnService;
 import android.net.vpn.L2tpIpsecPskProfile;
 import android.net.vpn.L2tpProfile;
 import android.net.vpn.VpnManager;
@@ -33,8 +37,10 @@
 import android.net.vpn.VpnType;
 import android.os.Bundle;
 import android.os.ConditionVariable;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceCategory;
@@ -86,8 +92,6 @@
     private static final String PROFILES_ROOT = VpnManager.PROFILES_PATH + "/";
     private static final String PROFILE_OBJ_FILE = ".pobj";
 
-    private static final String STATE_ACTIVE_ACTOR = "active_actor";
-
     private static final int REQUEST_ADD_OR_EDIT_PROFILE = 1;
     private static final int REQUEST_SELECT_VPN_TYPE = 2;
 
@@ -106,6 +110,10 @@
 
     private static final int NO_ERROR = 0;
 
+    private static final String NAMESPACE_VPN = "vpn";
+    private static final String KEY_PREFIX_IPSEC_PSK = "ipsk000";
+    private static final String KEY_PREFIX_L2TP_SECRET = "lscrt000";
+
     private PreferenceScreen mAddVpn;
     private PreferenceCategory mVpnListContainer;
 
@@ -113,8 +121,6 @@
     private Map<String, VpnPreference> mVpnPreferenceMap;
     private List<VpnProfile> mVpnProfileList;
 
-    private int mIndexOfEditedProfile = -1;
-
     // profile engaged in a connection
     private VpnProfile mActiveProfile;
 
@@ -159,28 +165,13 @@
         // listen to vpn connectivity event
         mVpnManager.registerConnectivityReceiver(mConnectivityReceiver);
 
-        String profileName = (savedInstanceState == null)
-                ? null
-                : savedInstanceState.getString(STATE_ACTIVE_ACTOR);
         retrieveVpnListFromStorage();
-        if (!TextUtils.isEmpty(profileName)) {
-            mActiveProfile = mVpnPreferenceMap.get(profileName).mProfile;
-            mConnectingActor = getActor(mActiveProfile);
-        } else {
-            checkVpnConnectionStatusInBackground();
-        }
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mStatusChecker.onPause();
+        checkVpnConnectionStatusInBackground();
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        mStatusChecker.onResume();
 
         if ((mUnlockAction != null) && isKeystoreUnlocked()) {
             Runnable action = mUnlockAction;
@@ -190,15 +181,6 @@
     }
 
     @Override
-    protected synchronized void onSaveInstanceState(Bundle outState) {
-        if (mConnectingActor == null) return;
-
-        Log.d(TAG, "   ~~~~~    save connecting actor");
-        outState.putString(STATE_ACTIVE_ACTOR,
-                mConnectingActor.getProfile().getName());
-    }
-
-    @Override
     protected void onDestroy() {
         super.onDestroy();
         unregisterForContextMenu(getListView());
@@ -278,8 +260,6 @@
                             public void onClick(DialogInterface dialog, int w) {
                                 VpnProfile p = mConnectingActor.getProfile();
                                 onIdle();
-                                mIndexOfEditedProfile =
-                                        mVpnProfileList.indexOf(p);
                                 startVpnEditor(p);
                             }
                         })
@@ -325,7 +305,6 @@
             return true;
 
         case CONTEXT_MENU_EDIT_ID:
-            mIndexOfEditedProfile = position;
             startVpnEditor(p);
             return true;
 
@@ -340,9 +319,6 @@
     @Override
     protected void onActivityResult(final int requestCode, final int resultCode,
             final Intent data) {
-        final int index = mIndexOfEditedProfile;
-        mIndexOfEditedProfile = -1;
-
         if ((resultCode == RESULT_CANCELED) || (data == null)) {
             Log.d(TAG, "no result returned by editor");
             return;
@@ -358,6 +334,7 @@
                 return;
             }
 
+            int index = getProfileIndexFromId(p.getId());
             if (checkDuplicateName(p, index)) {
                 final VpnProfile profile = p;
                 Util.showErrorMessage(this, String.format(
@@ -374,7 +351,6 @@
             if (needKeystoreToSave(p)) {
                 Runnable action = new Runnable() {
                     public void run() {
-                        mIndexOfEditedProfile = index;
                         onActivityResult(requestCode, resultCode, data);
                     }
                 };
@@ -382,7 +358,7 @@
             }
 
             try {
-                if ((index < 0) || (index >= mVpnProfileList.size())) {
+                if (index < 0) {
                     addProfile(p);
                     Util.showShortToastMessage(this, String.format(
                             getString(R.string.vpn_profile_added), p.getName()));
@@ -440,6 +416,18 @@
         }
     }
 
+    private int getProfileIndexFromId(String id) {
+        int index = 0;
+        for (VpnProfile p : mVpnProfileList) {
+            if (p.getId().equals(id)) {
+                return index;
+            } else {
+                index++;
+            }
+        }
+        return -1;
+    }
+
     // Replaces the profile at index in mVpnProfileList with p.
     // Returns true if p's name is a duplicate.
     private boolean checkDuplicateName(VpnProfile p, int index) {
@@ -517,11 +505,16 @@
         disableProfilePreferencesIfOneActive();
     }
 
+    private VpnPreference addPreferenceFor(VpnProfile p) {
+        return addPreferenceFor(p, true);
+    }
+
     // Adds a preference in mVpnListContainer
-    private void addPreferenceFor(VpnProfile p) {
+    private VpnPreference addPreferenceFor(
+            VpnProfile p, boolean addToContainer) {
         VpnPreference pref = new VpnPreference(this, p);
         mVpnPreferenceMap.put(p.getName(), pref);
-        mVpnListContainer.addPreference(pref);
+        if (addToContainer) mVpnListContainer.addPreference(pref);
 
         pref.setOnPreferenceClickListener(
                 new Preference.OnPreferenceClickListener() {
@@ -530,6 +523,7 @@
                         return true;
                     }
                 });
+        return pref;
     }
 
     // index: index to mVpnProfileList
@@ -790,12 +784,18 @@
                 return false;
             }
         });
-        for (VpnProfile p : mVpnProfileList) addPreferenceFor(p);
+        for (VpnProfile p : mVpnProfileList) {
+            Preference pref = addPreferenceFor(p, false);
+        }
         disableProfilePreferencesIfOneActive();
     }
 
     private void checkVpnConnectionStatusInBackground() {
-        mStatusChecker.check(mVpnProfileList);
+        new Thread(new Runnable() {
+            public void run() {
+                mStatusChecker.check(mVpnProfileList);
+            }
+        }).start();
     }
 
     // A sanity check. Returns true if the profile directory name and profile ID
@@ -843,37 +843,37 @@
         return mVpnManager.createVpnProfile(Enum.valueOf(VpnType.class, type));
     }
 
-    private static final String NAMESPACE_VPN = "vpn";
-    private static final String KEY_PREFIX_IPSEC_PSK = "ipsk000";
-    private static final String KEY_PREFIX_L2TP_SECRET = "lscrt000";
+    private String keyNameForDaemon(String keyName) {
+        return NAMESPACE_VPN + "_" + keyName;
+    }
 
     private void processSecrets(VpnProfile p) {
         Keystore ks = Keystore.getInstance();
         switch (p.getType()) {
             case L2TP_IPSEC_PSK:
                 L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
-                String keyName = KEY_PREFIX_IPSEC_PSK + p.getId();
-                String keyNameForDaemon = NAMESPACE_VPN + "_" + keyName;
                 String presharedKey = pskProfile.getPresharedKey();
-                if (!presharedKey.equals(keyNameForDaemon)) {
+                if (!presharedKey.equals(SECRET_SET_INDICATOR)) {
+                    String keyName = KEY_PREFIX_IPSEC_PSK + p.getId();
                     int ret = ks.put(NAMESPACE_VPN, keyName, presharedKey);
-                    if (ret < 0) Log.e(TAG, "keystore write failed: key=" + keyName);
-                    pskProfile.setPresharedKey(keyNameForDaemon);
+                    if (ret < 0) {
+                        Log.e(TAG, "keystore write failed: key=" + keyName);
+                    }
+                    pskProfile.setPresharedKey(keyNameForDaemon(keyName));
                 }
                 // pass through
 
             case L2TP:
                 L2tpProfile l2tpProfile = (L2tpProfile) p;
-                keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
+                String keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
                 if (l2tpProfile.isSecretEnabled()) {
-                    keyNameForDaemon = NAMESPACE_VPN + "_" + keyName;
                     String secret = l2tpProfile.getSecretString();
-                    if (!secret.equals(keyNameForDaemon)) {
+                    if (!secret.equals(SECRET_SET_INDICATOR)) {
                         int ret = ks.put(NAMESPACE_VPN, keyName, secret);
                         if (ret < 0) {
                             Log.e(TAG, "keystore write failed: key=" + keyName);
                         }
-                        l2tpProfile.setSecretString(keyNameForDaemon);
+                        l2tpProfile.setSecretString(keyNameForDaemon(keyName));
                     }
                 } else {
                     ks.remove(NAMESPACE_VPN, keyName);
@@ -931,49 +931,58 @@
 
     // managing status check in a background thread
     private class StatusChecker {
-        private Set<VpnProfile> mQueue = new HashSet<VpnProfile>();
-        private boolean mPaused = true;
-        private ConditionVariable mThreadCv = new ConditionVariable();
+        private List<VpnProfile> mList;
 
-        void onPause() {
-            mPaused = true;
-            mThreadCv.block(); // until the checking thread is over
-        }
+        synchronized void check(final List<VpnProfile> list) {
+            final ConditionVariable cv = new ConditionVariable();
+            cv.close();
+            mVpnManager.startVpnService();
+            ServiceConnection c = new ServiceConnection() {
+                public synchronized void onServiceConnected(
+                        ComponentName className, IBinder binder) {
+                    cv.open();
 
-        synchronized void onResume() {
-            start();
-        }
-
-        synchronized void check(List<VpnProfile> list) {
-            boolean started = !mQueue.isEmpty();
-            for (VpnProfile p : list) {
-                if (!mQueue.contains(p)) mQueue.add(p);
-            }
-            if (!started) start();
-        }
-
-        private synchronized VpnProfile next() {
-            if (mPaused || mQueue.isEmpty()) return null;
-            Iterator<VpnProfile> i = mQueue.iterator();
-            VpnProfile p = i.next();
-            i.remove();
-            return p;
-        }
-
-        private synchronized void start() {
-            if (!mPaused) return;
-            mPaused = false;
-            mThreadCv.close();
-            new Thread(new Runnable() {
-                public void run() {
-                    while (true) {
-                        VpnProfile p = next();
-                        if (p == null) break;
-                        getActor(p).checkStatus();
+                    IVpnService service = IVpnService.Stub.asInterface(binder);
+                    for (VpnProfile p : list) {
+                        try {
+                            service.checkStatus(p);
+                        } catch (Throwable e) {
+                            Log.e(TAG, " --- checkStatus(): " + p.getName(), e);
+                            changeState(p, VpnState.IDLE);
+                        }
                     }
-                    mThreadCv.open();
+                    VpnSettings.this.unbindService(this);
+                    showPreferences();
                 }
-            }).start();
+
+                public void onServiceDisconnected(ComponentName className) {
+                    cv.open();
+
+                    setDefaultState(list);
+                    VpnSettings.this.unbindService(this);
+                    showPreferences();
+                }
+            };
+            if (mVpnManager.bindVpnService(c)) {
+                if (!cv.block(1000)) {
+                    Log.d(TAG, "checkStatus() bindService failed");
+                    setDefaultState(list);
+                }
+            } else {
+                setDefaultState(list);
+            }
+        }
+
+        private void showPreferences() {
+            for (VpnProfile p : mVpnProfileList) {
+                VpnPreference pref = mVpnPreferenceMap.get(p.getName());
+                mVpnListContainer.addPreference(pref);
+            }
+        }
+
+        private void setDefaultState(List<VpnProfile> list) {
+            for (VpnProfile p : list) changeState(p, VpnState.IDLE);
+            showPreferences();
         }
     }
 }