Merge korg/donut into korg/master
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7b3e689..2092321 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -36,11 +36,14 @@
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
- <application android:label="@string/settings_label" android:icon="@drawable/ic_launcher_settings">
+ <application android:label="@string/settings_label"
+ android:icon="@drawable/ic_launcher_settings"
+ android:taskAffinity="">
<!-- Settings -->
<activity android:name="Settings" android:label="@string/settings_label"
+ android:taskAffinity="com.android.settings"
android:clearTaskOnLaunch="true"
android:launchMode="singleTop">
<intent-filter>
@@ -51,6 +54,13 @@
</intent-filter>
</activity>
+ <activity android:name="CreateShortcut" android:label="@string/settings_shortcut">
+ <intent-filter>
+ <action android:name="android.intent.action.CREATE_SHORTCUT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<!-- Wireless Controls -->
<activity android:name="WirelessSettings"
@@ -69,6 +79,7 @@
<!-- Top-level settings -->
<activity android:name=".wifi.WifiSettings" android:label="@string/wifi_settings"
+ android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -76,6 +87,7 @@
<action android:name="android.net.wifi.PICK_WIFI_NETWORK" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
@@ -85,6 +97,7 @@
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.WIFI_IP_SETTINGS" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -102,20 +115,37 @@
<activity android:name=".bluetooth.BluetoothSettings"
android:label="@string/bluetooth_settings_title"
+ android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.BLUETOOTH_SETTINGS" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="com.android.settings.SHORTCUT" />
+ <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+ <activity android:name=".vpn.VpnSettings"
+ android:launchMode="singleTask">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.net.vpn.SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.VOICE_LAUNCH" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".vpn.VpnTypeSelection"></activity>
+ <activity android:name=".vpn.VpnEditor"></activity>
+
<activity android:name="DateTimeSettings" android:label="@string/date_and_time"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.DATE_SETTINGS" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -142,12 +172,14 @@
</activity>
<activity android:name="LanguageSettings" android:label="@string/language_picker_title"
+ android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.INPUT_METHOD_SETTINGS" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
+ <category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
@@ -159,25 +191,30 @@
</intent-filter>
</activity>
- <activity android:name="UserDictionarySettings" android:icon="@drawable/app_settings"
- android:label="@string/user_dict_settings_titlebar">
+ <activity android:name="UserDictionarySettings"
+ android:label="@string/user_dict_settings_titlebar"
+ android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.USER_DICTIONARY_SETTINGS" />
<action android:name="com.android.settings.USER_DICTIONARY_INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
<activity android:name="SoundAndDisplaySettings" android:label="@string/sound_and_display_settings"
+ android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.android.settings.SOUND_SETTINGS" />
<action android:name="com.android.settings.DISPLAY_SETTINGS" />
+ <action android:name="android.settings.DISPLAY_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
@@ -211,6 +248,7 @@
<activity android:name="ManageApplications"
android:label="@string/manageapplications_settings_title"
+ android:clearTaskOnLaunch="true"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -219,6 +257,7 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
@@ -230,17 +269,22 @@
</intent-filter>
</activity>
- <activity android:name="SecuritySettings" android:label="@string/security_settings_title">
+ <activity android:name="SecuritySettings" android:label="@string/security_settings_title"
+ android:clearTaskOnLaunch="true"
+ >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.SECURITY_SETTINGS" />
<action android:name="android.settings.LOCATION_SOURCE_SETTINGS" />
+ <action android:name="android.security.ADD_CREDENTIAL" />
+ <action android:name="android.security.UNLOCK_CREDENTIAL_STORAGE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
- <activity android:name="SimLockSettings" android:label="@string/sim_lock_settings"
+ <activity android:name="IccLockSettings" android:label="@string/sim_lock_settings"
android:process="com.android.phone">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -249,8 +293,23 @@
</intent-filter>
</activity>
+ <activity android:name="AccessibilitySettings" android:label="@string/accessibility_settings_title"
+ android:theme="@android:style/Theme.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="ACCESSIBILITY_FEEDBACK_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.VOICE_LAUNCH" />
+ </intent-filter>
+ </activity>
-
+ <activity android:name="TextToSpeechSettings" android:label="@string/tts_settings">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="com.android.settings.TTS_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
<!-- Second and third-level settings -->
@@ -331,6 +390,7 @@
<action android:name="android.intent.action.MAIN" />
<action android:name="com.android.settings.QUICK_LAUNCH_SETTINGS" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -341,11 +401,12 @@
</intent-filter>
</activity>
- <activity android:name="DevelopmentSettings" android:icon="@drawable/app_settings"
+ <activity android:name="DevelopmentSettings"
android:label="@string/development_settings_title">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -442,7 +503,7 @@
</activity>
<activity android:name="ProxySelector" android:label="@string/proxy_settings_label"
- android:theme="@android:style/Theme.Dialog">
+ android:theme="@android:style/Theme.Dialog">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEVELOPMENT_PREFERENCE" />
@@ -488,7 +549,7 @@
<!-- Helper to bind any unbound widgets in Launcher, used as
part of initialization and upgrade process -->
<activity android:name="LauncherAppWidgetBinder"
- android:permission="com.android.launcher.permission.WRITE_SETTINGS"
+ android:permission="android.permission.BIND_APPWIDGET"
android:theme="@android:style/Theme.NoDisplay" android:exported="true" />
<activity android:name="UsageStats" android:label="@string/usage_stats_label">
@@ -498,7 +559,35 @@
</intent-filter>
</activity>
+ <activity android:name=".fuelgauge.PowerUsageSummary"
+ android:label="@string/power_usage_summary_title"
+ android:clearTaskOnLaunch="true"
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.intent.action.POWER_USAGE_SUMMARY" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="com.android.settings.SHORTCUT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".fuelgauge.PowerUsageDetail"
+ android:label="@string/details_title">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <receiver android:name=".widget.SettingsAppWidgetProvider" android:label="@string/gadget_title">
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
+ <action android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED" />
+ <action android:name="android.bluetooth.intent.action.BLUETOOTH_STATE_CHANGED" />
+ <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" /> <!-- pick up misc changes -->
+ </intent-filter>
+ <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" />
+ </receiver>
</application>
-
</manifest>
-
diff --git a/res/drawable-land/appwidget_bg.9.png b/res/drawable-land/appwidget_bg.9.png
new file mode 100644
index 0000000..a289712
--- /dev/null
+++ b/res/drawable-land/appwidget_bg.9.png
Binary files differ
diff --git a/res/drawable/app_gauge.9.png b/res/drawable/app_gauge.9.png
new file mode 100644
index 0000000..f6c7c99
--- /dev/null
+++ b/res/drawable/app_gauge.9.png
Binary files differ
diff --git a/res/drawable/appwidget_bg.9.png b/res/drawable/appwidget_bg.9.png
new file mode 100644
index 0000000..7ace816
--- /dev/null
+++ b/res/drawable/appwidget_bg.9.png
Binary files differ
diff --git a/res/drawable/appwidget_inner.xml b/res/drawable/appwidget_inner.xml
new file mode 100644
index 0000000..fc7bb6d
--- /dev/null
+++ b/res/drawable/appwidget_inner.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/appwidget_inner_default" />
+
+ <item android:state_pressed="true"
+ android:drawable="@drawable/appwidget_inner_pressed" />
+
+ <item android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/appwidget_inner_selected" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/appwidget_inner_default" />
+
+ <item
+ android:drawable="@drawable/appwidget_inner_default" />
+</selector>
diff --git a/res/drawable/appwidget_inner_default.9.png b/res/drawable/appwidget_inner_default.9.png
new file mode 100644
index 0000000..2c37b89
--- /dev/null
+++ b/res/drawable/appwidget_inner_default.9.png
Binary files differ
diff --git a/res/drawable/appwidget_inner_pressed.9.png b/res/drawable/appwidget_inner_pressed.9.png
new file mode 100644
index 0000000..b23c3ae
--- /dev/null
+++ b/res/drawable/appwidget_inner_pressed.9.png
Binary files differ
diff --git a/res/drawable/appwidget_inner_selected.9.png b/res/drawable/appwidget_inner_selected.9.png
new file mode 100644
index 0000000..474d717
--- /dev/null
+++ b/res/drawable/appwidget_inner_selected.9.png
Binary files differ
diff --git a/res/drawable/appwidget_outer.xml b/res/drawable/appwidget_outer.xml
new file mode 100644
index 0000000..d6f3cb6
--- /dev/null
+++ b/res/drawable/appwidget_outer.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/appwidget_outer_default" />
+
+ <item android:state_pressed="true"
+ android:drawable="@drawable/appwidget_outer_pressed" />
+
+ <item android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/appwidget_outer_selected" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/appwidget_outer_default" />
+
+ <item
+ android:drawable="@drawable/appwidget_outer_default" />
+</selector>
diff --git a/res/drawable/appwidget_outer_default.9.png b/res/drawable/appwidget_outer_default.9.png
new file mode 100644
index 0000000..d84e56a
--- /dev/null
+++ b/res/drawable/appwidget_outer_default.9.png
Binary files differ
diff --git a/res/drawable/appwidget_outer_pressed.9.png b/res/drawable/appwidget_outer_pressed.9.png
new file mode 100644
index 0000000..5348fef
--- /dev/null
+++ b/res/drawable/appwidget_outer_pressed.9.png
Binary files differ
diff --git a/res/drawable/appwidget_outer_selected.9.png b/res/drawable/appwidget_outer_selected.9.png
new file mode 100644
index 0000000..c6d5df7
--- /dev/null
+++ b/res/drawable/appwidget_outer_selected.9.png
Binary files differ
diff --git a/res/drawable/icon.png b/res/drawable/icon.png
new file mode 100755
index 0000000..16db056
--- /dev/null
+++ b/res/drawable/icon.png
Binary files differ
diff --git a/res/drawable/widget_btn_bluetooth.png b/res/drawable/widget_btn_bluetooth.png
new file mode 100644
index 0000000..f32d0b2
--- /dev/null
+++ b/res/drawable/widget_btn_bluetooth.png
Binary files differ
diff --git a/res/drawable/widget_btn_bluetooth_gray.png b/res/drawable/widget_btn_bluetooth_gray.png
new file mode 100644
index 0000000..a633554
--- /dev/null
+++ b/res/drawable/widget_btn_bluetooth_gray.png
Binary files differ
diff --git a/res/drawable/widget_btn_bluetooth_off.png b/res/drawable/widget_btn_bluetooth_off.png
new file mode 100644
index 0000000..c0ef641
--- /dev/null
+++ b/res/drawable/widget_btn_bluetooth_off.png
Binary files differ
diff --git a/res/drawable/widget_btn_brightness.png b/res/drawable/widget_btn_brightness.png
new file mode 100644
index 0000000..9a7c7b9
--- /dev/null
+++ b/res/drawable/widget_btn_brightness.png
Binary files differ
diff --git a/res/drawable/widget_btn_brightness_off.png b/res/drawable/widget_btn_brightness_off.png
new file mode 100644
index 0000000..46dc508
--- /dev/null
+++ b/res/drawable/widget_btn_brightness_off.png
Binary files differ
diff --git a/res/drawable/widget_btn_gps.png b/res/drawable/widget_btn_gps.png
new file mode 100644
index 0000000..b21e8c8
--- /dev/null
+++ b/res/drawable/widget_btn_gps.png
Binary files differ
diff --git a/res/drawable/widget_btn_gps_off.png b/res/drawable/widget_btn_gps_off.png
new file mode 100644
index 0000000..042fefb
--- /dev/null
+++ b/res/drawable/widget_btn_gps_off.png
Binary files differ
diff --git a/res/drawable/widget_btn_sync.png b/res/drawable/widget_btn_sync.png
new file mode 100644
index 0000000..6133233
--- /dev/null
+++ b/res/drawable/widget_btn_sync.png
Binary files differ
diff --git a/res/drawable/widget_btn_sync_off.png b/res/drawable/widget_btn_sync_off.png
new file mode 100644
index 0000000..192cad8
--- /dev/null
+++ b/res/drawable/widget_btn_sync_off.png
Binary files differ
diff --git a/res/drawable/widget_btn_wifi.png b/res/drawable/widget_btn_wifi.png
new file mode 100644
index 0000000..2d39681
--- /dev/null
+++ b/res/drawable/widget_btn_wifi.png
Binary files differ
diff --git a/res/drawable/widget_btn_wifi_gray.png b/res/drawable/widget_btn_wifi_gray.png
new file mode 100644
index 0000000..76f36e8
--- /dev/null
+++ b/res/drawable/widget_btn_wifi_gray.png
Binary files differ
diff --git a/res/drawable/widget_btn_wifi_off.png b/res/drawable/widget_btn_wifi_off.png
new file mode 100644
index 0000000..9b70cf1
--- /dev/null
+++ b/res/drawable/widget_btn_wifi_off.png
Binary files differ
diff --git a/res/layout-land/widget.xml b/res/layout-land/widget.xml
new file mode 100644
index 0000000..1e7fb5f
--- /dev/null
+++ b/res/layout-land/widget.xml
@@ -0,0 +1,63 @@
+<?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:id="@+id/main"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/appwidget_bg" >
+
+ <ImageButton
+ android:id="@+id/btn_wifi"
+ android:layout_width="79dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_outer"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_bluetooth"
+ android:layout_width="79dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_gps"
+ android:layout_width="79dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_sync"
+ android:layout_width="79dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_brightness"
+ android:layout_width="78dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ </LinearLayout>
diff --git a/res/layout/cstor_name_credential_dialog_view.xml b/res/layout/cstor_name_credential_dialog_view.xml
new file mode 100644
index 0000000..e5ccb36
--- /dev/null
+++ b/res/layout/cstor_name_credential_dialog_view.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="15dip">
+
+ <TextView android:id="@+id/cstor_name_credential_hint"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/vpn_connect_normal_text_size"
+ android:text="@string/cstor_name_credential_hint"
+ android:layout_marginBottom="10sp" />
+
+ <TextView android:id="@+id/cstor_error"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@color/red"
+ android:textStyle="bold" />
+
+ <TextView android:id="@+id/cstor_credential_name_title"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/cstor_credential_name" />
+ <EditText android:id="@+id/cstor_credential_name"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="True"/>
+
+ <TextView android:id="@+id/cstor_credential_info_title"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/cstor_credential_info" />
+ <TextView android:id="@+id/cstor_credential_info"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/cstor_set_password_dialog_view.xml b/res/layout/cstor_set_password_dialog_view.xml
new file mode 100644
index 0000000..eda317a
--- /dev/null
+++ b/res/layout/cstor_set_password_dialog_view.xml
@@ -0,0 +1,76 @@
+<?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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="15dip">
+
+ <TextView android:id="@+id/cstor_first_time_hint"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/vpn_connect_normal_text_size"
+ android:text="@string/cstor_first_time_hint"
+ android:layout_marginBottom="10sp" />
+
+ <TextView android:id="@+id/cstor_error"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@color/red"
+ android:textStyle="bold"
+ android:text="@string/cstor_password_empty_error" />
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/cstor_old_password_block"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+ <TextView android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/cstor_old_password" />
+ <EditText android:id="@+id/cstor_old_password"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:password="True"
+ android:singleLine="True"/>
+ </LinearLayout>
+
+ <TextView android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/cstor_new_password" />
+ <EditText android:id="@+id/cstor_new_password"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:password="True"
+ android:singleLine="True"/>
+
+ <TextView android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/cstor_confirm_password" />
+ <EditText android:id="@+id/cstor_confirm_password"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:password="True"
+ android:singleLine="True"/>
+
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/cstor_unlock_dialog_view.xml b/res/layout/cstor_unlock_dialog_view.xml
new file mode 100644
index 0000000..895306a
--- /dev/null
+++ b/res/layout/cstor_unlock_dialog_view.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="15dip">
+
+ <TextView android:id="@+id/cstor_access_dialog_hint_from_action"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/vpn_connect_normal_text_size"
+ android:text="@string/cstor_access_dialog_hint_from_action"
+ android:layout_marginBottom="10sp" />
+
+ <TextView android:id="@+id/cstor_error"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@color/red"
+ android:textStyle="bold" />
+
+ <EditText android:id="@+id/cstor_password"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:password="True"
+ android:singleLine="True"/>
+
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/installed_app_details.xml b/res/layout/installed_app_details.xml
index 7c8a672..13d3b10 100644
--- a/res/layout/installed_app_details.xml
+++ b/res/layout/installed_app_details.xml
@@ -28,9 +28,51 @@
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:orientation="vertical">
- <include
- layout="@layout/manage_applications_item"
- android:id="@+id/app_snippet"/>
+
+ <!-- App snippet -->
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_alignParentLeft="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="6dip"
+ android:paddingBottom="6dip"
+ android:paddingRight="6dip"
+ android:paddingLeft="6dip" >
+ <!-- application name -->
+ <TextView android:id="@+id/app_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:layout_marginBottom="2dip" />
+ <!-- application version -->
+ <TextView android:id="@+id/app_version"
+ android:layout_marginTop="-4dip"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+
+ <!-- application icon -->
+ <ImageView android:id="@+id/app_icon"
+ android:layout_width="@android:dimen/app_icon_size"
+ android:layout_height="@android:dimen/app_icon_size"
+ android:layout_alignParentRight="true"
+ android:paddingTop="6dip"
+ android:paddingBottom="6dip"
+ android:paddingRight="6dip"
+ android:scaleType="fitCenter" />
+ </RelativeLayout>
+
<TextView
style="?android:attr/listSeparatorTextViewStyle"
diff --git a/res/layout/power_usage_detail_item_text.xml b/res/layout/power_usage_detail_item_text.xml
new file mode 100644
index 0000000..7ea2432
--- /dev/null
+++ b/res/layout/power_usage_detail_item_text.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <!--Label for the item-->
+ <TextView
+ android:id="@+id/label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:singleLine="true"
+ android:layout_alignParentLeft="true"
+ android:layout_marginBottom="4dip"
+ android:layout_marginTop="4dip"
+ android:layout_marginLeft="4dip" />
+ <TextView
+ android:id="@+id/value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="normal"
+ android:singleLine="true"
+ android:layout_marginBottom="4dip"
+ android:layout_marginTop="4dip"
+ android:layout_marginRight="10dip"/>
+</RelativeLayout>
diff --git a/res/layout/power_usage_details.xml b/res/layout/power_usage_details.xml
new file mode 100644
index 0000000..ea7cfb3
--- /dev/null
+++ b/res/layout/power_usage_details.xml
@@ -0,0 +1,163 @@
+<?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.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <LinearLayout
+ android:id="@+id/all_details"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:paddingTop="5dip"
+ android:paddingBottom="5dip"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:paddingLeft="12dip"
+ android:paddingRight="?android:attr/scrollbarSize">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="48dip"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="6dip"
+ android:layout_gravity="center" />
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="8dip"
+ android:layout_marginTop="2dip"
+ android:layout_marginBottom="6dip"
+ android:layout_weight="1">
+
+ <TextView android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:layout_marginTop="2dip"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@+id/battery_percentage"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+ <TextView android:id="@+id/battery_percentage"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignBottom="@+id/name"
+ android:layout_gravity="bottom"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"/>
+ <ImageView
+ android:id="@+id/gauge"
+ android:background="#80404040"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_marginTop="5dip"
+ android:layout_below="@id/battery_percentage"
+ android:layout_gravity="center_vertical" />
+ <TextView android:id="@+id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/gauge"
+ android:layout_below="@id/gauge"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+ </RelativeLayout>
+ </LinearLayout>
+
+ <TextView
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:text="@string/details_subtitle" />
+
+ <LinearLayout
+ android:id="@+id/details"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="6dip"
+ android:orientation="vertical">
+
+ <!-- Insert detail items here -->
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/controls_section"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/controls_section_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>
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/packages_section_title"
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:layout_marginTop="6dip"
+ android:text="@string/packages_subtitle" />
+
+ <LinearLayout
+ android:id="@+id/packages_section"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="6dip"
+ android:orientation="vertical">
+
+ <!-- Insert detail items here -->
+
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/power_usage_package_item.xml b/res/layout/power_usage_package_item.xml
new file mode 100644
index 0000000..dcd5aad
--- /dev/null
+++ b/res/layout/power_usage_package_item.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <!--Label for the item-->
+ <TextView
+ android:id="@+id/label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:singleLine="true"
+ android:layout_alignParentLeft="true"
+ android:layout_marginBottom="2dip"
+ android:layout_marginTop="2dip" />
+</RelativeLayout>
diff --git a/res/layout/preference_powergauge.xml b/res/layout/preference_powergauge.xml
new file mode 100644
index 0000000..7aafec1
--- /dev/null
+++ b/res/layout/preference_powergauge.xml
@@ -0,0 +1,81 @@
+<?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="12dip"
+ android:id="@+android:id/widget_frame"
+ android:paddingRight="?android:attr/scrollbarSize">
+
+ <ImageView
+ android:id="@+id/appIcon"
+ android:layout_width="48dip"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="6dip"
+ android:layout_gravity="center" />
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="8dip"
+ android:layout_marginTop="2dip"
+ android:layout_marginBottom="6dip"
+ android:layout_weight="1">
+
+ <TextView android:id="@+android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:layout_marginTop="2dip"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@+id/percent"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+ <TextView android:id="@+id/percent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignBottom="@android:id/title"
+ android:layout_gravity="bottom"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"/>
+
+ <ImageView
+ android:id="@+id/appGauge"
+ android:background="#80404040"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_marginTop="5dip"
+ android:layout_below="@id/percent"
+ android:layout_gravity="center_vertical" />
+
+ <TextView android:id="@+android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/appGauge"
+ android:layout_below="@id/appGauge"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:maxLines="2" />
+
+ </RelativeLayout>
+
+</LinearLayout>
diff --git a/res/layout/vpn_connect_dialog_view.xml b/res/layout/vpn_connect_dialog_view.xml
new file mode 100644
index 0000000..062f881
--- /dev/null
+++ b/res/layout/vpn_connect_dialog_view.xml
@@ -0,0 +1,69 @@
+<?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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dip">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/username_str"
+ android:layout_width="@dimen/vpn_connect_input_box_label_width"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/vpn_connect_normal_text_size"
+ android:gravity="right"
+ android:layout_marginRight="@dimen/vpn_connect_margin_right"
+ android:text="@string/vpn_username_colon" />
+ <EditText android:id="@+id/username_value"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="True"/>
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/password_str"
+ android:layout_width="@dimen/vpn_connect_input_box_label_width"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/vpn_connect_normal_text_size"
+ android:gravity="right"
+ android:layout_marginRight="@dimen/vpn_connect_margin_right"
+ android:text="@string/vpn_password_colon" />
+ <EditText android:id="@+id/password_value"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:password="True"
+ android:singleLine="True"/>
+ </LinearLayout>
+
+ <CheckBox android:id="@+id/save_username"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="66dip"
+ android:text="@string/vpn_save_username" />
+
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/widget.xml b/res/layout/widget.xml
new file mode 100644
index 0000000..3a223b6
--- /dev/null
+++ b/res/layout/widget.xml
@@ -0,0 +1,63 @@
+<?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:id="@+id/main"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/appwidget_bg" >
+
+ <ImageButton
+ android:id="@+id/btn_wifi"
+ android:layout_width="57dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_outer"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_bluetooth"
+ android:layout_width="57dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_gps"
+ android:layout_width="57dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_sync"
+ android:layout_width="57dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ <ImageButton
+ android:id="@+id/btn_brightness"
+ android:layout_width="58dip"
+ android:layout_height="fill_parent"
+ android:background="@drawable/appwidget_inner"
+ android:layout_gravity="center_horizontal"
+ />
+
+ </LinearLayout>
diff --git a/res/layout/wifi_ap_configure.xml b/res/layout/wifi_ap_configure.xml
index d786cff..f8eb39a 100644
--- a/res/layout/wifi_ap_configure.xml
+++ b/res/layout/wifi_ap_configure.xml
@@ -24,11 +24,17 @@
android:padding="8dip"
android:orientation="vertical">
-
+ <LinearLayout
+ android:id="@+id/table"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+ </LinearLayout>
+
<!-- SSID -->
- <TextView
+ <TextView android:id="@+id/ssid_text"
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -44,7 +50,7 @@
<!-- Security -->
- <TextView
+ <TextView android:id="@+id/security_text"
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -55,9 +61,85 @@
<Spinner android:id="@+id/security_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
-
-
-
+
+ <!-- Enterprise Fields -->
+ <LinearLayout android:id="@+id/enterprise_wrapper"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="0dip"
+ android:orientation="vertical">
+ <TextView android:id="@+id/eap_text"
+ style="?android:attr/textAppearanceSmallInverse"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:text="@string/please_select_eap" />
+ <Spinner android:id="@+id/eap_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/phase2_text"
+ style="?android:attr/textAppearanceSmallInverse"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:text="@string/please_select_phase2" />
+ <Spinner android:id="@+id/phase2_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ <TextView android:id="@+id/ca_certificate_text"
+ style="?android:attr/textAppearanceSmallInverse"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:text="@string/please_select_ca_certificate" />
+ <Spinner android:id="@+id/ca_certificate_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/client_certificate_text"
+ style="?android:attr/textAppearanceSmallInverse"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:text="@string/please_select_client_certificate" />
+ <Spinner android:id="@+id/client_certificate_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/private_key_passwd_text"
+ style="?android:attr/textAppearanceSmallInverse"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:text="@string/please_type_private_key_passwd" />
+ <EditText android:id="@+id/private_key_passwd_edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dip"
+ android:singleLine="true" />
+ <TextView android:id="@+id/identity_text"
+ style="?android:attr/textAppearanceSmallInverse"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:text="@string/please_type_identity" />
+ <EditText android:id="@+id/identity_edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dip"
+ android:singleLine="true" />
+ <TextView android:id="@+id/anonymous_identity_text"
+ style="?android:attr/textAppearanceSmallInverse"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:text="@string/please_type_anonymous_identity" />
+ <EditText android:id="@+id/anonymous_identity_edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dip"
+ android:singleLine="true" />
+ </LinearLayout>
+
<!-- Password -->
<TextView android:id="@+id/password_text"
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 943dc50..5507d59 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -107,10 +107,6 @@
<string name="date_and_time">"Nastavení data a času"</string>
<string name="date_time_12_hour_sample">"13:00"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
- <skip />
- <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
- <skip />
<string name="choose_timezone">"Volba časového pásma"</string>
<string name="display_preview_label">"Náhled:"</string>
<string name="display_font_size_label">"Velikost písma:"</string>
@@ -491,13 +487,9 @@
<string name="location_network_based">"Zaměření přes bezdrátové sítě"</string>
<string name="location_networks_disabled">"Zobrazuje polohu v aplikacích (jako Mapy) pomocí bezdrátových sítí"</string>
<string name="location_neighborhood_level">"Poloha je zaměřena pomocí WiFi nebo mobilních sítí"</string>
- <string name="location_gps">"Zapnout GPS"</string>
+ <string name="location_gps">"Zapnout přijímač systému GPS"</string>
<string name="location_street_level">"Zaměření je s přesností na úrovni ulic (zrušením této volby lze šetřit baterii)"</string>
<string name="location_gps_disabled">"Umožňuje zaměřit na úrovni ulic (vetší spotřeba baterie a nutný výhled na oblohu)"</string>
- <string name="location_warning_title">"Svolení se sběrem dat o poloze"</string>
- <string name="location_warning_message">"Povolit službě určování polohy společnosti Google sběr anonymních a sdružených dat o poloze. Data budou sbírána bez ohledu na to, zda je nějaká aplikace aktivní."</string>
- <string name="agree">"Souhlasím"</string>
- <string name="disagree">"Nesouhlasím"</string>
<string name="about_settings">"Info o telefonu"</string>
<string name="about_settings_summary">"Zobrazuje právní informace, stav telefonu a verzi softwaru"</string>
<string name="legal_information">"Právní informace"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index df63656..a936059 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -16,12 +16,12 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="device_info_default">"Unbekannt"</string>
- <string name="turn_on_radio">"Mobilfunkverbindung aktivieren"</string>
- <string name="turn_off_radio">"Mobilfunkverbindung deaktivieren"</string>
+ <string name="turn_on_radio">"Radio einschalten"</string>
+ <string name="turn_off_radio">"Radio ausschalten"</string>
<string name="turn_on_qxdm">"QXDM-SD-Protokoll aktivieren"</string>
<string name="turn_off_qxdm">"QXDM-SD-Protokoll deaktivieren"</string>
<string name="radioInfo_menu_viewADN">"SIM-Adressbuch anzeigen"</string>
- <string name="radioInfo_menu_viewFDN">"Begrenzte Rufnummern anzeigen"</string>
+ <string name="radioInfo_menu_viewFDN">"Feste Rufnummern anzeigen"</string>
<string name="radioInfo_menu_viewSDN">"Servicerufnummern anzeigen"</string>
<string name="radioInfo_menu_getPDP">"PDP-Liste abrufen"</string>
<string name="radioInfo_menu_enableData">"Datenverbindung aktivieren"</string>
@@ -31,7 +31,7 @@
<string name="radioInfo_service_in">"In Betrieb"</string>
<string name="radioInfo_service_out">"Außer Betrieb"</string>
<string name="radioInfo_service_emergency">"Nur Notrufe"</string>
- <string name="radioInfo_service_off">"Mobilfunkverbindung aus"</string>
+ <string name="radioInfo_service_off">"Radio aus"</string>
<string name="radioInfo_roaming_in">"Roaming"</string>
<string name="radioInfo_roaming_not">"Kein Roaming"</string>
<string name="radioInfo_phone_idle">"Inaktiv"</string>
@@ -82,7 +82,7 @@
<string name="battery_info_health_over_voltage">"Überspannung"</string>
<string name="battery_info_health_unspecified_failure">"Unbekannter Fehler"</string>
<string name="bluetooth">"Bluetooth"</string>
- <string name="bluetooth_visibility">"Sichtbar"</string>
+ <string name="bluetooth_visibility">"Erkennbar"</string>
<string name="bluetooth_is_discoverable">"Für <xliff:g id="DISCOVERABLE_TIME_PERIOD">%1$s</xliff:g> Sekunden sichtbar..."</string>
<string name="bluetooth_not_discoverable">"Geräteerkennung deaktivieren"</string>
<string name="bluetooth_devices">"Bluetooth-Geräte"</string>
@@ -107,8 +107,6 @@
<string name="date_and_time">"Einstellungen"</string>
<string name="date_time_12_hour_sample">"1:00"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <string name="date_time_changeTime_text">"Zeit einstellen"</string>
- <string name="date_time_changeDate_text">"Datum"</string>
<string name="choose_timezone">"Zeitzone auswählen"</string>
<string name="display_preview_label">"Vorschau:"</string>
<string name="display_font_size_label">"Schriftgröße:"</string>
@@ -146,7 +144,7 @@
<string name="radio_info_signal_strength_label">"Signalstärke:"</string>
<string name="radio_info_call_status_label">"Rufstatus:"</string>
<string name="radio_info_ppp_sent_label">"PPP gesendet:"</string>
- <string name="radio_info_radio_resets_label">"Verbindungszurücksetzung"</string>
+ <string name="radio_info_radio_resets_label">"Radiozurücksetzung:"</string>
<string name="radio_info_message_waiting_label">"Nachricht liegt vor:"</string>
<string name="radio_info_phone_number_label">"Telefonnummer:"</string>
<string name="radio_info_band_mode_label">"Frequenzbereich auswählen"</string>
@@ -246,7 +244,7 @@
<string name="bluetooth_headset_profile_summary_use_for">"Für Audiosystem des Telefons verwenden"</string>
<string name="wifi">"WLAN"</string>
<string name="wifi_quick_toggle_title">"WLAN"</string>
- <string name="wifi_quick_toggle_summary">"WLAN aktivieren"</string>
+ <string name="wifi_quick_toggle_summary">"Wi-Fi aktivieren"</string>
<string name="wifi_settings">"WLAN-Einstellungen"</string>
<string name="wifi_settings_category">"WLAN-Einstellungen"</string>
<string name="wifi_settings_summary">"Wireless-Zugangspunkte festlegen und verwalten"</string>
@@ -291,7 +289,7 @@
<string name="wifi_security">"Sicherheit"</string>
<string name="wifi_save_config">"Speichern"</string>
<string name="wifi_password_unchanged">"(nicht geändert)"</string>
- <string name="wifi_add_other_network">"WLAN-Netzwerk hinzufügen"</string>
+ <string name="wifi_add_other_network">"Wi-Fi-Netzwerk hinzufügen"</string>
<string name="wifi_notify_open_networks">"Netzwerkhinweis"</string>
<string name="wifi_notify_open_networks_summary">"Benachrichtigen, wenn ein offenes Netzwerk verfügbar ist"</string>
<string name="wifi_password_incorrect_error">"Das eingegebene Netzwerkpasswort ist falsch. Bitte versuchen Sie es erneut."</string>
@@ -315,8 +313,8 @@
<string name="wifi_setting_num_channels_summary">"Anzahl an zu verwendenden Kanälen festlegen"</string>
<string name="wifi_setting_num_channels_error">"Beim Einrichten der Domain ist ein Problem aufgetreten."</string>
<string name="wifi_setting_num_channels_channel_phrase">"<xliff:g id="NUM_CHANNELS">%1$d</xliff:g> Kanäle"</string>
- <string name="wifi_setting_sleep_policy_title">"WLAN Standby-Richtlinie"</string>
- <string name="wifi_setting_sleep_policy_summary">"Festlegen, wann von WLAN auf mobile Daten umgeschaltet werden soll"</string>
+ <string name="wifi_setting_sleep_policy_title">"Wi-Fi Standby-Richtlinie"</string>
+ <string name="wifi_setting_sleep_policy_summary">"Festlegen, wann von Wi-Fi auf mobile Daten umgeschaltet werden soll"</string>
<string name="wifi_setting_sleep_policy_error">"Beim Einrichten der Standby-Richtlinie ist ein Problem aufgetreten."</string>
<string name="wifi_advanced_mac_address_title">"MAC-Adresse"</string>
<string name="fragment_status_scanning">"Scannen…"</string>
@@ -335,7 +333,7 @@
<string name="status_disconnecting">"Verbindung wird getrennt..."</string>
<string name="status_disconnected">"Nicht verbunden"</string>
<string name="status_failed">"Fehlgeschlagen"</string>
- <string name="sound_and_display_settings">"Sound und Display"</string>
+ <string name="sound_and_display_settings">"Töne und Display"</string>
<string name="sound_settings">"Toneinstellungen"</string>
<string name="sound_and_display_settings_summary">"Klingeltöne, Benachrichtigungen und Helligkeit festlegen"</string>
<string name="silent_mode_title">"Lautlosmodus"</string>
@@ -403,7 +401,7 @@
<string name="system_update_settings_list_item_summary">"Nach Systemaktualisierungen suchen"</string>
<string name="firmware_version">"Firmware-Version"</string>
<string name="model_number">"Modellnummer"</string>
- <string name="baseband_version">"Baseband-Version"</string>
+ <string name="baseband_version">"Basisband-Version"</string>
<string name="kernel_version">"Kernel-Version"</string>
<string name="build_number">"Build-Nummer"</string>
<string name="device_info_not_available">"Nicht verfügbar"</string>
@@ -414,7 +412,7 @@
<string name="storage_settings_summary">"SD-Karte entnehmen, verfügbaren Speicher anzeigen"</string>
<string name="status_number">"Telefonnummer"</string>
<string name="status_network_type">"Mobiler Netzwerktyp"</string>
- <string name="status_data_state">"Mobiler Netzwerkstatus"</string>
+ <string name="status_data_state">"Status des mobilen Netzwerks"</string>
<string name="status_service_state">"Servicestatus"</string>
<string name="status_signal_strength">"Signalstärke"</string>
<string name="status_roaming">"Roaming"</string>
@@ -482,7 +480,7 @@
<string name="media_format_gesture_prompt">"Bitte zeichnen Sie Ihr Entsperrungsmuster."</string>
<string name="media_format_gesture_explanation">"Sie müssen Ihr Entsperrungsmuster eingeben, um eine SD-Karten-Formatierung zu bestätigen."</string>
<string name="call_settings_title">"Anrufeinstellungen"</string>
- <string name="call_settings_summary">"Mailbox, Rufweiterleitung, Anklopfen, Anruferkennung einrichten"</string>
+ <string name="call_settings_summary">"Mailbox, Anrufweiterleitung, Anklopfen, Anruferkennung einrichten"</string>
<string name="network_settings_title">"Mobile Netzwerke"</string>
<string name="network_settings_summary">"Optionen für Roaming, Netzwerke, APNs festlegen"</string>
<string name="location_title">"Standortquellen"</string>
@@ -492,10 +490,6 @@
<string name="location_gps">"GPS-Satelliten aktivieren"</string>
<string name="location_street_level">"Auf Straßenebene lokalisieren (deaktivieren, um Akku zu sparen)"</string>
<string name="location_gps_disabled">"Auf Straßenebene lokalisieren (höherer Akkuverbrauch, im Freien)"</string>
- <string name="location_warning_title">"Standortgenehmigung"</string>
- <string name="location_warning_message">"Erlauben Sie dem Google-Standortservice, anonyme und aggregierte Standortdaten zu erfassen. Die Erfassung wird unabhängig davon durchgeführt, ob Anwendungen aktiv sind oder nicht."</string>
- <string name="agree">"Zustimmen"</string>
- <string name="disagree">"Ablehnen"</string>
<string name="about_settings">"Telefoninfo"</string>
<string name="about_settings_summary">"Rechtliche Hinweise, Telefonstatus und Softwareversion anzeigen"</string>
<string name="legal_information">"Rechtliche Hinweise"</string>
diff --git a/res/values-es-rUS-nokeys/strings.xml b/res/values-es-rUS-nokeys/strings.xml
new file mode 100644
index 0000000..0a6a749
--- /dev/null
+++ b/res/values-es-rUS-nokeys/strings.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="applications_settings_summary">"Administrar aplicaciones"</string>
+</resources>
diff --git a/res/values-es-rUS/arrays.xml b/res/values-es-rUS/arrays.xml
new file mode 100644
index 0000000..b368143
--- /dev/null
+++ b/res/values-es-rUS/arrays.xml
@@ -0,0 +1,76 @@
+<?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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="timezone_filters">
+ <item>"América"</item>
+ <item>"Europa"</item>
+ <item>"África"</item>
+ <item>"Asia"</item>
+ <item>"Australia"</item>
+ <item>"Pacífico"</item>
+ <item>"Todos"</item>
+ </string-array>
+ <string-array name="screen_timeout_entries">
+ <item>"15 segundos"</item>
+ <item>"30 segundos"</item>
+ <item>"1 minuto"</item>
+ <item>"2 minutos"</item>
+ <item>"10 minutos"</item>
+ <item>"Nunca se debe agotar el tiempo de espera"</item>
+ </string-array>
+ <string-array name="wifi_security_entries">
+ <item>"Automáticamente"</item>
+ <item>"Ninguno"</item>
+ <item>"WEP"</item>
+ <item>"WPA Personal"</item>
+ <item>"WPA2 Personal"</item>
+ </string-array>
+ <string-array name="wifi_security_without_auto_entries">
+ <item>"Ninguno"</item>
+ <item>"WEP"</item>
+ <item>"WPA Personal"</item>
+ <item>"WPA2 Personal"</item>
+ </string-array>
+ <string-array name="wifi_wep_type">
+ <item>"Automáticamente"</item>
+ <item>"WEP ASCII"</item>
+ <item>"WEP hexadecimal"</item>
+ </string-array>
+ <string-array name="wifi_sleep_policy_entries">
+ <item>"Cuando se apaga la pantalla"</item>
+ <item>"Nunca cuando está conectado"</item>
+ <item>"Nunca"</item>
+ </string-array>
+ <string-array name="battery_history_type_spinner">
+ <item>"Uso de CPU"</item>
+ <item>"Uso de red"</item>
+ <item>"Uso de GPS"</item>
+ <item>"Uso del sensor"</item>
+ <item>"Uso de despertador parcial"</item>
+ <item>"Otro uso"</item>
+ </string-array>
+ <string-array name="battery_history_which_spinner">
+ <item>"Desde la última vez que se desconectó"</item>
+ <item>"Total desde el reinicio"</item>
+ <item>"Total en todo el tiempo"</item>
+ </string-array>
+ <string-array name="usage_stats_display_order_types">
+ <item>"Hora de uso"</item>
+ <item>"Lanzar recuento"</item>
+ <item>"Nombre de la aplicación"</item>
+ </string-array>
+</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..9aa86af
--- /dev/null
+++ b/res/values-es-rUS/strings.xml
@@ -0,0 +1,701 @@
+<?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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="device_info_default">"Desconocido"</string>
+ <string name="turn_on_radio">"Encender la radio"</string>
+ <string name="turn_off_radio">"Apagar la radio"</string>
+ <string name="turn_on_qxdm">"Activar el registro SD de QXDM"</string>
+ <string name="turn_off_qxdm">"Desactivar el registro SD de QXDM"</string>
+ <string name="radioInfo_menu_viewADN">"Ver libreta de direcciones de SIM"</string>
+ <string name="radioInfo_menu_viewFDN">"Ver números fijos"</string>
+ <string name="radioInfo_menu_viewSDN">"Ver números del servicio técnico"</string>
+ <string name="radioInfo_menu_getPDP">"Obtener lista PDP"</string>
+ <string name="radioInfo_menu_enableData">"Activar la conexión de datos"</string>
+ <string name="radioInfo_menu_disableData">"Desactivar conexión de datos"</string>
+ <string name="radioInfo_menu_enableDataOnBoot">"Activar datos durante el reinicio"</string>
+ <string name="radioInfo_menu_disableDataOnBoot">"Desactivar datos durante el reinicio"</string>
+ <string name="radioInfo_service_in">"En servicio"</string>
+ <string name="radioInfo_service_out">"Fuera de servicio"</string>
+ <string name="radioInfo_service_emergency">"Sólo llamadas de emergencia"</string>
+ <string name="radioInfo_service_off">"Radio apagada"</string>
+ <string name="radioInfo_roaming_in">"Roaming"</string>
+ <string name="radioInfo_roaming_not">"No hay roaming"</string>
+ <string name="radioInfo_phone_idle">"Inactivo"</string>
+ <string name="radioInfo_phone_ringing">"Timbrando"</string>
+ <string name="radioInfo_phone_offhook">"Llamada en curso"</string>
+ <string name="radioInfo_data_disconnected">"Desconectado"</string>
+ <string name="radioInfo_data_connecting">"Conectando"</string>
+ <string name="radioInfo_data_connected">"Conectado"</string>
+ <string name="radioInfo_data_suspended">"Suspendido"</string>
+ <string name="radioInfo_unknown">"desconocida"</string>
+ <string name="radioInfo_display_packets">"paquetes"</string>
+ <string name="radioInfo_display_bytes">"bytes"</string>
+ <string name="radioInfo_display_dbm">"dBm"</string>
+ <string name="radioInfo_display_asu">"asu"</string>
+ <string name="radioInfo_lac">"LAC"</string>
+ <string name="radioInfo_cid">"CID"</string>
+ <string name="sdcard_unmount">"Desmontar la tarjeta SD"</string>
+ <string name="sdcard_format">"Formatear tarjeta SD"</string>
+ <string name="small_font">"Pequeño"</string>
+ <string name="medium_font">"Mediano"</string>
+ <string name="large_font">"Grande"</string>
+ <string name="font_size_save">"Aceptar"</string>
+ <string name="sdcard_setting">"Tarjeta SD"</string>
+ <string name="battery_info_status_label">"Estado de batería:"</string>
+ <string name="battery_info_scale_label">"Escala de batería:"</string>
+ <string name="battery_info_level_label">"Nivel de la batería:"</string>
+ <string name="battery_info_health_label">"Estado de la batería:"</string>
+ <string name="battery_info_technology_label">"Tecnología de la batería:"</string>
+ <string name="battery_info_voltage_label">"Voltaje de la batería:"</string>
+ <string name="battery_info_voltage_units">"mV"</string>
+ <string name="battery_info_temperature_label">"Temperatura de la batería:"</string>
+ <string name="battery_info_temperature_units">"° C"</string>
+ <string name="battery_info_uptime">"Tiempo desde el reinicio:"</string>
+ <string name="battery_info_awake_battery">"Hora de actividad en la batería:"</string>
+ <string name="battery_info_awake_plugged">"Hora de actividad durante la carga:"</string>
+ <string name="battery_info_screen_on">"Hora de Encendido de la pantalla:"</string>
+ <string name="battery_info_status_unknown">"Desconocido"</string>
+ <string name="battery_info_status_charging">"Cargando"</string>
+ <string name="battery_info_status_charging_ac">"(AC)"</string>
+ <string name="battery_info_status_charging_usb">"(USB)"</string>
+ <string name="battery_info_status_discharging">"Descargando"</string>
+ <string name="battery_info_status_not_charging">"No se realiza la carga"</string>
+ <string name="battery_info_status_full">"Total"</string>
+ <string name="battery_info_health_unknown">"Desconocido"</string>
+ <string name="battery_info_health_good">"Bueno"</string>
+ <string name="battery_info_health_overheat">"Recalentar"</string>
+ <string name="battery_info_health_dead">"Muerto"</string>
+ <string name="battery_info_health_over_voltage">"Voltaje excesivo"</string>
+ <string name="battery_info_health_unspecified_failure">"Error desconocido"</string>
+ <string name="bluetooth">"Bluetooth"</string>
+ <string name="bluetooth_visibility">"Visible"</string>
+ <string name="bluetooth_is_discoverable">"Visible durante <xliff:g id="DISCOVERABLE_TIME_PERIOD">%1$s</xliff:g> segundos…"</string>
+ <string name="bluetooth_not_discoverable">"Hacer que el dispositivo sea visible"</string>
+ <string name="bluetooth_devices">"Dispositivos de Bluetooth"</string>
+ <string name="bluetooth_device_name">"Nombre del dispositivo"</string>
+ <string name="bluetooth_name_not_set">"No hay nombre establecido, se utiliza el nombre de cuenta"</string>
+ <string name="bluetooth_scan_for_devices">"Explorar dispositivos"</string>
+ <string name="bluetooth_disconnect_blank">"Se desconectará <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_connected">"Conectado"</string>
+ <string name="bluetooth_disconnected">"Desconectado"</string>
+ <string name="bluetooth_disconnecting">"Desconectando…"</string>
+ <string name="bluetooth_connecting">"Conectando…"</string>
+ <!-- no translation found for bluetooth_unknown (644716244548801421) -->
+ <skip />
+ <string name="bluetooth_not_connected">"Vincular con este dispositivo"</string>
+ <string name="bluetooth_pairing">"Vinculando..."</string>
+ <string name="bluetooth_paired">"Vinculado pero no conectado"</string>
+ <string name="bluetooth_device">"manos libres/auriculares"</string>
+ <string name="progress_scanning">"Explorando"</string>
+ <string name="bluetooth_notif_ticker">"Solicitud de vinculación de Bluetooth"</string>
+ <string name="bluetooth_notif_title">"Vinculando solicitud"</string>
+ <string name="bluetooth_notif_message">"Seleccionar para vincularse con "</string>
+ <string name="date_and_time">"Configuración de fecha y hora"</string>
+ <string name="date_time_12_hour_sample">"1:00 p.m."</string>
+ <string name="date_time_24_hour_sample">"13:00"</string>
+ <string name="choose_timezone">"Seleccionar zona horaria"</string>
+ <string name="display_preview_label">"Vista previa:"</string>
+ <string name="display_font_size_label">"Tamaño de fuente:"</string>
+ <!-- no translation found for intent_sender_data_label (6332324780477289261) -->
+ <skip />
+ <string name="intent_sender_sendbroadcast_text">"Enviar <xliff:g id="BROADCAST">broadcast</xliff:g>"</string>
+ <string name="intent_sender_action_label">"<xliff:g id="ACTION">Action</xliff:g>:"</string>
+ <string name="intent_sender_startactivity_text">"Inicio <xliff:g id="ACTIVITY">activity</xliff:g>"</string>
+ <string name="intent_sender_resource_label">"<xliff:g id="RESOURCE">Resource</xliff:g>:"</string>
+ <string name="intent_sender_account_label">"Cuenta:"</string>
+ <string name="proxy_clear_text">"Borrar"</string>
+ <string name="proxy_port_label">"Puerto"</string>
+ <string name="proxy_defaultView_text">"Restaurar configuraciones predeterminadas"</string>
+ <string name="proxy_action_text">"Guardar"</string>
+ <string name="proxy_hostname_label">"Nombre del servidor"</string>
+ <string name="proxy_error">"Atención"</string>
+ <string name="proxy_error_dismiss">"Aceptar"</string>
+ <string name="proxy_error_invalid_host">"El nombre del servidor que has escrito no es válido."</string>
+ <string name="proxy_error_empty_port">"Debes completar el campo de puerto."</string>
+ <string name="proxy_error_empty_host_set_port">"El campo del puerto debe estar vacío si el campo de servidor está vacío."</string>
+ <string name="proxy_error_invalid_port">"El puerto que has escrito no es válido."</string>
+ <string name="radio_info_signal_location_label">"Ubicación:"</string>
+ <string name="radio_info_neighboring_location_label">"CID cercano:"</string>
+ <string name="radio_info_data_attempts_label">"Intentos de datos:"</string>
+ <string name="radio_info_gprs_service_label">"Servicio GPRS:"</string>
+ <string name="radio_info_roaming_label">"Roaming:"</string>
+ <string name="radio_info_imei_label">"IMEI:"</string>
+ <string name="radio_info_call_redirect_label">"Redireccionamiento de llamada:"</string>
+ <string name="radio_info_ppp_resets_label">"Cantidad de PPP restablecidos desde el reinicio:"</string>
+ <string name="radio_info_gsm_disconnects_label">"Desconexiones de GSM:"</string>
+ <string name="radio_info_current_network_label">"Red actual:"</string>
+ <string name="radio_info_data_successes_label">"Datos correctos:"</string>
+ <string name="radio_info_ppp_received_label">"PPP recibido:"</string>
+ <string name="radio_info_gsm_service_label">"Servicio GSM:"</string>
+ <string name="radio_info_signal_strength_label">"Potencia de la señal:"</string>
+ <string name="radio_info_call_status_label">"Estado de llamada:"</string>
+ <string name="radio_info_ppp_sent_label">"PPP enviado:"</string>
+ <string name="radio_info_radio_resets_label">"Restablecimiento de la radio:"</string>
+ <string name="radio_info_message_waiting_label">"Mensaje en espera:"</string>
+ <string name="radio_info_phone_number_label">"Número de teléfono"</string>
+ <string name="radio_info_band_mode_label">"Seleccionar banda de radio"</string>
+ <string name="radio_info_network_type_label">"Tipo de red:"</string>
+ <string name="radio_info_set_perferred_label">"Establecer el tipo de red preferida:"</string>
+ <string name="radio_info_ping_ipaddr">"Buscar direcciones de Internet de IpAddr:"</string>
+ <string name="radio_info_ping_hostname">"Buscar direcciones de Internet del nombre del servidor (www.google.com):"</string>
+ <string name="radio_info_http_client_test">"Prueba de cliente HTTP:"</string>
+ <string name="radio_info_toggle_ciph_label">"Cambiar el cifrado"</string>
+ <string name="ping_test_label">"Ejecutar la prueba de búsqueda de direcciones de Internet"</string>
+ <string name="radio_info_smsc_label">"SMSC:"</string>
+ <string name="radio_info_smsc_update_label">"Actualizar"</string>
+ <string name="radio_info_smsc_refresh_label">"Actualizar"</string>
+ <string name="radio_info_toggle_dns_check_label">"Cambiar la verificación de DNS"</string>
+ <string name="band_mode_title">"Establecer banda GSM y UMTS"</string>
+ <string name="band_mode_loading">"Cargando lista de banda..."</string>
+ <string name="band_mode_set">"Establecer"</string>
+ <string name="band_mode_failed">"Incorrecto"</string>
+ <string name="band_mode_succeeded">"Correcto"</string>
+ <string name="sdcard_changes_instructions">"Los cambios se aplican cuando se vuelve a conectar el cable USB"</string>
+ <string name="sdcard_settings_screen_mass_storage_text">"Activar el espacio de almacenamiento masivo USB"</string>
+ <string name="sdcard_settings_total_bytes_label">"Total de bytes:"</string>
+ <string name="sdcard_settings_not_present_status">"No hay tarjeta SD"</string>
+ <string name="sdcard_settings_available_bytes_label">"Bytes disponibles:"</string>
+ <string name="sdcard_settings_mass_storage_status">"La tarjeta SD se utiliza como dispositivo de almacenamiento masivo"</string>
+ <string name="sdcard_settings_unmounted_status">"Ahora es seguro extraer la tarjeta SD"</string>
+ <string name="sdcard_settings_bad_removal_status">"¡Se ha extraído la tarjeta SD mientras se encontraba en uso!"</string>
+ <string name="sdcard_settings_used_bytes_label">"Bytes utilizados:"</string>
+ <string name="sdcard_settings_scanning_status">"Explorando medios en la tarjeta SD..."</string>
+ <string name="sdcard_settings_read_only_status">"Tarjeta SD montada para sólo lectura"</string>
+ <string name="next_label">"Siguiente"</string>
+ <string name="language_picker_title">"País"</string>
+ <string name="select_your_language">"Selecciona tu idioma"</string>
+ <string name="activity_picker_label">"Seleccionar actividad"</string>
+ <string name="device_info_label">"Información de dispositivo"</string>
+ <string name="battery_info_label">"Información de la batería"</string>
+ <string name="battery_history_label">"Historial de batería"</string>
+ <string name="display_label">"Mostrar"</string>
+ <string name="phone_info_label">"Información del teléfono"</string>
+ <string name="sd_card_settings_label">"Tarjeta SD"</string>
+ <string name="proxy_settings_label">"Configuración de proxy"</string>
+ <string name="cancel">"Cancelar"</string>
+ <string name="settings_label">"Configuración"</string>
+ <string name="airplane_mode">"Modo avión"</string>
+ <string name="airplane_mode_summary">"Desactivar todas las conexiones inalámbricas"</string>
+ <string name="airplane_mode_turning_on">"Desactivando conexiones inalámbricas…"</string>
+ <string name="airplane_mode_turning_off">"Activando conexiones inalámbricas…"</string>
+ <string name="radio_controls_title">"Controles de teléfono inalámbrico"</string>
+ <string name="radio_controls_summary">"Administrar Wi-Fi, Bluetooth, modo avión y redes de celulares"</string>
+ <!-- no translation found for roaming (3596055926335478572) -->
+ <skip />
+ <!-- no translation found for roaming_enable (3737380951525303961) -->
+ <skip />
+ <!-- no translation found for roaming_disable (1295279574370898378) -->
+ <skip />
+ <!-- no translation found for roaming_reenable_message (9141007271031717369) -->
+ <skip />
+ <!-- no translation found for roaming_turn_it_on_button (4387601818162120589) -->
+ <skip />
+ <!-- no translation found for roaming_warning (1269870211689178511) -->
+ <skip />
+ <!-- no translation found for roaming_reenable_title (7626425894611573131) -->
+ <skip />
+ <!-- no translation found for networks (6333316876545927039) -->
+ <skip />
+ <!-- no translation found for sum_carrier_select (6648929373316748020) -->
+ <skip />
+ <string name="date_and_time_settings_title">"Fecha y hora"</string>
+ <string name="date_and_time_settings_summary">"Establecer fecha, hora, zona horaria y formatos"</string>
+ <string name="date_time_auto">"Automático"</string>
+ <string name="date_time_auto_summaryOn">"Utilizar valores proporcionados por la red"</string>
+ <string name="date_time_auto_summaryOff">"Utilizar valores proporcionados por la red"</string>
+ <string name="date_time_24hour">"Utilizar el formato de 24 horas"</string>
+ <string name="date_time_set_time">"Establecer la hora"</string>
+ <string name="date_time_set_timezone">"Seleccionar zona horaria"</string>
+ <string name="date_time_set_date">"Establecer fecha"</string>
+ <string name="date_time_date_format">"Seleccionar el formato de fecha"</string>
+ <string name="zone_list_menu_sort_alphabetically">"Ordenar alfabéticamente"</string>
+ <string name="zone_list_menu_sort_by_timezone">"Ordenar por zona horaria"</string>
+ <string name="security_settings_title">"Seguridad y ubicación"</string>
+ <string name="security_settings_summary">"Establecer Mi ubicación, desbloqueo de pantalla, bloqueo de tarjeta SIM"</string>
+ <string name="security_passwords_title">"Contraseñas"</string>
+ <string name="bluetooth_quick_toggle_title">"Bluetooth"</string>
+ <string name="bluetooth_quick_toggle_summary">"Activar Bluetooth"</string>
+ <string name="bluetooth_settings">"Configuración de Bluetooth"</string>
+ <string name="bluetooth_settings_title">"Configuración de Bluetooth"</string>
+ <string name="bluetooth_settings_summary">"Administrar conexiones, establecer nombre y detección del dispositivo"</string>
+ <string name="bluetooth_pin_entry">"Solicitud de vinculación de Bluetooth"</string>
+ <string name="bluetooth_device_info">"Información del dispositivo Bluetooth"</string>
+ <string name="bluetooth_enter_pin_msg">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"\n\n"Escribe el PIN para poder vincular."\n"(prueba con 0000 ó 1234.)"</string>
+ <string name="bluetooth_error_title">"Atención"</string>
+ <string name="bluetooth_pairing_error_message">"Se ha producido un problema al vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_pin_error_message">"Se ha producido un problema al vincular <xliff:g id="DEVICE_NAME">%1$s</xliff:g> debido a que el PIN que has escrito es incorrecto."</string>
+ <!-- no translation found for bluetooth_pairing_device_down_error_message (6688215193824686741) -->
+ <skip />
+ <!-- no translation found for bluetooth_pairing_rejected_error_message (1648157108520832454) -->
+ <skip />
+ <string name="bluetooth_connecting_error_message">"Se ha producido un problema al conectarse con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_preference_scan_title">"Explorar dispositivos"</string>
+ <string name="bluetooth_device_context_connect">"Conectar"</string>
+ <string name="bluetooth_device_context_disconnect">"Desconectar"</string>
+ <string name="bluetooth_device_context_pair_connect">"Vincular y conectar"</string>
+ <string name="bluetooth_device_context_unpair">"Desvincular"</string>
+ <string name="bluetooth_device_context_disconnect_unpair">"Desconectar y desvincular"</string>
+ <string name="bluetooth_device_context_connect_advanced">"Opciones..."</string>
+ <string name="bluetooth_connect_specific_profiles_title">"Conectar a..."</string>
+ <string name="bluetooth_profile_a2dp">"Medios"</string>
+ <string name="bluetooth_profile_headset">"Teléfono"</string>
+ <string name="bluetooth_summary_connected_to_a2dp">"Conectado al audio de medios"</string>
+ <string name="bluetooth_summary_connected_to_headset">"Conectado al audio del teléfono"</string>
+ <string name="bluetooth_summary_connected_to_a2dp_headset">"Conectado al audio del teléfono y los medios"</string>
+ <string name="bluetooth_device_advanced_title">"opciones de <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="bluetooth_device_advanced_online_mode_title">"Conectar"</string>
+ <string name="bluetooth_device_advanced_online_mode_summary">"Conectar al dispositivo Bluetooth"</string>
+ <string name="bluetooth_device_advanced_profile_header_title">"Perfiles"</string>
+ <string name="bluetooth_a2dp_profile_summary_connected">"Conectado al audio de medios"</string>
+ <string name="bluetooth_headset_profile_summary_connected">"Conectado al audio del teléfono"</string>
+ <string name="bluetooth_a2dp_profile_summary_use_for">"Utilizar para el audio de medios"</string>
+ <string name="bluetooth_headset_profile_summary_use_for">"Utilizar para el audio del teléfono"</string>
+ <string name="wifi">"Wi-Fi"</string>
+ <string name="wifi_quick_toggle_title">"Wi-Fi"</string>
+ <string name="wifi_quick_toggle_summary">"Encender Wi-Fi"</string>
+ <string name="wifi_settings">"Configuración Wi-Fi"</string>
+ <string name="wifi_settings_category">"Configuración Wi-Fi"</string>
+ <string name="wifi_settings_summary">"Configurar y administrar los puntos de acceso de teléfonos inalámbricos"</string>
+ <string name="forget_network">"Olvidar"</string>
+ <string name="wifi_status">"Estado"</string>
+ <string name="wifi_link_speed">"Velocidad"</string>
+ <string name="wifi_signal_3">"Excelente"</string>
+ <string name="wifi_signal_2">"Bueno"</string>
+ <string name="wifi_signal_1">"Aceptable"</string>
+ <string name="wifi_signal_0">"Baja calidad"</string>
+ <string name="security">"Seguridad"</string>
+ <string name="wifi_security_open">"Abrir"</string>
+ <string name="wifi_security_wep">"WEP"</string>
+ <string name="wifi_security_wpa">"WPA"</string>
+ <string name="wifi_security_wpa2">"WPA2"</string>
+ <string name="wifi_security_unknown">"Desconocido"</string>
+ <string name="wifi_security_verbose_open">"Abrir red"</string>
+ <string name="wifi_security_verbose_wep">"Asegurado con WEP"</string>
+ <string name="wifi_security_verbose_wpa">"Asegurado con WPA"</string>
+ <string name="wifi_security_verbose_wpa2">"Asegurado con WPA2"</string>
+ <string name="ip_address">"Dirección IP"</string>
+ <string name="signal">"Potencia de la señal"</string>
+ <string name="wifi_starting">"Encendiendo..."</string>
+ <string name="wifi_stopping">"Apagándose..."</string>
+ <string name="wifi_error">"Error"</string>
+ <string name="error_starting">"No se ha podido iniciar Wi-Fi"</string>
+ <string name="error_stopping">"No se ha podido detener Wi-Fi"</string>
+ <string name="error_scanning">"No se han podido explorar redes"</string>
+ <string name="error_connecting">"No se puede conectar a la red"</string>
+ <string name="error_saving">"No se ha podido guardar la red"</string>
+ <string name="connect">"Conectar"</string>
+ <string name="connect_to_blank">"Conectar a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="please_type_passphrase">"Contraseña de teléfono inalámbrico"</string>
+ <string name="please_type_hex_key">"Clave hexadecimal WEP (0-9, A-F)"</string>
+ <string name="wifi_show_password">"Mostrar contraseña."</string>
+ <string name="scan_wifi">"Explorar"</string>
+ <string name="summary_not_in_range">"Fuera del alcance"</string>
+ <string name="summary_remembered">"Recordado"</string>
+ <string name="summary_connection_failed">"La conexión no se ha realizado correctamente, selecciona para volver a intentarlo"</string>
+ <string name="wifi_access_points">"Redes de Wi-Fi"</string>
+ <string name="wifi_type_ssid">"SSID de red"</string>
+ <string name="wifi_security">"Seguridad"</string>
+ <string name="wifi_save_config">"Guardar"</string>
+ <string name="wifi_password_unchanged">"(sin cambios)"</string>
+ <string name="wifi_add_other_network">"Agregar red de Wi-Fi"</string>
+ <string name="wifi_notify_open_networks">"Notificación de red"</string>
+ <string name="wifi_notify_open_networks_summary">"Notificarme cuando se encuentre disponible una red abierta"</string>
+ <string name="wifi_password_incorrect_error">"La contraseña de la red que has escrito no es correcta. Vuelve a intentarlo."</string>
+ <string name="wifi_generic_connection_error">"Hay un problema de conexión de red. Vuelve a intentarlo."</string>
+ <string name="wifi_menu_advanced">"Avanzado"</string>
+ <string name="wifi_ip_settings_titlebar">"Configuración de IP"</string>
+ <string name="wifi_ip_settings_menu_save">"Guardar"</string>
+ <string name="wifi_ip_settings_menu_cancel">"Cancelar"</string>
+ <string name="wifi_ip_settings_invalid_ip">"Escribe una dirección IP válida."</string>
+ <string name="wifi_use_static_ip">"Utilizar IP estática"</string>
+ <string name="wifi_ip_address">"Dirección IP"</string>
+ <string name="wifi_dns1">"DNS 1"</string>
+ <string name="wifi_dns2">"DNS 2"</string>
+ <string name="wifi_gateway">"Acceso"</string>
+ <string name="wifi_netmask">"Máscara de red"</string>
+ <string name="wifi_context_menu_connect">"Conectar a la red"</string>
+ <string name="wifi_context_menu_forget">"Olvidar red"</string>
+ <string name="wifi_context_menu_change_password">"Cambiar contraseña"</string>
+ <string name="wifi_advanced_titlebar">"Avanzado"</string>
+ <string name="wifi_setting_num_channels_title">"Dominio regulador"</string>
+ <string name="wifi_setting_num_channels_summary">"Establecer la cantidad de canales a utilizar"</string>
+ <string name="wifi_setting_num_channels_error">"Se ha producido un problema al establecer el dominio regulador."</string>
+ <string name="wifi_setting_num_channels_channel_phrase">"<xliff:g id="NUM_CHANNELS">%1$d</xliff:g> canales"</string>
+ <string name="wifi_setting_sleep_policy_title">"Política de estado de inactividad de Wi-Fi"</string>
+ <string name="wifi_setting_sleep_policy_summary">"Especificar cuándo se debe cambiar de Wi-Fi a datos de celular"</string>
+ <string name="wifi_setting_sleep_policy_error">"Se ha producido un problema al establecer la política de estado de inactividad."</string>
+ <string name="wifi_advanced_mac_address_title">"Dirección de MAC"</string>
+ <string name="fragment_status_scanning">"Explorando..."</string>
+ <string name="fragment_status_connecting">"Conectando a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</string>
+ <string name="fragment_status_authenticating">"Autenticando con <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</string>
+ <string name="fragment_status_obtaining_ip">"Obteniendo dirección IP de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</string>
+ <string name="fragment_status_connected">"Conectado a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="fragment_status_disconnecting">"Desconectando de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</string>
+ <string name="fragment_status_disconnected">"Desconectado"</string>
+ <string name="fragment_status_failed">"Incorrecto"</string>
+ <string name="status_scanning">"Explorando..."</string>
+ <string name="status_connecting">"Conectando…"</string>
+ <string name="status_authenticating">"Autenticando…"</string>
+ <string name="status_obtaining_ip">"Obteniendo dirección..."</string>
+ <string name="status_connected">"Conectado"</string>
+ <string name="status_disconnecting">"Desconectando…"</string>
+ <string name="status_disconnected">"Desconectado"</string>
+ <string name="status_failed">"Incorrecto"</string>
+ <string name="sound_and_display_settings">"Sonido y visualización"</string>
+ <string name="sound_settings">"Configuración de sonido"</string>
+ <string name="sound_and_display_settings_summary">"Establecer tonos de llamada, notificaciones, brillo de pantalla"</string>
+ <string name="silent_mode_title">"Modo silencioso"</string>
+ <string name="silent_mode_summary">"Todos los sonidos excepto los medios y las alarmas están en silencio"</string>
+ <!-- no translation found for silent_mode_incl_alarm_summary (2088830834182228458) -->
+ <skip />
+ <string name="ringtone_title">"Tono de llamada del teléfono"</string>
+ <string name="ringtone_summary">"Establece tu tono predeterminado de llamada entrante"</string>
+ <string name="ring_volume_title">"Volumen del timbre"</string>
+ <string name="ring_volume_summary">"Establecer el volumen para las llamadas entrantes y notificaciones"</string>
+ <string name="vibrate_title">"Vibración del teléfono"</string>
+ <string name="vibrate_summary">"Hacer vibrar al teléfono para las llamadas entrantes"</string>
+ <string name="notification_sound_title">"Tono de llamada de notificación"</string>
+ <string name="notification_sound_summary">"Establecer tono predeterminado de llamada de notificación"</string>
+ <string name="incoming_call_volume_title">"Volumen de llamada entrante"</string>
+ <string name="notification_volume_title">"Volumen de notificación"</string>
+ <string name="checkbox_notification_same_as_incoming_call">"Utilizar el volumen de las llamadas entrantes para las notificaciones"</string>
+ <string name="notification_sound_dialog_title">"Seleccionar tono de llamada de notificación"</string>
+ <string name="media_volume_title">"Volumen de los medios"</string>
+ <string name="media_volume_summary">"Establecer volumen para la música y los videos"</string>
+ <string name="dtmf_tone_enable_title">"Tonos audibles"</string>
+ <string name="dtmf_tone_enable_summary_on">"Reproducir tonos cuando se utilice el teclado de marcación"</string>
+ <string name="dtmf_tone_enable_summary_off">"Reproducir tonos cuando se utilice el teclado de marcación"</string>
+ <string name="sound_effects_enable_title">"Selección audible"</string>
+ <string name="sound_effects_enable_summary_on">"Reproducir el sonido al realizar la selección de pantalla"</string>
+ <string name="sound_effects_enable_summary_off">"Reproducir el sonido al realizar la selección de pantalla"</string>
+ <string name="play_media_notification_sounds_enable_title">"Notificaciones de tarjeta SD"</string>
+ <string name="play_media_notification_sounds_enable_summary_on">"Desactivar los sonidos de notificación de la tarjeta SD"</string>
+ <string name="play_media_notification_sounds_enable_summary_off">"Activar los sonidos de notificación de la tarjeta SD"</string>
+ <string name="sync_settings">"Sincronización de datos"</string>
+ <string name="sync_settings_summary">"Seleccionar las aplicaciones que se sincronizan"</string>
+ <string name="display_settings">"Configuración de visualización"</string>
+ <string name="animations_title">"Animación"</string>
+ <string name="animations_summary_on">"Mostrar animación al abrir y cerrar ventanas"</string>
+ <string name="animations_summary_off">"Mostrar animación al abrir y cerrar ventanas"</string>
+ <string name="accelerometer_title">"Orientación"</string>
+ <string name="accelerometer_summary_on">"Cambiar la orientación automáticamente al girar el teléfono"</string>
+ <string name="accelerometer_summary_off">"Cambiar la orientación automáticamente al girar el teléfono"</string>
+ <string name="brightness">"Brillo"</string>
+ <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>
+ <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>
+ <string name="sim_pin_toggle">"Bloquear la tarjeta SIM"</string>
+ <string name="sim_lock_on">"Se requiere PIN para utilizar el teléfono"</string>
+ <string name="sim_lock_off">"Se requiere PIN para utilizar el teléfono"</string>
+ <string name="sim_pin_change">"Cambiar el PIN de SIM"</string>
+ <string name="sim_enter_pin">"PIN de SIM"</string>
+ <string name="sim_enable_sim_lock">"Bloquear la tarjeta SIM"</string>
+ <string name="sim_disable_sim_lock">"Desbloquear tarjeta SIM"</string>
+ <string name="sim_enter_old">"PIN de SIM anterior"</string>
+ <string name="sim_enter_new">"Nuevo PIN de SIM"</string>
+ <string name="sim_reenter_new">"Volver a escribir el PIN nuevo"</string>
+ <string name="sim_change_pin">"PIN de SIM"</string>
+ <string name="sim_bad_pin">"¡PIN incorrecto!"</string>
+ <string name="sim_pins_dont_match">"¡Los PIN no coinciden!"</string>
+ <string name="sim_change_failed">"No se ha podido cambiar el PIN."\n"PIN posiblemente incorrecto."</string>
+ <string name="sim_change_succeeded">"El PIN de SIM se ha cambiado correctamente"</string>
+ <string name="sim_lock_failed">"No se ha podido cambiar el estado de bloqueo de la tarjeta SIM. "\n"PIN posiblemente incorrecto."</string>
+ <string name="sim_enter_ok">"Aceptar"</string>
+ <string name="sim_enter_cancel">"Cancelar"</string>
+ <string name="device_info_settings">"Estado del teléfono"</string>
+ <string name="system_update_settings_list_item_title">"Actualizaciones del sistema"</string>
+ <string name="system_update_settings_list_item_summary">"Verificar si hay actualizaciones de sistema"</string>
+ <string name="firmware_version">"Versión de los programas inalterables"</string>
+ <string name="model_number">"Número de modelo"</string>
+ <string name="baseband_version">"Versión de banda de base"</string>
+ <string name="kernel_version">"Versión núcleo"</string>
+ <string name="build_number">"Crear número"</string>
+ <string name="device_info_not_available">"No disponible"</string>
+ <string name="device_status_activity_title">"Estado"</string>
+ <string name="device_status">"Estado"</string>
+ <string name="device_status_summary">"IMEI, número de teléfono, señal, etc."</string>
+ <string name="storage_settings_title">"Tarjeta SD y almacenamiento del teléfono"</string>
+ <string name="storage_settings_summary">"Desmontar tarjeta SD, ver espacio de almacenamiento disponible"</string>
+ <string name="status_number">"Número de teléfono"</string>
+ <string name="status_network_type">"Tipo de red de celulares"</string>
+ <string name="status_data_state">"Estado de red de celulares"</string>
+ <string name="status_service_state">"Estado del servicio"</string>
+ <string name="status_signal_strength">"Potencia de la señal"</string>
+ <string name="status_roaming">"Roaming"</string>
+ <string name="status_operator">"Red"</string>
+ <string name="status_wifi_mac_address">"Dirección MAC de Wi-Fi"</string>
+ <string name="status_bt_address">"Dirección de Bluetooth"</string>
+ <string name="status_unavailable">"No disponible"</string>
+ <string name="status_up_time">"Hora productiva"</string>
+ <string name="status_awake_time">"Hora de actividad"</string>
+ <string name="internal_memory">"Espacio de almacenamiento interno del teléfono"</string>
+ <string name="sd_memory">"Tarjeta SD"</string>
+ <string name="memory_available">"Espacio disponible"</string>
+ <string name="memory_size">"Espacio total"</string>
+ <string name="sd_eject">"Desmontar la tarjeta SD"</string>
+ <string name="sd_eject_summary">"Desmontar la tarjeta SD para extraerla de manera segura"</string>
+ <string name="sd_format">"Formatear tarjeta SD"</string>
+ <string name="sd_format_summary">"Formato (borrar) la tarjeta SD"</string>
+ <string name="sd_unavailable">"No disponible"</string>
+ <string name="read_only">" (Sólo lectura)"</string>
+ <string name="battery_status_title">"Estado de batería"</string>
+ <string name="battery_level_title">"Nivel de la batería"</string>
+ <string name="apn_settings">"APN"</string>
+ <string name="apn_edit">"Editar el punto de acceso"</string>
+ <string name="apn_not_set">"<No establecido>"</string>
+ <string name="apn_name">"Nombre"</string>
+ <string name="apn_apn">"APN"</string>
+ <string name="apn_http_proxy">"Proxy"</string>
+ <string name="apn_http_port">"Puerto"</string>
+ <string name="apn_user">"Nombre de usuario"</string>
+ <string name="apn_password">"Contraseña"</string>
+ <string name="apn_server">"Servidor"</string>
+ <string name="apn_mmsc">"MMSC"</string>
+ <string name="apn_mms_proxy">"Proxy de MMS"</string>
+ <string name="apn_mms_port">"Puerto MMS"</string>
+ <string name="apn_mcc">"MCC"</string>
+ <string name="apn_mnc">"MNC"</string>
+ <string name="apn_type">"Tipo de APN"</string>
+ <string name="menu_delete">"Eliminar APN"</string>
+ <string name="menu_new">"APN nuevo"</string>
+ <string name="menu_save">"Guardar"</string>
+ <string name="menu_cancel">"Descartar"</string>
+ <string name="error_title">"Atención"</string>
+ <string name="error_name_empty">"El campo Nombre no puede estar vacío"</string>
+ <string name="error_apn_empty">"El APN no puede estar vacío."</string>
+ <string name="error_mcc_not3">"El campo de MCC debe contener 3 dígitos."</string>
+ <string name="error_mnc_not23">"El campo MNC debe contener 2 ó 3 dígitos."</string>
+ <string name="restore_default_apn">"Restaurando la configuración APN predeterminada"</string>
+ <string name="menu_restore">"Reestablecer a la forma predeterminada"</string>
+ <string name="restore_default_apn_completed">"Restablecimiento completado de configuración de APN predeterminada"</string>
+ <string name="master_clear_title">"Restablecimiento de los datos de fábrica"</string>
+ <string name="master_clear_summary">"Borra todos los datos del teléfono"</string>
+ <string name="master_clear_desc">"¡Esta acción restablecerá el teléfono a su estado de fábrica inicial y borrará todos los datos y aplicaciones descargadas!"</string>
+ <string name="master_clear_button_text">"Restablecer el teléfono"</string>
+ <string name="master_clear_final_desc">"¿Deseas restablecer el teléfono y borrar todos los datos y aplicaciones? ¡Esta acción no se puede cambiar!"</string>
+ <string name="master_clear_final_button_text">"Borrar todo"</string>
+ <string name="master_clear_gesture_prompt">"Extrae tu patrón de desbloqueo"</string>
+ <string name="master_clear_gesture_explanation">"Debes extraer tu patrón de desbloqueo para confirmar el restablecimiento de un teléfono."</string>
+ <string name="master_clear_failed">"No se ha realizado ningún restablecimiento debido a que el servicio \"Borrar sistema\" no se encuentra disponible."</string>
+ <string name="media_format_title">"Formatear tarjeta SD."</string>
+ <string name="media_format_summary">"Borra todos los datos en la tarjeta SD"</string>
+ <string name="media_format_desc">"Esta acción borrará la tarjeta SD en el teléfono. ¡Perderás TODA la información de la tarjeta!"</string>
+ <string name="media_format_button_text">"Formatear tarjeta SD"</string>
+ <string name="media_format_final_desc">"¿Deseas formatear tarjeta SD y borrar todos tus medios? ¡Esta acción no se puede cambiar!"</string>
+ <string name="media_format_final_button_text">"Borrar todo"</string>
+ <string name="media_format_gesture_prompt">"Extrae tu patrón de desbloqueo"</string>
+ <string name="media_format_gesture_explanation">"Debes extraer tu patrón de desbloqueo parar confirmar un formato de tarjeta SD."</string>
+ <string name="call_settings_title">"Configuración de llamada"</string>
+ <string name="call_settings_summary">"Establecer correo de voz, desvío de llamadas, llamada en espera, identificador de llamadas"</string>
+ <string name="network_settings_title">"Redes de celulares"</string>
+ <string name="network_settings_summary">"Establecer opciones para roaming, redes, APN"</string>
+ <string name="location_title">"Mis fuentes de ubicación"</string>
+ <string name="location_network_based">"Utilizar redes inalámbricas"</string>
+ <string name="location_networks_disabled">"Ver ubicación en las aplicaciones (como Mapas) mediante redes inalámbricas"</string>
+ <string name="location_neighborhood_level">"Ubicación determinada por Wi-Fi o redes de celulares"</string>
+ <string name="location_gps">"Activar satélites de GPS"</string>
+ <string name="location_street_level">"Localizar con una precisión del nivel de calle (deseleccionar para conservar la batería)"</string>
+ <string name="location_gps_disabled">"Localizar a nivel de calle (requiere más batería además de la vista del cielo)"</string>
+ <string name="about_settings">"Acerca del teléfono"</string>
+ <string name="about_settings_summary">"Ver información legal, estado del teléfono, versión de software"</string>
+ <string name="legal_information">"Información legal"</string>
+ <string name="contributors_title">"Colaboradores"</string>
+ <string name="copyright_title">"Derechos de autor"</string>
+ <string name="license_title">"Licencia"</string>
+ <string name="terms_title">"Términos y condiciones"</string>
+ <!-- no translation found for system_tutorial_list_item_title (4315834755909579018) -->
+ <skip />
+ <!-- no translation found for system_tutorial_list_item_summary (3861815254521030201) -->
+ <skip />
+ <string name="settings_license_activity_title">"Abrir licencias de origen"</string>
+ <string name="settings_license_activity_unavailable">"Hay un problema para cargar las licencias."</string>
+ <string name="settings_license_activity_loading">"Cargando…"</string>
+ <string name="lock_settings_title">"Patrón de desbloqueo de la pantalla"</string>
+ <string name="lockpattern_change_lock_pattern_label">"Cambiar patrón de desbloqueo"</string>
+ <string name="lockpattern_need_to_unlock">"Confirmar el patrón guardado"</string>
+ <string name="lockpattern_need_to_unlock_wrong">"Lo sentimos, vuelve a intentarlo:"</string>
+ <string name="lockpattern_recording_intro_header">"Extraer un patrón de desbloqueo"</string>
+ <string name="lockpattern_recording_intro_footer">"Presiona el Menú para obtener ayuda."</string>
+ <string name="lockpattern_recording_inprogress">"Sacar el dedo cuando haya finalizado."</string>
+ <string name="lockpattern_recording_incorrect_too_short">"Conectar al menos <xliff:g id="NUMBER">%d</xliff:g> puntos. Vuelve a intentarlo."</string>
+ <string name="lockpattern_pattern_entered_header">"¡Patrón grabado!"</string>
+ <string name="lockpattern_need_to_confirm">"Extrae el patrón nuevamente para confirmar:"</string>
+ <string name="lockpattern_pattern_confirmed_header">"Tu nuevo patrón de desbloqueo:"</string>
+ <string name="lockpattern_confirm_button_text">"Confirmar"</string>
+ <string name="lockpattern_restart_button_text">"Revisar"</string>
+ <string name="lockpattern_retry_button_text">"Intentar nuevamente"</string>
+ <string name="lockpattern_continue_button_text">"Continuar"</string>
+ <string name="lockpattern_settings_title">"Patrón de desbloqueo"</string>
+ <string name="lockpattern_settings_enable_title">"Requiere un patrón"</string>
+ <string name="lockpattern_settings_enable_summary">"Debes extraer el patrón para desbloquear la pantalla"</string>
+ <string name="lockpattern_settings_enable_visible_pattern_title">"Utilizar un patrón visible"</string>
+ <string name="lockpattern_settings_enable_tactile_feedback_title">"Usar retroalimentación táctil"</string>
+ <string name="lockpattern_settings_choose_lock_pattern">"Establecer patrón de desbloqueo"</string>
+ <string name="lockpattern_settings_change_lock_pattern">"Cambiar patrón de desbloqueo"</string>
+ <string name="lockpattern_settings_help_how_to_record">"Cómo se debe extraer un patrón de desbloqueo"</string>
+ <string name="lockpattern_too_many_failed_confirmation_attempts_header">"¡Demasiados intentos incorrectos!"</string>
+ <string name="lockpattern_too_many_failed_confirmation_attempts_footer">"Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
+ <string name="skip_button_label">"Cancelar"</string>
+ <string name="next_button_label">"Siguiente"</string>
+ <string name="lock_title">"Asegurando tu teléfono"</string>
+ <string name="lock_intro_message"><font size="17">"Protege a tu teléfono de usos no autorizados al crear un patrón de desbloqueo en la pantalla personal. "\n<font height="17">\n</font><b>"1"</b>" En la pantalla siguiente, observa cómo se extrae un patrón de ejemplo. "\n<font height="17">\n</font><b>"2"</b>" Cuando estés listo, extrae tu propio patrón de desbloqueo personal. Experimenta con diferentes patrones pero conecta al menos cuatro puntos. "\n<font height="17">\n</font><b>"3"</b>" Revisa tu patrón para confirmar. "\n<font height="17">\n</font><b>"¿Estás listo para comenzar? Selecciona “Siguiente”"</b>". "\n<font height="3">\n</font>"Si deseas dejar sin protección a tu teléfono, selecciona “Cancelar”."</font></string>
+ <string name="lock_example_title">"Patrón de ejemplo"</string>
+ <string name="lock_example_message">"Conecta al menos cuatro puntos."\n" "\n"Selecciona “Siguiente” cuando estés listo para extraer tu propio patrón."</string>
+ <string name="manageapplications_settings_title">"Administrar aplicaciones"</string>
+ <string name="manageapplications_settings_summary">"Administrar y eliminar aplicaciones instaladas"</string>
+ <string name="applications_settings">"Aplicaciones"</string>
+ <string name="applications_settings_summary">"Administrar aplicaciones, configurar accesos directos para lanzamientos rápidos"</string>
+ <string name="applications_settings_header">"Configuración de aplicación"</string>
+ <string name="install_applications">"Fuentes desconocidas"</string>
+ <string name="install_unknown_applications">"Admite la instalación de aplicaciones que no pertenezcan a Market"</string>
+ <string name="install_all_warning">"Tu teléfono y datos personales son más vulnerables a sufrir ataques de aplicaciones provenientes de fuentes desconocidas. Aceptas que eres el único responsable de cualquier daño que sufra tu teléfono o de cualquier pérdida de datos que pueda ocasionar el uso de estas aplicaciones."</string>
+ <string name="application_info_label">"Información de aplicación"</string>
+ <string name="storage_label">"Espacio de almacenamiento"</string>
+ <string name="auto_launch_label">"Lanzar de manera predeterminada"</string>
+ <string name="permissions_label">"Permisos"</string>
+ <string name="cache_header_label">"Memoria caché"</string>
+ <string name="clear_cache_btn_text">"Borrar memoria caché"</string>
+ <string name="cache_size_label">"Memoria caché"</string>
+ <string name="controls_label">"Controles"</string>
+ <string name="force_stop">"Provocar la detención"</string>
+ <string name="total_size_label">"Total"</string>
+ <string name="application_size_label">"Aplicación"</string>
+ <string name="data_size_label">"Datos"</string>
+ <string name="uninstall_text">"Desinstalar..."</string>
+ <string name="clear_user_data_text">"Borrar datos"</string>
+ <string name="auto_launch_enable_text">"Has elegido lanzar esta aplicación de manera predeterminada para algunas acciones."</string>
+ <string name="auto_launch_disable_text">"No hay configuraciones predeterminadas establecidas."</string>
+ <string name="clear_activities">"Borrar configuraciones predeterminadas"</string>
+ <string name="unknown">"Desconocido"</string>
+ <string name="sort_order_alpha">"Ordenar"</string>
+ <string name="sort_order_size">"Ordenar por tamaño"</string>
+ <string name="manage_space_text">"Administrar el espacio"</string>
+ <string name="filter">"Filtro"</string>
+ <string name="filter_dlg_title">"Seleccionar opciones de filtro"</string>
+ <string name="filter_apps_all">"Todos"</string>
+ <string name="filter_apps_third_party">"Tercero"</string>
+ <string name="filter_apps_running">"En ejecución"</string>
+ <string name="loading">"Cargando…"</string>
+ <string name="recompute_size">"Recalculando el tamaño…"</string>
+ <string name="clear_data_dlg_title">"Eliminar"</string>
+ <string name="clear_data_dlg_text">"Toda la información que has guardado en esta aplicación se eliminará de manera permanente."</string>
+ <string name="dlg_ok">"Aceptar"</string>
+ <string name="dlg_cancel">"Cancelar"</string>
+ <string name="app_not_found_dlg_title">"No se ha encontrado la aplicación"</string>
+ <string name="app_not_found_dlg_text">"No se ha encontrado la aplicación en la lista de aplicaciones instaladas."</string>
+ <string name="clear_data_failed">"No se han podido borrar los datos de la aplicación."</string>
+ <string name="security_settings_desc">"Esta aplicación puede acceder a lo siguiente en tu teléfono:"</string>
+ <string name="computing_size">"Calculando..."</string>
+ <string name="invalid_size_value">"No se ha podido calcular el tamaño del paquete"</string>
+ <string name="empty_list_msg">"No tienes instalada ninguna aplicación de terceros."</string>
+ <string name="language_settings">"País y texto"</string>
+ <string name="language_settings_summary">"Establecer opciones de país (idioma y región), ingreso de texto y corrección automática"</string>
+ <string name="language_category">"Configuración de país"</string>
+ <string name="text_category">"Configuración de texto"</string>
+ <string name="phone_language">"Seleccionar país"</string>
+ <string name="phone_language_summary">"Seleccionar idioma y región"</string>
+ <string name="auto_replace">"Reemplazar automáticamente"</string>
+ <string name="auto_replace_summary">"Corregir palabras mal escritas"</string>
+ <string name="auto_caps">"Uso automático de mayúsculas"</string>
+ <string name="auto_caps_summary">"Escribir con mayúscula la primera letra en las oraciones"</string>
+ <string name="auto_punctuate">"Colocar la puntuación automáticamente"</string>
+ <string name="hardkeyboard_category">"Configuración de teclado físico"</string>
+ <string name="auto_punctuate_summary">"Presionar la tecla de espacio dos veces para insertar \".\""</string>
+ <string name="show_password">"Contraseñas visibles"</string>
+ <string name="show_password_summary">"Mostrar contraseña cuando escribas"</string>
+ <!-- no translation found for ime_security_warning (3458652708716006477) -->
+ <skip />
+ <string name="user_dict_settings_titlebar">"Diccionario del usuario"</string>
+ <string name="user_dict_settings_title">"Diccionario del usuario"</string>
+ <string name="user_dict_settings_summary">"Agregar y eliminar palabras del diccionario del usuario"</string>
+ <string name="user_dict_settings_add_menu_title">"Agregar"</string>
+ <string name="user_dict_settings_add_dialog_title">"Agregar al diccionario"</string>
+ <string name="user_dict_settings_edit_dialog_title">"Editar trabajo"</string>
+ <string name="user_dict_settings_context_menu_edit_title">"Editar"</string>
+ <string name="user_dict_settings_context_menu_delete_title">"Eliminar"</string>
+ <string name="user_dict_settings_empty_text">"El diccionario del usuario no contiene ninguna palabra. Puedes agregar una palabra a través del menú."</string>
+ <string name="testing">"Probando"</string>
+ <string name="testing_phone_info">"Información del teléfono"</string>
+ <string name="testing_battery_info">"Información sobre la batería"</string>
+ <string name="testing_battery_history">"Historial de batería"</string>
+ <string name="quick_launch_title">"Lanzamiento rápido"</string>
+ <string name="quick_launch_summary">"Establecer métodos abreviados de teclado para lanzar aplicaciones"</string>
+ <string name="quick_launch_assign_application">"Asignar aplicación"</string>
+ <string name="quick_launch_no_shortcut">"No hay acceso directo"</string>
+ <string name="quick_launch_shortcut">"Buscar + <xliff:g id="SHORTCUT_LETTER">%1$s</xliff:g>"</string>
+ <string name="quick_launch_clear_dialog_title">"Borrar"</string>
+ <string name="quick_launch_clear_dialog_message">"Se borrará tu acceso directo para <xliff:g id="SHORTCUT_LETTER">%1$s</xliff:g> (<xliff:g id="APPLICATION_NAME">%2$s</xliff:g>)."</string>
+ <string name="quick_launch_clear_ok_button">"Aceptar"</string>
+ <string name="quick_launch_clear_cancel_button">"Cancelar"</string>
+ <string name="quick_launch_display_mode_applications">"Aplicaciones"</string>
+ <string name="quick_launch_display_mode_shortcuts">"Accesos directos"</string>
+ <string name="input_methods_settings_title">"Ingreso de texto"</string>
+ <string name="input_methods_settings_summary">"Administrar opciones de ingreso de texto"</string>
+ <string name="input_methods_settings_label_format">"Configuración de <xliff:g id="IME_NAME">%1$s</xliff:g>"</string>
+ <string name="onscreen_keyboard_settings_summary">"Configuración de teclado en la pantalla"</string>
+ <string name="builtin_keyboard_settings_title">"Teclado del dispositivo"</string>
+ <string name="builtin_keyboard_settings_summary">"Configuración de teclado integrado"</string>
+ <string name="development_settings_title">"Desarrollo"</string>
+ <string name="development_settings_summary">"Establecer opciones para desarrollar aplicaciones"</string>
+ <string name="enable_adb">"Depuración de USB"</string>
+ <string name="enable_adb_summary">"Modo de depuración cuando se conecta el USB"</string>
+ <string name="keep_screen_on">"Permanecer activo"</string>
+ <string name="keep_screen_on_summary">"La pantalla nunca quedará inactiva mientras se realiza la carga"</string>
+ <string name="allow_mock_location">"Permitir la creación de ubicaciones de prueba"</string>
+ <string name="allow_mock_location_summary">"Permitir la creación de ubicaciones de prueba"</string>
+ <string name="gadget_picker_title">"Elegir gadget"</string>
+ <string name="widget_picker_title">"Elegir control"</string>
+ <string name="battery_history_details_for">"Detalles de %d de UID"</string>
+ <string name="battery_history_uid">"ID de usuario <xliff:g id="USER_ID">%1$d</xliff:g>"</string>
+ <string name="battery_history_network_usage">"Detalles de uso de la red para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="battery_history_bytes_received">"Bytes recibidos: <xliff:g id="BYTES">%1$d</xliff:g>"</string>
+ <string name="battery_history_bytes_sent">"Bytes enviados: <xliff:g id="BYTES">%1$d</xliff:g>"</string>
+ <string name="battery_history_bytes_total">"Total de bytes: <xliff:g id="BYTES">%1$d</xliff:g>"</string>
+ <string name="battery_history_cpu_usage">"Detalles de uso de CPU para <xliff:g id="APP_NAME">%1$s</xliff:g>:"</string>
+ <string name="battery_history_user_time">"Hora del usuario:"</string>
+ <string name="battery_history_system_time">"Hora del sistema:"</string>
+ <string name="battery_history_total_time">"Tiempo total:"</string>
+ <string name="battery_history_starts">"Comienza: <xliff:g id="STARTS">%1$d</xliff:g>"</string>
+ <string name="battery_history_days">"<xliff:g id="DAYS">%1$d</xliff:g> días, <xliff:g id="HOURS">%2$d</xliff:g> horas, <xliff:g id="MINUTES">%3$d</xliff:g> minutos, <xliff:g id="SECONDS">%4$d</xliff:g> segundos"</string>
+ <string name="battery_history_hours">"<xliff:g id="HOURS">%1$d</xliff:g> horas, <xliff:g id="MINUTES">%2$d</xliff:g> minutos, <xliff:g id="SECONDS">%3$d</xliff:g> segundos"</string>
+ <string name="battery_history_minutes">"<xliff:g id="MINUTES">%1$d</xliff:g> minutos, <xliff:g id="SECONDS">%2$d</xliff:g> segundos"</string>
+ <string name="battery_history_seconds">"<xliff:g id="SECONDS">%1$d</xliff:g> segundos"</string>
+ <string name="battery_history_packages_sharing_this_uid">"Paquetes que comparten esta UID:"</string>
+ <string name="battery_history_no_data">"No hay datos disponibles del uso de la batería"</string>
+ <string name="battery_history_sensor">"Sensor:"</string>
+ <string name="battery_history_wakelock">"Bloqueo de despertador parcial:"</string>
+ <string name="battery_history_used_by_packages">"Sensor utilizado por los paquetes:"</string>
+ <string name="battery_history_sensor_usage">"Utilizado <xliff:g id="COUNT">%1$d</xliff:g> veces por <xliff:g id="PACKAGE">%2$s</xliff:g>"</string>
+ <string name="battery_history_sensor_usage_multi">"Utilizado <xliff:g id="COUNT">%1$d</xliff:g> veces por uno de:"</string>
+ <string name="battery_history_awake_label">"En ejecución"</string>
+ <string name="battery_history_screen_on_label">"Pantalla encendida"</string>
+ <string name="battery_history_phone_on_label">"Teléfono encendido"</string>
+ <string name="battery_history_awake">"Tiempo de encendido sin estar en estado de inactividad:"</string>
+ <string name="battery_history_screen_on">"Tiempo de encendido de la pantalla:"</string>
+ <string name="battery_history_phone_on">"Tiempo de encendido del teléfono:"</string>
+ <string name="battery_history_screen_on_battery">"En la batería:"</string>
+ <string name="battery_history_screen_on_plugged">"Conectado:"</string>
+ <string name="usage_stats_label">"Estadísticas de uso"</string>
+ <string name="testing_usage_stats">"Estadísticas de uso"</string>
+ <string name="display_order_text">"Ordenar por:"</string>
+ <string name="app_name_label">"Aplicación"</string>
+ <string name="launch_count_label">"Contar"</string>
+ <string name="usage_time_label">"Hora de uso"</string>
+</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 1c867fd..5e6c425 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -107,8 +107,6 @@
<string name="date_and_time">"Configuración de fecha y hora"</string>
<string name="date_time_12_hour_sample">"1:00 p.m."</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <string name="date_time_changeTime_text">"Cambiar hora"</string>
- <string name="date_time_changeDate_text">"Fecha"</string>
<string name="choose_timezone">"Seleccionar zona horaria"</string>
<string name="display_preview_label">"Vista previa:"</string>
<string name="display_font_size_label">"Tamaño de fuente:"</string>
@@ -201,7 +199,7 @@
<string name="date_time_auto">"Automático"</string>
<string name="date_time_auto_summaryOn">"Utilizar valores proporcionados por la red"</string>
<string name="date_time_auto_summaryOff">"Utilizar valores proporcionados por la red"</string>
- <string name="date_time_24hour">"Formato de 24 horas"</string>
+ <string name="date_time_24hour">"Utilizar formato de 24 horas"</string>
<string name="date_time_set_time">"Establecer hora"</string>
<string name="date_time_set_timezone">"Seleccionar zona horaria"</string>
<string name="date_time_set_date">"Establecer fecha"</string>
@@ -361,7 +359,7 @@
<string name="sound_effects_enable_title">"Selección sonora"</string>
<string name="sound_effects_enable_summary_on">"Reproducir sonido cuando se realiza una selección de pantalla"</string>
<string name="sound_effects_enable_summary_off">"Reproducir sonido cuando se realiza una selección de pantalla"</string>
- <string name="play_media_notification_sounds_enable_title">"Notificaciones tarjeta SD"</string>
+ <string name="play_media_notification_sounds_enable_title">"Notificaciones de la tarjeta SD"</string>
<string name="play_media_notification_sounds_enable_summary_on">"Inhabilitar sonidos de notificación de la tarjeta SD"</string>
<string name="play_media_notification_sounds_enable_summary_off">"Habilitar sonidos de notificación de la tarjeta SD"</string>
<string name="sync_settings">"Sincronización de datos"</string>
@@ -375,10 +373,10 @@
<string name="accelerometer_summary_off">"Cambiar orientación automáticamente al girar el teléfono"</string>
<string name="brightness">"Brillo"</string>
<string name="brightness_summary">"Ajustar el brillo de la pantalla"</string>
- <string name="screen_timeout">"Tiempo espera pantalla"</string>
+ <string name="screen_timeout">"Tiempo de espera de pantalla"</string>
<string name="screen_timeout_summary">"Ajustar el tiempo de retraso antes de que la pantalla se apague automáticamente"</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_category">"Configurar bloqueo de tarjeta SIM"</string>
<string name="sim_lock_settings_title">"Bloqueo de tarjeta SIM"</string>
<string name="sim_pin_toggle">"Bloquear tarjeta SIM"</string>
<string name="sim_lock_on">"Solicitar PIN para utilizar el teléfono"</string>
@@ -419,7 +417,7 @@
<string name="status_signal_strength">"Intensidad de la señal"</string>
<string name="status_roaming">"Itinerancia"</string>
<string name="status_operator">"Red"</string>
- <string name="status_wifi_mac_address">"Dirección MAC de Wi-Fi"</string>
+ <string name="status_wifi_mac_address">"Dirección MAC de la red Wi-Fi"</string>
<string name="status_bt_address">"Dirección de Bluetooth"</string>
<string name="status_unavailable">"No disponible"</string>
<string name="status_up_time">"Tiempo de actividad"</string>
@@ -464,7 +462,7 @@
<string name="restore_default_apn">"Restaurando la configuración de APN predeterminada"</string>
<string name="menu_restore">"Restablecer valores predeterminados"</string>
<string name="restore_default_apn_completed">"Restablecimiento de la configuración de APN predeterminada completado"</string>
- <string name="master_clear_title">"Rest. datos de fábrica"</string>
+ <string name="master_clear_title">"Restablecer datos de fábrica"</string>
<string name="master_clear_summary">"Borrar todos los datos del teléfono"</string>
<string name="master_clear_desc">"Esta acción restablecerá el teléfono a su estado de fábrica inicial y borrará todos los datos y todas las aplicaciones descargadas."</string>
<string name="master_clear_button_text">"Reiniciar teléfono"</string>
@@ -485,17 +483,13 @@
<string name="call_settings_summary">"Configurar buzón, llamada en espera, desvío e identificador"</string>
<string name="network_settings_title">"Redes móviles"</string>
<string name="network_settings_summary">"Establecer opciones para itinerancia, redes, APN"</string>
- <string name="location_title">"Mis fuentes de ubicación"</string>
+ <string name="location_title">"Fuentes de Mi Ubicación"</string>
<string name="location_network_based">"Usar redes inalámbricas"</string>
<string name="location_networks_disabled">"Para ver una ubicación en aplicaciones (por ejemplo, Google Maps)"</string>
<string name="location_neighborhood_level">"Ubicación determinada por redes móviles o Wi-Fi"</string>
<string name="location_gps">"Habilitar satélites GPS"</string>
<string name="location_street_level">"Preciso en el nivel de calle (anula la selección para ahorrar batería)"</string>
<string name="location_gps_disabled">"Localizar en nivel de calle (requiere más batería además de la vista aérea)"</string>
- <string name="location_warning_title">"Consentimiento de ubicación"</string>
- <string name="location_warning_message">"Permite que el servicio de ubicación de Google recopile los datos de ubicación anónimos y globales. La recopilación tiene lugar aunque otras aplicaciones estén activas."</string>
- <string name="agree">"Acepto"</string>
- <string name="disagree">"No acepto"</string>
<string name="about_settings">"Acerca del teléfono"</string>
<string name="about_settings_summary">"Ver información legal, estado del teléfono, versión del software"</string>
<string name="legal_information">"Información legal"</string>
@@ -505,7 +499,7 @@
<string name="terms_title">"Términos y condiciones"</string>
<string name="system_tutorial_list_item_title">"Tutorial del sistema"</string>
<string name="system_tutorial_list_item_summary">"Aprende a utilizar tu teléfono"</string>
- <string name="settings_license_activity_title">"Licencias de SW libre"</string>
+ <string name="settings_license_activity_title">"Licencias de software libre"</string>
<string name="settings_license_activity_unavailable">"Se ha producido un problema al intentar cargar las licencias."</string>
<string name="settings_license_activity_loading">"Cargando..."</string>
<string name="lock_settings_title">"Patrón de desbloqueo de pantalla"</string>
@@ -527,8 +521,8 @@
<string name="lockpattern_settings_enable_title">"Patrón obligatorio"</string>
<string name="lockpattern_settings_enable_summary">"Se debe crear un patrón para desbloquear la pantalla."</string>
<string name="lockpattern_settings_enable_visible_pattern_title">"Utilizar patrón visible"</string>
- <string name="lockpattern_settings_enable_tactile_feedback_title">"Comentarios al crear patrón"</string>
- <string name="lockpattern_settings_choose_lock_pattern">"Patrón de desbloqueo"</string>
+ <string name="lockpattern_settings_enable_tactile_feedback_title">"Utilizar comentarios al crear patrón"</string>
+ <string name="lockpattern_settings_choose_lock_pattern">"Establecer patrón de desbloqueo"</string>
<string name="lockpattern_settings_change_lock_pattern">"Cambiar patrón de desbloqueo"</string>
<string name="lockpattern_settings_help_how_to_record">"Cómo crear un patrón de desbloqueo"</string>
<string name="lockpattern_too_many_failed_confirmation_attempts_header">"Se han realizado demasiados intentos incorrectos."</string>
@@ -590,7 +584,7 @@
<string name="language_settings_summary">"Configuración local, opciones de autocorrección e introducción de texto"</string>
<string name="language_category">"Configuración local"</string>
<string name="text_category">"Configuración de texto"</string>
- <string name="phone_language">"Configuración local"</string>
+ <string name="phone_language">"Seleccionar configuración local"</string>
<string name="phone_language_summary">"Seleccionar idioma y región"</string>
<string name="auto_replace">"Corrección automática"</string>
<string name="auto_replace_summary">"Corregir palabras con errores de escritura"</string>
@@ -606,7 +600,7 @@
<string name="user_dict_settings_title">"Diccionario del usuario"</string>
<string name="user_dict_settings_summary">"Añadir y eliminar palabras del diccionario del usuario"</string>
<string name="user_dict_settings_add_menu_title">"Añadir"</string>
- <string name="user_dict_settings_add_dialog_title">"Añadir al diccionario"</string>
+ <string name="user_dict_settings_add_dialog_title">"Añadir al usuario"</string>
<string name="user_dict_settings_edit_dialog_title">"Editar palabra"</string>
<string name="user_dict_settings_context_menu_edit_title">"Editar"</string>
<string name="user_dict_settings_context_menu_delete_title">"Suprimir"</string>
@@ -638,7 +632,7 @@
<string name="enable_adb_summary">"Modo de depuración cuando está conectado el dispositivo USB"</string>
<string name="keep_screen_on">"Pantalla activa"</string>
<string name="keep_screen_on_summary">"La pantalla nunca entra en modo de suspensión durante la carga"</string>
- <string name="allow_mock_location">"Ubicaciones simuladas"</string>
+ <string name="allow_mock_location">"Permitir ubicaciones simuladas"</string>
<string name="allow_mock_location_summary">"Permitir ubicaciones simuladas"</string>
<string name="gadget_picker_title">"Seleccionar gadget"</string>
<string name="widget_picker_title">"Seleccionar widget"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index edf7753..26abe66 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="device_info_default">"Inconnu"</string>
- <string name="turn_on_radio">"Allumer le signal radio"</string>
- <string name="turn_off_radio">"Éteindre le signal radio"</string>
+ <string name="turn_on_radio">"Allumer la radio"</string>
+ <string name="turn_off_radio">"Éteindre la radio"</string>
<string name="turn_on_qxdm">"Activer le journal SD QXDM"</string>
<string name="turn_off_qxdm">"Désactiver le journal QXMD SD"</string>
<string name="radioInfo_menu_viewADN">"Afficher le carnet d\'adresses de la carte SIM"</string>
@@ -31,7 +31,7 @@
<string name="radioInfo_service_in">"Service en cours"</string>
<string name="radioInfo_service_out">"Hors-service"</string>
<string name="radioInfo_service_emergency">"Appels d\'urgence uniquement"</string>
- <string name="radioInfo_service_off">"Signal radio désactivé"</string>
+ <string name="radioInfo_service_off">"Radio désactivée"</string>
<string name="radioInfo_roaming_in">"Itinérance"</string>
<string name="radioInfo_roaming_not">"Sans itinérance"</string>
<string name="radioInfo_phone_idle">"Inactif"</string>
@@ -69,7 +69,7 @@
<string name="battery_info_awake_plugged">"Temps en activité lors du rechargement :"</string>
<string name="battery_info_screen_on">"Écran activé :"</string>
<string name="battery_info_status_unknown">"Inconnu"</string>
- <string name="battery_info_status_charging">"Batterie en charge"</string>
+ <string name="battery_info_status_charging">"Chargement"</string>
<string name="battery_info_status_charging_ac">"(AC)"</string>
<string name="battery_info_status_charging_usb">"(USB)"</string>
<string name="battery_info_status_discharging">"Baisse du niveau de charge"</string>
@@ -88,7 +88,7 @@
<string name="bluetooth_devices">"Appareils Bluetooth"</string>
<string name="bluetooth_device_name">"Nom de l\'appareil"</string>
<string name="bluetooth_name_not_set">"Aucun nom n\'a été défini. Utilisation du nom du compte..."</string>
- <string name="bluetooth_scan_for_devices">"Recherche d\'appareils"</string>
+ <string name="bluetooth_scan_for_devices">"Rechercher d\'appareils"</string>
<string name="bluetooth_disconnect_blank">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> va être déconnecté."</string>
<string name="bluetooth_connected">"Connecté"</string>
<string name="bluetooth_disconnected">"Déconnecté"</string>
@@ -107,8 +107,6 @@
<string name="date_and_time">"Paramètres d\'heure et de date"</string>
<string name="date_time_12_hour_sample">"13:00 h"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <string name="date_time_changeTime_text">"Changer l\'heure"</string>
- <string name="date_time_changeDate_text">"Date"</string>
<string name="choose_timezone">"Choisir fuseau horaire"</string>
<string name="display_preview_label">"Aperçu :"</string>
<string name="display_font_size_label">"Taille de police :"</string>
@@ -135,7 +133,7 @@
<string name="radio_info_data_attempts_label">"Tentatives :"</string>
<string name="radio_info_gprs_service_label">"Service GPRS :"</string>
<string name="radio_info_roaming_label">"Itinérance :"</string>
- <string name="radio_info_imei_label">"Code IMEI :"</string>
+ <string name="radio_info_imei_label">"IIEM :"</string>
<string name="radio_info_call_redirect_label">"Redirection des appels :"</string>
<string name="radio_info_ppp_resets_label">"Nombre de réinitialisations PPP depuis le démarrage :"</string>
<string name="radio_info_gsm_disconnects_label">"Déconnexions GSM :"</string>
@@ -146,7 +144,7 @@
<string name="radio_info_signal_strength_label">"Intensité du signal :"</string>
<string name="radio_info_call_status_label">"État de l\'appel :"</string>
<string name="radio_info_ppp_sent_label">"PPP envoyés :"</string>
- <string name="radio_info_radio_resets_label">"Réinitialisations du signal radio :"</string>
+ <string name="radio_info_radio_resets_label">"Réinitialisations de la radio :"</string>
<string name="radio_info_message_waiting_label">"Message en attente :"</string>
<string name="radio_info_phone_number_label">"Numéro de téléphone :"</string>
<string name="radio_info_band_mode_label">"Choisir une bande radio"</string>
@@ -195,7 +193,7 @@
<string name="airplane_mode_turning_on">"Désactivation des connexions sans fil…"</string>
<string name="airplane_mode_turning_off">"Activation des connexions sans fil…"</string>
<string name="radio_controls_title">"Connexions sans fil"</string>
- <string name="radio_controls_summary">"Gérer le Wi-Fi, le mode Bluetooth, le mode Avion et les réseaux mobiles"</string>
+ <string name="radio_controls_summary">"Gérer le Wi-Fi, le mode Bluetooth, le mode avion et les réseaux mobiles"</string>
<string name="date_and_time_settings_title">"Date et heure"</string>
<string name="date_and_time_settings_summary">"Configurer la date, l\'heure, le fuseau horaire et les formats"</string>
<string name="date_time_auto">"Automatique"</string>
@@ -349,7 +347,7 @@
<string name="vibrate_summary">"Activer le vibreur pour les appels entrants"</string>
<string name="notification_sound_title">"Sonnerie de notification"</string>
<string name="notification_sound_summary">"Définir votre sonnerie de notification par défaut"</string>
- <string name="incoming_call_volume_title">"Volume des appels entrants"</string>
+ <string name="incoming_call_volume_title">"Volume de l\'appel entrant"</string>
<string name="notification_volume_title">"Volume des notifications"</string>
<string name="checkbox_notification_same_as_incoming_call">"Utiliser le volume des appels entrants pour les notifications"</string>
<string name="notification_sound_dialog_title">"Sélectionner une sonnerie de notification"</string>
@@ -405,11 +403,11 @@
<string name="model_number">"Numéro du modèle"</string>
<string name="baseband_version">"Version de bande de base"</string>
<string name="kernel_version">"Version du noyau"</string>
- <string name="build_number">"Numéro de build"</string>
+ <string name="build_number">"Numéro de version"</string>
<string name="device_info_not_available">"Non disponible"</string>
<string name="device_status_activity_title">"État"</string>
<string name="device_status">"État"</string>
- <string name="device_status_summary">"Code IMEI, numéro de téléphone, signal, etc."</string>
+ <string name="device_status_summary">"IIEM, numéro de téléphone, signal, etc."</string>
<string name="storage_settings_title">"Carte SD et mémoire"</string>
<string name="storage_settings_summary">"Retirer la carte SD, afficher la mémoire disponible"</string>
<string name="status_number">"Numéro de téléphone"</string>
@@ -470,8 +468,8 @@
<string name="master_clear_button_text">"Réinitialiser le téléphone"</string>
<string name="master_clear_final_desc">"Réinitialiser le téléphone et effacer toutes les données et applications ? Cette action ne peut être inversée."</string>
<string name="master_clear_final_button_text">"Tout effacer"</string>
- <string name="master_clear_gesture_prompt">"Saisissez votre schéma de déverrouillage"</string>
- <string name="master_clear_gesture_explanation">"Vous devez dessiner votre schéma de déverrouillage pour confirmer la réinitialisation du téléphone."</string>
+ <string name="master_clear_gesture_prompt">"Saisissez votre motif de déverrouillage"</string>
+ <string name="master_clear_gesture_explanation">"Vous devez dessiner votre motif de déverrouillage pour confirmer la réinitialisation du téléphone."</string>
<string name="master_clear_failed">"Les données n\'ont pas été réinitialisées car le service de nettoyage du système n\'est pas disponible."</string>
<string name="media_format_title">"Formater la carte SD."</string>
<string name="media_format_summary">"Permet d\'effacer toutes les données de la carte SD"</string>
@@ -482,20 +480,16 @@
<string name="media_format_gesture_prompt">"Créez votre schéma de déverrouillage"</string>
<string name="media_format_gesture_explanation">"Vous devez créer votre schéma de déverrouillage pour confirmer le format de la carte SD."</string>
<string name="call_settings_title">"Paramètres d\'appel"</string>
- <string name="call_settings_summary">"Configurer mess. vocale, transferts d\'appel, mises en attente, numéro de l\'appelant"</string>
+ <string name="call_settings_summary">"Configurer mess. vocale, transferts d\'appel, mises en attente, ID d\'appelant"</string>
<string name="network_settings_title">"Réseaux mobiles"</string>
<string name="network_settings_summary">"Définir les options d\'itinérance, réseaux, noms de points d\'accès"</string>
- <string name="location_title">"Mes sources de positionnement"</string>
+ <string name="location_title">"Sources pour Ma position"</string>
<string name="location_network_based">"Utiliser réseaux sans fil"</string>
<string name="location_networks_disabled">"Afficher position dans les applications (comme Google Maps)"</string>
<string name="location_neighborhood_level">"Position géographique déterminée par réseaux Wi-Fi et/ou mobile"</string>
<string name="location_gps">"Activer les satellites GPS"</string>
<string name="location_street_level">"Localisation précise au niveau de la rue lors du positionnement géographique (désélectionner pour économiser la batterie)"</string>
<string name="location_gps_disabled">"Localiser au niveau rue (requiert + de batterie et une vue dégagée)"</string>
- <string name="location_warning_title">"Votre lieu va être enregistré."</string>
- <string name="location_warning_message">"Autoriser le service de positionnement géographique de Google à collecter des données de lieu ne permettant pas de vous identifier personnellement. Les données seront collectées, quelles que soient les applications activées."</string>
- <string name="agree">"Accepter"</string>
- <string name="disagree">"Refuser"</string>
<string name="about_settings">"À propos du téléphone"</string>
<string name="about_settings_summary">"Informations légales, état du téléphone et version du logiciel"</string>
<string name="legal_information">"Informations légales"</string>
@@ -503,42 +497,42 @@
<string name="copyright_title">"Copyright"</string>
<string name="license_title">"Licence"</string>
<string name="terms_title">"Conditions d\'utilisation"</string>
- <string name="system_tutorial_list_item_title">"Didacticiel système"</string>
+ <string name="system_tutorial_list_item_title">"Didacticiel relatif au système"</string>
<string name="system_tutorial_list_item_summary">"Comment utiliser votre téléphone ?"</string>
<string name="settings_license_activity_title">"Licences open source"</string>
<string name="settings_license_activity_unavailable">"Un problème est survenu lors du chargement des licences."</string>
<string name="settings_license_activity_loading">"Chargement..."</string>
- <string name="lock_settings_title">"Schéma de déverrouillage de l\'écran"</string>
- <string name="lockpattern_change_lock_pattern_label">"Modifier le schéma de déverrouillage"</string>
- <string name="lockpattern_need_to_unlock">"Confirmer le schéma enregistré"</string>
+ <string name="lock_settings_title">"Motif de déverrouillage de l\'écran"</string>
+ <string name="lockpattern_change_lock_pattern_label">"Modifier le motif de déverrouillage"</string>
+ <string name="lockpattern_need_to_unlock">"Confirmer le motif enregistré"</string>
<string name="lockpattern_need_to_unlock_wrong">"Désolé. Merci de réessayer :"</string>
- <string name="lockpattern_recording_intro_header">"Dessiner un schéma de déverrouillage :"</string>
+ <string name="lockpattern_recording_intro_header">"Dessiner un motif de déverrouillage :"</string>
<string name="lockpattern_recording_intro_footer">"Appuyer sur Menu pour obtenir de l\'aide."</string>
<string name="lockpattern_recording_inprogress">"Ôtez le doigt lorsque vous avez terminé."</string>
<string name="lockpattern_recording_incorrect_too_short">"Reliez au moins <xliff:g id="NUMBER">%d</xliff:g> points. Veuillez réessayer :"</string>
- <string name="lockpattern_pattern_entered_header">"Schéma enregistré !"</string>
- <string name="lockpattern_need_to_confirm">"Redessinez le schéma pour confirmer :"</string>
- <string name="lockpattern_pattern_confirmed_header">"Votre nouveau schéma de déverrouillage :"</string>
+ <string name="lockpattern_pattern_entered_header">"Motif enregistré !"</string>
+ <string name="lockpattern_need_to_confirm">"Redessinez le motif pour confirmer :"</string>
+ <string name="lockpattern_pattern_confirmed_header">"Votre nouveau motif de déverrouillage :"</string>
<string name="lockpattern_confirm_button_text">"Confirmer"</string>
<string name="lockpattern_restart_button_text">"Redessiner"</string>
<string name="lockpattern_retry_button_text">"Réessayer"</string>
<string name="lockpattern_continue_button_text">"Continuer"</string>
- <string name="lockpattern_settings_title">"Schéma de déverrouillage"</string>
- <string name="lockpattern_settings_enable_title">"Demander un schéma"</string>
- <string name="lockpattern_settings_enable_summary">"Vous devez dessiner le schéma pour déverrouiller l\'écran."</string>
- <string name="lockpattern_settings_enable_visible_pattern_title">"Utiliser un schéma visible"</string>
+ <string name="lockpattern_settings_title">"Motif de déverrouillage"</string>
+ <string name="lockpattern_settings_enable_title">"Demander un motif"</string>
+ <string name="lockpattern_settings_enable_summary">"Vous devez dessiner le motif pour déverrouiller l\'écran."</string>
+ <string name="lockpattern_settings_enable_visible_pattern_title">"Utiliser un motif visible"</string>
<string name="lockpattern_settings_enable_tactile_feedback_title">"Commentaires tactiles"</string>
- <string name="lockpattern_settings_choose_lock_pattern">"Créer un schéma de déverrouillage"</string>
- <string name="lockpattern_settings_change_lock_pattern">"Modifier le schéma de déverrouillage"</string>
- <string name="lockpattern_settings_help_how_to_record">"Comment dessiner un schéma de déverrouillage :"</string>
+ <string name="lockpattern_settings_choose_lock_pattern">"Créer un motif de déverrouillage"</string>
+ <string name="lockpattern_settings_change_lock_pattern">"Modifier le motif de déverrouillage"</string>
+ <string name="lockpattern_settings_help_how_to_record">"Comment dessiner un motif de déverrouillage :"</string>
<string name="lockpattern_too_many_failed_confirmation_attempts_header">"Trop de tentatives échouées !"</string>
<string name="lockpattern_too_many_failed_confirmation_attempts_footer">"Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
<string name="skip_button_label">"Annuler"</string>
<string name="next_button_label">"Suivant"</string>
<string name="lock_title">"Sécurisation de votre téléphone"</string>
- <string name="lock_intro_message"><font size="17">"Protégez votre téléphone contre toute utilisation non autorisée en créant un schéma personnel de déverrouillage de l\'écran."\n<font height="17">\n</font><b>"1"</b>" L\'écran suivant vous présente un exemple de schéma "\n<font height="17">\n</font><b>"2"</b>" Lorsque vous êtes prêt, dessinez votre propre schéma de déverrouillage. Essayez différents schémas, mais reliez au moins quatre points."\n<font height="17">\n</font><b></b>"Reproduisez votre schéma pour confirmer."\n<font height="17">\n</font><b>"Pour commencer, sélectionnez \"Suivant\"."</b>\n<font height="3">\n</font>"Si vous ne souhaitez pas activer cette protection, sélectionnez \"Annuler\"."</font></string>
- <string name="lock_example_title">"Exemple de schéma"</string>
- <string name="lock_example_message">"Reliez au moins quatre points."\n" "\n"Sélectionnez \"Suivant\" pour créer votre propre schéma."</string>
+ <string name="lock_intro_message"><font size="17">"Protégez votre téléphone contre toute utilisation non autorisée en créant un motif personnel de déverrouillage de l\'écran."\n<font height="17">\n</font><b>"1"</b>" L\'écran suivant vous présente un exemple de motif. "\n<font height="17">\n</font><b>"2"</b>" Lorsque vous êtes prêt, dessinez votre propre motif de déverrouillage. Essayez différents motifs, mais reliez au moins quatre points."\n<font height="17">\n</font>"Reproduisez votre motif pour confirmer."\n<font height="17">\n</font><b>"Pour commencer, sélectionnez \"Suivant\"."</b>\n<font height="3">\n</font>"Si vous ne souhaitez pas activer cette protection, sélectionnez \"Annuler\"."</font></string>
+ <string name="lock_example_title">"Exemple de motif"</string>
+ <string name="lock_example_message">"Reliez au moins quatre points."\n" "\n"Sélectionnez \"Suivant\" lorsque vous voulez créer votre propre motif."</string>
<string name="manageapplications_settings_title">"Gérer les applications"</string>
<string name="manageapplications_settings_summary">"Gérer et supprimer les applications installées"</string>
<string name="applications_settings">"Applications"</string>
@@ -594,7 +588,7 @@
<string name="phone_language_summary">"Sélectionner la langue et le pays"</string>
<string name="auto_replace">"Remplacement auto"</string>
<string name="auto_replace_summary">"Corriger les mots mal saisis"</string>
- <string name="auto_caps">"Majuscules auto"</string>
+ <string name="auto_caps">"Majuscules automatiques"</string>
<string name="auto_caps_summary">"Mettre une majuscule en début de phrase"</string>
<string name="auto_punctuate">"Ponctuation automatique"</string>
<string name="hardkeyboard_category">"Paramètres du clavier physique"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index b7c41bb..24a7972 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -107,8 +107,6 @@
<string name="date_and_time">"Impostazioni data e ora"</string>
<string name="date_time_12_hour_sample">"1:00 pm"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <string name="date_time_changeTime_text">"Modifica ora"</string>
- <string name="date_time_changeDate_text">"Data"</string>
<string name="choose_timezone">"Seleziona fuso orario"</string>
<string name="display_preview_label">"Anteprima:"</string>
<string name="display_font_size_label">"Dimensioni carattere:"</string>
@@ -371,8 +369,8 @@
<string name="animations_summary_on">"Mostra l\'animazione durante l\'apertura e la chiusura di finestre"</string>
<string name="animations_summary_off">"Mostra l\'animazione durante l\'apertura e la chiusura di finestre"</string>
<string name="accelerometer_title">"Orientamento"</string>
- <string name="accelerometer_summary_on">"Cambia automaticamente quando il cellulare viene ruotato"</string>
- <string name="accelerometer_summary_off">"Cambia automatic. l\'orientamento quando il cell. viene ruotato"</string>
+ <string name="accelerometer_summary_on">"Cambia automaticamente l\'orientamento quando il cellulare viene ruotato"</string>
+ <string name="accelerometer_summary_off">"Cambia automaticamente l\'orientamento quando il cellulare viene ruotato"</string>
<string name="brightness">"Luminosità"</string>
<string name="brightness_summary">"Regola la luminosità dello schermo"</string>
<string name="screen_timeout">"Timeout schermo"</string>
@@ -492,10 +490,6 @@
<string name="location_gps">"Attiva satelliti GPS"</string>
<string name="location_street_level">"Accuratezza a livello stradale (deseleziona per risparmiare batteria)"</string>
<string name="location_gps_disabled">"Localizza a livello stradale (richiede più batteria e la vista del cielo)"</string>
- <string name="location_warning_title">"Consenso alla localizzazione"</string>
- <string name="location_warning_message">"Consenti al servizio di localizzazione di Google di raccogliere dati anonimi e aggregati sulla posizione. La raccolta dei dati verrà effettuata a prescindere dal fatto che ci siano o meno applicazioni attive."</string>
- <string name="agree">"Accetto"</string>
- <string name="disagree">"Non accetto"</string>
<string name="about_settings">"Info sul telefono"</string>
<string name="about_settings_summary">"Visualizza informazioni legali, stato del telefono, versione del software"</string>
<string name="legal_information">"Informazioni legali"</string>
@@ -503,7 +497,7 @@
<string name="copyright_title">"Copyright"</string>
<string name="license_title">"Licenza"</string>
<string name="terms_title">"Termini e condizioni"</string>
- <string name="system_tutorial_list_item_title">"Esercitazione"</string>
+ <string name="system_tutorial_list_item_title">"Esercitazione sul sistema"</string>
<string name="system_tutorial_list_item_summary">"Impara a utilizzare il tuo cellulare"</string>
<string name="settings_license_activity_title">"Licenze open source"</string>
<string name="settings_license_activity_unavailable">"Errore durante il caricamento delle licenze."</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index f793a67..b94265f 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -107,10 +107,6 @@
<string name="date_and_time">"日付形式"</string>
<string name="date_time_12_hour_sample">"1:00 PM"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
- <skip />
- <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
- <skip />
<string name="choose_timezone">"タイムゾーンの選択"</string>
<string name="display_preview_label">"プレビュー:"</string>
<string name="display_font_size_label">"フォントサイズ:"</string>
@@ -296,7 +292,7 @@
<string name="wifi_add_other_network">"Wi-Fiネットワークを追加"</string>
<string name="wifi_notify_open_networks">"ネットワークの通知"</string>
<string name="wifi_notify_open_networks_summary">"オープンネットワークが利用可能なときに通知する"</string>
- <string name="wifi_password_incorrect_error">"ネットワークキーまたはパスワードが正しくありません。入力し直してください。"</string>
+ <string name="wifi_password_incorrect_error">"入力したネットワークパスワードは正しくありません。再入力してください。"</string>
<string name="wifi_generic_connection_error">"ネットワーク接続に問題があります。やり直してください。"</string>
<string name="wifi_menu_advanced">"詳細設定"</string>
<string name="wifi_ip_settings_titlebar">"IP設定"</string>
@@ -494,10 +490,6 @@
<string name="location_gps">"GPS機能をONにする"</string>
<string name="location_street_level">"高精度測位(電池の消費を節約する場合はOFFにしてください)"</string>
<string name="location_gps_disabled">"高精度測位(電池消費増、電波が良好な場所で使用)"</string>
- <string name="location_warning_title">"位置情報についての同意"</string>
- <string name="location_warning_message">"Googleの位置情報サービスによる匿名化された位置データの収集および集計を許可します。データ収集はアプリケーション起動の有無にかかわらず行われます。"</string>
- <string name="agree">"同意する"</string>
- <string name="disagree">"同意しない"</string>
<string name="about_settings">"端末情報"</string>
<string name="about_settings_summary">"端末情報、規約、バージョン情報"</string>
<string name="legal_information">"法的情報"</string>
@@ -595,9 +587,9 @@
<string name="phone_language">"地域/言語を選択"</string>
<string name="phone_language_summary">"言語と地域の選択"</string>
<string name="auto_replace">"自動修正"</string>
- <string name="auto_replace_summary">"入力間違いを自動修正する"</string>
+ <string name="auto_replace_summary">"入力ミスを自動修正する"</string>
<string name="auto_caps">"自動大文字変換"</string>
- <string name="auto_caps_summary">"英字入力で文頭文字を大文字にする"</string>
+ <string name="auto_caps_summary">"先頭文字を大文字に変換する"</string>
<string name="auto_punctuate">"ピリオド自動挿入"</string>
<string name="hardkeyboard_category">"キーボードの設定"</string>
<string name="auto_punctuate_summary">"英語: Spaceキー2回でピリオド(.)を挿入"</string>
@@ -606,13 +598,13 @@
<string name="ime_security_warning">"この入力方法では入力したすべてのテキストの収集を許可します。収集されるテキストには個人情報データやクレジットカード番号などが含まれます。これはアプリケーション<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>によるものです。この入力方法を有効にしますか?"</string>
<string name="user_dict_settings_titlebar">"ユーザー辞書"</string>
<string name="user_dict_settings_title">"ユーザー辞書"</string>
- <string name="user_dict_settings_summary">"ユーザー辞書に単語を登録/削除する"</string>
+ <string name="user_dict_settings_summary">"ユーザー辞書への語句の追加と削除"</string>
<string name="user_dict_settings_add_menu_title">"追加"</string>
<string name="user_dict_settings_add_dialog_title">"辞書に追加"</string>
<string name="user_dict_settings_edit_dialog_title">"語句の編集"</string>
<string name="user_dict_settings_context_menu_edit_title">"編集"</string>
<string name="user_dict_settings_context_menu_delete_title">"削除"</string>
- <string name="user_dict_settings_empty_text">"ユーザー辞書に登録がありません。MENUから単語を登録してください。"</string>
+ <string name="user_dict_settings_empty_text">"ユーザー辞書に何も登録されていません。語句はメニューから登録できます。"</string>
<string name="testing">"テスト中"</string>
<string name="testing_phone_info">"携帯電話情報"</string>
<string name="testing_battery_info">"電池情報"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 93194fa..f813462 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -107,10 +107,6 @@
<string name="date_and_time">"날짜 및 시간 설정"</string>
<string name="date_time_12_hour_sample">"1:00 pm"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
- <skip />
- <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
- <skip />
<string name="choose_timezone">"표준시간대 선택"</string>
<string name="display_preview_label">"미리보기:"</string>
<string name="display_font_size_label">"글꼴 크기:"</string>
@@ -494,10 +490,6 @@
<string name="location_gps">"GPS 위성 사용"</string>
<string name="location_street_level">"도로 수준으로 정확하게 탐색(배터리를 절약하려면 선택 취소)"</string>
<string name="location_gps_disabled">"도로 수준으로 탐색(항공사진이 더해져 배터리 추가로 필요)"</string>
- <string name="location_warning_title">"위치 정보 수집에 동의"</string>
- <string name="location_warning_message">"Google의 위치 서비스가 익명의 위치 데이터를 광범위하게 수집합니다. 사용 중인 응용프로그램에 관계 없이 정보가 수집됩니다."</string>
- <string name="agree">"동의"</string>
- <string name="disagree">"동의하지 않음"</string>
<string name="about_settings">"전화기 정보"</string>
<string name="about_settings_summary">"법률 정보, 전화기 상태, 소프트웨어 버전 보기"</string>
<string name="legal_information">"법률정보"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 60e2620..af7bb4c 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -107,10 +107,6 @@
<string name="date_and_time">"Innstillinger for dato og tid"</string>
<string name="date_time_12_hour_sample">"1:00 pm"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
- <skip />
- <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
- <skip />
<string name="choose_timezone">"Velg tidssone"</string>
<string name="display_preview_label">"Forhåndsvisning:"</string>
<string name="display_font_size_label">"Skriftstørrelse:"</string>
@@ -342,7 +338,8 @@
<string name="sound_and_display_settings_summary">"Ringetoner, varsling, lysstyrke"</string>
<string name="silent_mode_title">"Stillemodus"</string>
<string name="silent_mode_summary">"Slå av alle lyder unntatt media og alarmer"</string>
- <string name="silent_mode_incl_alarm_summary">"Alle lyder unntatt media og alarmer er slått av"</string>
+ <!-- no translation found for silent_mode_incl_alarm_summary (2088830834182228458) -->
+ <skip />
<string name="ringtone_title">"Ringetone"</string>
<string name="ringtone_summary">"Standard ringetone for innkommende anrop"</string>
<string name="ring_volume_title">"Ringevolum"</string>
@@ -370,8 +367,10 @@
<string name="sync_settings_summary">"Applikasjoner som skal synkroniseres"</string>
<string name="display_settings">"Skjerminnstillinger"</string>
<string name="animations_title">"Animasjon"</string>
- <string name="animations_summary_on">"Vis animasjon under åpning og lukking av vinduer"</string>
- <string name="animations_summary_off">"Vis animasjon under åpning og lukking av vinduer"</string>
+ <!-- no translation found for animations_summary_on (8843613112130484436) -->
+ <skip />
+ <!-- no translation found for animations_summary_off (2777026828025551983) -->
+ <skip />
<string name="accelerometer_title">"Orientering"</string>
<string name="accelerometer_summary_on">"Bytt orientering automatisk når telefonen blir snudd"</string>
<string name="accelerometer_summary_off">"Bytt orientering automatisk når telefonen blir snudd"</string>
@@ -494,14 +493,6 @@
<string name="location_gps">"Bruk GPS-satellitter"</string>
<string name="location_street_level">"Nøyaktig til gatenivå (slå av for å spare batteri)"</string>
<string name="location_gps_disabled">"Finn plassering på gatenivå (bruker mer batteri, og trenger fri sikt til himmelen)"</string>
- <!-- no translation found for location_warning_title (788624242969337259) -->
- <skip />
- <!-- no translation found for location_warning_message (2455390825908728808) -->
- <skip />
- <!-- no translation found for agree (6288718671527758326) -->
- <skip />
- <!-- no translation found for disagree (6221069272309799230) -->
- <skip />
<string name="about_settings">"Om telefonen"</string>
<string name="about_settings_summary">"Vis juridisk informasjon, telefonstatus, programvareversjon"</string>
<string name="legal_information">"Juridisk informasjon"</string>
@@ -509,8 +500,10 @@
<string name="copyright_title">"Opphavsrett"</string>
<string name="license_title">"Lisens"</string>
<string name="terms_title">"Betingelser"</string>
- <string name="system_tutorial_list_item_title">"Systemguide"</string>
- <string name="system_tutorial_list_item_summary">"Lær å bruke telefonen"</string>
+ <!-- no translation found for system_tutorial_list_item_title (4315834755909579018) -->
+ <skip />
+ <!-- no translation found for system_tutorial_list_item_summary (3861815254521030201) -->
+ <skip />
<string name="settings_license_activity_title">"Åpen kildekode-lisenser"</string>
<string name="settings_license_activity_unavailable">"Kunne ikke hente lisensene."</string>
<string name="settings_license_activity_loading">"henter…"</string>
@@ -607,7 +600,8 @@
<string name="auto_punctuate_summary">"Trykk mellomromstasten to ganger for å skrive punktum"</string>
<string name="show_password">"Synlige passord"</string>
<string name="show_password_summary">"Vis passord mens de skrives inn"</string>
- <string name="ime_security_warning">"Inndatametoden har mulighet til å samle inn all tekst du skriver, inkludert personlige data som passord og kredittkortnummer. Den kommer fra applikasjonen <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Aktiver inndatametoden?"</string>
+ <!-- no translation found for ime_security_warning (3458652708716006477) -->
+ <skip />
<string name="user_dict_settings_titlebar">"Ordliste"</string>
<string name="user_dict_settings_title">"Ordliste"</string>
<string name="user_dict_settings_summary">"Legg til og fjern ord fra ordlisten"</string>
@@ -634,7 +628,8 @@
<string name="quick_launch_display_mode_shortcuts">"Snarveier"</string>
<string name="input_methods_settings_title">"Skriving av tekst"</string>
<string name="input_methods_settings_summary">"Innstillinger for skriving av tekst"</string>
- <string name="input_methods_settings_label_format">"Innstillinger for <xliff:g id="IME_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for input_methods_settings_label_format (6002887604815693322) -->
+ <skip />
<string name="onscreen_keyboard_settings_summary">"Innstillinger for skjermtastatur"</string>
<string name="builtin_keyboard_settings_title">"Enhetstastatur"</string>
<string name="builtin_keyboard_settings_summary">"Innstillinger for innebygget tastatur"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index a89c8a9..3a3e40a 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -107,8 +107,6 @@
<string name="date_and_time">"Datum- en tijdinstellingen"</string>
<string name="date_time_12_hour_sample">"13:00 uur"</string>
<string name="date_time_24_hour_sample">"01:00:00 PM"</string>
- <string name="date_time_changeTime_text">"Tijd wijzigen"</string>
- <string name="date_time_changeDate_text">"datum"</string>
<string name="choose_timezone">"Tijdzone selecteren"</string>
<string name="display_preview_label">"Voorbeeld:"</string>
<string name="display_font_size_label">"Lettergrootte:"</string>
@@ -209,7 +207,7 @@
<string name="zone_list_menu_sort_alphabetically">"Alfabetisch sorteren"</string>
<string name="zone_list_menu_sort_by_timezone">"Sorteren op tijdzone"</string>
<string name="security_settings_title">"Beveiliging en locatie"</string>
- <string name="security_settings_summary">"Mijn locatie instellen, scherm ontgrendelen en SIM-kaart vergrendelen"</string>
+ <string name="security_settings_summary">"\'Mijn locatie\' instellen, scherm ontgrendelen en SIM-kaart vergrendelen"</string>
<string name="security_passwords_title">"Wachtwoorden"</string>
<string name="bluetooth_quick_toggle_title">"Bluetooth"</string>
<string name="bluetooth_quick_toggle_summary">"Bluetooth inschakelen"</string>
@@ -355,7 +353,7 @@
<string name="notification_sound_dialog_title">"Beltoon voor meldingen selecteren"</string>
<string name="media_volume_title">"Mediavolume"</string>
<string name="media_volume_summary">"Volume voor muziek en video\'s instellen"</string>
- <string name="dtmf_tone_enable_title">"Aanraaktonen"</string>
+ <string name="dtmf_tone_enable_title">"Hoorbare aanraaktonen"</string>
<string name="dtmf_tone_enable_summary_on">"Tonen afspelen bij gebruik van toetsenblok"</string>
<string name="dtmf_tone_enable_summary_off">"Tonen afspelen bij gebruik van toetsenblok"</string>
<string name="sound_effects_enable_title">"Hoorbare selectie"</string>
@@ -490,12 +488,8 @@
<string name="location_networks_disabled">"Locatie in toepassingen (zoals Maps) bekijken via draadloze netwerken"</string>
<string name="location_neighborhood_level">"Locatie bepaald door Wi-Fi en/of mobiele netwerken"</string>
<string name="location_gps">"GPS-satellieten inschakelen"</string>
- <string name="location_street_level">"Locatie tot op straatniveau (uit om acculading te sparen)"</string>
- <string name="location_gps_disabled">"Locatie bepalen tot op straatniveau (meer stroom nodig en luchtweergave)"</string>
- <string name="location_warning_title">"Locatietoestemming"</string>
- <string name="location_warning_message">"Toestaan dat de locatieservice van Google anonieme, getotaliseerde locatiegegevens verzamelt. De gegevens worden verzameld, ongeacht of er toepassingen actief zijn."</string>
- <string name="agree">"Akkoord"</string>
- <string name="disagree">"Niet akkoord"</string>
+ <string name="location_street_level">"Bij locatie bepalen nauwkeurig tot op straatniveau (deselecteren om acculading te sparen)"</string>
+ <string name="location_gps_disabled">"Locatie bepalen tot op straatniveau (meer stroom nodig en weergave van lucht)"</string>
<string name="about_settings">"Over de telefoon"</string>
<string name="about_settings_summary">"Juridische info, telefoonstatus, softwareversie weergeven"</string>
<string name="legal_information">"Juridische informatie"</string>
@@ -503,7 +497,7 @@
<string name="copyright_title">"Auteursrecht"</string>
<string name="license_title">"Licentie"</string>
<string name="terms_title">"Algemene voorwaarden"</string>
- <string name="system_tutorial_list_item_title">"Systeemhandleiding"</string>
+ <string name="system_tutorial_list_item_title">"Systeemzelfstudie"</string>
<string name="system_tutorial_list_item_summary">"Meer informatie over het gebruik van uw telefoon"</string>
<string name="settings_license_activity_title">"Open-sourcelicenties"</string>
<string name="settings_license_activity_unavailable">"Er is een probleem bij het laden van de licenties."</string>
@@ -536,7 +530,7 @@
<string name="skip_button_label">"Annuleren"</string>
<string name="next_button_label">"Volgende"</string>
<string name="lock_title">"Uw telefoon beveiligen"</string>
- <string name="lock_intro_message"><font size="17">"Beveilig uw telefoon tegen ongeoorloofd gebruik door het instellen van een persoonlijk schermontgrendelingspatroon. "\n<font height="17">\n</font><b>"1"</b>" Op het volgende scherm ziet u hoe een voorbeeldpatroon wordt getekend. "\n<font height="17">\n</font><b>"2"</b>" Teken uw eigen persoonlijke ontgrendelingspatroon als het voorbeeld is voltooid. U kunt verschillende patronen uitproberen, maar u moet minimaal vier punten met elkaar verbinden. "\n<font height="17">\n</font><b>"3"</b>" Teken uw patroon nogmaals ter bevestiging. "\n<font height="17">\n</font><b>"Bent u er klaar voor? Selecteer \'Volgende\'"</b>". "\n<font height="3">\n</font>"Als u uw telefoon niet wilt beveiligen, selecteert u \'Annuleren\'."</font></string>
+ <string name="lock_intro_message"><font size="17">"Beveilig uw telefoon tegen ongeoorloofd gebruik door het instellen van een persoonlijk schermontgrendelingspatroon. "\n<font height="17">\n</font><b>"1"</b>" Op het volgende scherm ziet u hoe een voorbeeldpatroon wordt getekend. "\n<font height="17">\n</font><b>"2"</b>" Teken uw eigen persoonlijke deblokkeringspatroon als het voorbeeld is voltooid. U kunt verschillende patronen uitproberen, maar u moet minimaal vier punten met elkaar verbinden. "\n<font height="17">\n</font><b>"3"</b>" Teken uw patroon nogmaals ter bevestiging. "\n<font height="17">\n</font><b>"Bent u er klaar voor? Selecteer \'Volgende\'"</b>". "\n<font height="3">\n</font>"Als u uw telefoon niet wilt beveiligen, selecteert u \'Annuleren\'."</font></string>
<string name="lock_example_title">"Voorbeeldpatroon"</string>
<string name="lock_example_message">"Verbind minimaal vier punten. "\n" "\n"Selecteer \'Volgende\' als u klaar bent om uw eigen patroon te tekenen."</string>
<string name="manageapplications_settings_title">"Toepassingen beheren"</string>
@@ -598,13 +592,13 @@
<string name="auto_caps_summary">"Eerste letters in zinnen met hoofdletter"</string>
<string name="auto_punctuate">"Automatische interpunctie"</string>
<string name="hardkeyboard_category">"Instellingen voor vast toetsenbord"</string>
- <string name="auto_punctuate_summary">"Druk twee keer op de spatiebalk om een punt (.) in te voegen"</string>
+ <string name="auto_punctuate_summary">"Druk twee keer op de spatiebalk om \'.\' in te voegen"</string>
<string name="show_password">"Zichtbare wachtwoorden"</string>
<string name="show_password_summary">"Wachtwoord weergeven tijdens het typen"</string>
<string name="ime_security_warning">"Deze invoermethode verzamelt mogelijk alle tekst die u typt, inclusief persoonlijke gegevens zoals wachtwoorden en creditcardnummers. De methode is afkomstig uit de toepassing <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Deze invoermethode inschakelen?"</string>
<string name="user_dict_settings_titlebar">"Gebruikerswoordenboek"</string>
<string name="user_dict_settings_title">"Gebruikerswoordenboek"</string>
- <string name="user_dict_settings_summary">"Woorden toevoegen en verwijderen"</string>
+ <string name="user_dict_settings_summary">"Woorden toevoegen aan en verwijderen uit gebruikerswoordenboek"</string>
<string name="user_dict_settings_add_menu_title">"Toevoegen"</string>
<string name="user_dict_settings_add_dialog_title">"Toevoegen aan woordenboek"</string>
<string name="user_dict_settings_edit_dialog_title">"Woord bewerken"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 83c18cb..ba3ed98 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -107,8 +107,6 @@
<string name="date_and_time">"Ustawienia daty i czasu"</string>
<string name="date_time_12_hour_sample">"1:00 (po południu)"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <string name="date_time_changeTime_text">"Zmień godzinę"</string>
- <string name="date_time_changeDate_text">"Data"</string>
<string name="choose_timezone">"Wybierz strefę czasową"</string>
<string name="display_preview_label">"Podgląd:"</string>
<string name="display_font_size_label">"Rozmiar czcionki:"</string>
@@ -199,8 +197,8 @@
<string name="date_and_time_settings_title">"Data i czas"</string>
<string name="date_and_time_settings_summary">"Ustaw format daty, czasu i strefę czasową"</string>
<string name="date_time_auto">"Automatycznie"</string>
- <string name="date_time_auto_summaryOn">"Używaj wartości dostarczonych przez sieć"</string>
- <string name="date_time_auto_summaryOff">"Używaj informacji dostarczonych przez operatora"</string>
+ <string name="date_time_auto_summaryOn">"Skorzystaj z wartości dostarczonych przez sieć"</string>
+ <string name="date_time_auto_summaryOff">"Skorzystaj z informacji dostarczonych przez operatora"</string>
<string name="date_time_24hour">"Format 24-godzinny"</string>
<string name="date_time_set_time">"Ustaw czas"</string>
<string name="date_time_set_timezone">"Wybierz strefę czasową"</string>
@@ -292,7 +290,7 @@
<string name="wifi_save_config">"Zapisz"</string>
<string name="wifi_password_unchanged">"(niezmienione)"</string>
<string name="wifi_add_other_network">"Dodaj sieć Wi-Fi"</string>
- <string name="wifi_notify_open_networks">"Powiadomienie o sieci"</string>
+ <string name="wifi_notify_open_networks">"Powiadomienie sieciowe"</string>
<string name="wifi_notify_open_networks_summary">"Powiadom mnie, gdy będę w zasięgu otwartej sieci"</string>
<string name="wifi_password_incorrect_error">"Wprowadzone hasło sieci jest nieprawidłowe. Spróbuj ponownie."</string>
<string name="wifi_generic_connection_error">"Wystąpił problem podczas łączenia z siecią. Spróbuj ponownie."</string>
@@ -403,9 +401,9 @@
<string name="system_update_settings_list_item_summary">"Sprawdź aktualizacje systemu"</string>
<string name="firmware_version">"Wersja oprogramowania"</string>
<string name="model_number">"Numer modelu"</string>
- <string name="baseband_version">"Wersja pasma podstawowego"</string>
+ <string name="baseband_version">"Pasmo podstawowe"</string>
<string name="kernel_version">"Wersja jądra"</string>
- <string name="build_number">"Numer kompilacji"</string>
+ <string name="build_number">"Numer wersji"</string>
<string name="device_info_not_available">"Niedostępna"</string>
<string name="device_status_activity_title">"Informacje o telefonie"</string>
<string name="device_status">"Informacje o telefonie"</string>
@@ -427,9 +425,9 @@
<string name="internal_memory">"Pamięć wewnętrzna telefonu"</string>
<string name="sd_memory">"Karta SD"</string>
<string name="memory_available">"Dostępne miejsce"</string>
- <string name="memory_size">"Całkowita pojemność"</string>
- <string name="sd_eject">"Odłącz kartę SD"</string>
- <string name="sd_eject_summary">"Odłącz kartę SD, aby bezpiecznie ją usunąć"</string>
+ <string name="memory_size">"Łączna pojemność"</string>
+ <string name="sd_eject">"Odmontuj kartę SD"</string>
+ <string name="sd_eject_summary">"Odmontuj kartę SD, aby bezpiecznie ją usunąć"</string>
<string name="sd_format">"Formatuj kartę SD"</string>
<string name="sd_format_summary">"Formatuj (wymaż) kartę SD"</string>
<string name="sd_unavailable">"Niedostępna"</string>
@@ -479,23 +477,19 @@
<string name="media_format_button_text">"Formatuj kartę SD"</string>
<string name="media_format_final_desc">"Czy sformatować kartę SD i wymazać wszystkie multimedia? Nie można cofnąć tej akcji!"</string>
<string name="media_format_final_button_text">"Wymaż wszystko"</string>
- <string name="media_format_gesture_prompt">"Narysuj wzór odblokowania"</string>
- <string name="media_format_gesture_explanation">"Aby potwierdzić formatowanie karty SD, należy narysować swój wzór odblokowania."</string>
+ <string name="media_format_gesture_prompt">"Narysuj wzorzec odblokowania"</string>
+ <string name="media_format_gesture_explanation">"Aby potwierdzić formatowanie karty SD, należy narysować swój wzorzec do odblokowania."</string>
<string name="call_settings_title">"Ustawienia połączeń"</string>
- <string name="call_settings_summary">"Poczta głosowa, przekierowania połączeń, poł. oczekujące, ID rozmówcy"</string>
+ <string name="call_settings_summary">"Poczta głosowa, przekierowania połączeń, poł. oczekujące, ID dzwoniącego"</string>
<string name="network_settings_title">"Sieci komórkowe"</string>
<string name="network_settings_summary">"Ustaw opcje roamingu, sieci, nazw APN"</string>
<string name="location_title">"Źródło Mojej lokalizacji"</string>
<string name="location_network_based">"Użyj sieci Wi-Fi"</string>
<string name="location_networks_disabled">"Zobacz położenie w aplikacjach (takich jak Mapy), korzystając z sieci bezprzewodowych"</string>
- <string name="location_neighborhood_level">"Położenie określane jest za pomocą Wi-Fi i/lub sieci komórkowych"</string>
+ <string name="location_neighborhood_level">"Położenie określane jest za pomocą Wi-Fi i/lub sieci komórkowych."</string>
<string name="location_gps">"Użyj satelit GPS"</string>
<string name="location_street_level">"Ustalanie położenia z dokładnością do ulicy (wyłącz, aby oszczędzać baterię)"</string>
<string name="location_gps_disabled">"Podaje dokładne położenie (zużywa więcej baterii, działa na zewnątrz)"</string>
- <string name="location_warning_title">"Zgoda na usługę lokalizacji"</string>
- <string name="location_warning_message">"Zezwól usłudze lokalizacji Google na zbieranie anonimowych, zbiorczych danych o lokalizacji. Zbieranie danych będzie się odbywać bez względu na to, czy aktywne są aplikacje."</string>
- <string name="agree">"Zgadzam się"</string>
- <string name="disagree">"Nie zgadzam się"</string>
<string name="about_settings">"Informacje o telefonie"</string>
<string name="about_settings_summary">"Wyświetl informacje prawne, stan telefonu, wersję oprogramowania"</string>
<string name="legal_information">"Informacje prawne"</string>
@@ -536,7 +530,7 @@
<string name="skip_button_label">"Anuluj"</string>
<string name="next_button_label">"Dalej"</string>
<string name="lock_title">"Zabezpieczanie telefonu"</string>
- <string name="lock_intro_message"><font size="17">"Chroń swój telefon przed nieuprawnionym użyciem przez utworzenie osobistego wzoru odblokowania ekranu. "\n<font height="17">\n</font><b>"1"</b>" Obejrzyj rysowanie przykładowego wzoru na następnym ekranie. "\n<font height="17">\n</font><b>"2"</b>" Następnie narysuj swój własny wzór odblokowania. Eksperymentuj z różnymi wzorami, ale połącz co najmniej 4 punkty. "\n<font height="17">\n</font><b>"3"</b>" Narysuj swój wzór ponownie dla potwierdzenia. "\n<font height="17">\n</font><b>"Możemy zaczynać? Wybierz „Dalej”"</b>". "\n<font height="3">\n</font>"Aby zrezygnować z ustawiania blokady, wybierz „Anuluj”."</font></string>
+ <string name="lock_intro_message"><font size="17">"Chroń swój telefon przed nieuprawnionym użyciem przez stworzenie osobistego wzoru odblokowania ekranu. "\n<font height="17">\n</font><b>"1"</b>" Obejrzyj rysowanie przykładowego wzoru na następnym ekranie. "\n<font height="17">\n</font><b>"2"</b>" Następnie narysuj swój własny wzór odblokowania. Eksperymentuj z różnymi wzorami, ale połącz co najmniej 4 punkty. "\n<font height="17">\n</font><b>"3"</b>" Narysuj swój wzór ponownie dla potwierdzenia. "\n<font height="17">\n</font><b>"Możemy zaczynać? Wybierz „Dalej”"</b>". "\n<font height="3">\n</font>"Aby zrezygnować z ustawiania blokady, wybierz „Anuluj”."</font></string>
<string name="lock_example_title">"Przykładowy wzór"</string>
<string name="lock_example_message">"Połącz co najmniej cztery kropki."\n" "\n"Wybierz polecenie „Dalej”, aby narysować własny wzór."</string>
<string name="manageapplications_settings_title">"Zarządzaj aplikacjami"</string>
@@ -595,10 +589,10 @@
<string name="auto_replace">"Autokorekta"</string>
<string name="auto_replace_summary">"Poprawiaj błędnie wpisane słowa"</string>
<string name="auto_caps">"Wielka litera po kropce"</string>
- <string name="auto_caps_summary">"Zaczynaj zdania wielką literą"</string>
+ <string name="auto_caps_summary">"Zdanie zaczynaj wielką literą"</string>
<string name="auto_punctuate">"Łatwa interpunkcja"</string>
<string name="hardkeyboard_category">"Ustawienia klawiatury fizycznej"</string>
- <string name="auto_punctuate_summary">"Naciśnij dwukrotnie klawisz spacji, aby wstawić kropkę"</string>
+ <string name="auto_punctuate_summary">"Naciśnij klawisz spacji dwukrotnie, aby wstawić kropkę."</string>
<string name="show_password">"Widoczne hasła"</string>
<string name="show_password_summary">"Pokazuj hasło podczas wpisywania"</string>
<string name="ime_security_warning">"Ta metoda wprowadzania może gromadzić cały wpisywany tekst, w tym dane osobiste, takie jak hasła i numery kart kredytowych. Ta metoda pochodzi z aplikacji <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Włączyć tę metodę wprowadzania?"</string>
diff --git a/res/values-pt/arrays.xml b/res/values-pt/arrays.xml
new file mode 100644
index 0000000..59c9049
--- /dev/null
+++ b/res/values-pt/arrays.xml
@@ -0,0 +1,81 @@
+<?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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="timezone_filters">
+ <item>"América"</item>
+ <item>"Europa"</item>
+ <item>"África"</item>
+ <item>"Ásia"</item>
+ <item>"Austrália"</item>
+ <item>"Pacífico"</item>
+ <item>"Tudo"</item>
+ </string-array>
+ <string-array name="screen_timeout_entries">
+ <item>"15 segundos"</item>
+ <item>"30 segundos"</item>
+ <item>"1 minuto"</item>
+ <item>"2 minutos"</item>
+ <item>"10 minutos"</item>
+ <item>"Nunca esgotar o tempo"</item>
+ </string-array>
+ <!-- no translation found for tts_rate_entries:0 (6041212618892492920) -->
+ <!-- no translation found for tts_rate_entries:1 (2361722960903353554) -->
+ <!-- no translation found for tts_rate_entries:2 (1145554631248513562) -->
+ <!-- no translation found for tts_rate_entries:3 (7553665153391107454) -->
+ <!-- no translation found for tts_rate_entries:4 (2538100882620724753) -->
+ <!-- no translation found for tts_pitch_entries:0 (7526050907652687351) -->
+ <!-- no translation found for tts_pitch_entries:1 (2692137425242433765) -->
+ <!-- no translation found for tts_pitch_entries:2 (3332408460740717754) -->
+ <!-- no translation found for tts_pitch_entries:3 (4907380534957572531) -->
+ <!-- no translation found for tts_pitch_entries:4 (4699640516390840297) -->
+ <!-- no translation found for wifi_security_entries:3 (6303607119537134095) -->
+ <!-- no translation found for wifi_security_entries:4 (1977424472734732392) -->
+ <!-- no translation found for wifi_security_entries:5 (5185669984217684689) -->
+ <!-- no translation found for wifi_security_entries:6 (8643206823103498303) -->
+ <!-- no translation found for wifi_security_without_auto_entries:2 (2296204649410509235) -->
+ <!-- no translation found for wifi_security_without_auto_entries:3 (8928468573279595315) -->
+ <!-- no translation found for wifi_security_without_auto_entries:4 (8319241197948974314) -->
+ <!-- no translation found for wifi_security_without_auto_entries:5 (2222409752754955757) -->
+ <string-array name="wifi_wep_type">
+ <item>"Automático"</item>
+ <item>"WEP ASCII"</item>
+ <item>"WEP hexadecimal"</item>
+ </string-array>
+ <!-- no translation found for wifi_sleep_policy_entries:0 (3804733751095821976) -->
+ <!-- no translation found for wifi_sleep_policy_entries:1 (1549288661423279207) -->
+ <!-- no translation found for wifi_sleep_policy_entries:2 (1986753720941888596) -->
+ <!-- no translation found for battery_history_type_spinner:0 (2193799199027871385) -->
+ <!-- no translation found for battery_history_type_spinner:1 (6401018715947316517) -->
+ <!-- no translation found for battery_history_type_spinner:2 (188092590354892392) -->
+ <!-- no translation found for battery_history_type_spinner:3 (8414109131222049141) -->
+ <!-- no translation found for battery_history_type_spinner:4 (1327904325081257093) -->
+ <!-- no translation found for battery_history_type_spinner:5 (4832254146664706277) -->
+ <!-- no translation found for battery_history_which_spinner:0 (3451981114763440074) -->
+ <!-- no translation found for battery_history_which_spinner:1 (166936313535197598) -->
+ <!-- no translation found for battery_history_which_spinner:2 (4793941382744963893) -->
+ <!-- no translation found for usage_stats_display_order_types:0 (9077371706468756228) -->
+ <!-- no translation found for usage_stats_display_order_types:1 (1908750532762193304) -->
+ <!-- no translation found for usage_stats_display_order_types:2 (1213951670006606353) -->
+ <!-- no translation found for wifi_eap_entries:0 (8615575908717909498) -->
+ <!-- no translation found for wifi_eap_entries:1 (8667872640594311615) -->
+ <!-- no translation found for wifi_eap_entries:2 (7182812872984827322) -->
+ <!-- no translation found for wifi_phase2_entries:0 (1818786254010764570) -->
+ <!-- no translation found for wifi_phase2_entries:1 (6189918678874123056) -->
+ <!-- no translation found for wifi_phase2_entries:2 (1524112260493662517) -->
+ <!-- no translation found for wifi_phase2_entries:3 (1586767102985419413) -->
+ <!-- no translation found for wifi_phase2_entries:4 (8651992560135239389) -->
+</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
new file mode 100644
index 0000000..724dcf1
--- /dev/null
+++ b/res/values-pt/strings.xml
@@ -0,0 +1,929 @@
+<?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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="device_info_default">"Desconhecido"</string>
+ <string name="turn_on_radio">"Ligar rádio"</string>
+ <string name="turn_off_radio">"Desligar rádio"</string>
+ <string name="turn_on_qxdm">"Ativar registro do QXDM SD"</string>
+ <string name="turn_off_qxdm">"Desativar registro do QXDM SD"</string>
+ <string name="radioInfo_menu_viewADN">"Exibir catálogo de endereços do SIM"</string>
+ <string name="radioInfo_menu_viewFDN">"Exibir números de discagem fixa"</string>
+ <string name="radioInfo_menu_viewSDN">"Exibir números de discagem de serviço"</string>
+ <string name="radioInfo_menu_getPDP">"Obter lista PDP"</string>
+ <string name="radioInfo_menu_enableData">"Ativar conexão de dados"</string>
+ <string name="radioInfo_menu_disableData">"Desativar conexão de dados"</string>
+ <string name="radioInfo_menu_enableDataOnBoot">"Ativar dados na inicialização"</string>
+ <string name="radioInfo_menu_disableDataOnBoot">"Desativar dados na inicialização"</string>
+ <string name="radioInfo_service_in">"Em uso"</string>
+ <string name="radioInfo_service_out">"Fora de serviço"</string>
+ <string name="radioInfo_service_emergency">"Apenas chamadas de emergência"</string>
+ <string name="radioInfo_service_off">"Rádio desligado"</string>
+ <string name="radioInfo_roaming_in">"Roaming"</string>
+ <string name="radioInfo_roaming_not">"Não há roaming"</string>
+ <string name="radioInfo_phone_idle">"Ocioso"</string>
+ <string name="radioInfo_phone_ringing">"Tocando"</string>
+ <string name="radioInfo_phone_offhook">"Chamada em andamento"</string>
+ <string name="radioInfo_data_disconnected">"Desconectado"</string>
+ <string name="radioInfo_data_connecting">"Conectando"</string>
+ <string name="radioInfo_data_connected">"Conectado"</string>
+ <string name="radioInfo_data_suspended">"Suspenso"</string>
+ <string name="radioInfo_unknown">"desconhecido"</string>
+ <string name="radioInfo_display_packets">"pkts"</string>
+ <string name="radioInfo_display_bytes">"bytes"</string>
+ <string name="radioInfo_display_dbm">"dBm"</string>
+ <string name="radioInfo_display_asu">"asu"</string>
+ <string name="radioInfo_lac">"LAC"</string>
+ <string name="radioInfo_cid">"CID"</string>
+ <string name="sdcard_unmount">"Desmontar cartão SD"</string>
+ <!-- no translation found for sdcard_format (362497552060004057) -->
+ <skip />
+ <string name="small_font">"Pequeno"</string>
+ <string name="medium_font">"Meio"</string>
+ <string name="large_font">"Grande"</string>
+ <string name="font_size_save">"OK"</string>
+ <string name="sdcard_setting">"Cartão SD"</string>
+ <string name="battery_info_status_label">"Status da bateria:"</string>
+ <string name="battery_info_scale_label">"Escala da bateria:"</string>
+ <string name="battery_info_level_label">"Nível da bateria:"</string>
+ <string name="battery_info_health_label">"Saúde da bateria:"</string>
+ <string name="battery_info_technology_label">"Tecnologia da bateria:"</string>
+ <string name="battery_info_voltage_label">"Tensão da bateria:"</string>
+ <string name="battery_info_voltage_units">"mV"</string>
+ <string name="battery_info_temperature_label">"Temperatura da bateria:"</string>
+ <string name="battery_info_temperature_units">"° C"</string>
+ <string name="battery_info_uptime">"Tempo desde a inicialização:"</string>
+ <string name="battery_info_awake_battery">"Tempo de atividade usando a bateria:"</string>
+ <string name="battery_info_awake_plugged">"Tempo de atividade durante a carga:"</string>
+ <string name="battery_info_screen_on">"Tela Tempo LIGADA:"</string>
+ <string name="battery_info_status_unknown">"Desconhecido"</string>
+ <string name="battery_info_status_charging">"Carregando"</string>
+ <string name="battery_info_status_charging_ac">"(CA)"</string>
+ <string name="battery_info_status_charging_usb">"(USB)"</string>
+ <string name="battery_info_status_discharging">"Descarregando"</string>
+ <string name="battery_info_status_not_charging">"Não está carregando"</string>
+ <string name="battery_info_status_full">"Cheia"</string>
+ <string name="battery_info_health_unknown">"Desconhecido"</string>
+ <string name="battery_info_health_good">"Bom"</string>
+ <string name="battery_info_health_overheat">"Superaquecimento"</string>
+ <string name="battery_info_health_dead">"Inativo"</string>
+ <string name="battery_info_health_over_voltage">"Sobre tensão"</string>
+ <string name="battery_info_health_unspecified_failure">"Erro desconhecido"</string>
+ <string name="bluetooth">"Bluetooth"</string>
+ <string name="bluetooth_visibility">"Detectável"</string>
+ <string name="bluetooth_is_discoverable">"Detectável por <xliff:g id="DISCOVERABLE_TIME_PERIOD">%1$s</xliff:g> segundos…"</string>
+ <string name="bluetooth_not_discoverable">"Fazer com que o dispositivo possa ser localizado"</string>
+ <string name="bluetooth_devices">"Dispositivos bluetooth"</string>
+ <string name="bluetooth_device_name">"Nome do dispositivo"</string>
+ <string name="bluetooth_name_not_set">"Nenhum nome definido, usando nome da conta"</string>
+ <string name="bluetooth_scan_for_devices">"Examinar em busca de dispositivos"</string>
+ <string name="bluetooth_disconnect_blank">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> será desconectado."</string>
+ <string name="bluetooth_connected">"Conectado"</string>
+ <string name="bluetooth_disconnected">"Desconectado"</string>
+ <string name="bluetooth_disconnecting">"Desconectando…"</string>
+ <string name="bluetooth_connecting">"Conectando…"</string>
+ <!-- no translation found for bluetooth_unknown (644716244548801421) -->
+ <skip />
+ <string name="bluetooth_not_connected">"Parear com este dispositivo"</string>
+ <string name="bluetooth_pairing">"Pareando…"</string>
+ <!-- no translation found for bluetooth_paired (1247541089000057726) -->
+ <skip />
+ <string name="bluetooth_device">"viva-voz/headset"</string>
+ <string name="progress_scanning">"Examinando"</string>
+ <string name="bluetooth_notif_ticker">"Solicitação de pareamento de Bluetooth"</string>
+ <string name="bluetooth_notif_title">"Solicitação de pareamento"</string>
+ <string name="bluetooth_notif_message">"Selecionar para fazer pareamento "</string>
+ <string name="date_and_time">"Configurações de data & hora"</string>
+ <string name="date_time_12_hour_sample">"13:00"</string>
+ <string name="date_time_24_hour_sample">"13:00"</string>
+ <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
+ <skip />
+ <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
+ <skip />
+ <string name="choose_timezone">"Selecione fuso horário"</string>
+ <string name="display_preview_label">"Visualização:"</string>
+ <string name="display_font_size_label">"Tamanho da fonte:"</string>
+ <!-- no translation found for intent_sender_data_label (6332324780477289261) -->
+ <skip />
+ <string name="intent_sender_sendbroadcast_text">"Enviar <xliff:g id="BROADCAST">broadcast</xliff:g>"</string>
+ <string name="intent_sender_action_label">"<xliff:g id="ACTION">Action</xliff:g>:"</string>
+ <string name="intent_sender_startactivity_text">"Iniciar<xliff:g id="ACTIVITY">activity</xliff:g>"</string>
+ <string name="intent_sender_resource_label">"<xliff:g id="RESOURCE">Resource</xliff:g>:"</string>
+ <string name="intent_sender_account_label">"Conta:"</string>
+ <string name="proxy_clear_text">"Limpar"</string>
+ <string name="proxy_port_label">"Porta"</string>
+ <string name="proxy_defaultView_text">"Restaurar padrão"</string>
+ <string name="proxy_action_text">"Salvar"</string>
+ <string name="proxy_hostname_label">"Nome do host"</string>
+ <string name="proxy_error">"Atenção"</string>
+ <string name="proxy_error_dismiss">"OK"</string>
+ <string name="proxy_error_invalid_host">"O nome do host digitado não é válido."</string>
+ <string name="proxy_error_empty_port">"Você deve preencher o campo da porta."</string>
+ <string name="proxy_error_empty_host_set_port">"O campo da porta deverá ficar vazio se o campo do host estiver vazio."</string>
+ <string name="proxy_error_invalid_port">"A porta digitada não é válida."</string>
+ <string name="radio_info_signal_location_label">"Local:"</string>
+ <string name="radio_info_neighboring_location_label">"CID próximo:"</string>
+ <string name="radio_info_data_attempts_label">"Tentativas de dados:"</string>
+ <string name="radio_info_gprs_service_label">"Serviço GPRS:"</string>
+ <string name="radio_info_roaming_label">"Roaming:"</string>
+ <string name="radio_info_imei_label">"IMEI:"</string>
+ <string name="radio_info_call_redirect_label">"Redirecionamento de chamada:"</string>
+ <string name="radio_info_ppp_resets_label">"Número de redefinições de PPP desde a inicialização:"</string>
+ <string name="radio_info_gsm_disconnects_label">"Desconexões GSM:"</string>
+ <string name="radio_info_current_network_label">"Rede atual:"</string>
+ <string name="radio_info_data_successes_label">"Êxitos dos dados"</string>
+ <string name="radio_info_ppp_received_label">"PPP recebido:"</string>
+ <string name="radio_info_gsm_service_label">"Serviço GSM:"</string>
+ <string name="radio_info_signal_strength_label">"Força do sinal:"</string>
+ <string name="radio_info_call_status_label">"Status da chamada:"</string>
+ <string name="radio_info_ppp_sent_label">"PPP enviado:"</string>
+ <string name="radio_info_radio_resets_label">"Redefinições do rádio:"</string>
+ <string name="radio_info_message_waiting_label">"Mensagem em espera:"</string>
+ <string name="radio_info_phone_number_label">"Número de telefone:"</string>
+ <string name="radio_info_band_mode_label">"Selecione banda de rádio"</string>
+ <string name="radio_info_network_type_label">"Tipo de rede:"</string>
+ <string name="radio_info_set_perferred_label">"Definir tipo de rede preferida:"</string>
+ <string name="radio_info_ping_ipaddr">"Executar ping em IpAddr:"</string>
+ <string name="radio_info_ping_hostname">"Executar ping no nome do host (www.google.com):"</string>
+ <string name="radio_info_http_client_test">"Teste de cliente HTTP:"</string>
+ <string name="radio_info_toggle_ciph_label">"Alternar decodificação"</string>
+ <string name="ping_test_label">"Executar teste de ping"</string>
+ <string name="radio_info_smsc_label">"SMSC:"</string>
+ <string name="radio_info_smsc_update_label">"Atualizar"</string>
+ <string name="radio_info_smsc_refresh_label">"Atualizar"</string>
+ <!-- no translation found for radio_info_toggle_dns_check_label (8292252930563286858) -->
+ <skip />
+ <string name="band_mode_title">"Definir banda GSM/UMTS"</string>
+ <string name="band_mode_loading">"Carregando lista de bandas…"</string>
+ <string name="band_mode_set">"Definir"</string>
+ <string name="band_mode_failed">"Sem êxito"</string>
+ <string name="band_mode_succeeded">"Êxito"</string>
+ <string name="sdcard_changes_instructions">"As alterações ocorrem quando o cabo USB é reconectado"</string>
+ <string name="sdcard_settings_screen_mass_storage_text">"Ativar armazenamento em massa de USB"</string>
+ <string name="sdcard_settings_total_bytes_label">"Total de bytes:"</string>
+ <string name="sdcard_settings_not_present_status">"Não há cartão SD"</string>
+ <string name="sdcard_settings_available_bytes_label">"Bytes disponíveis:"</string>
+ <string name="sdcard_settings_mass_storage_status">"O cartão SD está sendo usado como um dispositivo de armazenamento em massa"</string>
+ <string name="sdcard_settings_unmounted_status">"Agora é seguro remover o cartão SD"</string>
+ <string name="sdcard_settings_bad_removal_status">"O cartão SD foi removido durante o uso."</string>
+ <string name="sdcard_settings_used_bytes_label">"Bytes usados:"</string>
+ <string name="sdcard_settings_scanning_status">"Examinando o cartão SD em busca de mídia…"</string>
+ <string name="sdcard_settings_read_only_status">"Cartão SD montado como somente leitura"</string>
+ <string name="next_label">"Avançar"</string>
+ <string name="language_picker_title">"Localidade"</string>
+ <string name="select_your_language">"Selecione seu idioma"</string>
+ <string name="activity_picker_label">"Selecione a atividade"</string>
+ <string name="device_info_label">"Informações do dispositivo"</string>
+ <string name="battery_info_label">"Informações sobre a bateria"</string>
+ <!-- no translation found for battery_history_label (8242244969757414501) -->
+ <skip />
+ <string name="display_label">"Exibição"</string>
+ <string name="phone_info_label">"Informações do telefone"</string>
+ <string name="sd_card_settings_label">"Cartão SD"</string>
+ <string name="proxy_settings_label">"Configurações de proxy"</string>
+ <string name="cancel">"Cancelar"</string>
+ <string name="settings_label">"Configurações"</string>
+ <string name="airplane_mode">"Modo avião"</string>
+ <string name="airplane_mode_summary">"Desativar todas as conexões sem fio"</string>
+ <string name="airplane_mode_turning_on">"Desativando conexões sem fio…"</string>
+ <string name="airplane_mode_turning_off">"Ativando as conexões sem fio…"</string>
+ <string name="radio_controls_title">"Controles sem fio"</string>
+ <string name="radio_controls_summary">"Gerenciar Wi-Fi, Bluetooth, modo avião & redes móveis"</string>
+ <!-- no translation found for roaming (3596055926335478572) -->
+ <skip />
+ <!-- no translation found for roaming_enable (3737380951525303961) -->
+ <skip />
+ <!-- no translation found for roaming_disable (1295279574370898378) -->
+ <skip />
+ <!-- no translation found for roaming_reenable_message (9141007271031717369) -->
+ <skip />
+ <!-- no translation found for roaming_turn_it_on_button (4387601818162120589) -->
+ <skip />
+ <!-- no translation found for roaming_warning (1269870211689178511) -->
+ <skip />
+ <!-- no translation found for roaming_reenable_title (7626425894611573131) -->
+ <skip />
+ <!-- no translation found for networks (6333316876545927039) -->
+ <skip />
+ <!-- no translation found for sum_carrier_select (6648929373316748020) -->
+ <skip />
+ <string name="date_and_time_settings_title">"Data & hora"</string>
+ <string name="date_and_time_settings_summary">"Definir data, hora, fuso horário & formatos"</string>
+ <string name="date_time_auto">"Automático"</string>
+ <string name="date_time_auto_summaryOn">"Use valores fornecidos pela rede"</string>
+ <string name="date_time_auto_summaryOff">"Use valores fornecidos pela rede"</string>
+ <string name="date_time_24hour">"Use formato de 24 horas"</string>
+ <string name="date_time_set_time">"Definir tempo"</string>
+ <string name="date_time_set_timezone">"Selecione fuso horário"</string>
+ <string name="date_time_set_date">"Definir data"</string>
+ <string name="date_time_date_format">"Selecione o formato de datas"</string>
+ <string name="zone_list_menu_sort_alphabetically">"Classificar alfabeticamente"</string>
+ <string name="zone_list_menu_sort_by_timezone">"Classificar por fuso horário"</string>
+ <string name="security_settings_title">"Segurança & local"</string>
+ <string name="security_settings_summary">"Definir Meu local, desbloqueio de tela, bloqueio do cartão SIM"</string>
+ <string name="security_passwords_title">"Senhas"</string>
+ <string name="bluetooth_quick_toggle_title">"Bluetooth"</string>
+ <string name="bluetooth_quick_toggle_summary">"Ativar Bluetooth"</string>
+ <string name="bluetooth_settings">"Configurações de Bluetooth"</string>
+ <string name="bluetooth_settings_title">"Configurações de Bluetooth"</string>
+ <string name="bluetooth_settings_summary">"Gerenciar conexões, definir o nome & possibilidade de detecção do dispositivo"</string>
+ <string name="bluetooth_pin_entry">"Solicitação de pareamento de Bluetooth"</string>
+ <string name="bluetooth_device_info">"Informações do dispositivo Bluetooth"</string>
+ <string name="bluetooth_enter_pin_msg">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"\n\n"Digite o PIN para realizar o pareamento."\n"(tente 0000 ou 1234)."</string>
+ <string name="bluetooth_error_title">"Atenção"</string>
+ <string name="bluetooth_pairing_error_message">"Ocorreu um problema ao parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_pin_error_message">"Ocorreu um problema ao parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> porque o PIN digitado está incorreto."</string>
+ <!-- no translation found for bluetooth_pairing_device_down_error_message (6688215193824686741) -->
+ <skip />
+ <!-- no translation found for bluetooth_pairing_rejected_error_message (1648157108520832454) -->
+ <skip />
+ <string name="bluetooth_connecting_error_message">"Ocorreu um problema ao conectar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_preference_scan_title">"Examinar em busca de dispositivos"</string>
+ <string name="bluetooth_device_context_connect">"Conectar"</string>
+ <string name="bluetooth_device_context_disconnect">"Desconectar"</string>
+ <string name="bluetooth_device_context_pair_connect">"Parear e conectar"</string>
+ <string name="bluetooth_device_context_unpair">"Cancelar pareamento"</string>
+ <string name="bluetooth_device_context_disconnect_unpair">"Desconectar e cancelar pareamento"</string>
+ <string name="bluetooth_device_context_connect_advanced">"Opções..."</string>
+ <string name="bluetooth_connect_specific_profiles_title">"Conectar a…"</string>
+ <string name="bluetooth_profile_a2dp">"Mídia"</string>
+ <string name="bluetooth_profile_headset">"Telefone"</string>
+ <string name="bluetooth_summary_connected_to_a2dp">"Conectado ao áudio da mídia"</string>
+ <string name="bluetooth_summary_connected_to_headset">"Conectado ao áudio do telefone"</string>
+ <string name="bluetooth_summary_connected_to_a2dp_headset">"Conectado ao áudio do telefone e da mídia"</string>
+ <string name="bluetooth_device_advanced_title">"opções de <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="bluetooth_device_advanced_online_mode_title">"Conectar"</string>
+ <string name="bluetooth_device_advanced_online_mode_summary">"Conectar ao dispositivo Bluetooth"</string>
+ <string name="bluetooth_device_advanced_profile_header_title">"Perfis"</string>
+ <string name="bluetooth_a2dp_profile_summary_connected">"Conectado ao áudio da mídia"</string>
+ <string name="bluetooth_headset_profile_summary_connected">"Conectado ao áudio do telefone"</string>
+ <string name="bluetooth_a2dp_profile_summary_use_for">"Usar para áudio da mídia"</string>
+ <string name="bluetooth_headset_profile_summary_use_for">"Usar para áudio do telefone"</string>
+ <string name="wifi">"Wi-Fi"</string>
+ <string name="wifi_quick_toggle_title">"Wi-Fi"</string>
+ <string name="wifi_quick_toggle_summary">"Ativar Wi-Fi"</string>
+ <string name="wifi_settings">"Configurações de Wi-Fi"</string>
+ <string name="wifi_settings_category">"Configurações de Wi-Fi"</string>
+ <string name="wifi_settings_summary">"Configurar & gerenciar pontos de acesso"</string>
+ <string name="forget_network">"Esquecer"</string>
+ <string name="wifi_status">"Status"</string>
+ <string name="wifi_link_speed">"Velocidade"</string>
+ <string name="wifi_signal_3">"Excelente"</string>
+ <string name="wifi_signal_2">"Bom"</string>
+ <string name="wifi_signal_1">"Regular"</string>
+ <string name="wifi_signal_0">"Ruim"</string>
+ <string name="security">"Segurança"</string>
+ <string name="wifi_security_open">"Abrir"</string>
+ <string name="wifi_security_wep">"WEP"</string>
+ <string name="wifi_security_wpa">"WPA"</string>
+ <string name="wifi_security_wpa2">"WPA2"</string>
+ <!-- no translation found for wifi_security_wpa_eap (7485687331651751101) -->
+ <skip />
+ <!-- no translation found for wifi_security_ieee8021x (8538687609878109005) -->
+ <skip />
+ <string name="wifi_security_unknown">"Desconhecido"</string>
+ <string name="wifi_security_verbose_open">"Abrir rede"</string>
+ <string name="wifi_security_verbose_wep">"Protegida com WEP"</string>
+ <string name="wifi_security_verbose_wpa">"Protegido com WPA"</string>
+ <string name="wifi_security_verbose_wpa2">"Protegido com WPA2"</string>
+ <!-- no translation found for wifi_security_verbose_wpa_eap (1317942027527749734) -->
+ <skip />
+ <!-- no translation found for wifi_security_verbose_ieee8021x (5123465248429588738) -->
+ <skip />
+ <string name="ip_address">"Endereço IP"</string>
+ <string name="signal">"Força do sinal"</string>
+ <string name="wifi_starting">"Ativando…"</string>
+ <string name="wifi_stopping">"Desligando…"</string>
+ <string name="wifi_error">"Erro"</string>
+ <string name="error_starting">"Não é possível iniciar a Wi-Fi"</string>
+ <string name="error_stopping">"Não é possível interromper a Wi-Fi"</string>
+ <string name="error_scanning">"Não é possível examinar em busca de novas redes"</string>
+ <string name="error_connecting">"Não é possível se conectar à rede"</string>
+ <string name="error_saving">"Não é possível salvar a rede"</string>
+ <string name="connect">"Conectar"</string>
+ <string name="connect_to_blank">"Conectar a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for please_select_eap (4488240331626456338) -->
+ <skip />
+ <!-- no translation found for please_select_phase2 (5231074529772044898) -->
+ <skip />
+ <!-- no translation found for please_type_identity (7061261155499513089) -->
+ <skip />
+ <!-- no translation found for please_type_anonymous_identity (835061562079965048) -->
+ <skip />
+ <!-- no translation found for please_select_client_certificate (2137906961594663234) -->
+ <skip />
+ <!-- no translation found for please_select_ca_certificate (5010815181914420677) -->
+ <skip />
+ <!-- no translation found for please_select_private_key (1804364378555255180) -->
+ <skip />
+ <!-- no translation found for please_type_private_key_passwd (4077744679722504443) -->
+ <skip />
+ <string name="please_type_passphrase">"Senha da rede sem fio"</string>
+ <string name="please_type_hex_key">"Chave hexadecimal WEP (0-9, A-F)"</string>
+ <string name="wifi_show_password">"Mostrar senha."</string>
+ <string name="scan_wifi">"Examinar"</string>
+ <string name="summary_not_in_range">"Não está dentro da faixa"</string>
+ <string name="summary_remembered">"Recordado"</string>
+ <string name="summary_connection_failed">"Falha de conexão, selecione para tentar novamente"</string>
+ <string name="wifi_access_points">"Redes Wi-Fi"</string>
+ <string name="wifi_type_ssid">"SSID de rede"</string>
+ <string name="wifi_security">"Segurança"</string>
+ <string name="wifi_save_config">"Salvar"</string>
+ <string name="wifi_password_unchanged">"(inalterado)"</string>
+ <string name="wifi_add_other_network">"Adicionar rede Wi-Fi"</string>
+ <string name="wifi_notify_open_networks">"Notificação de rede"</string>
+ <string name="wifi_notify_open_networks_summary">"Notifique-me quando uma rede aberta estiver disponível"</string>
+ <string name="wifi_password_incorrect_error">"A senha de rede digitada não está correta. Tente novamente."</string>
+ <string name="wifi_generic_connection_error">"Há um problema de conexão com a rede. Tente novamente."</string>
+ <string name="wifi_menu_advanced">"Avançado"</string>
+ <string name="wifi_ip_settings_titlebar">"Configurações de IP"</string>
+ <string name="wifi_ip_settings_menu_save">"Salvar"</string>
+ <string name="wifi_ip_settings_menu_cancel">"Cancelar"</string>
+ <string name="wifi_ip_settings_invalid_ip">"Digite um endereço IP válido."</string>
+ <string name="wifi_use_static_ip">"Usar IP estático"</string>
+ <string name="wifi_ip_address">"Endereço IP"</string>
+ <string name="wifi_dns1">"DNS 1"</string>
+ <string name="wifi_dns2">"DNS 2"</string>
+ <string name="wifi_gateway">"Gateway"</string>
+ <string name="wifi_netmask">"Máscara de rede"</string>
+ <string name="wifi_context_menu_connect">"Conectar à rede"</string>
+ <string name="wifi_context_menu_forget">"Esquecer rede"</string>
+ <string name="wifi_context_menu_change_password">"Alterar senha"</string>
+ <string name="wifi_advanced_titlebar">"Avançado"</string>
+ <string name="wifi_setting_num_channels_title">"Domínio controlador"</string>
+ <string name="wifi_setting_num_channels_summary">"Defina o número de canais para uso"</string>
+ <string name="wifi_setting_num_channels_error">"Houve um problema com a configuração do domínio controlador."</string>
+ <string name="wifi_setting_num_channels_channel_phrase">"<xliff:g id="NUM_CHANNELS">%1$d</xliff:g> canais"</string>
+ <!-- no translation found for wifi_setting_sleep_policy_title (1367731352485585528) -->
+ <skip />
+ <!-- no translation found for wifi_setting_sleep_policy_summary (7573693311804602041) -->
+ <skip />
+ <!-- no translation found for wifi_setting_sleep_policy_error (5103670439972135148) -->
+ <skip />
+ <string name="wifi_advanced_mac_address_title">"Endereço MAC"</string>
+ <string name="fragment_status_scanning">"Examinando…"</string>
+ <string name="fragment_status_connecting">"Conectando a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</string>
+ <string name="fragment_status_authenticating">"Autenticando com <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</string>
+ <string name="fragment_status_obtaining_ip">"Obtendo endereço IP da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</string>
+ <string name="fragment_status_connected">"Conectado ao <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="fragment_status_disconnecting">"Desconectando de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</string>
+ <string name="fragment_status_disconnected">"Desconectado"</string>
+ <string name="fragment_status_failed">"Sem êxito"</string>
+ <string name="status_scanning">"Examinando…"</string>
+ <string name="status_connecting">"Conectando…"</string>
+ <string name="status_authenticating">"Autenticando…"</string>
+ <string name="status_obtaining_ip">"Obtendo endereço…"</string>
+ <string name="status_connected">"Conectado"</string>
+ <string name="status_disconnecting">"Desconectando…"</string>
+ <string name="status_disconnected">"Desconectado"</string>
+ <string name="status_failed">"Sem êxito"</string>
+ <string name="sound_and_display_settings">"Som & tela"</string>
+ <string name="sound_settings">"Configurações de som"</string>
+ <string name="sound_and_display_settings_summary">"Definir ringtones, notificações, brilho da tela"</string>
+ <string name="silent_mode_title">"Modo silencioso"</string>
+ <string name="silent_mode_summary">"Todos os sons, exceto mídia e alarmes, são silenciados"</string>
+ <!-- no translation found for silent_mode_incl_alarm_summary (2088830834182228458) -->
+ <skip />
+ <string name="ringtone_title">"Ringtone do telefone"</string>
+ <string name="ringtone_summary">"Defina seu ringtone padrão de chamada recebida"</string>
+ <string name="ring_volume_title">"Volume da campainha"</string>
+ <string name="ring_volume_summary">"Definir volume para chamadas recebidas e notificações"</string>
+ <string name="vibrate_title">"Telefone vibra"</string>
+ <string name="vibrate_summary">"Vibrar o telefone para chamadas recebidas"</string>
+ <string name="notification_sound_title">"Ringtone de notificação"</string>
+ <string name="notification_sound_summary">"Definir seu ringtone de notificação padrão"</string>
+ <string name="incoming_call_volume_title">"Volume da chamada recebida"</string>
+ <string name="notification_volume_title">"Volume da notificação"</string>
+ <string name="checkbox_notification_same_as_incoming_call">"Usar volume das chamadas recebidas para notificações"</string>
+ <string name="notification_sound_dialog_title">"Selecione o ringtone de notificação"</string>
+ <string name="media_volume_title">"Volume da mídia"</string>
+ <string name="media_volume_summary">"Configurar volume para música e vídeos"</string>
+ <string name="dtmf_tone_enable_title">"Tons de toque audíveis"</string>
+ <string name="dtmf_tone_enable_summary_on">"Reproduzir tons ao usar o teclado"</string>
+ <string name="dtmf_tone_enable_summary_off">"Reproduzir tons ao usar o teclado"</string>
+ <string name="sound_effects_enable_title">"Seleção audível"</string>
+ <string name="sound_effects_enable_summary_on">"Reproduzir som ao fazer seleção de tela"</string>
+ <string name="sound_effects_enable_summary_off">"Reproduzir som ao fazer seleção de tela"</string>
+ <!-- no translation found for play_media_notification_sounds_enable_title (1008791464029179529) -->
+ <skip />
+ <!-- no translation found for play_media_notification_sounds_enable_summary_on (426729807044947187) -->
+ <skip />
+ <!-- no translation found for play_media_notification_sounds_enable_summary_off (803791141563778934) -->
+ <skip />
+ <string name="sync_settings">"Sincronização de dados"</string>
+ <string name="sync_settings_summary">"Selecione quais aplicativos serão sincronizados"</string>
+ <!-- no translation found for search_settings (1910951467596035063) -->
+ <skip />
+ <!-- no translation found for search_settings_summary (3736000832072784654) -->
+ <skip />
+ <string name="display_settings">"Exibir configurações"</string>
+ <string name="animations_title">"Animação"</string>
+ <!-- no translation found for animations_summary_on (8843613112130484436) -->
+ <skip />
+ <!-- no translation found for animations_summary_off (2777026828025551983) -->
+ <skip />
+ <!-- no translation found for accelerometer_title (6183763368844793276) -->
+ <skip />
+ <!-- no translation found for accelerometer_summary_on (1133737282813048021) -->
+ <skip />
+ <!-- no translation found for accelerometer_summary_off (5485489363715740761) -->
+ <skip />
+ <string name="brightness">"Brilho"</string>
+ <!-- no translation found for brightness_summary (838917350127550703) -->
+ <skip />
+ <string name="screen_timeout">"Tempo esgotado da tela"</string>
+ <!-- no translation found for screen_timeout_summary (2905757633140605334) -->
+ <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>
+ <string name="sim_pin_toggle">"Bloquear cartão SIM"</string>
+ <string name="sim_lock_on">"Requer PIN para usar o telefone"</string>
+ <string name="sim_lock_off">"Requer PIN para usar o telefone"</string>
+ <string name="sim_pin_change">"Alterar PIN do SIM"</string>
+ <string name="sim_enter_pin">"PIN do SIM"</string>
+ <string name="sim_enable_sim_lock">"Bloquear cartão SIM"</string>
+ <string name="sim_disable_sim_lock">"Desbloquear cartão SIM"</string>
+ <string name="sim_enter_old">"PIN do SIM antigo"</string>
+ <string name="sim_enter_new">"PIN do novo SIM"</string>
+ <string name="sim_reenter_new">"Digite novamente o novo PIN"</string>
+ <string name="sim_change_pin">"PIN do SIM"</string>
+ <string name="sim_bad_pin">"PIN incorreto."</string>
+ <string name="sim_pins_dont_match">"Os PINs não correspondem."</string>
+ <string name="sim_change_failed">"Não é possível alterar o PIN."\n"PIN possivelmente incorreto."</string>
+ <string name="sim_change_succeeded">"PIN do SIM alterado com êxito"</string>
+ <string name="sim_lock_failed">"Não é possível alterar o estado de bloqueio do cartão SIM."\n"PIN possivelmente incorreto."</string>
+ <string name="sim_enter_ok">"OK"</string>
+ <string name="sim_enter_cancel">"Cancelar"</string>
+ <string name="device_info_settings">"Status do telefone"</string>
+ <string name="system_update_settings_list_item_title">"Atualizações do sistema"</string>
+ <string name="system_update_settings_list_item_summary">"Verificar as atualização do sistema"</string>
+ <string name="firmware_version">"Versão do firmware"</string>
+ <string name="model_number">"Número do modelo"</string>
+ <string name="baseband_version">"Versão da banda de base"</string>
+ <string name="kernel_version">"Versão do kernel"</string>
+ <string name="build_number">"Número da compilação"</string>
+ <string name="device_info_not_available">"Não disponível"</string>
+ <string name="device_status_activity_title">"Status"</string>
+ <string name="device_status">"Status"</string>
+ <string name="device_status_summary">"IMEI, número de telefone, sinal etc."</string>
+ <string name="storage_settings_title">"Cartão SD & armazenamento do telefone"</string>
+ <string name="storage_settings_summary">"Cartão SD sem nome, exibir armazenamento disponível"</string>
+ <string name="status_number">"Número de telefone"</string>
+ <!-- no translation found for status_network_type (3279383550222116235) -->
+ <skip />
+ <!-- no translation found for status_data_state (5503181397066522950) -->
+ <skip />
+ <string name="status_service_state">"Estado do serviço"</string>
+ <string name="status_signal_strength">"Força do sinal"</string>
+ <string name="status_roaming">"Roaming"</string>
+ <string name="status_operator">"Rede"</string>
+ <string name="status_wifi_mac_address">"Endereço MAC Wi-Fi"</string>
+ <string name="status_bt_address">"Endereço Bluetooth"</string>
+ <string name="status_unavailable">"Não disponível"</string>
+ <string name="status_up_time">"Tempo de funcionamento"</string>
+ <string name="status_awake_time">"Tempo de atividade"</string>
+ <string name="internal_memory">"Armazenamento interno do telefone"</string>
+ <string name="sd_memory">"Cartão SD"</string>
+ <string name="memory_available">"Espaço disponível"</string>
+ <string name="memory_size">"Espaço total"</string>
+ <!-- no translation found for sd_eject (6915293408836853020) -->
+ <skip />
+ <!-- no translation found for sd_eject_summary (3315557796211542962) -->
+ <skip />
+ <!-- no translation found for sd_format (5448738337382712203) -->
+ <skip />
+ <!-- no translation found for sd_format_summary (6616491027883134004) -->
+ <skip />
+ <string name="sd_unavailable">"Não disponível"</string>
+ <string name="read_only">" (Somente leitura)"</string>
+ <string name="battery_status_title">"Status da bateria"</string>
+ <string name="battery_level_title">"Nível da bateria"</string>
+ <string name="apn_settings">"APNs"</string>
+ <string name="apn_edit">"Editar ponto de acesso"</string>
+ <string name="apn_not_set">"<Não definido>"</string>
+ <string name="apn_name">"Nome"</string>
+ <string name="apn_apn">"APN"</string>
+ <string name="apn_http_proxy">"Proxy"</string>
+ <string name="apn_http_port">"Porta"</string>
+ <string name="apn_user">"Nome de usuário"</string>
+ <string name="apn_password">"Senha"</string>
+ <string name="apn_server">"Servidor"</string>
+ <string name="apn_mmsc">"MMSC"</string>
+ <string name="apn_mms_proxy">"Proxy MMS"</string>
+ <string name="apn_mms_port">"Porta MMS"</string>
+ <string name="apn_mcc">"MCC"</string>
+ <string name="apn_mnc">"MNC"</string>
+ <string name="apn_type">"Tipo APN"</string>
+ <string name="menu_delete">"Excluir APN"</string>
+ <string name="menu_new">"Novo APN"</string>
+ <string name="menu_save">"Salvar"</string>
+ <string name="menu_cancel">"Descartar"</string>
+ <string name="error_title">"Atenção"</string>
+ <string name="error_name_empty">"O campo Nome não pode ficar vazio."</string>
+ <string name="error_apn_empty">"O APN não pode ser vazio."</string>
+ <string name="error_mcc_not3">"O campo MCC deve ter 3 dígitos."</string>
+ <string name="error_mnc_not23">"Campo MNC deve ter 2 ou 3 dígitos."</string>
+ <!-- no translation found for restore_default_apn (2724583218635739913) -->
+ <skip />
+ <!-- no translation found for menu_restore (8260067415075573273) -->
+ <skip />
+ <!-- no translation found for restore_default_apn_completed (3990449939234957281) -->
+ <skip />
+ <string name="master_clear_title">"Redefinição de dados da fábrica"</string>
+ <string name="master_clear_summary">"Apaga todos os dados no telefone"</string>
+ <string name="master_clear_desc">"Esta ação redefinirá o estado de fábrica do telefone, apagando todos os dados e aplicativos baixados."</string>
+ <string name="master_clear_button_text">"Reiniciar o telefone"</string>
+ <string name="master_clear_final_desc">"Reiniciar o telefone, apagando todos os dados e aplicativos? Essa ação não pode ser revertida."</string>
+ <string name="master_clear_final_button_text">"Apagar tudo"</string>
+ <string name="master_clear_gesture_prompt">"Desenhar seu padrão de desbloqueio"</string>
+ <string name="master_clear_gesture_explanation">"Você deve desenhar seu padrão de desbloqueio para confirmar a reinicialização de um telefone."</string>
+ <string name="master_clear_failed">"Nenhuma reinicialização foi realizada, pois o serviço System Clear não está disponível."</string>
+ <!-- no translation found for media_format_title (4671276096695789895) -->
+ <skip />
+ <!-- no translation found for media_format_summary (3805714639375830120) -->
+ <skip />
+ <!-- no translation found for media_format_desc (1142563222357820834) -->
+ <skip />
+ <!-- no translation found for media_format_button_text (370856400090190151) -->
+ <skip />
+ <!-- no translation found for media_format_final_desc (1776666694910717198) -->
+ <skip />
+ <!-- no translation found for media_format_final_button_text (4881713344315923175) -->
+ <skip />
+ <!-- no translation found for media_format_gesture_prompt (3109349468816856670) -->
+ <skip />
+ <!-- no translation found for media_format_gesture_explanation (4239529439389660159) -->
+ <skip />
+ <string name="call_settings_title">"Configurações da chamada"</string>
+ <string name="call_settings_summary">"Configurar correio de voz, transferência de chamada, chamada em espera, ID do chamador"</string>
+ <string name="network_settings_title">"Redes móveis"</string>
+ <string name="network_settings_summary">"Definir opções para roaming, redes e APNs"</string>
+ <string name="location_title">"Fontes de Meu local"</string>
+ <string name="location_network_based">"Usar redes sem fio"</string>
+ <string name="location_networks_disabled">"Consulte o local nos aplicativos (como Mapas) usando redes sem fio"</string>
+ <string name="location_neighborhood_level">"Local determinado pelas redes Wi-Fi e/ou móvel"</string>
+ <string name="location_gps">"Ativar satélites GPS"</string>
+ <string name="location_street_level">"Ao localizar, defina a precisão para nível de rua (retire a seleção de economia da bateria)"</string>
+ <string name="location_gps_disabled">"Localizar no nível da rua (exige mais bateria e vista do céu)"</string>
+ <string name="about_settings">"Sobre o telefone"</string>
+ <string name="about_settings_summary">"Exibir informações jurídicos, status do telefone, versão do software"</string>
+ <string name="legal_information">"Informações jurídicas"</string>
+ <string name="contributors_title">"Colaboradores"</string>
+ <string name="copyright_title">"Direitos autorais"</string>
+ <string name="license_title">"Licença"</string>
+ <string name="terms_title">"Termos e condições"</string>
+ <!-- no translation found for system_tutorial_list_item_title (4315834755909579018) -->
+ <skip />
+ <!-- no translation found for system_tutorial_list_item_summary (3861815254521030201) -->
+ <skip />
+ <string name="settings_license_activity_title">"Abrir licenças da fonte"</string>
+ <string name="settings_license_activity_unavailable">"Há um problema com o carregamento das licenças."</string>
+ <string name="settings_license_activity_loading">"Carregando…"</string>
+ <string name="lock_settings_title">"Padrão de desbloqueio da tela"</string>
+ <string name="lockpattern_change_lock_pattern_label">"Alterar padrão de desbloqueio"</string>
+ <string name="lockpattern_need_to_unlock">"Confirmar padrão salvo"</string>
+ <string name="lockpattern_need_to_unlock_wrong">"Sentimos muito, tente novamente:"</string>
+ <string name="lockpattern_recording_intro_header">"Desenhar um padrão de desbloqueio"</string>
+ <string name="lockpattern_recording_intro_footer">"Pressione Menu para obter ajuda."</string>
+ <string name="lockpattern_recording_inprogress">"Solte o dedo ao concluir."</string>
+ <string name="lockpattern_recording_incorrect_too_short">"Ligue no mínimo <xliff:g id="NUMBER">%d</xliff:g> pontos. Tente novamente:"</string>
+ <string name="lockpattern_pattern_entered_header">"Padrão registrado."</string>
+ <string name="lockpattern_need_to_confirm">"Desenhar padrão novamente para confirmar:"</string>
+ <string name="lockpattern_pattern_confirmed_header">"Seu novo padrão de desbloqueio:"</string>
+ <string name="lockpattern_confirm_button_text">"Confirmar"</string>
+ <string name="lockpattern_restart_button_text">"Redesenhar"</string>
+ <string name="lockpattern_retry_button_text">"Tentar novamente"</string>
+ <string name="lockpattern_continue_button_text">"Continuar"</string>
+ <string name="lockpattern_settings_title">"Padrão de desbloqueio"</string>
+ <string name="lockpattern_settings_enable_title">"Exige o padrão"</string>
+ <string name="lockpattern_settings_enable_summary">"Deve desenhar o padrão para desbloquear a tela"</string>
+ <string name="lockpattern_settings_enable_visible_pattern_title">"Usar padrão visível"</string>
+ <string name="lockpattern_settings_enable_tactile_feedback_title">"Usar leitura tátil"</string>
+ <string name="lockpattern_settings_choose_lock_pattern">"Definir padrão de desbloqueio"</string>
+ <string name="lockpattern_settings_change_lock_pattern">"Alterar padrão de desbloqueio"</string>
+ <string name="lockpattern_settings_help_how_to_record">"Como desenhar um padrão de desbloqueio"</string>
+ <string name="lockpattern_too_many_failed_confirmation_attempts_header">"Muitas tentativas incorretas."</string>
+ <string name="lockpattern_too_many_failed_confirmation_attempts_footer">"Tentar novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
+ <string name="skip_button_label">"Cancelar"</string>
+ <string name="next_button_label">"Avançar"</string>
+ <string name="lock_title">"Proteção do seu telefone"</string>
+ <string name="lock_intro_message"><font size="17">"Proteja o telefone contra o uso inadequado criando um padrão de desbloqueio de tela pessoal. "\n<font height="17">\n</font><b>"1"</b>" Na próxima tela, observe enquanto um exemplo de padrão é desenhado. "\n<font height="17">\n</font><b>"2"</b>" Quando estiver pronto, desenhe seu próprio padrão de desbloqueio. Experimente padrões diferentes, mas ligue no mínimo quatro pontos. "\n<font height="17">\n</font><b>"3"</b>" Desenhe seu padrão novamente para confirmar. "\n<font height="17">\n</font><b>"Pronto para começar? Selecione “Avançar”"</b>". "\n<font height="3">\n</font>"Para deixar seu telefone desprotegido, selecione “Cancelar”."</font></string>
+ <string name="lock_example_title">"Exemplo de padrão"</string>
+ <string name="lock_example_message">"Ligue no mínimo quatro pontos."\n" "\n"Selecione “Avançar” quando estiver pronto para desenhar seu próprio padrão."</string>
+ <string name="manageapplications_settings_title">"Gerenciar aplicativos"</string>
+ <!-- no translation found for manageapplications_settings_summary (6097117021500651232) -->
+ <skip />
+ <string name="applications_settings">"Aplicativos"</string>
+ <string name="applications_settings_summary">"Gerenciar aplicativos, configurar atalhos de inicialização rápida"</string>
+ <string name="applications_settings_header">"Configurações do aplicativo"</string>
+ <string name="install_applications">"Fontes desconhecidas"</string>
+ <string name="install_unknown_applications">"Permite a instalação de aplicativos que não são do Market"</string>
+ <string name="install_all_warning">"Seu telefone e dados pessoais são mais vulneráveis ao ataque de aplicativos de fontes desconhecidas. Você concorda que é totalmente responsável por qualquer dano causado ao seu telefone ou pela perda de dados que possa resultar do uso desses aplicativos."</string>
+ <string name="application_info_label">"Informações sobre o aplicativo"</string>
+ <string name="storage_label">"Armazenamento"</string>
+ <string name="auto_launch_label">"Iniciar por padrão"</string>
+ <string name="permissions_label">"Permissões"</string>
+ <string name="cache_header_label">"Cache"</string>
+ <string name="clear_cache_btn_text">"Limpar cache"</string>
+ <string name="cache_size_label">"Cache"</string>
+ <!-- no translation found for controls_label (7611113077086853799) -->
+ <skip />
+ <!-- no translation found for force_stop (7435006169872876756) -->
+ <skip />
+ <string name="total_size_label">"Total"</string>
+ <string name="application_size_label">"Aplicativo"</string>
+ <string name="data_size_label">"Dados"</string>
+ <string name="uninstall_text">"Desinstalar"</string>
+ <string name="clear_user_data_text">"Limpar dados"</string>
+ <!-- no translation found for app_factory_reset (7167892023319924674) -->
+ <skip />
+ <string name="auto_launch_enable_text">"Você selecionou iniciar este aplicativo por padrão para usar algumas ações."</string>
+ <string name="auto_launch_disable_text">"Nenhum padrão definido."</string>
+ <string name="clear_activities">"Limpar padrões"</string>
+ <string name="unknown">"Desconhecido"</string>
+ <string name="sort_order_alpha">"Classificar"</string>
+ <string name="sort_order_size">"Classificar por tamanho"</string>
+ <string name="manage_space_text">"Gerenciar o espaço"</string>
+ <!-- no translation found for filter (2018011724373033887) -->
+ <skip />
+ <!-- no translation found for filter_dlg_title (6507663329723966854) -->
+ <skip />
+ <string name="filter_apps_all">"Tudo"</string>
+ <string name="filter_apps_third_party">"Terceiros"</string>
+ <string name="filter_apps_running">"Em execução"</string>
+ <string name="loading">"Carregando…"</string>
+ <string name="recompute_size">"Recalculando o tamanho…"</string>
+ <string name="clear_data_dlg_title">"Excluir"</string>
+ <string name="clear_data_dlg_text">"Todas as informações salvas neste aplicativo serão excluídas permanentemente."</string>
+ <string name="dlg_ok">"OK"</string>
+ <string name="dlg_cancel">"Cancelar"</string>
+ <string name="app_not_found_dlg_title">"Aplicativo não encontrado"</string>
+ <string name="app_not_found_dlg_text">"O aplicativo não foi encontrado na lista de aplicativos instalados."</string>
+ <string name="clear_data_failed">"Não é possível limpar os dados do aplicativo."</string>
+ <!-- no translation found for app_factory_reset_dlg_title (4370229555040541055) -->
+ <skip />
+ <!-- no translation found for app_factory_reset_dlg_text (1183261746385587974) -->
+ <skip />
+ <!-- no translation found for clear_failed_dlg_title (2387060805294783175) -->
+ <skip />
+ <!-- no translation found for clear_failed_dlg_text (7943411157007320290) -->
+ <skip />
+ <string name="security_settings_desc">"Este aplicativo pode acessar os seguintes itens em seu telefone:"</string>
+ <!-- no translation found for computing_size (1599186977475211186) -->
+ <skip />
+ <string name="invalid_size_value">"Não é possível calcular o tamanho do pacote"</string>
+ <string name="empty_list_msg">"Você não possui nenhum aplicativo de terceiros instalado."</string>
+ <!-- no translation found for version_text (9189073826278676425) -->
+ <skip />
+ <string name="language_settings">"Localidade & texto"</string>
+ <string name="language_settings_summary">"Definir opções de localidade (idioma e região), entrada de texto e correção automática"</string>
+ <string name="language_category">"Configuração de localidade"</string>
+ <string name="text_category">"Configurações de texto"</string>
+ <string name="phone_language">"Selecione a localidade"</string>
+ <!-- no translation found for phone_language_summary (1809580675831352352) -->
+ <skip />
+ <string name="auto_replace">"Substituição automática"</string>
+ <string name="auto_replace_summary">"Corrigir palavras com erro de digitação"</string>
+ <string name="auto_caps">"Capitalização automática"</string>
+ <string name="auto_caps_summary">"Colocar a primeira letra das frases em maiúscula"</string>
+ <string name="auto_punctuate">"Pontuação automática"</string>
+ <!-- no translation found for hardkeyboard_category (5957168411305769899) -->
+ <skip />
+ <string name="auto_punctuate_summary">"Pressione a tecla Espaço duas vezes para inserir \".\""</string>
+ <string name="show_password">"Senhas visíveis"</string>
+ <string name="show_password_summary">"Mostrar a senha enquanto digita"</string>
+ <!-- no translation found for ime_security_warning (3458652708716006477) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_titlebar (765659257455000490) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_title (8357027437499042191) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_summary (2460427065601355471) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_add_menu_title (4056762757149923551) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_add_dialog_title (4702613990174126482) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_edit_dialog_title (8967476444840548674) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_context_menu_edit_title (2210564879320004837) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_context_menu_delete_title (9140703913776549054) -->
+ <skip />
+ <!-- no translation found for user_dict_settings_empty_text (6209268025109242806) -->
+ <skip />
+ <string name="testing">"Teste"</string>
+ <string name="testing_phone_info">"Informações do telefone"</string>
+ <string name="testing_battery_info">"Informações da bateria"</string>
+ <!-- no translation found for testing_battery_history (3043329445810695647) -->
+ <skip />
+ <string name="quick_launch_title">"Inicialização rápida"</string>
+ <string name="quick_launch_summary">"Define os atalhos do teclado para iniciar os aplicativos"</string>
+ <string name="quick_launch_assign_application">"Atribuir aplicativo"</string>
+ <string name="quick_launch_no_shortcut">"Sem atalho"</string>
+ <string name="quick_launch_shortcut">"Procurar + <xliff:g id="SHORTCUT_LETTER">%1$s</xliff:g>"</string>
+ <string name="quick_launch_clear_dialog_title">"Limpar"</string>
+ <string name="quick_launch_clear_dialog_message">"O atalho para <xliff:g id="SHORTCUT_LETTER">%1$s</xliff:g> (<xliff:g id="APPLICATION_NAME">%2$s</xliff:g>) será apagado."</string>
+ <string name="quick_launch_clear_ok_button">"OK"</string>
+ <string name="quick_launch_clear_cancel_button">"Cancelar"</string>
+ <string name="quick_launch_display_mode_applications">"Aplicativos"</string>
+ <string name="quick_launch_display_mode_shortcuts">"Atalhos"</string>
+ <string name="input_methods_settings_title">"Entrada de texto"</string>
+ <string name="input_methods_settings_summary">"Gerenciar opções de entrada de texto"</string>
+ <!-- no translation found for input_methods_settings_label_format (6002887604815693322) -->
+ <skip />
+ <!-- no translation found for onscreen_keyboard_settings_summary (4919680715154885028) -->
+ <skip />
+ <!-- no translation found for builtin_keyboard_settings_title (8169889453770863227) -->
+ <skip />
+ <!-- no translation found for builtin_keyboard_settings_summary (6404687907454621637) -->
+ <skip />
+ <string name="development_settings_title">"Desenvolvimento"</string>
+ <string name="development_settings_summary">"Definir opções para o desenvolvimento de aplicativos"</string>
+ <string name="enable_adb">"Depuração USB"</string>
+ <string name="enable_adb_summary">"Modo de depuração quando o USB está conectado"</string>
+ <string name="keep_screen_on">"Permanecer ativo"</string>
+ <string name="keep_screen_on_summary">"A tela nunca repousará durante o carregamento"</string>
+ <string name="allow_mock_location">"Permitir imitação de localização"</string>
+ <string name="allow_mock_location_summary">"Permitir imitação de localização"</string>
+ <!-- no translation found for gadget_picker_title (98374951396755811) -->
+ <skip />
+ <!-- no translation found for widget_picker_title (9130684134213467557) -->
+ <skip />
+ <!-- no translation found for battery_history_details_for (5189636461798594740) -->
+ <skip />
+ <!-- no translation found for battery_history_uid (1016606150528436298) -->
+ <skip />
+ <!-- no translation found for battery_history_network_usage (8010852371665217020) -->
+ <skip />
+ <!-- no translation found for battery_history_bytes_received (980307569180518302) -->
+ <skip />
+ <!-- no translation found for battery_history_bytes_sent (2501748768602119159) -->
+ <skip />
+ <!-- no translation found for battery_history_bytes_total (4444807574361642753) -->
+ <skip />
+ <!-- no translation found for battery_history_cpu_usage (2597353713014790877) -->
+ <skip />
+ <!-- no translation found for battery_history_user_time (6227507614894791359) -->
+ <skip />
+ <!-- no translation found for battery_history_system_time (2015862072724507547) -->
+ <skip />
+ <!-- no translation found for battery_history_total_time (3618703970098556104) -->
+ <skip />
+ <!-- no translation found for battery_history_starts (9137453931978571696) -->
+ <skip />
+ <!-- no translation found for battery_history_days (7820397518485221829) -->
+ <skip />
+ <!-- no translation found for battery_history_hours (102352608746026227) -->
+ <skip />
+ <!-- no translation found for battery_history_minutes (5344879003050455195) -->
+ <skip />
+ <!-- no translation found for battery_history_seconds (761623624964984375) -->
+ <skip />
+ <!-- no translation found for battery_history_packages_sharing_this_uid (4101596071379250050) -->
+ <skip />
+ <!-- no translation found for battery_history_no_data (1177238743237067617) -->
+ <skip />
+ <!-- no translation found for battery_history_sensor (2333488996028993982) -->
+ <skip />
+ <!-- no translation found for battery_history_wakelock (608683447522396293) -->
+ <skip />
+ <!-- no translation found for battery_history_used_by_packages (3000711380023436470) -->
+ <skip />
+ <!-- no translation found for battery_history_sensor_usage (3593133338613209024) -->
+ <skip />
+ <!-- no translation found for battery_history_sensor_usage_multi (4536084375991014508) -->
+ <skip />
+ <!-- no translation found for battery_history_awake_label (8449792868990080882) -->
+ <skip />
+ <!-- no translation found for battery_history_screen_on_label (1848936521786339362) -->
+ <skip />
+ <!-- no translation found for battery_history_phone_on_label (700191958853142297) -->
+ <skip />
+ <!-- no translation found for battery_history_awake (4350886665719031057) -->
+ <skip />
+ <!-- no translation found for battery_history_screen_on (1377240025275657277) -->
+ <skip />
+ <!-- no translation found for battery_history_phone_on (4891504401623839532) -->
+ <skip />
+ <!-- no translation found for battery_history_screen_on_battery (536058210445081888) -->
+ <skip />
+ <!-- no translation found for battery_history_screen_on_plugged (5019127390021871260) -->
+ <skip />
+ <!-- no translation found for usage_stats_label (5890846333487083609) -->
+ <skip />
+ <!-- no translation found for testing_usage_stats (7823048598893937339) -->
+ <skip />
+ <!-- no translation found for display_order_text (8592776965827565271) -->
+ <skip />
+ <!-- no translation found for app_name_label (2000949925256858308) -->
+ <skip />
+ <!-- no translation found for launch_count_label (4019444833263957024) -->
+ <skip />
+ <!-- no translation found for usage_time_label (295954901452833058) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_title (4239640930601071058) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_summary (8185181964847149507) -->
+ <skip />
+ <!-- no translation found for toggle_accessibility_title (650839277066574497) -->
+ <skip />
+ <!-- no translation found for enable_accessibility_service_summary (587346887866360112) -->
+ <skip />
+ <!-- no translation found for disable_accessibility_service_summary (3712100338753526029) -->
+ <skip />
+ <!-- no translation found for accessibility_services_category (8127851026323672607) -->
+ <skip />
+ <!-- no translation found for no_accessibility_services_summary (694578333333808159) -->
+ <skip />
+ <!-- no translation found for accessibility_service_security_warning (8386156287296967181) -->
+ <skip />
+ <!-- no translation found for accessibility_service_disable_warning (8930591383312775132) -->
+ <skip />
+ <!-- no translation found for power_usage_summary_title (6299347977868560167) -->
+ <skip />
+ <!-- no translation found for battery_since_unplugged (7650779969628963056) -->
+ <skip />
+ <!-- no translation found for battery_since_reset (8921307141345382144) -->
+ <skip />
+ <!-- no translation found for awake (387122265874485088) -->
+ <skip />
+ <!-- no translation found for wifi_on_time (4630925382578609056) -->
+ <skip />
+ <!-- no translation found for details_title (7884781172929635971) -->
+ <skip />
+ <!-- no translation found for details_subtitle (5086639882427527064) -->
+ <skip />
+ <!-- no translation found for controls_subtitle (3218143829900515242) -->
+ <skip />
+ <!-- no translation found for power_screen (1513495511309040704) -->
+ <skip />
+ <!-- no translation found for power_wifi (1185503168440278173) -->
+ <skip />
+ <!-- no translation found for power_cell (4633684550964059948) -->
+ <skip />
+ <!-- no translation found for power_phone (8900576354902742370) -->
+ <skip />
+ <!-- no translation found for power_idle (9036717846023423658) -->
+ <skip />
+ <!-- no translation found for usage_type_cpu (715162150698338714) -->
+ <skip />
+ <!-- no translation found for usage_type_cpu_foreground (6500579611933211831) -->
+ <skip />
+ <!-- no translation found for usage_type_gps (7989688715128160790) -->
+ <skip />
+ <!-- no translation found for usage_type_phone (9108247984998041853) -->
+ <skip />
+ <!-- no translation found for usage_type_data_send (2857401966985425427) -->
+ <skip />
+ <!-- no translation found for usage_type_data_recv (7251090882025234185) -->
+ <skip />
+ <!-- no translation found for usage_type_audio (6957269406840886290) -->
+ <skip />
+ <!-- no translation found for usage_type_video (4295357792078579944) -->
+ <skip />
+ <!-- no translation found for menu_stats_unplugged (7775586751038490112) -->
+ <skip />
+ <!-- no translation found for menu_stats_total (8973377864854807854) -->
+ <skip />
+ <!-- no translation found for menu_stats_refresh (1676215433344981075) -->
+ <skip />
+ <!-- no translation found for tts_settings (6454363854545277027) -->
+ <skip />
+ <!-- no translation found for tts_settings_summary (2627715231944602766) -->
+ <skip />
+ <!-- no translation found for tts_settings_title (5064947197040356736) -->
+ <skip />
+ <!-- no translation found for use_default_tts_settings_title (1577063839539732930) -->
+ <skip />
+ <!-- no translation found for use_default_tts_settings_summary (4253502106159206276) -->
+ <skip />
+ <!-- no translation found for tts_default_settings_section (5787915620218907443) -->
+ <skip />
+ <!-- no translation found for tts_default_rate_title (6030550998379310088) -->
+ <skip />
+ <!-- no translation found for tts_default_rate_summary (4061815292287182801) -->
+ <skip />
+ <!-- no translation found for tts_default_pitch_title (6135942113172488671) -->
+ <skip />
+ <!-- no translation found for tts_default_pitch_summary (1328298665182885277) -->
+ <skip />
+ <!-- no translation found for tts_available_synths_section (5787033928850926152) -->
+ <skip />
+ <!-- no translation found for gadget_title (7455548605888590466) -->
+ <skip />
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 5297e2f..ee7d1dc 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -107,10 +107,6 @@
<string name="date_and_time">"Настройки даты и времени"</string>
<string name="date_time_12_hour_sample">"13:00"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
- <skip />
- <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
- <skip />
<string name="choose_timezone">"Выбрать часовой пояс"</string>
<string name="display_preview_label">"Предварительный просмотр:"</string>
<string name="display_font_size_label">"Размер шрифта:"</string>
@@ -494,10 +490,6 @@
<string name="location_gps">"Включить спутники GPS"</string>
<string name="location_street_level">"Определение местоположения с точностью до улицы (для экономии заряда батареи отмените выбор)"</string>
<string name="location_gps_disabled">"Находить меня до уровня улицы (требуется больше заряда батареи, а также прямая видимость неба)"</string>
- <string name="location_warning_title">"Разрешение на отслеживание местоположения"</string>
- <string name="location_warning_message">"Разрешить Google собирать данные о местоположении без идентификации личной информации. Данные будут собираться, даже если не будет запущено ни одного приложения."</string>
- <string name="agree">"Принимаю"</string>
- <string name="disagree">"Не принимаю"</string>
<string name="about_settings">"О телефоне"</string>
<string name="about_settings_summary">"Просмотреть юридические сведения, состояние телефона, версию ПО"</string>
<string name="legal_information">"Юридическая информация"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 2089b98..1428b85 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -107,10 +107,6 @@
<string name="date_and_time">"日期和时间设置"</string>
<string name="date_time_12_hour_sample">"下午 1:00"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
- <skip />
- <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
- <skip />
<string name="choose_timezone">"选择时区"</string>
<string name="display_preview_label">"预览:"</string>
<string name="display_font_size_label">"字体大小:"</string>
@@ -495,14 +491,6 @@
<string name="location_gps">"启用 GPS 卫星设置"</string>
<string name="location_street_level">"定位时,精确到街道级别(取消选择可节约电量)"</string>
<string name="location_gps_disabled">"定位到街道级别(需要更多电量来观看天空)"</string>
- <!-- no translation found for location_warning_title (788624242969337259) -->
- <skip />
- <!-- no translation found for location_warning_message (2455390825908728808) -->
- <skip />
- <!-- no translation found for agree (6288718671527758326) -->
- <skip />
- <!-- no translation found for disagree (6221069272309799230) -->
- <skip />
<string name="about_settings">"关于手机"</string>
<string name="about_settings_summary">"查看法律信息、手机状态和软件版本"</string>
<string name="legal_information">"法律信息"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 0fe09eb..bbaae3d 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -21,7 +21,7 @@
<string name="turn_on_qxdm">"啟用 QXDM SD 記錄"</string>
<string name="turn_off_qxdm">"停用 QXDM SD 記錄"</string>
<string name="radioInfo_menu_viewADN">"檢視 SIM 地址簿"</string>
- <string name="radioInfo_menu_viewFDN">"檢視限制撥號號碼"</string>
+ <string name="radioInfo_menu_viewFDN">"查看固定撥號"</string>
<string name="radioInfo_menu_viewSDN">"檢視服務撥號號碼"</string>
<string name="radioInfo_menu_getPDP">"取得 PDP 清單"</string>
<string name="radioInfo_menu_enableData">"啟用資料連線"</string>
@@ -56,8 +56,8 @@
<string name="font_size_save">"確定"</string>
<string name="sdcard_setting">"SD 卡"</string>
<string name="battery_info_status_label">"電池狀態:"</string>
- <string name="battery_info_scale_label">"電池計量:"</string>
- <string name="battery_info_level_label">"電池計量:"</string>
+ <string name="battery_info_scale_label">"電池存量:"</string>
+ <string name="battery_info_level_label">"電池存量:"</string>
<string name="battery_info_health_label">"電池壽命:"</string>
<string name="battery_info_technology_label">"電池技術:"</string>
<string name="battery_info_voltage_label">"電池電壓:"</string>
@@ -89,9 +89,9 @@
<string name="bluetooth_device_name">"裝置名稱"</string>
<string name="bluetooth_name_not_set">"未設定名稱,使用帳戶名稱"</string>
<string name="bluetooth_scan_for_devices">"掃描裝置"</string>
- <string name="bluetooth_disconnect_blank">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>即將斷線。"</string>
+ <string name="bluetooth_disconnect_blank">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>即將中斷連線。"</string>
<string name="bluetooth_connected">"已連線"</string>
- <string name="bluetooth_disconnected">"連線中斷"</string>
+ <string name="bluetooth_disconnected">"已中斷連線"</string>
<string name="bluetooth_disconnecting">"連線中斷..."</string>
<string name="bluetooth_connecting">"連線中..."</string>
<!-- no translation found for bluetooth_unknown (644716244548801421) -->
@@ -107,10 +107,6 @@
<string name="date_and_time">"日期與時間設定"</string>
<string name="date_time_12_hour_sample">"下午 1:00"</string>
<string name="date_time_24_hour_sample">"13:00"</string>
- <!-- no translation found for date_time_changeTime_text (7037437020000867740) -->
- <skip />
- <!-- no translation found for date_time_changeDate_text (5259762626498028057) -->
- <skip />
<string name="choose_timezone">"選取時區"</string>
<string name="display_preview_label">"預覽:"</string>
<string name="display_font_size_label">"字型大小:"</string>
@@ -179,8 +175,8 @@
<string name="sdcard_settings_used_bytes_label">"使用容量 (bytes):"</string>
<string name="sdcard_settings_scanning_status">"從 SD 卡掃描媒體中..."</string>
<string name="sdcard_settings_read_only_status">"SD 卡為唯讀狀態"</string>
- <string name="next_label">"下一步"</string>
- <string name="language_picker_title">"地區"</string>
+ <string name="next_label">"下一頁"</string>
+ <string name="language_picker_title">"地區設定"</string>
<string name="select_your_language">"選取語言"</string>
<string name="activity_picker_label">"選取動作"</string>
<string name="device_info_label">"裝置資訊"</string>
@@ -193,9 +189,9 @@
<string name="cancel">"取消"</string>
<string name="settings_label">"設定"</string>
<string name="airplane_mode">"飛航模式"</string>
- <string name="airplane_mode_summary">"停用所有的無線連線"</string>
+ <string name="airplane_mode_summary">"停用所有的無線網路連線"</string>
<string name="airplane_mode_turning_on">"停用無線網路連線中..."</string>
- <string name="airplane_mode_turning_off">"啟動無線網路連線中..."</string>
+ <string name="airplane_mode_turning_off">"啟用無線網路連線中..."</string>
<string name="radio_controls_title">"無線網路控制"</string>
<string name="radio_controls_summary">"管理 Wi-Fi、藍牙、飛航模式與行動網路"</string>
<string name="date_and_time_settings_title">"日期與時間"</string>
@@ -210,7 +206,7 @@
<string name="date_time_date_format">"選取日期格式"</string>
<string name="zone_list_menu_sort_alphabetically">"依照字母排序"</string>
<string name="zone_list_menu_sort_by_timezone">"依時區排序"</string>
- <string name="security_settings_title">"安全與位置"</string>
+ <string name="security_settings_title">"安全性與位置"</string>
<string name="security_settings_summary">"設定我的位置、螢幕解鎖、SIM 卡鎖定"</string>
<string name="security_passwords_title">"密碼"</string>
<string name="bluetooth_quick_toggle_title">"藍牙"</string>
@@ -227,10 +223,10 @@
<string name="bluetooth_connecting_error_message">"連接至<xliff:g id="DEVICE_NAME">%1$s</xliff:g>時發生問題。"</string>
<string name="bluetooth_preference_scan_title">"掃描裝置"</string>
<string name="bluetooth_device_context_connect">"連線"</string>
- <string name="bluetooth_device_context_disconnect">"斷線"</string>
+ <string name="bluetooth_device_context_disconnect">"中斷連線"</string>
<string name="bluetooth_device_context_pair_connect">"配對並連線"</string>
<string name="bluetooth_device_context_unpair">"解除配對"</string>
- <string name="bluetooth_device_context_disconnect_unpair">"中斷連接並解除配對"</string>
+ <string name="bluetooth_device_context_disconnect_unpair">"中斷連線並解除配對"</string>
<string name="bluetooth_device_context_connect_advanced">"選項..."</string>
<string name="bluetooth_connect_specific_profiles_title">"連線到..."</string>
<string name="bluetooth_profile_a2dp">"媒體"</string>
@@ -244,21 +240,21 @@
<string name="bluetooth_device_advanced_profile_header_title">"設定檔"</string>
<string name="bluetooth_a2dp_profile_summary_connected">"連接至媒體音訊"</string>
<string name="bluetooth_headset_profile_summary_connected">"連接至電話音訊"</string>
- <string name="bluetooth_a2dp_profile_summary_use_for">"用作媒體音訊"</string>
- <string name="bluetooth_headset_profile_summary_use_for">"用作電話音訊"</string>
+ <string name="bluetooth_a2dp_profile_summary_use_for">"用於媒體音訊"</string>
+ <string name="bluetooth_headset_profile_summary_use_for">"用於電話音訊"</string>
<string name="wifi">"Wi-Fi"</string>
<string name="wifi_quick_toggle_title">"Wi-Fi"</string>
<string name="wifi_quick_toggle_summary">"開啟 Wi-Fi"</string>
<string name="wifi_settings">"Wi-Fi 設定"</string>
<string name="wifi_settings_category">"Wi-Fi 設定"</string>
- <string name="wifi_settings_summary">"設定、管理無線存取點"</string>
+ <string name="wifi_settings_summary">"設定、管理無線網路存取點"</string>
<string name="forget_network">"清除"</string>
<string name="wifi_status">"狀態"</string>
<string name="wifi_link_speed">"速度"</string>
- <string name="wifi_signal_3">"極佳"</string>
- <string name="wifi_signal_2">"好"</string>
- <string name="wifi_signal_1">"差"</string>
- <string name="wifi_signal_0">"微弱"</string>
+ <string name="wifi_signal_3">"優"</string>
+ <string name="wifi_signal_2">"良"</string>
+ <string name="wifi_signal_1">"可"</string>
+ <string name="wifi_signal_0">"差"</string>
<string name="security">"安全性"</string>
<string name="wifi_security_open">"開啟"</string>
<string name="wifi_security_wep">"WEP"</string>
@@ -274,7 +270,7 @@
<string name="wifi_starting">"開啟中..."</string>
<string name="wifi_stopping">"關閉中..."</string>
<string name="wifi_error">"錯誤"</string>
- <string name="error_starting">"無法開始 Wi-Fi"</string>
+ <string name="error_starting">"無法開啟 Wi-Fi"</string>
<string name="error_stopping">"無法停止 Wi-Fi"</string>
<string name="error_scanning">"無法掃描網路"</string>
<string name="error_connecting">"無法連線到此網路"</string>
@@ -326,24 +322,23 @@
<string name="fragment_status_authenticating">"驗證 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> 中..."</string>
<string name="fragment_status_obtaining_ip">"從 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> 取得 IP 位址中..."</string>
<string name="fragment_status_connected">"已連線到 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="fragment_status_disconnecting">"從 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> 斷線中..."</string>
- <string name="fragment_status_disconnected">"連線中斷"</string>
+ <string name="fragment_status_disconnecting">"自 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> 中斷連線中..."</string>
+ <string name="fragment_status_disconnected">"已中斷連線"</string>
<string name="fragment_status_failed">"失敗"</string>
<string name="status_scanning">"掃描中..."</string>
<string name="status_connecting">"連線中..."</string>
- <string name="status_authenticating">"認證中..."</string>
+ <string name="status_authenticating">"驗證中..."</string>
<string name="status_obtaining_ip">"取得位址中..."</string>
<string name="status_connected">"已連線"</string>
<string name="status_disconnecting">"連線中斷..."</string>
- <string name="status_disconnected">"連線中斷"</string>
+ <string name="status_disconnected">"已中斷連線"</string>
<string name="status_failed">"失敗"</string>
<string name="sound_and_display_settings">"音效與顯示"</string>
<string name="sound_settings">"音效設定"</string>
<string name="sound_and_display_settings_summary">"設定鈴聲、通知與螢幕亮度"</string>
<string name="silent_mode_title">"靜音模式"</string>
<string name="silent_mode_summary">"將媒體和鬧鐘以外的所有音效靜音"</string>
- <!-- no translation found for silent_mode_incl_alarm_summary (2088830834182228458) -->
- <skip />
+ <string name="silent_mode_incl_alarm_summary">"將所有非媒體音效設為靜音"</string>
<string name="ringtone_title">"電話鈴聲"</string>
<string name="ringtone_summary">"設定預設來電鈴聲"</string>
<string name="ring_volume_title">"鈴聲音量"</string>
@@ -358,16 +353,16 @@
<string name="notification_sound_dialog_title">"選取通知鈴聲"</string>
<string name="media_volume_title">"媒體音量"</string>
<string name="media_volume_summary">"設定音樂與影片的音量"</string>
- <string name="dtmf_tone_enable_title">"觸碰音效"</string>
+ <string name="dtmf_tone_enable_title">"觸控音效"</string>
<string name="dtmf_tone_enable_summary_on">"使用撥號面板時播放按鍵音效"</string>
<string name="dtmf_tone_enable_summary_off">"使用撥號面板時播放按鍵音效"</string>
- <string name="sound_effects_enable_title">"可聽見選項"</string>
+ <string name="sound_effects_enable_title">"有聲選項"</string>
<string name="sound_effects_enable_summary_on">"使用螢幕選取時播放音效"</string>
- <string name="sound_effects_enable_summary_off">"使用螢幕選取時播放音效"</string>
+ <string name="sound_effects_enable_summary_off">"在螢幕上進行選取時播放音效"</string>
<string name="play_media_notification_sounds_enable_title">"SD 卡通知"</string>
<string name="play_media_notification_sounds_enable_summary_on">"停用 SD 卡通知音效"</string>
<string name="play_media_notification_sounds_enable_summary_off">"啟用 SD 卡通知音效"</string>
- <string name="sync_settings">"資料同步化"</string>
+ <string name="sync_settings">"資料同步處理"</string>
<string name="sync_settings_summary">"選取要同步處理的應用程式"</string>
<string name="display_settings">"顯示設定"</string>
<string name="animations_title">"動畫"</string>
@@ -438,7 +433,7 @@
<string name="sd_unavailable">"無法取得資訊"</string>
<string name="read_only">" (唯讀)"</string>
<string name="battery_status_title">"電池狀態"</string>
- <string name="battery_level_title">"電池計量"</string>
+ <string name="battery_level_title">"電池存量"</string>
<string name="apn_settings">"APN"</string>
<string name="apn_edit">"編輯存取點"</string>
<string name="apn_not_set">"(未設定)"</string>
@@ -467,42 +462,34 @@
<string name="restore_default_apn">"正在還原預設 APN 設定"</string>
<string name="menu_restore">"還原為預設狀態"</string>
<string name="restore_default_apn_completed">"重設預設 APN 設定已完成"</string>
- <string name="master_clear_title">"出廠資料重設"</string>
+ <string name="master_clear_title">"重設為原廠設定"</string>
<string name="master_clear_summary">"清除手機上所有資料"</string>
- <string name="master_clear_desc">"此項操作會將手機回復至出廠設定,清除所有資料與下載的應用程式!"</string>
+ <string name="master_clear_desc">"此項操作會將手機還原至出廠設定,並清除所有資料與下載的應用程式!"</string>
<string name="master_clear_button_text">"重設手機"</string>
- <string name="master_clear_final_desc">"確定要重設手機,清除所有資料與應用程式?此項操作無法復原!"</string>
+ <string name="master_clear_final_desc">"確定要重設手機,清除所有資料與應用程式嗎?此項操作將無法復原!"</string>
<string name="master_clear_final_button_text">"清除全部"</string>
<string name="master_clear_gesture_prompt">"畫出解鎖圖形"</string>
<string name="master_clear_gesture_explanation">"請畫出解鎖圖形,以確認重設手機。"</string>
<string name="master_clear_failed">"因「系統清除」服務異常,未成功執行重設。"</string>
<string name="media_format_title">"將 SD 卡格式化。"</string>
<string name="media_format_summary">"清除 SD 卡上的所有資料"</string>
- <string name="media_format_desc">"此動作將會清除手機中 SD 卡上的所有資料。SD 卡上的所有資料將會遺失!"</string>
+ <string name="media_format_desc">"此項操作將清除手機中 SD 卡上的資料。SD 卡上的全部資料將會消失!"</string>
<string name="media_format_button_text">"將 SD 卡格式化"</string>
- <string name="media_format_final_desc">"要將 SD 卡格式化、清除所有媒體嗎?此動作無法復原!"</string>
+ <string name="media_format_final_desc">"確定要將 SD 卡格式化、清除所有媒體嗎?此項操作將無法復原!"</string>
<string name="media_format_final_button_text">"全部清除"</string>
<string name="media_format_gesture_prompt">"畫出解鎖圖形"</string>
<string name="media_format_gesture_explanation">"您必須畫出解鎖圖形,以確認將 SD 卡格式化。"</string>
<string name="call_settings_title">"通話設定"</string>
- <string name="call_settings_summary">"設定語音信箱、來電指定轉接、話中插接、本機號碼"</string>
+ <string name="call_settings_summary">"設定語音信箱、來電轉接、來電待接及本機號碼顯示"</string>
<string name="network_settings_title">"行動網路"</string>
<string name="network_settings_summary">"設定漫遊、網路、APN 選項"</string>
<string name="location_title">"我的位置來源"</string>
<string name="location_network_based">"使用無線網路"</string>
<string name="location_networks_disabled">"使用無線網路,在應用程式中查詢位置 (例如 Google 地圖)"</string>
- <string name="location_neighborhood_level">"位置根據 Wi-Fi 與/或行動網路決定"</string>
+ <string name="location_neighborhood_level">"根據 Wi-Fi 與/或行動網路判定位置"</string>
<string name="location_gps">"啟用 GPS 衛星接收器"</string>
- <string name="location_street_level">"定位時,精準度設定為街道層級 (不選此項較省電)"</string>
- <string name="location_gps_disabled">"切換到街道檢視 (需要更多電力及天候允許)"</string>
- <!-- no translation found for location_warning_title (788624242969337259) -->
- <skip />
- <!-- no translation found for location_warning_message (2455390825908728808) -->
- <skip />
- <!-- no translation found for agree (6288718671527758326) -->
- <skip />
- <!-- no translation found for disagree (6221069272309799230) -->
- <skip />
+ <string name="location_street_level">"定位時,精準度設定為街道等級 (取消選取此項可較省電)"</string>
+ <string name="location_gps_disabled">"定位至街道等級 (需要更多電力及天候允許)"</string>
<string name="about_settings">"關於手機"</string>
<string name="about_settings_summary">"檢視法律資訊、手機狀態、軟體版本"</string>
<string name="legal_information">"法律資訊"</string>
@@ -510,19 +497,17 @@
<string name="copyright_title">"版權"</string>
<string name="license_title">"授權"</string>
<string name="terms_title">"條款及細則"</string>
- <!-- no translation found for system_tutorial_list_item_title (4315834755909579018) -->
- <skip />
- <!-- no translation found for system_tutorial_list_item_summary (3861815254521030201) -->
- <skip />
+ <string name="system_tutorial_list_item_title">"系統教學課程"</string>
+ <string name="system_tutorial_list_item_summary">"瞭解如何使用您的手機"</string>
<string name="settings_license_activity_title">"開啟原始授權"</string>
<string name="settings_license_activity_unavailable">"載入授權時發生問題"</string>
<string name="settings_license_activity_loading">"載入中..."</string>
<string name="lock_settings_title">"螢幕解鎖圖形"</string>
<string name="lockpattern_change_lock_pattern_label">"變更解鎖圖形"</string>
<string name="lockpattern_need_to_unlock">"確認儲存的圖形"</string>
- <string name="lockpattern_need_to_unlock_wrong">"抱歉,請再試一次:"</string>
+ <string name="lockpattern_need_to_unlock_wrong">"很抱歉,請再試一次:"</string>
<string name="lockpattern_recording_intro_header">"畫出解鎖圖形"</string>
- <string name="lockpattern_recording_intro_footer">"按下 [選單] 尋求幫助。"</string>
+ <string name="lockpattern_recording_intro_footer">"請按 [選單] 以取得說明。"</string>
<string name="lockpattern_recording_inprogress">"完成後手指離開。"</string>
<string name="lockpattern_recording_incorrect_too_short">"請連接至少 <xliff:g id="NUMBER">%d</xliff:g> 點。再試一次:"</string>
<string name="lockpattern_pattern_entered_header">"圖形已記錄!"</string>
@@ -543,23 +528,23 @@
<string name="lockpattern_too_many_failed_confirmation_attempts_header">"錯誤嘗試太多!"</string>
<string name="lockpattern_too_many_failed_confirmation_attempts_footer">"<xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。"</string>
<string name="skip_button_label">"取消"</string>
- <string name="next_button_label">"下一步"</string>
+ <string name="next_button_label">"下一頁"</string>
<string name="lock_title">"手機安全設定"</string>
- <string name="lock_intro_message"><font size="17">" 建立個人螢幕解鎖圖形,避免您的手機在未授權狀態下被使用。"\n<font height="17">\n</font><b>" 1 "</b>" 在下個螢幕中,檢視範例圖形繪畫示範。"\n<font height="17">\n</font><b>" 2 "</b>" 您準備好後,便可畫出個人解鎖圖形。您可以嘗試不同的圖形,但需要至少連接四點。"\n<font height="17">\n</font><b>" 3 "</b>" 再次畫出圖形以確認。"\n<font height="17">\n</font><b>" 準備開始了嗎?選取 [下一步]"</b>"。"\n<font height="3">\n</font>" 若要保持未保護狀態,請選取 [取消]。"</font></string>
+ <string name="lock_intro_message"><font size="17">" 建立個人螢幕解鎖圖形,避免您的手機在未授權狀態下遭人使用。 "\n<font height="17">\n</font><b>" 1 "</b>" 請在下一個畫面中,檢視範例圖形繪畫示範。"\n<font height="17">\n</font><b>" 2 "</b>" 準備好後,便可畫出個人解鎖圖形。您可以嘗試不同的圖形,但需要至少連接四點。 "\n<font height="17">\n</font><b>" 3 "</b>" 再次畫出圖形以確認。"\n<font height="17">\n</font><b>" 準備開始了嗎?選取 [下一步]"</b>"。"\n<font height="3">\n</font>" 如要維持未保護的狀態,請選取 [取消]。"</font></string>
<string name="lock_example_title">"範例圖形"</string>
<string name="lock_example_message">"畫出圖形時,需要至少連接四個點。"\n" "\n"準備好要畫出您的解鎖圖形時,請選取 [下一步]。"</string>
<string name="manageapplications_settings_title">"管理應用程式"</string>
<string name="manageapplications_settings_summary">"管理及移除已安裝的應用程式"</string>
<string name="applications_settings">"應用程式"</string>
- <string name="applications_settings_summary">"管理應用程式,設定快速啟動捷徑"</string>
+ <string name="applications_settings_summary">"管理應用程式,設定快速啟動鍵"</string>
<string name="applications_settings_header">"應用程式設定"</string>
<string name="install_applications">"未知的來源"</string>
- <string name="install_unknown_applications">"允許安裝非市場應用程式"</string>
- <string name="install_all_warning">"如果是未知來源的應用程式,便比較可能攻擊您的手機與個人資訊。若使用這些應用程式造成手機受損或資料遺失,您必須為此完全負責。"</string>
+ <string name="install_unknown_applications">"允許安裝非 Market 應用程式"</string>
+ <string name="install_all_warning">"未知來源的應用程式可能會損害您的手機及個人資訊。如使用這些應用程式而造成手機受損或資料遺失,您必須自行承擔責任。"</string>
<string name="application_info_label">"應用程式資訊"</string>
- <string name="storage_label">"儲存"</string>
- <string name="auto_launch_label">"依預設值啟動"</string>
- <string name="permissions_label">"許可"</string>
+ <string name="storage_label">"儲存空間"</string>
+ <string name="auto_launch_label">"預設為啟動"</string>
+ <string name="permissions_label">"權限"</string>
<string name="cache_header_label">"快取"</string>
<string name="clear_cache_btn_text">"清除快取"</string>
<string name="cache_size_label">"快取"</string>
@@ -570,7 +555,7 @@
<string name="data_size_label">"資料"</string>
<string name="uninstall_text">"解除安裝"</string>
<string name="clear_user_data_text">"清除資料"</string>
- <string name="auto_launch_enable_text">"您已設定在某些動作下啟動此應用程式。"</string>
+ <string name="auto_launch_enable_text">"您已設定在某些操作下啟動此應用程式。"</string>
<string name="auto_launch_disable_text">"沒有預設值。"</string>
<string name="clear_activities">"清除預設值"</string>
<string name="unknown">"未知的"</string>
@@ -594,24 +579,23 @@
<string name="security_settings_desc">"此應用程式可存取您電話中的下列項目:"</string>
<string name="computing_size">"計算中..."</string>
<string name="invalid_size_value">"無法計算封裝大小"</string>
- <string name="empty_list_msg">"您尚未安裝任何的第三方應用程式。"</string>
- <string name="language_settings">"地區與文字"</string>
- <string name="language_settings_summary">"設定地區 (語言和地區)、文字輸入和文字自動校正選項"</string>
+ <string name="empty_list_msg">"您未安裝任何第三方應用程式。"</string>
+ <string name="language_settings">"地區設定與文字"</string>
+ <string name="language_settings_summary">"選取地區設定 (語言和地區)、文字輸入和自動校正選項"</string>
<string name="language_category">"地區設定"</string>
<string name="text_category">"文字設定"</string>
- <string name="phone_language">"選取地區"</string>
+ <string name="phone_language">"選取地區設定"</string>
<string name="phone_language_summary">"選取語言及地區"</string>
- <string name="auto_replace">"自動取代"</string>
+ <string name="auto_replace">"自動替換"</string>
<string name="auto_replace_summary">"修改不正確的字"</string>
<string name="auto_caps">"自動大寫"</string>
- <string name="auto_caps_summary">"句子首字字母大寫"</string>
+ <string name="auto_caps_summary">"句首字母大寫"</string>
<string name="auto_punctuate">"自動標點"</string>
<string name="hardkeyboard_category">"實體鍵盤設定"</string>
<string name="auto_punctuate_summary">"按空白鍵兩次可插入「.」"</string>
- <string name="show_password">"密碼可見"</string>
+ <string name="show_password">"顯示密碼"</string>
<string name="show_password_summary">"顯示輸入的密碼"</string>
- <!-- no translation found for ime_security_warning (3458652708716006477) -->
- <skip />
+ <string name="ime_security_warning">"此輸入法可能會收集您輸入的所有文字,包括密碼和信用卡號等個人資料。此輸入法來自 <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> 應用程式。是否啟用此輸入法?"</string>
<string name="user_dict_settings_titlebar">"使用者字典"</string>
<string name="user_dict_settings_title">"使用者字典"</string>
<string name="user_dict_settings_summary">"在使用者字典中新增及移除字詞"</string>
@@ -620,22 +604,22 @@
<string name="user_dict_settings_edit_dialog_title">"編輯文字"</string>
<string name="user_dict_settings_context_menu_edit_title">"編輯"</string>
<string name="user_dict_settings_context_menu_delete_title">"刪除"</string>
- <string name="user_dict_settings_empty_text">"您的使用者字典中沒有任何字詞。您可以透過選單新增字詞。"</string>
+ <string name="user_dict_settings_empty_text">"您的使用者字典中沒有任何字詞。您可以透過 [選單] 新增字詞。"</string>
<string name="testing">"測試中"</string>
<string name="testing_phone_info">"手機資訊"</string>
<string name="testing_battery_info">"電池資訊"</string>
<string name="testing_battery_history">"電池記錄"</string>
<string name="quick_launch_title">"快速啟動"</string>
- <string name="quick_launch_summary">"設定啟動應用程式的鍵盤捷徑"</string>
- <string name="quick_launch_assign_application">"分配應用程式"</string>
- <string name="quick_launch_no_shortcut">"沒有捷徑"</string>
+ <string name="quick_launch_summary">"設定啟動應用程式的鍵盤快速鍵"</string>
+ <string name="quick_launch_assign_application">"指派應用程式"</string>
+ <string name="quick_launch_no_shortcut">"沒有快速建"</string>
<string name="quick_launch_shortcut">"搜尋 + <xliff:g id="SHORTCUT_LETTER">%1$s</xliff:g>"</string>
<string name="quick_launch_clear_dialog_title">"清除"</string>
<string name="quick_launch_clear_dialog_message">"<xliff:g id="SHORTCUT_LETTER">%1$s</xliff:g> (<xliff:g id="APPLICATION_NAME">%2$s</xliff:g>) 的捷徑會被清除。"</string>
<string name="quick_launch_clear_ok_button">"確定"</string>
<string name="quick_launch_clear_cancel_button">"取消"</string>
<string name="quick_launch_display_mode_applications">"應用程式"</string>
- <string name="quick_launch_display_mode_shortcuts">"捷徑"</string>
+ <string name="quick_launch_display_mode_shortcuts">"快速鍵"</string>
<string name="input_methods_settings_title">"文字輸入法"</string>
<string name="input_methods_settings_summary">"管理輸入法選項"</string>
<string name="input_methods_settings_label_format">"<xliff:g id="IME_NAME">%1$s</xliff:g> 設定"</string>
@@ -643,9 +627,9 @@
<string name="builtin_keyboard_settings_title">"裝置小鍵盤"</string>
<string name="builtin_keyboard_settings_summary">"內建小鍵盤設定"</string>
<string name="development_settings_title">"開發"</string>
- <string name="development_settings_summary">"設定應用程式開發的選項"</string>
- <string name="enable_adb">"USB 除錯中"</string>
- <string name="enable_adb_summary">"USB 連線時進入除錯模式"</string>
+ <string name="development_settings_summary">"設定應用程式開發選項"</string>
+ <string name="enable_adb">"USB 偵錯"</string>
+ <string name="enable_adb_summary">"連接 USB 時進入偵錯模式"</string>
<string name="keep_screen_on">"保持清醒"</string>
<string name="keep_screen_on_summary">"充電時螢幕不會進入休眠"</string>
<string name="allow_mock_location">"允許模擬位置"</string>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 6cfa7f0..a470acc 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -39,18 +39,12 @@
<item>All</item>
</string-array>
- <!-- There is a setting to control the format of dates displayed throughout the system. This is in the Date & Time Settings screen. Unfortunately, these cannot be changed at all. --> <skip />
- <!-- Do not translate. This is fed directly to the formatter. -->
- <string-array name="date_format_values">
- <!-- Do not translate. This is fed directly to the formatter. -->
+ <!-- There is a setting to control the format of dates displayed throughout the system. This is in the Date & Time Settings screen. These will be adjusted to use punctuation appropriate to the user's locale. -->
+ <string-array name="date_format_values" translatable="false">
+ <!-- The blank item means to use whatever the locale calls for. -->
+ <item></item>
<item>MM-dd-yyyy</item>
- <!-- Do not translate. This is fed directly to the formatter. -->
<item>dd-MM-yyyy</item>
- <!-- Do not translate. This is fed directly to the formatter. -->
- <item>MMM d, yyyy</item>
- <!-- Do not translate. This is fed directly to the formatter. -->
- <item>d-MMM-yyyy</item>
- <!-- Do not translate. This is fed directly to the formatter. -->
<item>yyyy-MM-dd</item>
</string-array>
@@ -81,6 +75,61 @@
<item>-1</item>
</string-array>
+ <!-- TTS settings -->
+
+ <!-- Default speech rate choices -->
+ <string-array name="tts_rate_entries">
+ <item>Very slow</item>
+ <item>Slow</item>
+ <item>Normal</item>
+ <item>Fast</item>
+ <item>Very fast</item>
+ </string-array>
+ <!-- Do not translate. -->
+ <string-array name="tts_rate_values">
+ <item>60</item>
+ <item>80</item>
+ <item>100</item>
+ <item>150</item>
+ <item>200</item>
+ </string-array>
+
+ <!-- Default pitch choices -->
+ <string-array name="tts_pitch_entries">
+ <item>Very low</item>
+ <item>Low</item>
+ <item>Normal</item>
+ <item>High</item>
+ <item>Very high</item>
+ </string-array>
+ <!-- Do not translate. -->
+ <string-array name="tts_pitch_values">
+ <item>50</item>
+ <item>80</item>
+ <item>100</item>
+ <item>120</item>
+ <item>150</item>
+ </string-array>
+
+ <!-- Default language choices -->
+ <string-array name="tts_lang_entries">
+ <item>American English</item>
+ <item>British English</item>
+ <item>French</item>
+ <item>German</item>
+ <item>Italian</item>
+ <item>Spanish</item>
+ </string-array>
+ <!-- Do not translate. -->
+ <string-array name="tts_lang_values">
+ <item>eng-USA</item>
+ <item>eng-GBR</item>
+ <item>fra-FRA</item>
+ <item>deu-DEU</item>
+ <item>ita-ITA</item>
+ <item>spa-ESP</item>
+ </string-array>
+
<!-- Wi-Fi settings -->
<!-- Match this with code. --> <skip />
@@ -93,9 +142,13 @@
<!-- Do not translate. The Wi-Fi network has WEP security. -->
<item>WEP</item>
<!-- The Wi-Fi network has WPA personal security. WPA Personal is a tech term, and might be better left untranslated? -->
- <item>WPA Personal</item>
+ <item>WPA personal</item>
<!-- The Wi-Fi network has WPA2 personal security. WPA Personal is a tech term, and might be better left untranslated? -->
- <item>WPA2 Personal</item>
+ <item>WPA2 personal</item>
+ <!-- The Wi-Fi network has WPA EAP extensible authentication protocol. -->
+ <item>WPA-EAP</item>
+ <!-- IEEE 802.1X key management -->
+ <item>IEEE 802.1x</item>
</string-array>
<!-- Match this with code. --> <skip />
@@ -106,9 +159,14 @@
<!-- Do not translate. The Wi-Fi network has WEP security. -->
<item>WEP</item>
<!-- The Wi-Fi network has WPA personal security. WPA Personal is a tech term, and might be better left untranslated? -->
- <item>WPA Personal</item>
+ <item>WPA personal</item>
<!-- The Wi-Fi network has WPA2 personal security. WPA Personal is a tech term, and might be better left untranslated? -->
- <item>WPA2 Personal</item>
+ <item>WPA2 personal</item>
+ <!-- The Wi-Fi network has WPA enterprise security. WPA Enterprise is a tech term, and might be better left untranslated? -->
+ <!-- The Wi-Fi network has WPA EAP extensible authentication protocol. -->
+ <item>WPA-EAP</item>
+ <!-- IEEE 802.1X key management -->
+ <item>IEEE 802.1x</item>
</string-array>
<!-- Match this with code. --> <skip />
@@ -167,4 +225,34 @@
<item>Application Name</item>
</string-array>
+ <!-- EAP method -->
+ <string-array name="wifi_eap_entries">
+ <item>PEAP</item>
+ <item>TLS</item>
+ <item>TTLS</item>
+ </string-array>
+
+ <!-- Phase 2 options -->
+ <string-array name="wifi_phase2_entries">
+ <item>None</item>
+ <item>PAP</item>
+ <item>MSCHAP</item>
+ <item>MSCHAP2</item>
+ <item>GTC</item>
+ </string-array>
+
+ <!-- Sound settings for emergency tone. -->
+ <string-array name="emergency_tone_entries">
+ <item>Off</item>
+ <item>Alert</item>
+ <item>Vibrate</item>
+ </string-array>
+
+ <!-- Do not translate. -->
+ <string-array name="emergency_tone_values">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ </string-array>
+
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a170c92..193388c 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -16,5 +16,6 @@
<resources>
<color name="black">#000</color>
+ <color name="red">#F00</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
new file mode 100755
index 0000000..790f86b
--- /dev/null
+++ b/res/values/dimens.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="vpn_connect_margin_right">10sp</dimen>
+ <dimen name="vpn_connect_normal_text_size">16sp</dimen>
+ <dimen name="vpn_connect_input_box_label_width">90sp</dimen>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 70e1618..8af3c58 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -243,6 +243,10 @@
<!-- Do not translate. Used as the value for a setting. -->
<string name="default_date_format"><xliff:g id="default_date_format">MM/dd/yyyy</xliff:g></string>
+ <!-- The option in the date-format picker for using the normal format
+ called for by the user's locale. -->
+ <string name="normal_date_format">Normal (<xliff:g id="date" example="12-31-2009">%s</xliff:g>)</string>
+
<!-- Label of preview text when tweaking font size -->
<string name="display_preview_label">Preview:</string>
<!-- Label for chosen font size -->
@@ -291,6 +295,7 @@
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_data_attempts_label">Data attempts:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+
<string name="radio_info_gprs_service_label">GPRS service:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_roaming_label">Roaming:</string>
@@ -419,6 +424,8 @@
<!-- Main Settings screen title -->
<string name="settings_label">Settings</string>
+ <!-- Label for option to select a settings panel as a shortcut -->
+ <string name="settings_shortcut">Settings</string>
<!-- Wireless controls settings screen, setting check box label -->
<string name="airplane_mode">Airplane mode</string>
<!-- Wireless controls settings screen, setting option summary text -->
@@ -430,9 +437,28 @@
<!-- Main Settings screen settings title for things like Wi-Fi, bluetooth, airplane mode. This will take you to another screen with those settings. -->
<string name="radio_controls_title">Wireless controls</string>
<!-- Main Settings screen settings summary text for the "Wireless controls" setting -->
- <string name="radio_controls_summary">Manage Wi-Fi, Bluetooth, airplane mode, & mobile networks</string>
+ <string name="radio_controls_summary">Manage Wi-Fi, Bluetooth, airplane mode, mobile networks, & VPNs</string>
+ <!-- mobile network settings screen, setting check box title -->
+ <string name="roaming">Data roaming</string>
+ <!-- mobile network settings screen, setting option summary text when check box is selected -->
+ <string name="roaming_enable">Connect to data services when roaming</string>
+ <!-- mobile network settings screen, setting option summary text when check box is clear -->
+ <string name="roaming_disable">Connect to data services when roaming</string>
+ <!-- mobile network settings screen, dialog message when you are roaming and clear the "Data roaming" check box -->
+ <string name="roaming_reenable_message">You have lost data connectivity because you left your home network with data roaming turned off.</string>
+ <!-- mobile network settings screen, button on dialog box that appears when you are roaming and clear the "Data roaming" check box -->
+ <string name="roaming_turn_it_on_button">Turn it on</string>
+ <!-- mobile network settings screen, message in dialog box that appears when you select the "Data roaming" check box -->
+ <string name="roaming_warning">Allow data roaming? You may incur significant roaming charges!</string>
+ <!-- mobile network settings screen, title of dialog box that appears when you select the "Data roaming" check box -->
+ <string name="roaming_reenable_title">Attention</string>
+ <!-- mobile network settings screen, setting option name -->
+ <string name="networks">Operator selection</string>
+ <!-- mobile network settings screen, setting option summary text -->
+ <string name="sum_carrier_select">Select a network operator</string>
+
<!-- Date and time settings -->
<!-- Main Settings screen setting option name to go into the date and time settings-->
<string name="date_and_time_settings_title">Date & time</string>
@@ -462,7 +488,7 @@
<!-- Main Settings screen setting option title for the item to take you the security and location screen -->
<string name="security_settings_title">Security & location</string>
<!-- Main Settings screen setting option summary text for the item tot ake you to the security and location screen -->
- <string name="security_settings_summary">Set My Location, screen unlock, SIM card lock</string>
+ <string name="security_settings_summary">Set My Location, screen unlock, SIM card lock, credential storage lock</string>
<!-- In the security screen, the header title for settings related to Passwords-->
<string name="security_passwords_title">Passwords</string>
@@ -491,6 +517,10 @@
<string name="bluetooth_pairing_error_message">There was a problem pairing with <xliff:g id="device_name">%1$s</xliff:g>.</string>
<!-- Message for the error dialog when BT pairing fails because the PIN entered is incorrect. -->
<string name="bluetooth_pairing_pin_error_message">There was a problem pairing with <xliff:g id="device_name">%1$s</xliff:g> because the typed PIN is incorrect.</string>
+ <!-- Message for the error dialog when BT pairing fails because the other device is down. -->
+ <string name="bluetooth_pairing_device_down_error_message">Cannot establish communication with <xliff:g id="device_name">%1$s</xliff:g>.</string>
+ <!-- Message for the error dialog when BT pairing fails because the other device rejected the pairing. -->
+ <string name="bluetooth_pairing_rejected_error_message">Pairing rejected by <xliff:g id="device_name">%1$s</xliff:g>.</string>
<!-- Message for the error dialog when BT connecting operation fails generically. -->
<string name="bluetooth_connecting_error_message">There was a problem connecting to <xliff:g id="device_name">%1$s</xliff:g>.</string>
@@ -590,16 +620,25 @@
<string name="wifi_security_wpa">WPA</string>
<!-- Value for the wifi security -->
<string name="wifi_security_wpa2">WPA2</string>
+ <!-- Value for the wifi security -->
+ <string name="wifi_security_wpa_eap">WPA-EAP</string>
+ <!-- Value for the wifi security -->
+ <string name="wifi_security_ieee8021x">IEEE8021X</string>
+
<!-- Value for the wifi security when it is unknown -->
<string name="wifi_security_unknown">Unknown</string>
- <!-- Verbose security type of a wifi network. Open means no security. -->
- <string name="wifi_security_verbose_open">Open network</string>
- <!-- Verbose security type of a wifi network. -->
- <string name="wifi_security_verbose_wep">Secured with WEP</string>
- <!-- Verbose security type of a wifi network. -->
- <string name="wifi_security_verbose_wpa">Secured with WPA</string>
- <!-- Verbose security type of a wifi network. -->
- <string name="wifi_security_verbose_wpa2">Secured with WPA2</string>
+ <!-- Verbose security type of a wifi network. Open means no security. Capitalized by app. -->
+ <string name="wifi_security_verbose_open">open network</string>
+ <!-- Verbose security type of a wifi network. Capitalized by app. -->
+ <string name="wifi_security_verbose_wep">secured with WEP</string>
+ <!-- Verbose security type of a wifi network. Capitalized by app. -->
+ <string name="wifi_security_verbose_wpa">secured with WPA</string>
+ <!-- Verbose security type of a wifi network. Capitalized by app. -->
+ <string name="wifi_security_verbose_wpa2">secured with WPA2</string>
+ <!-- Verbose security type of a wifi network. Capitalized by app. -->
+ <string name="wifi_security_verbose_wpa_eap">secured with WPA-EAP</string>
+ <!-- Verbose security type of a wifi network. Capitalized by app. -->
+ <string name="wifi_security_verbose_ieee8021x">secured with IEEE 802.1x</string>
<!-- Wi-Fi IP addrress label -->
<string name="ip_address">IP address</string>
<!-- Label for the signal strength -->
@@ -624,6 +663,20 @@
<string name="connect">Connect</string>
<!-- Dialog title for when the user is trying to connect to a particular network-->
<string name="connect_to_blank">Connect to <xliff:g id="network_name">%1$s</xliff:g></string>
+ <!-- Caption for the eap method -->
+ <string name="please_select_eap">EAP method</string>
+ <!-- Caption for the phase2 -->
+ <string name="please_select_phase2">Phase 2 authentication</string>
+ <!-- Caption for the identity -->
+ <string name="please_type_identity">Identity</string>
+ <!-- Caption for the anonymous_identity -->
+ <string name="please_type_anonymous_identity">Anonymous identity</string>
+ <!-- Caption for the client_certificate -->
+ <string name="please_select_client_certificate">Client certificate</string>
+ <!-- Caption for the ca certificate -->
+ <string name="please_select_ca_certificate">CA certificate</string>
+ <!-- Caption for the Private Key -->
+ <string name="please_type_private_key_passwd">Private key password</string>
<!-- Caption for the wireless password -->
<string name="please_type_passphrase">Wireless password</string>
<!--Wi-Fi settings screen, connect to network dialog box, field label and hint text -->
@@ -632,10 +685,10 @@
<string name="wifi_show_password">Show password.</string>
<!--Wi-Fi settings screen menu option -->
<string name="scan_wifi">Scan</string>
- <!-- Wifi network summary when not in nearby -->
+ <!-- Wifi network summary when not in nearby. -->
<string name="summary_not_in_range">Not in range</string>
- <!-- Wifi network summary when the network is configured previously -->
- <string name="summary_remembered">Remembered</string>
+ <!-- Wifi network summary when the network is configured previously, capitalized by app -->
+ <string name="summary_remembered">remembered</string>
<!-- Wifi network summary when there was an error connecting -->
<string name="summary_connection_failed">Connection unsuccessful, select to try again</string>
<!-- Header for the list of wifi networks-->
@@ -799,15 +852,20 @@
<!-- Sound settings screen, setting check box label -->
<string name="play_media_notification_sounds_enable_title">SD card notifications</string>
<!-- Sound settings screen, setting option summary text when check box is selected -->
- <string name="play_media_notification_sounds_enable_summary_on">Disable SD card notification sounds</string>
+ <string name="play_media_notification_sounds_enable_summary_on">Play sound for SD card notifications</string>
<!-- Sound settings screen, setting option summary text when check box is clear -->
- <string name="play_media_notification_sounds_enable_summary_off">Enable SD card notification sounds</string>
+ <string name="play_media_notification_sounds_enable_summary_off">Play sound for SD card notifications</string>
<!-- Main Settings screen setting option name to go into the screen for data sync settings-->
<string name="sync_settings">Data synchronization</string>
<!-- Main Settings screen setting option summary text for the itme to go into the screen with data sync settings-->
<string name="sync_settings_summary">Select which applications are synchronized</string>
+ <!-- Main Settings screen, setting option name to go into search settings -->
+ <string name="search_settings">Search</string>
+ <!-- Main Settings screen, setting option summary to go into search settings -->
+ <string name="search_settings_summary">Manage search settings and history</string>
+
<!-- Display settings -->
<!-- Sound & display settings screen, section header for settings related to display -->
<string name="display_settings">Display settings</string>
@@ -832,6 +890,13 @@
<!-- 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 -->
@@ -900,7 +965,7 @@
<!-- About phone screen, title of the item to go into the Phone status screen -->
<string name="device_status">Status</string>
<!-- About phone screen, summary of the item to go into the phone status screen -->
- <string name="device_status_summary">IMEI, phone number, signal, etc.</string>
+ <string name="device_status_summary">Phone number, signal, etc.</string>
<!-- Main settings screen item's title to go into the SD card and storage settings screen-->
<string name="storage_settings_title">SD card & phone storage</string>
<!-- Main settings screen item's summary for the SD card and storage settings -->
@@ -910,7 +975,13 @@
<!-- Do not translate. About phone, status item title -->
<string name="status_imei_sv">IMEI SV</string>
<!-- About phone, status item title. The phone number of the current device.-->
- <string name="status_number">Phone number</string>
+ <string name="status_number">My phone number</string>
+ <!-- About phone, status item title. The phone MIN number of the current device.-->
+ <string name="status_min_number">MIN</string>
+ <!-- About phone, status item title. The phone PRL Version of the current device.-->
+ <string name="status_prl_version">PRL Version</string>
+ <!-- About phone, status item title. The phone MEID number of the current device.-->
+ <string name="status_meid_number">MEID</string>
<!-- About phone, status item title for the type of data phone network we're connected to, for example 3G or Edge or GPRS -->
<string name="status_network_type">Mobile network type</string>
<!-- About phone, status item title. The status of data access. For example, the value may be "Connected" -->
@@ -1022,11 +1093,11 @@
<!-- SD card & phone storage settings screen, setting option summary text under Internal phone storage heading -->
<string name="master_clear_summary">Erases all data on phone</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset -->
- <string name="master_clear_desc">This action will reset the phone to its initial factory state, erasing all data and downloaded applications!</string>
+ <string name="master_clear_desc">Factory data reset erases all of your personal information from the phone, including details about your Google account and any other accounts, system and application data and preferences, and any applications that you have downloaded. It does not change the version of the system software and bundled applications. It does not erase any photos, music, or other information stored on an SD card.</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
<string name="master_clear_button_text">Reset phone</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Reset phone button -->
- <string name="master_clear_final_desc">Reset phone, erasing all your data and applications? Action cannot be reversed!</string>
+ <string name="master_clear_final_desc">Erase all of your personal information and any downloaded applications? It is impossible to reverse this action!</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Reset phone button -->
<string name="master_clear_final_button_text">Erase everything</string>
<!-- Message to draw an unlock pattern before clearing the device -->
@@ -1065,7 +1136,7 @@
<string name="network_settings_summary">Set options for roaming, networks, APNs</string>
<!-- Security & location settings screen, section header for settings relating to location -->
- <string name="location_title">My Location sources</string>
+ <string name="location_title">My Location</string>
<!-- Security & location settings screen, setting check box label if the user wants to use wireless network-based positioning (cell ID, wifi, etc.) -->
<string name="location_network_based">Use wireless networks</string>
<!-- Security & location settings screen, setting summary when Use wireless networks check box is clear -->
@@ -1078,16 +1149,19 @@
<string name="location_street_level">When locating, accurate to street level (deselect to conserve battery)</string>
<!-- Security & location settings screen, setting summary when Enable GPS satellites check box is clear -->
<string name="location_gps_disabled">Locate to street-level (requires more battery plus view of sky)</string>
- <!-- Title of warning dialog to user that location information will be logged -->
- <string name="location_warning_title">Location consent</string>
- <!-- Warning text to user that location information will be logged -->
- <string name="location_warning_message">"Allow Google's location service to collect anonymous and aggregate location data. Collection will occur regardless of whether any applications are active."</string>
- <!-- Agree button-->
+ <!-- Setting title for allow sending location to google -->
+ <string name="use_location_title">Share with Google</string>
+ <!-- Title of dialog to user requesting use of location information to improve services -->
+ <string name="use_location_summary">Allow Google to use location for improved search and other services</string>
+ <!-- Message of dialog to user requesting use of location information -->
+ <string name="use_location_warning_message">Allow Google to use location for improved search results and other services</string>
+ <!-- Agree -->
<string name="agree">Agree</string>
- <!-- Disagree button-->
+ <!-- Disagree -->
<string name="disagree">Disagree</string>
- <!-- About -->
+
+ <!-- About --> <skip />
<!-- Main settings screen, setting title for the user to go into the About phone screen -->
<string name="about_settings">About phone</string>
<!-- Main settings screen, setting summary for the user to go into the About phone screen-->
@@ -1106,7 +1180,7 @@
<!-- About phone settings screen, setting option name to see terms and conditions -->
<string name="terms_title">Terms and conditions</string>
<!-- About phone settings screen, running the System Tutorial -->
- <string name="system_tutorial_list_item_title">System Tutorial</string>
+ <string name="system_tutorial_list_item_title">System tutorial</string>
<!-- About phone settings screen, summary of what System Tutorial does -->
<string name="system_tutorial_list_item_summary">Learn how to use your phone</string>
@@ -1245,6 +1319,8 @@
<string name="uninstall_text">Uninstall</string>
<!-- Manage applications, individual application info screen, button label under Storage heading. Button to clear all data associated with tis app (for exampel, remove all cached emails for an Email app) -->
<string name="clear_user_data_text">Clear data</string>
+ <!-- Manage applications, restore updated system application to factory version -->
+ <string name="app_factory_reset">Uninstall updates</string>
<!-- Manage applications, individual application info screen, screen, message text under Launch by default heading. This is present if the app is set as a default for some actions. -->
<string name="auto_launch_enable_text">You have selected to launch this application by default for some actions.</string>
<!-- Manage applications, individual application screen, text under Launch by default heading if the app is NOT a default for actions -->
@@ -1290,12 +1366,22 @@
found in the list of installed applications.</string>
<!-- Manage applications, individual application dialog box message. Shown when there was an error trying to clear the data. -->
<string name="clear_data_failed">Unable to clear application data.</string>
+ <!-- Manage applications, factory reset dialog title for system applications. -->
+ <string name="app_factory_reset_dlg_title">Uninstall updates</string>
+ <!-- Manage applications, factory reset option dialog text for system applications. -->
+ <string name="app_factory_reset_dlg_text">Do you want to uninstall all updates to this Android system application?</string>
+ <!-- Manage applications, title for dialog if clear data fails-->
+ <string name="clear_failed_dlg_title">Clear data</string>
+ <!-- Manage applications, text for dialog if clear data fails-->
+ <string name="clear_failed_dlg_text">Failed clearing data for application</string>
<!-- Manage applications, individual application info screen, text that appears under the "Permissions" heading. This describes the permissions that the application has. -->
<string name="security_settings_desc">This application can access the following on your phone:</string>
<string name="computing_size">Computing\u2026</string>
<string name="invalid_size_value">Unable to compute package size</string>
<!-- String displayed when list is empty -->
<string name="empty_list_msg">You do not have any third-party apps installed.</string>
+ <!-- Manage applications, version string displayed in app snippet -->
+ <string name="version_text">version <xliff:g id="version_num">%1$s</xliff:g></string>
<!-- Language Settings --> <skip />
<!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings realted to locale and text -->
@@ -1377,7 +1463,7 @@
<string name="quick_launch_no_shortcut">No shortcut</string>
<!-- On the Quick launch settings screen, summary text under the item for each assigned letter. -->
<string name="quick_launch_shortcut">Search + <xliff:g id="shortcut_letter">%1$s</xliff:g></string>
- <!-- On the Quick launch settings screen, title of "Clear shortcut" confirmation dialog. This is reached by longpressing an item for a shortcut letter. This allows the user to clear the assigned applicatino for that shortcut letter. -->
+ <!-- On the Quick launch settings screen, title of "Clear shortcut" confirmation dialog. This is reached by longpressing an item for a shortcut letter. This allows the user to clear the assigned application for that shortcut letter. -->
<string name="quick_launch_clear_dialog_title">Clear</string>
<!-- On the Quick launch settings screen, message in the "Clear shortcut" confirmation dialog. See the title for this dialog for more info. -->
<string name="quick_launch_clear_dialog_message">Your shortcut for <xliff:g id="shortcut_letter">%1$s</xliff:g> (<xliff:g id="application_name">%2$s</xliff:g>) will be cleared.</string>
@@ -1418,6 +1504,10 @@
<string name="allow_mock_location">Allow mock locations</string>
<!-- setting Checkbox summary whether to allow mock locations -->
<string name="allow_mock_location_summary">Allow mock locations</string>
+ <!-- Title of warning dialog about the implications of enabling USB debugging -->
+ <string name="adb_warning_title">Enable USB debugging?</string>
+ <!-- Warning text to user about the implications of enabling USB debugging -->
+ <string name="adb_warning_message">USB debugging is intended for development purposes only. It can be used to copy data between your computer and your device, install applications on your device without notification, and read log data.</string>
<!-- Title for the screen that lets the user choose a gadget to add to the home screen
(or other screens that can host gadgets). Note to translators: we're still determining
@@ -1462,16 +1552,16 @@
<string name="battery_history_starts">Starts: <xliff:g id="starts">%1$d</xliff:g></string>
<!-- Used to show an amount of time in the form "d days, h hours, m minutes, s seconds" in BatteryHistory -->
- <string name="battery_history_days"><xliff:g id="days">%1$d</xliff:g> days, <xliff:g id="hours">%2$d</xliff:g> hours, <xliff:g id="minutes">%3$d</xliff:g> minutes, <xliff:g id="seconds">%4$d</xliff:g> seconds</string>
+ <string name="battery_history_days"><xliff:g id="days">%1$d</xliff:g>d <xliff:g id="hours">%2$d</xliff:g>h <xliff:g id="minutes">%3$d</xliff:g>m <xliff:g id="seconds">%4$d</xliff:g>s</string>
<!-- Used to show an amount of time in the form "h hours, m minutes, s seconds" in BatteryHistory -->
- <string name="battery_history_hours"><xliff:g id="hours">%1$d</xliff:g> hours, <xliff:g id="minutes">%2$d</xliff:g> minutes, <xliff:g id="seconds">%3$d</xliff:g> seconds</string>
+ <string name="battery_history_hours"><xliff:g id="hours">%1$d</xliff:g>h <xliff:g id="minutes">%2$d</xliff:g>m <xliff:g id="seconds">%3$d</xliff:g>s</string>
<!-- Used to show an amount of time in the form "m minutes, s seconds" in BatteryHistory -->
- <string name="battery_history_minutes"><xliff:g id="minutes">%1$d</xliff:g> minutes, <xliff:g id="seconds">%2$d</xliff:g> seconds</string>
+ <string name="battery_history_minutes"><xliff:g id="minutes">%1$d</xliff:g>m <xliff:g id="seconds">%2$d</xliff:g>s</string>
<!-- Used to show an amount of time in the form "s seconds" in BatteryHistory -->
- <string name="battery_history_seconds"><xliff:g id="seconds">%1$d</xliff:g> seconds</string>
+ <string name="battery_history_seconds"><xliff:g id="seconds">%1$d</xliff:g>s</string>
<!-- Used to head a list of packages that share a given user id BatteryHistory -->
<string name="battery_history_packages_sharing_this_uid">Packages sharing this UID:</string>
@@ -1531,4 +1621,385 @@
<string name="launch_count_label">Count</string>
<!-- label for usage time -->
<string name="usage_time_label">Usage time</string>
+
+ <!-- Accessibility settings -->
+ <skip/>
+
+ <!-- Settings title for accessibility settings -->
+ <string name="accessibility_settings_title">Accessibility</string>
+ <!-- Settings summary for accessibility settings -->
+ <string name="accessibility_settings_summary">Manage accessibility options</string>
+ <!-- Setting Checkbox title for enabling accessibility -->
+ <string name="toggle_accessibility_title">Accessibility</string>
+ <!-- Setting accessibility services category -->
+ <string name="accessibility_services_category">Accessibility services</string>
+ <!-- Message for announcing the lack of installed accessibility services. -->
+ <string name="no_accessibility_services_summary">No installed accessibility services.</string>
+ <!-- Warning message about security implications of enabling an accessibility service,
+ displayed as a dialog message when the user selects to enable an accessibility service. -->
+ <string name="accessibility_service_security_warning">This accessibility service may be able to collect
+ all the text you type, including personal data credit card numbers except passwords.
+ It may also log your user interface interactions. It comes from the application
+ <xliff:g id="accessibility_service_name">%1$s</xliff:g>. Enable this accessibility service?</string>
+ <!-- Warning about disabling accessibility displayed as a dialog message when the user
+ selects to disable accessibility. This avoids accidental disabling. -->
+ <string name="accessibility_service_disable_warning">Disable accessibility?</string>
+
+ <!-- App Fuel Gauge strings -->
+ <skip/>
+
+ <!-- Activity title for App Fuel Gauge summary -->
+ <string name="power_usage_summary_title">Battery use</string>
+ <!-- Activity title summary for App Fuel Gauge summary -->
+ <string name="power_usage_summary">What has been using the battery</string>
+ <!-- Battery usage since unplugged -->
+ <string name="battery_since_unplugged">Battery use since unplugged</string>
+ <!-- Battery usage since user reset the stats -->
+ <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>
+ <!-- CPU awake time title -->
+ <string name="awake">Device awake time</string>
+ <!-- Wifi on time -->
+ <string name="wifi_on_time">WiFi on time</string>
+ <!-- Bluetooth on time -->
+ <string name="bluetooth_on_time">WiFi on time</string>
+ <!-- Application name and battery usage percentage -->
+ <string name="usage_name_percent"><xliff:g id="name">%1$s</xliff:g>" - "
+ <xliff:g id="percent">%2$s</xliff:g>"%%"</string>
+
+ <!-- Activity title for battery usage details for an app. or power consumer -->
+ <string name="details_title">Battery use details</string>
+ <!-- Subtitle for application/subsystem details -->
+ <string name="details_subtitle">Use details</string>
+ <!-- Subtitle for possible options -->
+ <string name="controls_subtitle">Adjust power use</string>
+ <!-- Subtitle for list of packages -->
+ <string name="packages_subtitle">Included packages</string>
+
+ <!-- Label for power consumed by the screen -->
+ <string name="power_screen">Display</string>
+ <!-- Label for power consumed by WiFi -->
+ <string name="power_wifi">Wi-Fi</string>
+ <!-- Label for power consumed by Bluetooth -->
+ <string name="power_bluetooth">Bluetooth</string>
+ <!-- Label for power consumed by Cell idle -->
+ <string name="power_cell">Cell standby</string>
+ <!-- Label for power consumed by Calling -->
+ <string name="power_phone">Voice calls</string>
+ <!-- Label for power consumed when Idle -->
+ <string name="power_idle">Phone idle</string>
+
+ <!-- Label for CPU usage time -->
+ <string name="usage_type_cpu">CPU total</string>
+ <!-- Label for CPU usage in foreground -->
+ <string name="usage_type_cpu_foreground">CPU foreground</string>
+ <!-- Label for GPU usage time -->
+ <string name="usage_type_gps">GPS</string>
+ <!-- Label for Phone usage time -->
+ <string name="usage_type_phone">Phone</string>
+ <!-- Label for Data sent -->
+ <string name="usage_type_data_send">Data sent</string>
+ <!-- Label for Data received -->
+ <string name="usage_type_data_recv">Data received</string>
+ <!-- Label for Audio usage time -->
+ <string name="usage_type_audio">Audio</string>
+ <!-- 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>
+ <!-- Label for force stop action -->
+ <string name="battery_action_stop">Force stop</string>
+ <!-- Label for app details action -->
+ <string name="battery_action_app_details">Application info</string>
+ <!-- Label for app settings action -->
+ <string name="battery_action_app_settings">Application settings</string>
+ <!-- Label for display settings -->
+ <string name="battery_action_display">Display settings</string>
+ <!-- Label for wifi settings -->
+ <string name="battery_action_wifi">WiFi settings</string>
+ <!-- Label for bluetooth settings -->
+ <string name="battery_action_bluetooth">Bluetooth settings</string>
+
+ <!-- Description for voice call detail -->
+ <string name="battery_desc_voice">Battery used by voice calls</string>
+
+ <!-- Description for standby detail -->
+ <string name="battery_desc_standby">Battery used when phone is idle</string>
+
+ <!-- Description for cell radio detail -->
+ <string name="battery_desc_radio">Battery used by cell radio</string>
+ <!-- Suggestion to switch to airplane mode to save power -->
+ <string name="battery_sugg_radio">Switch to airplane mode to save power in areas with no cell coverage</string>
+
+ <!-- Description for power consumed by display -->
+ <string name="battery_desc_display">Battery used by the display and backlight</string>
+ <!-- Suggestion for reducing display power -->
+ <string name="battery_sugg_display">Reduce the screen brightness and/or screen timeout</string>
+
+ <!-- Description for wifi connectivity -->
+ <string name="battery_desc_wifi">Battery used by Wi-Fi</string>
+ <!-- Suggestion for wifi connectivity power drain -->
+ <string name="battery_sugg_wifi">Turn off WiFi when not using it or where it is not available</string>
+
+ <!-- Description for bluetooth power consumption detail -->
+ <string name="battery_desc_bluetooth">Battery used by bluetooth</string>
+ <!-- Suggestion for bluetooth -->
+ <string name="battery_sugg_bluetooth_basic">Turn off bluetooth when you aren't using it</string>
+ <!-- Suggestion for bluetooth headset -->
+ <string name="battery_sugg_bluetooth_headset">Try connecting to a different bluetooth device</string>
+
+ <!-- Description for power consumed by applications -->
+ <string name="battery_desc_apps">Battery used by applications when running</string>
+ <!-- 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>
+ <!-- Suggestion for getting apps to consume less power -->
+ <string name="battery_sugg_apps_settings">The application may offer settings to reduce battery use</string>
+
+ <!-- Menu label for viewing battery usage since unplugged -->
+ <string name="menu_stats_unplugged"><xliff:g id="unplugged">%1$s</xliff:g> since unplugged</string>
+ <!-- Menu label for viewing battery usage since unplugged -->
+ <string name="menu_stats_last_unplugged">While last unplugged for <xliff:g id="unplugged">%1$s</xliff:g></string>
+ <!-- Menu label for viewing battery usage total -->
+ <string name="menu_stats_total">Usage totals</string>
+ <!-- Menu label for refreshing with latest usage numbers -->
+ <string name="menu_stats_refresh">Refresh</string>
+
+ <!-- Label for kernel threads -->
+ <string name="process_kernel_label">Android OS</string>
+ <!-- Label for mediaserver process -->
+ <string name="process_mediaserver_label">Mediaserver</string>
+
+ <!-- Text-To-Speech (TTS) settings --><skip />
+ <!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings related to the text-to-speech functionality -->
+ <string name="tts_settings">Speech synthesis</string>
+ <!-- Summary of setting on main settings screen. This item will take the user to the screen to tweak settings related to the text-to-speech functionality -->
+ <string name="tts_settings_summary">Set text-to-speech options</string>
+ <!-- Main TTS Settings screen title -->
+ <string name="tts_settings_title">Speech synthesizer controls</string>
+ <!-- On main TTS Settings screen, title for toggle used to force use of default TTS settings -->
+ <string name="use_default_tts_settings_title">Always use my settings</string>
+ <!-- On main TTS Settings screen, summary for toggle used to force use of default TTS settings -->
+ <string name="use_default_tts_settings_summary">Default settings below override application settings</string>
+ <!-- On main TTS Settings screen, section header for default TTS settings -->
+ <string name="tts_default_settings_section">Default settings</string>
+ <!-- On main TTS Settings screen, in default settings section, setting default speech rate for synthesized voice -->
+ <string name="tts_default_rate_title">Speech rate</string>
+ <!-- On main TTS Settings screen, summary for default speech rate for synthesized voice -->
+ <string name="tts_default_rate_summary">Speed at which the text is spoken</string>
+ <!-- On main TTS Settings screen, in default settings section, setting default pitch for synthesized voice -->
+ <string name="tts_default_pitch_title">Pitch</string>
+ <!-- On main TTS Settings screen, summary for default pitch for synthesized voice -->
+ <string name="tts_default_pitch_summary">Affects the tone of the spoken text</string>
+ <!-- On main TTS Settings screen, in default settings section, setting default language for synthesized voice -->
+ <string name="tts_default_lang_title">Language</string>
+ <!-- On main TTS Settings screen, summary for default language for synthesized voice -->
+ <string name="tts_default_lang_summary">Sets the language-specific voice for the spoken text</string>
+ <!-- On main TTS Settings screen, triggers playback of an example of speech synthesis -->
+ <string name="tts_play_example_title">Listen to an example</string>
+ <!-- On main TTS Settings screen, summary for triggering playback of an example of speech synthesis -->
+ <string name="tts_play_example_summary">Play a short demonstration of speech synthesis</string>
+ <!-- On main TTS Settings screen, click to install required speech synthesis data -->
+ <string name="tts_install_data_title">Install voice data</string>
+ <!-- On main TTS Settings screen, summary for click to install required speech synthesis data -->
+ <string name="tts_install_data_summary">Install the voice data required for speech synthesis</string>
+ <!-- On main TTS Settings screen, summary for when required speech synthesis data alrady installed on SD card -->
+ <string name="tts_data_installed_summary">Voices required for speech synthesis already properly installed</string>
+ <!-- Text spoken by the TTS engine for demonstration purposes -->
+ <string name="tts_demo">This is an example of speech synthesis.</string>
+ <!-- Text spoken by the TTS engine when TTS settings (other than language) have been changed -->
+ <string name="tts_settings_changed_demo">Your settings have changed. This is an example of how they sound.</string>
+
+ <!-- Power Control Widget -->
+ <string name="gadget_title">Power Control</string>
+
+ <string name="vpn_settings_activity_title">VPN settings</string>
+
+ <!-- Title of VPN connect dialog -->
+ <string name="vpn_connect_to">Connect to %s</string>
+ <!-- In VPN connect dialog, for inputing username and password -->
+ <string name="vpn_username_colon">Username:</string>
+ <string name="vpn_password_colon">Password:</string>
+ <string name="vpn_a_username">a username</string>
+ <string name="vpn_a_password">a password</string>
+
+ <!-- In VPN connect dialog where user may check to remember the username entered -->
+ <string name="vpn_save_username">Remember username</string>
+
+ <string name="vpn_connect_button">Connect</string>
+ <string name="vpn_yes_button">Yes</string>
+ <string name="vpn_no_button">No</string>
+ <string name="vpn_back_button">Back</string>
+ <string name="vpn_mistake_button">No, it's a mistake</string>
+
+ <string name="vpn_menu_done">Save</string>
+ <string name="vpn_menu_cancel">Cancel</string>
+ <string name="vpn_menu_revert">Revert</string>
+ <string name="vpn_menu_connect">Connect to network</string>
+ <string name="vpn_menu_disconnect">Disconnect from network</string>
+ <string name="vpn_menu_edit">Edit network</string>
+ <string name="vpn_menu_delete">Delete network</string>
+
+ <!-- VPN error dialog messages -->
+ <string name="vpn_error_miss_entering">You must enter %s.</string>
+ <string name="vpn_error_miss_selecting">You must select %s.</string>
+ <string name="vpn_error_duplicate_name">The VPN name \'%s\' already exists. Find another name.</string>
+ <string name="vpn_confirm_profile_deletion">Are you sure you want to delete this VPN?</string>
+ <string name="vpn_confirm_add_profile_cancellation">Are you sure you don\'t want to create this profile?</string>
+ <string name="vpn_confirm_edit_profile_cancellation">Are you sure you want to discard the changes made to this profile?</string>
+ <string name="vpn_confirm_reconnect">Unable to connect to the network. Do you want to try again?</string>
+
+ <!-- VPN type selection activity title -->
+ <string name="vpn_type_title">Add VPN</string>
+ <!-- "Add VPN" preference title -->
+ <string name="vpn_add_new_vpn">Add VPN</string>
+ <!-- VPN profile editor title when adding a new profile -->
+ <string name="vpn_edit_title_add">Add %s VPN</string>
+ <!-- VPN profile editor title when editing an existing profile -->
+ <string name="vpn_edit_title_edit">%s details</string>
+ <!-- Preference group title for a list of VPN profiles -->
+ <string name="vpns">VPNs</string>
+ <!-- Preference summary text when VPN is connecting -->
+ <string name="vpn_connecting">Connecting...</string>
+ <!-- Preference summary text when VPN is disconnecting -->
+ <string name="vpn_disconnecting">Disconnecting...</string>
+ <!-- Preference summary text when VPN is connected -->
+ <string name="vpn_connected">Connected</string>
+ <!-- Preference summary text when VPN is not connected -->
+ <string name="vpn_connect_hint">Connect to network</string>
+
+ <string name="vpn_default_profile_name">nowhere</string>
+
+ <!-- Name of a VPN profile -->
+ <string name="vpn_name">VPN name</string>
+ <string name="vpn_a_name">a VPN name</string>
+
+ <!-- Toast message shown when a profile is added -->
+ <string name="vpn_profile_added">'%s' is added</string>
+ <!-- Toast message shown when changes of a profile is saved -->
+ <string name="vpn_profile_replaced">Changes are made to '%s'</string>
+
+ <!-- Preference title -->
+ <string name="vpn_user_certificate_title">Set user certificate</string>
+ <!-- Complete term -->
+ <string name="vpn_user_certificate">User certificate</string>
+ <string name="vpn_a_user_certificate">a user certificate</string>
+
+ <!-- Preference title -->
+ <string name="vpn_ca_certificate_title">Set CA certificate</string>
+ <!-- Complete term -->
+ <string name="vpn_ca_certificate">Certificate authority (CA) certificate</string>
+ <string name="vpn_a_ca_certificate">a CA certificate</string>
+ <!-- Preference title -->
+ <string name="vpn_l2tp_secret_string_title">Set L2TP secret</string>
+ <!-- Complete term -->
+ <string name="vpn_l2tp_secret">L2TP secret</string>
+ <string name="vpn_a_l2tp_secret">an L2TP secret</string>
+
+ <!-- Preference title -->
+ <string name="vpn_ipsec_presharedkey_title">Set IPSec pre-shared key</string>
+ <!-- Complete term -->
+ <string name="vpn_ipsec_presharedkey">IPSec pre-shared key</string>
+ <string name="vpn_a_ipsec_presharedkey">an IPSec pre-shared key</string>
+
+ <!-- Preference title -->
+ <string name="vpn_vpn_server_title">Set VPN server</string>
+ <!-- Complete term -->
+ <string name="vpn_vpn_server">VPN server</string>
+ <string name="vpn_a_vpn_server">a VPN server</string>
+ <!-- Dialog title for setting VPN server name -->
+ <string name="vpn_vpn_server_dialog_title">VPN server name</string>
+
+ <!-- Preference title -->
+ <string name="vpn_dns_search_list_title">DNS search domains</string>
+ <!-- Complete term -->
+ <string name="vpn_dns_search_list">DNS search domains</string>
+
+ <!-- Summary text to hint that the value is set -->
+ <string name="vpn_field_is_set">%s is set</string>
+ <!-- Summary text to hint that the value is not set -->
+ <string name="vpn_field_not_set">%s not set</string>
+ <!-- Summary text to hint that the value is not set but it's not required-->
+ <string name="vpn_field_not_set_optional">%s not set (optional)</string>
+
+ <!-- CheckBoxPreference title to enable something -->
+ <string name="vpn_enable_field">Enable %s</string>
+ <!-- CheckBoxPreference title to disable something -->
+ <string name="vpn_disable_field">Disable %s</string>
+
+ <!-- CheckBoxPreference summary to hint that something is enabled -->
+ <string name="vpn_is_enabled">%s is enabled</string>
+ <!-- CheckBoxPreference summary to hint that something is disabled -->
+ <string name="vpn_is_disabled">%s is disabled</string>
+
+ <!-- Title of preference to enter the VPN settings activity -->
+ <string name="vpn_settings_title">VPN settings</string>
+ <!-- Summary of preference to enter the VPN settings activity -->
+ <string name="vpn_settings_summary">Set up & manage Virtual Private Networks (VPNs)</string>
+
+ <!-- Title of preference group for credential storage settings -->
+ <string name="cstor_settings_category">Credential storage</string>
+ <!-- Title of preference to enable/dislable access to credential storage -->
+ <string name="cstor_access_title">Use secure credentials</string>
+ <!-- Summary of preference to enable/dislable access to credential storage -->
+ <string name="cstor_access_summary">Allow applications to access secure certificates and other credentials</string>
+ <!-- Title of dialog to enable/dislable access to credential storage -->
+ <string name="cstor_access_dialog_title">Enter password</string>
+ <!-- Description of dialog to enable/dislable access to credential storage from an action that requires the credential storage -->
+ <string name="cstor_access_dialog_hint_from_action">Enter the credential storage password.</string>
+
+ <!-- Title of preference to set storage password -->
+ <string name="cstor_set_passwd_title">Set password</string>
+ <!-- Summary of preference to set storage password -->
+ <string name="cstor_set_passwd_summary">Set or change the credential storage password</string>
+ <!-- Title of dialog to set storage password -->
+ <string name="cstor_set_passwd_dialog_title">Set password</string>
+
+ <!-- Title of preference to reset storage -->
+ <string name="cstor_reset_title">Clear storage</string>
+ <!-- Summary of preference to reset storage -->
+ <string name="cstor_reset_summary">Clear credential storage of all contents and reset its password</string>
+ <string name="cstor_reset_hint">Are you sure you want to delete all credentials and reset the credential storage password?</string>
+
+ <!-- Title of dialog to name a credential -->
+ <string name="cstor_name_credential_dialog_title">Name the certificate</string>
+ <!-- Description for the credential name input box -->
+ <string name="cstor_credential_name">Certificate name:</string>
+ <!-- Title of the credential info -->
+ <string name="cstor_credential_info">Certificate details:</string>
+ <string name="cstor_name_credential_hint">The name can contain only letters and numbers.</string>
+
+
+ <!-- Description for the old-password input box -->
+ <string name="cstor_old_password">Current password:</string>
+ <!-- Description for the new-password input box -->
+ <string name="cstor_new_password">New password:</string>
+ <!-- Description for the confirm-new-password input box -->
+ <string name="cstor_confirm_password">Confirm new password:</string>
+ <!-- Description when user set up the storage for the very first time -->
+ <string name="cstor_first_time_hint">Set a password for the credential storage.</string>
+ <!-- Description when user set up the storage for the very first time from an action that requires the credential storage-->
+ <string name="cstor_first_time_hint_from_action">Set a password for the credential storage.</string>
+ <string name="cstor_password_error">Please enter the correct password.</string>
+ <string name="cstor_password_error_reset_warning">Please enter the correct password. You have one more try to enter the correct password before the credential storage is erased.</string>
+ <string name="cstor_password_error_reset_warning_plural">Please enter the correct password. You have %d more tries to enter the correct password before the credential storage is erased.</string>
+ <string name="cstor_passwords_error">Passwords do not match.</string>
+ <string name="cstor_passwords_empty_error">You must enter and confirm a password.</string>
+ <string name="cstor_password_empty_error">Please enter the password.</string>
+ <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>
+
+ <!-- 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>
+ <!-- Sound settings screen, setting option summary text -->
+ <string name="emergency_tone_summary">Set behavior when an emergency call is placed</string>
</resources>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
new file mode 100644
index 0000000..3606f04
--- /dev/null
+++ b/res/xml/accessibility_settings.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+ <CheckBoxPreference
+ android:key="toggle_accessibility_service_checkbox"
+ android:title="@string/toggle_accessibility_title"
+ android:persistent="false"/>
+
+ <PreferenceCategory android:key="accessibility_services_category"
+ android:title="@string/accessibility_services_category" />
+
+</PreferenceScreen>
diff --git a/res/xml/appwidget_info.xml b/res/xml/appwidget_info.xml
new file mode 100644
index 0000000..2186dab
--- /dev/null
+++ b/res/xml/appwidget_info.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="294dip"
+ android:minHeight="72dip"
+ android:initialLayout="@layout/widget"
+ >
+</appwidget-provider>
diff --git a/res/xml/device_info_settings.xml b/res/xml/device_info_settings.xml
index bb7c531..80370e2 100644
--- a/res/xml/device_info_settings.xml
+++ b/res/xml/device_info_settings.xml
@@ -33,13 +33,19 @@
android:targetClass="com.android.settings.deviceinfo.Status" />
</PreferenceScreen>
+ <PreferenceScreen
+ android:key="power_usage"
+ android:title="@string/power_usage_summary_title"
+ android:summary="@string/power_usage_summary">
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.fuelgauge.PowerUsageSummary" />
+ </PreferenceScreen>
+
<!-- Legal Information -->
<PreferenceScreen
android:key="container"
android:title="@string/legal_information">
-
- <!-- Title for this other screen -->
- <PreferenceCategory android:title="@string/legal_information" />
<!-- Note: The titles given here probably won't be used. Instead, we programmatically
fill the title with the label of the activity with the corresponding action.
diff --git a/res/xml/device_info_status.xml b/res/xml/device_info_status.xml
index 2d4c772..dee606d 100644
--- a/res/xml/device_info_status.xml
+++ b/res/xml/device_info_status.xml
@@ -32,6 +32,24 @@
android:title="@string/status_number"
android:summary="@string/device_info_not_available"
android:persistent="false" />
+ <!-- This menu item is only for CDMA phone -->
+ <Preference android:key="min_number"
+ style="?android:attr/preferenceInformationStyle"
+ android:title="@string/status_min_number"
+ android:summary="@string/device_info_not_available"
+ android:persistent="false" />
+ <!-- This menu item is only for CDMA phone -->
+ <Preference android:key="prl_version"
+ style="?android:attr/preferenceInformationStyle"
+ android:title="@string/status_prl_version"
+ android:summary="@string/device_info_not_available"
+ android:persistent="false" />
+ <!-- This menu item is only for CDMA phone -->
+ <Preference android:key="meid_number"
+ style="?android:attr/preferenceInformationStyle"
+ android:title="@string/status_meid_number"
+ android:summary="@string/device_info_not_available"
+ android:persistent="false" />
<Preference android:key="operator_name"
style="?android:attr/preferenceInformationStyle"
android:title="@string/status_operator"
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
new file mode 100644
index 0000000..b49b140
--- /dev/null
+++ b/res/xml/power_usage_summary.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/battery_since_unplugged"
+ android:key="app_list">
+</PreferenceScreen>
diff --git a/res/xml/security_settings.xml b/res/xml/security_settings.xml
index 788aae3..8dd9d89 100644
--- a/res/xml/security_settings.xml
+++ b/res/xml/security_settings.xml
@@ -17,11 +17,12 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
+ android:key="location_category"
android:title="@string/location_title">
<CheckBoxPreference
android:key="location_network"
- android:title="@string/location_network_based"
+ android:title="@string/location_network_based"
android:summaryOn="@string/location_neighborhood_level"
android:summaryOff="@string/location_networks_disabled"/>
@@ -30,7 +31,13 @@
android:title="@string/location_gps"
android:summaryOn="@string/location_street_level"
android:summaryOff="@string/location_gps_disabled"/>
-
+
+ <CheckBoxPreference
+ android:key="use_location"
+ android:title="@string/use_location_title"
+ android:persistent="false"
+ android:summary="@string/use_location_summary"/>
+
</PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/settings.xml b/res/xml/settings.xml
index 5c0a1e1..9ca581a 100644
--- a/res/xml/settings.xml
+++ b/res/xml/settings.xml
@@ -115,6 +115,43 @@
android:targetClass="com.android.settings.LanguageSettings" />
</PreferenceScreen>
+ <!-- Search.
+ The settings activity will ensure that this is resolved to an
+ activity on the system image, otherwise it will remove this
+ preference.
+ The intent action is the same as
+ android.app.SearchManager.INTENT_ACTION_SEARCH_SETTINGS.
+ -->
+
+ <PreferenceScreen
+ android:title="@string/search_settings"
+ android:summary="@string/search_settings_summary"
+ android:key="search_settings">
+ <intent android:action="android.search.action.SEARCH_SETTINGS" />
+ </PreferenceScreen>
+
+ <!-- Accessibility feedback -->
+
+ <PreferenceScreen
+ android:title="@string/accessibility_settings_title"
+ android:summary="@string/accessibility_settings_summary">
+ <intent
+ android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.AccessibilitySettings" />
+ </PreferenceScreen>
+
+ <!-- Text-To-Speech -->
+
+ <PreferenceScreen
+ android:title="@string/tts_settings"
+ android:summary="@string/tts_settings_summary">
+ <intent
+ android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.TextToSpeechSettings" />
+ </PreferenceScreen>
+
<!-- About Device -->
<PreferenceScreen
diff --git a/res/xml/sound_and_display_settings.xml b/res/xml/sound_and_display_settings.xml
index c8a9360..223e52a 100644
--- a/res/xml/sound_and_display_settings.xml
+++ b/res/xml/sound_and_display_settings.xml
@@ -94,6 +94,13 @@
</PreferenceCategory>
+ <ListPreference
+ android:key="emergency_tone"
+ android:title="@string/emergency_tone_title"
+ android:summary="@string/emergency_tone_summary"
+ android:entries="@array/emergency_tone_entries"
+ android:entryValues="@array/emergency_tone_values" />
+
<PreferenceCategory
android:title="@string/display_settings">
@@ -124,6 +131,11 @@
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/res/xml/tts_settings.xml b/res/xml/tts_settings.xml
new file mode 100644
index 0000000..d94d575
--- /dev/null
+++ b/res/xml/tts_settings.xml
@@ -0,0 +1,60 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/tts_settings_title">
+
+ <Preference
+ android:key="tts_play_example"
+ android:persistent="false"
+ android:title="@string/tts_play_example_title"
+ android:summary="@string/tts_play_example_summary" />
+
+ <Preference
+ android:key="tts_install_data"
+ android:persistent="false"
+ android:title="@string/tts_install_data_title"
+ android:summary="@string/tts_install_data_summary" />
+
+ <CheckBoxPreference
+ android:key="toggle_use_default_tts_settings"
+ android:title="@string/use_default_tts_settings_title"
+ android:summary="@string/use_default_tts_settings_summary"
+ android:persistent="false" />
+
+ <PreferenceCategory
+ android:title="@string/tts_default_settings_section">
+
+ <ListPreference
+ android:key="tts_default_rate"
+ android:title="@string/tts_default_rate_title"
+ android:summary="@string/tts_default_rate_summary"
+ android:persistent="false"
+ android:entries="@array/tts_rate_entries"
+ android:entryValues="@array/tts_rate_values" />
+
+ <ListPreference
+ android:key="tts_default_lang"
+ android:title="@string/tts_default_lang_title"
+ android:summary="@string/tts_default_lang_summary"
+ android:persistent="false"
+ android:entries="@array/tts_lang_entries"
+ android:entryValues="@array/tts_lang_values" />
+
+ </PreferenceCategory>
+
+
+</PreferenceScreen>
diff --git a/res/xml/vpn_edit.xml b/res/xml/vpn_edit.xml
new file mode 100644
index 0000000..a3cab9c
--- /dev/null
+++ b/res/xml/vpn_edit.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+ <EditTextPreference
+ android:key="vpn_name"
+ android:title="@string/vpn_name"
+ android:dialogTitle="@string/vpn_name"
+ android:singleLine="true"/>
+
+</PreferenceScreen>
diff --git a/res/xml/vpn_settings.xml b/res/xml/vpn_settings.xml
new file mode 100644
index 0000000..773ae1c
--- /dev/null
+++ b/res/xml/vpn_settings.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/vpn_settings_activity_title">
+
+ <PreferenceScreen android:key="add_new_vpn"
+ android:title="@string/vpn_add_new_vpn">
+ <!--intent
+ android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings.vpn"
+ android:targetClass="com.android.settings.vpn.VpnEditor" /-->
+ </PreferenceScreen>
+
+ <!--CheckBoxPreference android:key="installer_enabled"
+ android:defaultValue="false"
+ android:title="@string/installer_enabled"
+ android:summaryOn="@string/installer_enabled_summary_on"
+ android:summaryOff="@string/installer_enabled_summary_off" /-->
+
+ <PreferenceCategory android:key="vpn_list" android:title="@string/vpns">
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/res/xml/vpn_type.xml b/res/xml/vpn_type.xml
new file mode 100644
index 0000000..fbc7822
--- /dev/null
+++ b/res/xml/vpn_type.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:title="@string/vpn_type_title">
+
+</PreferenceScreen>
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index f81fb41..4731fb3 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -53,6 +53,16 @@
</PreferenceScreen>
<PreferenceScreen
+ android:title="@string/vpn_settings_title"
+ android:summary="@string/vpn_settings_summary"
+ android:dependency="toggle_airplane">
+ <intent
+ android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.vpn.VpnSettings" />
+ </PreferenceScreen>
+
+ <PreferenceScreen
android:title="@string/network_settings_title"
android:summary="@string/network_settings_summary"
android:dependency="toggle_airplane">
diff --git a/src/com/android/settings/AccessibilitySettings.java b/src/com/android/settings/AccessibilitySettings.java
new file mode 100644
index 0000000..54e3f14
--- /dev/null
+++ b/src/com/android/settings/AccessibilitySettings.java
@@ -0,0 +1,273 @@
+/*
+ * 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.
+ */
+
+package com.android.settings;
+
+import android.app.AlertDialog;
+import android.app.Service;
+import android.content.DialogInterface;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager;
+
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Activity with the accessibility settings.
+ */
+public class AccessibilitySettings extends PreferenceActivity {
+ private final String TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX =
+ "toggle_accessibility_service_checkbox";
+
+ private static final String ACCESSIBILITY_SERVICES_CATEGORY =
+ "accessibility_services_category";
+
+ private CheckBoxPreference mToggleCheckBox;
+
+ private Map<String, ServiceInfo> mAccessibilityServices =
+ new LinkedHashMap<String, ServiceInfo>();
+
+ private TextUtils.SimpleStringSplitter mStringColonSplitter =
+ new TextUtils.SimpleStringSplitter(':');
+
+ private PreferenceGroup mAccessibilityServicesCategory;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ addPreferencesFromResource(R.xml.accessibility_settings);
+
+ mToggleCheckBox = (CheckBoxPreference) findPreference(
+ TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX);
+
+ addAccessibilitServicePreferences();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ final HashSet<String> enabled = new HashSet<String>();
+ String settingValue = Settings.Secure.getString(getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+ if (settingValue != null) {
+ TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
+ splitter.setString(settingValue);
+ while (splitter.hasNext()) {
+ enabled.add(splitter.next());
+ }
+ }
+
+ Map<String, ServiceInfo> accessibilityServices = mAccessibilityServices;
+
+ for (String key : accessibilityServices.keySet()) {
+ CheckBoxPreference preference = (CheckBoxPreference) findPreference(key);
+ if (preference != null) {
+ preference.setChecked(enabled.contains(key));
+ }
+ }
+
+ int serviceState = Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0);
+
+ if (!accessibilityServices.isEmpty()) {
+ if (serviceState == 1) {
+ mToggleCheckBox.setChecked(true);
+ } else {
+ setAccessibilityServicePreferencesState(false);
+ }
+ mToggleCheckBox.setEnabled(true);
+ } else {
+ if (serviceState == 1) {
+ // no service and accessibility is enabled => disable
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0);
+ setAccessibilityServicePreferencesState(false);
+ }
+ mToggleCheckBox.setEnabled(false);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ persistEnabledAccessibilityServices();
+ }
+
+ /**
+ * Sets the state of the preferences for enabling/disabling AccessibilityServices.
+ *
+ * @param isEnabled If to enable or disable the preferences.
+ */
+ private void setAccessibilityServicePreferencesState(boolean isEnabled) {
+ if (mAccessibilityServicesCategory == null) {
+ return;
+ }
+
+ int count = mAccessibilityServicesCategory.getPreferenceCount();
+ for (int i = 0; i < count; i++) {
+ mAccessibilityServicesCategory.getPreference(i).setEnabled(isEnabled);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ final String key = preference.getKey();
+
+ if (TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX.equals(key)) {
+ boolean isChecked = ((CheckBoxPreference) preference).isChecked();
+ handleEnableAccessibilityStateChange((CheckBoxPreference) preference);
+ } else if (preference instanceof CheckBoxPreference) {
+ handleEnableAccessibilityServiceStateChange((CheckBoxPreference) preference);
+ }
+
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
+ }
+
+ /**
+ * Handles the change of the accessibility enabled setting state.
+ *
+ * @param preference The preference for enabling/disabling accessibility.
+ */
+ private void handleEnableAccessibilityStateChange(CheckBoxPreference preference) {
+ if (preference.isChecked()) {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 1);
+ setAccessibilityServicePreferencesState(true);
+ } else {
+ final CheckBoxPreference checkBoxPreference = preference;
+ AlertDialog dialog = (new AlertDialog.Builder(this))
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.accessibility_service_disable_warning))
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0);
+ setAccessibilityServicePreferencesState(false);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ checkBoxPreference.setChecked(true);
+ }
+ })
+ .create();
+ dialog.show();
+ }
+ }
+
+ /**
+ * Handles the change of the preference for enabling/disabling an AccessibilityService.
+ *
+ * @param preference The preference.
+ */
+ private void handleEnableAccessibilityServiceStateChange(CheckBoxPreference preference) {
+ if (preference.isChecked()) {
+ final CheckBoxPreference checkBoxPreference = preference;
+ AlertDialog dialog = (new AlertDialog.Builder(this))
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.accessibility_service_security_warning,
+ mAccessibilityServices.get(preference.getKey())
+ .applicationInfo.loadLabel(getPackageManager())))
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ checkBoxPreference.setChecked(true);
+ persistEnabledAccessibilityServices();
+ }
+ })
+ .setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ checkBoxPreference.setChecked(false);
+ }
+ })
+ .create();
+ dialog.show();
+ } else {
+ persistEnabledAccessibilityServices();
+ }
+ }
+
+ /**
+ * Persists the Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES setting.
+ * The AccessibilityManagerService watches this property and manages the
+ * AccessibilityServices.
+ */
+ private void persistEnabledAccessibilityServices() {
+ StringBuilder builder = new StringBuilder(256);
+
+ int firstEnabled = -1;
+ for (String key : mAccessibilityServices.keySet()) {
+ CheckBoxPreference preference = (CheckBoxPreference) findPreference(key);
+ if (preference.isChecked()) {
+ builder.append(key);
+ builder.append(':');
+ }
+ }
+
+ Settings.Secure.putString(getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, builder.toString());
+ }
+
+ /**
+ * Adds {@link CheckBoxPreference} for enabling or disabling an accessibility services.
+ */
+ private void addAccessibilitServicePreferences() {
+ AccessibilityManager accessibilityManager =
+ (AccessibilityManager) getSystemService(Service.ACCESSIBILITY_SERVICE);
+
+ List<ServiceInfo> installedServices = accessibilityManager.getAccessibilityServiceList();
+
+ mAccessibilityServicesCategory =
+ (PreferenceGroup) findPreference(ACCESSIBILITY_SERVICES_CATEGORY);
+
+ if (installedServices.isEmpty()) {
+ getPreferenceScreen().removePreference(mAccessibilityServicesCategory);
+ mAccessibilityServicesCategory = null;
+ return;
+ }
+
+ for (int i = 0, count = installedServices.size(); i < count; ++i) {
+ ServiceInfo serviceInfo = installedServices.get(i);
+ String key = serviceInfo.packageName + "/" + serviceInfo.name;
+
+ mAccessibilityServices.put(key, serviceInfo);
+
+ CheckBoxPreference preference = new CheckBoxPreference(this);
+ preference.setKey(key);
+ preference.setTitle(serviceInfo.loadLabel(getPackageManager()));
+ mAccessibilityServicesCategory.addPreference(preference);
+ }
+ }
+}
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index f1fa2ef..0bd91a8 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -202,7 +202,7 @@
mApnType.setText(mCursor.getString(TYPE_INDEX));
if (mNewApn) {
String numeric =
- SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC);
+ SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
// MCC is first 3 chars and then in 2 - 3 chars of MNC
if (numeric != null && numeric.length() > 4) {
// Country code
diff --git a/src/com/android/settings/ApnSettings.java b/src/com/android/settings/ApnSettings.java
index ecfdb24..2624990 100644
--- a/src/com/android/settings/ApnSettings.java
+++ b/src/com/android/settings/ApnSettings.java
@@ -146,7 +146,7 @@
private void fillList() {
String where = "numeric=\""
- + android.os.SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC, "")
+ + android.os.SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "")
+ "\"";
Cursor cursor = managedQuery(Telephony.Carriers.CONTENT_URI, new String[] {
diff --git a/src/com/android/settings/ApplicationSettings.java b/src/com/android/settings/ApplicationSettings.java
index 85fe11f..6a8aa81 100644
--- a/src/com/android/settings/ApplicationSettings.java
+++ b/src/com/android/settings/ApplicationSettings.java
@@ -53,6 +53,14 @@
}
@Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mWarnInstallApps != null) {
+ mWarnInstallApps.dismiss();
+ }
+ }
+
+ @Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference == mToggleAppInstallation) {
if (mToggleAppInstallation.isChecked()) {
diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
new file mode 100644
index 0000000..b2dcee2
--- /dev/null
+++ b/src/com/android/settings/CreateShortcut.java
@@ -0,0 +1,25 @@
+package com.android.settings;
+
+import android.app.LauncherActivity;
+import android.content.Intent;
+import android.view.View;
+import android.widget.ListView;
+
+public class CreateShortcut extends LauncherActivity {
+ @Override protected Intent getTargetIntent() {
+ Intent targetIntent = new Intent(Intent.ACTION_MAIN, null);
+ targetIntent.addCategory("com.android.settings.SHORTCUT");
+ targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return targetIntent;
+ }
+
+ @Override protected void onListItemClick(ListView l, View v, int position, long id) {
+ Intent shortcutIntent = intentForPosition(position);
+ shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, itemForPosition(position).label);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+}
diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index 1b9fecb..5b38651 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -87,19 +87,25 @@
mDatePref = findPreference("date");
mDateFormat = (ListPreference) findPreference(KEY_DATE_FORMAT);
- int currentFormatIndex = -1;
String [] dateFormats = getResources().getStringArray(R.array.date_format_values);
String [] formattedDates = new String[dateFormats.length];
String currentFormat = getDateFormat();
// Initialize if DATE_FORMAT is not set in the system settings
// This can happen after a factory reset (or data wipe)
if (currentFormat == null) {
- currentFormat = getResources().getString(R.string.default_date_format);
- setDateFormat(currentFormat);
+ currentFormat = "";
}
for (int i = 0; i < formattedDates.length; i++) {
- formattedDates[i] = DateFormat.format(dateFormats[i], mDummyDate).toString();
- if (currentFormat.equals(dateFormats[i])) currentFormatIndex = i;
+ String formatted =
+ DateFormat.getDateFormatForSetting(this, dateFormats[i]).
+ format(mDummyDate.getTime());
+
+ if (dateFormats[i].length() == 0) {
+ formattedDates[i] = getResources().
+ getString(R.string.normal_date_format, formatted);
+ } else {
+ formattedDates[i] = formatted;
+ }
}
mDateFormat.setEntries(formattedDates);
@@ -109,14 +115,14 @@
mTimePref.setEnabled(!autoEnabled);
mDatePref.setEnabled(!autoEnabled);
mTimeZone.setEnabled(!autoEnabled);
-
- getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onResume() {
super.onResume();
+
+ getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
((CheckBoxPreference)mTime24Pref).setChecked(is24Hour());
@@ -134,6 +140,7 @@
protected void onPause() {
super.onPause();
unregisterReceiver(mIntentReceiver);
+ getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
private void updateTimeAndDateDisplay() {
@@ -313,6 +320,10 @@
}
private void setDateFormat(String format) {
+ if (format.length() == 0) {
+ format = null;
+ }
+
Settings.System.putString(getContentResolver(), Settings.System.DATE_FORMAT, format);
}
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 155f085..c1da18a 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -16,6 +16,8 @@
package com.android.settings;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.SystemProperties;
@@ -29,7 +31,8 @@
/*
* Displays preferences for application developers.
*/
-public class DevelopmentSettings extends PreferenceActivity {
+public class DevelopmentSettings extends PreferenceActivity
+ implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
private static final String ENABLE_ADB = "enable_adb";
private static final String KEEP_SCREEN_ON = "keep_screen_on";
@@ -39,6 +42,9 @@
private CheckBoxPreference mKeepScreenOn;
private CheckBoxPreference mAllowMockLocation;
+ // To track whether Yes was clicked in the adb warning dialog
+ private boolean mOkClicked;
+
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -72,8 +78,19 @@
}
if (preference == mEnableAdb) {
- Settings.Secure.putInt(getContentResolver(), Settings.Secure.ADB_ENABLED,
- mEnableAdb.isChecked() ? 1 : 0);
+ if (mEnableAdb.isChecked()) {
+ mOkClicked = false;
+ new AlertDialog.Builder(this).setMessage(
+ getResources().getString(R.string.adb_warning_message))
+ .setTitle(R.string.adb_warning_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(android.R.string.yes, this)
+ .setNegativeButton(android.R.string.no, this)
+ .show()
+ .setOnDismissListener(this);
+ } else {
+ Settings.Secure.putInt(getContentResolver(), Settings.Secure.ADB_ENABLED, 0);
+ }
} else if (preference == mKeepScreenOn) {
Settings.System.putInt(getContentResolver(), Settings.System.STAY_ON_WHILE_PLUGGED_IN,
mKeepScreenOn.isChecked() ?
@@ -85,4 +102,21 @@
return false;
}
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ mOkClicked = true;
+ Settings.Secure.putInt(getContentResolver(), Settings.Secure.ADB_ENABLED, 1);
+ } else {
+ // Reset the toggle
+ mEnableAdb.setChecked(false);
+ }
+ }
+
+ public void onDismiss(DialogInterface dialog) {
+ // Assuming that onClick gets called first
+ if (!mOkClicked) {
+ mEnableAdb.setChecked(false);
+ }
+ }
}
diff --git a/src/com/android/settings/SimLockSettings.java b/src/com/android/settings/IccLockSettings.java
similarity index 80%
rename from src/com/android/settings/SimLockSettings.java
rename to src/com/android/settings/IccLockSettings.java
index 286e3d6..18beb32 100644
--- a/src/com/android/settings/SimLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -22,35 +22,36 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
-import android.preference.CheckBoxPreference;
import android.preference.PreferenceScreen;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
import android.widget.Toast;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
/**
- * Implements the preference screen to enable/disable SIM lock and
- * also the dialogs to change the SIM PIN. In the former case, enabling/disabling
- * the SIM lock will prompt the user for the current PIN.
+ * Implements the preference screen to enable/disable ICC lock and
+ * also the dialogs to change the ICC PIN. In the former case, enabling/disabling
+ * the ICC lock will prompt the user for the current PIN.
* In the Change PIN case, it prompts the user for old pin, new pin and new pin
* again before attempting to change it. Calls the SimCard interface to execute
* these operations.
*
*/
-public class SimLockSettings extends PreferenceActivity
+public class IccLockSettings extends PreferenceActivity
implements EditPinPreference.OnPinEnteredListener {
private static final int OFF_MODE = 0;
- // State when enabling/disabling SIM lock
- private static final int SIM_LOCK_MODE = 1;
+ // State when enabling/disabling ICC lock
+ private static final int ICC_LOCK_MODE = 1;
// State when entering the old pin
- private static final int SIM_OLD_MODE = 2;
+ private static final int ICC_OLD_MODE = 2;
// State when entering the new pin - first time
- private static final int SIM_NEW_MODE = 3;
+ private static final int ICC_NEW_MODE = 3;
// State when entering the new pin - second time
- private static final int SIM_REENTER_MODE = 4;
+ private static final int ICC_REENTER_MODE = 4;
// Keys in xml file
private static final String PIN_DIALOG = "sim_pin";
@@ -70,7 +71,7 @@
private String mOldPin;
private String mNewPin;
private String mError;
- // Are we trying to enable or disable SIM lock?
+ // Are we trying to enable or disable ICC lock?
private boolean mToState;
private Phone mPhone;
@@ -81,19 +82,19 @@
private Resources mRes;
// For async handler to identify request type
- private static final int ENABLE_SIM_PIN_COMPLETE = 100;
- private static final int CHANGE_SIM_PIN_COMPLETE = 101;
+ private static final int ENABLE_ICC_PIN_COMPLETE = 100;
+ private static final int CHANGE_ICC_PIN_COMPLETE = 101;
- // For replies from SimCard interface
+ // For replies from IccCard interface
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
AsyncResult ar = (AsyncResult) msg.obj;
switch (msg.what) {
- case ENABLE_SIM_PIN_COMPLETE:
- simLockChanged(ar.exception == null);
+ case ENABLE_ICC_PIN_COMPLETE:
+ iccLockChanged(ar.exception == null);
break;
- case CHANGE_SIM_PIN_COMPLETE:
- simPinChanged(ar.exception == null);
+ case CHANGE_ICC_PIN_COMPLETE:
+ iccPinChanged(ar.exception == null);
break;
}
@@ -102,24 +103,24 @@
};
// For top-level settings screen to query
- static boolean isSimLockEnabled() {
- return PhoneFactory.getDefaultPhone().getSimCard().getSimLockEnabled();
+ static boolean isIccLockEnabled() {
+ return PhoneFactory.getDefaultPhone().getIccCard().getIccLockEnabled();
}
static String getSummary(Context context) {
Resources res = context.getResources();
- String summary = isSimLockEnabled()
- ? res.getString(R.string.sim_lock_on)
+ String summary = isIccLockEnabled()
+ ? res.getString(R.string.sim_lock_on)
: res.getString(R.string.sim_lock_off);
return summary;
}
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
addPreferencesFromResource(R.xml.sim_lock_settings);
-
+
mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
mPinToggle = (CheckBoxPreference) findPreference(PIN_TOGGLE);
if (savedInstanceState != null && savedInstanceState.containsKey(DIALOG_STATE)) {
@@ -142,7 +143,7 @@
protected void onResume() {
super.onResume();
- mPinToggle.setChecked(mPhone.getSimCard().getSimLockEnabled());
+ mPinToggle.setChecked(mPhone.getIccCard().getIccLockEnabled());
if (mDialogState != OFF_MODE) {
showPinDialog();
@@ -182,21 +183,21 @@
mPinDialog.setText(mPin);
String message = "";
switch (mDialogState) {
- case SIM_LOCK_MODE:
+ case ICC_LOCK_MODE:
message = mRes.getString(R.string.sim_enter_pin);
mPinDialog.setDialogTitle(mToState
? mRes.getString(R.string.sim_enable_sim_lock)
: mRes.getString(R.string.sim_disable_sim_lock));
break;
- case SIM_OLD_MODE:
+ case ICC_OLD_MODE:
message = mRes.getString(R.string.sim_enter_old);
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
break;
- case SIM_NEW_MODE:
+ case ICC_NEW_MODE:
message = mRes.getString(R.string.sim_enter_new);
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
break;
- case SIM_REENTER_MODE:
+ case ICC_REENTER_MODE:
message = mRes.getString(R.string.sim_reenter_new);
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
break;
@@ -222,26 +223,26 @@
return;
}
switch (mDialogState) {
- case SIM_LOCK_MODE:
- tryChangeSimLockState();
+ case ICC_LOCK_MODE:
+ tryChangeIccLockState();
break;
- case SIM_OLD_MODE:
+ case ICC_OLD_MODE:
mOldPin = mPin;
- mDialogState = SIM_NEW_MODE;
+ mDialogState = ICC_NEW_MODE;
mError = null;
mPin = null;
showPinDialog();
break;
- case SIM_NEW_MODE:
+ case ICC_NEW_MODE:
mNewPin = mPin;
- mDialogState = SIM_REENTER_MODE;
+ mDialogState = ICC_REENTER_MODE;
mPin = null;
showPinDialog();
break;
- case SIM_REENTER_MODE:
+ case ICC_REENTER_MODE:
if (!mPin.equals(mNewPin)) {
mError = mRes.getString(R.string.sim_pins_dont_match);
- mDialogState = SIM_NEW_MODE;
+ mDialogState = ICC_NEW_MODE;
mPin = null;
showPinDialog();
} else {
@@ -258,21 +259,21 @@
mToState = mPinToggle.isChecked();
// Flip it back and pop up pin dialog
mPinToggle.setChecked(!mToState);
- mDialogState = SIM_LOCK_MODE;
+ mDialogState = ICC_LOCK_MODE;
showPinDialog();
}
return true;
}
- private void tryChangeSimLockState() {
- // Try to change sim lock. If it succeeds, toggle the lock state and
+ private void tryChangeIccLockState() {
+ // Try to change icc lock. If it succeeds, toggle the lock state and
// reset dialog state. Else inject error message and show dialog again.
- Message callback = Message.obtain(mHandler, ENABLE_SIM_PIN_COMPLETE);
- mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback);
+ Message callback = Message.obtain(mHandler, ENABLE_ICC_PIN_COMPLETE);
+ mPhone.getIccCard().setIccLockEnabled(mToState, mPin, callback);
}
- private void simLockChanged(boolean success) {
+ private void iccLockChanged(boolean success) {
if (success) {
mPinToggle.setChecked(mToState);
} else {
@@ -283,14 +284,14 @@
resetDialogState();
}
- private void simPinChanged(boolean success) {
+ private void iccPinChanged(boolean success) {
if (!success) {
// TODO: I18N
- Toast.makeText(this, mRes.getString(R.string.sim_change_failed),
+ Toast.makeText(this, mRes.getString(R.string.sim_change_failed),
Toast.LENGTH_SHORT)
.show();
} else {
- Toast.makeText(this, mRes.getString(R.string.sim_change_succeeded),
+ Toast.makeText(this, mRes.getString(R.string.sim_change_succeeded),
Toast.LENGTH_SHORT)
.show();
@@ -299,8 +300,8 @@
}
private void tryChangePin() {
- Message callback = Message.obtain(mHandler, CHANGE_SIM_PIN_COMPLETE);
- mPhone.getSimCard().changeSimLockPassword(mOldPin,
+ Message callback = Message.obtain(mHandler, CHANGE_ICC_PIN_COMPLETE);
+ mPhone.getIccCard().changeIccLockPassword(mOldPin,
mNewPin, callback);
}
@@ -314,7 +315,7 @@
private void resetDialogState() {
mError = null;
- mDialogState = SIM_OLD_MODE; // Default for when Change PIN is clicked
+ mDialogState = ICC_OLD_MODE; // Default for when Change PIN is clicked
mPin = "";
setDialogValues();
}
diff --git a/src/com/android/settings/InstalledAppDetails.java b/src/com/android/settings/InstalledAppDetails.java
index 327874b..5a4e672 100644
--- a/src/com/android/settings/InstalledAppDetails.java
+++ b/src/com/android/settings/InstalledAppDetails.java
@@ -22,13 +22,16 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageStatsObserver;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -36,6 +39,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
import android.text.format.Formatter;
import android.util.Config;
import android.util.Log;
@@ -64,9 +68,8 @@
private ApplicationInfo mAppInfo;
private Button mAppButton;
private Button mActivitiesButton;
- private boolean mCanUninstall;
- private boolean localLOGV=Config.LOGV || false;
- private TextView mAppSnippetSize;
+ private boolean localLOGV = false;
+ private TextView mAppVersion;
private TextView mTotalSize;
private TextView mAppSize;
private TextView mDataSize;
@@ -100,10 +103,18 @@
private CharSequence mComputingStr;
private CharSequence mAppButtonText;
+ // Dialog identifiers used in showDialog
+ private static final int DLG_BASE = 0;
+ private static final int DLG_CLEAR_DATA = DLG_BASE + 1;
+ private static final int DLG_FACTORY_RESET = DLG_BASE + 2;
+ private static final int DLG_APP_NOT_FOUND = DLG_BASE + 3;
+ private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 4;
+
// Possible btn states
private enum AppButtonStates {
CLEAR_DATA,
UNINSTALL,
+ FACTORY_RESET,
NONE
}
private AppButtonStates mAppButtonState;
@@ -127,14 +138,6 @@
}
};
- private boolean isUninstallable() {
- if (((mAppInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) &&
- ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0)) {
- return false;
- }
- return true;
- }
-
class ClearUserDataObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(final String packageName, final boolean succeeded) {
final Message msg = mHandler.obtainMessage(CLEAR_USER_DATA);
@@ -154,7 +157,7 @@
}
}
-
+
class ClearCacheObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(final String packageName, final boolean succeeded) {
final Message msg = mHandler.obtainMessage(CLEAR_CACHE);
@@ -170,40 +173,13 @@
return Formatter.formatFileSize(this, size);
}
- private void setAppBtnState() {
- boolean visible = false;
- if(mCanUninstall) {
- //app can clear user data
- if((mAppInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
- == ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) {
- mAppButtonText = getText(R.string.clear_user_data_text);
- mAppButtonState = AppButtonStates.CLEAR_DATA;
- visible = true;
- } else {
- //hide button if diableClearUserData is set
- visible = false;
- mAppButtonState = AppButtonStates.NONE;
- }
- } else {
- visible = true;
- mAppButtonState = AppButtonStates.UNINSTALL;
- mAppButtonText = getText(R.string.uninstall_text);
- }
- if(visible) {
- mAppButton.setText(mAppButtonText);
- mAppButton.setVisibility(View.VISIBLE);
- } else {
- mAppButton.setVisibility(View.GONE);
- }
- }
-
/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
- //get package manager
+ // Get package manager
mPm = getPackageManager();
- //get application's name from intent
+ // Get application's name from intent
Intent intent = getIntent();
final String packageName = intent.getStringExtra(ManageApplications.APP_PKG_NAME);
mComputingStr = getText(R.string.computing_size);
@@ -212,45 +188,31 @@
totalSizeStr = appSizeStr = dataSizeStr = mComputingStr;
if(localLOGV) Log.i(TAG, "Have to compute package sizes");
mSizeObserver = new PkgSizeObserver();
- mPm.getPackageSizeInfo(packageName, mSizeObserver);
-
try {
mAppInfo = mPm.getApplicationInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException e) {
Log.e(TAG, "Exception when retrieving package:"+packageName, e);
- displayErrorDialog(R.string.app_not_found_dlg_text, true, true);
+ showDialogInner(DLG_APP_NOT_FOUND);
+ return;
}
- setContentView(R.layout.installed_app_details);
- ((ImageView)findViewById(R.id.app_icon)).setImageDrawable(mAppInfo.loadIcon(mPm));
- //set application name TODO version
- CharSequence appName = mAppInfo.loadLabel(mPm);
- if(appName == null) {
- appName = getString(_UNKNOWN_APP);
- }
- ((TextView)findViewById(R.id.app_name)).setText(appName);
- mAppSnippetSize = ((TextView)findViewById(R.id.app_size));
- mAppSnippetSize.setText(totalSizeStr);
+ setContentView(R.layout.installed_app_details);
//TODO download str and download url
- //set values on views
+ // Set default values on sizes
mTotalSize = (TextView)findViewById(R.id.total_size_text);
mTotalSize.setText(totalSizeStr);
mAppSize = (TextView)findViewById(R.id.application_size_text);
mAppSize.setText(appSizeStr);
mDataSize = (TextView)findViewById(R.id.data_size_text);
mDataSize.setText(dataSizeStr);
-
+ // Get AppButton
mAppButton = ((Button)findViewById(R.id.uninstall_button));
- //determine if app is a system app
- mCanUninstall = !isUninstallable();
- if(localLOGV) Log.i(TAG, "Is systemPackage "+mCanUninstall);
- setAppBtnState();
+ // Get ManageSpaceButton
mManageSpaceButton = (Button)findViewById(R.id.manage_space_button);
if(mAppInfo.manageSpaceActivityName != null) {
mManageSpaceButton.setVisibility(View.VISIBLE);
mManageSpaceButton.setOnClickListener(this);
}
-
// Cache section
mCachePanel = findViewById(R.id.cache_panel);
mCacheSize = (TextView) findViewById(R.id.cache_size_text);
@@ -258,17 +220,16 @@
mClearCacheButton = (Button) findViewById(R.id.clear_cache_button);
mForceStopButton = (Button) findViewById(R.id.force_stop_button);
mForceStopButton.setOnClickListener(this);
-
- //clear activities
+ // Get list of preferred activities
mActivitiesButton = (Button)findViewById(R.id.clear_activities_button);
List<ComponentName> prefActList = new ArrayList<ComponentName>();
- //intent list cannot be null. so pass empty list
+ // Intent list cannot be null. so pass empty list
List<IntentFilter> intentList = new ArrayList<IntentFilter>();
mPm.getPreferredActivities(intentList, prefActList, packageName);
if(localLOGV) Log.i(TAG, "Have "+prefActList.size()+" number of activities in prefered list");
TextView autoLaunchView = (TextView)findViewById(R.id.auto_launch);
if(prefActList.size() <= 0) {
- //disable clear activities button
+ // Disable clear activities button
autoLaunchView.setText(R.string.auto_launch_disable_text);
mActivitiesButton.setEnabled(false);
} else {
@@ -276,7 +237,7 @@
mActivitiesButton.setOnClickListener(this);
}
- // security permissions section
+ // Security permissions section
LinearLayout permsView = (LinearLayout) findViewById(R.id.permissions_section);
AppSecurityPermissions asp = new AppSecurityPermissions(this, packageName);
if(asp.getPermissionCount() > 0) {
@@ -290,21 +251,85 @@
}
}
- private void displayErrorDialog(int msgId, final boolean finish, final boolean changed) {
- //display confirmation dialog
- new AlertDialog.Builder(this)
- .setTitle(getString(R.string.app_not_found_dlg_title))
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(msgId))
- .setNeutralButton(getString(R.string.dlg_ok),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- //force to recompute changed value
- setIntentAndFinish(finish, changed);
- }
+ private void refreshAppAttributes(PackageInfo pkgInfo) {
+ setAppLabelAndIcon();
+ // Version number of application
+ setAppVersion(pkgInfo);
+ setAppBtnState();
+ // Refresh size info
+ if (mAppInfo != null && mAppInfo.packageName != null) {
+ mPm.getPackageSizeInfo(mAppInfo.packageName, mSizeObserver);
+ }
+ }
+
+ // Utility method to set applicaiton label and icon.
+ private void setAppLabelAndIcon() {
+ ((ImageView)findViewById(R.id.app_icon)).setImageDrawable(mAppInfo.loadIcon(mPm));
+ //set application name TODO version
+ CharSequence appName = mAppInfo.loadLabel(mPm);
+ if(appName == null) {
+ appName = getString(_UNKNOWN_APP);
+ }
+ ((TextView)findViewById(R.id.app_name)).setText(appName);
+ }
+
+ // Utility method to set application version
+ private void setAppVersion(PackageInfo pkgInfo) {
+ // Version number of application
+ mAppVersion = ((TextView)findViewById(R.id.app_version));
+ if (pkgInfo != null) {
+ mAppVersion.setVisibility(View.VISIBLE);
+ mAppVersion.setText(getString(R.string.version_text,
+ String.valueOf(pkgInfo.versionCode)));
+ } else {
+ mAppVersion.setVisibility(View.GONE);
+ }
+ }
+
+ // Utility method to set button state
+ private void setAppBtnState() {
+ boolean visible = true;
+ if ((mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ mAppButtonState = AppButtonStates.FACTORY_RESET;
+ mAppButtonText = getText(R.string.app_factory_reset);
+ } else {
+ if ((mAppInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) {
+ // Hide button if diableClearUserData is set
+ mAppButtonState = AppButtonStates.NONE;
+ visible = false;
+ } else {
+ mAppButtonState = AppButtonStates.CLEAR_DATA;
+ mAppButtonText = getText(R.string.clear_user_data_text);
}
- )
- .show();
+ }
+ } else {
+ mAppButtonState = AppButtonStates.UNINSTALL;
+ mAppButtonText = getText(R.string.uninstall_text);
+ }
+ if(visible) {
+ mAppButton.setText(mAppButtonText);
+ mAppButton.setVisibility(View.VISIBLE);
+ } else {
+ mAppButton.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ PackageInfo pkgInfo;
+ // Get application info again to refresh changed properties of application
+ try {
+ mAppInfo = mPm.getApplicationInfo(mAppInfo.packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ pkgInfo = mPm.getPackageInfo(mAppInfo.packageName, 0);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Exception when retrieving package:" + mAppInfo.packageName, e);
+ showDialogInner(DLG_APP_NOT_FOUND);
+ return;
+ }
+ refreshAppAttributes(pkgInfo);
}
private void setIntentAndFinish(boolean finish, boolean appChanged) {
@@ -331,7 +356,6 @@
mSizeInfo = newPs;
String str = getSizeStr(newTot);
mTotalSize.setText(str);
- mAppSnippetSize.setText(str);
mAppSize.setText(getSizeStr(newPs.codeSize));
mDataSize.setText(getSizeStr(newPs.dataSize));
mCacheSize.setText(getSizeStr(newPs.cacheSize));
@@ -340,7 +364,6 @@
if(newTot != oldTot) {
String str = getSizeStr(newTot);
mTotalSize.setText(str);
- mAppSnippetSize.setText(str);
changed = true;
}
if(newPs.codeSize != mSizeInfo.codeSize) {
@@ -415,14 +438,76 @@
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
if(!res) {
- //doesnt initiate clear. some error. should not happen but just log error for now
+ // Clearing data failed for some obscure reason. Just log error for now
Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
- displayErrorDialog(R.string.clear_data_failed, false, false);
+ showDialogInner(DLG_CANNOT_CLEAR_DATA);
} else {
mAppButton.setText(R.string.recompute_size);
}
}
+ private void showDialogInner(int id) {
+ //removeDialog(id);
+ showDialog(id);
+ }
+
+ @Override
+ public Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DLG_CLEAR_DATA:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.clear_data_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.clear_data_dlg_text))
+ .setPositiveButton(R.string.dlg_ok, this)
+ .setNegativeButton(R.string.dlg_cancel, this)
+ .create();
+ case DLG_FACTORY_RESET:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.app_factory_reset_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.app_factory_reset_dlg_text))
+ .setPositiveButton(R.string.dlg_ok, this)
+ .setNegativeButton(R.string.dlg_cancel, this)
+ .create();
+ case DLG_APP_NOT_FOUND:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.app_not_found_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.app_not_found_dlg_title))
+ .setNeutralButton(getString(R.string.dlg_ok),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ //force to recompute changed value
+ setIntentAndFinish(true, true);
+ }
+ })
+ .create();
+ case DLG_CANNOT_CLEAR_DATA:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.clear_failed_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.clear_failed_dlg_text))
+ .setNeutralButton(R.string.dlg_ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ //force to recompute changed value
+ setIntentAndFinish(false, false);
+ }
+ })
+ .create();
+ }
+ return null;
+ }
+
+ private void uninstallPkg(String packageName) {
+ // Create new intent to launch Uninstaller activity
+ Uri packageURI = Uri.parse("package:"+packageName);
+ Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
+ startActivity(uninstallIntent);
+ setIntentAndFinish(true, true);
+ }
+
/*
* Method implementing functionality of buttons clicked
* @see android.view.View.OnClickListener#onClick(android.view.View)
@@ -430,21 +515,12 @@
public void onClick(View v) {
String packageName = mAppInfo.packageName;
if(v == mAppButton) {
- if(mCanUninstall) {
- //display confirmation dialog
- new AlertDialog.Builder(this)
- .setTitle(getString(R.string.clear_data_dlg_title))
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(R.string.clear_data_dlg_text))
- .setPositiveButton(R.string.dlg_ok, this)
- .setNegativeButton(R.string.dlg_cancel, this)
- .show();
- } else {
- //create new intent to launch Uninstaller activity
- Uri packageURI = Uri.parse("package:"+packageName);
- Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
- startActivity(uninstallIntent);
- setIntentAndFinish(true, true);
+ if (mAppButtonState == AppButtonStates.CLEAR_DATA) {
+ showDialogInner(DLG_CLEAR_DATA);
+ } else if (mAppButtonState == AppButtonStates.FACTORY_RESET) {
+ showDialogInner(DLG_FACTORY_RESET);
+ } else if (mAppButtonState == AppButtonStates.UNINSTALL) {
+ uninstallPkg(packageName);
}
} else if(v == mActivitiesButton) {
mPm.clearPackagePreferredActivities(packageName);
@@ -468,8 +544,13 @@
public void onClick(DialogInterface dialog, int which) {
if(which == AlertDialog.BUTTON_POSITIVE) {
- //invoke uninstall or clear user data based on sysPackage
- initiateClearUserDataForSysPkg();
+ if (mAppButtonState == AppButtonStates.CLEAR_DATA) {
+ // Invoke uninstall or clear user data based on sysPackage
+ initiateClearUserDataForSysPkg();
+ } else if (mAppButtonState == AppButtonStates.FACTORY_RESET) {
+ // Initiate package installer to delete package
+ uninstallPkg(mAppInfo.packageName);
+ }
} else {
//cancel do nothing just retain existing screen
}
diff --git a/src/com/android/settings/LocalePicker.java b/src/com/android/settings/LocalePicker.java
index 386d7e0..39fb6fa 100644
--- a/src/com/android/settings/LocalePicker.java
+++ b/src/com/android/settings/LocalePicker.java
@@ -19,6 +19,7 @@
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.ListActivity;
+import android.backup.BackupManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.RemoteException;
@@ -30,6 +31,7 @@
import java.io.BufferedWriter;
import java.io.FileOutputStream;
+import java.text.Collator;
import java.util.Arrays;
import java.util.Locale;
@@ -38,7 +40,9 @@
Loc[] mLocales;
- private static class Loc {
+ private static class Loc implements Comparable {
+ static Collator sCollator = Collator.getInstance();
+
String label;
Locale locale;
@@ -51,6 +55,10 @@
public String toString() {
return this.label;
}
+
+ public int compareTo(Object o) {
+ return sCollator.compare(this.label, ((Loc) o).label);
+ }
}
int getContentView() {
@@ -71,38 +79,42 @@
for (int i = 0 ; i < origSize; i++ ) {
String s = locales[i];
int len = s.length();
- if (len == 2) {
- Locale l = new Locale(s);
- preprocess[finalSize++] = new Loc(toTitleCase(l.getDisplayLanguage()), l);
- } else if (len == 5) {
+ if (len == 5) {
String language = s.substring(0, 2);
String country = s.substring(3, 5);
Locale l = new Locale(language, country);
if (finalSize == 0) {
- preprocess[finalSize++] = new Loc(toTitleCase(l.getDisplayLanguage()), l);
+ Log.v(TAG, "adding initial "+
+ toTitleCase(l.getDisplayLanguage(l)));
+ preprocess[finalSize++] =
+ new Loc(toTitleCase(l.getDisplayLanguage(l)), l);
} else {
// check previous entry:
- // same lang and no country -> overwrite it with a lang-only name
- // same lang and a country -> upgrade to full name and
+ // same lang and a country -> upgrade to full name and
// insert ours with full name
// diff lang -> insert ours with lang-only name
- if (preprocess[finalSize-1].locale.getLanguage().equals(language)) {
- String prevCountry = preprocess[finalSize-1].locale.getCountry();
- if (prevCountry.length() == 0) {
- preprocess[finalSize-1].locale = l;
- preprocess[finalSize-1].label = toTitleCase(l.getDisplayLanguage());
- } else {
- preprocess[finalSize-1].label = toTitleCase(preprocess[finalSize-1].locale.getDisplayName());
- preprocess[finalSize++] = new Loc(toTitleCase(l.getDisplayName()), l);
- }
+ if (preprocess[finalSize-1].locale.getLanguage().equals(
+ language)) {
+ Log.v(TAG, "backing up and fixing "+
+ preprocess[finalSize-1].label+" to "+
+ preprocess[finalSize-1].locale.
+ getDisplayName(l));
+ preprocess[finalSize-1].label = toTitleCase(
+ preprocess[finalSize-1].
+ locale.getDisplayName(l));
+ Log.v(TAG, " and adding "+
+ toTitleCase(l.getDisplayName(l)));
+ preprocess[finalSize++] =
+ new Loc(toTitleCase(l.getDisplayName(l)), l);
} else {
String displayName;
if (s.equals("zz_ZZ")) {
displayName = "Pseudo...";
} else {
- displayName = toTitleCase(l.getDisplayLanguage());
+ displayName = toTitleCase(l.getDisplayLanguage(l));
}
+ Log.v(TAG, "adding "+displayName);
preprocess[finalSize++] = new Loc(displayName, l);
}
}
@@ -112,9 +124,11 @@
for (int i = 0; i < finalSize ; i++) {
mLocales[i] = preprocess[i];
}
+ Arrays.sort(mLocales);
int layoutId = R.layout.locale_picker_item;
int fieldId = R.id.locale;
- ArrayAdapter<Loc> adapter = new ArrayAdapter<Loc>(this, layoutId, fieldId, mLocales);
+ ArrayAdapter<Loc> adapter =
+ new ArrayAdapter<Loc>(this, layoutId, fieldId, mLocales);
getListView().setAdapter(adapter);
}
@@ -145,6 +159,8 @@
config.userSetLocale = true;
am.updateConfiguration(config);
+ // Trigger the dirty bit for the Settings Provider.
+ BackupManager.dataChanged("com.android.providers.settings");
} catch (RemoteException e) {
// Intentionally left blank
}
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 5df9313..257122b 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -94,7 +94,7 @@
private static final int MENU_ITEM_TOGGLE_DATA = 5;
private static final int MENU_ITEM_TOGGLE_DATA_ON_BOOT = 6;
- private TextView mImei;
+ private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
private TextView number;
private TextView callState;
private TextView operatorName;
@@ -239,8 +239,7 @@
if (ar.exception != null) {
smsc.setText("refresh error");
} else {
- byte[] buf = (byte[]) ar.result;
- smsc.setText(new String(buf));
+ smsc.setText((String)ar.result);
}
break;
case EVENT_UPDATE_SMSC_DONE:
@@ -272,9 +271,6 @@
final int OEM_QXDM_SDLOG_LEN = 4;
final int OEM_PS_AUTO_ATTACH_FUNCTAG = 0x00020000;
final int OEM_CIPHERING_FUNCTAG = 0x00020001;
- final int OEM_SMSC_UPDATE_FUNCTAG = 0x00020002;
- final int OEM_SMSC_QUERY_FUNCTAG = 0x00020003;
- final int OEM_SMSC_QUERY_LEN = 0;
/**
* The OEM interface to store QXDM to SD.
@@ -339,32 +335,6 @@
return bos.toByteArray();
}
- byte[] getSmscQueryData() {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- DataOutputStream dos = new DataOutputStream(bos);
- try {
- writeIntLittleEndian(dos, OEM_SMSC_QUERY_FUNCTAG);
- writeIntLittleEndian(dos, OEM_SMSC_QUERY_LEN * SIZE_OF_INT);
- } catch (IOException e) {
- return null;
- }
- return bos.toByteArray();
- }
-
- byte[] getSmscUpdateData(String smsc) {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- DataOutputStream dos = new DataOutputStream(bos);
- try {
- byte[] smsc_bytes = smsc.getBytes();
- writeIntLittleEndian(dos, OEM_SMSC_UPDATE_FUNCTAG);
- writeIntLittleEndian(dos, smsc_bytes.length);
- dos.write(smsc_bytes);
- } catch (IOException e) {
- return null;
- }
- return bos.toByteArray();
- }
-
byte[] getPsAutoAttachData(boolean enable) {
return getSimpleFeatureData(OEM_PS_AUTO_ATTACH_FUNCTAG, enable);
}
@@ -405,7 +375,7 @@
mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
phone = PhoneFactory.getDefaultPhone();
- mImei = (TextView) findViewById(R.id.imei);
+ mDeviceId= (TextView) findViewById(R.id.imei);
number = (TextView) findViewById(R.id.number);
callState = (TextView) findViewById(R.id.call);
operatorName = (TextView) findViewById(R.id.operator);
@@ -518,7 +488,8 @@
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label).setOnMenuItemClickListener(mSelectBandCallback)
+ menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label)
+ .setOnMenuItemClickListener(mSelectBandCallback)
.setAlphabeticShortcut('b');
menu.add(1, MENU_ITEM_VIEW_ADN, 0,
R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
@@ -531,14 +502,14 @@
menu.add(1, MENU_ITEM_TOGGLE_DATA,
0, R.string.radioInfo_menu_disableData).setOnMenuItemClickListener(mToggleData);
menu.add(1, MENU_ITEM_TOGGLE_DATA_ON_BOOT,
- 0, R.string.radioInfo_menu_disableDataOnBoot).setOnMenuItemClickListener(mToggleDataOnBoot);
+ 0, R.string.radioInfo_menu_disableDataOnBoot).setOnMenuItemClickListener(
+ mToggleDataOnBoot);
return true;
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu)
- {
+ public boolean onPrepareOptionsMenu(Menu menu) {
// Get the TOGGLE DATA menu item in the right state.
MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
int state = mTelephonyManager.getDataState();
@@ -575,11 +546,10 @@
}
private void updatePowerState() {
- //log("updatePowerState");
String buttonText = isRadioOn() ?
getString(R.string.turn_off_radio) :
getString(R.string.turn_on_radio);
- radioPowerButton.setText(buttonText);
+ radioPowerButton.setText(buttonText);
}
private void updateQxdmState(Boolean newQxdmStatus) {
@@ -619,24 +589,24 @@
}
private void updateDnsCheckState() {
- GSMPhone gsmPhone = (GSMPhone) phone;
- dnsCheckState.setText(gsmPhone.isDnsCheckDisabled() ?
+ dnsCheckState.setText(phone.isDnsCheckDisabled() ?
"0.0.0.0 allowed" :"0.0.0.0 not allowed");
}
-
+
private final void
updateSignalStrength() {
- int state =
- mPhoneStateReceiver.getServiceState().getState();
+ // TODO PhoneStateIntentReceiver is deprecated and PhoneStateListener
+ // should probably used instead.
+ int state = mPhoneStateReceiver.getServiceState().getState();
Resources r = getResources();
if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
(ServiceState.STATE_POWER_OFF == state)) {
dBm.setText("0");
}
-
+
int signalDbm = mPhoneStateReceiver.getSignalStrengthDbm();
-
+
if (-1 == signalDbm) signalDbm = 0;
int signalAsu = mPhoneStateReceiver.getSignalStrength();
@@ -650,11 +620,15 @@
}
private final void updateLocation(CellLocation location) {
- GsmCellLocation loc = (GsmCellLocation)location;
- Resources r = getResources();
+ int lac = -1;
+ int cid = -1;
+ if (location instanceof GsmCellLocation) {
+ GsmCellLocation loc = (GsmCellLocation)location;
+ lac = loc.getLac();
+ cid = loc.getCid();
+ }
- int lac = loc.getLac();
- int cid = loc.getCid();
+ Resources r = getResources();
mLocation.setText(r.getString(R.string.radioInfo_lac) + " = "
+ ((lac == -1) ? "unknown" : Integer.toHexString(lac))
@@ -782,8 +756,9 @@
s = phone.getDeviceId();
if (s == null) s = r.getString(R.string.radioInfo_unknown);
- mImei.setText(s);
+ mDeviceId.setText(s);
+
s = phone.getLine1Number();
if (s == null) s = r.getString(R.string.radioInfo_unknown);
number.setText(s);
@@ -889,10 +864,7 @@
}
private void refreshSmsc() {
- byte[] data = mOem.getSmscQueryData();
- if (data == null) return;
- phone.invokeOemRilRequestRaw(data,
- mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
+ phone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
}
private final void updatePingState() {
@@ -1030,7 +1002,7 @@
private MenuItem.OnMenuItemClickListener mViewSDNCallback = new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(
- Intent.ACTION_VIEW, Uri.parse("content://sim/sdn"));
+ Intent.ACTION_VIEW, Uri.parse("content://icc/sdn"));
// XXX We need to specify the component here because if we don't
// the activity manager will try to resolve the type by calling
// the content provider, which causes it to be loaded in a process
@@ -1085,7 +1057,7 @@
private MenuItem.OnMenuItemClickListener mGetPdpList = new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
- phone.getPdpContextList(null);
+ phone.getDataCallList(null);
return true;
}
};
@@ -1122,8 +1094,7 @@
OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
public void onClick(View v) {
- GSMPhone gsmPhone = (GSMPhone) phone;
- gsmPhone.disableDnsCheck(!gsmPhone.isDnsCheckDisabled());
+ phone.disableDnsCheck(!phone.isDnsCheckDisabled());
updateDnsCheckState();
}
};
@@ -1137,9 +1108,7 @@
OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
public void onClick(View v) {
updateSmscButton.setEnabled(false);
- byte[] data = mOem.getSmscUpdateData(smsc.getText().toString());
- if (data == null) return;
- phone.invokeOemRilRequestRaw(data,
+ phone.setSmscAddress(smsc.getText().toString(),
mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
}
};
@@ -1170,7 +1139,7 @@
mPreferredNetworkHandler = new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView parent, View v, int pos, long id) {
Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
- if (pos>=0 && pos<=2) {
+ if (pos>=0 && pos<=7) { //IS THIS NEEDED to extend to the entire range of values
phone.setPreferredNetworkType(pos, msg);
}
}
diff --git a/src/com/android/settings/SdCardSettings.java b/src/com/android/settings/SdCardSettings.java
index b6935a2..637babe 100644
--- a/src/com/android/settings/SdCardSettings.java
+++ b/src/com/android/settings/SdCardSettings.java
@@ -27,6 +27,7 @@
import android.os.IMountService;
import android.os.ServiceManager;
import android.os.StatFs;
+import android.text.format.Formatter;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@@ -153,29 +154,7 @@
}
private String formatSize(long size) {
- String suffix = null;
-
- // add K or M suffix if size is greater than 1K or 1M
- if (size >= 1024) {
- suffix = "K";
- size /= 1024;
- if (size >= 1024) {
- suffix = "M";
- size /= 1024;
- }
- }
-
- StringBuilder resultBuffer = new StringBuilder(Long.toString(size));
-
- int commaOffset = resultBuffer.length() - 3;
- while (commaOffset > 0) {
- resultBuffer.insert(commaOffset, ',');
- commaOffset -= 3;
- }
-
- if (suffix != null)
- resultBuffer.append(suffix);
- return resultBuffer.toString();
+ return Formatter.formatFileSize(this, size);
}
OnClickListener mMassStorageListener = new OnClickListener() {
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 6858fd3..73578c7 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -19,31 +19,48 @@
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.ContentQueryMap;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.Cursor;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
+import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings;
-import android.util.Config;
-import android.util.Log;
+import android.security.Keystore;
+import android.text.Html;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
import com.android.internal.widget.LockPatternUtils;
+import android.telephony.TelephonyManager;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Observable;
+import java.util.Observer;
/**
* Gesture lock pattern settings.
*/
-public class SecuritySettings extends PreferenceActivity
- implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+public class SecuritySettings extends PreferenceActivity implements
+ DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
// Lock Settings
-
+
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";
@@ -56,18 +73,51 @@
private Preference mChoosePattern;
private CheckBoxPreference mShowPassword;
-
+
// Location Settings
-
+ private static final String LOCATION_CATEGORY = "location_category";
private static final String LOCATION_NETWORK = "location_network";
private static final String LOCATION_GPS = "location_gps";
+ // Credential storage
+ public static final String ACTION_ADD_CREDENTIAL =
+ "android.security.ADD_CREDENTIAL";
+ public static final String ACTION_UNLOCK_CREDENTIAL_STORAGE =
+ "android.security.UNLOCK_CREDENTIAL_STORAGE";
+ private static final String KEY_CSTOR_TYPE_NAME = "typeName";
+ private static final String KEY_CSTOR_ITEM = "item";
+ private static final String KEY_CSTOR_NAMESPACE = "namespace";
+ private static final String KEY_CSTOR_DESCRIPTION = "description";
+ private static final int CSTOR_MIN_PASSWORD_LENGTH = 8;
+
+ private static final int CSTOR_INIT_DIALOG = 1;
+ private static final int CSTOR_CHANGE_PASSWORD_DIALOG = 2;
+ private static final int CSTOR_UNLOCK_DIALOG = 3;
+ private static final int CSTOR_RESET_DIALOG = 4;
+ private static final int CSTOR_NAME_CREDENTIAL_DIALOG = 5;
+
+ private CstorHelper mCstorHelper = new CstorHelper();
+
+ // Vendor specific
+ private static final String GSETTINGS_PROVIDER = "com.google.android.providers.settings";
+ private static final String USE_LOCATION = "use_location";
+ private static final String KEY_DONE_USE_LOCATION = "doneLocation";
+ private CheckBoxPreference mUseLocation;
+ private boolean mOkClicked;
+ private Dialog mUseLocationDialog;
+
private CheckBoxPreference mNetwork;
private CheckBoxPreference mGps;
- private LocationManager mLocationManager;
-
- // To track whether Agree was clicked in the Network location warning dialog
- private boolean mOkClicked;
+
+ // These provide support for receiving notification when Location Manager settings change.
+ // This is necessary because the Network Location Provider can change settings
+ // if the user does not confirm enabling the provider.
+ private ContentQueryMap mContentQueryMap;
+ private final class SettingsObserver implements Observer {
+ public void update(Observable o, Object arg) {
+ updateToggles();
+ }
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -77,14 +127,36 @@
mLockPatternUtils = new LockPatternUtils(getContentResolver());
createPreferenceHierarchy();
-
- // Get the available location providers
- mLocationManager = (LocationManager)
- getSystemService(Context.LOCATION_SERVICE);
mNetwork = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_NETWORK);
mGps = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_GPS);
+ mUseLocation = (CheckBoxPreference) getPreferenceScreen().findPreference(USE_LOCATION);
+
+ // Vendor specific
+ try {
+ if (mUseLocation != null
+ && getPackageManager().getPackageInfo(GSETTINGS_PROVIDER, 0) == null) {
+ ((PreferenceGroup)findPreference(LOCATION_CATEGORY))
+ .removePreference(mUseLocation);
+ }
+ } catch (NameNotFoundException nnfe) {
+ }
updateToggles();
+
+ // listen for Location Manager settings changes
+ Cursor settingsCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, null,
+ "(" + Settings.System.NAME + "=?)",
+ new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
+ null);
+ mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null);
+ mContentQueryMap.addObserver(new SettingsObserver());
+ boolean doneUseLocation = savedInstanceState != null
+ && savedInstanceState.getBoolean(KEY_DONE_USE_LOCATION, true);
+ if (getIntent().getBooleanExtra("SHOW_USE_LOCATION", false) && !doneUseLocation) {
+ showUseLocationDialog(true);
+ }
+
+ mCstorHelper.handleCstorIntents(getIntent());
}
private PreferenceScreen createPreferenceHierarchy() {
@@ -122,32 +194,46 @@
mChoosePattern = getPreferenceManager().createPreferenceScreen(this);
mChoosePattern.setIntent(intent);
inlinePrefCat.addPreference(mChoosePattern);
-
- PreferenceScreen simLockPreferences = getPreferenceManager()
- .createPreferenceScreen(this);
- simLockPreferences.setTitle(R.string.sim_lock_settings_category);
- // Intent to launch SIM lock settings
- intent = new Intent();
- intent.setClassName("com.android.settings", "com.android.settings.SimLockSettings");
- simLockPreferences.setIntent(intent);
-
- PreferenceCategory simLockCat = new PreferenceCategory(this);
- simLockCat.setTitle(R.string.sim_lock_settings_title);
- root.addPreference(simLockCat);
- simLockCat.addPreference(simLockPreferences);
+
+ int activePhoneType = TelephonyManager.getDefault().getPhoneType();
+
+ // do not display SIM lock for CDMA phone
+ if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType)
+ {
+ PreferenceScreen simLockPreferences = getPreferenceManager()
+ .createPreferenceScreen(this);
+ simLockPreferences.setTitle(R.string.sim_lock_settings_category);
+ // Intent to launch SIM lock settings
+ intent = new Intent();
+ intent.setClassName("com.android.settings", "com.android.settings.IccLockSettings");
+ simLockPreferences.setIntent(intent);
+
+ PreferenceCategory simLockCat = new PreferenceCategory(this);
+ simLockCat.setTitle(R.string.sim_lock_settings_title);
+ root.addPreference(simLockCat);
+ simLockCat.addPreference(simLockPreferences);
+ }
// Passwords
PreferenceCategory passwordsCat = new PreferenceCategory(this);
passwordsCat.setTitle(R.string.security_passwords_title);
root.addPreference(passwordsCat);
-
+
CheckBoxPreference showPassword = mShowPassword = new CheckBoxPreference(this);
showPassword.setKey("show_password");
showPassword.setTitle(R.string.show_password);
showPassword.setSummary(R.string.show_password_summary);
showPassword.setPersistent(false);
passwordsCat.addPreference(showPassword);
-
+
+ // Credential storage
+ PreferenceCategory credStoreCat = new PreferenceCategory(this);
+ credStoreCat.setTitle(R.string.cstor_settings_category);
+ root.addPreference(credStoreCat);
+ credStoreCat.addPreference(mCstorHelper.createAccessCheckBox());
+ credStoreCat.addPreference(mCstorHelper.createSetPasswordPreference());
+ credStoreCat.addPreference(mCstorHelper.createResetPreference());
+
return root;
}
@@ -168,13 +254,30 @@
R.string.lockpattern_settings_change_lock_pattern :
R.string.lockpattern_settings_choose_lock_pattern;
mChoosePattern.setTitle(chooseStringRes);
-
+
mShowPassword
.setChecked(Settings.System.getInt(getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
}
@Override
+ public void onPause() {
+ if (mUseLocationDialog != null && mUseLocationDialog.isShowing()) {
+ mUseLocationDialog.dismiss();
+ }
+ mUseLocationDialog = null;
+ super.onPause();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle icicle) {
+ if (mUseLocationDialog != null && mUseLocationDialog.isShowing()) {
+ icicle.putBoolean(KEY_DONE_USE_LOCATION, false);
+ }
+ super.onSaveInstanceState(icicle);
+ }
+
+ @Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) {
final String key = preference.getKey();
@@ -189,93 +292,70 @@
Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
mShowPassword.isChecked() ? 1 : 0);
} else if (preference == mNetwork) {
- //normally called on the toggle click
- if (mNetwork.isChecked()) {
- // Show a warning to the user that location data will be shared
- mOkClicked = false;
- new AlertDialog.Builder(this).setMessage(
- getResources().getString(R.string.location_warning_message))
- .setTitle(R.string.location_warning_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setPositiveButton(R.string.agree, this)
- .setNegativeButton(R.string.disagree, this)
- .show()
- .setOnDismissListener(this);
- } else {
- updateProviders();
- }
+ Settings.Secure.setLocationProviderEnabled(getContentResolver(),
+ LocationManager.NETWORK_PROVIDER, mNetwork.isChecked());
} else if (preference == mGps) {
- updateProviders();
+ Settings.Secure.setLocationProviderEnabled(getContentResolver(),
+ LocationManager.GPS_PROVIDER, mGps.isChecked());
+ } else if (preference == mUseLocation) {
+ //normally called on the toggle click
+ if (mUseLocation.isChecked()) {
+ showUseLocationDialog(false);
+ } else {
+ updateUseLocation();
+ }
}
return false;
}
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- updateProviders();
- mOkClicked = true;
- } else {
- // Reset the toggle
- mNetwork.setChecked(false);
- }
+ private void showPrivacyPolicy() {
+ Intent intent = new Intent("android.settings.TERMS");
+ startActivity(intent);
}
-
- public void onDismiss(DialogInterface dialog) {
- // Assuming that onClick gets called first
- if (!mOkClicked) {
- mNetwork.setChecked(false);
+
+ private void showUseLocationDialog(boolean force) {
+ // Show a warning to the user that location data will be shared
+ mOkClicked = false;
+ if (force) {
+ mUseLocation.setChecked(true);
}
+
+ CharSequence msg = getResources().getText(R.string.use_location_warning_message);
+ mUseLocationDialog = new AlertDialog.Builder(this).setMessage(msg)
+ .setTitle(R.string.use_location_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(R.string.agree, this)
+ .setNegativeButton(R.string.disagree, this)
+ .show();
+ ((TextView)mUseLocationDialog.findViewById(android.R.id.message))
+ .setMovementMethod(LinkMovementMethod.getInstance());
+ mUseLocationDialog.setOnDismissListener(this);
}
/*
* Creates toggles for each available location provider
*/
private void updateToggles() {
- String providers = getAllowedProviders();
- mNetwork.setChecked(providers.contains(LocationManager.NETWORK_PROVIDER));
- mGps.setChecked(providers.contains(LocationManager.GPS_PROVIDER));
- }
-
- private void updateProviders() {
- String preferredProviders = "";
- if (mNetwork.isChecked()) {
- preferredProviders += LocationManager.NETWORK_PROVIDER;
- }
- if (mGps.isChecked()) {
- preferredProviders += "," + LocationManager.GPS_PROVIDER;
- }
- setProviders(preferredProviders);
- }
-
- private void setProviders(String providers) {
- // Update the secure setting LOCATION_PROVIDERS_ALLOWED
- Settings.Secure.putString(getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED, providers);
- if (Config.LOGV) {
- Log.v("Location Accuracy", "Setting LOCATION_PROVIDERS_ALLOWED = " + providers);
- }
- // Inform the location manager about the changes
- mLocationManager.updateProviders();
- }
-
- /**
- * @return string containing a list of providers that have been enabled for use
- */
- private String getAllowedProviders() {
- String allowedProviders =
- Settings.Secure.getString(getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
- if (allowedProviders == null) {
- allowedProviders = "";
- }
- return allowedProviders;
+ ContentResolver res = getContentResolver();
+ mNetwork.setChecked(Settings.Secure.isLocationProviderEnabled(
+ res, LocationManager.NETWORK_PROVIDER));
+ mGps.setChecked(Settings.Secure.isLocationProviderEnabled(
+ res, LocationManager.GPS_PROVIDER));
+ mUseLocation.setChecked(Settings.Secure.getInt(res,
+ Settings.Secure.USE_LOCATION_FOR_SERVICES, 2) == 1);
}
private boolean isToggled(Preference pref) {
return ((CheckBoxPreference) pref).isChecked();
}
+ private void updateUseLocation() {
+ boolean use = mUseLocation.isChecked();
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.USE_LOCATION_FOR_SERVICES, use ? 1 : 0);
+ }
+
/**
* For the user to disable keyguard, we first make them verify their
@@ -311,15 +391,546 @@
* @see #confirmPatternThenDisableAndClear
*/
@Override
- protected void onActivityResult(int requestCode, int resultCode,
- Intent data) {
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
final boolean resultOk = resultCode == Activity.RESULT_OK;
- if ((requestCode == CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE) && resultOk) {
+ if ((requestCode == CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE)
+ && resultOk) {
mLockPatternUtils.setLockPatternEnabled(false);
mLockPatternUtils.saveLockPattern(null);
}
}
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ //updateProviders();
+ mOkClicked = true;
+ } else {
+ // Reset the toggle
+ mUseLocation.setChecked(false);
+ }
+ updateUseLocation();
+ }
+
+ public void onDismiss(DialogInterface dialog) {
+ // Assuming that onClick gets called first
+ if (!mOkClicked) {
+ mUseLocation.setChecked(false);
+ }
+ }
+
+ @Override
+ protected Dialog onCreateDialog (int id) {
+ switch (id) {
+ case CSTOR_INIT_DIALOG:
+ case CSTOR_CHANGE_PASSWORD_DIALOG:
+ return mCstorHelper.createSetPasswordDialog(id);
+
+ case CSTOR_UNLOCK_DIALOG:
+ return mCstorHelper.createUnlockDialog();
+
+ case CSTOR_RESET_DIALOG:
+ return mCstorHelper.createResetDialog();
+
+ case CSTOR_NAME_CREDENTIAL_DIALOG:
+ return mCstorHelper.createNameCredentialDialog();
+
+ default:
+ return null;
+ }
+ }
+
+ private class CstorHelper implements
+ DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+ private Keystore mKeystore = Keystore.getInstance();
+ private View mView;
+ private int mDialogId;
+ private boolean mConfirm = true;
+
+ private CheckBoxPreference mAccessCheckBox;
+ private Preference mResetButton;
+
+ private Intent mSpecialIntent;
+ private CstorAddCredentialHelper mCstorAddCredentialHelper;
+
+ void handleCstorIntents(Intent intent) {
+ if (intent == null) return;
+ String action = intent.getAction();
+
+ if (ACTION_ADD_CREDENTIAL.equals(action)) {
+ mCstorAddCredentialHelper = new CstorAddCredentialHelper(intent);
+ showDialog(CSTOR_NAME_CREDENTIAL_DIALOG);
+ } else if (ACTION_UNLOCK_CREDENTIAL_STORAGE.equals(action)) {
+ mSpecialIntent = intent;
+ showDialog(mCstorHelper.isCstorInitialized()
+ ? CSTOR_UNLOCK_DIALOG
+ : CSTOR_INIT_DIALOG);
+ }
+ }
+
+ private boolean isCstorUnlocked() {
+ return (mKeystore.getState() == Keystore.UNLOCKED);
+ }
+
+ private boolean isCstorInitialized() {
+ return (mKeystore.getState() != Keystore.UNINITIALIZED);
+ }
+
+ private void lockCstor() {
+ mKeystore.lock();
+ mAccessCheckBox.setChecked(false);
+ }
+
+ private int unlockCstor(String passwd) {
+ int ret = mKeystore.unlock(passwd);
+ if (ret == -1) resetCstor();
+ if (ret == 0) {
+ Toast.makeText(SecuritySettings.this, R.string.cstor_is_enabled,
+ Toast.LENGTH_SHORT).show();
+ }
+ return ret;
+ }
+
+ private int changeCstorPassword(String oldPasswd, String newPasswd) {
+ int ret = mKeystore.changePassword(oldPasswd, newPasswd);
+ if (ret == -1) resetCstor();
+ return ret;
+ }
+
+ private void initCstor(String passwd) {
+ mKeystore.setPassword(passwd);
+ enablePreferences(true);
+ mAccessCheckBox.setChecked(true);
+ Toast.makeText(SecuritySettings.this, R.string.cstor_is_enabled,
+ Toast.LENGTH_SHORT).show();
+ }
+
+ private void resetCstor() {
+ mKeystore.reset();
+ enablePreferences(false);
+ 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 onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_NEGATIVE) {
+ if (mCstorAddCredentialHelper != null) finish();
+ return;
+ }
+
+ switch (mDialogId) {
+ case CSTOR_INIT_DIALOG:
+ case CSTOR_CHANGE_PASSWORD_DIALOG:
+ mConfirm = checkPasswords((Dialog) dialog);
+ break;
+
+ case CSTOR_UNLOCK_DIALOG:
+ mConfirm = checkUnlockPassword((Dialog) dialog);
+ break;
+
+ case CSTOR_RESET_DIALOG:
+ resetCstor();
+ break;
+
+ case CSTOR_NAME_CREDENTIAL_DIALOG:
+ mConfirm = checkAddCredential();
+ break;
+ }
+ }
+
+ public void onDismiss(DialogInterface dialog) {
+ if (!mConfirm) {
+ mConfirm = true;
+ showDialog(mDialogId);
+ } else {
+ removeDialog(mDialogId);
+
+ if (mCstorAddCredentialHelper != null) {
+ if (!isCstorInitialized()) {
+ showDialog(CSTOR_INIT_DIALOG);
+ } else if (!isCstorUnlocked()) {
+ showDialog(CSTOR_UNLOCK_DIALOG);
+ } else {
+ addCredential();
+ finish();
+ }
+ } else if (mSpecialIntent != null) {
+ finish();
+ }
+ }
+ }
+
+ private void showResetWarning(int count) {
+ TextView v = showError(count <= 3
+ ? R.string.cstor_password_error_reset_warning
+ : R.string.cstor_password_error);
+ if (count <= 3) {
+ if (count == 1) {
+ v.setText(R.string.cstor_password_error_reset_warning);
+ } else {
+ String format = getString(
+ R.string.cstor_password_error_reset_warning_plural);
+ v.setText(String.format(format, count));
+ }
+ }
+ }
+
+ private boolean checkAddCredential() {
+ hideError();
+
+ String name = getText(R.id.cstor_credential_name);
+ if (TextUtils.isEmpty(name)) {
+ showError(R.string.cstor_name_empty_error);
+ return false;
+ }
+
+ for (int i = 0, len = name.length(); i < len; i++) {
+ if (!Character.isLetterOrDigit(name.charAt(i))) {
+ showError(R.string.cstor_name_char_error);
+ return false;
+ }
+ }
+
+ mCstorAddCredentialHelper.setName(name);
+ return true;
+ }
+
+ // returns true if the password is long enough and does not contain
+ // characters that we don't like
+ private boolean verifyPassword(String passwd) {
+ if (passwd == null) {
+ showError(R.string.cstor_passwords_empty_error);
+ return false;
+ } else if ((passwd.length() < CSTOR_MIN_PASSWORD_LENGTH)
+ || passwd.contains(" ")) {
+ showError(R.string.cstor_password_verification_error);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ // returns true if the password is ok
+ private boolean checkUnlockPassword(Dialog d) {
+ hideError();
+
+ String passwd = getText(R.id.cstor_password);
+ if (TextUtils.isEmpty(passwd)) {
+ showError(R.string.cstor_password_empty_error);
+ return false;
+ }
+
+ int count = unlockCstor(passwd);
+ if (count > 0) {
+ showResetWarning(count);
+ return false;
+ } else {
+ // done or reset
+ return true;
+ }
+ }
+
+ // returns true if the passwords are ok
+ private boolean checkPasswords(Dialog d) {
+ hideError();
+
+ String oldPasswd = getText(R.id.cstor_old_password);
+ String newPasswd = getText(R.id.cstor_new_password);
+ String confirmPasswd = getText(R.id.cstor_confirm_password);
+
+ if ((mDialogId == CSTOR_CHANGE_PASSWORD_DIALOG)
+ && TextUtils.isEmpty(oldPasswd)) {
+ showError(R.string.cstor_password_empty_error);
+ return false;
+ }
+
+ if (TextUtils.isEmpty(newPasswd)
+ && TextUtils.isEmpty(confirmPasswd)) {
+ showError(R.string.cstor_passwords_empty_error);
+ return false;
+ }
+
+ if (!verifyPassword(newPasswd)) {
+ return false;
+ } else if (!newPasswd.equals(confirmPasswd)) {
+ showError(R.string.cstor_passwords_error);
+ return false;
+ }
+
+ if (mDialogId == CSTOR_CHANGE_PASSWORD_DIALOG) {
+ int count = changeCstorPassword(oldPasswd, newPasswd);
+ if (count > 0) {
+ showResetWarning(count);
+ return false;
+ } else {
+ // done or reset
+ return true;
+ }
+ } else {
+ initCstor(newPasswd);
+ return true;
+ }
+ }
+
+ private TextView showError(int messageId) {
+ TextView v = (TextView) mView.findViewById(R.id.cstor_error);
+ v.setText(messageId);
+ if (v != null) v.setVisibility(View.VISIBLE);
+ return v;
+ }
+
+ private void hide(int viewId) {
+ View v = mView.findViewById(viewId);
+ if (v != null) v.setVisibility(View.GONE);
+ }
+
+ private void hideError() {
+ hide(R.id.cstor_error);
+ }
+
+ private String getText(int viewId) {
+ return ((TextView) mView.findViewById(viewId)).getText().toString();
+ }
+
+ private void setText(int viewId, String text) {
+ TextView v = (TextView) mView.findViewById(viewId);
+ if (v != null) v.setText(text);
+ }
+
+ private void setText(int viewId, int textId) {
+ TextView v = (TextView) mView.findViewById(viewId);
+ if (v != null) v.setText(textId);
+ }
+
+ private void enablePreferences(boolean enabled) {
+ mAccessCheckBox.setEnabled(enabled);
+ mResetButton.setEnabled(enabled);
+ }
+
+ private Preference createAccessCheckBox() {
+ CheckBoxPreference pref = new CheckBoxPreference(
+ SecuritySettings.this);
+ pref.setTitle(R.string.cstor_access_title);
+ pref.setSummary(R.string.cstor_access_summary);
+ pref.setChecked(isCstorUnlocked());
+ pref.setOnPreferenceChangeListener(
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object value) {
+ if (((Boolean) value)) {
+ showDialog(isCstorInitialized()
+ ? CSTOR_UNLOCK_DIALOG
+ : CSTOR_INIT_DIALOG);
+ } else {
+ lockCstor();
+ }
+ return true;
+ }
+ });
+ pref.setEnabled(isCstorInitialized());
+ mAccessCheckBox = pref;
+ return pref;
+ }
+
+ private Preference createSetPasswordPreference() {
+ Preference pref = new Preference(SecuritySettings.this);
+ pref.setTitle(R.string.cstor_set_passwd_title);
+ pref.setSummary(R.string.cstor_set_passwd_summary);
+ pref.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference pref) {
+ showDialog(isCstorInitialized()
+ ? CSTOR_CHANGE_PASSWORD_DIALOG
+ : CSTOR_INIT_DIALOG);
+ return true;
+ }
+ });
+ return pref;
+ }
+
+ private Preference createResetPreference() {
+ Preference pref = new Preference(SecuritySettings.this);
+ pref.setTitle(R.string.cstor_reset_title);
+ pref.setSummary(R.string.cstor_reset_summary);
+ pref.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference pref) {
+ showDialog(CSTOR_RESET_DIALOG);
+ return true;
+ }
+ });
+ pref.setEnabled(isCstorInitialized());
+ mResetButton = pref;
+ return pref;
+ }
+
+ private Dialog createUnlockDialog() {
+ mDialogId = CSTOR_UNLOCK_DIALOG;
+ mView = View.inflate(SecuritySettings.this,
+ R.layout.cstor_unlock_dialog_view, null);
+ hideError();
+
+ // show extra hint only when the action comes from outside
+ if ((mSpecialIntent == null)
+ && (mCstorAddCredentialHelper == null)) {
+ hide(R.id.cstor_access_dialog_hint_from_action);
+ }
+
+ Dialog d = new AlertDialog.Builder(SecuritySettings.this)
+ .setView(mView)
+ .setTitle(R.string.cstor_access_dialog_title)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .setCancelable(false)
+ .create();
+ d.setOnDismissListener(this);
+ return d;
+ }
+
+ private Dialog createSetPasswordDialog(int id) {
+ mDialogId = id;
+ mView = View.inflate(SecuritySettings.this,
+ R.layout.cstor_set_password_dialog_view, null);
+ hideError();
+
+ // show extra hint only when the action comes from outside
+ if ((mSpecialIntent != null)
+ || (mCstorAddCredentialHelper != null)) {
+ setText(R.id.cstor_first_time_hint,
+ R.string.cstor_first_time_hint_from_action);
+ }
+
+ switch (id) {
+ case CSTOR_INIT_DIALOG:
+ mView.findViewById(R.id.cstor_old_password_block)
+ .setVisibility(View.GONE);
+ break;
+
+ case CSTOR_CHANGE_PASSWORD_DIALOG:
+ mView.findViewById(R.id.cstor_first_time_hint)
+ .setVisibility(View.GONE);
+ break;
+
+ default:
+ throw new RuntimeException(
+ "Unknown dialog id: " + mDialogId);
+ }
+
+ Dialog d = new AlertDialog.Builder(SecuritySettings.this)
+ .setView(mView)
+ .setTitle(R.string.cstor_set_passwd_dialog_title)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .setCancelable(false)
+ .create();
+ d.setOnDismissListener(this);
+ return d;
+ }
+
+ private Dialog createResetDialog() {
+ mDialogId = CSTOR_RESET_DIALOG;
+ return new AlertDialog.Builder(SecuritySettings.this)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.cstor_reset_hint)
+ .setPositiveButton(getString(android.R.string.ok), this)
+ .setNegativeButton(getString(android.R.string.cancel), this)
+ .create();
+ }
+
+ private Dialog createNameCredentialDialog() {
+ mDialogId = CSTOR_NAME_CREDENTIAL_DIALOG;
+ mView = View.inflate(SecuritySettings.this,
+ R.layout.cstor_name_credential_dialog_view, null);
+ hideError();
+
+ setText(R.id.cstor_credential_name_title,
+ R.string.cstor_credential_name);
+ setText(R.id.cstor_credential_info_title,
+ R.string.cstor_credential_info);
+ setText(R.id.cstor_credential_info,
+ mCstorAddCredentialHelper.getDescription().toString());
+
+ Dialog d = new AlertDialog.Builder(SecuritySettings.this)
+ .setView(mView)
+ .setTitle(R.string.cstor_name_credential_dialog_title)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .setCancelable(false)
+ .create();
+ d.setOnDismissListener(this);
+ return d;
+ }
+ }
+
+ private class CstorAddCredentialHelper {
+ private String mTypeName;
+ private List<byte[]> mItemList;
+ private List<String> mNamespaceList;
+ private String mDescription;
+ private String mName;
+
+ CstorAddCredentialHelper(Intent intent) {
+ parse(intent);
+ }
+
+ String getTypeName() {
+ return mTypeName;
+ }
+
+ CharSequence getDescription() {
+ return Html.fromHtml(mDescription);
+ }
+
+ void setName(String name) {
+ mName = name;
+ }
+
+ String getName() {
+ return mName;
+ }
+
+ 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;
+ }
+ return 0;
+ }
+
+ private void parse(Intent intent) {
+ mTypeName = intent.getStringExtra(KEY_CSTOR_TYPE_NAME);
+ mItemList = new ArrayList<byte[]>();
+ mNamespaceList = new ArrayList<String>();
+ for (int i = 0; ; i++) {
+ byte[] blob = intent.getByteArrayExtra(KEY_CSTOR_ITEM + i);
+ if (blob == null) break;
+ mItemList.add(blob);
+ mNamespaceList.add(intent.getStringExtra(
+ KEY_CSTOR_NAMESPACE + i));
+ }
+
+ // build description string
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; ; i++) {
+ String s = intent.getStringExtra(KEY_CSTOR_DESCRIPTION + i);
+ if (s == null) break;
+ sb.append(s).append("<br>");
+ }
+ mDescription = sb.toString();
+ }
+ }
}
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 0c4545e..4f888ff 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -26,6 +26,7 @@
private static final String KEY_PARENT = "parent";
private static final String KEY_CALL_SETTINGS = "call_settings";
private static final String KEY_SYNC_SETTINGS = "sync_settings";
+ private static final String KEY_SEARCH_SETTINGS = "search_settings";
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -35,6 +36,7 @@
PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
Utils.updatePreferenceToSpecificActivityOrRemove(this, parent, KEY_SYNC_SETTINGS, 0);
+ Utils.updatePreferenceToSpecificActivityOrRemove(this, parent, KEY_SEARCH_SETTINGS, 0);
}
@Override
diff --git a/src/com/android/settings/SoundAndDisplaySettings.java b/src/com/android/settings/SoundAndDisplaySettings.java
index e8cb10f..8e7411c 100644
--- a/src/com/android/settings/SoundAndDisplaySettings.java
+++ b/src/com/android/settings/SoundAndDisplaySettings.java
@@ -17,6 +17,7 @@
package com.android.settings;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.provider.Settings.System.COMPATIBILITY_MODE;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -36,6 +37,7 @@
import android.provider.Settings;
import android.util.Log;
import android.view.IWindowManager;
+import android.telephony.TelephonyManager;
public class SoundAndDisplaySettings extends PreferenceActivity implements
Preference.OnPreferenceChangeListener {
@@ -43,6 +45,7 @@
/** If there is no setting in the provider, use this. */
private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000;
+ private static final int FALLBACK_EMERGENCY_TONE_VALUE = 0;
private static final String KEY_SILENT = "silent";
private static final String KEY_VIBRATE = "vibrate";
@@ -52,6 +55,8 @@
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;
@@ -71,6 +76,7 @@
private CheckBoxPreference mSoundEffects;
private CheckBoxPreference mAnimations;
private CheckBoxPreference mAccelerometer;
+ private CheckBoxPreference mCompatibilityMode;
private float[] mAnimationScales;
private AudioManager mAudioManager;
@@ -88,6 +94,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ContentResolver resolver = getContentResolver();
+ int activePhoneType = TelephonyManager.getDefault().getPhoneType();
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
@@ -96,6 +103,11 @@
addPreferencesFromResource(R.xml.sound_and_display_settings);
+ if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType) {
+ // device is not CDMA, do not display CDMA emergency_tone
+ getPreferenceScreen().removePreference(findPreference(KEY_EMERGENCY_TONE));
+ }
+
mSilent = (CheckBoxPreference) findPreference(KEY_SILENT);
mPlayMediaNotificationSounds = (CheckBoxPreference) findPreference(KEY_PLAY_MEDIA_NOTIFICATION_SOUNDS);
@@ -112,12 +124,24 @@
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);
screenTimeoutPreference.setValue(String.valueOf(Settings.System.getInt(
resolver, SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE)));
screenTimeoutPreference.setOnPreferenceChangeListener(this);
+
+ if (TelephonyManager.PHONE_TYPE_CDMA == activePhoneType) {
+ ListPreference emergencyTonePreference =
+ (ListPreference) findPreference(KEY_EMERGENCY_TONE);
+ emergencyTonePreference.setValue(String.valueOf(Settings.System.getInt(
+ resolver, Settings.System.EMERGENCY_TONE, FALLBACK_EMERGENCY_TONE_VALUE)));
+ emergencyTonePreference.setOnPreferenceChangeListener(this);
+ }
}
@Override
@@ -192,33 +216,29 @@
Settings.System.ACCELEROMETER_ROTATION, 0) != 0);
}
+ private void setRingerMode(boolean silent, boolean vibrate) {
+ if (silent) {
+ mAudioManager.setRingerMode(vibrate ? AudioManager.RINGER_MODE_VIBRATE :
+ AudioManager.RINGER_MODE_SILENT);
+ } else {
+ mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+ mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
+ vibrate ? AudioManager.VIBRATE_SETTING_ON
+ : AudioManager.VIBRATE_SETTING_OFF);
+ }
+ }
+
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
- if (preference == mSilent) {
- final boolean silent = mSilent.isChecked();
- mAudioManager.setRingerMode(silent ? AudioManager.RINGER_MODE_SILENT
- : AudioManager.RINGER_MODE_NORMAL);
- updateState(false);
-
+ if (preference == mSilent || preference == mVibrate) {
+ setRingerMode(mSilent.isChecked(), mVibrate.isChecked());
+ if (preference == mSilent) updateState(false);
} else if (preference == mPlayMediaNotificationSounds) {
try {
mMountService.setPlayNotificationSounds(mPlayMediaNotificationSounds.isChecked());
} catch (RemoteException e) {
}
- } else if (preference == mVibrate) {
- final boolean vibrate = mVibrate.isChecked();
- final boolean silent = mSilent.isChecked();
-
- if (silent) {
- mAudioManager.setRingerMode(vibrate ? AudioManager.RINGER_MODE_VIBRATE :
- AudioManager.RINGER_MODE_SILENT);
- } else {
- mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
- vibrate ? AudioManager.VIBRATE_SETTING_ON
- : AudioManager.VIBRATE_SETTING_OFF);
- }
-
} else if (preference == mDtmfTone) {
Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING,
mDtmfTone.isChecked() ? 1 : 0);
@@ -249,6 +269,10 @@
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;
}
@@ -262,6 +286,14 @@
} catch (NumberFormatException e) {
Log.e(TAG, "could not persist screen timeout setting", e);
}
+ } else if (KEY_EMERGENCY_TONE.equals(preference.getKey())) {
+ int value = Integer.parseInt((String) objValue);
+ try {
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.EMERGENCY_TONE, value);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "could not persist emergency tone setting", e);
+ }
}
return true;
diff --git a/src/com/android/settings/TextToSpeechSettings.java b/src/com/android/settings/TextToSpeechSettings.java
new file mode 100644
index 0000000..88bfc67
--- /dev/null
+++ b/src/com/android/settings/TextToSpeechSettings.java
@@ -0,0 +1,398 @@
+/*
+ * 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.
+ */
+
+package com.android.settings;
+
+import static android.provider.Settings.Secure.TTS_USE_DEFAULTS;
+import static android.provider.Settings.Secure.TTS_DEFAULT_RATE;
+import static android.provider.Settings.Secure.TTS_DEFAULT_LANG;
+import static android.provider.Settings.Secure.TTS_DEFAULT_COUNTRY;
+import static android.provider.Settings.Secure.TTS_DEFAULT_VARIANT;
+import static android.provider.Settings.Secure.TTS_DEFAULT_SYNTH;
+
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.CheckBoxPreference;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+public class TextToSpeechSettings extends PreferenceActivity implements
+ Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
+ TextToSpeech.OnInitListener {
+
+ private static final String TAG = "TextToSpeechSettings";
+
+ private static final String KEY_TTS_PLAY_EXAMPLE = "tts_play_example";
+ private static final String KEY_TTS_INSTALL_DATA = "tts_install_data";
+ private static final String KEY_TTS_USE_DEFAULT = "toggle_use_default_tts_settings";
+ private static final String KEY_TTS_DEFAULT_RATE = "tts_default_rate";
+ private static final String KEY_TTS_DEFAULT_LANG = "tts_default_lang";
+ private static final String KEY_TTS_DEFAULT_COUNTRY = "tts_default_country";
+ private static final String KEY_TTS_DEFAULT_VARIANT = "tts_default_variant";
+
+ 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 Preference mPlayExample = null;
+ private Preference mInstallData = null;
+ private CheckBoxPreference mUseDefaultPref = null;
+ private ListPreference mDefaultRatePref = null;
+ private ListPreference mDefaultLocPref = null;
+ private String mDefaultLanguage = null;
+ private String mDefaultCountry = null;
+ private String mDefaultLocVariant = null;
+ private String mDefaultEng = "";
+
+ private boolean mEnableDemo = false;
+
+ private TextToSpeech mTts = null;
+
+ /**
+ * Request code (arbitrary value) for voice data check through
+ * startActivityForResult.
+ */
+ private static final int VOICE_DATA_INTEGRITY_CHECK = 1977;
+ /**
+ * Request code (arbitrary value) for voice data installation through
+ * startActivityForResult.
+ */
+ private static final int VOICE_DATA_INSTALLATION = 1980;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.tts_settings);
+
+ mEnableDemo = false;
+ initClickers();
+ initDefaultSettings();
+ }
+
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ // whenever we return to this screen, we don't know the state of the
+ // system, so we have to recheck that we can play the demo, or it must be disabled.
+ // TODO make the TTS service listen to "changes in the system", i.e. sd card un/mount
+ initClickers();
+ updateWidgetState();
+ checkVoiceData();
+ }
+
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mTts != null) {
+ mTts.shutdown();
+ }
+ }
+
+
+ private void initClickers() {
+ mPlayExample = findPreference(KEY_TTS_PLAY_EXAMPLE);
+ mPlayExample.setOnPreferenceClickListener(this);
+
+ mInstallData = findPreference(KEY_TTS_INSTALL_DATA);
+ mInstallData.setOnPreferenceClickListener(this);
+ }
+
+
+ private void initDefaultSettings() {
+ ContentResolver resolver = getContentResolver();
+ int intVal = 0;
+
+ // Find the default TTS values in the settings, initialize and store the
+ // settings if they are not found.
+
+ // "Use Defaults"
+ mUseDefaultPref = (CheckBoxPreference) findPreference(KEY_TTS_USE_DEFAULT);
+ try {
+ intVal = Settings.Secure.getInt(resolver, TTS_USE_DEFAULTS);
+ } catch (SettingNotFoundException e) {
+ // "use default" setting not found, initialize it
+ intVal = TextToSpeech.Engine.FALLBACK_TTS_USE_DEFAULTS;
+ Settings.Secure.putInt(resolver, TTS_USE_DEFAULTS, intVal);
+ }
+ mUseDefaultPref.setChecked(intVal == 1);
+ mUseDefaultPref.setOnPreferenceChangeListener(this);
+
+ // Default engine
+ String engine = Settings.Secure.getString(resolver, TTS_DEFAULT_SYNTH);
+ if (engine == null) {
+ // TODO move FALLBACK_TTS_DEFAULT_SYNTH to TextToSpeech
+ engine = FALLBACK_TTS_DEFAULT_SYNTH;
+ Settings.Secure.putString(resolver, TTS_DEFAULT_SYNTH, engine);
+ }
+ mDefaultEng = engine;
+
+ // Default rate
+ mDefaultRatePref = (ListPreference) findPreference(KEY_TTS_DEFAULT_RATE);
+ try {
+ intVal = Settings.Secure.getInt(resolver, TTS_DEFAULT_RATE);
+ } catch (SettingNotFoundException e) {
+ // default rate setting not found, initialize it
+ intVal = TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_RATE;
+ Settings.Secure.putInt(resolver, TTS_DEFAULT_RATE, intVal);
+ }
+ mDefaultRatePref.setValue(String.valueOf(intVal));
+ mDefaultRatePref.setOnPreferenceChangeListener(this);
+
+ // Default language / country / variant : these three values map to a single ListPref
+ // representing the matching Locale
+ String language = null;
+ String country = null;
+ String variant = null;
+ mDefaultLocPref = (ListPreference) findPreference(KEY_TTS_DEFAULT_LANG);
+ language = Settings.Secure.getString(resolver, TTS_DEFAULT_LANG);
+ if (language == null) {
+ // the default language property isn't set, use that of the current locale
+ Locale currentLocale = Locale.getDefault();
+ language = currentLocale.getISO3Language();
+ country = currentLocale.getISO3Country();
+ variant = currentLocale.getVariant();
+ Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, language);
+ Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, country);
+ Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, variant);
+ }
+ mDefaultLanguage = language;
+ if (country == null) {
+ // country wasn't initialized yet because a default language was found
+ country = Settings.Secure.getString(resolver, KEY_TTS_DEFAULT_COUNTRY);
+ if (country == null) {
+ // default country setting not found, initialize it, as well as the variant;
+ Locale currentLocale = Locale.getDefault();
+ country = currentLocale.getISO3Country();
+ variant = currentLocale.getVariant();
+ Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, country);
+ Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, variant);
+ }
+ }
+ mDefaultCountry = country;
+ if (variant == null) {
+ // variant wasn't initialized yet because a default country was found
+ variant = Settings.Secure.getString(resolver, KEY_TTS_DEFAULT_VARIANT);
+ if (variant == null) {
+ // default variant setting not found, initialize it
+ Locale currentLocale = Locale.getDefault();
+ variant = currentLocale.getVariant();
+ Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, variant);
+ }
+ }
+ mDefaultLocVariant = variant;
+
+ setDefaultLocalePref(language, country, variant);
+ mDefaultLocPref.setOnPreferenceChangeListener(this);
+ }
+
+
+ /**
+ * Ask the current default engine to launch the matching CHECK_TTS_DATA activity
+ * to check the required TTS files are properly installed.
+ */
+ private void checkVoiceData() {
+ PackageManager pm = getPackageManager();
+ Intent intent = new Intent();
+ intent.setAction("android.intent.action.CHECK_TTS_DATA");
+ List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
+ // query only the package that matches that of the default engine
+ for (int i = 0; i < resolveInfos.size(); i++) {
+ ActivityInfo currentActivityInfo = resolveInfos.get(i).activityInfo;
+ if (mDefaultEng.equals(currentActivityInfo.packageName)) {
+ intent.setClassName(mDefaultEng, currentActivityInfo.name);
+ this.startActivityForResult(intent, VOICE_DATA_INTEGRITY_CHECK);
+ }
+ }
+ }
+
+
+ /**
+ * Ask the current default engine to launch the matching INSTALL_TTS_DATA activity
+ * so the required TTS files are properly installed.
+ */
+ private void installVoiceData() {
+ PackageManager pm = getPackageManager();
+ Intent intent = new Intent();
+ intent.setAction("android.intent.action.INSTALL_TTS_DATA");
+ List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
+ // query only the package that matches that of the default engine
+ for (int i = 0; i < resolveInfos.size(); i++) {
+ ActivityInfo currentActivityInfo = resolveInfos.get(i).activityInfo;
+ if (mDefaultEng.equals(currentActivityInfo.packageName)) {
+ intent.setClassName(mDefaultEng, currentActivityInfo.name);
+ this.startActivityForResult(intent, VOICE_DATA_INSTALLATION);
+ }
+ }
+ }
+
+
+ /**
+ * Called when the TTS engine is initialized.
+ */
+ public void onInit(int status) {
+ if (status == TextToSpeech.TTS_SUCCESS) {
+ Log.v(TAG, "TTS engine for settings screen initialized.");
+ mEnableDemo = true;
+ } else {
+ Log.v(TAG, "TTS engine for settings screen failed to initialize successfully.");
+ mEnableDemo = false;
+ }
+ updateWidgetState();
+ }
+
+
+ /**
+ * Called when voice data integrity check returns
+ */
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == VOICE_DATA_INTEGRITY_CHECK) {
+ if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
+ Log.v(TAG, "Voice data check passed");
+ if (mTts == null) {
+ mTts = new TextToSpeech(this, this);
+ }
+ } else {
+ Log.v(TAG, "Voice data check failed");
+ mEnableDemo = false;
+ updateWidgetState();
+ }
+ }
+ }
+
+
+ public boolean onPreferenceChange(Preference preference, Object objValue) {
+ if (KEY_TTS_USE_DEFAULT.equals(preference.getKey())) {
+ // "Use Defaults"
+ int value = (Boolean)objValue ? 1 : 0;
+ Settings.Secure.putInt(getContentResolver(), TTS_USE_DEFAULTS,
+ value);
+ Log.i(TAG, "TTS use default settings is "+objValue.toString());
+ } else if (KEY_TTS_DEFAULT_RATE.equals(preference.getKey())) {
+ // Default rate
+ int value = Integer.parseInt((String) objValue);
+ try {
+ Settings.Secure.putInt(getContentResolver(),
+ TTS_DEFAULT_RATE, value);
+ if (mTts != null) {
+ mTts.setSpeechRate((float)(value/100.0f));
+ }
+ Log.i(TAG, "TTS default rate is "+value);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "could not persist default TTS rate setting", e);
+ }
+ } else if (KEY_TTS_DEFAULT_LANG.equals(preference.getKey())) {
+ // Default locale
+ ContentResolver resolver = getContentResolver();
+ parseLocaleInfo((String) objValue);
+ Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, mDefaultLanguage);
+ Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, mDefaultCountry);
+ Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, mDefaultLocVariant);
+ Log.v(TAG, "TTS default lang/country/variant set to "
+ + mDefaultLanguage + "/" + mDefaultCountry + "/" + mDefaultLocVariant);
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Called when mPlayExample or mInstallData is clicked
+ */
+ public boolean onPreferenceClick(Preference preference) {
+ if (preference == mPlayExample) {
+ // Play example
+ if (mTts != null) {
+ mTts.speak(getResources().getString(R.string.tts_demo),
+ TextToSpeech.TTS_QUEUE_FLUSH, null);
+ }
+ return true;
+ }
+ if (preference == mInstallData) {
+ installVoiceData();
+ // quit this activity so it needs to be restarted after installation of the voice data
+ finish();
+ return true;
+ }
+ return false;
+ }
+
+
+ private void updateWidgetState() {
+ mPlayExample.setEnabled(mEnableDemo);
+ mUseDefaultPref.setEnabled(mEnableDemo);
+ mDefaultRatePref.setEnabled(mEnableDemo);
+ mDefaultLocPref.setEnabled(mEnableDemo);
+
+ mInstallData.setEnabled(!mEnableDemo);
+ }
+
+
+ private void parseLocaleInfo(String locale) {
+ StringTokenizer tokenizer = new StringTokenizer(locale, LOCALE_DELIMITER);
+ mDefaultLanguage = "";
+ mDefaultCountry = "";
+ mDefaultLocVariant = "";
+ if (tokenizer.hasMoreTokens()) {
+ mDefaultLanguage = tokenizer.nextToken().trim();
+ }
+ if (tokenizer.hasMoreTokens()) {
+ mDefaultCountry = tokenizer.nextToken().trim();
+ }
+ if (tokenizer.hasMoreTokens()) {
+ mDefaultLocVariant = tokenizer.nextToken().trim();
+ }
+ }
+
+
+ private void setDefaultLocalePref(String language, String country, String variant) {
+ // build a string from the default lang/country/variant trio,
+ String localeString = new String(language);
+ if (country.compareTo("") != 0) {
+ localeString += LOCALE_DELIMITER + country;
+ } else {
+ localeString += LOCALE_DELIMITER + " ";
+ }
+ if (variant.compareTo("") != 0) {
+ localeString += LOCALE_DELIMITER + variant;
+ }
+
+ if (mDefaultLocPref.findIndexOfValue(localeString) > -1) {
+ mDefaultLocPref.setValue(localeString);
+ } else {
+ mDefaultLocPref.setValueIndex(0);
+ }
+
+ Log.v(TAG, "In initDefaultSettings: localeString=" + localeString);
+ }
+
+}
diff --git a/src/com/android/settings/battery_history/BatteryHistory.java b/src/com/android/settings/battery_history/BatteryHistory.java
index ad6479a..06f38ae 100644
--- a/src/com/android/settings/battery_history/BatteryHistory.java
+++ b/src/com/android/settings/battery_history/BatteryHistory.java
@@ -607,8 +607,8 @@
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);
+ long totalTime = (timer.getTotalTimeLocked(uSecNow, mWhich) + 500) / 1000;
+ int count = timer.getCountLocked(mWhich);
if (handle == BatteryStats.Uid.Sensor.GPS) {
timeGps += totalTime;
countGps += count;
@@ -655,8 +655,8 @@
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);
+ time += (timer.getTotalTimeLocked(uSecNow, mWhich) + 500) / 1000;
+ count += timer.getCountLocked(mWhich);
}
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index f0a8189..7053ff5 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -104,6 +104,9 @@
protected void onBindView(View view) {
super.onBindView(view);
+ // Disable this view if the bluetooth enable/disable preference view is off
+ setDependency("bt_checkbox");
+
ImageView btClass = (ImageView) view.findViewById(R.id.btClass);
btClass.setImageResource(mLocalDevice.getBtClassDrawable());
btClass.setAlpha(isEnabled() ? 255 : sDimAlpha);
diff --git a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
index d458c5f..58fb569 100644
--- a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
@@ -30,7 +30,6 @@
import android.os.SystemProperties;
import android.preference.Preference;
import android.preference.CheckBoxPreference;
-import android.util.Log;
/**
* BluetoothDiscoverableEnabler is a helper to manage the "Discoverable"
@@ -39,7 +38,6 @@
*/
public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChangeListener {
private static final String TAG = "BluetoothDiscoverableEnabler";
- private static final boolean V = LocalBluetoothManager.V;
private static final String SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT =
"debug.bt.discoverable_time";
@@ -109,10 +107,6 @@
}
public boolean onPreferenceChange(Preference preference, Object value) {
- if (V) {
- Log.v(TAG, "Preference changed to " + value);
- }
-
// Turn on/off BT discoverability
setEnabled((Boolean) value);
@@ -155,10 +149,6 @@
}
private void handleModeChanged(int mode) {
- if (V) {
- Log.v(TAG, "Got mode changed: " + mode);
- }
-
if (mode == BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
mCheckBoxPreference.setChecked(true);
updateCountdownSummary();
diff --git a/src/com/android/settings/bluetooth/BluetoothEnabler.java b/src/com/android/settings/bluetooth/BluetoothEnabler.java
index 82961b8..af2722f 100644
--- a/src/com/android/settings/bluetooth/BluetoothEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothEnabler.java
@@ -19,6 +19,7 @@
import com.android.settings.R;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -48,7 +49,9 @@
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- handleStateChanged(mLocalManager.getBluetoothState());
+ int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE,
+ BluetoothError.ERROR);
+ handleStateChanged(state);
}
};
diff --git a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
index 71b91d3..af64c98 100644
--- a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
+++ b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
@@ -18,8 +18,8 @@
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothError;
+import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -27,6 +27,8 @@
import android.content.IntentFilter;
import android.util.Log;
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
+
/**
* BluetoothEventRedirector receives broadcasts and callbacks from the Bluetooth
* API and dispatches the event on the UI thread to the right class in the
@@ -89,9 +91,8 @@
Log.i(TAG, "Failed to connect BT headset");
}
- boolean transientState = !(newState == BluetoothHeadset.STATE_CONNECTED
- || newState == BluetoothHeadset.STATE_DISCONNECTED);
- mManager.getLocalDeviceManager().onProfileStateChanged(address,transientState);
+ mManager.getLocalDeviceManager().onProfileStateChanged(address,
+ Profile.HEADSET, newState);
} else if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
int newState = intent.getIntExtra(BluetoothA2dp.SINK_STATE, 0);
@@ -101,9 +102,8 @@
Log.i(TAG, "Failed to connect BT A2DP");
}
- boolean transientState = !(newState == BluetoothA2dp.STATE_CONNECTED
- || newState == BluetoothA2dp.STATE_DISCONNECTED);
- mManager.getLocalDeviceManager().onProfileStateChanged(address, transientState);
+ mManager.getLocalDeviceManager().onProfileStateChanged(address,
+ Profile.A2DP, newState);
} else if (action.equals(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION)) {
mManager.getLocalDeviceManager().onBtClassChanged(address);
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
index 86b1d69..5259d7b 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
@@ -16,9 +16,6 @@
package com.android.settings.bluetooth;
-import com.android.settings.R;
-import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
-
import android.app.AlertDialog;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
@@ -32,6 +29,9 @@
import android.view.Menu;
import android.view.MenuItem;
+import com.android.settings.R;
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
+
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -47,6 +47,8 @@
*/
public class LocalBluetoothDevice implements Comparable<LocalBluetoothDevice> {
private static final String TAG = "LocalBluetoothDevice";
+ private static final boolean D = LocalBluetoothManager.D;
+ private static final boolean V = LocalBluetoothManager.V;
private static final int CONTEXT_ITEM_CONNECT = Menu.FIRST + 1;
private static final int CONTEXT_ITEM_DISCONNECT = Menu.FIRST + 2;
@@ -124,18 +126,21 @@
private static LinkedList<BluetoothJob> workQueue = new LinkedList<BluetoothJob>();
private void queueCommand(BluetoothJob job) {
- Log.d(TAG, workQueue.toString());
+ if (D) {
+ Log.d(TAG, workQueue.toString());
+ }
synchronized (workQueue) {
boolean processNow = pruneQueue(job);
// Add job to queue
- Log.d(TAG, "Adding: " + job.toString());
+ if (D) {
+ Log.d(TAG, "Adding: " + job.toString());
+ }
workQueue.add(job);
// if there's nothing pending from before, send the command to bt
// framework immediately.
if (workQueue.size() == 1 || processNow) {
- Log.d(TAG, "workQueue.size() == 1 || TimeOut -> process command now");
// If the failed to process, just drop it from the queue.
// There will be no callback to remove this from the queue.
processCommands();
@@ -156,7 +161,9 @@
&& existingJob.command == BluetoothCommand.CONNECT
&& existingJob.device.mAddress.equals(job.device.mAddress)
&& existingJob.profile == job.profile) {
- Log.d(TAG, "Removed because of a pending disconnect. " + existingJob);
+ if (D) {
+ Log.d(TAG, "Removed because of a pending disconnect. " + existingJob);
+ }
it.remove();
continue;
}
@@ -165,7 +172,6 @@
// Defensive Code: Remove any job that older than a preset time.
// We never got a call back. It is better to have overlapping
// calls than to get stuck.
- Log.d(TAG, "Age:" + (now - existingJob.timeSent));
if (existingJob.timeSent != 0
&& (now - existingJob.timeSent) >= MAX_WAIT_TIME_FOR_FRAMEWORK) {
Log.w(TAG, "Timeout. Removing Job:" + existingJob.toString());
@@ -191,45 +197,59 @@
}
if (successful) {
- Log.d(TAG, "Command sent successfully:" + job.toString());
- } else {
- Log.d(TAG, "Framework rejected command immediately:" + job.toString());
+ if (D) {
+ Log.d(TAG, "Command sent successfully:" + job.toString());
+ }
+ } else if (V) {
+ Log.v(TAG, "Framework rejected command immediately:" + job.toString());
}
-
- } else {
+ } else if (D) {
Log.d(TAG, "Job already has a sent time. Skip. " + job.toString());
}
return successful;
}
- public void onProfileStateChanged() {
- Log.d(TAG, "onProfileStateChanged:" + workQueue.toString());
- BluetoothJob job = workQueue.peek();
- if (job == null) {
- Log.v(TAG, "Yikes, onProfileStateChanged called but job queue is empty. "
- + "(Okay for device initiated actions and BluetoothA2dpService initiated "
- + "Auto-connections)");
- return;
- } else if (job.device.mAddress != mAddress) {
- // This can happen in 2 cases: 1) BT device initiated pairing and
- // 2) disconnects of one headset that's triggered by connects of
- // another.
- Log.v(TAG, "onProfileStateChanged called. The addresses differ. this.mAddress="
- + mAddress + " workQueue.head=" + job.toString());
-
- // Check to see if we need to remove the stale items from the queue
- if (!pruneQueue(null)) {
- // nothing in the queue was modify. Just ignore the notification and return.
- return;
- }
- } else {
- // Remove the first item and process the next one
- Log.d(TAG, "LocalBluetoothDevice.onProfileStateChanged() called. MAC addr matched");
- workQueue.poll();
+ public void onProfileStateChanged(Profile profile, int newProfileState) {
+ if (D) {
+ Log.d(TAG, "onProfileStateChanged:" + workQueue.toString());
}
- processCommands();
+ int newState = LocalBluetoothProfileManager.getProfileManager(mLocalManager,
+ profile).convertState(newProfileState);
+
+ if (newState == SettingsBtStatus.CONNECTION_STATUS_CONNECTED) {
+ if (!mProfiles.contains(profile)) {
+ mProfiles.add(profile);
+ }
+ }
+
+ /* Ignore the transient states e.g. connecting, disconnecting */
+ if (newState == SettingsBtStatus.CONNECTION_STATUS_CONNECTED ||
+ newState == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) {
+ BluetoothJob job = workQueue.peek();
+ if (job == null) {
+ return;
+ } else if (job.device.mAddress != mAddress) {
+ // This can happen in 2 cases: 1) BT device initiated pairing and
+ // 2) disconnects of one headset that's triggered by connects of
+ // another.
+ if (D) {
+ Log.d(TAG, "mAddresses:" + mAddress + " != head:" + job.toString());
+ }
+
+ // Check to see if we need to remove the stale items from the queue
+ if (!pruneQueue(null)) {
+ // nothing in the queue was modify. Just ignore the notification and return.
+ return;
+ }
+ } else {
+ // Remove the first item and process the next one
+ workQueue.poll();
+ }
+
+ processCommands();
+ }
}
/*
@@ -240,7 +260,9 @@
* notification when it finishes processing a command
*/
private void processCommands() {
- Log.d(TAG, "processCommands:" + workQueue.toString());
+ if (D) {
+ Log.d(TAG, "processCommands:" + workQueue.toString());
+ }
Iterator<BluetoothJob> it = workQueue.iterator();
while (it.hasNext()) {
BluetoothJob job = it.next();
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java b/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java
index 9527980..2c70fd2 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java
@@ -21,6 +21,7 @@
import com.android.settings.R;
import com.android.settings.bluetooth.LocalBluetoothManager.Callback;
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import java.util.ArrayList;
import java.util.List;
@@ -181,19 +182,30 @@
* BluetoothDevice.UNBOND_REASON_*
*/
public synchronized void onBondingError(String address, int reason) {
- mLocalManager.showError(address, R.string.bluetooth_error_title,
- (reason == BluetoothDevice.UNBOND_REASON_AUTH_FAILED) ?
- R.string.bluetooth_pairing_pin_error_message :
- R.string.bluetooth_pairing_error_message);
+ int errorMsg;
+
+ switch(reason) {
+ case BluetoothDevice.UNBOND_REASON_AUTH_FAILED:
+ errorMsg = R.string.bluetooth_pairing_pin_error_message;
+ break;
+ case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED:
+ errorMsg = R.string.bluetooth_pairing_rejected_error_message;
+ break;
+ case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN:
+ errorMsg = R.string.bluetooth_pairing_device_down_error_message;
+ break;
+ default:
+ errorMsg = R.string.bluetooth_pairing_error_message;
+ }
+ mLocalManager.showError(address, R.string.bluetooth_error_title, errorMsg);
}
- public synchronized void onProfileStateChanged(String address, boolean transientState) {
+ public synchronized void onProfileStateChanged(String address, Profile profile,
+ int newProfileState) {
LocalBluetoothDevice device = findDevice(address);
if (device == null) return;
-
- if (!transientState) {
- device.onProfileStateChanged();
- }
+
+ device.onProfileStateChanged(profile, newProfileState);
device.refresh();
}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
index 1a848b2..2e84338 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
@@ -30,6 +30,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.util.Config;
import android.util.Log;
import android.widget.Toast;
@@ -40,7 +41,8 @@
*/
public class LocalBluetoothManager {
private static final String TAG = "LocalBluetoothManager";
- static final boolean V = true;
+ static final boolean V = Config.LOGV;
+ static final boolean D = Config.LOGD && false;
private static final String SHARED_PREFERENCES_NAME = "bluetooth_settings";
@@ -199,9 +201,17 @@
}
private void syncBluetoothState() {
- setBluetoothStateInt(mManager.isEnabled()
- ? BluetoothDevice.BLUETOOTH_STATE_ON
- : BluetoothDevice.BLUETOOTH_STATE_OFF);
+ int bluetoothState;
+
+ if (mManager != null) {
+ bluetoothState = mManager.isEnabled()
+ ? BluetoothDevice.BLUETOOTH_STATE_ON
+ : BluetoothDevice.BLUETOOTH_STATE_OFF;
+ } else {
+ bluetoothState = BluetoothError.ERROR;
+ }
+
+ setBluetoothStateInt(bluetoothState);
}
public void setBluetoothEnabled(boolean enabled) {
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
index 24563a7..b396732 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
@@ -16,17 +16,14 @@
package com.android.settings.bluetooth;
-import com.android.settings.R;
-
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothClass;
-import android.content.Context;
-import android.content.SharedPreferences;
import android.os.Handler;
import android.text.TextUtils;
+import com.android.settings.R;
+
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -102,6 +99,8 @@
public abstract int getSummary(String address);
+ public abstract int convertState(int a2dpState);
+
public abstract boolean isPreferred(String address);
public abstract void setPreferred(String address, boolean preferred);
@@ -176,7 +175,8 @@
preferred ? BluetoothA2dp.PRIORITY_AUTO : BluetoothA2dp.PRIORITY_OFF);
}
- private static int convertState(int a2dpState) {
+ @Override
+ public int convertState(int a2dpState) {
switch (a2dpState) {
case BluetoothA2dp.STATE_CONNECTED:
return SettingsBtStatus.CONNECTION_STATUS_CONNECTED;
@@ -217,7 +217,9 @@
*/
String address = mService.getHeadsetAddress();
if (TextUtils.isEmpty(address)) return;
- mLocalManager.getLocalDeviceManager().onProfileStateChanged(address, true);
+ mLocalManager.getLocalDeviceManager()
+ .onProfileStateChanged(address, Profile.HEADSET,
+ BluetoothHeadset.STATE_CONNECTED);
}
});
}
@@ -273,7 +275,8 @@
preferred ? BluetoothHeadset.PRIORITY_AUTO : BluetoothHeadset.PRIORITY_OFF);
}
- private static int convertState(int headsetState) {
+ @Override
+ public int convertState(int headsetState) {
switch (headsetState) {
case BluetoothHeadset.STATE_CONNECTED:
return SettingsBtStatus.CONNECTION_STATUS_CONNECTED;
diff --git a/src/com/android/settings/deviceinfo/Memory.java b/src/com/android/settings/deviceinfo/Memory.java
index 75a84b7..53e2a69 100644
--- a/src/com/android/settings/deviceinfo/Memory.java
+++ b/src/com/android/settings/deviceinfo/Memory.java
@@ -31,6 +31,7 @@
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
+import android.text.format.Formatter;
import android.util.Log;
import com.android.settings.R;
@@ -194,25 +195,7 @@
}
private String formatSize(long size) {
- String suffix = null;
-
- // add KB or MB suffix if size is greater than 1K or 1M
- if (size >= 1024) {
- suffix = " KB";
- size /= 1024;
- if (size >= 1024) {
- suffix = " MB";
- size /= 1024;
- }
- }
-
- DecimalFormat formatter = new DecimalFormat();
- formatter.setGroupingSize(3);
- String result = formatter.format(size);
-
- if (suffix != null)
- result = result + suffix;
- return result;
+ return Formatter.formatFileSize(this, size);
}
}
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index 9162d25..a165754 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -50,7 +50,7 @@
* # Phone Number
* # Network
* # Roaming
- * # IMEI
+ * # Device Id (IMEI in GSM and MEID in CDMA)
* # Network type
* # Signal Strength
* # Battery Strength : TODO
@@ -181,10 +181,28 @@
mSignalStrength = findPreference("signal_strength");
mUptime = findPreference("up_time");
- setSummaryText("imei", mPhone.getDeviceId());
- setSummaryText("imei_sv",
- ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
+ //NOTE "imei" is the "Device ID" since it represents the IMEI in GSM and the MEID in CDMA
+ if (mPhone.getPhoneName().equals("CDMA")) {
+ setSummaryText("meid_number", mPhone.getMeid());
+ setSummaryText("min_number", mPhone.getCdmaMin());
+ setSummaryText("prl_version", mPhone.getCdmaPrlVersion());
+
+ // device is not GSM/UMTS, do not display GSM/UMTS features
+ getPreferenceScreen().removePreference(findPreference("imei"));
+ getPreferenceScreen().removePreference(findPreference("imei_sv"));
+ } else {
+ setSummaryText("imei", mPhone.getDeviceId());
+
+ setSummaryText("imei_sv",
+ ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
.getDeviceSoftwareVersion());
+
+ // device is not CDMA, do not display CDMA features
+ getPreferenceScreen().removePreference(findPreference("prl_version"));
+ getPreferenceScreen().removePreference(findPreference("meid_number"));
+ getPreferenceScreen().removePreference(findPreference("min_number"));
+ }
+
setSummaryText("number", mPhone.getLine1Number());
mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
@@ -301,6 +319,9 @@
}
void updateSignalStrength() {
+ // TODO PhoneStateIntentReceiver is deprecated and PhoneStateListener
+ // should probably used instead.
+
// not loaded in some versions of the code (e.g., zaku)
if (mSignalStrength != null) {
int state =
diff --git a/src/com/android/settings/fuelgauge/PercentageBar.java b/src/com/android/settings/fuelgauge/PercentageBar.java
new file mode 100644
index 0000000..1c4478b
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PercentageBar.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+
+/**
+ * A drawable for drawing a bar with a background.
+ */
+class PercentageBar extends Drawable {
+
+ Drawable bar;
+ double percent;
+ int lastWidth = -1;
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (lastWidth == -1) {
+ lastWidth = getBarWidth();
+ bar.setBounds(0, 0, lastWidth, bar.getIntrinsicHeight());
+ }
+ bar.draw(canvas);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // Ignore
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ // Ignore
+ }
+
+ private int getBarWidth() {
+ int width = (int) ((this.getBounds().width() * percent) / 100);
+ int intrinsicWidth = bar.getIntrinsicWidth();
+ return Math.max(width, intrinsicWidth);
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return bar.getIntrinsicHeight();
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
new file mode 100644
index 0000000..68f294c
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.preference.Preference;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.fuelgauge.PowerUsageSummary.BatterySipper;
+
+/**
+ * Custom preference for displaying power consumption as a bar and an icon on the left for the
+ * subsystem/app type.
+ *
+ */
+public class PowerGaugePreference extends Preference {
+
+ private Drawable mIcon;
+ private PercentageBar mGauge;
+ private double mValue;
+ private BatterySipper mInfo;
+ private double mPercent;
+
+ public PowerGaugePreference(Context context, Drawable icon, BatterySipper info) {
+ super(context);
+ setLayoutResource(R.layout.preference_powergauge);
+ mIcon = icon;
+ mGauge = new PercentageBar();
+ mGauge.bar = context.getResources().getDrawable(R.drawable.app_gauge);
+ mInfo = info;
+ }
+
+ /**
+ * Sets the width of the gauge in percentage (0 - 100)
+ * @param percent
+ */
+ void setGaugeValue(double percent) {
+ mValue = percent;
+ mGauge.percent = mValue;
+ }
+
+ void setPercent(double percent) {
+ mPercent = percent;
+ }
+
+ BatterySipper getInfo() {
+ return mInfo;
+ }
+
+ void setIcon(Drawable icon) {
+ mIcon = icon;
+ notifyChanged();
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+
+ ImageView appIcon = (ImageView) view.findViewById(R.id.appIcon);
+ if (mIcon == null) {
+ mIcon = getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);
+ }
+ appIcon.setImageDrawable(mIcon);
+
+ ImageView appGauge = (ImageView) view.findViewById(R.id.appGauge);
+ appGauge.setImageDrawable(mGauge);
+
+ TextView percentView = (TextView) view.findViewById(R.id.percent);
+ percentView.setText((int) (Math.ceil(mPercent)) + "%");
+ }
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
new file mode 100644
index 0000000..e78e041
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settings.InstalledAppDetails;
+import com.android.settings.R;
+
+public class PowerUsageDetail extends Activity implements Button.OnClickListener {
+
+ enum DrainType {
+ IDLE,
+ CELL,
+ PHONE,
+ WIFI,
+ BLUETOOTH,
+ SCREEN,
+ APP
+ }
+
+ // Note: Must match the sequence of the DrainType
+ private static int[] sDrainTypeDesciptions = new int[] {
+ R.string.battery_desc_standby,
+ R.string.battery_desc_radio,
+ R.string.battery_desc_voice,
+ R.string.battery_desc_wifi,
+ R.string.battery_desc_bluetooth,
+ 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 USAGE_SINCE_UNPLUGGED = 1;
+ public static final int USAGE_SINCE_RESET = 2;
+
+ public static final String EXTRA_TITLE = "title";
+ public static final String EXTRA_PERCENT = "percent";
+ public static final String EXTRA_GAUGE = "gauge";
+ public static final String EXTRA_UID = "uid";
+ public static final String EXTRA_USAGE_SINCE = "since";
+ public static final String EXTRA_USAGE_DURATION = "duration";
+ public static final String EXTRA_DETAIL_TYPES = "types"; // Array of usage types (cpu, gps, etc)
+ 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_ICON_ID = "iconId"; // Int
+
+ private static final boolean DEBUG = true;
+ private String mTitle;
+ private int mUsageSince;
+ private int[] mTypes;
+ private int mUid;
+ private double[] mValues;
+ private TextView mTitleView;
+ private ViewGroup mDetailsParent;
+ private long mStartTime;
+ private DrainType mDrainType;
+ private int mAction1;
+ private int mAction2;
+ private PercentageBar mGauge;
+ private Drawable mAppIcon;
+
+ private static final String TAG = "PowerUsageDetail";
+ private Button mButton1;
+ private Button mButton2;
+ private String[] mPackages;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.power_usage_details);
+ createDetails();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mStartTime = android.os.Process.getElapsedCpuTime();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ private void createDetails() {
+ final Intent intent = getIntent();
+ mTitle = intent.getStringExtra(EXTRA_TITLE);
+ final int percentage = intent.getIntExtra(EXTRA_PERCENT, 1);
+ final int gaugeValue = intent.getIntExtra(EXTRA_GAUGE, 1);
+ mUsageSince = intent.getIntExtra(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
+ mUid = intent.getIntExtra(EXTRA_UID, 0);
+ mDrainType = (DrainType) intent.getSerializableExtra(EXTRA_DRAIN_TYPE);
+ String iconPackage = intent.getStringExtra(EXTRA_ICON_PACKAGE);
+ int iconId = intent.getIntExtra(EXTRA_ICON_ID, 0);
+ if (!TextUtils.isEmpty(iconPackage)) {
+ try {
+ final PackageManager pm = getPackageManager();
+ ApplicationInfo ai = pm.getPackageInfo(iconPackage, 0).applicationInfo;
+ if (ai != null) {
+ mAppIcon = ai.loadIcon(pm);
+ }
+ } catch (NameNotFoundException nnfe) {
+ // Use default icon
+ }
+ } else if (iconId != 0) {
+ mAppIcon = getResources().getDrawable(iconId);
+ }
+ if (mAppIcon == null) {
+ mAppIcon = getPackageManager().getDefaultActivityIcon();
+ }
+
+ // Set the description
+ String summary = getDescriptionForDrainType();
+ ((TextView)findViewById(R.id.summary)).setText(summary);
+
+ mTypes = intent.getIntArrayExtra(EXTRA_DETAIL_TYPES);
+ mValues = intent.getDoubleArrayExtra(EXTRA_DETAIL_VALUES);
+
+ mTitleView = (TextView) findViewById(R.id.name);
+ mTitleView.setText(mTitle);
+ ((TextView)findViewById(R.id.battery_percentage))
+ .setText(String.format("%d%%", percentage));
+
+ ImageView gaugeImage = (ImageView) findViewById(R.id.gauge);
+ mGauge = new PercentageBar();
+ mGauge.percent = gaugeValue;
+ mGauge.bar = getResources().getDrawable(R.drawable.app_gauge);
+ gaugeImage.setImageDrawable(mGauge);
+
+ ImageView iconImage = (ImageView) findViewById(R.id.icon);
+ iconImage.setImageDrawable(mAppIcon);
+
+ mDetailsParent = (ViewGroup) findViewById(R.id.details);
+ LayoutInflater inflater = getLayoutInflater();
+ if (mTypes != null && mValues != null) {
+ for (int i = 0; i < mTypes.length; i++) {
+ // Only add an item if the time is greater than zero
+ if (mValues[i] <= 0) continue;
+ final String label = getString(mTypes[i]);
+ String value = null;
+ switch (mTypes[i]) {
+ case R.string.usage_type_data_recv:
+ case R.string.usage_type_data_send:
+ value = Utils.formatBytes(this, mValues[i]);
+ break;
+ default:
+ value = Utils.formatElapsedTime(this, mValues[i]);
+ }
+ ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_detail_item_text,
+ null);
+ mDetailsParent.addView(item);
+ TextView labelView = (TextView) item.findViewById(R.id.label);
+ TextView valueView = (TextView) item.findViewById(R.id.value);
+ labelView.setText(label);
+ 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;
+ try {
+ pi = packages != null ? pm.getPackageInfo(packages[0], 0) : null;
+ } catch (NameNotFoundException nnfe) { /* Nothing */ }
+ 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;
+ }
+ }
+ 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 (label2 == null) {
+ findViewById(R.id.controls_section).setVisibility(View.GONE);
+ } else {
+ mButton2.setText(label2);
+ }
+ }
+
+ private void removePackagesSection() {
+ View view;
+ if ((view = findViewById(R.id.packages_section_title)) != null) {
+ view.setVisibility(View.GONE);
+ }
+ if ((view = findViewById(R.id.packages_section)) != null) {
+ view.setVisibility(View.GONE);
+ }
+ }
+
+ private void killProcesses() {
+ if (mPackages == null) return;
+ ActivityManager am = (ActivityManager)getSystemService(
+ Context.ACTIVITY_SERVICE);
+ for (int i = 0; i < mPackages.length; i++) {
+ am.restartPackage(mPackages[i]);
+ }
+ }
+
+ private void fillPackagesSection(int uid) {
+ if (uid < 1) {
+ removePackagesSection();
+ return;
+ }
+ ViewGroup packagesParent = (ViewGroup) findViewById(R.id.packages_section);
+ if (packagesParent == null) return;
+ LayoutInflater inflater = getLayoutInflater();
+
+ PackageManager pm = getPackageManager();
+ final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
+ mPackages = pm.getPackagesForUid(uid);
+ if (mPackages == null || mPackages.length < 2) {
+ removePackagesSection();
+ return;
+ }
+
+ // Convert package names to user-facing labels where possible
+ for (int i = 0; i < mPackages.length; i++) {
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0);
+ CharSequence label = ai.loadLabel(pm);
+ Drawable icon = defaultActivityIcon;
+ if (label != null) {
+ mPackages[i] = label.toString();
+ }
+ if (ai.icon != 0) {
+ icon = ai.loadIcon(pm);
+ }
+ ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_package_item,
+ null);
+ packagesParent.addView(item);
+ TextView labelView = (TextView) item.findViewById(R.id.label);
+ labelView.setText(mPackages[i]);
+ } catch (NameNotFoundException e) {
+ }
+ }
+ }
+
+ private String getDescriptionForDrainType() {
+ return getResources().getString(sDrainTypeDesciptions[mDrainType.ordinal()]);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
new file mode 100644
index 0000000..8df0919
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -0,0 +1,697 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.drawable.Drawable;
+import android.hardware.SensorManager;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.BatteryStats.Uid;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.PowerProfile;
+import com.android.settings.R;
+import com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Displays a list of apps and subsystems that consume power, ordered by how much power was
+ * consumed since the last time it was unplugged.
+ */
+public class PowerUsageSummary extends PreferenceActivity implements Runnable {
+
+ private static final boolean DEBUG = false;
+
+ private static final String TAG = "PowerUsageSummary";
+
+ private static final int MENU_STATS_TYPE = Menu.FIRST;
+ private static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
+
+ IBatteryStats mBatteryInfo;
+ BatteryStatsImpl mStats;
+ private List<BatterySipper> mUsageList = new ArrayList<BatterySipper>();
+
+ private PreferenceGroup mAppListGroup;
+
+ private int mStatsType = BatteryStats.STATS_UNPLUGGED;
+
+ private static final int MIN_POWER_THRESHOLD = 5;
+ private static final int MAX_ITEMS_TO_LIST = 10;
+
+ private double mMaxPower = 1;
+ private double mTotalPower;
+
+ private boolean mScaleByMax = true;
+
+ private PowerProfile mPowerProfile;
+
+ private HashMap<String,UidToDetail> mUidCache = new HashMap<String,UidToDetail>();
+
+ /** Queue for fetching name and icon for an application */
+ private ArrayList<BatterySipper> mRequestQueue = new ArrayList<BatterySipper>();
+ private Thread mRequestThread;
+ private boolean mAbort;
+
+ static class UidToDetail {
+ String name;
+ String packageName;
+ Drawable icon;
+ }
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ addPreferencesFromResource(R.xml.power_usage_summary);
+ mBatteryInfo = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService("batteryinfo"));
+ mAppListGroup = (PreferenceGroup) findPreference("app_list");
+ mPowerProfile = new PowerProfile(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mAbort = false;
+ refreshStats();
+ }
+
+ @Override
+ protected void onPause() {
+ synchronized (mRequestQueue) {
+ mAbort = true;
+ }
+ mHandler.removeMessages(MSG_UPDATE_NAME_ICON);
+ super.onPause();
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ PowerGaugePreference pgp = (PowerGaugePreference) preference;
+ BatterySipper sipper = pgp.getInfo();
+ Intent intent = new Intent(this, PowerUsageDetail.class);
+ intent.putExtra(PowerUsageDetail.EXTRA_TITLE, sipper.name);
+ intent.putExtra(PowerUsageDetail.EXTRA_PERCENT, (int)
+ Math.ceil(sipper.getSortValue() * 100 / mTotalPower));
+ intent.putExtra(PowerUsageDetail.EXTRA_GAUGE, (int)
+ Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
+ intent.putExtra(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
+ intent.putExtra(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
+ if (sipper.uidObj != null) {
+ intent.putExtra(PowerUsageDetail.EXTRA_UID, sipper.uidObj.getUid());
+ }
+ intent.putExtra(PowerUsageDetail.EXTRA_DRAIN_TYPE, sipper.drainType);
+ switch (sipper.drainType) {
+ case APP:
+ {
+ Uid uid = sipper.uidObj;
+ int[] types = new int[] {
+ R.string.usage_type_cpu,
+ R.string.usage_type_cpu_foreground,
+ R.string.usage_type_gps,
+ R.string.usage_type_data_send,
+ R.string.usage_type_data_recv,
+ R.string.usage_type_audio,
+ R.string.usage_type_video,
+ };
+ double[] values = new double[] {
+ sipper.cpuTime,
+ sipper.cpuFgTime,
+ sipper.gpsTime,
+ uid != null? uid.getTcpBytesSent(mStatsType) : 0,
+ uid != null? uid.getTcpBytesReceived(mStatsType) : 0,
+ 0,
+ 0
+ };
+ intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
+ intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
+
+ }
+ break;
+ default:
+ {
+ int[] types = new int[] {
+ R.string.usage_type_on_time
+ };
+ double[] values = new double[] {
+ sipper.usageTime
+ };
+ intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
+ intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
+ }
+ }
+ startActivity(intent);
+
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ if (DEBUG) {
+ menu.add(0, MENU_STATS_TYPE, 0, R.string.menu_stats_total)
+ .setIcon(com.android.internal.R.drawable.ic_menu_info_details)
+ .setAlphabeticShortcut('t');
+ }
+ menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh)
+ .setIcon(com.android.internal.R.drawable.ic_menu_refresh)
+ .setAlphabeticShortcut('r');
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ if (DEBUG) {
+ menu.findItem(MENU_STATS_TYPE).setTitle(mStatsType == BatteryStats.STATS_TOTAL
+ ? R.string.menu_stats_unplugged
+ : R.string.menu_stats_total);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_STATS_TYPE:
+ if (mStatsType == BatteryStats.STATS_TOTAL) {
+ mStatsType = BatteryStats.STATS_UNPLUGGED;
+ } else {
+ mStatsType = BatteryStats.STATS_TOTAL;
+ }
+ refreshStats();
+ return true;
+ case MENU_STATS_REFRESH:
+ mStats = null;
+ refreshStats();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void refreshStats() {
+ if (mStats == null) {
+ load();
+ }
+ mMaxPower = 0;
+ mTotalPower = 0;
+
+ mAppListGroup.removeAll();
+ mUsageList.clear();
+ processAppUsage();
+ processMiscUsage();
+
+ 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()));
+ }
+ mAppListGroup.addPreference(pref);
+ if (mAppListGroup.getPreferenceCount() > MAX_ITEMS_TO_LIST) break;
+ }
+ if (DEBUG) setTitle("Battery total uAh = " + ((mTotalPower * 1000) / 3600));
+ synchronized (mRequestQueue) {
+ if (!mRequestQueue.isEmpty()) {
+ if (mRequestThread == null) {
+ mRequestThread = new Thread(this, "BatteryUsage Icon Loader");
+ mRequestThread.setPriority(Thread.MIN_PRIORITY);
+ mRequestThread.start();
+ }
+ mRequestQueue.notify();
+ }
+ }
+ }
+
+ private void updateStatsPeriod(long duration) {
+ String durationString = Utils.formatElapsedTime(this, duration / 1000);
+ String label = getString(R.string.battery_stats_duration, durationString);
+ setTitle(label);
+ }
+
+ private void processAppUsage() {
+ SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ final int which = mStatsType;
+ final double powerCpuNormal = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_NORMAL);
+ final double averageCostPerByte = getAverageDataCost();
+ long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
+ updateStatsPeriod(uSecTime);
+ SparseArray<? extends Uid> uidStats = mStats.getUidStats();
+ final int NU = uidStats.size();
+ for (int iu = 0; iu < NU; iu++) {
+ Uid u = uidStats.valueAt(iu);
+ double power = 0;
+ double highestDrain = 0;
+ String packageWithHighestDrain = null;
+ //mUsageList.add(new AppUsage(u.getUid(), new double[] {power}));
+ Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
+ long cpuTime = 0;
+ long cpuFgTime = 0;
+ long gpsTime = 0;
+ if (processStats.size() > 0) {
+ // Process CPU time
+ for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
+ : processStats.entrySet()) {
+ if (DEBUG) Log.i(TAG, "Process name = " + ent.getKey());
+ Uid.Proc ps = ent.getValue();
+ final long userTime = ps.getUserTime(which);
+ final long systemTime = ps.getSystemTime(which);
+ final long foregroundTime = ps.getForegroundTime(which);
+ cpuFgTime += foregroundTime * 10; // convert to millis
+ final long tmpCpuTime = (userTime + systemTime) * 10; // convert to millis
+ final double processPower = tmpCpuTime * powerCpuNormal;
+ cpuTime += tmpCpuTime;
+ power += processPower;
+ if (highestDrain < processPower) {
+ highestDrain = processPower;
+ packageWithHighestDrain = ent.getKey();
+ }
+
+ }
+ if (DEBUG) Log.i(TAG, "Max drain of " + highestDrain
+ + " by " + packageWithHighestDrain);
+ }
+ if (cpuFgTime > cpuTime) {
+ if (DEBUG && cpuFgTime > cpuTime + 10000) {
+ Log.i(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
+ }
+ cpuTime = cpuFgTime; // Statistics may not have been gathered yet.
+ }
+ power /= 1000;
+
+ // Add cost of data traffic
+ power += (u.getTcpBytesReceived(mStatsType) + u.getTcpBytesSent(mStatsType))
+ * averageCostPerByte;
+
+ // Process Sensor usage
+ Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
+ for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> sensorEntry
+ : sensorStats.entrySet()) {
+ Uid.Sensor sensor = sensorEntry.getValue();
+ int sensorType = sensor.getHandle();
+ BatteryStats.Timer timer = sensor.getSensorTime();
+ long sensorTime = timer.getTotalTimeLocked(uSecTime, which) / 1000;
+ double multiplier = 0;
+ switch (sensorType) {
+ case Uid.Sensor.GPS:
+ multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
+ gpsTime = sensorTime;
+ break;
+ default:
+ android.hardware.Sensor sensorData =
+ sensorManager.getDefaultSensor(sensorType);
+ if (sensorData != null) {
+ multiplier = sensorData.getPower();
+ if (DEBUG) {
+ Log.i(TAG, "Got sensor " + sensorData.getName() + " with power = "
+ + multiplier);
+ }
+ }
+ }
+ power += (multiplier * sensorTime) / 1000;
+ }
+
+ // Add the app to the list if it is consuming power
+ if (power != 0) {
+ BatterySipper app = new BatterySipper(packageWithHighestDrain, DrainType.APP, 0, u,
+ new double[] {power});
+ app.cpuTime = cpuTime;
+ app.gpsTime = gpsTime;
+ app.cpuFgTime = cpuFgTime;
+ mUsageList.add(app);
+ }
+ if (power > mMaxPower) mMaxPower = power;
+ mTotalPower += power;
+ if (DEBUG) Log.i(TAG, "Added power = " + power);
+ }
+ }
+
+ private void addPhoneUsage(long uSecNow) {
+ long phoneOnTimeMs = mStats.getPhoneOnTime(uSecNow, mStatsType) / 1000;
+ double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
+ * phoneOnTimeMs / 1000;
+ addEntry(getString(R.string.power_phone), DrainType.PHONE, phoneOnTimeMs,
+ android.R.drawable.ic_menu_call, phoneOnPower);
+ }
+
+ private void addScreenUsage(long uSecNow) {
+ double power = 0;
+ long screenOnTimeMs = mStats.getScreenOnTime(uSecNow, mStatsType) / 1000;
+ power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON);
+ final double screenFullPower =
+ mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
+ for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
+ double screenBinPower = screenFullPower * (i + 0.5f)
+ / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
+ long brightnessTime = mStats.getScreenBrightnessTime(i, uSecNow, mStatsType) / 1000;
+ power += screenBinPower * brightnessTime;
+ if (DEBUG) {
+ Log.i(TAG, "Screen bin power = " + (int) screenBinPower + ", time = "
+ + brightnessTime);
+ }
+ }
+ power /= 1000; // To seconds
+ addEntry(getString(R.string.power_screen), DrainType.SCREEN, screenOnTimeMs,
+ android.R.drawable.ic_menu_view, power);
+ }
+
+ private void addRadioUsage(long uSecNow) {
+ double power = 0;
+ final int BINS = BatteryStats.NUM_SIGNAL_STRENGTH_BINS;
+ long signalTimeMs = 0;
+ for (int i = 0; i < BINS; i++) {
+ long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, uSecNow, mStatsType) / 1000;
+ power += strengthTimeMs / 1000
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
+ signalTimeMs += strengthTimeMs;
+ }
+ addEntry(getString(R.string.power_cell), DrainType.CELL, signalTimeMs,
+ android.R.drawable.ic_menu_sort_by_size, power);
+ }
+
+ private void addWiFiUsage(long uSecNow) {
+ long onTimeMs = mStats.getWifiOnTime(uSecNow, mStatsType) / 1000;
+ long runningTimeMs = mStats.getWifiRunningTime(uSecNow, mStatsType) / 1000;
+ double wifiPower = (onTimeMs * 0 /* TODO */
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
+ + runningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
+ addEntry(getString(R.string.power_wifi), DrainType.WIFI, runningTimeMs,
+ R.drawable.ic_wifi_signal_4, wifiPower);
+ }
+
+ private void addIdleUsage(long uSecNow) {
+ long idleTimeMs = (uSecNow - mStats.getScreenOnTime(uSecNow, mStatsType)) / 1000;
+ double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE))
+ / 1000;
+ addEntry(getString(R.string.power_idle), DrainType.IDLE, idleTimeMs,
+ android.R.drawable.ic_lock_power_off, idlePower);
+ }
+
+ private void addBluetoothUsage(long uSecNow) {
+ long btOnTimeMs = mStats.getBluetoothOnTime(uSecNow, mStatsType) / 1000;
+ double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
+ / 1000;
+ addEntry(getString(R.string.power_bluetooth), DrainType.IDLE, btOnTimeMs,
+ com.android.internal.R.drawable.ic_volume_bluetooth_in_call, btPower);
+ }
+
+ private double getAverageDataCost() {
+ final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
+ final long MOBILE_BPS = 200000; // TODO: Extract average bit rates from system
+ final double WIFI_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
+ / 3600;
+ final double MOBILE_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
+ / 3600;
+ final long mobileData = mStats.getMobileTcpBytesReceived(mStatsType) +
+ mStats.getMobileTcpBytesSent(mStatsType);
+ final long wifiData = mStats.getTotalTcpBytesReceived(mStatsType) +
+ mStats.getTotalTcpBytesSent(mStatsType) - mobileData;
+ final long radioDataUptimeMs = mStats.getRadioDataUptimeMs();
+ final long mobileBps = radioDataUptimeMs != 0
+ ? mobileData * 8 * 1000 / radioDataUptimeMs
+ : MOBILE_BPS;
+
+ double mobileCostPerByte = MOBILE_POWER / (mobileBps / 8);
+ double wifiCostPerByte = WIFI_POWER / (WIFI_BPS / 8);
+ if (wifiData + mobileData != 0) {
+ return (mobileCostPerByte * mobileData + wifiCostPerByte * wifiData)
+ / (mobileData + wifiData);
+ } else {
+ return 0;
+ }
+ }
+
+ private void processMiscUsage() {
+ final int which = mStatsType;
+ long uSecTime = SystemClock.elapsedRealtime() * 1000;
+ final long uSecNow = mStats.computeBatteryRealtime(uSecTime, which);
+ final long timeSinceUnplugged = uSecNow;
+ if (DEBUG) {
+ Log.i(TAG, "Uptime since last unplugged = " + (timeSinceUnplugged / 1000));
+ }
+
+ addPhoneUsage(uSecNow);
+ addScreenUsage(uSecNow);
+ addWiFiUsage(uSecNow);
+ addBluetoothUsage(uSecNow);
+ addIdleUsage(uSecNow); // Not including cellular idle power
+ addRadioUsage(uSecNow);
+ }
+
+ private void 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);
+ }
+
+ private void load() {
+ try {
+ byte[] data = mBatteryInfo.getStatistics();
+ Parcel parcel = Parcel.obtain();
+ parcel.unmarshall(data, 0, data.length);
+ parcel.setDataPosition(0);
+ mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
+ .createFromParcel(parcel);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException:", e);
+ }
+ }
+
+ class BatterySipper implements Comparable<BatterySipper> {
+ String name;
+ Drawable icon;
+ int iconId; // For passing to the detail screen.
+ Uid uidObj;
+ double value;
+ double[] values;
+ DrainType drainType;
+ long usageTime;
+ long cpuTime;
+ long gpsTime;
+ long cpuFgTime;
+ double percent;
+ String defaultPackageName;
+
+ BatterySipper(String label, DrainType drainType, int iconId, Uid uid, double[] values) {
+ this.values = values;
+ name = label;
+ this.drainType = drainType;
+ if (iconId > 0) {
+ 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);
+ }
+ uidObj = uid;
+ }
+
+ double getSortValue() {
+ return value;
+ }
+
+ double[] getValues() {
+ return values;
+ }
+
+ Drawable getIcon() {
+ return icon;
+ }
+
+ public int compareTo(BatterySipper other) {
+ // Return the flipped value because we want the items in descending order
+ return (int) (other.getSortValue() - getSortValue());
+ }
+
+ void getQuickNameIconForUid(Uid uidObj) {
+ final int uid = uidObj.getUid();
+ final String uidString = Integer.toString(uid);
+ if (mUidCache.containsKey(uidString)) {
+ UidToDetail utd = mUidCache.get(uidString);
+ defaultPackageName = utd.packageName;
+ name = utd.name;
+ icon = utd.icon;
+ return;
+ }
+ PackageManager pm = getPackageManager();
+ final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
+ String[] packages = pm.getPackagesForUid(uid);
+ icon = pm.getDefaultActivityIcon();
+ if (packages == null) {
+ //name = Integer.toString(uid);
+ if (uid == 0) {
+ name = getResources().getString(R.string.process_kernel_label);
+ } else if ("mediaserver".equals(name)) {
+ name = getResources().getString(R.string.process_mediaserver_label);
+ }
+ return;
+ } else {
+ //name = packages[0];
+ }
+ synchronized (mRequestQueue) {
+ mRequestQueue.add(this);
+ }
+ }
+
+ /**
+ * Sets name and icon
+ * @param uid Uid of the application
+ */
+ void getNameIcon() {
+ PackageManager pm = getPackageManager();
+ final int uid = uidObj.getUid();
+ final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
+ String[] packages = pm.getPackagesForUid(uid);
+ if (packages == null) {
+ name = Integer.toString(uid);
+ return;
+ }
+
+ String[] packageLabels = new String[packages.length];
+ System.arraycopy(packages, 0, packageLabels, 0, packages.length);
+
+ int preferredIndex = -1;
+ // Convert package names to user-facing labels where possible
+ for (int i = 0; i < packageLabels.length; i++) {
+ // Check if package matches preferred package
+ if (packageLabels[i].equals(name)) preferredIndex = i;
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0);
+ CharSequence label = ai.loadLabel(pm);
+ if (label != null) {
+ packageLabels[i] = label.toString();
+ }
+ if (ai.icon != 0) {
+ defaultPackageName = packages[i];
+ icon = ai.loadIcon(pm);
+ break;
+ }
+ } catch (NameNotFoundException e) {
+ }
+ }
+ if (icon == null) icon = defaultActivityIcon;
+
+ if (packageLabels.length == 1) {
+ name = packageLabels[0];
+ } else {
+ // Look for an official name for this UID.
+ for (String pkgName : packages) {
+ try {
+ PackageInfo pi = pm.getPackageInfo(pkgName, 0);
+ if (pi.sharedUserLabel != 0) {
+ CharSequence nm = pm.getText(pkgName,
+ pi.sharedUserLabel, pi.applicationInfo);
+ if (nm != null) {
+ name = nm.toString();
+ if (pi.applicationInfo.icon != 0) {
+ defaultPackageName = pkgName;
+ icon = pi.applicationInfo.loadIcon(pm);
+ }
+ break;
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ }
+ }
+ final String uidString = Integer.toString(uidObj.getUid());
+ UidToDetail utd = new UidToDetail();
+ utd.name = name;
+ utd.icon = icon;
+ utd.packageName = defaultPackageName;
+ mUidCache.put(uidString, utd);
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
+ }
+ }
+
+ public void run() {
+ while (true) {
+ BatterySipper bs;
+ synchronized (mRequestQueue) {
+ if (mRequestQueue.isEmpty() || mAbort) {
+ mRequestThread = null;
+ return;
+ }
+ bs = mRequestQueue.remove(0);
+ }
+ bs.getNameIcon();
+ }
+ }
+
+ private static final int MSG_UPDATE_NAME_ICON = 1;
+
+ Handler mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_NAME_ICON:
+ BatterySipper bs = (BatterySipper) msg.obj;
+ PowerGaugePreference pgp =
+ (PowerGaugePreference) findPreference(
+ Integer.toString(bs.uidObj.getUid()));
+ if (pgp != null) {
+ pgp.setIcon(bs.icon);
+ pgp.setPercent(bs.percent);
+ pgp.setTitle(bs.name);
+ }
+ break;
+ }
+ super.handleMessage(msg);
+ }
+ };
+}
diff --git a/src/com/android/settings/fuelgauge/Utils.java b/src/com/android/settings/fuelgauge/Utils.java
new file mode 100644
index 0000000..2ffc9de
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/Utils.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+
+import com.android.settings.R;
+
+/**
+ * Contains utility functions for formatting elapsed time and consumed bytes
+ */
+public class Utils {
+ private static final int SECONDS_PER_MINUTE = 60;
+ private static final int SECONDS_PER_HOUR = 60 * 60;
+ private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+
+ /**
+ * Returns elapsed time for the given millis, in the following format:
+ * 2d 5h 40m 29s
+ * @param context the application context
+ * @param millis the elapsed time in milli seconds
+ * @return the formatted elapsed time
+ */
+ public static String formatElapsedTime(Context context, double millis) {
+ StringBuilder sb = new StringBuilder();
+ int seconds = (int) Math.floor(millis / 1000);
+
+ int days = 0, hours = 0, minutes = 0;
+ if (seconds > SECONDS_PER_DAY) {
+ days = seconds / SECONDS_PER_DAY;
+ seconds -= days * SECONDS_PER_DAY;
+ }
+ if (seconds > SECONDS_PER_HOUR) {
+ hours = seconds / SECONDS_PER_HOUR;
+ seconds -= hours * SECONDS_PER_HOUR;
+ }
+ if (seconds > SECONDS_PER_MINUTE) {
+ minutes = seconds / SECONDS_PER_MINUTE;
+ seconds -= minutes * SECONDS_PER_MINUTE;
+ }
+ if (days > 0) {
+ sb.append(context.getString(R.string.battery_history_days,
+ days, hours, minutes, seconds));
+ } else if (hours > 0) {
+ sb.append(context.getString(R.string.battery_history_hours, hours, minutes, seconds));
+ } else if (minutes > 0) {
+ sb.append(context.getString(R.string.battery_history_minutes, minutes, seconds));
+ } else {
+ sb.append(context.getString(R.string.battery_history_seconds, seconds));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Formats data size in KB, MB, from the given bytes.
+ * @param context the application context
+ * @param bytes data size in bytes
+ * @return the formatted size such as 4.52 MB or 245 KB or 332 bytes
+ */
+ public static String formatBytes(Context context, double bytes) {
+ // TODO: I18N
+ if (bytes > 1000 * 1000) {
+ return String.format("%.2f MB", ((int) (bytes / 1000)) / 1000f);
+ } else if (bytes > 1024) {
+ return String.format("%.2f KB", ((int) (bytes / 10)) / 100f);
+ } else {
+ return String.format("%d bytes", (int) bytes);
+ }
+ }
+}
diff --git a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
index 4d44524..40316b5 100644
--- a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
+++ b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
@@ -20,6 +20,8 @@
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
@@ -39,6 +41,8 @@
import com.android.settings.R;
+import java.net.URISyntaxException;
+
/**
* Settings activity for quick launch.
* <p>
@@ -300,7 +304,27 @@
if (shortcut == 0) continue;
ShortcutPreference pref = getOrCreatePreference(shortcut);
- pref.setTitle(Bookmarks.getTitle(this, c));
+ CharSequence title = Bookmarks.getTitle(this, c);
+
+ /*
+ * The title retrieved from Bookmarks.getTitle() will be in
+ * the original boot locale, not the current locale.
+ * Try to look up a localized title from the PackageManager.
+ */
+ int intentColumn = c.getColumnIndex(Bookmarks.INTENT);
+ String intentUri = c.getString(intentColumn);
+ PackageManager packageManager = getPackageManager();
+ try {
+ Intent intent = Intent.getIntent(intentUri);
+ ResolveInfo info = packageManager.resolveActivity(intent, 0);
+ if (info != null) {
+ title = info.loadLabel(packageManager);
+ }
+ } catch (URISyntaxException e) {
+ // Just use the non-localized title, then.
+ }
+
+ pref.setTitle(title);
pref.setSummary(getString(R.string.quick_launch_shortcut,
String.valueOf(shortcut)));
pref.setHasBookmark(true);
diff --git a/src/com/android/settings/vpn/AuthenticationActor.java b/src/com/android/settings/vpn/AuthenticationActor.java
new file mode 100644
index 0000000..286064f
--- /dev/null
+++ b/src/com/android/settings/vpn/AuthenticationActor.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.app.Dialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.net.vpn.IVpnService;
+import android.net.vpn.VpnManager;
+import android.net.vpn.VpnProfile;
+import android.net.vpn.VpnState;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import java.io.IOException;
+
+/**
+ * A {@link VpnProfileActor} that provides an authentication view for users to
+ * input username and password before connecting to the VPN server.
+ */
+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;
+ private VpnManager mVpnManager;
+
+ public AuthenticationActor(Context context, VpnProfile p) {
+ mContext = context;
+ mProfile = p;
+ mVpnManager = new VpnManager(context);
+ }
+
+ //@Override
+ public VpnProfile getProfile() {
+ return mProfile;
+ }
+
+ //@Override
+ public boolean isConnectDialogNeeded() {
+ return true;
+ }
+
+ //@Override
+ public String validateInputs(Dialog d) {
+ TextView usernameView = (TextView) d.findViewById(R.id.username_value);
+ TextView passwordView = (TextView) d.findViewById(R.id.password_value);
+ Context c = mContext;
+ if (TextUtils.isEmpty(usernameView.getText().toString())) {
+ return c.getString(R.string.vpn_a_username);
+ } else if (TextUtils.isEmpty(passwordView.getText().toString())) {
+ return c.getString(R.string.vpn_a_password);
+ } else {
+ return null;
+ }
+ }
+
+ //@Override
+ public void connect(Dialog d) {
+ TextView usernameView = (TextView) d.findViewById(R.id.username_value);
+ TextView passwordView = (TextView) d.findViewById(R.id.password_value);
+ CheckBox saveUsername = (CheckBox) d.findViewById(R.id.save_username);
+
+ try {
+ setSavedUsername(saveUsername.isChecked()
+ ? usernameView.getText().toString()
+ : "");
+ } catch (IOException e) {
+ Log.e(TAG, "setSavedUsername()", e);
+ }
+
+ connect(usernameView.getText().toString(),
+ passwordView.getText().toString());
+ passwordView.setText("");
+ }
+
+ //@Override
+ public View createConnectView() {
+ return View.inflate(mContext, R.layout.vpn_connect_dialog_view, null);
+ }
+
+ //@Override
+ public void updateConnectView(Dialog d) {
+ String username = mProfile.getSavedUsername();
+ if (username == null) username = "";
+ updateConnectView(d, username, "", !TextUtils.isEmpty(username));
+ }
+
+ protected Context getContext() {
+ return mContext;
+ }
+
+ private void connect(final String username, final String password) {
+ mVpnManager.startVpnService();
+ ServiceConnection c = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+ boolean success = false;
+ try {
+ success = IVpnService.Stub.asInterface(service)
+ .connect(mProfile, username, password);
+ } catch (Throwable e) {
+ Log.e(TAG, "connect()", e);
+ checkStatus();
+ } finally {
+ mContext.unbindService(this);
+
+ if (!success) {
+ Log.d(TAG, "~~~~~~ connect() failed!");
+ broadcastConnectivity(VpnState.IDLE);
+ } else {
+ Log.d(TAG, "~~~~~~ connect() succeeded!");
+ }
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ checkStatus();
+ }
+ };
+ if (!bindService(c)) broadcastConnectivity(VpnState.IDLE);
+ }
+
+ //@Override
+ public void disconnect() {
+ ServiceConnection c = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+ try {
+ IVpnService.Stub.asInterface(service).disconnect();
+ } catch (RemoteException e) {
+ Log.e(TAG, "disconnect()", e);
+ checkStatus();
+ } finally {
+ mContext.unbindService(this);
+ broadcastConnectivity(VpnState.IDLE);
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ checkStatus();
+ }
+ };
+ bindService(c);
+ }
+
+ //@Override
+ public void checkStatus() {
+ ServiceConnection c = new ServiceConnection() {
+ public synchronized void onServiceConnected(ComponentName className,
+ IBinder service) {
+ try {
+ IVpnService.Stub.asInterface(service).checkStatus(mProfile);
+ } catch (Throwable e) {
+ Log.e(TAG, "checkStatus()", e);
+ } finally {
+ notify();
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // do nothing
+ }
+ };
+ if (bindService(c)) {
+ // wait for a second, let status propagate
+ wait(c, ONE_SECOND);
+ }
+ mContext.unbindService(c);
+ }
+
+ private boolean bindService(ServiceConnection c) {
+ return mVpnManager.bindVpnService(c);
+ }
+
+ private void updateConnectView(Dialog d, String username,
+ String password, boolean toSaveUsername) {
+ TextView usernameView = (TextView) d.findViewById(R.id.username_value);
+ TextView passwordView = (TextView) d.findViewById(R.id.password_value);
+ CheckBox saveUsername = (CheckBox) d.findViewById(R.id.save_username);
+ usernameView.setText(username);
+ passwordView.setText(password);
+ saveUsername.setChecked(toSaveUsername);
+ }
+
+ private void broadcastConnectivity(VpnState s) {
+ mVpnManager.broadcastConnectivity(mProfile.getName(), s);
+ }
+
+ 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);
+ VpnSettings.saveProfileToStorage(mProfile);
+ }
+ }
+}
diff --git a/src/com/android/settings/vpn/L2tpEditor.java b/src/com/android/settings/vpn/L2tpEditor.java
new file mode 100644
index 0000000..643ba3b
--- /dev/null
+++ b/src/com/android/settings/vpn/L2tpEditor.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.net.vpn.L2tpProfile;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+
+/**
+ * The class for editing {@link L2tpProfile}.
+ */
+class L2tpEditor extends VpnProfileEditor {
+ private CheckBoxPreference mSecret;
+ private EditTextPreference mSecretString;
+ private String mOriginalSecret;
+ private boolean mOriginalSecretEnabled;
+
+ public L2tpEditor(L2tpProfile p) {
+ super(p);
+ }
+
+ @Override
+ protected void loadExtraPreferencesTo(PreferenceGroup subpanel) {
+ Context c = subpanel.getContext();
+ subpanel.addPreference(createSecretPreference(c));
+ subpanel.addPreference(createSecretStringPreference(c));
+ mSecretString.setEnabled(mSecret.isChecked());
+
+ L2tpProfile profile = (L2tpProfile) getProfile();
+ mOriginalSecret = profile.getSecretString();
+ mOriginalSecretEnabled = profile.isSecretEnabled();
+ }
+
+ @Override
+ public String validate() {
+ String result = super.validate();
+ if (!mSecret.isChecked()) return result;
+
+ return ((result != null)
+ ? result
+ : validate(mSecretString, R.string.vpn_a_l2tp_secret));
+ }
+
+ private Preference createSecretPreference(Context c) {
+ final L2tpProfile profile = (L2tpProfile) getProfile();
+ CheckBoxPreference secret = mSecret = new CheckBoxPreference(c);
+ boolean enabled = profile.isSecretEnabled();
+ setSecretTitle(secret, R.string.vpn_l2tp_secret, enabled);
+ secret.setChecked(enabled);
+ setSecretSummary(secret, enabled);
+ secret.setOnPreferenceChangeListener(
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ boolean enabled = (Boolean) newValue;
+ profile.setSecretEnabled(enabled);
+ mSecretString.setEnabled(enabled);
+ setSecretTitle(mSecret, R.string.vpn_l2tp_secret,
+ enabled);
+ setSecretSummary(mSecret, enabled);
+ return true;
+ }
+ });
+ return secret;
+ }
+
+ private Preference createSecretStringPreference(Context c) {
+ final L2tpProfile profile = (L2tpProfile) getProfile();
+ mSecretString = createSecretPreference(c,
+ R.string.vpn_l2tp_secret_string_title,
+ R.string.vpn_l2tp_secret,
+ profile.getSecretString(),
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ profile.setSecretString((String) newValue);
+ setSecretSummary(mSecretString,
+ R.string.vpn_l2tp_secret,
+ (String) newValue);
+ return true;
+ }
+ });
+ return mSecretString;
+ }
+
+ private void setSecretSummary(CheckBoxPreference secret, boolean enabled) {
+ Context c = secret.getContext();
+ String formatString = c.getString(enabled
+ ? R.string.vpn_is_enabled
+ : R.string.vpn_is_disabled);
+ secret.setSummary(String.format(
+ formatString, c.getString(R.string.vpn_l2tp_secret)));
+ }
+}
diff --git a/src/com/android/settings/vpn/L2tpIpsecEditor.java b/src/com/android/settings/vpn/L2tpIpsecEditor.java
new file mode 100644
index 0000000..b14feb3
--- /dev/null
+++ b/src/com/android/settings/vpn/L2tpIpsecEditor.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.net.vpn.L2tpIpsecProfile;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.security.CertTool;
+import android.text.TextUtils;
+
+/**
+ * The class for editing {@link L2tpIpsecProfile}.
+ */
+class L2tpIpsecEditor extends L2tpEditor {
+ private static final String TAG = L2tpIpsecEditor.class.getSimpleName();
+
+ private ListPreference mUserCertificate;
+ private ListPreference mCaCertificate;
+
+ private L2tpIpsecProfile mProfile;
+
+ public L2tpIpsecEditor(L2tpIpsecProfile p) {
+ super(p);
+ mProfile = p;
+ }
+
+ @Override
+ protected void loadExtraPreferencesTo(PreferenceGroup subpanel) {
+ super.loadExtraPreferencesTo(subpanel);
+ Context c = subpanel.getContext();
+ subpanel.addPreference(createUserCertificatePreference(c));
+ subpanel.addPreference(createCaCertificatePreference(c));
+ }
+
+ @Override
+ public String validate() {
+ String result = super.validate();
+ if (result == null) {
+ result = validate(mUserCertificate, R.string.vpn_a_user_certificate);
+ }
+ if (result == null) {
+ result = validate(mCaCertificate, R.string.vpn_a_ca_certificate);
+ }
+ return result;
+ }
+
+ private Preference createUserCertificatePreference(Context c) {
+ mUserCertificate = createListPreference(c,
+ R.string.vpn_user_certificate_title,
+ mProfile.getUserCertificate(),
+ CertTool.getInstance().getAllUserCertificateKeys(),
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ mProfile.setUserCertificate((String) newValue);
+ setSummary(pref, R.string.vpn_user_certificate,
+ (String) newValue);
+ return true;
+ }
+ });
+ setSummary(mUserCertificate, R.string.vpn_user_certificate,
+ mProfile.getUserCertificate());
+ return mUserCertificate;
+ }
+
+ private Preference createCaCertificatePreference(Context c) {
+ mCaCertificate = createListPreference(c,
+ R.string.vpn_ca_certificate_title,
+ mProfile.getCaCertificate(),
+ CertTool.getInstance().getAllCaCertificateKeys(),
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ mProfile.setCaCertificate((String) newValue);
+ setSummary(pref, R.string.vpn_ca_certificate,
+ (String) newValue);
+ return true;
+ }
+ });
+ setSummary(mCaCertificate, R.string.vpn_ca_certificate,
+ mProfile.getCaCertificate());
+ return mCaCertificate;
+ }
+
+ private ListPreference createListPreference(Context c, int titleResId,
+ String text, String[] keys,
+ Preference.OnPreferenceChangeListener listener) {
+ ListPreference pref = new ListPreference(c);
+ pref.setTitle(titleResId);
+ pref.setDialogTitle(titleResId);
+ pref.setPersistent(true);
+ pref.setEntries(keys);
+ pref.setEntryValues(keys);
+ pref.setValue(text);
+ pref.setOnPreferenceChangeListener(listener);
+ return pref;
+ }
+}
diff --git a/src/com/android/settings/vpn/L2tpIpsecPskEditor.java b/src/com/android/settings/vpn/L2tpIpsecPskEditor.java
new file mode 100644
index 0000000..11590da
--- /dev/null
+++ b/src/com/android/settings/vpn/L2tpIpsecPskEditor.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.net.vpn.L2tpIpsecPskProfile;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+
+/**
+ * The class for editing {@link L2tpIpsecPskProfile}.
+ */
+class L2tpIpsecPskEditor extends L2tpEditor {
+ private EditTextPreference mPresharedKey;
+
+ public L2tpIpsecPskEditor(L2tpIpsecPskProfile p) {
+ super(p);
+ }
+
+ @Override
+ protected void loadExtraPreferencesTo(PreferenceGroup subpanel) {
+ Context c = subpanel.getContext();
+ subpanel.addPreference(createPresharedKeyPreference(c));
+ super.loadExtraPreferencesTo(subpanel);
+ }
+
+ @Override
+ public String validate() {
+ String result = super.validate();
+
+ return ((result != null)
+ ? result
+ : validate(mPresharedKey, R.string.vpn_a_ipsec_presharedkey));
+ }
+
+ private Preference createPresharedKeyPreference(Context c) {
+ final L2tpIpsecPskProfile profile = (L2tpIpsecPskProfile) getProfile();
+ mPresharedKey = createSecretPreference(c,
+ R.string.vpn_ipsec_presharedkey_title,
+ R.string.vpn_ipsec_presharedkey,
+ profile.getPresharedKey(),
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ profile.setPresharedKey((String) newValue);
+ setSecretSummary(mPresharedKey,
+ R.string.vpn_ipsec_presharedkey,
+ (String) newValue);
+ return true;
+ }
+ });
+ return mPresharedKey;
+ }
+}
diff --git a/src/com/android/settings/vpn/Util.java b/src/com/android/settings/vpn/Util.java
new file mode 100644
index 0000000..a37049d
--- /dev/null
+++ b/src/com/android/settings/vpn/Util.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+class Util {
+
+ static void showShortToastMessage(Context context, String message) {
+ Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+ }
+
+ static void showShortToastMessage(Context context, int messageId) {
+ Toast.makeText(context, messageId, Toast.LENGTH_SHORT).show();
+ }
+
+ static void showLongToastMessage(Context context, String message) {
+ Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+ }
+
+ static void showLongToastMessage(Context context, int messageId) {
+ Toast.makeText(context, messageId, Toast.LENGTH_LONG).show();
+ }
+
+ static void showErrorMessage(Context c, String message) {
+ createErrorDialog(c, message, null).show();
+ }
+
+ static void showErrorMessage(Context c, String message,
+ DialogInterface.OnClickListener listener) {
+ createErrorDialog(c, message, listener).show();
+ }
+
+ static void deleteFile(String path) {
+ deleteFile(new File(path));
+ }
+
+ static void deleteFile(String path, boolean toDeleteSelf) {
+ deleteFile(new File(path), toDeleteSelf);
+ }
+
+ static void deleteFile(File f) {
+ deleteFile(f, true);
+ }
+
+ static void deleteFile(File f, boolean toDeleteSelf) {
+ if (f.isDirectory()) {
+ for (File child : f.listFiles()) deleteFile(child, true);
+ }
+ if (toDeleteSelf) f.delete();
+ }
+
+ static boolean isFileOrEmptyDirectory(String path) {
+ File f = new File(path);
+ if (!f.isDirectory()) return true;
+
+ String[] list = f.list();
+ return ((list == null) || (list.length == 0));
+ }
+
+ static boolean copyFiles(String sourcePath , String targetPath)
+ throws IOException {
+ return copyFiles(new File(sourcePath), new File(targetPath));
+ }
+
+ // returns false if sourceLocation is the same as the targetLocation
+ static boolean copyFiles(File sourceLocation , File targetLocation)
+ throws IOException {
+ if (sourceLocation.equals(targetLocation)) return false;
+
+ if (sourceLocation.isDirectory()) {
+ if (!targetLocation.exists()) {
+ targetLocation.mkdir();
+ }
+ String[] children = sourceLocation.list();
+ for (int i=0; i<children.length; i++) {
+ copyFiles(new File(sourceLocation, children[i]),
+ new File(targetLocation, children[i]));
+ }
+ } else if (sourceLocation.exists()) {
+ InputStream in = new FileInputStream(sourceLocation);
+ OutputStream out = new FileOutputStream(targetLocation);
+
+ // Copy the bits from instream to outstream
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ in.close();
+ out.close();
+ }
+ return true;
+ }
+
+ private static AlertDialog createErrorDialog(Context c, String message,
+ DialogInterface.OnClickListener okListener) {
+ AlertDialog.Builder b = new AlertDialog.Builder(c)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(message);
+ if (okListener != null) {
+ b.setPositiveButton(R.string.vpn_back_button, okListener);
+ } else {
+ b.setPositiveButton(android.R.string.ok, null);
+ }
+ return b.create();
+ }
+
+ private Util() {
+ }
+}
diff --git a/src/com/android/settings/vpn/VpnEditor.java b/src/com/android/settings/vpn/VpnEditor.java
new file mode 100644
index 0000000..1d419ea
--- /dev/null
+++ b/src/com/android/settings/vpn/VpnEditor.java
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.vpn.L2tpIpsecProfile;
+import android.net.vpn.L2tpIpsecPskProfile;
+import android.net.vpn.L2tpProfile;
+import android.net.vpn.VpnProfile;
+import android.net.vpn.VpnType;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceGroup;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+/**
+ * The activity class for editing a new or existing VPN profile.
+ */
+public class VpnEditor extends PreferenceActivity {
+ private static final int MENU_SAVE = Menu.FIRST;
+ private static final int MENU_CANCEL = Menu.FIRST + 1;
+ private static final String KEY_PROFILE = "profile";
+ private static final String KEY_ORIGINAL_PROFILE_NAME = "orig_profile_name";
+
+ private VpnProfileEditor mProfileEditor;
+ private boolean mAddingProfile;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ VpnProfile p = (VpnProfile) ((savedInstanceState == null)
+ ? getIntent().getParcelableExtra(VpnSettings.KEY_VPN_PROFILE)
+ : savedInstanceState.getParcelable(KEY_PROFILE));
+ mProfileEditor = getEditor(p);
+ mAddingProfile = TextUtils.isEmpty(p.getName());
+
+ // Loads the XML preferences file
+ addPreferencesFromResource(R.xml.vpn_edit);
+
+ initViewFor(p);
+ }
+
+ @Override
+ protected synchronized void onSaveInstanceState(Bundle outState) {
+ if (mProfileEditor == null) return;
+
+ outState.putParcelable(KEY_PROFILE, getProfile());
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.add(0, MENU_SAVE, 0, R.string.vpn_menu_done)
+ .setIcon(android.R.drawable.ic_menu_save);
+ menu.add(0, MENU_CANCEL, 0,
+ mAddingProfile ? R.string.vpn_menu_cancel
+ : R.string.vpn_menu_revert)
+ .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_SAVE:
+ if (validateAndSetResult()) {
+ finish();
+ }
+ return true;
+ case MENU_CANCEL:
+ showCancellationConfirmDialog();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void initViewFor(VpnProfile profile) {
+ setTitle(profile);
+ mProfileEditor.loadPreferencesTo(getPreferenceScreen());
+ }
+
+ private void setTitle(VpnProfile profile) {
+ String formatString = mAddingProfile
+ ? getString(R.string.vpn_edit_title_add)
+ : getString(R.string.vpn_edit_title_edit);
+ setTitle(String.format(formatString,
+ profile.getType().getDisplayName()));
+ }
+
+ /**
+ * Checks the validity of the inputs and set the profile as result if valid.
+ * @return true if the result is successfully set
+ */
+ private boolean validateAndSetResult() {
+ String errorMsg = mProfileEditor.validate();
+
+ if (errorMsg != null) {
+ Util.showErrorMessage(this, errorMsg);
+ return false;
+ }
+
+ setResult(getProfile());
+ return true;
+ }
+
+ private void setResult(VpnProfile p) {
+ Intent intent = new Intent(this, VpnSettings.class);
+ intent.putExtra(VpnSettings.KEY_VPN_PROFILE, (Parcelable) p);
+ setResult(RESULT_OK, intent);
+ }
+
+ private VpnProfileEditor getEditor(VpnProfile p) {
+ switch (p.getType()) {
+ case L2TP_IPSEC:
+ return new L2tpIpsecEditor((L2tpIpsecProfile) p);
+
+ case L2TP_IPSEC_PSK:
+ return new L2tpIpsecPskEditor((L2tpIpsecPskProfile) p);
+
+ case L2TP:
+ return new L2tpEditor((L2tpProfile) p);
+
+ default:
+ return new VpnProfileEditor(p);
+ }
+ }
+
+ private void showCancellationConfirmDialog() {
+ new AlertDialog.Builder(this)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(mAddingProfile
+ ? R.string.vpn_confirm_add_profile_cancellation
+ : R.string.vpn_confirm_edit_profile_cancellation)
+ .setPositiveButton(R.string.vpn_yes_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int w) {
+ finish();
+ }
+ })
+ .setNegativeButton(R.string.vpn_mistake_button, null)
+ .show();
+ }
+
+ private VpnProfile getProfile() {
+ return mProfileEditor.getProfile();
+ }
+}
diff --git a/src/com/android/settings/vpn/VpnProfileActor.java b/src/com/android/settings/vpn/VpnProfileActor.java
new file mode 100644
index 0000000..1e71e86
--- /dev/null
+++ b/src/com/android/settings/vpn/VpnProfileActor.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import android.app.Dialog;
+import android.net.vpn.VpnProfile;
+import android.view.View;
+
+/**
+ * The interface to act on a {@link VpnProfile}.
+ */
+public interface VpnProfileActor {
+ VpnProfile getProfile();
+
+ /**
+ * Returns true if a connect dialog is needed before establishing a
+ * connection.
+ */
+ boolean isConnectDialogNeeded();
+
+ /**
+ * Creates the view in the connect dialog.
+ */
+ View createConnectView();
+
+ /**
+ * Updates the view in the connect dialog.
+ * @param dialog the recycled connect dialog.
+ */
+ void updateConnectView(Dialog dialog);
+
+ /**
+ * Validates the inputs in the dialog.
+ * @param dialog the connect dialog
+ * @return an error message if the inputs are not valid
+ */
+ String validateInputs(Dialog dialog);
+
+ /**
+ * Establishes a VPN connection.
+ * @param dialog the connect dialog
+ */
+ void connect(Dialog dialog);
+
+ /**
+ * Tears down the connection.
+ */
+ void disconnect();
+
+ /**
+ * Checks the current status. The result is expected to be broadcast.
+ * Use {@link VpnManager#registerConnectivityReceiver()} to register a
+ * broadcast receiver and to receives the broadcast events.
+ */
+ void checkStatus();
+}
diff --git a/src/com/android/settings/vpn/VpnProfileEditor.java b/src/com/android/settings/vpn/VpnProfileEditor.java
new file mode 100644
index 0000000..a1cdc76
--- /dev/null
+++ b/src/com/android/settings/vpn/VpnProfileEditor.java
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.net.vpn.VpnProfile;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.text.TextUtils;
+import android.text.method.PasswordTransformationMethod;
+
+/**
+ * The common class for editing {@link VpnProfile}.
+ */
+class VpnProfileEditor {
+ private static final String KEY_VPN_NAME = "vpn_name";
+
+ private EditTextPreference mName;
+ private EditTextPreference mServerName;
+ private EditTextPreference mDomainSuffices;
+ private VpnProfile mProfile;
+
+ public VpnProfileEditor(VpnProfile p) {
+ mProfile = p;
+ }
+
+ //@Override
+ public VpnProfile getProfile() {
+ return mProfile;
+ }
+
+ /**
+ * Adds the preferences to the panel. Subclasses should override
+ * {@link #loadExtraPreferencesTo(PreferenceGroup)} instead of this method.
+ */
+ public void loadPreferencesTo(PreferenceGroup subpanel) {
+ Context c = subpanel.getContext();
+
+ mName = (EditTextPreference) subpanel.findPreference(KEY_VPN_NAME);
+ mName.setOnPreferenceChangeListener(
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ setName((String) newValue);
+ return true;
+ }
+ });
+ setName(getProfile().getName());
+
+ subpanel.addPreference(createServerNamePreference(c));
+ loadExtraPreferencesTo(subpanel);
+ subpanel.addPreference(createDomainSufficesPreference(c));
+ }
+
+ /**
+ * Adds the extra preferences to the panel. Subclasses should add
+ * additional preferences in this method.
+ */
+ protected void loadExtraPreferencesTo(PreferenceGroup subpanel) {
+ }
+
+ /**
+ * Validates the inputs in the preferences.
+ *
+ * @return an error message that is ready to be displayed in a dialog; or
+ * null if all the inputs are valid
+ */
+ public String validate() {
+ String result = validate(mName, R.string.vpn_a_name);
+ return ((result != null)
+ ? result
+ : validate(mServerName, R.string.vpn_a_vpn_server));
+ }
+
+ /**
+ * Creates a preference for users to input domain suffices.
+ */
+ protected EditTextPreference createDomainSufficesPreference(Context c) {
+ mDomainSuffices = createEditTextPreference(c,
+ R.string.vpn_dns_search_list_title,
+ R.string.vpn_dns_search_list,
+ mProfile.getDomainSuffices(),
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ String v = ((String) newValue).trim();
+ mProfile.setDomainSuffices(v);
+ setSummary(pref, R.string.vpn_dns_search_list, v, false);
+ return true;
+ }
+ });
+ return mDomainSuffices;
+ }
+
+ private Preference createServerNamePreference(Context c) {
+ mServerName = createEditTextPreference(c,
+ R.string.vpn_vpn_server_title,
+ R.string.vpn_vpn_server,
+ mProfile.getServerName(),
+ new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(
+ Preference pref, Object newValue) {
+ String v = ((String) newValue).trim();
+ mProfile.setServerName(v);
+ setSummary(pref, R.string.vpn_vpn_server, v);
+ return true;
+ }
+ });
+ return mServerName;
+ }
+
+ protected EditTextPreference createEditTextPreference(Context c, int titleId,
+ int prefNameId, String value,
+ Preference.OnPreferenceChangeListener listener) {
+ EditTextPreference pref = new EditTextPreference(c);
+ pref.setTitle(titleId);
+ pref.setDialogTitle(titleId);
+ setSummary(pref, prefNameId, value);
+ pref.setText(value);
+ pref.setPersistent(true);
+ pref.setOnPreferenceChangeListener(listener);
+ return pref;
+ }
+
+ protected EditTextPreference createSecretPreference(Context c, int titleId,
+ int fieldNameId, String value,
+ Preference.OnPreferenceChangeListener listener) {
+ EditTextPreference pref = new EditTextPreference(c);
+ pref.setTitle(titleId);
+ pref.setDialogTitle(titleId);
+ pref.getEditText().setTransformationMethod(
+ new PasswordTransformationMethod());
+ pref.setText(value);
+ setSecretSummary(pref, fieldNameId, value);
+ pref.setPersistent(true);
+ pref.setOnPreferenceChangeListener(listener);
+ return pref;
+ }
+
+ protected String validate(Preference pref, int fieldNameId) {
+ Context c = pref.getContext();
+ String value = (pref instanceof EditTextPreference)
+ ? ((EditTextPreference) pref).getText()
+ : ((ListPreference) pref).getValue();
+ String formatString = (pref instanceof EditTextPreference)
+ ? c.getString(R.string.vpn_error_miss_entering)
+ : c.getString(R.string.vpn_error_miss_selecting);
+ return (TextUtils.isEmpty(value)
+ ? String.format(formatString, c.getString(fieldNameId))
+ : null);
+ }
+
+ protected void setSummary(Preference pref, int fieldNameId, String v) {
+ setSummary(pref, fieldNameId, v, true);
+ }
+
+ protected void setSummary(Preference pref, int fieldNameId, String v,
+ boolean required) {
+ Context c = pref.getContext();
+ String formatString = required
+ ? c.getString(R.string.vpn_field_not_set)
+ : c.getString(R.string.vpn_field_not_set_optional);
+ pref.setSummary(TextUtils.isEmpty(v)
+ ? String.format(formatString, c.getString(fieldNameId))
+ : v);
+ }
+
+ protected void setSecretSummary(Preference pref, int fieldNameId,
+ String value) {
+ Context c = pref.getContext();
+ String formatString = TextUtils.isEmpty(value)
+ ? c.getString(R.string.vpn_field_not_set)
+ : c.getString(R.string.vpn_field_is_set);
+ pref.setSummary(String.format(formatString, c.getString(fieldNameId)));
+ }
+
+ protected void setSecretTitle(
+ CheckBoxPreference pref, int fieldNameId, boolean enabled) {
+ Context c = pref.getContext();
+ String formatString = enabled
+ ? c.getString(R.string.vpn_disable_field)
+ : c.getString(R.string.vpn_enable_field);
+ pref.setTitle(String.format(formatString, c.getString(fieldNameId)));
+ }
+
+ private void setName(String newName) {
+ newName = (newName == null) ? "" : newName.trim();
+ mName.setText(newName);
+ getProfile().setName(newName);
+ setSummary(mName, R.string.vpn_name, newName);
+ }
+}
diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java
new file mode 100644
index 0000000..e429f9f
--- /dev/null
+++ b/src/com/android/settings/vpn/VpnSettings.java
@@ -0,0 +1,915 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+import com.android.settings.SecuritySettings;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.vpn.L2tpIpsecPskProfile;
+import android.net.vpn.L2tpProfile;
+import android.net.vpn.VpnManager;
+import android.net.vpn.VpnProfile;
+import android.net.vpn.VpnState;
+import android.net.vpn.VpnType;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.security.Keystore;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The preference activity for configuring VPN settings.
+ */
+public class VpnSettings extends PreferenceActivity implements
+ DialogInterface.OnClickListener {
+ // Key to the field exchanged for profile editing.
+ static final String KEY_VPN_PROFILE = "vpn_profile";
+
+ // Key to the field exchanged for VPN type selection.
+ static final String KEY_VPN_TYPE = "vpn_type";
+
+ private static final String TAG = VpnSettings.class.getSimpleName();
+
+ private static final String PREF_ADD_VPN = "add_new_vpn";
+ private static final String PREF_VPN_LIST = "vpn_list";
+
+ 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;
+
+ private static final int CONTEXT_MENU_CONNECT_ID = ContextMenu.FIRST + 0;
+ private static final int CONTEXT_MENU_DISCONNECT_ID = ContextMenu.FIRST + 1;
+ private static final int CONTEXT_MENU_EDIT_ID = ContextMenu.FIRST + 2;
+ private static final int CONTEXT_MENU_DELETE_ID = ContextMenu.FIRST + 3;
+
+ private static final int CONNECT_BUTTON = DialogInterface.BUTTON1;
+ private static final int OK_BUTTON = DialogInterface.BUTTON1;
+
+ private static final int DIALOG_CONNECT = 0;
+
+ private PreferenceScreen mAddVpn;
+ private PreferenceCategory mVpnListContainer;
+
+ // profile name --> VpnPreference
+ private Map<String, VpnPreference> mVpnPreferenceMap;
+ private List<VpnProfile> mVpnProfileList;
+
+ private int mIndexOfEditedProfile = -1;
+
+ // profile engaged in a connection
+ private VpnProfile mActiveProfile;
+
+ // actor engaged in connecting
+ private VpnProfileActor mConnectingActor;
+ private boolean mStateSaved = false;
+
+ // states saved for unlocking keystore
+ private Runnable mUnlockAction;
+
+ private VpnManager mVpnManager = new VpnManager(this);
+
+ private ConnectivityReceiver mConnectivityReceiver =
+ new ConnectivityReceiver();
+
+ private boolean mConnectingError;
+
+ private StatusChecker mStatusChecker = new StatusChecker();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.vpn_settings);
+
+ // restore VpnProfile list and construct VpnPreference map
+ mVpnListContainer = (PreferenceCategory) findPreference(PREF_VPN_LIST);
+
+ // set up the "add vpn" preference
+ mAddVpn = (PreferenceScreen) findPreference(PREF_ADD_VPN);
+ mAddVpn.setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference preference) {
+ startVpnTypeSelection();
+ return true;
+ }
+ });
+
+ // for long-press gesture on a profile preference
+ registerForContextMenu(getListView());
+
+ // listen to vpn connectivity event
+ mVpnManager.registerConnectivityReceiver(mConnectivityReceiver);
+
+ String profileName = (savedInstanceState == null)
+ ? null
+ : savedInstanceState.getString(STATE_ACTIVE_ACTOR);
+ mStateSaved = !TextUtils.isEmpty(profileName);
+ retrieveVpnListFromStorage();
+ if (mStateSaved) {
+ mConnectingActor =
+ getActor(mVpnPreferenceMap.get(profileName).mProfile);
+ } else {
+ checkVpnConnectionStatusInBackground();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mStatusChecker.onPause();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mStatusChecker.onResume();
+
+ if ((mUnlockAction != null) && isKeystoreUnlocked()) {
+ Runnable action = mUnlockAction;
+ mUnlockAction = null;
+ runOnUiThread(action);
+ }
+ }
+
+ @Override
+ protected synchronized void onSaveInstanceState(Bundle outState) {
+ if (mConnectingActor == null) return;
+
+ outState.putString(STATE_ACTIVE_ACTOR,
+ mConnectingActor.getProfile().getName());
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ unregisterForContextMenu(getListView());
+ mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver);
+ }
+
+ @Override
+ protected Dialog onCreateDialog (int id) {
+ switch (id) {
+ case DIALOG_CONNECT:
+ return createConnectDialog();
+
+ default:
+ return null;
+ }
+ }
+
+ private Dialog createConnectDialog() {
+ if (mConnectingActor == null) {
+ Log.e(TAG, "no connecting actor to create the dialog");
+ return null;
+ }
+ String name = (mConnectingActor == null)
+ ? getString(R.string.vpn_default_profile_name)
+ : mConnectingActor.getProfile().getName();
+ Dialog d = new AlertDialog.Builder(this)
+ .setView(mConnectingActor.createConnectView())
+ .setTitle(String.format(getString(R.string.vpn_connect_to),
+ name))
+ .setPositiveButton(getString(R.string.vpn_connect_button),
+ this)
+ .setNegativeButton(getString(android.R.string.cancel),
+ this)
+ .create();
+ return d;
+ }
+
+ @Override
+ protected void onPrepareDialog (int id, Dialog dialog) {
+ if (mStateSaved) {
+ mStateSaved = false;
+ super.onPrepareDialog(id, dialog);
+ } else if (mConnectingActor != null) {
+ mConnectingActor.updateConnectView(dialog);
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v,
+ ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+
+ VpnProfile p = getProfile(getProfilePositionFrom(
+ (AdapterContextMenuInfo) menuInfo));
+ if (p != null) {
+ VpnState state = p.getState();
+ menu.setHeaderTitle(p.getName());
+
+ boolean isIdle = (state == VpnState.IDLE);
+ boolean isNotConnect =
+ (isIdle || (state == VpnState.DISCONNECTING));
+ menu.add(0, CONTEXT_MENU_CONNECT_ID, 0, R.string.vpn_menu_connect)
+ .setEnabled(isIdle && (mActiveProfile == null));
+ menu.add(0, CONTEXT_MENU_DISCONNECT_ID, 0,
+ R.string.vpn_menu_disconnect)
+ .setEnabled(state == VpnState.CONNECTED);
+ menu.add(0, CONTEXT_MENU_EDIT_ID, 0, R.string.vpn_menu_edit)
+ .setEnabled(isNotConnect);
+ menu.add(0, CONTEXT_MENU_DELETE_ID, 0, R.string.vpn_menu_delete)
+ .setEnabled(isNotConnect);
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ int position = getProfilePositionFrom(
+ (AdapterContextMenuInfo) item.getMenuInfo());
+ VpnProfile p = getProfile(position);
+
+ switch(item.getItemId()) {
+ case CONTEXT_MENU_CONNECT_ID:
+ case CONTEXT_MENU_DISCONNECT_ID:
+ connectOrDisconnect(p);
+ return true;
+
+ case CONTEXT_MENU_EDIT_ID:
+ mIndexOfEditedProfile = position;
+ startVpnEditor(p);
+ return true;
+
+ case CONTEXT_MENU_DELETE_ID:
+ deleteProfile(position);
+ return true;
+ }
+
+ return super.onContextItemSelected(item);
+ }
+
+ @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;
+ }
+
+ if (requestCode == REQUEST_SELECT_VPN_TYPE) {
+ String typeName = data.getStringExtra(KEY_VPN_TYPE);
+ startVpnEditor(createVpnProfile(typeName));
+ } else if (requestCode == REQUEST_ADD_OR_EDIT_PROFILE) {
+ VpnProfile p = data.getParcelableExtra(KEY_VPN_PROFILE);
+ if (p == null) {
+ Log.e(TAG, "null object returned by editor");
+ return;
+ }
+
+ if (checkDuplicateName(p, index)) {
+ final VpnProfile profile = p;
+ Util.showErrorMessage(this, String.format(
+ getString(R.string.vpn_error_duplicate_name),
+ p.getName()),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int w) {
+ startVpnEditor(profile);
+ }
+ });
+ return;
+ }
+
+ if (needKeystoreToSave(p)) {
+ Runnable action = new Runnable() {
+ public void run() {
+ mIndexOfEditedProfile = index;
+ onActivityResult(requestCode, resultCode, data);
+ }
+ };
+ if (!unlockKeystore(p, action)) return;
+ }
+
+ try {
+ if ((index < 0) || (index >= mVpnProfileList.size())) {
+ addProfile(p);
+ Util.showShortToastMessage(this, String.format(
+ getString(R.string.vpn_profile_added), p.getName()));
+ } else {
+ replaceProfile(index, p);
+ Util.showShortToastMessage(this, String.format(
+ getString(R.string.vpn_profile_replaced),
+ p.getName()));
+ }
+ } catch (IOException e) {
+ final VpnProfile profile = p;
+ Util.showErrorMessage(this, e + ": " + e.getMessage(),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int w) {
+ startVpnEditor(profile);
+ }
+ });
+ }
+ } else {
+ throw new RuntimeException("unknown request code: " + requestCode);
+ }
+ }
+
+ // Called when the buttons on the connect dialog are clicked.
+ //@Override
+ public synchronized void onClick(DialogInterface dialog, int which) {
+ dismissDialog(DIALOG_CONNECT);
+ if (which == CONNECT_BUTTON) {
+ Dialog d = (Dialog) dialog;
+ String error = mConnectingActor.validateInputs(d);
+ if (error == null) {
+ changeState(mConnectingActor.getProfile(), VpnState.CONNECTING);
+ mConnectingActor.connect(d);
+ return;
+ } else {
+ // show error dialog
+ new AlertDialog.Builder(this)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(String.format(getString(
+ R.string.vpn_error_miss_entering), error))
+ .setPositiveButton(R.string.vpn_back_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ showDialog(DIALOG_CONNECT);
+ }
+ })
+ .show();
+ }
+ }
+ }
+
+ // 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) {
+ List<VpnProfile> list = mVpnProfileList;
+ VpnPreference pref = mVpnPreferenceMap.get(p.getName());
+ if ((pref != null) && (index >= 0) && (index < list.size())) {
+ // not a duplicate if p is to replace the profile at index
+ if (pref.mProfile == list.get(index)) pref = null;
+ }
+ return (pref != null);
+ }
+
+ private int getProfilePositionFrom(AdapterContextMenuInfo menuInfo) {
+ // excludes mVpnListContainer and the preferences above it
+ return menuInfo.position - mVpnListContainer.getOrder() - 1;
+ }
+
+ // position: position in mVpnProfileList
+ private VpnProfile getProfile(int position) {
+ return ((position >= 0) ? mVpnProfileList.get(position) : null);
+ }
+
+ // position: position in mVpnProfileList
+ private void deleteProfile(final int position) {
+ if ((position < 0) || (position >= mVpnProfileList.size())) return;
+ DialogInterface.OnClickListener onClickListener =
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ if (which == OK_BUTTON) {
+ VpnProfile p = mVpnProfileList.remove(position);
+ VpnPreference pref =
+ mVpnPreferenceMap.remove(p.getName());
+ mVpnListContainer.removePreference(pref);
+ removeProfileFromStorage(p);
+ }
+ }
+ };
+ new AlertDialog.Builder(this)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.vpn_confirm_profile_deletion)
+ .setPositiveButton(android.R.string.ok, onClickListener)
+ .setNegativeButton(R.string.vpn_no_button, onClickListener)
+ .show();
+ }
+
+ // Randomly generates an ID for the profile.
+ // The ID is unique and only set once when the profile is created.
+ private void setProfileId(VpnProfile profile) {
+ String id;
+
+ while (true) {
+ id = String.valueOf(Math.abs(
+ Double.doubleToLongBits(Math.random())));
+ if (id.length() >= 8) break;
+ }
+ for (VpnProfile p : mVpnProfileList) {
+ if (p.getId().equals(id)) {
+ setProfileId(profile);
+ return;
+ }
+ }
+ profile.setId(id);
+ }
+
+ private void addProfile(VpnProfile p) throws IOException {
+ setProfileId(p);
+ saveProfileToStorage(p);
+ mVpnProfileList.add(p);
+ addPreferenceFor(p);
+ disableProfilePreferencesIfOneActive();
+ }
+
+ // Adds a preference in mVpnListContainer
+ private void addPreferenceFor(VpnProfile p) {
+ VpnPreference pref = new VpnPreference(this, p);
+ mVpnPreferenceMap.put(p.getName(), pref);
+ mVpnListContainer.addPreference(pref);
+
+ pref.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference pref) {
+ connectOrDisconnect(((VpnPreference) pref).mProfile);
+ return true;
+ }
+ });
+ }
+
+ // index: index to mVpnProfileList
+ private void replaceProfile(int index, VpnProfile p) throws IOException {
+ Map<String, VpnPreference> map = mVpnPreferenceMap;
+ VpnProfile oldProfile = mVpnProfileList.set(index, p);
+ VpnPreference pref = map.remove(oldProfile.getName());
+ if (pref.mProfile != oldProfile) {
+ throw new RuntimeException("inconsistent state!");
+ }
+
+ p.setId(oldProfile.getId());
+
+ processSecrets(p);
+
+ // TODO: remove copyFiles once the setId() code propagates.
+ // Copy config files and remove the old ones if they are in different
+ // directories.
+ if (Util.copyFiles(getProfileDir(oldProfile), getProfileDir(p))) {
+ removeProfileFromStorage(oldProfile);
+ }
+ saveProfileToStorage(p);
+
+ pref.setProfile(p);
+ map.put(p.getName(), pref);
+ }
+
+ private void startVpnTypeSelection() {
+ Intent intent = new Intent(this, VpnTypeSelection.class);
+ startActivityForResult(intent, REQUEST_SELECT_VPN_TYPE);
+ }
+
+ private boolean isKeystoreUnlocked() {
+ return (Keystore.getInstance().getState() == Keystore.UNLOCKED);
+ }
+
+
+ // Returns true if the profile needs to access keystore
+ private boolean needKeystoreToSave(VpnProfile p) {
+ return needKeystoreToConnect(p);
+ }
+
+ // Returns true if the profile needs to access keystore
+ private boolean needKeystoreToEdit(VpnProfile p) {
+ switch (p.getType()) {
+ case L2TP_IPSEC:
+ case L2TP_IPSEC_PSK:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ // Returns true if the profile needs to access keystore
+ private boolean needKeystoreToConnect(VpnProfile p) {
+ switch (p.getType()) {
+ case L2TP_IPSEC:
+ case L2TP_IPSEC_PSK:
+ return true;
+
+ case L2TP:
+ return ((L2tpProfile) p).isSecretEnabled();
+
+ default:
+ return false;
+ }
+ }
+
+ // Returns true if keystore is unlocked or keystore is not a concern
+ private boolean unlockKeystore(VpnProfile p, Runnable action) {
+ if (isKeystoreUnlocked()) return true;
+ mUnlockAction = action;
+ startActivity(
+ new Intent(SecuritySettings.ACTION_UNLOCK_CREDENTIAL_STORAGE));
+ return false;
+ }
+
+ private void startVpnEditor(final VpnProfile profile) {
+ if (needKeystoreToEdit(profile)) {
+ Runnable action = new Runnable() {
+ public void run() {
+ startVpnEditor(profile);
+ }
+ };
+ if (!unlockKeystore(profile, action)) return;
+ }
+
+ Intent intent = new Intent(this, VpnEditor.class);
+ intent.putExtra(KEY_VPN_PROFILE, (Parcelable) profile);
+ startActivityForResult(intent, REQUEST_ADD_OR_EDIT_PROFILE);
+ }
+
+ private synchronized void connect(final VpnProfile p) {
+ if (needKeystoreToConnect(p)) {
+ Runnable action = new Runnable() {
+ public void run() {
+ connect(p);
+ }
+ };
+ if (!unlockKeystore(p, action)) return;
+ }
+
+ mConnectingActor = getActor(p);
+ if (mConnectingActor.isConnectDialogNeeded()) {
+ removeDialog(DIALOG_CONNECT);
+ showDialog(DIALOG_CONNECT);
+ } else {
+ changeState(p, VpnState.CONNECTING);
+ mConnectingActor.connect(null);
+ }
+ }
+
+ // Do connect or disconnect based on the current state.
+ private synchronized void connectOrDisconnect(VpnProfile p) {
+ VpnPreference pref = mVpnPreferenceMap.get(p.getName());
+ switch (p.getState()) {
+ case IDLE:
+ connect(p);
+ break;
+
+ case CONNECTING:
+ // do nothing
+ break;
+
+ case CONNECTED:
+ mConnectingError = false;
+ // pass through
+ case DISCONNECTING:
+ changeState(p, VpnState.DISCONNECTING);
+ getActor(p).disconnect();
+ break;
+ }
+ }
+
+ private void changeState(VpnProfile p, VpnState state) {
+ VpnState oldState = p.getState();
+ if (oldState == state) return;
+
+ p.setState(state);
+ mVpnPreferenceMap.get(p.getName()).setSummary(
+ getProfileSummaryString(p));
+
+ switch (state) {
+ case CONNECTED:
+ mConnectingActor = null;
+ // pass through
+ case CONNECTING:
+ mActiveProfile = p;
+ disableProfilePreferencesIfOneActive();
+ break;
+
+ case DISCONNECTING:
+ if (oldState == VpnState.CONNECTING) {
+ mConnectingError = true;
+ }
+ break;
+
+ case CANCELLED:
+ changeState(p, VpnState.IDLE);
+ break;
+
+ case IDLE:
+ assert(mActiveProfile != p);
+ mActiveProfile = null;
+ mConnectingActor = null;
+ enableProfilePreferences();
+
+ if (oldState == VpnState.CONNECTING) mConnectingError = true;
+ if (mConnectingError) showReconnectDialog(p);
+ break;
+ }
+ }
+
+ private void showReconnectDialog(final VpnProfile p) {
+ new AlertDialog.Builder(this)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.vpn_confirm_reconnect)
+ .setPositiveButton(R.string.vpn_yes_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int w) {
+ dialog.dismiss();
+ connectOrDisconnect(p);
+ }
+ })
+ .setNegativeButton(R.string.vpn_no_button, null)
+ .show();
+ }
+
+ private void disableProfilePreferencesIfOneActive() {
+ if (mActiveProfile == null) return;
+
+ for (VpnProfile p : mVpnProfileList) {
+ switch (p.getState()) {
+ case DISCONNECTING:
+ case IDLE:
+ mVpnPreferenceMap.get(p.getName()).setEnabled(false);
+ break;
+
+ default:
+ mVpnPreferenceMap.get(p.getName()).setEnabled(true);
+ }
+ }
+ }
+
+ private void enableProfilePreferences() {
+ for (VpnProfile p : mVpnProfileList) {
+ mVpnPreferenceMap.get(p.getName()).setEnabled(true);
+ }
+ }
+
+ static String getProfileDir(VpnProfile p) {
+ return PROFILES_ROOT + p.getId();
+ }
+
+ static void saveProfileToStorage(VpnProfile p) throws IOException {
+ File f = new File(getProfileDir(p));
+ if (!f.exists()) f.mkdirs();
+ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
+ new File(f, PROFILE_OBJ_FILE)));
+ oos.writeObject(p);
+ oos.close();
+ }
+
+ private void removeProfileFromStorage(VpnProfile p) {
+ Util.deleteFile(getProfileDir(p));
+ }
+
+ private void retrieveVpnListFromStorage() {
+ mVpnPreferenceMap = new LinkedHashMap<String, VpnPreference>();
+ mVpnProfileList = Collections.synchronizedList(
+ new ArrayList<VpnProfile>());
+ mVpnListContainer.removeAll();
+
+ File root = new File(PROFILES_ROOT);
+ String[] dirs = root.list();
+ if (dirs == null) return;
+ for (String dir : dirs) {
+ File f = new File(new File(root, dir), PROFILE_OBJ_FILE);
+ if (!f.exists()) continue;
+ try {
+ VpnProfile p = deserialize(f);
+ if (p == null) continue;
+ if (!checkIdConsistency(dir, p)) continue;
+
+ mVpnProfileList.add(p);
+ } catch (IOException e) {
+ Log.e(TAG, "retrieveVpnListFromStorage()", e);
+ }
+ }
+ Collections.sort(mVpnProfileList, new Comparator<VpnProfile>() {
+ public int compare(VpnProfile p1, VpnProfile p2) {
+ return p1.getName().compareTo(p2.getName());
+ }
+
+ public boolean equals(VpnProfile p) {
+ // not used
+ return false;
+ }
+ });
+ for (VpnProfile p : mVpnProfileList) addPreferenceFor(p);
+ disableProfilePreferencesIfOneActive();
+ }
+
+ private void checkVpnConnectionStatusInBackground() {
+ mStatusChecker.check(mVpnProfileList);
+ }
+
+ // A sanity check. Returns true if the profile directory name and profile ID
+ // are consistent.
+ private boolean checkIdConsistency(String dirName, VpnProfile p) {
+ if (!dirName.equals(p.getId())) {
+ Log.d(TAG, "ID inconsistent: " + dirName + " vs " + p.getId());
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private VpnProfile deserialize(File profileObjectFile) throws IOException {
+ try {
+ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
+ profileObjectFile));
+ VpnProfile p = (VpnProfile) ois.readObject();
+ ois.close();
+ return p;
+ } catch (ClassNotFoundException e) {
+ Log.d(TAG, "deserialize a profile", e);
+ return null;
+ }
+ }
+
+ private String getProfileSummaryString(VpnProfile p) {
+ switch (p.getState()) {
+ case CONNECTING:
+ return getString(R.string.vpn_connecting);
+ case DISCONNECTING:
+ return getString(R.string.vpn_disconnecting);
+ case CONNECTED:
+ return getString(R.string.vpn_connected);
+ default:
+ return getString(R.string.vpn_connect_hint);
+ }
+ }
+
+ private VpnProfileActor getActor(VpnProfile p) {
+ return new AuthenticationActor(this, p);
+ }
+
+ private VpnProfile createVpnProfile(String type) {
+ 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 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 presharedKey = pskProfile.getPresharedKey();
+ if (!presharedKey.equals(keyName)) {
+ ks.put(NAMESPACE_VPN, keyName, presharedKey);
+ pskProfile.setPresharedKey(NAMESPACE_VPN + "_" + keyName);
+ }
+ // pass through
+
+ case L2TP:
+ L2tpProfile l2tpProfile = (L2tpProfile) p;
+ keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
+ String secret = l2tpProfile.getSecretString();
+ if (l2tpProfile.isSecretEnabled()) {
+ if (!secret.equals(keyName)) {
+ ks.put(NAMESPACE_VPN, keyName, secret);
+ l2tpProfile.setSecretString(
+ NAMESPACE_VPN + "_" + keyName);
+ }
+ } else {
+ ks.remove(NAMESPACE_VPN, keyName);
+ }
+ break;
+ }
+ }
+
+ private class VpnPreference extends Preference {
+ VpnProfile mProfile;
+ VpnPreference(Context c, VpnProfile p) {
+ super(c);
+ setProfile(p);
+ }
+
+ void setProfile(VpnProfile p) {
+ mProfile = p;
+ setTitle(p.getName());
+ setSummary(getProfileSummaryString(p));
+ }
+ }
+
+ // to receive vpn connectivity events broadcast by VpnService
+ private class ConnectivityReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String profileName = intent.getStringExtra(
+ VpnManager.BROADCAST_PROFILE_NAME);
+ if (profileName == null) return;
+
+ VpnState s = (VpnState) intent.getSerializableExtra(
+ VpnManager.BROADCAST_CONNECTION_STATE);
+ if (s == null) {
+ Log.e(TAG, "received null connectivity state");
+ return;
+ }
+ VpnPreference pref = mVpnPreferenceMap.get(profileName);
+ if (pref != null) {
+ Log.d(TAG, "received connectivity: " + profileName
+ + ": connected? " + s);
+ changeState(pref.mProfile, s);
+ } else {
+ Log.e(TAG, "received connectivity: " + profileName
+ + ": connected? " + s + ", but profile does not exist;"
+ + " just ignore it");
+ }
+ }
+ }
+
+ // managing status check in a background thread
+ private class StatusChecker {
+ private Set<VpnProfile> mQueue = new HashSet<VpnProfile>();
+ private boolean mPaused;
+ private ConditionVariable mThreadCv = new ConditionVariable();
+
+ void onPause() {
+ mPaused = true;
+ mThreadCv.block(); // until the checking thread is over
+ }
+
+ synchronized void onResume() {
+ mPaused = false;
+ 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 void start() {
+ mThreadCv.close();
+ new Thread(new Runnable() {
+ public void run() {
+ while (true) {
+ VpnProfile p = next();
+ if (p == null) break;
+ getActor(p).checkStatus();
+ }
+ mThreadCv.open();
+ }
+ }).start();
+ }
+ }
+}
diff --git a/src/com/android/settings/vpn/VpnTypeSelection.java b/src/com/android/settings/vpn/VpnTypeSelection.java
new file mode 100644
index 0000000..e74fb43
--- /dev/null
+++ b/src/com/android/settings/vpn/VpnTypeSelection.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.vpn;
+
+import com.android.settings.R;
+
+import android.content.Intent;
+import android.net.vpn.VpnManager;
+import android.net.vpn.VpnType;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The activity to select a VPN type.
+ */
+public class VpnTypeSelection extends PreferenceActivity {
+ private Map<String, VpnType> mTypeMap = new HashMap<String, VpnType>();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.vpn_type);
+ initTypeList();
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen ps, Preference pref) {
+ setResult(mTypeMap.get(pref.getTitle().toString()));
+ finish();
+ return true;
+ }
+
+ private void initTypeList() {
+ PreferenceScreen root = getPreferenceScreen();
+ for (VpnType t : VpnManager.getSupportedVpnTypes()) {
+ String displayName = t.getDisplayName();
+ String message = String.format(
+ getString(R.string.vpn_edit_title_add), displayName);
+ mTypeMap.put(message, t);
+
+ Preference pref = new Preference(this);
+ pref.setTitle(message);
+ pref.setSummary(t.getDescription());
+ root.addPreference(pref);
+ }
+ }
+
+ private void setResult(VpnType type) {
+ Intent intent = new Intent(this, VpnSettings.class);
+ intent.putExtra(VpnSettings.KEY_VPN_TYPE, type.toString());
+ setResult(RESULT_OK, intent);
+ }
+}
diff --git a/src/com/android/settings/widget/SettingsAppWidgetProvider.java b/src/com/android/settings/widget/SettingsAppWidgetProvider.java
new file mode 100644
index 0000000..d8747c9
--- /dev/null
+++ b/src/com/android/settings/widget/SettingsAppWidgetProvider.java
@@ -0,0 +1,403 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.widget;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.bluetooth.BluetoothDevice;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.IContentService;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.location.LocationManager;
+import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.net.wifi.WifiManager;
+import android.os.IHardwareService;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.util.Log;
+import android.widget.RemoteViews;
+import com.android.settings.R;
+import com.android.settings.bluetooth.LocalBluetoothManager;
+
+/**
+ * Provides control of power-related settings from a widget.
+ */
+public class SettingsAppWidgetProvider extends AppWidgetProvider {
+ static final String TAG = "SettingsAppWidgetProvider";
+
+ static final ComponentName THIS_APPWIDGET =
+ new ComponentName("com.android.settings",
+ "com.android.settings.widget.SettingsAppWidgetProvider");
+
+ private static LocalBluetoothManager mLocalBluetoothManager = null;
+
+ private static final int BUTTON_WIFI = 0;
+ private static final int BUTTON_BRIGHTNESS = 1;
+ private static final int BUTTON_SYNC = 2;
+ private static final int BUTTON_GPS = 3;
+ private static final int BUTTON_BLUETOOTH = 4;
+
+ private static final int STATE_DISABLED = 0;
+ private static final int STATE_ENABLED = 1;
+ private static final int STATE_INTERMEDIATE = 2;
+
+ /**
+ * Minimum and maximum brightnesses. Don't go to 0 since that makes the display unusable
+ */
+ private static final int MINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 10;
+ private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;
+ private static final int DEFAULT_BACKLIGHT = (int) (android.os.Power.BRIGHTNESS_ON * 0.4f);
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager,
+ int[] appWidgetIds) {
+ // Update each requested appWidgetId
+ RemoteViews view = buildUpdate(context, -1);
+
+ for (int i = 0; i < appWidgetIds.length; i++) {
+ appWidgetManager.updateAppWidget(appWidgetIds[i], view);
+ }
+ }
+
+ @Override
+ public void onEnabled(Context context) {
+ PackageManager pm = context.getPackageManager();
+ pm.setComponentEnabledSetting(
+ new ComponentName("com.android.settings", ".widget.SettingsAppWidgetProvider"),
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+
+ @Override
+ public void onDisabled(Context context) {
+ Class clazz = com.android.settings.widget.SettingsAppWidgetProvider.class;
+ PackageManager pm = context.getPackageManager();
+ pm.setComponentEnabledSetting(
+ new ComponentName("com.android.settings", ".widget.SettingsAppWidgetProvider"),
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+
+ /**
+ * Load image for given widget and build {@link RemoteViews} for it.
+ */
+ static RemoteViews buildUpdate(Context context, int appWidgetId) {
+ RemoteViews views = new RemoteViews(context.getPackageName(),
+ R.layout.widget);
+ views.setOnClickPendingIntent(R.id.btn_wifi, getLaunchPendingIntent(context, appWidgetId,
+ BUTTON_WIFI));
+ views.setOnClickPendingIntent(R.id.btn_brightness,
+ getLaunchPendingIntent(context,
+ appWidgetId, BUTTON_BRIGHTNESS));
+ views.setOnClickPendingIntent(R.id.btn_sync,
+ getLaunchPendingIntent(context,
+ appWidgetId, BUTTON_SYNC));
+ views.setOnClickPendingIntent(R.id.btn_gps,
+ getLaunchPendingIntent(context, appWidgetId, BUTTON_GPS));
+ views.setOnClickPendingIntent(R.id.btn_bluetooth,
+ getLaunchPendingIntent(context,
+ appWidgetId, BUTTON_BLUETOOTH));
+
+ updateButtons(views, context);
+ return views;
+ }
+
+ /**
+ * Updates the widget when something changes, or when a button is pushed.
+ *
+ * @param context
+ */
+ public static void updateWidget(Context context) {
+ RemoteViews views = buildUpdate(context, -1);
+ // Update specific list of appWidgetIds if given, otherwise default to all
+ final AppWidgetManager gm = AppWidgetManager.getInstance(context);
+ gm.updateAppWidget(THIS_APPWIDGET, views);
+ }
+
+ /**
+ * Updates the buttons based on the underlying states of wifi, etc.
+ *
+ * @param views The RemoteViews to update.
+ * @param context
+ */
+ private static void updateButtons(RemoteViews views, Context context) {
+ switch (getWifiState(context)) {
+ case STATE_DISABLED:
+ views.setImageViewResource(R.id.btn_wifi, R.drawable.widget_btn_wifi_off);
+ break;
+ case STATE_ENABLED:
+ views.setImageViewResource(R.id.btn_wifi, R.drawable.widget_btn_wifi);
+ break;
+ case STATE_INTERMEDIATE:
+ views.setImageViewResource(R.id.btn_wifi, R.drawable.widget_btn_wifi_gray);
+ break;
+ }
+ if (getBrightness(context)) {
+ views.setImageViewResource(R.id.btn_brightness, R.drawable.widget_btn_brightness);
+ } else {
+ views.setImageViewResource(R.id.btn_brightness, R.drawable.widget_btn_brightness_off);
+ }
+ if (getBackgroundDataState(context)) {
+ views.setImageViewResource(R.id.btn_sync, R.drawable.widget_btn_sync);
+ } else {
+ views.setImageViewResource(R.id.btn_sync, R.drawable.widget_btn_sync_off);
+ }
+ if (getGpsState(context)) {
+ views.setImageViewResource(R.id.btn_gps, R.drawable.widget_btn_gps);
+ } else {
+ views.setImageViewResource(R.id.btn_gps, R.drawable.widget_btn_gps_off);
+ }
+ switch (getBluetoothState(context)) {
+ case STATE_DISABLED:
+ views.setImageViewResource(R.id.btn_bluetooth, R.drawable.widget_btn_bluetooth_off);
+ break;
+ case STATE_ENABLED:
+ views.setImageViewResource(R.id.btn_bluetooth, R.drawable.widget_btn_bluetooth);
+ break;
+ case STATE_INTERMEDIATE:
+ views.setImageViewResource(R.id.btn_bluetooth, R.drawable.widget_btn_bluetooth_gray);
+ break;
+ }
+ }
+
+ /**
+ * Creates PendingIntent to notify the widget of a button click.
+ *
+ * @param context
+ * @param appWidgetId
+ * @return
+ */
+ private static PendingIntent getLaunchPendingIntent(Context context, int appWidgetId, int buttonId) {
+ Intent launchIntent = new Intent();
+ launchIntent.setClass(context, SettingsAppWidgetProvider.class);
+ launchIntent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ launchIntent.setData(Uri.parse("custom:" + buttonId));
+ PendingIntent pi = PendingIntent.getBroadcast(context, 0 /* no requestCode */,
+ launchIntent, 0 /* no flags */);
+ return pi;
+ }
+
+ /**
+ * Receives and processes a button pressed intent or state change.
+ *
+ * @param context
+ * @param intent Indicates the pressed button.
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ super.onReceive(context, intent);
+ if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
+ Uri data = intent.getData();
+ int buttonId = Integer.parseInt(data.getSchemeSpecificPart());
+ if (buttonId == BUTTON_WIFI) {
+ toggleWifi(context);
+ } else if (buttonId == BUTTON_BRIGHTNESS) {
+ toggleBrightness(context);
+ } else if (buttonId == BUTTON_SYNC) {
+ toggleBackgroundData(context);
+ } else if (buttonId == BUTTON_GPS) {
+ toggleGps(context);
+ } else if (buttonId == BUTTON_BLUETOOTH) {
+ toggleBluetooth(context);
+ }
+ }
+ // State changes fall through
+ updateWidget(context);
+ }
+
+ /**
+ * Gets the state of Wi-Fi
+ *
+ * @param context
+ * @return STATE_ENABLED, STATE_DISABLED, or STATE_INTERMEDIATE
+ */
+ private static int getWifiState(Context context) {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ int wifiState = wifiManager.getWifiState();
+ if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
+ return STATE_DISABLED;
+ } else if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
+ return STATE_ENABLED;
+ } else {
+ return STATE_INTERMEDIATE;
+ }
+ }
+
+ /**
+ * Toggles the state of Wi-Fi
+ *
+ * @param context
+ */
+ private void toggleWifi(Context context) {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ int wifiState = getWifiState(context);
+ if (wifiState == STATE_ENABLED) {
+ wifiManager.setWifiEnabled(false);
+ } else if (wifiState == STATE_DISABLED) {
+ wifiManager.setWifiEnabled(true);
+ }
+ }
+
+ /**
+ * Gets the state of background data.
+ *
+ * @param context
+ * @return true if enabled
+ */
+ private static boolean getBackgroundDataState(Context context) {
+ ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ return connManager.getBackgroundDataSetting();
+ }
+
+ /**
+ * Toggle background data and sync tickles.
+ *
+ * @param context
+ */
+ private void toggleBackgroundData(Context context) {
+ ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ boolean sync = getBackgroundDataState(context);
+ connManager.setBackgroundDataSetting(!sync);
+
+ IContentService contentService = ContentResolver.getContentService();
+ try {
+ contentService.setListenForNetworkTickles(!sync);
+ } catch (RemoteException e) {
+ Log.d(TAG, "toggleBackgroundData: " + e);
+ }
+ }
+
+ /**
+ * Gets the state of GPS location.
+ *
+ * @param context
+ * @return true if enabled.
+ */
+ private static boolean getGpsState(Context context) {
+ ContentResolver resolver = context.getContentResolver();
+ return Settings.Secure.isLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER);
+ }
+
+ /**
+ * Toggles the state of GPS.
+ *
+ * @param context
+ */
+ private void toggleGps(Context context) {
+ ContentResolver resolver = context.getContentResolver();
+ boolean enabled = getGpsState(context);
+ Settings.Secure.setLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER, !enabled);
+ }
+
+ /**
+ * Gets state of brightness.
+ *
+ * @param context
+ * @return true if more than moderately bright.
+ */
+ private static boolean getBrightness(Context context) {
+ try {
+ IHardwareService hardware = IHardwareService.Stub.asInterface(
+ ServiceManager.getService("hardware"));
+ if (hardware != null) {
+ int brightness = Settings.System.getInt(context.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS);
+ return brightness > 100;
+ }
+ } catch (Exception e) {
+ Log.d(TAG, "getBrightness: " + e);
+ }
+ return false;
+ }
+
+ /**
+ * Increases or decreases the brightness.
+ *
+ * @param context
+ */
+ private void toggleBrightness(Context context) {
+ try {
+ IHardwareService hardware = IHardwareService.Stub.asInterface(
+ ServiceManager.getService("hardware"));
+ if (hardware != null) {
+ ContentResolver cr = context.getContentResolver();
+ int brightness = Settings.System.getInt(cr,
+ Settings.System.SCREEN_BRIGHTNESS);
+ // Rotate MINIMUM -> DEFAULT -> MAXIMUM
+ // Technically, not a toggle...
+ if (brightness < DEFAULT_BACKLIGHT) {
+ brightness = DEFAULT_BACKLIGHT;
+ } else if (brightness < MAXIMUM_BACKLIGHT) {
+ brightness = MAXIMUM_BACKLIGHT;
+ } else {
+ brightness = MINIMUM_BACKLIGHT;
+ }
+ hardware.setBacklights(brightness);
+ Settings.System.putInt(cr, Settings.System.SCREEN_BRIGHTNESS, brightness);
+ brightness = Settings.System.getInt(cr,
+ Settings.System.SCREEN_BRIGHTNESS);
+ }
+ } catch (RemoteException e) {
+ Log.d(TAG, "toggleBrightness: " + e);
+ } catch (Settings.SettingNotFoundException e) {
+ Log.d(TAG, "toggleBrightness: " + e);
+ }
+ }
+
+ /**
+ * Gets state of bluetooth
+ *
+ * @param context
+ * @return STATE_ENABLED, STATE_DISABLED, or STATE_INTERMEDIATE
+ */
+ private static int getBluetoothState(Context context) {
+ if (mLocalBluetoothManager == null) {
+ mLocalBluetoothManager = LocalBluetoothManager.getInstance(context);
+ if (mLocalBluetoothManager == null) {
+ return STATE_INTERMEDIATE; // On emulator?
+ }
+ }
+ int state = mLocalBluetoothManager.getBluetoothState();
+ if (state == BluetoothDevice.BLUETOOTH_STATE_OFF) {
+ return STATE_DISABLED;
+ } else if (state == BluetoothDevice.BLUETOOTH_STATE_ON) {
+ return STATE_ENABLED;
+ } else {
+ return STATE_INTERMEDIATE;
+ }
+ }
+
+ /**
+ * Toggles the state of bluetooth
+ *
+ * @param context
+ */
+ private void toggleBluetooth(Context context) {
+ int state = getBluetoothState(context);
+ if (state == STATE_ENABLED) {
+ mLocalBluetoothManager.setBluetoothEnabled(false);
+ } else if (state == STATE_DISABLED) {
+ mLocalBluetoothManager.setBluetoothEnabled(true);
+ }
+ }
+}
diff --git a/src/com/android/settings/wifi/AccessPointDialog.java b/src/com/android/settings/wifi/AccessPointDialog.java
index 919f7fc..c9f511b 100644
--- a/src/com/android/settings/wifi/AccessPointDialog.java
+++ b/src/com/android/settings/wifi/AccessPointDialog.java
@@ -17,10 +17,15 @@
package com.android.settings.wifi;
import com.android.settings.R;
+import com.android.settings.SecuritySettings;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.security.CertTool;
+import android.security.Keystore;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -71,12 +76,16 @@
private static final int SECURITY_WEP = 2;
private static final int SECURITY_WPA_PERSONAL = 3;
private static final int SECURITY_WPA2_PERSONAL = 4;
+ private static final int SECURITY_WPA_EAP = 5;
+ private static final int SECURITY_IEEE8021X = 6;
private static final int[] WEP_TYPE_VALUES = {
AccessPointState.WEP_PASSWORD_AUTO, AccessPointState.WEP_PASSWORD_ASCII,
AccessPointState.WEP_PASSWORD_HEX
};
-
+ private static final String NOT_APPLICABLE = "N/A";
+ private static final String BLOB_HEADER = "blob://";
+
// Button positions, default to impossible values
private int mConnectButtonPos = Integer.MAX_VALUE;
private int mForgetButtonPos = Integer.MAX_VALUE;
@@ -92,22 +101,45 @@
// General views
private View mView;
+ private View mEnterpriseView;
private TextView mPasswordText;
private EditText mPasswordEdit;
private CheckBox mShowPasswordCheckBox;
+
+ // Enterprise fields
+ private TextView mEapText;
+ private Spinner mEapSpinner;
+ private TextView mPhase2Text;
+ private Spinner mPhase2Spinner;
+ private TextView mIdentityText;
+ private EditText mIdentityEdit;
+ private TextView mAnonymousIdentityText;
+ private EditText mAnonymousIdentityEdit;
+ private TextView mCaCertText;
+ private Spinner mCaCertSpinner;
+ private TextView mClientCertText;
+ private Spinner mClientCertSpinner;
+ private TextView mPrivateKeyPasswdText;
+ private EditText mPrivateKeyPasswdEdit;
+ private EditText[] mEnterpriseTextFields;
+
// Info-specific views
private ViewGroup mTable;
// Configure-specific views
private EditText mSsidEdit;
+ private TextView mSsidText;
+ private TextView mSecurityText;
private Spinner mSecuritySpinner;
private Spinner mWepTypeSpinner;
+ private CertTool mCertTool;
public AccessPointDialog(Context context, WifiLayer wifiLayer) {
super(context);
mWifiLayer = wifiLayer;
+ mCertTool = CertTool.getInstance();
}
@Override
@@ -208,9 +240,17 @@
positiveButtonResId = R.string.wifi_save_config;
mSaveButtonPos = POSITIVE_BUTTON;
-
+
+ setEnterpriseFieldsVisible(false);
+
} else if (mMode == MODE_INFO) {
- setLayout(R.layout.wifi_ap_info);
+ if (mState.isEnterprise() && !mState.configured) {
+ setLayout(R.layout.wifi_ap_configure);
+ defaultPasswordVisibility = false;
+ setEnterpriseFieldsVisible(true);
+ } else {
+ setLayout(R.layout.wifi_ap_info);
+ }
if (mState.isConnectable()) {
if (mCustomTitle == null) {
@@ -255,37 +295,114 @@
private void onReferenceViews(View view) {
mPasswordText = (TextView) view.findViewById(R.id.password_text);
mPasswordEdit = (EditText) view.findViewById(R.id.password_edit);
-
+ mSsidText = (TextView) view.findViewById(R.id.ssid_text);
+ mSsidEdit = (EditText) view.findViewById(R.id.ssid_edit);
+ mSecurityText = (TextView) view.findViewById(R.id.security_text);
+ mSecuritySpinner = (Spinner) view.findViewById(R.id.security_spinner);
+ mWepTypeSpinner = (Spinner) view.findViewById(R.id.wep_type_spinner);
+ mEnterpriseView = mView.findViewById(R.id.enterprise_wrapper);
+
mShowPasswordCheckBox = (CheckBox) view.findViewById(R.id.show_password_checkbox);
if (mShowPasswordCheckBox != null) {
mShowPasswordCheckBox.setOnClickListener(this);
}
-
if (mMode == MODE_CONFIGURE) {
- mSsidEdit = (EditText) view.findViewById(R.id.ssid_edit);
- mSecuritySpinner = (Spinner) view.findViewById(R.id.security_spinner);
mSecuritySpinner.setOnItemSelectedListener(this);
- setSecuritySpinnerAdapter();
- mWepTypeSpinner = (Spinner) view.findViewById(R.id.wep_type_spinner);
-
+ mSecuritySpinner.setPromptId(R.string.security);
+ setSpinnerAdapter(mSecuritySpinner, mAutoSecurityAllowed ?
+ R.array.wifi_security_entries
+ : R.array.wifi_security_without_auto_entries);
} else if (mMode == MODE_INFO) {
mTable = (ViewGroup) view.findViewById(R.id.table);
}
-
+ /* for enterprise one */
+ if (mMode == MODE_CONFIGURE ||
+ (mState.isEnterprise() && !mState.configured)) {
+ setEnterpriseFields(view);
+ mEapSpinner.setSelection(getSelectionIndex(
+ R.array.wifi_eap_entries, mState.getEap()));
+ mClientCertSpinner.setSelection(getSelectionIndex(
+ getAllUserCertificateKeys(), mState.getEnterpriseField(
+ AccessPointState.CLIENT_CERT)));
+ mCaCertSpinner.setSelection(getSelectionIndex(
+ getAllCaCertificateKeys(), mState.getEnterpriseField(
+ AccessPointState.CA_CERT)));
+ }
}
-
- private void setSecuritySpinnerAdapter() {
- Context context = getContext();
- int arrayResId = mAutoSecurityAllowed ? R.array.wifi_security_entries
- : R.array.wifi_security_without_auto_entries;
- ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(context,
- android.R.layout.simple_spinner_item,
- context.getResources().getStringArray(arrayResId));
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mSecuritySpinner.setAdapter(adapter);
+ private String[] getAllCaCertificateKeys() {
+ return appendEmptyInSelection(mCertTool.getAllCaCertificateKeys());
}
-
+
+ private String[] getAllUserCertificateKeys() {
+ return appendEmptyInSelection(mCertTool.getAllUserCertificateKeys());
+ }
+
+ private String[] appendEmptyInSelection(String[] keys) {
+ String[] selections = new String[keys.length + 1];
+ System.arraycopy(keys, 0, selections, 0, keys.length);
+ selections[keys.length] = NOT_APPLICABLE;
+ return selections;
+ }
+
+ private void setEnterpriseFields(View view) {
+ mIdentityText = (TextView) view.findViewById(R.id.identity_text);
+ mIdentityEdit = (EditText) view.findViewById(R.id.identity_edit);
+ mAnonymousIdentityText =
+ (TextView) view.findViewById(R.id.anonymous_identity_text);
+ mAnonymousIdentityEdit =
+ (EditText) view.findViewById(R.id.anonymous_identity_edit);
+ mClientCertText =
+ (TextView) view.findViewById(R.id.client_certificate_text);
+ mCaCertText = (TextView) view.findViewById(R.id.ca_certificate_text);
+ mPrivateKeyPasswdEdit =
+ (EditText) view.findViewById(R.id.private_key_passwd_edit);
+ mEapText = (TextView) view.findViewById(R.id.eap_text);
+ mEapSpinner = (Spinner) view.findViewById(R.id.eap_spinner);
+ mEapSpinner.setOnItemSelectedListener(this);
+ mEapSpinner.setPromptId(R.string.please_select_eap);
+ setSpinnerAdapter(mEapSpinner, R.array.wifi_eap_entries);
+
+ mPhase2Text = (TextView) view.findViewById(R.id.phase2_text);
+ mPhase2Spinner = (Spinner) view.findViewById(R.id.phase2_spinner);
+ mPhase2Spinner.setOnItemSelectedListener(this);
+ mPhase2Spinner.setPromptId(R.string.please_select_phase2);
+ setSpinnerAdapter(mPhase2Spinner, R.array.wifi_phase2_entries);
+
+ mClientCertSpinner =
+ (Spinner) view.findViewById(R.id.client_certificate_spinner);
+ mClientCertSpinner.setOnItemSelectedListener(this);
+ mClientCertSpinner.setPromptId(
+ R.string.please_select_client_certificate);
+ setSpinnerAdapter(mClientCertSpinner, getAllUserCertificateKeys());
+
+ mCaCertSpinner =
+ (Spinner) view.findViewById(R.id.ca_certificate_spinner);
+ mCaCertSpinner.setOnItemSelectedListener(this);
+ mCaCertSpinner.setPromptId(R.string.please_select_ca_certificate);
+ setSpinnerAdapter(mCaCertSpinner, getAllCaCertificateKeys());
+
+ mEnterpriseTextFields = new EditText[] {
+ mIdentityEdit, mAnonymousIdentityEdit, mPrivateKeyPasswdEdit
+ };
+
+ }
+
+ private void setSpinnerAdapter(Spinner spinner, String[] items) {
+ if (items != null) {
+ ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
+ getContext(), android.R.layout.simple_spinner_item, items);
+ adapter.setDropDownViewResource(
+ android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ }
+ }
+
+ private void setSpinnerAdapter(Spinner spinner, int arrayResId) {
+ setSpinnerAdapter(spinner,
+ getContext().getResources().getStringArray(arrayResId));
+ }
+
/** Called when the widgets are in-place waiting to be filled with data */
private void onFill() {
@@ -313,8 +430,9 @@
if (!TextUtils.isEmpty(ssid)) {
mSsidEdit.setText(ssid);
}
-
- mPasswordEdit.setHint(R.string.wifi_password_unchanged);
+ if (mState.configured) {
+ mPasswordEdit.setHint(R.string.wifi_password_unchanged);
+ }
}
updatePasswordCaption(mState.security);
@@ -381,39 +499,52 @@
if (!replaceStateWithWifiLayerInstance()) {
Log.w(TAG, "Assuming connecting to a new network.");
}
-
- /*
- * If the network is secured and they haven't entered a password, popup
- * an error. Allow empty passwords if the state already has a password
- * set (since in that scenario, an empty password means keep the old
- * password).
- */
- String password = getEnteredPassword();
- boolean passwordIsEmpty = TextUtils.isEmpty(password);
-
- /*
- * When 'retry password', they can not enter a blank password. In any
- * other mode, we let them enter a blank password if the state already
- * has a password.
- */
- if (passwordIsEmpty && (!mState.hasPassword() || mMode == MODE_RETRY_PASSWORD)
- && (mState.security != null) && !mState.security.equals(AccessPointState.OPEN)) {
- new AlertDialog.Builder(getContext())
- .setTitle(R.string.error_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.wifi_password_incorrect_error)
- .setPositiveButton(android.R.string.ok, null)
- .show();
- return;
+
+ if (mState.isEnterprise()) {
+ if(!mState.configured) {
+ updateEnterpriseFields(
+ AccessPointState.WPA_EAP.equals(mState.security) ?
+ SECURITY_WPA_EAP : SECURITY_IEEE8021X);
+ }
}
-
- if (!passwordIsEmpty) {
- mState.setPassword(password);
- }
-
- mWifiLayer.connectToNetwork(mState);
+ updatePasswordField();
+
+ mWifiLayer.connectToNetwork(mState);
}
-
+
+ /*
+ * If the network is secured and they haven't entered a password, popup an
+ * error. Allow empty passwords if the state already has a password set
+ * (since in that scenario, an empty password means keep the old password).
+ */
+ private void updatePasswordField() {
+
+ String password = getEnteredPassword();
+ boolean passwordIsEmpty = TextUtils.isEmpty(password);
+ /*
+ * When 'retry password', they can not enter a blank password. In any
+ * other mode, we let them enter a blank password if the state already
+ * has a password.
+ */
+ if (passwordIsEmpty && (!mState.hasPassword() ||
+ mMode == MODE_RETRY_PASSWORD) &&
+ (mState.security != null) &&
+ !mState.security.equals(AccessPointState.OPEN) &&
+ !mState.isEnterprise()) {
+ new AlertDialog.Builder(getContext())
+ .setTitle(R.string.error_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.wifi_password_incorrect_error)
+ .setPositiveButton(android.R.string.ok, null)
+ .show();
+ return;
+ }
+
+ if (!passwordIsEmpty) {
+ mState.setPassword(password);
+ }
+ }
+
private void handleSave() {
replaceStateWithWifiLayerInstance();
@@ -423,43 +554,53 @@
mState.setSsid(ssid);
int securityType = getSecurityTypeFromSpinner();
-
- if (!TextUtils.isEmpty(password)) {
- switch (securityType) {
-
- case SECURITY_WPA_PERSONAL: {
- mState.setSecurity(AccessPointState.WPA);
- mState.setPassword(password);
- break;
- }
-
- case SECURITY_WPA2_PERSONAL: {
- mState.setSecurity(AccessPointState.WPA2);
- mState.setPassword(password);
- break;
- }
-
- case SECURITY_AUTO: {
- mState.setPassword(password);
- break;
- }
-
- case SECURITY_WEP: {
- mState.setSecurity(AccessPointState.WEP);
- mState.setPassword(password,
- WEP_TYPE_VALUES[mWepTypeSpinner.getSelectedItemPosition()]);
- break;
- }
-
+
+ if (!TextUtils.isEmpty(password) && (securityType != SECURITY_WEP)) {
+ mState.setPassword(password);
+ }
+
+ switch (securityType) {
+ case SECURITY_WPA_PERSONAL: {
+ mState.setSecurity(AccessPointState.WPA);
+ break;
}
- } else {
- mState.setSecurity(AccessPointState.OPEN);
+
+ case SECURITY_WPA2_PERSONAL: {
+ mState.setSecurity(AccessPointState.WPA2);
+ break;
+ }
+
+ case SECURITY_AUTO: {
+ break;
+ }
+
+ case SECURITY_WEP: {
+ mState.setSecurity(AccessPointState.WEP);
+ mState.setPassword(password, WEP_TYPE_VALUES[
+ mWepTypeSpinner.getSelectedItemPosition()]);
+ break;
+ }
+
+ case SECURITY_WPA_EAP:
+ mState.setSecurity(AccessPointState.WPA_EAP);
+ break;
+
+ case SECURITY_IEEE8021X:
+ mState.setSecurity(AccessPointState.IEEE8021X);
+ break;
+
+ case SECURITY_NONE:
+ default:
+ mState.setSecurity(AccessPointState.OPEN);
+ break;
}
-
- if (securityType == SECURITY_NONE) {
- mState.setSecurity(AccessPointState.OPEN);
+
+ if (mState.isEnterprise() && !mState.configured) {
+ updateEnterpriseFields(
+ AccessPointState.WPA_EAP.equals(mState.security) ?
+ SECURITY_WPA_EAP : SECURITY_IEEE8021X);
}
-
+
if (!mWifiLayer.saveNetwork(mState)) {
return;
}
@@ -471,6 +612,72 @@
}
+ private int getSelectionIndex(String[] array, String selection) {
+ if(selection != null) {
+ for (int i = 0 ; i < array.length ; i++) {
+ if (selection.contains(array[i])) return i;
+ }
+ }
+ return 0;
+ }
+
+ private int getSelectionIndex(int arrayResId, String selection) {
+ return getSelectionIndex(
+ getContext().getResources().getStringArray(arrayResId), selection);
+ }
+
+ private void updateEnterpriseFields(int securityType) {
+ int i;
+ String value;
+ for (i = AccessPointState.IDENTITY ;
+ i <= AccessPointState.PRIVATE_KEY_PASSWD ; i++) {
+ value = mEnterpriseTextFields[i].getText().toString();
+ if (!TextUtils.isEmpty(value) ||
+ (i == AccessPointState.PRIVATE_KEY_PASSWD)) {
+ mState.setEnterpriseField(i, value);
+ }
+ }
+ Spinner spinner = mClientCertSpinner;
+ int index = spinner.getSelectedItemPosition();
+ if (index != (spinner.getCount() - 1)) {
+ String key = (String)spinner.getSelectedItem();
+ value = mCertTool.getUserCertificate(key);
+ if (!TextUtils.isEmpty(value)) {
+ mState.setEnterpriseField(AccessPointState.CLIENT_CERT,
+ BLOB_HEADER + value);
+ }
+ value = mCertTool.getUserPrivateKey(key);
+ if (!TextUtils.isEmpty(value)) {
+ mState.setEnterpriseField(AccessPointState.PRIVATE_KEY,
+ BLOB_HEADER + value);
+ }
+ }
+ spinner = mCaCertSpinner;
+ index = spinner.getSelectedItemPosition();
+ if (index != (spinner.getCount() - 1)) {
+ String key = (String)spinner.getSelectedItem();
+ value = mCertTool.getCaCertificate(key);
+ if (!TextUtils.isEmpty(value)) {
+ mState.setEnterpriseField(AccessPointState.CA_CERT,
+ BLOB_HEADER + value);
+ }
+ }
+ switch (securityType) {
+ case SECURITY_WPA_EAP: {
+ mState.setSecurity(AccessPointState.WPA_EAP);
+ mState.setEap(mEapSpinner.getSelectedItemPosition());
+ break;
+ }
+ case SECURITY_IEEE8021X: {
+ mState.setSecurity(AccessPointState.IEEE8021X);
+ mState.setEap(mEapSpinner.getSelectedItemPosition());
+ break;
+ }
+ default:
+ mState.setSecurity(AccessPointState.OPEN);
+ }
+ }
+
/**
* Replaces our {@link #mState} with the equal WifiLayer instance. This is useful after
* we unparceled the state previously and before we are calling methods on {@link #mWifiLayer}.
@@ -516,7 +723,21 @@
mPasswordEdit.setVisibility(visibility);
mShowPasswordCheckBox.setVisibility(visibility);
}
-
+
+ private void setEnterpriseFieldsVisible(boolean visible) {
+ int visibility = visible ? View.VISIBLE : View.GONE;
+ mEnterpriseView.setVisibility(visibility);
+ if (visible) {
+ setWepVisible(false);
+ }
+ if (mMode != MODE_CONFIGURE) {
+ mSsidText.setVisibility(View.GONE);
+ mSsidEdit.setVisibility(View.GONE);
+ mSecurityText.setVisibility(View.GONE);
+ mSecuritySpinner.setVisibility(View.GONE);
+ }
+ }
+
public void onItemSelected(AdapterView parent, View view, int position, long id) {
if (parent == mSecuritySpinner) {
handleSecurityChange(getSecurityTypeFromSpinner());
@@ -527,7 +748,7 @@
}
private void handleSecurityChange(int security) {
-
+ setEnterpriseFieldsVisible(false);
switch (security) {
case SECURITY_NONE: {
@@ -559,6 +780,21 @@
updatePasswordCaption(AccessPointState.WPA);
break;
}
+ case SECURITY_WPA_EAP:
+ case SECURITY_IEEE8021X: {
+ // Unlock the keystore if it is not unlocked yet.
+ if (Keystore.getInstance().getState() != Keystore.UNLOCKED) {
+ getContext().startActivity(new Intent(
+ SecuritySettings.ACTION_UNLOCK_CREDENTIAL_STORAGE));
+ mSecuritySpinner.setSelection(0);
+ return;
+ }
+ setEnterpriseFieldsVisible(true);
+ setGenericPasswordVisible(true);
+ // Both WPA and WPA2 show the same caption, so either is ok
+ updatePasswordCaption(AccessPointState.WPA);
+ break;
+ }
}
}
diff --git a/src/com/android/settings/wifi/AccessPointState.java b/src/com/android/settings/wifi/AccessPointState.java
index 2569802..8fb651b 100644
--- a/src/com/android/settings/wifi/AccessPointState.java
+++ b/src/com/android/settings/wifi/AccessPointState.java
@@ -43,6 +43,12 @@
public static final String WEP = "WEP";
public static final String OPEN = "Open";
+ /* For EAP Enterprise fields */
+ public static final String WPA_EAP = "WPA-EAP";
+ public static final String IEEE8021X = "IEEE8021X";
+
+ public static final String[] EAP_METHOD = { "PEAP", "TLS", "TTLS" };
+
/** String present in capabilities if the scan result is ad-hoc */
private static final String ADHOC_CAPABILITY = "[IBSS]";
/** String present in capabilities if the scan result is enterprise secured */
@@ -93,7 +99,19 @@
public static final int WEP_PASSWORD_ASCII = 1;
public static final int WEP_PASSWORD_HEX = 2;
private int mWepPasswordType;
-
+
+ /* Enterprise Fields */
+ public static final int IDENTITY = 0;
+ public static final int ANONYMOUS_IDENTITY = 1;
+ public static final int PRIVATE_KEY_PASSWD = 2;
+ public static final int CLIENT_CERT = 3;
+ public static final int CA_CERT = 4;
+ public static final int PRIVATE_KEY = 5;
+ public static final int MAX_ENTRPRISE_FIELD = 6;
+ private String mEnterpriseFields[] = new String[MAX_ENTRPRISE_FIELD];
+ private String mEap;
+ private String mPhase2;
+
private Context mContext;
/**
@@ -258,7 +276,12 @@
requestRefresh();
}
}
-
+
+ public boolean isEnterprise() {
+ return (WPA_EAP.equals(security) ||
+ AccessPointState.IEEE8021X.equals(security));
+ }
+
public void setSecurity(String security) {
if (TextUtils.isEmpty(this.security) || !this.security.equals(security)) {
this.security = security;
@@ -275,7 +298,9 @@
else if (security.equals(WEP)) return mContext.getString(R.string.wifi_security_wep);
else if (security.equals(WPA)) return mContext.getString(R.string.wifi_security_wpa);
else if (security.equals(WPA2)) return mContext.getString(R.string.wifi_security_wpa2);
-
+ else if (security.equals(WPA_EAP)) return mContext.getString(R.string.wifi_security_wpa_eap);
+ else if (security.equals(IEEE8021X)) return mContext.getString(R.string.wifi_security_ieee8021x);
+
return mContext.getString(R.string.wifi_security_unknown);
}
@@ -300,7 +325,7 @@
*/
public static String getScanResultSecurity(ScanResult scanResult) {
final String cap = scanResult.capabilities;
- final String[] securityModes = { WEP, WPA, WPA2 };
+ final String[] securityModes = { WEP, WPA, WPA2, WPA_EAP, IEEE8021X };
for (int i = securityModes.length - 1; i >= 0; i--) {
if (cap.contains(securityModes[i])) {
return securityModes[i];
@@ -347,7 +372,30 @@
mPassword = password;
mWepPasswordType = wepPasswordType;
}
-
+
+ /* For Enterprise Fields */
+ public void setEnterpriseField(int field, String value) {
+ if (value != null && field >= 0 && field < MAX_ENTRPRISE_FIELD) {
+ this.mEnterpriseFields[field] = value;
+ requestRefresh();
+ }
+ }
+
+ public void setEap(int method) {
+ mEap = EAP_METHOD[method];
+ requestRefresh();
+ }
+
+ public String getEap() {
+ return mEap;
+ }
+ public String getEnterpriseField(int field) {
+ if(field >=0 && field < MAX_ENTRPRISE_FIELD) {
+ return mEnterpriseFields[field];
+ }
+ return null;
+ }
+
public boolean hasPassword() {
return !TextUtils.isEmpty(mPassword) || mConfigHadPassword;
}
@@ -382,6 +430,10 @@
} else {
return OPEN;
}
+ } else if (wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
+ return WPA_EAP;
+ } else if (wifiConfig.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+ return IEEE8021X;
} else if (wifiConfig.allowedProtocols.get(Protocol.RSN)) {
return WPA2;
} else if (wifiConfig.allowedProtocols.get(Protocol.WPA)) {
@@ -442,7 +494,43 @@
config.priority = priority;
config.hiddenSSID = hiddenSsid;
config.SSID = convertToQuotedString(ssid);
-
+ config.eap = mEap;
+ if (!TextUtils.isEmpty(mEnterpriseFields[IDENTITY])) {
+ config.identity =
+ convertToQuotedString(mEnterpriseFields[IDENTITY]);
+ } else {
+ config.identity = null;
+ }
+ if (!TextUtils.isEmpty(mEnterpriseFields[ANONYMOUS_IDENTITY])) {
+ config.anonymousIdentity = convertToQuotedString(
+ mEnterpriseFields[ANONYMOUS_IDENTITY]);
+ } else {
+ config.anonymousIdentity = null;
+ }
+ if (!TextUtils.isEmpty(mEnterpriseFields[CLIENT_CERT])) {
+ config.clientCert = convertToQuotedString(
+ mEnterpriseFields[CLIENT_CERT]);
+ } else {
+ config.clientCert = null;
+ }
+ if (!TextUtils.isEmpty(mEnterpriseFields[CA_CERT])) {
+ config.caCert = convertToQuotedString(
+ mEnterpriseFields[CA_CERT]);
+ } else {
+ config.caCert = null;
+ }
+ if (!TextUtils.isEmpty(mEnterpriseFields[PRIVATE_KEY])) {
+ config.privateKey = convertToQuotedString(
+ mEnterpriseFields[PRIVATE_KEY]);
+ } else {
+ config.privateKey = null;
+ }
+ if (!TextUtils.isEmpty(mEnterpriseFields[PRIVATE_KEY_PASSWD])) {
+ config.privateKeyPasswd = convertToQuotedString(
+ mEnterpriseFields[PRIVATE_KEY_PASSWD]);
+ } else {
+ config.privateKeyPasswd = null;
+ }
setupSecurity(config);
}
@@ -509,6 +597,17 @@
} else if (security.equals(OPEN)) {
config.allowedKeyManagement.set(KeyMgmt.NONE);
+ } else if (security.equals(WPA_EAP) || security.equals(IEEE8021X)) {
+ config.allowedGroupCiphers.set(GroupCipher.TKIP);
+ config.allowedGroupCiphers.set(GroupCipher.CCMP);
+ if (security.equals(WPA_EAP)) {
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ } else {
+ config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ }
+ if (!TextUtils.isEmpty(mPassword)) {
+ config.password = convertToQuotedString(mPassword);
+ }
}
}
@@ -716,26 +815,31 @@
return mContext.getString(R.string.wifi_security_verbose_wpa2);
} else if (OPEN.equals(security)) {
return mContext.getString(R.string.wifi_security_verbose_open);
+ } else if (WPA_EAP.equals(security)) {
+ return mContext.getString(R.string.wifi_security_verbose_wpa_eap);
+ } else if (IEEE8021X.equals(security)) {
+ return mContext.getString(R.string.wifi_security_verbose_ieee8021x);
} else {
return null;
}
}
-
- private void buildSummary(StringBuilder sb, String string, boolean autoLowerCaseFirstLetter) {
+
+ private void buildSummary(StringBuilder sb, String string, boolean autoUpperCaseFirstLetter) {
if (sb.length() == 0) {
- sb.append(string);
- } else {
- sb.append(", ");
- if (autoLowerCaseFirstLetter) {
- // Convert first letter to lowercase
- sb.append(Character.toLowerCase(string.charAt(0))).append(string, 1,
+ if (autoUpperCaseFirstLetter && string.length() > 1
+ && Character.isLowerCase(string.charAt(0))
+ && !Character.isUpperCase(string.charAt(1))) {
+ sb.append(Character.toUpperCase(string.charAt(0))).append(string, 1,
string.length());
} else {
sb.append(string);
}
+ } else {
+ sb.append(", ");
+ sb.append(string);
}
}
-
+
public int compareTo(AccessPointState other) {
// This ranks the states for displaying in the AP list, not for
// connecting to (wpa_supplicant does that using the WifiConfiguration's
diff --git a/src/com/android/settings/wifi/WifiLayer.java b/src/com/android/settings/wifi/WifiLayer.java
index b0857d2..751a5a3 100644
--- a/src/com/android/settings/wifi/WifiLayer.java
+++ b/src/com/android/settings/wifi/WifiLayer.java
@@ -1133,7 +1133,6 @@
* Hidden networks show up with empty SSID.
*/
if (AccessPointState.isAdhoc(scanResult)
- || AccessPointState.isEnterprise(scanResult)
|| TextUtils.isEmpty(scanResult.SSID)) {
continue;
}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index d2683c0..a015534 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -18,6 +18,7 @@
import com.android.settings.ProgressCategory;
import com.android.settings.R;
+import com.android.settings.SecuritySettings;
import android.app.Dialog;
import android.content.DialogInterface;
@@ -29,6 +30,7 @@
import android.preference.PreferenceScreen;
import android.preference.CheckBoxPreference;
import android.provider.Settings;
+import android.security.Keystore;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
@@ -259,7 +261,7 @@
@Override
public boolean onContextItemSelected(MenuItem item) {
-
+
AccessPointState state = getStateFromMenuInfo(item.getMenuInfo());
if (state == null) {
return false;
@@ -352,6 +354,12 @@
}
public void showAccessPointDialog(AccessPointState state, int mode) {
+ if (state.isEnterprise() &&
+ Keystore.getInstance().getState() != Keystore.UNLOCKED) {
+ startActivity(new Intent(
+ SecuritySettings.ACTION_UNLOCK_CREDENTIAL_STORAGE));
+ return;
+ }
AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer);
dialog.setMode(mode);
dialog.setState(state);