Merge "add developer setting for multiprocess webview" into nyc-dev
diff --git a/res/layout/battery_usage_graph.xml b/res/layout/battery_usage_graph.xml
new file mode 100644
index 0000000..ddf7d93
--- /dev/null
+++ b/res/layout/battery_usage_graph.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/charge"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textSize="36sp"
+ android:textColor="?android:attr/colorAccent" />
+
+ <TextView
+ android:id="@+id/estimation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <com.android.settingslib.graph.UsageView
+ android:id="@+id/battery_usage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ settings:sideLabels="@array/battery_labels"
+ android:colorAccent="?android:attr/colorAccent"
+ android:gravity="end"
+ settings:textColor="?android:attr/textColorSecondary" />
+
+</LinearLayout>
diff --git a/res/layout/screen_zoom_preview_3.xml b/res/layout/preference_widget_summary.xml
similarity index 72%
rename from res/layout/screen_zoom_preview_3.xml
rename to res/layout/preference_widget_summary.xml
index 6fc7fd0..aa4c76b 100644
--- a/res/layout/screen_zoom_preview_3.xml
+++ b/res/layout/preference_widget_summary.xml
@@ -14,7 +14,9 @@
limitations under the License.
-->
-<com.android.settings.display.AppGridView
- xmlns:android="http://schemas.android.com/apk/res/android"
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/widget_summary"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary" />
diff --git a/res/layout/preview_seek_bar_view_pager.xml b/res/layout/preview_seek_bar_view_pager.xml
index ac315b8..4badca4 100644
--- a/res/layout/preview_seek_bar_view_pager.xml
+++ b/res/layout/preview_seek_bar_view_pager.xml
@@ -24,7 +24,8 @@
android:id="@+id/preview_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?android:attr/colorBackgroundFloating" />
+ android:background="?android:attr/colorBackgroundFloating"
+ android:importantForAccessibility="noHideDescendants"/>
<View
android:layout_width="match_parent"
diff --git a/res/layout/screen_zoom_preview_2.xml b/res/layout/screen_zoom_preview_2.xml
index ca2ecca..d9b748d 100644
--- a/res/layout/screen_zoom_preview_2.xml
+++ b/res/layout/screen_zoom_preview_2.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2016 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.
@@ -13,11 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.settings.display.AppGridView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scrollbars="none"
- android:background="?android:attr/colorBackgroundFloating">
-
-</ScrollView>
+ android:layout_height="match_parent" />
diff --git a/res/layout/screen_zoom_preview_settings.xml b/res/layout/screen_zoom_preview_settings.xml
new file mode 100644
index 0000000..cf9a8bd
--- /dev/null
+++ b/res/layout/screen_zoom_preview_settings.xml
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none"
+ android:background="?android:attr/colorBackgroundFloating">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- Wifi Setting -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingStart="8dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:src="@drawable/wifi_signal_dark"
+ android:tint="?android:attr/colorAccent"
+ android:scaleType="center" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingStart="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/wifi_settings"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorPrimary" />
+
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/wifi_display_status_not_available"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <!-- Data usage Setting -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingStart="8dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:src="@drawable/ic_settings_data_usage"
+ android:tint="?android:attr/colorAccent"
+ android:scaleType="center" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingStart="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/data_usage_summary_title"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/no_data_usage"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <!-- Display Setting -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingStart="8dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:src="@drawable/ic_settings_display"
+ android:tint="?android:attr/colorAccent"
+ android:scaleType="center" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingStart="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/display_settings_title"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/display_summary_on"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <!-- Sound & Notification Setting -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingStart="8dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:src="@drawable/ic_settings_sound"
+ android:tint="?android:attr/colorAccent"
+ android:scaleType="center" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingStart="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/sound_settings"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/sound_settings_example_summary"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <!-- Apps Setting -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingStart="8dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:src="@drawable/ic_settings_applications"
+ android:tint="?android:attr/colorAccent"
+ android:scaleType="center" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingStart="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/applications_settings"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/apps_summary_example"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 89dd47e..9644171 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1130,6 +1130,21 @@
<!-- Title shown on security settings to allow the user to change their lockscreen password [CHAR LIMIT=22]-->
<string name="unlock_change_lock_password_title">Change unlock password</string>
+ <!-- Message shown when the user incorrectly enters their lock and it counts towards the max attempts before wiping the work profile. -->
+ <string name="lock_profile_wipe_attempts">Try again. Attempt <xliff:g id="current_attempts">%1$d</xliff:g> of <xliff:g id="total_attempts">%2$d</xliff:g>.</string>
+ <!-- Title of a dialog shown when the user only has one attempt left to provide the lock before the work profile is wiped. -->
+ <string name="lock_profile_wipe_warning_title">Last try</string>
+ <!-- Content of the dialog shown when the user only has one attempt left to provide the work pattern before the work profile is wiped. -->
+ <string name="lock_profile_wipe_warning_content_pattern">If you enter an incorrect work pattern on this attempt, your work profile and associated data will be removed from this device.</string>
+ <!-- Content of the dialog shown when the user only has one attempt left to provide the work PIN before the work profile is wiped. -->
+ <string name="lock_profile_wipe_warning_content_pin">If you enter an incorrect work PIN on this attempt, your work profile and associated data will be removed from this device.</string>
+ <!-- Content of the dialog shown when the user only has one attempt left to provide the work password before the work profile is wiped. -->
+ <string name="lock_profile_wipe_warning_content_password">If you enter an incorrect work password on this attempt, your work profile and associated data will be removed from this device.</string>
+ <!-- Content of the dialog shown when the user has failed to provide the work lock too many times and the work profile is wiped. -->
+ <string name="lock_profile_wipe_content">Too many incorrect attempts. Your work profile and associated data will be removed from this device.</string>
+ <!-- Button label to dismiss the dialog telling the user the work profile has been wiped. [CHAR LIMIT=40] -->
+ <string name="lock_profile_wipe_dismiss">Dismiss</string>
+
<!-- Hint shown in dialog screen when password is too short -->
<string name="lockpassword_password_too_short">Password must be at least %d characters</string>
<!-- Hint shown in dialog screen when PIN is too short -->
@@ -3133,13 +3148,13 @@
<!-- Security & location settings screen, title when changing or confirming the work profile lock -->
<string name="lock_settings_profile_screen_lock_title">Work profile screen lock</string>
<!-- Security & location settings screen, setting option name to unify work and personal locks -->
- <string name="lock_settings_profile_unification_title">Use same screenlock</string>
+ <string name="lock_settings_profile_unification_title">Use same screen lock</string>
<!-- Security & location settings screen, setting option explanation to unify work and personal locks -->
<string name="lock_settings_profile_unification_summary">Change primary profile to match work profile</string>
<!-- Security & location settings screen, title of the dialog asking if the user wants to unify work and personal locks -->
- <string name="lock_settings_profile_unification_dialog_title">Use the same screenlock?</string>
+ <string name="lock_settings_profile_unification_dialog_title">Use the same screen lock?</string>
<!-- Security & location settings screen, explanation in the dialog asking if the user wants to unify work and personal locks -->
- <string name="lock_settings_profile_unification_dialog_body">You can use this lock for your device but it will include all screenlock related policies set by your IT admin on the work profile.\nDo you want to use the same screen lock for your device?</string>
+ <string name="lock_settings_profile_unification_dialog_body">You can use this lock for your device but it will include all screen lock related policies set by your IT admin on the work profile.\nDo you want to use the same screen lock for your device?</string>
<!-- Security & location settings screen, summary of the item that changes your work profile lock when it is unified with the personal lock -->
<string name="lock_settings_profile_unified_summary">Same as your device lock</string>
@@ -3390,6 +3405,8 @@
<string name="app_forward_locked">App is copy-protected.</string>
<string name="invalid_location">Install location isn\u2019t valid.</string>
<string name="system_package">System updates can\u2019t be installed on external media.</string>
+ <!-- Error message shown when trying to move device administrators to external disks, such as SD card [CHAR_LIMIT=none] -->
+ <string name="move_error_device_admin">Device Administrator can\u2019t be installed on external media.</string>
<string name="force_stop_dlg_title">Force stop?</string>
<!-- [CHAR LIMIT=200] Manage applications, text for dialog when killing persistent apps-->
@@ -4441,6 +4458,11 @@
behalf. It comes from the <xliff:g id="voice_input_service_app_name">%s</xliff:g>
application. Enable the use of this service?</string>
+ <!-- On main TTS Settings screen, in default settings section, reset speech rate for synthesized voice to 1x speech rate.-->
+ <string name="tts_reset_speech_rate_title">Reset speech rate</string>
+ <!-- On main TTS Settings screen, summary for reset speech rate for synthesized voice -->
+ <string name="tts_reset_speech_rate_summary">Reset the speed at which the text is spoken to normal.</string>
+
<!-- Power Control Widget -->
<string name="gadget_title">Power control</string>
<string name="gadget_toggle_wifi">Updating Wi\u2011Fi setting</string>
@@ -5746,6 +5768,9 @@
<!-- Sound: Dashboard summary. [CHAR LIMIT=100] -->
<string name="sound_settings_summary">Ringer volume at <xliff:g id="percentage" example="2">%1$s</xliff:g></string>
+ <!-- Sound: Dashboard summary example used in Setup Wizard preview screen. [CHAR LIMIT=100] -->
+ <string name="sound_settings_example_summary">Ringer volume at 80%</string>
+
<!-- Sound: Title for the option managing media volume. [CHAR LIMIT=30] -->
<string name="media_volume_option_title">Media volume</string>
@@ -6921,6 +6946,8 @@
<!-- Summary of apps [CHAR LIMIT=NONE] -->
<string name="apps_summary"><xliff:g id="count" example="24">%1$d</xliff:g> apps installed</string>
+ <!-- Example summary of apps used in Setup Wizard preview screen [CHAR LIMIT=NONE] -->
+ <string name="apps_summary_example">24 apps installed</string>
<!-- Summary of storage usage [CHAR LIMIT=NONE] -->
<string name="storage_summary"><xliff:g id="size1" example="8GB">%1$s</xliff:g> of <xliff:g id="size2" example="32GB">%2$s</xliff:g> used</string>
@@ -7144,4 +7171,19 @@
<!-- Title for suggestion adding more fingerprints [CHAR LIMIT=30] -->
<string name="suggestion_additional_fingerprints">Additional Fingerprints</string>
+ <!-- Summary of battery saver when on [CHAR LIMIT=NONE] -->
+ <string name="battery_saver_on_summary">On / <xliff:g name="automatic_state" example="Never turn on automatically">%1$s</xliff:g></string>
+
+ <!-- Summary of battery saver when off [CHAR LIMIT=NONE] -->
+ <string name="battery_saver_off_summary">Off / <xliff:g name="automatic_state" example="Never turn on automatically">%1$s</xliff:g></string>
+
+ <!-- [CHAR_LIMIT=NONE] Battery saver: Description for automatic entry option: Never -->
+ <string name="battery_saver_desc_turn_on_auto_never">Never turn on automatically</string>
+
+ <!-- [CHAR_LIMIT=NONE] Battery saver: Description for automatic entry option: pct% battery -->
+ <string name="battery_saver_desc_turn_on_auto_pct">Turn on automatically at %1$s battery</string>
+
+ <!-- [CHAR_LIMIT=NONE] Label for when app is ignoring battery optimizations -->
+ <string name="not_battery_optimizing">Not using battery optimization</string>
+
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a74d70b..70b5005 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -101,6 +101,10 @@
<item name="android:widgetLayout">@layout/preference_widget_sync_toggle</item>
</style>
+ <style name="EditTextPreference" parent="@*android:style/Preference.Material.DialogPreference.EditTextPreference">
+ <item name="android:dialogLayout">@layout/preference_dialog_edittext</item>
+ </style>
+
<style name="PreferenceHeaderPanelSinglePane">
<item name="android:layout_marginStart">0dp</item>
<item name="android:layout_marginEnd">0dp</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 30c372b..fbe574e 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -102,6 +102,7 @@
<style name="PreferenceTheme" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="@android:preferenceStyle">@style/Preference</item>
+ <item name="@android:editTextPreferenceStyle">@style/EditTextPreference</item>
<item name="@dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
<item name="@android:preferenceFragmentStyle">@style/PreferenceFragmentStyle</item>
<item name="apnPreferenceStyle">@style/ApnPreference</item>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 3f39d47..1ae0a44 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -19,6 +19,10 @@
android:title="@string/power_usage_summary_title"
settings:keywords="@string/keywords_battery">
+ <com.android.settings.fuelgauge.BatterySaverPreference
+ android:title="@string/battery_saver"
+ android:fragment="com.android.settings.fuelgauge.BatterySaverSettings" />
+
<com.android.settings.fuelgauge.BatteryHistoryPreference
android:key="battery_history" />
diff --git a/res/xml/tts_settings.xml b/res/xml/tts_settings.xml
index 071406b..b980f0a 100644
--- a/res/xml/tts_settings.xml
+++ b/res/xml/tts_settings.xml
@@ -31,6 +31,11 @@
android:defaultValue="50"
android:max="600" />
+ <Preference android:key="reset_speech_rate"
+ android:persistent="false"
+ android:title="@string/tts_reset_speech_rate_title"
+ android:summary="@string/tts_reset_speech_rate_summary" />
+
<Preference android:key="tts_play_example"
android:persistent="false"
android:title="@string/tts_play_example_title"
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index 5944b3e..8d20f31 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -35,9 +35,9 @@
android:key="add_users_when_locked"
android:title="@string/user_add_on_lockscreen_menu"
android:summary="@string/user_add_on_lockscreen_menu_summary" />
- <Preference
- android:key="emergency_info"
- android:title="@string/emergency_info_title"
- android:summary="@string/emergency_info_subtitle"/>
</PreferenceCategory>
+ <Preference
+ android:key="emergency_info"
+ android:title="@string/emergency_info_title"
+ android:summary="@string/emergency_info_subtitle"/>
</PreferenceScreen>
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index c0b6e00..102d6cc 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -21,7 +21,6 @@
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
@@ -40,15 +39,13 @@
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
-
import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.util.HashSet;
import java.util.Set;
public class ApnEditor extends InstrumentedPreferenceActivity
- implements SharedPreferences.OnSharedPreferenceChangeListener,
- Preference.OnPreferenceChangeListener {
+ implements Preference.OnPreferenceChangeListener {
private final static String TAG = ApnEditor.class.getSimpleName();
@@ -250,6 +247,10 @@
mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
+ for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
+ getPreferenceScreen().getPreference(i).setOnPreferenceChangeListener(this);
+ }
+
fillUi();
}
@@ -261,14 +262,10 @@
@Override
public void onResume() {
super.onResume();
- getPreferenceScreen().getSharedPreferences()
- .registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
- getPreferenceScreen().getSharedPreferences()
- .unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
@@ -487,7 +484,7 @@
int index = Integer.parseInt((String) newValue);
mAuthType.setValueIndex(index);
- String []values = mRes.getStringArray(R.array.apn_auth_entries);
+ String[] values = mRes.getStringArray(R.array.apn_auth_entries);
mAuthType.setSummary(values[index]);
} catch (NumberFormatException e) {
return false;
@@ -521,6 +518,13 @@
mMvnoType.setValue((String) newValue);
mMvnoType.setSummary(mvno);
}
+ if (preference.equals(mPassword)) {
+ preference.setSummary(starify(newValue != null ? String.valueOf(newValue) : ""));
+ } else if (preference.equals(mCarrierEnabled) || preference.equals(mBearerMulti)) {
+ // do nothing
+ } else {
+ preference.setSummary(checkNull(newValue != null ? String.valueOf(newValue) : null));
+ }
return true;
}
@@ -765,16 +769,4 @@
}
}
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- Preference pref = findPreference(key);
- if (pref != null) {
- if (pref.equals(mPassword)){
- pref.setSummary(starify(sharedPreferences.getString(key, "")));
- } else if (pref.equals(mCarrierEnabled) || pref.equals(mBearerMulti)) {
- // do nothing
- } else {
- pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
- }
- }
- }
}
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index 40e3103..ad1d2eb 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -20,10 +20,13 @@
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
+import android.app.AlertDialog;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentSender;
import android.graphics.Point;
@@ -31,7 +34,9 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
import android.view.View;
import android.view.ViewGroup;
@@ -40,6 +45,7 @@
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.internal.widget.LockPatternUtils;
import com.android.settings.fingerprint.FingerprintUiHelper;
/**
@@ -65,6 +71,9 @@
protected Button mCancelButton;
protected ImageView mFingerprintIcon;
protected int mEffectiveUserId;
+ protected LockPatternUtils mLockPatternUtils;
+ protected TextView mErrorTextView;
+ protected final Handler mHandler = new Handler();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -74,6 +83,7 @@
// Only take this argument into account if it belongs to the current profile.
Intent intent = getActivity().getIntent();
mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
+ mLockPatternUtils = new LockPatternUtils(getActivity());
}
@Override
@@ -109,6 +119,10 @@
if (mAllowFpAuthentication) {
mFingerprintHelper.startListening();
}
+ if (isProfileChallenge()) {
+ updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
+ mEffectiveUserId));
+ }
}
protected void setAccessibilityTitle(CharSequence suplementalText) {
@@ -200,4 +214,87 @@
screenSize.y));
}
}
+
+ protected boolean isProfileChallenge() {
+ return UserHandle.myUserId() != mEffectiveUserId;
+ }
+
+ protected void reportSuccessfullAttempt() {
+ if (isProfileChallenge()) {
+ mLockPatternUtils.reportSuccessfulPasswordAttempt(mEffectiveUserId);
+ }
+ }
+
+ protected void reportFailedAttempt() {
+ if (isProfileChallenge()) {
+ // + 1 for this attempt.
+ updateErrorMessage(
+ mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1);
+ mLockPatternUtils.reportFailedPasswordAttempt(mEffectiveUserId);
+ }
+ }
+
+ protected void updateErrorMessage(int numAttempts) {
+ final int maxAttempts =
+ mLockPatternUtils.getMaximumFailedPasswordsForWipe(mEffectiveUserId);
+ if (maxAttempts > 0 && numAttempts > 0) {
+ int remainingAttempts = maxAttempts - numAttempts;
+ if (remainingAttempts == 1) {
+ // Last try
+ final String title = getActivity().getString(
+ R.string.lock_profile_wipe_warning_title);
+ final String message = getActivity().getString(getLastTryErrorMessage());
+ showDialog(title, message, android.R.string.ok, false /* dismiss */);
+ } else if (remainingAttempts <= 0) {
+ // Profile is wiped
+ final String message = getActivity().getString(R.string.lock_profile_wipe_content);
+ showDialog(null, message, R.string.lock_profile_wipe_dismiss, true /* dismiss */);
+ }
+ if (mErrorTextView != null) {
+ final String message = getActivity().getString(R.string.lock_profile_wipe_attempts,
+ numAttempts, maxAttempts);
+ showError(message, 0);
+ }
+ }
+ }
+
+ protected abstract int getLastTryErrorMessage();
+
+ private final Runnable mResetErrorRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mErrorTextView.setText("");
+ }
+ };
+
+ protected void showError(CharSequence msg, long timeout) {
+ mErrorTextView.setText(msg);
+ onShowError();
+ mHandler.removeCallbacks(mResetErrorRunnable);
+ if (timeout != 0) {
+ mHandler.postDelayed(mResetErrorRunnable, timeout);
+ }
+ }
+
+ protected abstract void onShowError();
+
+ protected void showError(int msg, long timeout) {
+ showError(getText(msg), timeout);
+ }
+
+ private void showDialog(String title, String message, int buttonString, final boolean dismiss) {
+ final AlertDialog dialog = new AlertDialog.Builder(getActivity())
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(buttonString, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (dismiss) {
+ getActivity().finish();
+ }
+ }
+ })
+ .create();
+ dialog.show();
+ }
}
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 8f83221..c69bb89 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -20,11 +20,9 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentSender;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
-import android.os.Handler;
import android.os.SystemClock;
import android.os.UserManager;
import android.os.storage.StorageManager;
@@ -84,14 +82,11 @@
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
private TextView mPasswordEntry;
private TextViewInputDisabler mPasswordEntryInputDisabler;
- private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck;
private CredentialCheckResultTracker mCredentialCheckResultTracker;
private boolean mDisappearing = false;
private TextView mHeaderTextView;
private TextView mDetailsTextView;
- private TextView mErrorTextView;
- private Handler mHandler = new Handler();
private CountDownTimer mCountdownTimer;
private boolean mIsAlpha;
private InputMethodManager mImm;
@@ -108,7 +103,6 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mLockPatternUtils = new LockPatternUtils(getActivity());
}
@Override
@@ -194,6 +188,12 @@
}
@Override
+ protected int getLastTryErrorMessage() {
+ return mIsAlpha ? R.string.lock_profile_wipe_warning_content_password
+ : R.string.lock_profile_wipe_warning_content_pin;
+ }
+
+ @Override
public void prepareEnterAnimation() {
super.prepareEnterAnimation();
mHeaderTextView.setAlpha(0f);
@@ -406,9 +406,12 @@
}
private void onPasswordChecked(boolean matched, Intent intent, int timeoutMs,
- int effectiveUserId) {
+ int effectiveUserId, boolean newResult) {
mPasswordEntryInputDisabler.setInputEnabled(true);
if (matched) {
+ if (newResult) {
+ reportSuccessfullAttempt();
+ }
startDisappearAnimation(intent);
checkForPendingIntent();
} else {
@@ -417,15 +420,23 @@
effectiveUserId, timeoutMs);
handleAttemptLockout(deadline);
} else {
- showError(getErrorMessage());
+ showError(getErrorMessage(), ERROR_MESSAGE_TIMEOUT);
+ }
+ if (newResult) {
+ reportFailedAttempt();
}
}
}
@Override
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
- int effectiveUserId) {
- onPasswordChecked(matched, intent, timeoutMs, effectiveUserId);
+ int effectiveUserId, boolean newResult) {
+ onPasswordChecked(matched, intent, timeoutMs, effectiveUserId, newResult);
+ }
+
+ @Override
+ protected void onShowError() {
+ mPasswordEntry.setText(null);
}
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
@@ -447,6 +458,10 @@
public void onFinish() {
resetState();
mErrorTextView.setText("");
+ if (isProfileChallenge()) {
+ updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
+ mEffectiveUserId));
+ }
}
}.start();
}
@@ -464,29 +479,6 @@
}
}
- private void showError(int msg) {
- showError(msg, ERROR_MESSAGE_TIMEOUT);
- }
-
- private final Runnable mResetErrorRunnable = new Runnable() {
- public void run() {
- mErrorTextView.setText("");
- }
- };
-
- private void showError(CharSequence msg, long timeout) {
- mErrorTextView.setText(msg);
- mPasswordEntry.setText(null);
- mHandler.removeCallbacks(mResetErrorRunnable);
- if (timeout != 0) {
- mHandler.postDelayed(mResetErrorRunnable, timeout);
- }
- }
-
- private void showError(int msg, long timeout) {
- showError(getText(msg), timeout);
- }
-
// {@link OnEditorActionListener} methods.
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter or "done" key
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index d4b0902..dbe9ebe 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -18,7 +18,6 @@
import android.app.Activity;
import android.content.Intent;
-import android.content.IntentSender;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
@@ -85,7 +84,6 @@
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
private LockPatternView mLockPatternView;
- private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck;
private CredentialCheckResultTracker mCredentialCheckResultTracker;
private boolean mDisappearing = false;
@@ -93,7 +91,6 @@
private TextView mHeaderTextView;
private TextView mDetailsTextView;
- private TextView mErrorTextView;
private View mLeftSpacerLandscape;
private View mRightSpacerLandscape;
@@ -112,7 +109,6 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mLockPatternUtils = new LockPatternUtils(getActivity());
}
@Override
@@ -221,6 +217,10 @@
}
@Override
+ protected void onShowError() {
+ }
+
+ @Override
public void prepareEnterAnimation() {
super.prepareEnterAnimation();
mHeaderTextView.setAlpha(0f);
@@ -284,6 +284,10 @@
R.string.lockpassword_confirm_your_pattern_generic_profile);
}
mErrorTextView.setText("");
+ if (isProfileChallenge()) {
+ updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
+ mEffectiveUserId));
+ }
mLockPatternView.setEnabled(true);
mLockPatternView.enableInput();
@@ -470,9 +474,12 @@
};
private void onPatternChecked(boolean matched, Intent intent, int timeoutMs,
- int effectiveUserId) {
+ int effectiveUserId, boolean newResult) {
mLockPatternView.setEnabled(true);
if (matched) {
+ if (newResult) {
+ reportSuccessfullAttempt();
+ }
startDisappearAnimation(intent);
checkForPendingIntent();
} else {
@@ -484,13 +491,21 @@
updateStage(Stage.NeedToUnlockWrong);
postClearPatternRunnable();
}
+ if (newResult) {
+ reportFailedAttempt();
+ }
}
}
@Override
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
- int effectiveUserId) {
- onPatternChecked(matched, intent, timeoutMs, effectiveUserId);
+ int effectiveUserId, boolean newResult) {
+ onPatternChecked(matched, intent, timeoutMs, effectiveUserId, newResult);
+ }
+
+ @Override
+ protected int getLastTryErrorMessage() {
+ return R.string.lock_profile_wipe_warning_content_pattern;
}
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
diff --git a/src/com/android/settings/CredentialCheckResultTracker.java b/src/com/android/settings/CredentialCheckResultTracker.java
index 5c55073..179a93c 100644
--- a/src/com/android/settings/CredentialCheckResultTracker.java
+++ b/src/com/android/settings/CredentialCheckResultTracker.java
@@ -47,7 +47,7 @@
mListener = listener;
if (mListener != null && mHasResult) {
mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs,
- mResultEffectiveUserId);
+ mResultEffectiveUserId, false /* newResult */);
}
}
@@ -60,7 +60,7 @@
mHasResult = true;
if (mListener != null) {
mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs,
- mResultEffectiveUserId);
+ mResultEffectiveUserId, true /* newResult */);
}
}
@@ -74,6 +74,6 @@
interface Listener {
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
- int effectiveUserId);
+ int effectiveUserId, boolean newResult);
}
}
diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index a67ef72..90c1d38 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -19,9 +19,10 @@
import android.app.Activity;
import android.app.AlarmManager;
import android.app.DatePickerDialog;
+import android.app.DatePickerDialog.OnDateSetListener;
import android.app.Dialog;
import android.app.TimePickerDialog;
-import android.app.admin.DevicePolicyManager;
+import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -33,10 +34,10 @@
import android.provider.Settings.SettingNotFoundException;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.text.format.DateFormat;
import android.widget.DatePicker;
import android.widget.TimePicker;
-
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settingslib.RestrictedLockUtils;
@@ -49,8 +50,7 @@
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
public class DateTimeSettings extends SettingsPreferenceFragment
- implements OnSharedPreferenceChangeListener,
- TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
+ implements OnTimeSetListener, OnDateSetListener, OnPreferenceChangeListener {
private static final String HOURS_12 = "12";
private static final String HOURS_24 = "24";
@@ -94,6 +94,7 @@
boolean autoTimeZoneEnabled = getAutoState(Settings.Global.AUTO_TIME_ZONE);
mAutoTimePref = (RestrictedSwitchPreference) findPreference(KEY_AUTO_TIME);
+ mAutoTimePref.setOnPreferenceChangeListener(this);
EnforcedAdmin admin = RestrictedLockUtils.checkIfAutoTimeRequired(getActivity());
mAutoTimePref.setDisabledByAdmin(admin);
@@ -106,6 +107,7 @@
// Settings.Global.AUTO_TIME to true. Note that this app listens to that change.
mAutoTimePref.setChecked(autoTimeEnabled);
mAutoTimeZonePref = (SwitchPreference) findPreference(KEY_AUTO_TIME_ZONE);
+ mAutoTimeZonePref.setOnPreferenceChangeListener(this);
// Override auto-timezone if it's a wifi-only device or if we're still in setup wizard.
// TODO: Remove the wifiOnly test when auto-timezone is implemented based on wifi-location.
if (Utils.isWifiOnly(getActivity()) || isFirstRun) {
@@ -131,9 +133,6 @@
public void onResume() {
super.onResume();
- getPreferenceScreen().getSharedPreferences()
- .registerOnSharedPreferenceChangeListener(this);
-
((SwitchPreference)mTime24Pref).setChecked(is24Hour());
// Register for time ticks and other reasons for time change
@@ -150,8 +149,6 @@
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mIntentReceiver);
- getPreferenceScreen().getSharedPreferences()
- .unregisterOnSharedPreferenceChangeListener(this);
}
public void updateTimeAndDateDisplay(Context context) {
@@ -190,19 +187,20 @@
}
@Override
- public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
- if (key.equals(KEY_AUTO_TIME)) {
- boolean autoEnabled = preferences.getBoolean(key, true);
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference.getKey().equals(KEY_AUTO_TIME)) {
+ boolean autoEnabled = (Boolean) newValue;
Settings.Global.putInt(getContentResolver(), Settings.Global.AUTO_TIME,
autoEnabled ? 1 : 0);
mTimePref.setEnabled(!autoEnabled);
mDatePref.setEnabled(!autoEnabled);
- } else if (key.equals(KEY_AUTO_TIME_ZONE)) {
- boolean autoZoneEnabled = preferences.getBoolean(key, true);
+ } else if (preference.getKey().equals(KEY_AUTO_TIME_ZONE)) {
+ boolean autoZoneEnabled = (Boolean) newValue;
Settings.Global.putInt(
getContentResolver(), Settings.Global.AUTO_TIME_ZONE, autoZoneEnabled ? 1 : 0);
mTimeZone.setEnabled(!autoZoneEnabled);
}
+ return true;
}
@Override
diff --git a/src/com/android/settings/DeviceAdminSettings.java b/src/com/android/settings/DeviceAdminSettings.java
index 9791160..3adce15 100644
--- a/src/com/android/settings/DeviceAdminSettings.java
+++ b/src/com/android/settings/DeviceAdminSettings.java
@@ -359,6 +359,9 @@
DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(resolveInfo);
// add only visible ones (note: active admins are added regardless of visibility)
if (deviceAdminInfo != null && deviceAdminInfo.isVisible()) {
+ if (!deviceAdminInfo.getActivityInfo().applicationInfo.isInternal()) {
+ continue;
+ }
DeviceAdminListItem item = new DeviceAdminListItem();
item.info = deviceAdminInfo;
item.name = deviceAdminInfo.loadLabel(pm).toString();
@@ -391,6 +394,8 @@
for (int j = 0; j < resolvedMax; ++j) {
DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(resolved.get(j));
if (deviceAdminInfo != null) {
+ // Don't do the applicationInfo.isInternal() check here; if an active
+ // admin is already on SD card, just show it.
DeviceAdminListItem item = new DeviceAdminListItem();
item.info = deviceAdminInfo;
item.name = deviceAdminInfo.loadLabel(packageManager).toString();
diff --git a/src/com/android/settings/PreferenceAvailabilityProvider.java b/src/com/android/settings/PreferenceAvailabilityProvider.java
new file mode 100644
index 0000000..bb33aee
--- /dev/null
+++ b/src/com/android/settings/PreferenceAvailabilityProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 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.content.Context;
+
+/**
+ * Interface for classes whose instances can provide the availability of the preference.
+ */
+public interface PreferenceAvailabilityProvider {
+ /**
+ * @return the availability of the preference. Please make sure the availability in managed
+ * profile is taken into account.
+ */
+ boolean isAvailable(Context context);
+}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 9aebdbf..49d72b4 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -40,7 +40,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-import com.android.settings.accessibility.AccessibilitySettingsForSetupWizardActivity;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.widget.FloatingActionButton;
@@ -164,8 +163,7 @@
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- if (!TextUtils.isEmpty(mHelpUri)
- && !(getActivity() instanceof AccessibilitySettingsForSetupWizardActivity)) {
+ if (!TextUtils.isEmpty(mHelpUri)) {
setHasOptionsMenu(true);
}
}
diff --git a/src/com/android/settings/TintablePreference.java b/src/com/android/settings/TintablePreference.java
index 0ada6ed..45f43fb 100644
--- a/src/com/android/settings/TintablePreference.java
+++ b/src/com/android/settings/TintablePreference.java
@@ -42,6 +42,8 @@
if (mTintColor != 0) {
((ImageView) view.findViewById(android.R.id.icon)).setImageTintList(
ColorStateList.valueOf(mTintColor));
+ } else {
+ ((ImageView) view.findViewById(android.R.id.icon)).setImageTintList(null);
}
}
}
diff --git a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
index 26f5f39..35bb83b 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
@@ -17,14 +17,18 @@
package com.android.settings.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.os.Bundle;
+import android.os.Handler;
import android.provider.Settings;
import android.support.v7.preference.Preference;
+import android.util.Log;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.MetricsProto;
@@ -40,16 +44,30 @@
public class AccessibilitySettingsForSetupWizard extends SettingsPreferenceFragment
implements DialogCreatable, Preference.OnPreferenceChangeListener {
+ private static final String TAG = AccessibilitySettingsForSetupWizard.class.getSimpleName();
+
// Preferences.
private static final String DISPLAY_MAGNIFICATION_PREFERENCE =
"screen_magnification_preference";
- private static final String TALKBACK_PREFERENCE = "talkback_preference";
+ private static final String SCREEN_READER_PREFERENCE = "talkback_preference";
private static final String FONT_SIZE_PREFERENCE = "font_size_preference";
+ // Time needed to let Talkback initialize its self before launching the tutorial.
+ private static final long SCREEN_READER_INITIALIZATION_DELAY_MS = 3000;
+
+ private String mTalkbackPackage;
+
// Preference controls.
private Preference mDisplayMagnificationPreference;
private Preference mTalkbackPreference;
+ private Runnable mStartTalkbackRunnable = new Runnable() {
+ @Override
+ public void run() {
+ launchTalkbackTutorial();
+ }
+ };
+
@Override
protected int getMetricsCategory() {
return MetricsProto.MetricsEvent.ACCESSIBILITY;
@@ -61,7 +79,7 @@
addPreferencesFromResource(R.xml.accessibility_settings_for_setup_wizard);
mDisplayMagnificationPreference = findPreference(DISPLAY_MAGNIFICATION_PREFERENCE);
- mTalkbackPreference = findPreference(TALKBACK_PREFERENCE);
+ mTalkbackPreference = findPreference(SCREEN_READER_PREFERENCE);
}
@Override
@@ -75,41 +93,16 @@
return false;
}
- /**
- * Returns a semicolon-delimited string containing a list of all the
- * installed {@link AccessibilityService}s that provide at least one
- * required feedback type.
- *
- * @param context The {@link android.app.Activity} context.
- * @param requiredFeedbackTypes An integer mask containing the required
- * feedback types.
- * @return A semicolon-delimited string containing a list of accessibility services.
- */
- private String getAccessibilityServicesFiltered(
- Context context, int requiredFeedbackTypes) {
- final AccessibilityManager manager = context.getSystemService(AccessibilityManager.class);
- final List<AccessibilityServiceInfo> accessibilityServices = manager
- .getInstalledAccessibilityServiceList();
- final StringBuilder servicesToEnable = new StringBuilder();
-
- for (AccessibilityServiceInfo accessibilityService : accessibilityServices) {
- if ((accessibilityService.feedbackType & requiredFeedbackTypes) == 0) {
- continue;
- }
-
- final ServiceInfo serviceInfo = accessibilityService.getResolveInfo().serviceInfo;
- final ComponentName componentName = new ComponentName(serviceInfo.packageName,
- serviceInfo.name);
-
- servicesToEnable.append(componentName.flattenToString());
- servicesToEnable.append(':');
+ private void launchTalkbackTutorial() {
+ try {
+ Intent intent = new Intent(Settings.ACTION_SCREEN_READER_TUTORIAL);
+ intent.setPackage(mTalkbackPackage);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ // This can happen if either the build is misconfigued or an OEM removes the intent
+ // filter for the Talkback tutorial from their implementation of Talkback.
+ Log.e(TAG, "Can't find Talkback Tutorial: " + Settings.ACTION_SCREEN_READER_TUTORIAL);
}
-
- if (servicesToEnable.length() > 0) {
- servicesToEnable.deleteCharAt(servicesToEnable.length() - 1);
- }
-
- return servicesToEnable.toString();
}
@Override
@@ -130,17 +123,34 @@
final int accessibilityEnabled =
Settings.Secure.getInt(resolver, Settings.Secure.ACCESSIBILITY_ENABLED, 0);
if (accessibilityEnabled == 0) {
- final String servicesToEnable = getAccessibilityServicesFiltered(
- getActivity(), AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+ // Find the first installed screen reader.
+ String serviceToEnable = null;
+ final AccessibilityManager manager =
+ getActivity().getSystemService(AccessibilityManager.class);
+ final List<AccessibilityServiceInfo> accessibilityServices =
+ manager.getInstalledAccessibilityServiceList();
+ for (AccessibilityServiceInfo accessibilityService : accessibilityServices) {
+ if ((accessibilityService.feedbackType
+ & AccessibilityServiceInfo.FEEDBACK_SPOKEN) != 0) {
+ final ServiceInfo serviceInfo =
+ accessibilityService.getResolveInfo().serviceInfo;
+ mTalkbackPackage = serviceInfo.packageName;
+ final ComponentName componentName =
+ new ComponentName(serviceInfo.packageName, serviceInfo.name);
+
+ serviceToEnable = componentName.flattenToString();
+ break;
+ }
+ }
// Enable all accessibility services with spoken feedback type.
Settings.Secure.putString(resolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- servicesToEnable);
+ serviceToEnable);
// Allow the services we just enabled to toggle touch exploration.
Settings.Secure.putString(resolver,
Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- servicesToEnable);
+ serviceToEnable);
// Enable touch exploration.
Settings.Secure.putInt(resolver, Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1);
@@ -148,6 +158,13 @@
// Turn on accessibility mode last, since enabling accessibility with no
// services has no effect.
Settings.Secure.putInt(resolver, Settings.Secure.ACCESSIBILITY_ENABLED, 1);
+
+ // Since Talkback will display an error message if it's not active when the Tutorial
+ // is launched, launch Talkbck Tutorial with a delay.
+ new Handler().postDelayed(mStartTalkbackRunnable,
+ SCREEN_READER_INITIALIZATION_DELAY_MS);
+ } else {
+ launchTalkbackTutorial();
}
}
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 041fed8..748dc15 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -55,7 +55,7 @@
view.setDividerAllowedBelow(false);
final RelativeLayout background =
(RelativeLayout) view.findViewById(R.id.video_background);
- final VideoView videoView = (VideoView) view.findViewById(R.id.video);
+ VideoView videoView = (VideoView) view.findViewById(R.id.video);
// Hacky adjustment for using VideoView in recycle view and positioning
// it on the background image
@@ -98,7 +98,8 @@
ContentResolver.SCHEME_ANDROID_RESOURCE,
getPrefContext().getPackageName(),
R.raw.accessibility_screen_magnification)));
- videoView.setMediaController(new MediaController(getPrefContext()));
+ // Make sure video controls (e.g. for pausing) are not displayed.
+ videoView.setMediaController(null);
videoView.start();
}
}
@@ -149,6 +150,11 @@
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 0) {
setMagnificationEnabled(1);
}
+
+ VideoView videoView = (VideoView) getView().findViewById(R.id.video);
+ if (videoView != null) {
+ videoView.start();
+ }
}
@Override
diff --git a/src/com/android/settings/applications/DefaultBrowserPreference.java b/src/com/android/settings/applications/DefaultBrowserPreference.java
index 32f77ba..a9a4e2a 100644
--- a/src/com/android/settings/applications/DefaultBrowserPreference.java
+++ b/src/com/android/settings/applications/DefaultBrowserPreference.java
@@ -25,6 +25,7 @@
import android.util.AttributeSet;
import com.android.settings.AppListPreference;
+import com.android.settings.PreferenceAvailabilityProvider;
import java.util.ArrayList;
import java.util.List;
@@ -72,4 +73,11 @@
return result;
}
+
+ public static class AvailabilityProvider implements PreferenceAvailabilityProvider {
+ @Override
+ public boolean isAvailable(Context context) {
+ return true;
+ }
+ }
}
diff --git a/src/com/android/settings/applications/DefaultEmergencyPreference.java b/src/com/android/settings/applications/DefaultEmergencyPreference.java
index 7c9b124..bb6e84d 100644
--- a/src/com/android/settings/applications/DefaultEmergencyPreference.java
+++ b/src/com/android/settings/applications/DefaultEmergencyPreference.java
@@ -32,6 +32,7 @@
import android.util.AttributeSet;
import com.android.settings.AppListPreference;
+import com.android.settings.PreferenceAvailabilityProvider;
import com.android.settings.Utils;
import java.util.List;
@@ -51,10 +52,7 @@
public DefaultEmergencyPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContentResolver = context.getContentResolver();
-
- if (isAvailable(context)) {
- load();
- }
+ load();
}
@Override
@@ -135,13 +133,7 @@
return packages;
}
- public static boolean isAvailable(Context context) {
- return isCapable(context)
- && context.getPackageManager().resolveActivity(QUERY_INTENT, 0) != null
- && !Utils.isManagedProfile(UserManager.get(context)) ;
- }
-
- public static boolean isCapable(Context context) {
+ private static boolean isCapable(Context context) {
return TelephonyManager.EMERGENCY_ASSISTANCE_ENABLED
&& context.getResources().getBoolean(
com.android.internal.R.bool.config_voice_capable);
@@ -151,4 +143,13 @@
return info.applicationInfo != null
&& (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
+
+ public static class AvailabilityProvider implements PreferenceAvailabilityProvider {
+ @Override
+ public boolean isAvailable(Context context) {
+ return isCapable(context)
+ && context.getPackageManager().resolveActivity(QUERY_INTENT, 0) != null
+ && !Utils.isManagedProfile(UserManager.get(context));
+ }
+ }
}
diff --git a/src/com/android/settings/applications/DefaultHomePreference.java b/src/com/android/settings/applications/DefaultHomePreference.java
index 7426ce6..2837a97 100644
--- a/src/com/android/settings/applications/DefaultHomePreference.java
+++ b/src/com/android/settings/applications/DefaultHomePreference.java
@@ -26,8 +26,11 @@
import android.os.Build;
import android.os.UserManager;
import android.util.AttributeSet;
+
import com.android.settings.AppListPreference;
+import com.android.settings.PreferenceAvailabilityProvider;
import com.android.settings.R;
+import com.android.settings.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -115,4 +118,10 @@
return false;
}
+ public static class AvailabilityProvider implements PreferenceAvailabilityProvider {
+ @Override
+ public boolean isAvailable(Context context) {
+ return !Utils.isManagedProfile(UserManager.get(context));
+ }
+ }
}
diff --git a/src/com/android/settings/applications/DefaultNotificationAssistantPreference.java b/src/com/android/settings/applications/DefaultNotificationAssistantPreference.java
index 186c442..ab3a0b2 100644
--- a/src/com/android/settings/applications/DefaultNotificationAssistantPreference.java
+++ b/src/com/android/settings/applications/DefaultNotificationAssistantPreference.java
@@ -34,6 +34,7 @@
import java.util.ArrayList;
import java.util.List;
+import com.android.settings.PreferenceAvailabilityProvider;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.notification.ManagedServiceSettings;
@@ -111,7 +112,10 @@
return c;
}
- public static boolean isAvailable(Context context) {
- return !Utils.isManagedProfile(UserManager.get(context));
+ public static class AvailabilityProvider implements PreferenceAvailabilityProvider {
+ @Override
+ public boolean isAvailable(Context context) {
+ return !Utils.isManagedProfile(UserManager.get(context));
+ }
}
}
diff --git a/src/com/android/settings/applications/DefaultPhonePreference.java b/src/com/android/settings/applications/DefaultPhonePreference.java
index 3d9131e..7ab6325 100644
--- a/src/com/android/settings/applications/DefaultPhonePreference.java
+++ b/src/com/android/settings/applications/DefaultPhonePreference.java
@@ -25,6 +25,8 @@
import android.util.AttributeSet;
import com.android.settings.AppListPreference;
+import com.android.settings.PreferenceAvailabilityProvider;
+import com.android.settings.Utils;
import java.util.List;
import java.util.Objects;
@@ -36,9 +38,7 @@
super(context, attrs);
mContext = context.getApplicationContext();
- if (isAvailable(context)) {
- loadDialerApps();
- }
+ loadDialerApps();
}
@Override
@@ -65,15 +65,19 @@
return DefaultDialerManager.getDefaultDialerApplication(getContext());
}
- public static boolean isAvailable(Context context) {
- final TelephonyManager tm =
- (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- if (!tm.isVoiceCapable()) {
- return false;
- }
+ public static class AvailabilityProvider implements PreferenceAvailabilityProvider {
+ @Override
+ public boolean isAvailable(Context context) {
- final UserManager um =
- (UserManager) context.getSystemService(Context.USER_SERVICE);
- return !um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
+ final TelephonyManager tm =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ if (!tm.isVoiceCapable()) {
+ return false;
+ }
+
+ final UserManager um =
+ (UserManager) context.getSystemService(Context.USER_SERVICE);
+ return !um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
+ }
}
}
diff --git a/src/com/android/settings/applications/DefaultSmsPreference.java b/src/com/android/settings/applications/DefaultSmsPreference.java
index 7281394..73404bb 100644
--- a/src/com/android/settings/applications/DefaultSmsPreference.java
+++ b/src/com/android/settings/applications/DefaultSmsPreference.java
@@ -17,6 +17,7 @@
import android.content.ComponentName;
import android.content.Context;
+import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -25,6 +26,7 @@
import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.SmsApplication.SmsApplicationData;
import com.android.settings.AppListPreference;
+import com.android.settings.PreferenceAvailabilityProvider;
import com.android.settings.Utils;
import java.util.Collection;
@@ -68,10 +70,18 @@
return true;
}
- public static boolean isAvailable(Context context) {
- TelephonyManager tm =
- (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- return tm.isSmsCapable() && !Utils.isManagedProfile(UserManager.get(context));
+ public static class AvailabilityProvider implements PreferenceAvailabilityProvider {
+ @Override
+ public boolean isAvailable(Context context) {
+ boolean isRestrictedUser =
+ UserManager.get(context)
+ .getUserInfo(UserHandle.myUserId()).isRestricted();
+ TelephonyManager tm =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ return !isRestrictedUser
+ && tm.isSmsCapable()
+ && !Utils.isManagedProfile(UserManager.get(context));
+ }
}
}
diff --git a/src/com/android/settings/applications/ManageAssist.java b/src/com/android/settings/applications/ManageAssist.java
index fca124f..5a17a31 100644
--- a/src/com/android/settings/applications/ManageAssist.java
+++ b/src/com/android/settings/applications/ManageAssist.java
@@ -28,6 +28,7 @@
import android.support.v7.preference.Preference;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.PreferenceAvailabilityProvider;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
@@ -179,7 +180,10 @@
updateUi();
}
- public static boolean isAvailable(Context context) {
- return !Utils.isManagedProfile(UserManager.get(context));
+ public static class AvailabilityProvider implements PreferenceAvailabilityProvider {
+ @Override
+ public boolean isAvailable(Context context) {
+ return !Utils.isManagedProfile(UserManager.get(context));
+ }
}
}
diff --git a/src/com/android/settings/applications/ManageDefaultApps.java b/src/com/android/settings/applications/ManageDefaultApps.java
index b421c9d..327c98b 100644
--- a/src/com/android/settings/applications/ManageDefaultApps.java
+++ b/src/com/android/settings/applications/ManageDefaultApps.java
@@ -24,15 +24,17 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
+import android.support.v4.util.ArrayMap;
import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.PreferenceAvailabilityProvider;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Index;
@@ -48,18 +50,23 @@
private static final String TAG = ManageDefaultApps.class.getSimpleName();
+ private static final String KEY_DEFAULT_HOME = "default_home";
private static final String KEY_ASSIST_AND_VOICE_INPUT = "assist_and_voice_input";
private static final String KEY_DEFAULT_BROWSER = "default_browser";
private static final String KEY_DEFAULT_PHONE_APP = "default_phone_app";
private static final String KEY_DEFAULT_EMERGENCY_APP = "default_emergency_app";
private static final String KEY_SMS_APPLICATION = "default_sms_app";
private static final String KEY_DEFAULT_NOTIFICATION_ASST = "default_notification_asst_app";
+ private static final String[] PREFERENCE_KEYS = new String[] {
+ KEY_DEFAULT_HOME, KEY_ASSIST_AND_VOICE_INPUT, KEY_DEFAULT_BROWSER,
+ KEY_DEFAULT_PHONE_APP, KEY_DEFAULT_EMERGENCY_APP, KEY_SMS_APPLICATION,
+ KEY_DEFAULT_NOTIFICATION_ASST
+ };
private DefaultBrowserPreference mDefaultBrowserPreference;
private PackageManager mPm;
private int myUserId;
-
private static final long DELAY_UPDATE_BROWSER_MILLIS = 500;
private final Handler mHandler = new Handler();
@@ -140,6 +147,7 @@
new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
+
if (newValue == null) {
return false;
}
@@ -157,35 +165,65 @@
return result;
}
});
- final boolean isRestrictedUser = UserManager.get(getActivity())
- .getUserInfo(myUserId).isRestricted();
- // Restricted users cannot currently read/write SMS.
- // Remove SMS Application if the device does not support SMS
- if (isRestrictedUser || !DefaultSmsPreference.isAvailable(getActivity())) {
- removePreference(KEY_SMS_APPLICATION);
- }
+ updatePreferenceVisibility();
+ // Update the index.
+ Index.getInstance(getActivity()).updateFromClassNameResource(
+ ManageDefaultApps.class.getName(), true, true);
+ }
- if (!DefaultPhonePreference.isAvailable(getActivity())) {
- removePreference(KEY_DEFAULT_PHONE_APP);
+ /**
+ * Iterate all preferences and hide it if it is unavailable.
+ */
+ private void updatePreferenceVisibility() {
+ PreferenceScreen preferenceScreen = getPreferenceScreen();
+ int count = preferenceScreen.getPreferenceCount();
+ List<String> preferenceKeys = new ArrayList<>();
+ for (int i = 0; i < count; i++) {
+ String preferenceKey = preferenceScreen.getPreference(i).getKey();
+ if (!TextUtils.isEmpty(preferenceKey)) {
+ preferenceKeys.add(preferenceKey);
+ }
}
+ for (String preferenceKey : preferenceKeys) {
+ boolean isAvailable = getPreferenceAvailability(getContext(), preferenceKey);
+ if (!isAvailable) {
+ Preference preference = preferenceScreen.findPreference(preferenceKey);
+ preferenceScreen.removePreference(preference);
+ }
+ }
+ }
- if (!DefaultEmergencyPreference.isAvailable(getActivity())) {
- removePreference(KEY_DEFAULT_EMERGENCY_APP);
- }
+ /**
+ * Get availability of preference from {@link PreferenceAvailabilityProvider}.
+ */
+ private static boolean getPreferenceAvailability(Context context,
+ String preferenceKey) {
+ // Consider the preference is unavailable if no corresponding provider is found.
+ PreferenceAvailabilityProvider provider = getPreferenceAvailabilityProvider(preferenceKey);
+ return (provider == null) ? false : provider.isAvailable(context);
+ }
- if (!ManageAssist.isAvailable(getActivity())) {
- removePreference(KEY_ASSIST_AND_VOICE_INPUT);
+ private static PreferenceAvailabilityProvider getPreferenceAvailabilityProvider(
+ String preferenceKey) {
+ switch (preferenceKey) {
+ case KEY_ASSIST_AND_VOICE_INPUT:
+ return new ManageAssist.AvailabilityProvider();
+ case KEY_DEFAULT_BROWSER:
+ return new DefaultBrowserPreference.AvailabilityProvider();
+ case KEY_DEFAULT_EMERGENCY_APP:
+ return new DefaultEmergencyPreference.AvailabilityProvider();
+ case KEY_DEFAULT_HOME:
+ return new DefaultHomePreference.AvailabilityProvider();
+ case KEY_DEFAULT_NOTIFICATION_ASST:
+ return new DefaultNotificationAssistantPreference.AvailabilityProvider();
+ case KEY_DEFAULT_PHONE_APP:
+ return new DefaultPhonePreference.AvailabilityProvider();
+ case KEY_SMS_APPLICATION:
+ return new DefaultSmsPreference.AvailabilityProvider();
}
-
- if (!DefaultNotificationAssistantPreference.isAvailable(getActivity())) {
- removePreference(KEY_DEFAULT_NOTIFICATION_ASST);
- }
-
- if (DefaultEmergencyPreference.isCapable(getActivity())) {
- Index.getInstance(getActivity()).updateFromClassNameResource(
- ManageDefaultApps.class.getName(), true, true);
- }
+ Log.w(TAG, "getPreferenceAvailabilityProvider: Cannot find provider for " + preferenceKey);
+ return null;
}
@Override
@@ -224,19 +262,14 @@
@Override
public List<String> getNonIndexableKeys(Context context) {
- final ArrayList<String> result = new ArrayList<String>();
-
- // Remove SMS Application if the device does not support SMS
- final boolean isRestrictedUser = UserManager.get(context)
- .getUserInfo(UserHandle.myUserId()).isRestricted();
- if (!DefaultSmsPreference.isAvailable(context) || isRestrictedUser) {
- result.add(KEY_SMS_APPLICATION);
+ // Iterate all preferences to see which is not available.
+ final ArrayList<String> result = new ArrayList<>();
+ for (String key : PREFERENCE_KEYS) {
+ boolean isAvailable = getPreferenceAvailability(context, key);
+ if (!isAvailable) {
+ result.add(key);
+ }
}
-
- if (!DefaultEmergencyPreference.isAvailable(context)) {
- result.add(KEY_DEFAULT_EMERGENCY_APP);
- }
-
return result;
}
};
diff --git a/src/com/android/settings/dashboard/SuggestionsChecks.java b/src/com/android/settings/dashboard/SuggestionsChecks.java
index d465942..7d617b7 100644
--- a/src/com/android/settings/dashboard/SuggestionsChecks.java
+++ b/src/com/android/settings/dashboard/SuggestionsChecks.java
@@ -20,12 +20,14 @@
import android.app.IWallpaperManagerCallback;
import android.app.KeyguardManager;
import android.app.NotificationManager;
+import android.app.WallpaperManager;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+
import com.android.ims.ImsManager;
import com.android.settings.Settings.FingerprintEnrollSuggestionActivity;
import com.android.settings.Settings.FingerprintSuggestionActivity;
@@ -98,7 +100,8 @@
IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
IWallpaperManager service = Stub.asInterface(b);
try {
- return service.getWallpaper(mCallback, new Bundle()) != null;
+ return service.getWallpaper(mCallback, WallpaperManager.FLAG_SET_SYSTEM,
+ new Bundle(), mContext.getUserId()) != null;
} catch (RemoteException e) {
}
return false;
diff --git a/src/com/android/settings/deviceinfo/StorageItemPreference.java b/src/com/android/settings/deviceinfo/StorageItemPreference.java
index 3875885..b6eedc3 100644
--- a/src/com/android/settings/deviceinfo/StorageItemPreference.java
+++ b/src/com/android/settings/deviceinfo/StorageItemPreference.java
@@ -39,7 +39,11 @@
public void setStorageSize(long size, long total) {
setSummary(Formatter.formatFileSize(getContext(), size));
- progress = (int)(size * PROGRESS_MAX / total);
+ if (total == 0) {
+ progress = 0;
+ } else {
+ progress = (int)(size * PROGRESS_MAX / total);
+ }
updateProgressBar();
}
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
index fffdf74..69247f6 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
@@ -86,6 +86,8 @@
switch (returnCode) {
case PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE:
return getString(R.string.insufficient_storage);
+ case PackageManager.MOVE_FAILED_DEVICE_ADMIN:
+ return getString(R.string.move_error_device_admin);
case PackageManager.MOVE_FAILED_DOESNT_EXIST:
return getString(R.string.does_not_exist);
case PackageManager.MOVE_FAILED_FORWARD_LOCKED:
diff --git a/src/com/android/settings/display/DisplayDensityUtils.java b/src/com/android/settings/display/DisplayDensityUtils.java
index cef5418..891b7fb 100644
--- a/src/com/android/settings/display/DisplayDensityUtils.java
+++ b/src/com/android/settings/display/DisplayDensityUtils.java
@@ -116,7 +116,8 @@
if (numSmaller > 0) {
final float interval = (1 - minScale) / numSmaller;
for (int i = numSmaller - 1; i >= 0; i--) {
- final int density = (int) (normalDensity * (1 - (i + 1) * interval));
+ // Round down to a multiple of 2 by truncating the low bit.
+ final int density = ((int) (normalDensity * (1 - (i + 1) * interval))) & ~1;
if (currentDensity == density) {
currentDensityIndex = curIndex;
}
@@ -136,7 +137,8 @@
if (numLarger > 0) {
final float interval = (maxScale - 1) / numLarger;
for (int i = 0; i < numLarger; i++) {
- final int density = (int) (normalDensity * (1 + (i + 1) * interval));
+ // Round down to a multiple of 2 by truncating the low bit.
+ final int density = ((int) (normalDensity * (1 + (i + 1) * interval))) & ~1;
if (currentDensity == density) {
currentDensityIndex = curIndex;
}
diff --git a/src/com/android/settings/display/ScreenZoomSettings.java b/src/com/android/settings/display/ScreenZoomSettings.java
index 406c993..d87f230 100644
--- a/src/com/android/settings/display/ScreenZoomSettings.java
+++ b/src/com/android/settings/display/ScreenZoomSettings.java
@@ -50,7 +50,7 @@
// This should be replaced once the final preview sample screen is in place.
mPreviewSampleResIds = new int[]{R.layout.screen_zoom_preview_1,
R.layout.screen_zoom_preview_2,
- R.layout.screen_zoom_preview_3};
+ R.layout.screen_zoom_preview_settings};
final DisplayDensityUtils density = new DisplayDensityUtils(getContext());
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index 461c498..7aafeba 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -17,17 +17,17 @@
package com.android.settings.fuelgauge;
import android.content.Context;
-import android.content.Intent;
-import android.os.BatteryStats;
import android.os.Bundle;
+import android.os.SystemClock;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
-import android.view.ViewGroup;
-
+import android.widget.TextView;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
-import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
+import com.android.settingslib.BatteryInfo;
+import com.android.settingslib.graph.UsageView;
/**
* Custom preference for displaying power consumption as a bar and an icon on the left for the
@@ -38,73 +38,41 @@
protected static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
- private BatteryStats mStats;
- private Intent mBatteryBroadcast;
-
- private BatteryHistoryChart mChart;
private BatteryStatsHelper mHelper;
+ private BatteryInfo mBatteryInfo;
public BatteryHistoryPreference(Context context, AttributeSet attrs) {
super(context, attrs);
+ setLayoutResource(R.layout.battery_usage_graph);
}
-
+
@Override
protected void onClick() {
- if (!isEnabled()) {
- return;
- }
mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
Bundle args = new Bundle();
args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
- args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST,
- mHelper.getBatteryBroadcast());
- if (getContext() instanceof SettingsActivity) {
- SettingsActivity sa = (SettingsActivity) getContext();
- sa.startPreferencePanel(BatteryHistoryDetail.class.getName(), args,
- R.string.history_details_title, null, null, 0);
- }
+ args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST, mHelper.getBatteryBroadcast());
+ Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
+ null, 0, R.string.history_details_title, null);
}
public void setStats(BatteryStatsHelper batteryStats) {
- // Clear out the chart to receive new data.
- mChart = null;
mHelper = batteryStats;
- mStats = batteryStats.getStats();
- mBatteryBroadcast = batteryStats.getBatteryBroadcast();
- if (getLayoutResource() != R.layout.battery_history_chart) {
- // Now we should have some data, set the layout we want.
- setLayoutResource(R.layout.battery_history_chart);
- }
+ final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
+ mBatteryInfo = BatteryInfo.getBatteryInfo(getContext(), batteryStats.getBatteryBroadcast(),
+ batteryStats.getStats(), elapsedRealtimeUs);
notifyChanged();
}
- BatteryStats getStats() {
- return mStats;
- }
-
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
-
- if (mStats == null) {
+ if (mBatteryInfo == null) {
return;
}
- BatteryHistoryChart chart = (BatteryHistoryChart) view.findViewById(
- R.id.battery_history_chart);
- if (mChart == null) {
- // First time: use and initialize this chart.
- chart.setStats(mStats, mBatteryBroadcast);
- mChart = chart;
- } else {
- // All future times: forget the newly inflated chart, re-use the
- // already initialized chart from last time.
- ViewGroup parent = (ViewGroup) chart.getParent();
- int index = parent.indexOfChild(chart);
- parent.removeViewAt(index);
- if (mChart.getParent() != null) {
- ((ViewGroup) mChart.getParent()).removeView(mChart);
- }
- parent.addView(mChart, index);
- }
+ view.setDividerAllowedAbove(true);
+ ((TextView) view.findViewById(R.id.charge)).setText(mBatteryInfo.batteryPercentString);
+ ((TextView) view.findViewById(R.id.estimation)).setText(mBatteryInfo.remainingLabel);
+ UsageView usageView = (UsageView) view.findViewById(R.id.battery_usage);
+ mBatteryInfo.bindHistory(usageView);
}
}
diff --git a/src/com/android/settings/fuelgauge/BatterySaverPreference.java b/src/com/android/settings/fuelgauge/BatterySaverPreference.java
new file mode 100644
index 0000000..9e0f39b
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatterySaverPreference.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 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.database.ContentObserver;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.support.v7.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import com.android.settings.R;
+import com.android.settings.Utils;
+
+public class BatterySaverPreference extends Preference {
+
+ private PowerManager mPowerManager;
+
+ public BatterySaverPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void performClick(View view) {
+ Utils.startWithFragment(getContext(), getFragment(), null, null, 0, 0, getTitle());
+ }
+
+ @Override
+ public void onAttached() {
+ super.onAttached();
+ mPowerManager = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
+ mObserver.onChange(true);
+ getContext().getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Global.LOW_POWER_MODE_TRIGGER_LEVEL), true, mObserver);
+ getContext().getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Global.LOW_POWER_MODE), true, mObserver);
+ }
+
+ @Override
+ public void onDetached() {
+ super.onDetached();
+ getContext().getContentResolver().unregisterContentObserver(mObserver);
+ }
+
+ private void updateSwitch() {
+ final Context context = getContext();
+ final boolean mode = mPowerManager.isPowerSaveMode();
+ int format = mode ? R.string.battery_saver_on_summary
+ : R.string.battery_saver_off_summary;
+ int percent = Settings.Global.getInt(context.getContentResolver(),
+ Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+ int percentFormat = percent > 0 ? R.string.battery_saver_desc_turn_on_auto_pct
+ : R.string.battery_saver_desc_turn_on_auto_never;
+ setSummary(context.getString(format, context.getString(percentFormat,
+ Utils.formatPercentage(percent))));
+ }
+
+ private final ContentObserver mObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateSwitch();
+ }
+ };
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index 5b39a14..b0bf4b4 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -20,30 +20,37 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.preference.PreferenceViewHolder;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
-
-import com.android.settings.AppProgressPreference;
+import com.android.settings.R;
+import com.android.settings.TintablePreference;
import com.android.settings.Utils;
/**
* Custom preference for displaying power consumption as a bar and an icon on
* the left for the subsystem/app type.
*/
-public class PowerGaugePreference extends AppProgressPreference {
+public class PowerGaugePreference extends TintablePreference {
+ private final int mIconSize;
+
private BatteryEntry mInfo;
private final CharSequence mContentDescription;
+ private CharSequence mProgress;
public PowerGaugePreference(Context context, Drawable icon, CharSequence contentDescription,
BatteryEntry info) {
super(context, null);
setIcon(icon != null ? icon : new ColorDrawable(0));
+ setWidgetLayoutResource(R.layout.preference_widget_summary);
mInfo = info;
mContentDescription = contentDescription;
+ mIconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
}
public void setPercent(double percentOfMax, double percentOfTotal) {
- setProgress((int) Math.ceil(percentOfMax));
- setSummary(Utils.formatPercentage((int) (percentOfTotal + 0.5)));
+ mProgress = Utils.formatPercentage((int) (percentOfTotal + 0.5));
+ notifyChanged();
}
BatteryEntry getInfo() {
@@ -53,7 +60,10 @@
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
+ ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
+ icon.setLayoutParams(new LinearLayout.LayoutParams(mIconSize, mIconSize));
+ ((TextView) view.findViewById(R.id.widget_summary)).setText(mProgress);
if (mContentDescription != null) {
final TextView titleView = (TextView) view.findViewById(android.R.id.title);
titleView.setContentDescription(mContentDescription);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index d7b6849..a0d276f 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -65,7 +65,6 @@
private static final String KEY_BATTERY_HISTORY = "battery_history";
private static final int MENU_STATS_TYPE = Menu.FIRST;
- private static final int MENU_BATTERY_SAVER = Menu.FIRST + 2;
private static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
private static final int MENU_HELP = Menu.FIRST + 4;
@@ -134,9 +133,6 @@
.setAlphabeticShortcut('t');
}
- MenuItem batterySaver = menu.add(0, MENU_BATTERY_SAVER, 0, R.string.battery_saver);
- batterySaver.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-
menu.add(0, MENU_HIGH_POWER_APPS, 0, R.string.high_power_apps);
super.onCreateOptionsMenu(menu, inflater);
}
@@ -158,10 +154,6 @@
}
refreshStats();
return true;
- case MENU_BATTERY_SAVER:
- sa.startPreferencePanel(BatterySaverSettings.class.getName(), null,
- R.string.battery_saver, null, null, 0);
- return true;
case MENU_HIGH_POWER_APPS:
Bundle args = new Bundle();
args.putString(ManageApplications.EXTRA_CLASSNAME,
@@ -280,6 +272,7 @@
protected void refreshStats() {
super.refreshStats();
+ PowerWhitelistBackend powerWhiteist = PowerWhitelistBackend.getInstance();
updatePreference(mHistPref);
mAppListGroup.removeAll();
mAppListGroup.setOrderingAsAdded(false);
@@ -352,6 +345,12 @@
pref.setTitle(entry.getLabel());
pref.setOrder(i + 1);
pref.setPercent(percentOfMax, percentOfTotal);
+ if (sipper.drainType == DrainType.APP) {
+ pref.setSummary(powerWhiteist.isWhitelisted(entry.defaultPackageName)
+ || powerWhiteist.isSysWhitelisted(entry.defaultPackageName)
+ ? getString(R.string.not_battery_optimizing)
+ : null);
+ }
if (sipper.uidObj != null) {
pref.setKey(Integer.toString(sipper.uidObj.getUid()));
}
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index 7504218..dcf50e8 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -64,6 +64,9 @@
/** Preference key for the TTS rate selection dialog. */
private static final String KEY_DEFAULT_RATE = "tts_default_rate";
+ /** Preference key for the TTS reset speech rate preference. */
+ private static final String KEY_RESET_SPEECH_RATE = "reset_speech_rate";
+
/** Preference key for the TTS status field. */
private static final String KEY_STATUS = "tts_status";
@@ -87,6 +90,7 @@
private PreferenceCategory mEnginePreferenceCategory;
private SeekBarPreference mDefaultRatePref;
private SwitchPreference mHigherRateSwitchPref;
+ private Preference mResetSpeechRate;
private Preference mPlayExample;
private Preference mEngineStatus;
@@ -171,6 +175,9 @@
mPlayExample.setOnPreferenceClickListener(this);
mPlayExample.setEnabled(false);
+ mResetSpeechRate = findPreference(KEY_RESET_SPEECH_RATE);
+ mResetSpeechRate.setOnPreferenceClickListener(this);
+
mEnginePreferenceCategory = (PreferenceCategory) findPreference(
KEY_ENGINE_PREFERENCE_SECTION);
mDefaultRatePref = (SeekBarPreference) findPreference(KEY_DEFAULT_RATE);
@@ -459,24 +466,13 @@
@Override
public boolean onPreferenceChange(Preference preference, Object objValue) {
if (KEY_DEFAULT_RATE.equals(preference.getKey())) {
- // Default rate
- mDefaultRate = ((Integer) objValue).intValue();
- try {
- android.provider.Settings.Secure.putInt(getContentResolver(),
- TTS_DEFAULT_RATE, mDefaultRate);
- if (mTts != null) {
- mTts.setSpeechRate(mDefaultRate / 100.0f);
- }
- if (DBG) Log.d(TAG, "TTS default rate changed, now " + mDefaultRate);
- } catch (NumberFormatException e) {
- Log.e(TAG, "could not persist default TTS rate setting", e);
- }
+ updateSpeechRate(((Integer) objValue).intValue());
}
return true;
}
/**
- * Called when mPlayExample is clicked
+ * Called when mPlayExample or mResetSpeechRate is clicked.
*/
@Override
public boolean onPreferenceClick(Preference preference) {
@@ -485,11 +481,29 @@
// the actual speaking
speakSampleText();
return true;
+ } else if (preference == mResetSpeechRate) {
+ mDefaultRatePref.setProgress(TextToSpeech.Engine.DEFAULT_RATE);
+ updateSpeechRate(TextToSpeech.Engine.DEFAULT_RATE);
+ return true;
}
-
return false;
}
+ private void updateSpeechRate(int speechRate) {
+ mDefaultRate = speechRate;
+ try {
+ android.provider.Settings.Secure.putInt(getContentResolver(),
+ TTS_DEFAULT_RATE, mDefaultRate);
+ if (mTts != null) {
+ mTts.setSpeechRate(mDefaultRate / 100.0f);
+ }
+ if (DBG) Log.d(TAG, "TTS default rate changed, now " + mDefaultRate);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "could not persist default TTS rate setting", e);
+ }
+ return;
+ }
+
private void updateWidgetState(boolean enable) {
mPlayExample.setEnabled(enable);
mDefaultRatePref.setEnabled(enable);
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 6a50a6d..8ff26f7 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -104,7 +104,6 @@
private static final String KEY_USER_ME = "user_me";
private static final String KEY_ADD_USER = "user_add";
private static final String KEY_EMERGENCY_INFO = "emergency_info";
- private static final String KEY_LOCK_SCREEN_SETTINGS = "lock_screen_settings";
private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENGY_INFO";
@@ -237,14 +236,6 @@
mLockScreenSettings = (PreferenceGroup) findPreference("lock_screen_settings");
mAddUserWhenLocked = (RestrictedSwitchPreference) findPreference("add_users_when_locked");
mEmergencyInfoPreference = findPreference(KEY_EMERGENCY_INFO);
- if(emergencyInfoActivityPresent()) {
- mEmergencyInfoPreference.setOnPreferenceClickListener(this);
- } else {
- // Remove this view if the emergency info package is not found.
- PreferenceCategory lockScreenSettingsCategory =
- (PreferenceCategory) findPreference(KEY_LOCK_SCREEN_SETTINGS);
- lockScreenSettingsCategory.removePreference(mEmergencyInfoPreference);
- }
loadProfile();
setHasOptionsMenu(true);
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
@@ -843,6 +834,12 @@
mAddUserWhenLocked.setDisabledByAdmin(
mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
}
+
+ if (emergencyInfoActivityPresent()) {
+ mEmergencyInfoPreference.setOnPreferenceClickListener(this);
+ mEmergencyInfoPreference.setOrder(Preference.DEFAULT_ORDER);
+ preferenceScreen.addPreference(mEmergencyInfoPreference);
+ }
}
private int getMaxRealUsers() {
diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
index bf093d4..019103f 100644
--- a/src/com/android/settings/widget/SwitchBar.java
+++ b/src/com/android/settings/widget/SwitchBar.java
@@ -318,11 +318,15 @@
requestLayout();
}
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return Switch.class.getName();
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
- info.setClassName(Switch.class.getName());
info.setText(mTextView.getText());
info.setCheckable(true);
info.setChecked(mSwitch.isChecked());
@@ -332,7 +336,10 @@
@Override
public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
super.onInitializeAccessibilityEventInternal(event);
- event.setClassName(Switch.class.getName());
+ // Don't say "on on" or "off off" - rather, speak the state only once. We need to specify
+ // this explicitly as each of our children (the textview and the checkbox) contribute to
+ // the state once, giving us duplicate text by default.
+ event.setContentDescription(mTextView.getText());
event.setChecked(mSwitch.isChecked());
}
}