Merge "Fix searched item isn't highlighted" am: 363c529dc6 am: 1d07de566d
am: 85768b3723
Change-Id: I7bb1c3b3a5dbb1ee4e6d8934a7be542076d1e863
diff --git a/Android.mk b/Android.mk
index 61734fb..537004e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,6 +1,16 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ $(call all-logtags-files-under, src)
+
+LOCAL_MODULE := settings-logtags
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Build the Settings APK
+include $(CLEAR_VARS)
+
LOCAL_JAVA_LIBRARIES := bouncycastle core-oj telephony-common ims-common
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-v4 \
@@ -9,13 +19,13 @@
android-support-v7-preference \
android-support-v7-appcompat \
android-support-v14-preference \
- jsr305
+ jsr305 \
+ settings-logtags
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
- src/com/android/settings/EventLogTags.logtags
+ $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
frameworks/support/v7/preference/res \
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 48e8c03..9dd7383 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -67,6 +67,7 @@
<uses-permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
+ <uses-permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" />
<uses-permission android:name="android.permission.SET_TIME" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" />
<uses-permission android:name="android.permission.REBOOT" />
@@ -81,6 +82,7 @@
<uses-permission android:name="android.permission.CHANGE_APP_IDLE_STATE" />
<uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
<uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS"/>
+ <uses-permission android:name="android.permission.DELETE_PACKAGES"/>
<application android:label="@string/settings_label"
android:icon="@mipmap/ic_launcher_settings"
@@ -119,6 +121,7 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
+ <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
</activity-alias>
<activity android:name=".Settings$WirelessSettings"
@@ -207,7 +210,7 @@
<activity android:name="AirplaneModeVoiceActivity"
android:label="@string/wireless_networks_settings_title"
- android:theme="@android:style/Theme.Material.Light.Voice"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Voice"
android:exported="true">
<intent-filter>
<action android:name="android.settings.VOICE_CONTROL_AIRPLANE_MODE" />
@@ -377,11 +380,15 @@
android:exported="true"
android:permission="android.permission.CONNECTIVITY_INTERNAL"
android:taskAffinity=""
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter>
<action android:name="android.net.conn.PROMPT_UNVALIDATED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.net.conn.PROMPT_LOST_VALIDATION" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
@@ -558,7 +565,7 @@
<activity android:name="DateTimeSettingsSetupWizard"
android:label="@string/date_and_time"
- android:theme="@android:style/Theme.Material.Light.NoActionBar"
+ android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar"
android:screenOrientation="behind">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -727,7 +734,7 @@
<activity android:name=".inputmethod.UserDictionaryAddWordActivity"
android:label="@string/user_dict_settings_title"
- android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
android:windowSoftInputMode="stateVisible"
android:noHistory="true"
android:excludeFromRecents="true">
@@ -851,29 +858,23 @@
android:label="@string/wallpaper_settings_fragment_title"
android:icon="@drawable/ic_wallpaper"
android:taskAffinity="">
- <intent-filter android:priority="1">
- <action android:name="android.settings.WALLPAPER_SETTINGS" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.WallpaperTypeSettings" />
</activity>
- <activity android:name="Settings$WallpaperSuggestionActivity"
- android:label="@string/wallpaper_settings_title"
- android:exported="true"
- android:icon="@drawable/ic_wallpaper"
- android:taskAffinity="">
+ <activity android:name="WallpaperSuggestionActivity"
+ android:label="@string/wallpaper_settings_title"
+ android:icon="@drawable/ic_wallpaper"
+ android:exported="true"
+ android:theme="@android:style/Theme.NoDisplay">
<intent-filter android:priority="1">
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.SETTINGS_ONLY" />
</intent-filter>
- <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.WallpaperTypeSettings" />
<meta-data android:name="com.android.settings.title"
- android:resource="@string/wallpaper_suggestion_title" />
+ android:resource="@string/wallpaper_suggestion_title" />
<meta-data android:name="com.android.settings.summary"
- android:resource="@string/wallpaper_suggestion_summary" />
+ android:resource="@string/wallpaper_suggestion_summary" />
</activity>
<activity android:name="Settings$ZenModeScheduleRuleSettingsActivity"
@@ -962,6 +963,26 @@
android:value="com.android.settings.DisplaySettings" />
</activity-alias>
+ <activity android:name="Settings$NightDisplaySettingsActivity"
+ android:label="@string/night_display_title"
+ android:enabled="@*android:bool/config_nightDisplayAvailable"
+ android:icon="@drawable/ic_settings_night_display"
+ android:taskAffinity="">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.NIGHT_DISPLAY_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="com.android.settings.SHORTCUT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.display.NightDisplaySettings" />
+ <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+ android:value="true" />
+ </activity>
+
<activity android:name="Settings$DeviceInfoSettingsActivity"
android:theme="@style/Theme.SubSettingsDialogWhenLarge"
android:label="@string/device_info_settings"
@@ -992,7 +1013,7 @@
<activity android:name="SettingsLicenseActivity"
android:label="@string/settings_license_activity_title"
- android:theme="@android:style/Theme.Material.Light.Panel"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Panel"
android:configChanges="orientation|screenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.LICENSE" />
@@ -1028,6 +1049,20 @@
android:value="true" />
</activity>
+ <activity android:name="Settings$ManageDomainUrlsActivity"
+ android:taskAffinity="com.android.settings"
+ android:label="@string/domain_urls_title"
+ android:icon="@drawable/ic_settings_memory">
+ <intent-filter>
+ <action android:name="android.settings.MANAGE_DOMAIN_URLS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.category"
+ android:value="com.android.settings.category.device" />
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.applications.ManageDomainUrls" />
+ </activity>
+
<activity android:name="Settings$MemorySettingsActivity"
android:label="@string/memory_settings_title"
android:icon="@drawable/ic_settings_memory"
@@ -1097,7 +1132,7 @@
<activity android:name=".fuelgauge.RequestIgnoreBatteryOptimizations"
android:label="@string/high_power_apps"
android:taskAffinity=""
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1">
<action android:name="android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<category android:name="android.intent.category.DEFAULT" />
@@ -1215,7 +1250,7 @@
</activity>
<activity android:name=".notification.ZenModeVoiceActivity"
- android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
android:label="@string/zen_mode_settings_title">
<intent-filter>
<action android:name="android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE" />
@@ -1585,7 +1620,8 @@
android:enabled="false"
android:exported="true"
android:taskAffinity="com.android.wizard"
- android:theme="@style/SetupWizardDisableAppStartingTheme"
+ android:theme="@style/SuwThemeGlif.Light"
+ android:label="@string/lock_screen_notifications_interstitial_title"
android:icon="@drawable/ic_suggested_notifications">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -1599,7 +1635,8 @@
android:resource="@string/notification_suggestion_summary" />
</activity>
- <activity android:name=".notification.RedactionInterstitial"/>
+ <activity android:name=".notification.RedactionInterstitial"
+ android:theme="@style/SetupWizardTheme.Light" />
<activity android:name=".notification.RedactionSettingsStandalone"
android:exported="true">
@@ -1646,7 +1683,7 @@
<activity android:name=".fingerprint.SetupFingerprintEnrollIntroduction"
android:exported="true"
android:permission="android.permission.MANAGE_FINGERPRINT"
- android:theme="@style/SetupWizardDisableAppStartingTheme">
+ android:theme="@style/SetupWizardTheme.Light">
<intent-filter>
<action android:name="android.settings.FINGERPRINT_SETUP" />
<category android:name="android.intent.category.DEFAULT" />
@@ -1666,7 +1703,7 @@
<activity android:name="SetupChooseLockGeneric"
android:taskAffinity="com.android.wizard"
- android:theme="@style/SetupWizardDisableAppStartingTheme"
+ android:theme="@style/SetupWizardTheme.Light"
android:label="@string/lock_settings_picker_title">
<intent-filter android:priority="1">
<action android:name="com.android.settings.SETUP_LOCK_SCREEN" />
@@ -1676,6 +1713,11 @@
<activity android:name="ChooseLockGeneric"
android:label="@string/lockpassword_choose_lock_generic_header"
+ android:excludeFromRecents="true"
+ android:exported="false" />
+
+ <activity android:name=".password.SetNewPasswordActivity"
+ android:theme="@android:style/Theme.NoDisplay"
android:excludeFromRecents="true" >
<intent-filter android:priority="1">
<action android:name="android.app.action.SET_NEW_PASSWORD" />
@@ -1711,7 +1753,7 @@
<meta-data android:name="com.android.settings.require_feature"
android:value="android.hardware.fingerprint" />
<meta-data android:name="com.android.settings.title"
- android:resource="@string/suggested_lock_settings_title" />
+ android:resource="@string/suggested_fingerprint_lock_settings_title" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/suggested_fingerprint_lock_settings_summary" />
</activity>
@@ -1724,33 +1766,36 @@
<activity android:name="SetupChooseLockPattern"
android:exported="false"
android:taskAffinity="com.android.wizard"
- android:theme="@style/SetupWizardDisableAppStartingTheme" />
+ android:theme="@style/SetupWizardTheme.Light" />
- <activity android:name="ChooseLockPattern" android:exported="false"/>
+ <activity android:name="ChooseLockPattern"
+ android:exported="false"
+ android:theme="@style/SetupWizardTheme.Light" />
<activity android:name="SetupChooseLockPassword"
android:exported="false"
android:taskAffinity="com.android.wizard"
- android:theme="@style/SetupWizardDisableAppStartingTheme"
+ android:theme="@style/SetupWizardTheme.Light"
android:windowSoftInputMode="stateVisible|adjustResize" />
- <activity android:name="ChooseLockPassword" android:exported="false"
+ <activity android:name="ChooseLockPassword"
+ android:exported="false"
+ android:theme="@style/SetupWizardTheme.Light"
android:windowSoftInputMode="stateVisible|adjustResize"/>
<activity android:name=".SetupEncryptionInterstitial"
android:label="@string/encryption_interstitial_header"
android:taskAffinity="com.android.wizard"
- android:theme="@style/SetupWizardDisableAppStartingTheme"/>
+ android:theme="@style/SetupWizardTheme.Light"/>
- <activity android:name=".EncryptionInterstitial"/>
+ <activity android:name=".EncryptionInterstitial"
+ android:theme="@style/SetupWizardTheme.Light" />
- <!-- Runs in the phone process since it needs access to the Phone object -->
<activity android:name=".Settings$StatusActivity"
android:label="@string/device_status_activity_title"
android:theme="@style/Theme.SubSettingsDialogWhenLarge"
android:taskAffinity="com.android.settings"
- android:parentActivityName="Settings$DeviceInfoSettingsActivity"
- android:process="com.android.phone">
+ android:parentActivityName="Settings$DeviceInfoSettingsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
@@ -1975,7 +2020,7 @@
</activity-alias>
<activity android:name=".AppPicker" android:label="@string/select_application"
- android:theme="@android:style/Theme.Material.Light.Dialog" />
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" />
<!-- Keep compatibility with old shortcuts. -->
<activity-alias android:name="UsbSettings"
@@ -1992,7 +2037,7 @@
android:label="@string/bluetooth_pairing_request"
android:excludeFromRecents="true"
android:windowSoftInputMode="stateVisible|adjustResize"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1">
<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2025,7 +2070,7 @@
android:label="@string/bluetooth_permission_request"
android:excludeFromRecents="true"
android:permission="android.permission.BLUETOOTH"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1">
<action android:name="android.bluetooth.adapter.action.REQUEST_DISCOVERABLE" />
<action android:name="android.bluetooth.adapter.action.REQUEST_ENABLE" />
@@ -2046,14 +2091,14 @@
android:excludeFromRecents="true"
android:exported="true"
android:permission="android.permission.MANAGE_USB"
- android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar">
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar">
</activity>
<activity android:name=".RemoteBugreportActivity"
android:excludeFromRecents="true"
android:exported="true"
android:permission="android.permission.DUMP"
- android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar">
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar">
<intent-filter>
<action android:name="android.settings.SHOW_REMOTE_BUGREPORT_DIALOG" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2064,7 +2109,7 @@
android:label="@string/bluetooth_pairing_request"
android:excludeFromRecents="true"
android:permission="android.permission.BLUETOOTH"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
</activity>
<receiver android:name=".bluetooth.BluetoothPairingRequest">
@@ -2087,7 +2132,7 @@
android:label="@string/bluetooth_connection_permission_request"
android:excludeFromRecents="true"
android:permission="android.permission.BLUETOOTH_ADMIN"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1">
<action android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
<action android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
@@ -2097,7 +2142,7 @@
<activity android:name="ActivityPicker"
android:label="@string/activity_picker_label"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true">
<intent-filter android:priority="1">
<action android:name="android.intent.action.PICK_ACTIVITY" />
@@ -2160,7 +2205,7 @@
<!-- TODO: Is this needed? -->
<activity android:name="BandMode"
- android:theme="@android:style/Theme.Material.Light.Dialog.Alert"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:process="com.android.phone">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -2188,7 +2233,7 @@
<!-- Standard picker for widgets -->
<activity android:name="AppWidgetPickActivity"
android:label="@string/widget_picker_title"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true">
<intent-filter android:priority="1">
<action android:name="android.appwidget.action.APPWIDGET_PICK" />
@@ -2197,7 +2242,7 @@
</activity>
<activity android:name="AllowBindAppWidgetActivity"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
<intent-filter android:priority="1">
@@ -2267,7 +2312,7 @@
<activity android:name=".fuelgauge.BatterySaverModeVoiceActivity"
android:label="@string/power_usage_summary_title"
- android:theme="@android:style/Theme.Material.Light.Voice"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Voice"
android:exported="true">
<intent-filter>
<action android:name="android.settings.VOICE_CONTROL_BATTERY_SAVER_MODE" />
@@ -2364,6 +2409,7 @@
<!-- Triggered when user-selected home app isn't encryption aware -->
<activity android:name=".FallbackHome"
android:excludeFromRecents="true"
+ android:screenOrientation="nosensor"
android:theme="@style/FallbackHome">
<intent-filter android:priority="-1000">
<action android:name="android.intent.action.MAIN" />
@@ -2485,7 +2531,7 @@
<activity android:name=".nfc.PaymentDefaultDialog"
android:label="@string/nfc_payment_set_default_label"
android:excludeFromRecents="true"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1">
<action android:name="android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2503,7 +2549,7 @@
<activity android:name=".SmsDefaultDialog"
android:label="@string/sms_application_title"
android:excludeFromRecents="true"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1">
<action android:name="android.provider.Telephony.ACTION_CHANGE_DEFAULT" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2513,7 +2559,7 @@
<activity android:name=".ActiveNetworkScorerDialog"
android:label="@string/wifi_assistant_title"
android:excludeFromRecents="true"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter android:priority="1">
<action android:name="android.net.scoring.CHANGE_ACTIVE" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2687,7 +2733,7 @@
<!-- Show regulatory info (from settings item or dialing "*#07#") -->
<activity android:name="RegulatoryInfoDisplayActivity"
- android:label="@string/regulatory_information"
+ android:label="@string/regulatory_labels"
android:taskAffinity=""
android:enabled="@bool/config_show_regulatory_info">
<intent-filter>
@@ -2766,7 +2812,7 @@
</activity>
<activity android:name=".sim.SimPreferenceDialog"
- android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
android:excludeFromRecents="true">
</activity>
@@ -2784,7 +2830,7 @@
</activity>
<activity android:name=".sim.SimDialogActivity"
- android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
android:label="@string/sim_settings_title"
android:excludeFromRecents="true">
<intent-filter>
@@ -2910,7 +2956,7 @@
<activity android:name=".WebViewImplementation"
android:exported="true"
android:excludeFromRecents="true"
- android:theme="@*android:style/Theme.Material.Light.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter>
<action android:name="android.settings.WEBVIEW_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2919,6 +2965,63 @@
android:value="true" />
</activity>
+ <!-- activity for gesture settings -->
+ <activity android:name="Settings$GestureSettingsActivity"
+ android:label="@string/gesture_preference_title"
+ android:icon="@drawable/ic_settings_gestures"
+ android:enabled="@bool/config_gesture_settings_enabled">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.settings.SHORTCUT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="com.android.settings.action.SETTINGS" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.category"
+ android:value="com.android.settings.category.device" />
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.gestures.GestureSettings" />
+ <meta-data android:name="com.android.settings.summary"
+ android:resource="@string/gesture_preference_summary" />
+ </activity>
+
+ <activity android:name="BackupSettingsActivity"
+ android:label="@string/privacy_settings_title"
+ android:icon="@drawable/ic_settings_backup"
+ android:theme="@android:style/Theme.NoDisplay"
+ android:taskAffinity="com.android.settings"
+ android:parentActivityName="Settings">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.PRIVACY_SETTINGS" />
+ <action android:name="android.settings.BACKUP_AND_RESET_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.VOICE_LAUNCH" />
+ </intent-filter>
+ <intent-filter android:priority="-2">
+ <action android:name="com.android.settings.action.SETTINGS" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.category"
+ android:value="com.android.settings.category.personal" />
+ <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+ android:value="true" />
+ </activity>
+
+ <activity android:name="Settings$AutomaticStorageManagerSettingsActivity"
+ android:exported="@bool/config_storage_manager_settings_enabled"
+ android:label="@string/automatic_storage_manager_settings"
+ android:taskAffinity="">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.STORAGE_MANAGER_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.deletionhelper.AutomaticStorageManagerSettings" />
+ </activity>
+
<service
android:name=".SettingsDumpService"
android:exported="true"
@@ -2978,6 +3081,13 @@
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
+
+ <activity android:name=".HelpTrampoline"
+ android:exported="true"
+ android:theme="@android:style/Theme.NoDisplay"
+ android:permission="android.permission.DUMP"
+ android:enabled="@bool/config_has_help" />
+
<!-- This is the longest AndroidManifest.xml ever. -->
</application>
</manifest>
diff --git a/proguard.flags b/proguard.flags
index 3c3300e..040fa6c 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -17,8 +17,10 @@
-keep class com.android.settings.users.*
-keep class com.android.settings.nfc.*
-keep class com.android.settings.notification.*
+-keep class com.android.settings.overlay.FeatureFactoryImpl
-keep class com.android.settings.accessibility.*FragmentForSetupWizard
-keep class com.android.settings.display.*FragmentForSetupWizard
+-keep class com.android.settings.display.NightDisplaySettings
# Keep click responders
-keepclassmembers class com.android.settings.inputmethod.UserDictionaryAddWordActivity {
diff --git a/res/values-sw360dp/aliases.xml b/res/color/sliding_tab_title_text_color.xml
similarity index 69%
copy from res/values-sw360dp/aliases.xml
copy to res/color/sliding_tab_title_text_color.xml
index a10585b..925ab97 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/color/sliding_tab_title_text_color.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!--
+ Copyright (C) 2016 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.
@@ -14,7 +15,8 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="false"
+ android:color="#b3ffffff"/>
+ <item android:color="@android:color/white"/>
+</selector>
diff --git a/res/drawable-hdpi/ic_bt_config.png b/res/drawable-hdpi/ic_bt_config.png
deleted file mode 100644
index a204936..0000000
--- a/res/drawable-hdpi/ic_bt_config.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_bt_imaging.png b/res/drawable-hdpi/ic_bt_imaging.png
deleted file mode 100644
index 62624ee..0000000
--- a/res/drawable-hdpi/ic_bt_imaging.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_bt_laptop.png b/res/drawable-hdpi/ic_bt_laptop.png
deleted file mode 100644
index 42c3dc5..0000000
--- a/res/drawable-hdpi/ic_bt_laptop.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_lockscreen_ime.png b/res/drawable-hdpi/ic_lockscreen_ime.png
deleted file mode 100644
index 70d35bf..0000000
--- a/res/drawable-hdpi/ic_lockscreen_ime.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_add_dark.png b/res/drawable-hdpi/ic_menu_add_dark.png
deleted file mode 100644
index 40a26b1..0000000
--- a/res/drawable-hdpi/ic_menu_add_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_add_light.png b/res/drawable-hdpi/ic_menu_add_light.png
deleted file mode 100644
index 91b0354..0000000
--- a/res/drawable-hdpi/ic_menu_add_light.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_add_white.png b/res/drawable-hdpi/ic_menu_add_white.png
deleted file mode 100644
index 7638c64..0000000
--- a/res/drawable-hdpi/ic_menu_add_white.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_sysbar_quicksettings.png b/res/drawable-hdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index a204936..0000000
--- a/res/drawable-hdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_bt_config.png b/res/drawable-mdpi/ic_bt_config.png
deleted file mode 100644
index d266b39..0000000
--- a/res/drawable-mdpi/ic_bt_config.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_bt_imaging.png b/res/drawable-mdpi/ic_bt_imaging.png
deleted file mode 100644
index 76234a6..0000000
--- a/res/drawable-mdpi/ic_bt_imaging.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_bt_laptop.png b/res/drawable-mdpi/ic_bt_laptop.png
deleted file mode 100644
index 792e8df..0000000
--- a/res/drawable-mdpi/ic_bt_laptop.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_lockscreen_ime.png b/res/drawable-mdpi/ic_lockscreen_ime.png
deleted file mode 100644
index 3216776..0000000
--- a/res/drawable-mdpi/ic_lockscreen_ime.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_add_dark.png b/res/drawable-mdpi/ic_menu_add_dark.png
deleted file mode 100644
index d7aa774..0000000
--- a/res/drawable-mdpi/ic_menu_add_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_add_light.png b/res/drawable-mdpi/ic_menu_add_light.png
deleted file mode 100644
index 8b55810..0000000
--- a/res/drawable-mdpi/ic_menu_add_light.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_add_white.png b/res/drawable-mdpi/ic_menu_add_white.png
deleted file mode 100644
index 40cdc82..0000000
--- a/res/drawable-mdpi/ic_menu_add_white.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_sysbar_quicksettings.png b/res/drawable-mdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index d266b39..0000000
--- a/res/drawable-mdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_bt_config.png b/res/drawable-xhdpi/ic_bt_config.png
deleted file mode 100644
index 46077be..0000000
--- a/res/drawable-xhdpi/ic_bt_config.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_bt_imaging.png b/res/drawable-xhdpi/ic_bt_imaging.png
deleted file mode 100644
index 9ea3b85..0000000
--- a/res/drawable-xhdpi/ic_bt_imaging.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_bt_laptop.png b/res/drawable-xhdpi/ic_bt_laptop.png
deleted file mode 100644
index 1c053c8..0000000
--- a/res/drawable-xhdpi/ic_bt_laptop.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_lockscreen_ime.png b/res/drawable-xhdpi/ic_lockscreen_ime.png
deleted file mode 100644
index 02cc3af..0000000
--- a/res/drawable-xhdpi/ic_lockscreen_ime.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_add_dark.png b/res/drawable-xhdpi/ic_menu_add_dark.png
deleted file mode 100644
index 2f00b96..0000000
--- a/res/drawable-xhdpi/ic_menu_add_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_add_light.png b/res/drawable-xhdpi/ic_menu_add_light.png
deleted file mode 100644
index 4109b2c..0000000
--- a/res/drawable-xhdpi/ic_menu_add_light.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_add_white.png b/res/drawable-xhdpi/ic_menu_add_white.png
deleted file mode 100644
index 1d53989..0000000
--- a/res/drawable-xhdpi/ic_menu_add_white.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_sysbar_quicksettings.png b/res/drawable-xhdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index 46077be..0000000
--- a/res/drawable-xhdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_bt_config.png b/res/drawable-xxhdpi/ic_bt_config.png
deleted file mode 100644
index ad964b4..0000000
--- a/res/drawable-xxhdpi/ic_bt_config.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_bt_imaging.png b/res/drawable-xxhdpi/ic_bt_imaging.png
deleted file mode 100644
index a0058dc..0000000
--- a/res/drawable-xxhdpi/ic_bt_imaging.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_bt_laptop.png b/res/drawable-xxhdpi/ic_bt_laptop.png
deleted file mode 100644
index bca7145..0000000
--- a/res/drawable-xxhdpi/ic_bt_laptop.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_lockscreen_ime.png b/res/drawable-xxhdpi/ic_lockscreen_ime.png
deleted file mode 100644
index f23b0e7..0000000
--- a/res/drawable-xxhdpi/ic_lockscreen_ime.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_menu_add_dark.png b/res/drawable-xxhdpi/ic_menu_add_dark.png
deleted file mode 100644
index 0ab6a40..0000000
--- a/res/drawable-xxhdpi/ic_menu_add_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_menu_add_light.png b/res/drawable-xxhdpi/ic_menu_add_light.png
deleted file mode 100644
index 767b808..0000000
--- a/res/drawable-xxhdpi/ic_menu_add_light.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_menu_add_white.png b/res/drawable-xxhdpi/ic_menu_add_white.png
deleted file mode 100644
index 16a8b8a..0000000
--- a/res/drawable-xxhdpi/ic_menu_add_white.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_sysbar_quicksettings.png b/res/drawable-xxhdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index ad964b4..0000000
--- a/res/drawable-xxhdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_bt_config.png b/res/drawable-xxxhdpi/ic_bt_config.png
deleted file mode 100644
index e89d484..0000000
--- a/res/drawable-xxxhdpi/ic_bt_config.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_bt_imaging.png b/res/drawable-xxxhdpi/ic_bt_imaging.png
deleted file mode 100644
index f0ffb52..0000000
--- a/res/drawable-xxxhdpi/ic_bt_imaging.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_bt_laptop.png b/res/drawable-xxxhdpi/ic_bt_laptop.png
deleted file mode 100644
index 2d758bd..0000000
--- a/res/drawable-xxxhdpi/ic_bt_laptop.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_lockscreen_ime.png b/res/drawable-xxxhdpi/ic_lockscreen_ime.png
deleted file mode 100644
index 2eb8a92..0000000
--- a/res/drawable-xxxhdpi/ic_lockscreen_ime.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_menu_add_dark.png b/res/drawable-xxxhdpi/ic_menu_add_dark.png
deleted file mode 100644
index 01f53fe..0000000
--- a/res/drawable-xxxhdpi/ic_menu_add_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_menu_add_white.png b/res/drawable-xxxhdpi/ic_menu_add_white.png
deleted file mode 100644
index 27a15f5..0000000
--- a/res/drawable-xxxhdpi/ic_menu_add_white.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_sysbar_quicksettings.png b/res/drawable-xxxhdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index e89d484..0000000
--- a/res/drawable-xxxhdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/drag_handle.xml b/res/drawable/drag_handle.xml
index 33a68c6..835ac5b 100644
--- a/res/drawable/drag_handle.xml
+++ b/res/drawable/drag_handle.xml
@@ -22,6 +22,6 @@
android:tint="@color/material_grey_600">
<path android:fillColor="@android:color/white"
- android:pathData="M8,18v4h32v-4hm-32,8v4h32v-4z" />
+ android:pathData="M6,30h36v-4L6,26v4zM6,38h36v-4L6,34v4zM6,22h36L42,18L6,18v4zM6,10v4h36L42,10L6,10z" />
</vector>
diff --git a/res/drawable/fallback_home_unprovisioned_background.xml b/res/drawable/fallback_home_unprovisioned_background.xml
new file mode 100644
index 0000000..9ec3874
--- /dev/null
+++ b/res/drawable/fallback_home_unprovisioned_background.xml
@@ -0,0 +1,19 @@
+<?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
+ -->
+
+<color xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="#000000" />
\ No newline at end of file
diff --git a/res/drawable/ic_add_24dp.xml b/res/drawable/ic_add_24dp.xml
index 97178b2..2014603 100644
--- a/res/drawable/ic_add_24dp.xml
+++ b/res/drawable/ic_add_24dp.xml
@@ -16,10 +16,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
- android:viewportWidth="48"
- android:viewportHeight="48"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
android:tint="?android:attr/colorAccent">
<path
android:fillColor="@android:color/white"
- android:pathData="M38,26L26,26l0,12l-4,0L22,26L10,26l0,-4l12,0L22,10l4,0l0,12l12,0l0,4.0z"/>
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>
diff --git a/res/drawable/ic_bt_imaging.xml b/res/drawable/ic_bt_imaging.xml
new file mode 100644
index 0000000..01e78c0
--- /dev/null
+++ b/res/drawable/ic_bt_imaging.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19,8L5,8c-1.66,0 -3,1.34 -3,3v6h4v4h12v-4h4v-6c0,-1.66 -1.34,-3
+ -3,-3zM16,19L8,19v-5h8v5zM19,12c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1
+ -1,1zM18,3L6,3v4h12L18,3z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_bt_laptop.xml b/res/drawable/ic_bt_laptop.xml
new file mode 100644
index 0000000..bf2fd49
--- /dev/null
+++ b/res/drawable/ic_bt_laptop.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M20,18c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2H4c-1.1,0
+ -2,0.9 -2,2v10c0,1.1 0.9,2 2,2H0v2h24v-2h-4zM4,6h16v10H4V6z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_call_24dp.xml b/res/drawable/ic_call_24dp.xml
new file mode 100644
index 0000000..26bbde5
--- /dev/null
+++ b/res/drawable/ic_call_24dp.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36
+ 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1 -9.39,0
+ -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57
+ 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
+</vector>
diff --git a/res/values-sw360dp/aliases.xml b/res/drawable/ic_check_green_24dp.xml
similarity index 64%
copy from res/values-sw360dp/aliases.xml
copy to res/drawable/ic_check_green_24dp.xml
index a10585b..c836a02 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/drawable/ic_check_green_24dp.xml
@@ -1,4 +1,3 @@
-<?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");
@@ -14,7 +13,12 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"
+ android:fillColor="#0F9D58"/>
+</vector>
diff --git a/res/values-sw360dp/aliases.xml b/res/drawable/ic_cross_grey_24dp.xml
similarity index 61%
copy from res/values-sw360dp/aliases.xml
copy to res/drawable/ic_cross_grey_24dp.xml
index a10585b..312c034 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/drawable/ic_cross_grey_24dp.xml
@@ -1,4 +1,3 @@
-<?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");
@@ -14,7 +13,12 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"
+ android:fillColor="#757575"/>
+</vector>
diff --git a/res/drawable/ic_fingerprint_24dp.xml b/res/drawable/ic_fingerprint_24dp.xml
new file mode 100644
index 0000000..714a05e
--- /dev/null
+++ b/res/drawable/ic_fingerprint_24dp.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:pathData="M17.81,4.47c-0.08,0 -0.16,-0.02 -0.23,-0.06C15.66,3.42 14,3 12.01,3c-1.98,0 -3.86,0.47 -5.57,1.41 -0.24,0.13 -0.54,0.04 -0.68,-0.2 -0.13,-0.24 -0.04,-0.55 0.2,-0.68C7.82,2.52 9.86,2 12.01,2c2.13,0 3.99,0.47 6.03,1.52 0.25,0.13 0.34,0.43 0.21,0.67 -0.09,0.18 -0.26,0.28 -0.44,0.28zM3.5,9.72c-0.1,0 -0.2,-0.03 -0.29,-0.09 -0.23,-0.16 -0.28,-0.47 -0.12,-0.7 0.99,-1.4 2.25,-2.5 3.75,-3.27C9.98,4.04 14,4.03 17.15,5.65c1.5,0.77 2.76,1.86 3.75,3.25 0.16,0.22 0.11,0.54 -0.12,0.7 -0.23,0.16 -0.54,0.11 -0.7,-0.12 -0.9,-1.26 -2.04,-2.25 -3.39,-2.94 -2.87,-1.47 -6.54,-1.47 -9.4,0.01 -1.36,0.7 -2.5,1.7 -3.4,2.96 -0.08,0.14 -0.23,0.21 -0.39,0.21zM9.75,21.79c-0.13,0 -0.26,-0.05 -0.35,-0.15 -0.87,-0.87 -1.34,-1.43 -2.01,-2.64 -0.69,-1.23 -1.05,-2.73 -1.05,-4.34 0,-2.97 2.54,-5.39 5.66,-5.39s5.66,2.42 5.66,5.39c0,0.28 -0.22,0.5 -0.5,0.5s-0.5,-0.22 -0.5,-0.5c0,-2.42 -2.09,-4.39 -4.66,-4.39 -2.57,0 -4.66,1.97 -4.66,4.39 0,1.44 0.32,2.77 0.93,3.85 0.64,1.15 1.08,1.64 1.85,2.42 0.19,0.2 0.19,0.51 0,0.71 -0.11,0.1 -0.24,0.15 -0.37,0.15zM16.92,19.94c-1.19,0 -2.24,-0.3 -3.1,-0.89 -1.49,-1.01 -2.38,-2.65 -2.38,-4.39 0,-0.28 0.22,-0.5 0.5,-0.5s0.5,0.22 0.5,0.5c0,1.41 0.72,2.74 1.94,3.56 0.71,0.48 1.54,0.71 2.54,0.71 0.24,0 0.64,-0.03 1.04,-0.1 0.27,-0.05 0.53,0.13 0.58,0.41 0.05,0.27 -0.13,0.53 -0.41,0.58 -0.57,0.11 -1.07,0.12 -1.21,0.12zM14.91,22c-0.04,0 -0.09,-0.01 -0.13,-0.02 -1.59,-0.44 -2.63,-1.03 -3.72,-2.1 -1.4,-1.39 -2.17,-3.24 -2.17,-5.22 0,-1.62 1.38,-2.94 3.08,-2.94 1.7,0 3.08,1.32 3.08,2.94 0,1.07 0.93,1.94 2.08,1.94s2.08,-0.87 2.08,-1.94c0,-3.77 -3.25,-6.83 -7.25,-6.83 -2.84,0 -5.44,1.58 -6.61,4.03 -0.39,0.81 -0.59,1.76 -0.59,2.8 0,0.78 0.07,2.01 0.67,3.61 0.1,0.26 -0.03,0.55 -0.29,0.64 -0.26,0.1 -0.55,-0.04 -0.64,-0.29 -0.49,-1.31 -0.73,-2.61 -0.73,-3.96 0,-1.2 0.23,-2.29 0.68,-3.24 1.33,-2.79 4.28,-4.6 7.51,-4.6 4.55,0 8.25,3.51 8.25,7.83 0,1.62 -1.38,2.94 -3.08,2.94s-3.08,-1.32 -3.08,-2.94c0,-1.07 -0.93,-1.94 -2.08,-1.94s-2.08,0.87 -2.08,1.94c0,1.71 0.66,3.31 1.87,4.51 0.95,0.94 1.86,1.46 3.27,1.85 0.27,0.07 0.42,0.35 0.35,0.61 -0.05,0.23 -0.26,0.38 -0.47,0.38z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/res/drawable/ic_fingerprint_error.xml b/res/drawable/ic_fingerprint_error.xml
index d00280d..b822d45 100644
--- a/res/drawable/ic_fingerprint_error.xml
+++ b/res/drawable/ic_fingerprint_error.xml
@@ -19,12 +19,12 @@
android:viewportWidth="32.0"
android:viewportHeight="32.0">
<path
- android:fillColor="@color/warning"
+ android:fillColor="@*android:color/system_error"
android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/>
<path
- android:fillColor="@color/warning"
+ android:fillColor="@*android:color/system_error"
android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/>
<path
- android:fillColor="@color/warning"
+ android:fillColor="@*android:color/system_error"
android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/>
</vector>
diff --git a/res/drawable/ic_fingerprint_header.xml b/res/drawable/ic_fingerprint_header.xml
new file mode 100644
index 0000000..e7ac81a
--- /dev/null
+++ b/res/drawable/ic_fingerprint_header.xml
@@ -0,0 +1,38 @@
+<!--
+ 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
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:tint="?android:attr/colorPrimary"
+ android:viewportHeight="32.0"
+ android:viewportWidth="32.0">
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M23.7,5.9c-0.1,0.0 -0.2,0.0 -0.3,-0.1C21.0,4.5 18.6,3.9 16.0,3.9c-2.5,0.0 -4.6,0.6 -6.9,1.9C8.8,6.0 8.3,5.9 8.1,5.5C7.9,5.2 8.0,4.7 8.4,4.5c2.5,-1.4 4.9,-2.1 7.7,-2.1c2.8,0.0 5.4,0.7 8.0,2.1c0.4,0.2 0.5,0.6 0.3,1.0C24.2,5.7 24.0,5.9 23.7,5.9z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M13.3,29.6c-0.2,0.0 -0.4,-0.1 -0.5,-0.2c-1.1,-1.2 -1.7,-2.0 -2.6,-3.6c-0.9,-1.7 -1.4,-3.7 -1.4,-5.9c0.0,-4.1 3.3,-7.4 7.4,-7.4c4.1,0.0 7.4,3.3 7.4,7.4c0.0,0.4 -0.3,0.7 -0.7,0.7s-0.7,-0.3 -0.7,-0.7c0.0,-3.3 -2.7,-5.9 -5.9,-5.9c-3.3,0.0 -5.9,2.7 -5.9,5.9c0.0,2.0 0.4,3.8 1.2,5.2c0.8,1.6 1.4,2.2 2.4,3.3c0.3,0.3 0.3,0.8 0.0,1.0C13.7,29.5 13.5,29.6 13.3,29.6z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M22.6,27.1c-1.6,0.0 -2.9,-0.4 -4.1,-1.2c-1.9,-1.4 -3.1,-3.6 -3.1,-6.0c0.0,-0.4 0.3,-0.7 0.7,-0.7s0.7,0.3 0.7,0.7c0.0,1.9 0.9,3.7 2.5,4.8c0.9,0.6 1.9,1.0 3.2,1.0c0.3,0.0 0.8,0.0 1.3,-0.1c0.4,-0.1 0.8,0.2 0.8,0.6c0.1,0.4 -0.2,0.8 -0.6,0.8C23.4,27.1 22.8,27.1 22.6,27.1z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M20.0,29.9c-0.1,0.0 -0.1,0.0 -0.2,0.0c-2.1,-0.6 -3.4,-1.4 -4.8,-2.9c-1.8,-1.9 -2.8,-4.4 -2.8,-7.1c0.0,-2.2 1.8,-4.1 4.1,-4.1c2.2,0.0 4.1,1.8 4.1,4.1c0.0,1.4 1.2,2.6 2.6,2.6c1.4,0.0 2.6,-1.2 2.6,-2.6c0.0,-5.1 -4.2,-9.3 -9.3,-9.3c-3.6,0.0 -6.9,2.1 -8.4,5.4C7.3,17.1 7.0,18.4 7.0,19.8c0.0,1.1 0.1,2.7 0.9,4.9c0.1,0.4 -0.1,0.8 -0.4,0.9c-0.4,0.1 -0.8,-0.1 -0.9,-0.4c-0.6,-1.8 -0.9,-3.6 -0.9,-5.4c0.0,-1.6 0.3,-3.1 0.9,-4.4c1.7,-3.8 5.6,-6.3 9.8,-6.3c5.9,0.0 10.7,4.8 10.7,10.7c0.0,2.2 -1.8,4.1 -4.1,4.1s-4.0,-1.8 -4.0,-4.1c0.0,-1.4 -1.2,-2.6 -2.6,-2.6c-1.4,0.0 -2.6,1.2 -2.6,2.6c0.0,2.3 0.9,4.5 2.4,6.1c1.2,1.3 2.4,2.0 4.2,2.5c0.4,0.1 0.6,0.5 0.5,0.9C20.6,29.7 20.3,29.9 20.0,29.9z" />
+</vector>
diff --git a/res/drawable/ic_gesture_play_button.xml b/res/drawable/ic_gesture_play_button.xml
new file mode 100644
index 0000000..e2fa6e0
--- /dev/null
+++ b/res/drawable/ic_gesture_play_button.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,
+ 16.5v-9l6,4.5 -6,4.5z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_help_24dp.xml b/res/drawable/ic_help_24dp.xml
new file mode 100644
index 0000000..d80b717
--- /dev/null
+++ b/res/drawable/ic_help_24dp.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M20,19.59V8l-6,-6H6c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2
+ 1.99,2H18c0.45,0 0.85,-0.15 1.19,-0.4l-4.43,-4.43c-0.8,0.52 -1.74,0.83 -2.76,0.83 -2.76,0
+ -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5c0,1.02 -0.31,1.96 -0.83,2.75L20,19.59zM9,13c0,1.66
+ 1.34,3 3,3s3,-1.34 3,-3 -1.34,-3 -3,-3 -3,1.34 -3,3z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_lightbulb_outline_24.xml b/res/drawable/ic_lightbulb_outline_24.xml
new file mode 100644
index 0000000..89cf8fa
--- /dev/null
+++ b/res/drawable/ic_lightbulb_outline_24.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,21c0,0.55 0.45,1 1,1h4c0.55,0 1,-0.45 1,-1v-1L9,20v1zM12,2C8.14,2
+ 5,5.14 5,9c0,2.38 1.19,4.47 3,5.74L8,17c0,0.55 0.45,1 1,1h6c0.55,0 1,-0.45
+ 1,-1v-2.26c1.81,-1.27 3,-3.36 3,-5.74 0,-3.86 -3.14,-7
+ -7,-7zM14.85,13.1l-0.85,0.6L14,16h-4v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9c0,-2.76
+ 2.24,-5 5,-5s5,2.24 5,5c0,1.63 -0.8,3.16 -2.15,4.1z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_lock.xml b/res/drawable/ic_lock.xml
new file mode 100644
index 0000000..975cbf5
--- /dev/null
+++ b/res/drawable/ic_lock.xml
@@ -0,0 +1,24 @@
+<!--
+ 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
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="?android:attr/colorPrimary"
+ android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" />
+</vector>
diff --git a/res/drawable/ic_menu_add.xml b/res/drawable/ic_menu_add.xml
index ed58072..3387f29 100644
--- a/res/drawable/ic_menu_add.xml
+++ b/res/drawable/ic_menu_add.xml
@@ -15,6 +15,13 @@
limitations under the License.
-->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_add_white"
- android:tint="?android:attr/colorAccent" />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/res/values-sw360dp/aliases.xml b/res/drawable/ic_menu_add_white.xml
similarity index 62%
copy from res/values-sw360dp/aliases.xml
copy to res/drawable/ic_menu_add_white.xml
index a10585b..9a06d5c 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/drawable/ic_menu_add_white.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
@@ -14,7 +15,12 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/res/drawable/ic_settings.xml b/res/drawable/ic_settings.xml
new file mode 100644
index 0000000..439c1a7
--- /dev/null
+++ b/res/drawable/ic_settings.xml
@@ -0,0 +1,36 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66
+ -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3
+ -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2
+ 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59
+ -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49
+ 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66
+ 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3
+ 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42
+ 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25
+ 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49
+ -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57
+ -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
+</vector>
diff --git a/res/drawable/ic_settings_gestures.xml b/res/drawable/ic_settings_gestures.xml
new file mode 100644
index 0000000..9537bed
--- /dev/null
+++ b/res/drawable/ic_settings_gestures.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,11.24L9,7.5C9,6.12 10.12,5 11.5,5S14,6.12 14,7.5v3.74c1.21,-0.81 2,-2.18 2,-3.74C16,5.01 13.99,3 11.5,3S7,5.01 7,7.5c0,1.56 0.79,2.93 2,3.74zM18.84,15.87l-4.54,-2.26c-0.17,-0.07 -0.35,-0.11 -0.54,-0.11L13,13.5v-6c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,6.67 10,7.5v10.74l-3.43,-0.72c-0.08,-0.01 -0.15,-0.03 -0.24,-0.03 -0.31,0 -0.59,0.13 -0.79,0.33l-0.79,0.8 4.94,4.94c0.27,0.27 0.65,0.44 1.06,0.44h6.79c0.75,0 1.33,-0.55 1.44,-1.28l0.75,-5.27c0.01,-0.07 0.02,-0.14 0.02,-0.2 0,-0.62 -0.38,-1.16 -0.91,-1.38z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_settings_night_display.xml b/res/drawable/ic_settings_night_display.xml
new file mode 100644
index 0000000..edd1da7
--- /dev/null
+++ b/res/drawable/ic_settings_night_display.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorAccent">
+
+ <path
+ android:fillColor="#FFF"
+ android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
+
+</vector>
diff --git a/res/drawable/ic_shortcut_battery.xml b/res/drawable/ic_shortcut_battery.xml
new file mode 100644
index 0000000..97fdd11
--- /dev/null
+++ b/res/drawable/ic_shortcut_battery.xml
@@ -0,0 +1,30 @@
+<?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
+ -->
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="80dp"
+ android:height="80dp"
+ android:viewportWidth="52.0"
+ android:viewportHeight="52.0" >
+ <path
+ android:fillColor="#FFF5F5F5"
+ android:pathData="M2,26a24,24 0 1,0 48,0a24,24 0 1,0 -48,0"/>
+ <path
+ android:fillColor="@*android:color/accent_device_default_light"
+ android:pathData="M29.67,18H28v-2h-4v2h-1.67C21.6,18,21,18.6,21,19.33v15.33C21,35.4,21.6,36,22.33,36h7.33
+ C30.4,36,31,35.4,31,34.67V19.33C31,18.6,30.4,18,29.67,18z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_shortcut_data_usage.xml b/res/drawable/ic_shortcut_data_usage.xml
new file mode 100644
index 0000000..dddd493
--- /dev/null
+++ b/res/drawable/ic_shortcut_data_usage.xml
@@ -0,0 +1,31 @@
+<?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
+ -->
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="80dp"
+ android:height="80dp"
+ android:viewportWidth="52.0"
+ android:viewportHeight="52.0" >
+ <path
+ android:fillColor="#FFF5F5F5"
+ android:pathData="M2,26a24,24 0 1,0 48,0a24,24 0 1,0 -48,0"/>
+ <path
+ android:fillColor="@*android:color/accent_device_default_light"
+ android:pathData="M27,16.05v3.03c3.39,0.49,6,3.39,6,6.92c0,0.9-0.18,1.75-0.48,2.54l2.6,1.53C35.68,28.83,36,27.45,36,26
+ C36,20.82,32.05,16.55,27,16.05z M26,33c-3.87,0-7-3.13-7-7c0-3.53,2.61-6.43,6-6.92v-3.03c-5.06,0.5-9,4.76-9,9.95
+ c0,5.52,4.47,10,9.99,10c3.31,0,6.24-1.61,8.06-4.09l-2.6-1.53C30.17,31.98,28.21,33,26,33z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_shortcut_wireless.xml b/res/drawable/ic_shortcut_wireless.xml
new file mode 100644
index 0000000..d5607e5
--- /dev/null
+++ b/res/drawable/ic_shortcut_wireless.xml
@@ -0,0 +1,29 @@
+<?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
+ -->
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="80dp"
+ android:height="80dp"
+ android:viewportWidth="52.0"
+ android:viewportHeight="52.0" >
+ <path
+ android:fillColor="#FFF5F5F5"
+ android:pathData="M2,26a24,24 0 1,0 48,0a24,24 0 1,0 -48,0"/>
+ <path
+ android:fillColor="@*android:color/accent_device_default_light"
+ android:pathData="M26.01,35.49L37.64,21c-0.45-0.34-4.93-4-11.64-4c-6.72,0-11.19,3.66-11.64,4l11.63,14.49L26,35.5L26.01,35.49z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_wifi_signal_0.xml b/res/drawable/ic_wifi_signal_0.xml
new file mode 100644
index 0000000..55faf64
--- /dev/null
+++ b/res/drawable/ic_wifi_signal_0.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="26dp"
+ android:height="24dp"
+ android:viewportWidth="26"
+ android:viewportHeight="24">
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="?attr/wifi_signal_color"
+ android:pathData="M13.0,22.0L25.6,6.5C25.1,6.1 20.3,2.1 13.0,2.1S0.9,6.1 0.4,6.5L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/selectable_card.xml b/res/drawable/selectable_card.xml
index 554b9f6..df9ddb1 100644
--- a/res/drawable/selectable_card.xml
+++ b/res/drawable/selectable_card.xml
@@ -1,21 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2015 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
- -->
+ Copyright (C) 2016 The Android Open Source Project
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight" >
+ 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.
+-->
+
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
<item android:drawable="@color/card_background"/>
-</ripple>
+</ripple>
\ No newline at end of file
diff --git a/res/values-sw360dp/aliases.xml b/res/drawable/selectable_card_grey.xml
similarity index 69%
copy from res/values-sw360dp/aliases.xml
copy to res/drawable/selectable_card_grey.xml
index a10585b..e4c73ba 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/drawable/selectable_card_grey.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
@@ -14,7 +15,8 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <item android:drawable="@color/card_background_grey"/>
+</ripple>
diff --git a/res/drawable/switchbar_background.xml b/res/drawable/switchbar_background.xml
index ac340be..a58f2e9 100644
--- a/res/drawable/switchbar_background.xml
+++ b/res/drawable/switchbar_background.xml
@@ -16,6 +16,6 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
- <item android:drawable="@color/switchbar_background_color" />
+ <item android:drawable="?android:attr/colorSecondary" />
</ripple>
diff --git a/res/layout-land/choose_lock_password.xml b/res/layout-land/choose_lock_password.xml
deleted file mode 100644
index f79de61..0000000
--- a/res/layout-land/choose_lock_password.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, 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:fillViewport="true">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center_horizontal">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
- <!-- "Enter PIN(Password) to unlock" -->
- <TextView android:id="@+id/headerText"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:layout_marginEnd="6dip"
- android:layout_marginStart="6dip"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip"
- android:gravity="start"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- />
-
- <!-- Password entry field -->
- <EditText android:id="@+id/password_entry"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dip"
- android:layout_marginBottom="5dip"
- android:layout_gravity="center"
- android:layout_weight="1"
- android:inputType="textPassword"
- android:imeOptions="actionNext|flagNoExtractUi"
- android:gravity="center"
- android:textSize="24sp"
- style="@style/TextAppearance.PasswordEntry"
- />
- </LinearLayout>
-
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
- android:layout_alignParentBottom="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#00000000"
- android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
- android:visibility="gone"
- />
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1">
- <LinearLayout
- style="@style/SecurityPreferenceButtonContainer"
- android:orientation="horizontal"
- android:layout_alignParentEnd="true"
- android:layout_alignParentBottom="true">
-
- <!-- left : cancel -->
- <Button android:id="@+id/cancel_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_cancel_label"/>
-
- <!-- right : continue -->
- <Button android:id="@+id/next_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_continue_label"/>
-
- </LinearLayout>
- </RelativeLayout>
-
- </LinearLayout>
-
-</ScrollView>
diff --git a/res/layout-land/choose_lock_pattern.xml b/res/layout-land/choose_lock_pattern.xml
index f048ba2..89e3d57 100644
--- a/res/layout-land/choose_lock_pattern.xml
+++ b/res/layout-land/choose_lock_pattern.xml
@@ -1,94 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!--
+ Copyright (C) 2015 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
+ 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
+ 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.
+ 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.
-->
-<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/topLayout"
- android:orientation="horizontal"
+<com.android.setupwizardlib.GlifLayout
+ 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="match_parent">
+ android:layout_height="match_parent"
+ android:icon="@drawable/ic_lock"
+ android:layout="@layout/suw_glif_blank_template"
+ settings:suwHeaderText="@string/lock_settings_picker_title">
- <!-- left side: instructions and messages -->
- <LinearLayout
- android:orientation="vertical"
+ <com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
+ android:id="@+id/topLayout"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- left side: instructions and messages -->
+ <LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1.0"
- >
+ android:layout_marginStart="?attr/suwMarginSides"
+ android:layout_marginBottom="@dimen/suw_content_frame_padding_bottom"
+ android:orientation="vertical">
- <!-- header message -->
- <TextView android:id="@+id/headerText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:gravity="center"
- android:textSize="18sp"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <!-- footer can show a message, or confirm / restart buttons -->
- <RelativeLayout
+ <ImageView
+ android:id="@+id/suw_layout_icon"
+ style="@style/SuwGlifIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="0dp"
+ android:src="@drawable/ic_lock" />
+
+ <TextView
+ android:id="@+id/suw_layout_title"
+ style="@style/SuwGlifHeaderTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="0dp" />
+
+ </LinearLayout>
+
+ <!-- header message -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:gravity="start|bottom"
+ android:textSize="18sp" />
+
+ <!-- footer can show a message, or confirm / restart buttons -->
+ <RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1.0">
- <!-- confirm / restart buttons -->
- <LinearLayout android:id="@+id/buttonContainer"
- style="@style/SecurityPreferenceButtonContainer"
- android:layout_centerHorizontal="true"
- android:layout_alignParentBottom="true"
- android:orientation="horizontal">
-
- <!-- left / top button: skip, or re-try -->
- <Button android:id="@+id/footerLeftButton"
- style="@style/SecurityPreferenceButton"
+ <!-- confirm / restart buttons -->
+ <LinearLayout android:id="@+id/buttonContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/lockpattern_restart_button_text"/>
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true"
+ android:orientation="horizontal">
- <!-- right / bottom button: confirm or ok -->
- <Button android:id="@+id/footerRightButton"
- style="@style/SecurityPreferenceButton"
- android:layout_width="match_parent"
+ <!-- left / top button: skip, or re-try -->
+ <Button android:id="@+id/footerLeftButton"
+ style="@style/SetupWizardButton.Negative"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lockpattern_restart_button_text" />
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <!-- right / bottom button: confirm or ok -->
+ <Button android:id="@+id/footerRightButton"
+ style="@style/SetupWizardButton.Positive"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lockpattern_confirm_button_text" />
+
+ </LinearLayout>
+
+ <!-- message above buttons -->
+ <TextView android:id="@+id/footerText"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/lockpattern_confirm_button_text"/>
+ android:layout_above="@+id/buttonContainer"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="4dip"
+ android:textSize="14sp"
+ android:visibility="gone" />
- </LinearLayout>
+ </RelativeLayout>
- <!-- message above buttons -->
- <TextView android:id="@+id/footerText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_above="@+id/buttonContainer"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="4dip"
- android:textSize="14sp"/>
+ </LinearLayout>
- </RelativeLayout>
- </LinearLayout>
+ <!-- right side: lock pattern -->
+ <FrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0">
- <View
- android:background="@*android:drawable/code_lock_left"
- android:layout_width="2dip"
- android:layout_height="match_parent" />
+ <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:background="@color/lock_pattern_background" />
- <!-- right side: lock pattern -->
- <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/lock_pattern_background" />
+ </FrameLayout>
+ </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
-</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
-
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout-land/fingerprint_enroll_enrolling.xml b/res/layout-land/fingerprint_enroll_enrolling.xml
index c72c029..ba0f803 100644
--- a/res/layout-land/fingerprint_enroll_enrolling.xml
+++ b/res/layout-land/fingerprint_enroll_enrolling.xml
@@ -15,11 +15,12 @@
~ limitations under the License
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:layout="@layout/suw_glif_blank_template"
style="?attr/fingerprint_layout_theme">
<LinearLayout
@@ -33,28 +34,62 @@
<!-- Both texts are kept as separate text views so it doesn't jump around in portrait.
See layouts/fingerprint_enroll_enrolling_base.xml. -->
- <FrameLayout
+ <LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical">
+ android:layout_height="match_parent"
+ android:layout_marginStart="?attr/suwMarginSides"
+ android:layout_marginBottom="@dimen/suw_content_frame_padding_bottom"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/suw_layout_icon"
+ style="@style/SuwGlifIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="0dp"
+ android:src="@drawable/ic_lock" />
<TextView
- style="@style/TextAppearance.FingerprintMessage"
- android:id="@+id/start_message"
+ android:id="@+id/suw_layout_title"
+ style="@style/SuwGlifHeaderTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/security_settings_fingerprint_enroll_start_message"/>
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="0dp" />
- <TextView
- style="@style/TextAppearance.FingerprintMessage"
- android:id="@+id/repeat_message"
+ <FrameLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/security_settings_fingerprint_enroll_repeat_message"
- android:visibility="invisible"/>
+ android:layout_height="wrap_content">
- </FrameLayout>
+ <TextView
+ style="@style/TextAppearance.FingerprintMessage"
+ android:id="@+id/start_message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_fingerprint_enroll_start_message"/>
+
+ <TextView
+ style="@style/TextAppearance.FingerprintMessage"
+ android:id="@+id/repeat_message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_fingerprint_enroll_repeat_message"
+ android:visibility="invisible"/>
+
+ </FrameLayout>
+
+ <Button
+ android:id="@+id/skip_button"
+ style="@style/SetupWizardButton.Negative"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/skip_label"
+ android:visibility="gone" />
+
+ </LinearLayout>
<FrameLayout
android:layout_width="0dp"
@@ -73,10 +108,11 @@
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_gravity="center_horizontal|bottom"
+ android:accessibilityLiveRegion="polite"
android:visibility="invisible"/>
</FrameLayout>
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout-land/fingerprint_enroll_find_sensor.xml b/res/layout-land/fingerprint_enroll_find_sensor.xml
index 81d1dac..0a3a33f 100644
--- a/res/layout-land/fingerprint_enroll_find_sensor.xml
+++ b/res/layout-land/fingerprint_enroll_find_sensor.xml
@@ -15,44 +15,67 @@
~ limitations under the License
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:layout="@layout/suw_glif_blank_template"
style="?attr/fingerprint_layout_theme">
<LinearLayout
- style="@style/SuwContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:clipToPadding="false"
- android:clipChildren="false"
- android:paddingBottom="0dp">
+ android:clipChildren="false">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
+ android:layout_height="match_parent"
+ android:layout_marginStart="?attr/suwMarginSides"
+ android:layout_marginBottom="@dimen/suw_content_frame_padding_bottom"
android:orientation="vertical">
- <TextView
- style="@style/TextAppearance.FingerprintMessage"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
+ android:orientation="vertical">
- <Button
- style="@style/Button.FingerprintButton"
- android:id="@+id/next_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_marginStart="-12dp"
- android:gravity="start|center_vertical"
- android:text="@string/fingerprint_enroll_button_next" />
+ <ImageView
+ android:id="@+id/suw_layout_icon"
+ style="@style/SuwGlifIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="0dp"
+ android:src="@drawable/ic_lock" />
+
+ <TextView
+ android:id="@+id/suw_layout_title"
+ style="@style/SuwGlifHeaderTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="0dp" />
+
+ <TextView
+ style="@style/TextAppearance.FingerprintMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
+
+ <Button
+ style="@style/SetupWizardButton.Positive"
+ android:id="@+id/next_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/fingerprint_enroll_button_next" />
+
+ </LinearLayout>
+
</LinearLayout>
<FrameLayout
@@ -70,4 +93,4 @@
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout-land/fingerprint_enroll_finish.xml b/res/layout-land/fingerprint_enroll_finish.xml
index e051f15..664123d 100644
--- a/res/layout-land/fingerprint_enroll_finish.xml
+++ b/res/layout-land/fingerprint_enroll_finish.xml
@@ -15,7 +15,7 @@
~ limitations under the License
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
@@ -50,29 +50,32 @@
style="@style/TextAppearance.FingerprintMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suw_description_margin_top"
+ android:layout_marginTop="@dimen/suw_description_glif_margin_top"
android:text="@string/setup_fingerprint_enroll_finish_message_secondary"
android:textColor="?android:attr/textColorSecondary"
android:visibility="gone" />
<LinearLayout
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
- android:layout_marginStart="-12dp"
android:orientation="horizontal">
<Button
- style="@style/Button.FingerprintButton"
+ style="@style/SetupWizardButton.Negative"
android:id="@+id/add_another_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
- android:gravity="start|center_vertical"
android:text="@string/fingerprint_enroll_button_add" />
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
<Button
- style="@style/Button.FingerprintButton"
+ style="@style/SetupWizardButton.Positive"
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -100,4 +103,4 @@
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout-land/setup_choose_lock_pattern.xml b/res/layout-land/setup_choose_lock_pattern.xml
deleted file mode 100644
index 6ee8e81..0000000
--- a/res/layout-land/setup_choose_lock_pattern.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-
-<com.android.setupwizardlib.SetupWizardLayout
- 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="match_parent"
- settings:suwBackgroundTile="@drawable/setup_illustration_tile"
- settings:suwHeaderText="@string/wifi_setup_wizard_title"
- settings:suwIllustrationHorizontalTile="@drawable/setup_illustration_horizontal_tile"
- settings:suwIllustrationImage="@drawable/setup_illustration_lock_screen">
-
- <com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
- android:id="@+id/topLayout"
- style="@style/SuwContentFrame"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- left side: instructions and messages -->
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1.0"
- android:orientation="vertical">
-
- <!-- header message -->
- <TextView android:id="@+id/headerText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:gravity="start|bottom"
- android:textSize="18sp" />
-
- <Button android:id="@+id/retryButton"
- style="@android:style/Widget.Material.Button.Borderless.Colored"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start"
- android:layout_marginStart="-12dp"
- android:minWidth="0dp"
- android:text="@string/lockpattern_retry_button_text" />
-
- <!-- footer can show a message, or confirm / restart buttons -->
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1.0"
- android:visibility="gone">
-
- <!-- confirm / restart buttons -->
- <LinearLayout android:id="@+id/buttonContainer"
- style="@style/SecurityPreferenceButtonContainer"
- android:layout_centerHorizontal="true"
- android:layout_alignParentBottom="true"
- android:orientation="horizontal">
-
- <!-- left / top button: skip, or re-try -->
- <Button android:id="@+id/footerLeftButton"
- style="@style/SecurityPreferenceButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/lockpattern_restart_button_text" />
-
- <!-- right / bottom button: confirm or ok -->
- <Button android:id="@+id/footerRightButton"
- style="@style/SecurityPreferenceButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/lockpattern_confirm_button_text" />
-
- </LinearLayout>
-
- <!-- message above buttons -->
- <TextView android:id="@+id/footerText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_above="@+id/buttonContainer"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="4dip"
- android:textSize="14sp"
- android:visibility="gone" />
-
- </RelativeLayout>
-
- </LinearLayout>
-
- <!-- right side: lock pattern -->
- <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/lock_pattern_background" />
-
- </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
-
-</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/layout-land/setup_fingerprint_enroll_find_sensor.xml b/res/layout-land/setup_fingerprint_enroll_find_sensor.xml
deleted file mode 100644
index 3873e00..0000000
--- a/res/layout-land/setup_fingerprint_enroll_find_sensor.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-
-<com.android.setupwizardlib.SetupWizardLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/setup_wizard_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- style="?attr/fingerprint_layout_theme">
-
- <LinearLayout
- style="@style/SuwContentFrame"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:clipToPadding="false"
- android:clipChildren="false"
- android:paddingBottom="0dp">
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:orientation="vertical">
-
- <TextView
- style="@style/TextAppearance.FingerprintMessage"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
-
- <Button
- style="@style/Button.FingerprintButton"
- android:id="@+id/next_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_marginStart="-12dp"
- android:gravity="start|center_vertical"
- android:text="@string/fingerprint_enroll_button_next" />
- </LinearLayout>
-
- <FrameLayout
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="match_parent">
-
- <include
- layout="@layout/fingerprint_enroll_find_sensor_graphic"
- android:layout_width="@dimen/fingerprint_find_sensor_graphic_size"
- android:layout_height="@dimen/fingerprint_find_sensor_graphic_size"
- android:layout_gravity="center"/>
-
- </FrameLayout>
-
- </LinearLayout>
-
-</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/layout-land/font_size_activity.xml b/res/layout-sw300dp-land/font_size_activity.xml
similarity index 100%
rename from res/layout-land/font_size_activity.xml
rename to res/layout-sw300dp-land/font_size_activity.xml
diff --git a/res/layout-land/screen_zoom_activity.xml b/res/layout-sw300dp-land/screen_zoom_activity.xml
similarity index 100%
rename from res/layout-land/screen_zoom_activity.xml
rename to res/layout-sw300dp-land/screen_zoom_activity.xml
diff --git a/res/layout-sw600dp-land/choose_lock_password.xml b/res/layout-sw600dp-land/choose_lock_password.xml
deleted file mode 100644
index 199c9ac..0000000
--- a/res/layout-sw600dp-land/choose_lock_password.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, 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="fill_parent">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="20dip"
- android:orientation="horizontal">
-
- <!-- "Enter PIN(Password) to unlock" -->
- <TextView android:id="@+id/headerText"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:layout_marginEnd="6dip"
- android:layout_marginStart="6dip"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip"
- android:gravity="start"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceLarge"
- />
-
- <!-- Password entry field -->
- <EditText android:id="@+id/password_entry"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dip"
- android:layout_marginBottom="5dip"
- android:layout_gravity="center"
- android:layout_weight="1"
- android:inputType="textPassword"
- android:imeOptions="actionNext"
- android:gravity="center"
- android:textSize="24sp"
- style="@style/TextAppearance.PasswordEntry"
- />
- </LinearLayout>
-
- <!-- confirm / restart buttons -->
- <LinearLayout
- style="@style/SecurityPreferenceButtonContainer"
- android:layout_alignParentEnd="true"
- android:layout_alignParentBottom="true"
- android:orientation="horizontal">
-
- <!-- left / top button: skip, or re-try -->
- <Button android:id="@+id/cancel_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_cancel_label"/>
-
- <!-- right / bottom button: confirm or ok -->
- <Button android:id="@+id/next_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_continue_label"/>
-
- </LinearLayout>
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
- android:layout_alignParentBottom="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#00000000"
- android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
- android:visibility="gone"
- />
-
-</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout-sw600dp-land/choose_lock_pattern.xml b/res/layout-sw600dp-land/choose_lock_pattern.xml
deleted file mode 100644
index e0d9667..0000000
--- a/res/layout-sw600dp-land/choose_lock_pattern.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/topLayout"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal">
-
- <!-- header message -->
- <ScrollView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:layout_marginTop="14dip">
-
- <TextView android:id="@+id/headerText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- </ScrollView>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="0.6"/>
-
- <!-- lock pattern widget -->
- <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
- android:layout_width="354dip"
- android:layout_height="354dip"
- android:background="@color/lock_pattern_background"
- aspect="square"/>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"/>
-
- <!-- footer message -->
- <TextView android:id="@+id/footerText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/headerText"
- android:layout_marginTop="16dip"
- android:layout_toEndOf="@id/lockPattern"
- android:layout_marginStart="100dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:visibility="gone"/>
-
- <!-- confirm / restart buttons -->
- <LinearLayout android:id="@+id/buttonContainer"
- style="@style/SecurityPreferenceButtonContainer"
- android:layout_alignParentEnd="true"
- android:layout_alignParentBottom="true"
- android:orientation="horizontal">
-
- <!-- left / top button: skip, or re-try -->
- <Button android:id="@+id/footerLeftButton"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpattern_restart_button_text"/>
-
- <!-- right / bottom button: confirm or ok -->
- <Button android:id="@+id/footerRightButton"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpattern_confirm_button_text"/>
-
- </LinearLayout>
-
-</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
-
diff --git a/res/layout-sw600dp/choose_lock_password.xml b/res/layout-sw600dp/choose_lock_password.xml
deleted file mode 100644
index ca8975e..0000000
--- a/res/layout-sw600dp/choose_lock_password.xml
+++ /dev/null
@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, 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="fill_parent"
- android:orientation="vertical"
- android:gravity="center_horizontal">
-
- <!-- header text ('Enter Pin') -->
- <TextView android:id="@+id/headerText"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:lines="2"
- android:textAppearance="?android:attr/textAppearanceLarge"/>
-
- <!-- Password entry field -->
- <EditText android:id="@+id/password_entry"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="15dip"
- android:layout_marginStart="30dip"
- android:layout_marginEnd="30dip"
- android:layout_gravity="center"
- android:inputType="textPassword"
- android:imeOptions="actionNext"
- android:gravity="center"
- android:textSize="32sp"
- style="@style/TextAppearance.PasswordEntry"
- />
-
- <!-- Spacer between password entry and keyboard -->
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1" />
-
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
- android:layout_alignParentBottom="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#00000000"
- android:layout_marginBottom="30dip"
- android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
- android:visibility="gone"
- />
-
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- />
-
- <RelativeLayout
- android:layout_height="wrap_content"
- android:layout_width="match_parent">
-
- <LinearLayout
- style="@style/SecurityPreferenceButtonContainer"
- android:layout_alignParentEnd="true"
- android:orientation="horizontal">
-
- <Button android:id="@+id/cancel_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_cancel_label"/>
-
- <Button android:id="@+id/next_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_continue_label"/>
-
- </LinearLayout>
-
- </RelativeLayout>
-
-</LinearLayout>
diff --git a/res/layout-sw600dp/choose_lock_pattern.xml b/res/layout-sw600dp/choose_lock_pattern.xml
deleted file mode 100644
index 7733184..0000000
--- a/res/layout-sw600dp/choose_lock_pattern.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/topLayout"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal">
-
- <!-- top: instructions and buttons -->
-
- <!-- header message -->
- <ScrollView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:layout_marginTop="96dip">
-
- <TextView android:id="@+id/headerText"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- </ScrollView>
-
- <!-- footer message -->
- <TextView android:id="@+id/footerText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:visibility="gone"/>
-
- <!-- bottom: lock pattern -->
- <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
- android:layout_width="354dip"
- android:layout_height="354dip"
- android:layout_marginTop="80dip"
- android:background="@color/lock_pattern_background"
- aspect="square"/>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"/>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- style="@style/SecurityPreferenceButtonContainer"
- android:layout_alignParentEnd="true"
- android:orientation="horizontal">
-
- <!-- left / top button: skip, or re-try -->
- <Button android:id="@+id/footerLeftButton"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpattern_restart_button_text"/>
-
- <!-- right / bottom button: confirm or ok -->
- <Button android:id="@+id/footerRightButton"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpattern_confirm_button_text"/>
-
- </LinearLayout>
-
- </RelativeLayout>
-
-</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
diff --git a/res/layout/accessibility_settings_for_suw.xml b/res/layout/accessibility_settings_for_suw.xml
deleted file mode 100644
index d566811..0000000
--- a/res/layout/accessibility_settings_for_suw.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?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"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <FrameLayout
- android:id="@+id/suw_main_content"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <com.android.setupwizardlib.view.NavigationBar
- android:id="@+id/suw_navigation_bar"
- style="@style/SuwNavBarTheme"
- android:layout_width="match_parent"
- android:layout_height="@dimen/suw_navbar_height"
- android:accessibilityTraversalAfter="@id/suw_main_content" />
-
-</LinearLayout>
diff --git a/res/layout/app_item.xml b/res/layout/app_item.xml
index ea0008e..15a9014 100644
--- a/res/layout/app_item.xml
+++ b/res/layout/app_item.xml
@@ -60,6 +60,14 @@
android:textColor="?android:attr/textColorSecondary"
android:duplicateParentState="true" />
+ <Switch
+ android:id="@android:id/switch_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:background="@null"
+ android:visibility="gone"/>
+
<FrameLayout
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
diff --git a/res/layout/battery_active_view.xml b/res/layout/battery_active_view.xml
index b5ada00..bdc0328 100644
--- a/res/layout/battery_active_view.xml
+++ b/res/layout/battery_active_view.xml
@@ -26,6 +26,7 @@
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary" />
diff --git a/res/layout/bluetooth_pin_entry.xml b/res/layout/bluetooth_pin_entry.xml
index aa9f187..c309a24 100644
--- a/res/layout/bluetooth_pin_entry.xml
+++ b/res/layout/bluetooth_pin_entry.xml
@@ -28,32 +28,14 @@
android:layout_width="match_parent"
android:orientation="vertical">
- <TextView
- android:id="@+id/message_caption"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/bluetooth_dialog_padding"
- android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
- android:layout_marginTop="@dimen/bluetooth_dialog_padding"
- android:gravity="center_vertical"
- android:textAppearance="@android:style/TextAppearance.Material.Caption" />
-
- <TextView
- android:id="@+id/message_subhead"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/bluetooth_dialog_padding"
- android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
- android:layout_marginBottom="@dimen/bluetooth_dialog_padding"
- android:gravity="center_vertical"
- android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
-
<EditText
android:id="@+id/text"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:layout_marginStart="@dimen/bluetooth_dialog_padding"
- android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+ android:layout_marginStart="@dimen/bluetooth_pairing_edittext_padding"
+ android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+ android:layout_marginTop="11dp"
+ android:minHeight="48dp"
android:inputType="textPassword"
android:singleLine="true" />
@@ -62,8 +44,9 @@
android:text="@string/bluetooth_pin_values_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/bluetooth_dialog_padding"
- android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+ android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+ android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+ android:layout_marginBottom="6dp"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall" />
@@ -72,30 +55,37 @@
android:text="@string/bluetooth_enable_alphanumeric_pin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/bluetooth_dialog_padding"
- android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+ android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+ android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+ android:layout_marginBottom="16dp"
android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:paddingStart="@dimen/bluetooth_checkbox_padding"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"/>
<TextView
android:id="@+id/message_below_pin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/bluetooth_dialog_padding"
- android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+ android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+ android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+ android:layout_marginBottom="12dp"
android:gravity="center_vertical"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
- android:textColor="@*android:color/secondary_text_material_light"/>
+ android:textColor="?android:attr/textColorSecondary"/>
<CheckBox
android:id="@+id/phonebook_sharing_message_entry_pin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/bluetooth_dialog_padding"
- android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+ android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+ android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+ android:layout_marginBottom="12dp"
android:gravity="center_vertical"
+ android:paddingStart="@dimen/bluetooth_checkbox_padding"
android:text="@string/bluetooth_pairing_shares_phonebook"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
diff --git a/res/layout/choose_lock_generic_fingerprint_header.xml b/res/layout/choose_lock_generic_fingerprint_header.xml
index 5ad3004..6a107bf 100644
--- a/res/layout/choose_lock_generic_fingerprint_header.xml
+++ b/res/layout/choose_lock_generic_fingerprint_header.xml
@@ -15,6 +15,7 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fingerprint_header_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
@@ -22,4 +23,4 @@
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:text="@string/lock_settings_picker_fingerprint_message"
- android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
+ style="@style/FingerprintHeaderStyle" />
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index c13d150..4b9f3e5 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -1,79 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-**
-** Copyright 2008, 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.
-*/
+ Copyright (C) 2014 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="fill_parent"
- android:orientation="vertical"
- android:gravity="center_horizontal">
-
- <!-- header text ('Enter Pin') -->
- <TextView android:id="@+id/headerText"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:lines="2"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <!-- Password entry field -->
- <EditText android:id="@+id/password_entry"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginStart="30dip"
- android:layout_marginEnd="30dip"
- android:inputType="textPassword"
- android:imeOptions="actionNext"
- android:gravity="center"
- android:textSize="24sp"
- style="@style/TextAppearance.PasswordEntry"
- />
-
- <!-- Spacer between password entry and keyboard -->
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1" />
+<com.android.setupwizardlib.GlifLayout
+ 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="match_parent"
+ android:icon="@drawable/ic_lock"
+ settings:suwHeaderText="@string/lockpassword_choose_your_password_header">
<LinearLayout
- style="@style/SecurityPreferenceButtonContainer"
- android:orientation="horizontal">
+ style="@style/SuwContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
- <!-- left : cancel -->
- <Button android:id="@+id/cancel_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_cancel_label"/>
+ <!-- header text ('Enter Pin') -->
+ <TextView
+ android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:accessibilityLiveRegion="polite"
+ android:gravity="center"
+ android:lines="2"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
- <!-- right : continue -->
- <Button android:id="@+id/next_button"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpassword_continue_label"/>
+ <!-- Password entry field -->
+ <EditText android:id="@+id/password_entry"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:inputType="textPassword"
+ android:imeOptions="actionNext|flagNoExtractUi"
+ android:textSize="24sp"
+ style="@style/TextAppearance.PasswordEntry"/>
+ <LinearLayout
+ android:id="@+id/bottom_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/password_requirements_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:gravity="end"
+ android:orientation="horizontal">
+
+ <!-- left : cancel -->
+ <Button android:id="@+id/cancel_button"
+ style="@style/SetupWizardButton.Negative"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lockpassword_cancel_label" />
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <!-- right : continue -->
+ <Button android:id="@+id/next_button"
+ style="@style/SetupWizardButton.Positive"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lockpassword_continue_label" />
+ </LinearLayout>
+ </LinearLayout>
</LinearLayout>
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
- android:layout_alignParentBottom="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#00000000"
- android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
- android:visibility="gone"
- />
-
-</LinearLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/choose_lock_pattern.xml b/res/layout/choose_lock_pattern.xml
deleted file mode 100644
index 94eecef..0000000
--- a/res/layout/choose_lock_pattern.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/topLayout"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="match_parent">
-
- <!-- takes up all space above button bar at bottom -->
- <com.android.settings.widget.MatchParentShrinkingLinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1">
-
- <TextView android:id="@+id/headerText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:minLines="2"
- android:gravity="center"
- android:textSize="18sp" />
-
- <View
- android:background="@*android:drawable/code_lock_top"
- android:layout_width="match_parent"
- android:layout_height="2dip" />
-
- <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <!-- bottom line looks bad when button bar is their too, omit in this case -->
- <!--View
- android:background="@*android:drawable/code_lock_bottom"
- android:layout_width="match_parent"
- android:layout_height="8dip" /-->
-
- <TextView android:id="@+id/footerText"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:gravity="center"
- android:textSize="14sp"/>
-
- </com.android.settings.widget.MatchParentShrinkingLinearLayout>
-
- <LinearLayout
- style="@style/SecurityPreferenceButtonContainer"
- android:orientation="horizontal">
-
- <!-- left : cancel, or re-try -->
- <Button android:id="@+id/footerLeftButton"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpattern_tutorial_cancel_label"/>
-
- <!-- right : confirm or ok -->
- <Button android:id="@+id/footerRightButton"
- style="@style/SecurityPreferenceButton"
- android:text="@string/lockpattern_tutorial_continue_label"/>
-
- </LinearLayout>
-
-</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
diff --git a/res/layout/choose_lock_pattern_common.xml b/res/layout/choose_lock_pattern_common.xml
new file mode 100644
index 0000000..6557e6a
--- /dev/null
+++ b/res/layout/choose_lock_pattern_common.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<!-- Used in phone portrait and tablet, as referenced in alias.xml. -->
+<com.android.setupwizardlib.GlifLayout
+ 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="match_parent"
+ android:icon="@drawable/ic_lock"
+ settings:suwHeaderText="@string/wifi_setup_wizard_title">
+
+ <com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
+ android:id="@+id/topLayout"
+ style="@style/SuwContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <!-- takes up all space above button bar at bottom -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:minLines="2"
+ android:gravity="center"
+ android:textSize="18sp" />
+
+ <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="4" />
+
+ <!-- Buttons are hidden during setup, and use the buttons in setup navigation bar instead -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <!-- left : cancel, or re-try -->
+ <Button android:id="@+id/footerLeftButton"
+ style="@style/SetupWizardButton.Negative"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lockpattern_tutorial_cancel_label" />
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <!-- right : confirm or ok -->
+ <Button android:id="@+id/footerRightButton"
+ style="@style/SetupWizardButton.Positive"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lockpattern_tutorial_continue_label" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <TextView android:id="@+id/footerText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:minHeight="50dip"
+ android:textSize="14sp"
+ android:visibility="gone"/>
+
+ </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
+
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/condition_card.xml b/res/layout/condition_card.xml
index 5c82c7e..7c9e46d 100644
--- a/res/layout/condition_card.xml
+++ b/res/layout/condition_card.xml
@@ -25,7 +25,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingStart="16dp"
android:background="?android:attr/colorAccent"
android:elevation="2dp"
android:clickable="true"
@@ -35,6 +34,7 @@
android:id="@+id/collapsed_group"
android:layout_width="match_parent"
android:layout_height="56dp"
+ android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:gravity="center">
@@ -42,7 +42,8 @@
android:id="@android:id/icon"
android:layout_width="24dp"
android:layout_height="wrap_content"
- android:layout_marginEnd="36dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="32dp"
android:tint="?android:attr/textColorPrimaryInverse" />
<TextView
@@ -58,10 +59,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="16dp"
- android:tint="?android:attr/textColorPrimaryInverse"
- android:clickable="true"
- android:focusable="true"
- android:background="?android:attr/selectableItemBackground" />
+ android:tint="?android:attr/textColorPrimaryInverse"/>
</LinearLayout>
@@ -69,7 +67,7 @@
android:id="@+id/detail_group"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:paddingStart="60dp"
+ android:paddingStart="72dp"
android:visibility="gone"
android:orientation="vertical">
@@ -103,18 +101,22 @@
<Button
android:id="@+id/first_action"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:paddingStart="0dp"
android:alpha=".8"
+ android:textAlignment="viewStart"
android:textColor="?android:attr/textColorPrimaryInverse"
style="?android:attr/buttonBarButtonStyle" />
<Button
android:id="@+id/second_action"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:alpha=".8"
+ android:textAlignment="viewStart"
android:textColor="?android:attr/textColorPrimaryInverse"
style="?android:attr/buttonBarButtonStyle" />
diff --git a/res/layout/dashboard.xml b/res/layout/dashboard.xml
index ebf5204..73a7255 100644
--- a/res/layout/dashboard.xml
+++ b/res/layout/dashboard.xml
@@ -19,9 +19,11 @@
android:id="@+id/dashboard_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:focusable="false"
android:paddingStart="@dimen/dashboard_padding_start"
android:paddingEnd="@dimen/dashboard_padding_end"
android:paddingTop="@dimen/dashboard_padding_top"
android:paddingBottom="@dimen/dashboard_padding_bottom"
- android:clipChildren="false"
- android:clipToPadding="false" />
+ android:scrollbars="vertical"/>
diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
index 7019a9c..2e5dd5c 100644
--- a/res/layout/dashboard_category.xml
+++ b/res/layout/dashboard_category.xml
@@ -20,9 +20,7 @@
android:layout_height="@dimen/dashboard_category_height"
android:orientation="vertical"
android:paddingBottom="8dip"
- android:background="@color/card_background"
- android:importantForAccessibility="noHideDescendants"
- android:elevation="@dimen/dashboard_category_elevation" >
+ android:background="@color/card_background">
<TextView android:id="@android:id/title"
android:layout_width="match_parent"
diff --git a/res/values-sw360dp/aliases.xml b/res/layout/dashboard_container.xml
similarity index 72%
rename from res/values-sw360dp/aliases.xml
rename to res/layout/dashboard_container.xml
index a10585b..f6b81ae 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/layout/dashboard_container.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<com.android.settings.widget.RtlCompatibleViewPager
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
diff --git a/res/layout/dashboard_container_header.xml b/res/layout/dashboard_container_header.xml
new file mode 100644
index 0000000..a9d78ed
--- /dev/null
+++ b/res/layout/dashboard_container_header.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<com.android.settings.widget.SlidingTabLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/sliding_tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/dashboard_header_margin_start"
+ android:layout_marginEnd="@dimen/dashboard_header_margin_end"
+ android:background="?android:attr/colorPrimary"/>
diff --git a/res/layout/dashboard_spacer.xml b/res/layout/dashboard_spacer.xml
index 19ef8ff..8d58c80 100644
--- a/res/layout/dashboard_spacer.xml
+++ b/res/layout/dashboard_spacer.xml
@@ -14,6 +14,8 @@
limitations under the License.
-->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="6dp" />
+<View
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="8dp"
+ android:background="@color/card_background_grey"/>
diff --git a/res/layout/dashboard_tile.xml b/res/layout/dashboard_tile.xml
index a588ed4..0e06d18 100644
--- a/res/layout/dashboard_tile.xml
+++ b/res/layout/dashboard_tile.xml
@@ -19,12 +19,11 @@
android:id="@+id/dashboard_tile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="@drawable/selectable_card"
android:gravity="center_vertical"
android:minHeight="@dimen/dashboard_tile_minimum_height"
android:clickable="true"
- android:focusable="true"
- android:background="@drawable/selectable_card"
- android:elevation="@dimen/dashboard_category_elevation" >
+ android:focusable="true">
<ImageView
android:id="@android:id/icon"
diff --git a/res/layout/device_profiles_settings.xml b/res/layout/device_profiles_settings.xml
index bd78bea..260fa05 100644
--- a/res/layout/device_profiles_settings.xml
+++ b/res/layout/device_profiles_settings.xml
@@ -14,48 +14,56 @@
limitations under the License.
-->
-<LinearLayout
+<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="25dp"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/bluetooth_preference_paired_dialog_name_label"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
- android:textColor="?android:attr/textColorSecondary"
- android:textDirection="locale"
- android:paddingTop="16dp"
- style="@style/bt_item_label" />
-
- <EditText
- android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textNoSuggestions"
- android:maxLength="@integer/bluetooth_name_length"
- android:singleLine="true"
- android:paddingBottom="@dimen/bluetooth_dialog_padding"
- android:textDirection="locale"
- style="@style/bt_item_edit_content" />
-
- <TextView
- android:id="@+id/profiles_label"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="16dp"
- android:paddingBottom="4dp"
- android:text="@string/bluetooth_device_advanced_profile_header_title"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
- android:textColor="?android:attr/textColorSecondary" />
+ android:paddingEnd="25dp">
<LinearLayout
- android:id="@+id/profiles_section"
- android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
-</LinearLayout>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/bluetooth_preference_paired_dialog_name_label"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textDirection="locale"
+ android:paddingTop="16dp"
+ style="@style/bt_item_label"/>
+
+ <EditText
+ android:id="@+id/name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="textNoSuggestions"
+ android:maxLength="@integer/bluetooth_name_length"
+ android:singleLine="true"
+ android:paddingBottom="@dimen/bluetooth_dialog_padding"
+ android:textDirection="locale"
+ style="@style/bt_item_edit_content"/>
+
+ <TextView
+ android:id="@+id/profiles_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="4dp"
+ android:text="@string/bluetooth_device_advanced_profile_header_title"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+
+ <LinearLayout
+ android:id="@+id/profiles_section"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/res/layout/dialog_edittext.xml b/res/layout/dialog_edittext.xml
index 0da47a9..c534bf1 100644
--- a/res/layout/dialog_edittext.xml
+++ b/res/layout/dialog_edittext.xml
@@ -17,15 +17,17 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingStart="8dip"
- android:paddingEnd="8dip">
-
- <EditText
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="12dp"
+ >
+
+ <EditText
android:id="@+id/edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="50"
android:singleLine="true"
/>
-
</LinearLayout>
diff --git a/res/layout/dream_info_row.xml b/res/layout/dream_info_row.xml
index 1a4dc8e..fd70ad5 100644
--- a/res/layout/dream_info_row.xml
+++ b/res/layout/dream_info_row.xml
@@ -89,6 +89,6 @@
android:padding="8dip"
android:clickable="true"
android:focusable="true"
- android:src="@drawable/ic_bt_config" />
+ android:src="@drawable/ic_settings" />
</LinearLayout>
diff --git a/res/layout/enable_accessibility_service_dialog_content.xml b/res/layout/enable_accessibility_service_dialog_content.xml
index 25c6ba2..3ca40ac 100644
--- a/res/layout/enable_accessibility_service_dialog_content.xml
+++ b/res/layout/enable_accessibility_service_dialog_content.xml
@@ -26,25 +26,30 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="16dip"
- android:paddingEnd="16dip" >
+ android:paddingEnd="16dip">
- <TextView android:id="@+id/encryption_warning"
+ <TextView
+ android:id="@+id/encryption_warning"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip"
+ android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceMedium"/>
- <TextView android:id="@+id/capabilities_header"
+ <TextView
+ android:id="@+id/capabilities_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:textAlignment="viewStart"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
- <LinearLayout android:id="@+id/capabilities"
+ <LinearLayout
+ android:id="@+id/capabilities"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:padding="10dip" />
+ android:padding="10dip"/>
</LinearLayout>
diff --git a/res/layout/encryption_interstitial_header.xml b/res/layout/encryption_interstitial_header.xml
index 8d36432..9601fa8 100644
--- a/res/layout/encryption_interstitial_header.xml
+++ b/res/layout/encryption_interstitial_header.xml
@@ -20,8 +20,9 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="56dp"
- android:paddingTop="16dp"
+ android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingBottom="16dp"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:paddingTop="@dimen/suw_description_glif_margin_top"
+ android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
+ android:textAppearance="?android:attr/textAppearanceListItem" />
diff --git a/res/layout/fallback_home_finishing_boot.xml b/res/layout/fallback_home_finishing_boot.xml
new file mode 100644
index 0000000..2714409
--- /dev/null
+++ b/res/layout/fallback_home_finishing_boot.xml
@@ -0,0 +1,49 @@
+<?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
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#80000000"
+ android:forceHasOverlappingRendering="false">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@*android:string/android_start_title"/>
+
+ <ProgressBar
+ android:theme="@style/FallbackHomeProgressBar"
+ style="@android:style/Widget.Material.ProgressBar.Horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12.75dp"
+ android:indeterminate="true"/>
+
+ </LinearLayout>
+</FrameLayout>
diff --git a/res/layout/fingerprint_enroll_enrolling_base.xml b/res/layout/fingerprint_enroll_enrolling_base.xml
index c93de4e..e9e3385 100644
--- a/res/layout/fingerprint_enroll_enrolling_base.xml
+++ b/res/layout/fingerprint_enroll_enrolling_base.xml
@@ -15,7 +15,7 @@
~ limitations under the License
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
@@ -35,7 +35,7 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suw_description_margin_top">
+ android:layout_marginTop="@dimen/suw_description_glif_margin_top">
<TextView
style="@style/TextAppearance.FingerprintMessage"
@@ -70,6 +70,14 @@
android:accessibilityLiveRegion="polite"
android:visibility="invisible"/>
+ <Button
+ android:id="@+id/skip_button"
+ style="@style/SetupWizardButton.Negative"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/skip_label"
+ android:visibility="gone" />
+
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/fingerprint_enroll_enrolling_content.xml b/res/layout/fingerprint_enroll_enrolling_content.xml
index 4b36b23..42769d1 100644
--- a/res/layout/fingerprint_enroll_enrolling_content.xml
+++ b/res/layout/fingerprint_enroll_enrolling_content.xml
@@ -37,6 +37,7 @@
android:layout_centerInParent="true"
style="?android:attr/progressBarStyleHorizontal"
android:max="10000"
+ android:mirrorForRtl="false"
android:progress="0"
android:indeterminate="false"
android:progressDrawable="@drawable/fingerprint_progress_ring"
diff --git a/res/layout/fingerprint_enroll_find_sensor_base.xml b/res/layout/fingerprint_enroll_find_sensor_base.xml
index 3f69a0a..d38818b 100644
--- a/res/layout/fingerprint_enroll_find_sensor_base.xml
+++ b/res/layout/fingerprint_enroll_find_sensor_base.xml
@@ -15,7 +15,7 @@
~ limitations under the License
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
@@ -47,7 +47,7 @@
style="@style/TextAppearance.FingerprintMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suw_description_margin_top"
+ android:layout_marginTop="@dimen/suw_description_glif_margin_top"
android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
<View
@@ -56,16 +56,14 @@
android:layout_weight="1"/>
<Button
- style="@style/Button.FingerprintButton"
+ style="@style/SetupWizardButton.Positive"
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
- android:layout_marginEnd="-12dp"
android:layout_gravity="end"
- android:gravity="end|center_vertical"
android:text="@string/fingerprint_enroll_button_next" />
</LinearLayout>
</FrameLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/fingerprint_enroll_finish_base.xml b/res/layout/fingerprint_enroll_finish_base.xml
index 15ee22a..bcbbadf 100644
--- a/res/layout/fingerprint_enroll_finish_base.xml
+++ b/res/layout/fingerprint_enroll_finish_base.xml
@@ -15,7 +15,7 @@
~ limitations under the License
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
@@ -35,7 +35,7 @@
style="@style/TextAppearance.FingerprintMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suw_description_margin_top"
+ android:layout_marginTop="@dimen/suw_description_glif_margin_top"
android:text="@string/security_settings_fingerprint_enroll_finish_message"/>
<TextView
@@ -43,7 +43,7 @@
style="@style/TextAppearance.FingerprintMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suw_description_margin_top"
+ android:layout_marginTop="@dimen/suw_description_glif_margin_top"
android:text="@string/setup_fingerprint_enroll_finish_message_secondary"
android:textColor="?android:attr/textColorSecondary"
android:visibility="gone" />
@@ -72,30 +72,32 @@
android:layout_weight="1"/>
<LinearLayout
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginEnd="-12dp"
android:layout_marginBottom="4dp"
- android:layout_gravity="end"
android:orientation="horizontal">
<Button
- style="@style/Button.FingerprintButton"
+ style="@style/SetupWizardButton.Negative"
android:id="@+id/add_another_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fingerprint_enroll_button_add" />
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
<Button
- style="@style/Button.FingerprintButton"
+ style="@style/SetupWizardButton.Positive"
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="end|center_vertical"
android:text="@string/security_settings_fingerprint_enroll_done" />
</LinearLayout>
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml
index f43bdb6..2348b6a 100644
--- a/res/layout/fingerprint_enroll_introduction.xml
+++ b/res/layout/fingerprint_enroll_introduction.xml
@@ -15,10 +15,52 @@
limitations under the License
-->
-<com.android.setupwizardlib.SetupWizardRecyclerLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ style="?attr/fingerprint_layout_theme"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:entries="@xml/fingerprint_enroll_introduction_items"
- style="?attr/fingerprint_layout_theme" />
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ style="@style/SuwContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <com.android.setupwizardlib.view.RichTextView
+ android:id="@+id/description_text"
+ style="@style/SuwDescription.Glif"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_fingerprint_enroll_introduction_message" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/fingerprint_cancel_button"
+ style="@style/SetupWizardButton.Negative"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_fingerprint_enroll_introduction_cancel" />
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <Button
+ android:id="@+id/fingerprint_next_button"
+ style="@style/SetupWizardButton.Positive"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/suw_next_button_label" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/gesture_preference.xml b/res/layout/gesture_preference.xml
new file mode 100644
index 0000000..d5685ea
--- /dev/null
+++ b/res/layout/gesture_preference.xml
@@ -0,0 +1,103 @@
+<?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"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingTop="24dp"
+ android:paddingBottom="16dp"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="@android:color/white">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:ellipsize="marquee"/>
+
+ <Switch
+ android:id="@android:id/switch_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="end|center_vertical"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/gesture_animation_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/gestures_setting_background_color"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:orientation="horizontal">
+
+ <com.android.settings.widget.AspectRatioFrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:padding="@dimen/gesture_animation_padding">
+
+ <TextureView
+ android:id="@+id/gesture_video"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"/>
+
+ <ImageView
+ android:id="@+id/gesture_image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/gestures_setting_background_color"/>
+
+ <ImageView
+ android:id="@+id/gesture_play_button"
+ android:layout_width="@dimen/gestures_play_button_size"
+ android:layout_height="@dimen/gestures_play_button_size"
+ android:src="@drawable/ic_gesture_play_button"
+ android:gravity="center"
+ android:layout_gravity="center"/>
+
+ </com.android.settings.widget.AspectRatioFrameLayout>
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:paddingTop="@dimen/gestures_settings_padding_top_bottom"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="10"
+ android:ellipsize="end"/>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/nfc_payment_option.xml b/res/layout/nfc_payment_option.xml
index 90ba279..be5fe5f 100644
--- a/res/layout/nfc_payment_option.xml
+++ b/res/layout/nfc_payment_option.xml
@@ -21,7 +21,7 @@
android:focusable="true"
android:clickable="false"
android:orientation="horizontal"
- android:paddingLeft="24dip"
+ android:paddingStart="24dip"
android:minHeight="?android:attr/listPreferredItemHeight"
android:background="?android:attr/selectableItemBackground">
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/res/values-sw360dp/aliases.xml b/res/layout/password_requirement_item.xml
similarity index 70%
copy from res/values-sw360dp/aliases.xml
copy to res/layout/password_requirement_item.xml
index a10585b..df7f45c 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/layout/password_requirement_item.xml
@@ -14,7 +14,9 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/description_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:textSize="14sp"/>
\ No newline at end of file
diff --git a/res/layout/preference_app_restrictions.xml b/res/layout/preference_app_restrictions.xml
index fe575a2..d571b5f 100644
--- a/res/layout/preference_app_restrictions.xml
+++ b/res/layout/preference_app_restrictions.xml
@@ -83,7 +83,7 @@
android:layout_height="fill_parent"
android:paddingStart="12dip"
android:paddingEnd="12dp"
- android:src="@drawable/ic_sysbar_quicksettings"
+ android:src="@drawable/ic_settings"
android:contentDescription="@string/apps_with_restrictions_settings_button"
android:layout_gravity="center"
android:clickable="true"
diff --git a/res/layout/preference_bluetooth.xml b/res/layout/preference_bluetooth.xml
index 17ee70c..c339e67 100644
--- a/res/layout/preference_bluetooth.xml
+++ b/res/layout/preference_bluetooth.xml
@@ -27,7 +27,7 @@
android:layout_gravity="center_vertical"
android:padding="8dip"
android:background="?android:attr/selectableItemBackground"
- android:src="@drawable/ic_bt_config"
+ android:src="@drawable/ic_settings"
android:contentDescription="@string/bluetooth_device_details" />
</LinearLayout>
diff --git a/res/layout/preference_importance_slider.xml b/res/layout/preference_importance_slider.xml
index ddbcd30..3861807 100644
--- a/res/layout/preference_importance_slider.xml
+++ b/res/layout/preference_importance_slider.xml
@@ -58,8 +58,8 @@
android:focusable="true"
android:background="#00ffffff"
android:progressBackgroundTint="@color/importance_secondary_slider_color"
- android:thumbTint="@color/importance_slider_color"
- android:progressTint="@color/importance_slider_color"
+ android:thumbTint="?android:attr/colorAccent"
+ android:progressTint="?android:attr/colorAccent"
style="@android:style/Widget.Material.SeekBar.Discrete"
android:tickMarkTint="@android:color/black" />
diff --git a/res/layout/preference_list_fragment.xml b/res/layout/preference_list_fragment.xml
index 9f1e076..6e540c4 100644
--- a/res/layout/preference_list_fragment.xml
+++ b/res/layout/preference_list_fragment.xml
@@ -83,6 +83,7 @@
android:visibility="gone">
<Button android:id="@+id/back_button"
+ style="?android:attr/buttonBarButtonStyle"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_margin="5dip"
@@ -97,7 +98,8 @@
android:layout_alignParentEnd="true">
<Button android:id="@+id/skip_button"
- android:layout_width="150dip"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="@*android:string/skip_button_label"
@@ -105,7 +107,8 @@
/>
<Button android:id="@+id/next_button"
- android:layout_width="150dip"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="@*android:string/next_button_label"
diff --git a/res/layout/preference_tts_engine.xml b/res/layout/preference_tts_engine.xml
index fe8e967..277fc23 100644
--- a/res/layout/preference_tts_engine.xml
+++ b/res/layout/preference_tts_engine.xml
@@ -41,7 +41,7 @@
android:layout_height="match_parent"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:src="@drawable/ic_sysbar_quicksettings"
+ android:src="@drawable/ic_settings"
android:contentDescription="@string/tts_engine_settings_button"
android:layout_centerVertical="true"
android:clickable="true"
diff --git a/res/layout/preference_wallpaper_type b/res/layout/preference_wallpaper_type.xml
similarity index 100%
rename from res/layout/preference_wallpaper_type
rename to res/layout/preference_wallpaper_type.xml
diff --git a/res/layout/preference_widget_settings.xml b/res/layout/preference_widget_settings.xml
index 6d9ac2fe..dfeca1a 100644
--- a/res/layout/preference_widget_settings.xml
+++ b/res/layout/preference_widget_settings.xml
@@ -27,7 +27,7 @@
android:layout_gravity="center_vertical"
android:padding="8dip"
android:background="?android:attr/selectableItemBackground"
- android:src="@drawable/ic_sysbar_quicksettings"
+ android:src="@drawable/ic_settings"
android:contentDescription="@string/settings_button" />
</LinearLayout>
diff --git a/res/layout/preview_seek_bar_view_pager.xml b/res/layout/preview_seek_bar_view_pager.xml
index 5524d8a..e5dfa94 100644
--- a/res/layout/preview_seek_bar_view_pager.xml
+++ b/res/layout/preview_seek_bar_view_pager.xml
@@ -25,7 +25,7 @@
<android.support.v4.view.ViewPager
android:id="@+id/preview_pager"
android:layout_width="match_parent"
- android:layout_height="0dp"
+ android:layout_height="100dp"
android:layout_weight="1"
android:background="?android:attr/colorBackgroundFloating"
android:contentDescription="@string/preview_pager_content_description" />
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index 834bba2..e11e997 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -190,6 +190,22 @@
android:layout_height="wrap_content"
android:text="@string/volte_provisioned_switch_string"/>
+ <!-- VT provisioned -->
+ <Switch android:id="@+id/vt_provisioned_switch"
+ android:textSize="14sp"
+ android:layout_marginTop="8dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/vt_provisioned_switch_string"/>
+
+ <!-- Wifi Calling provisioned -->
+ <Switch android:id="@+id/wfc_provisioned_switch"
+ android:textSize="14sp"
+ android:layout_marginTop="8dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/wfc_provisioned_switch_string"/>
+
<!-- SMSC -->
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content">
diff --git a/res/layout/redaction_interstitial.xml b/res/layout/redaction_interstitial.xml
index ec0c249..d1ce0dc 100644
--- a/res/layout/redaction_interstitial.xml
+++ b/res/layout/redaction_interstitial.xml
@@ -1,68 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
-
<!--
- ~ Copyright (C) 2014 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
- -->
+ Copyright (C) 2015 The Android Open Source Project
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
+ 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
+-->
+
+<com.android.setupwizardlib.GlifLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingStart="?attr/side_margin"
- android:paddingEnd="?attr/side_margin">
+ android:icon="@drawable/ic_lock"
+ settings:suwHeaderText="@string/lock_screen_notifications_interstitial_title">
- <TextView
- android:id="@+id/message"
+ <LinearLayout
+ style="@style/SuwContentFrame"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/redaction_vertical_margins"
- android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
- android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:text="@string/lock_screen_notifications_interstitial_message"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <RadioGroup
- android:id="@+id/radio_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/redaction_vertical_margins"
- android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
- android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:checkedButton="@+id/redact_sensitive">
-
- <com.android.settings.RestrictedRadioButton
- android:id="@+id/show_all"
+ <TextView
+ android:id="@+id/message"
+ style="@style/SuwDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/RedactionItemAndLabel"
- android:text="@string/lock_screen_notifications_summary_show" />
+ android:text="@string/lock_screen_notifications_interstitial_message" />
- <com.android.settings.RestrictedRadioButton
- android:id="@+id/redact_sensitive"
+ <RadioGroup
+ android:id="@+id/radio_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/RedactionItemAndLabel"
- android:text="@string/lock_screen_notifications_summary_hide" />
+ android:layout_marginTop="@dimen/redaction_vertical_margins"
+ android:checkedButton="@+id/redact_sensitive">
- <RadioButton
- android:id="@+id/hide_all"
- android:layout_width="match_parent"
+ <com.android.settings.RestrictedRadioButton
+ android:id="@+id/show_all"
+ style="@style/SuwRadioButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lock_screen_notifications_summary_show" />
+
+ <com.android.settings.RestrictedRadioButton
+ android:id="@+id/redact_sensitive"
+ style="@style/SuwRadioButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lock_screen_notifications_summary_hide" />
+
+ <RadioButton
+ android:id="@+id/hide_all"
+ style="@style/SuwRadioButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/lock_screen_notifications_summary_disable" />
+
+ </RadioGroup>
+
+ <Button
+ android:id="@+id/redaction_done_button"
+ style="@style/SetupWizardButton.Positive"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="@style/RedactionItemAndLabel"
- android:text="@string/lock_screen_notifications_summary_disable" />
+ android:layout_gravity="end"
+ android:text="@string/app_notifications_dialog_done" />
- </RadioGroup>
+ </LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/restricted_preference_user_delete_widget.xml b/res/layout/restricted_preference_user_delete_widget.xml
index 7ffb0e4..7fd5d88 100644
--- a/res/layout/restricted_preference_user_delete_widget.xml
+++ b/res/layout/restricted_preference_user_delete_widget.xml
@@ -35,7 +35,7 @@
android:layout_height="fill_parent"
android:paddingStart="16dip"
android:paddingEnd="16dip"
- android:src="@drawable/ic_sysbar_quicksettings"
+ android:src="@drawable/ic_settings"
android:contentDescription="@string/settings_label"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground" />
diff --git a/res/layout/running_processes_header.xml b/res/layout/running_processes_header.xml
index 38ff614..615d30e 100644
--- a/res/layout/running_processes_header.xml
+++ b/res/layout/running_processes_header.xml
@@ -97,7 +97,7 @@
android:layout_height="16sp"
android:layout_gravity="center"
android:scaleType="centerInside"
- android:src="@color/running_processes_apps_ram"
+ android:src="?android:attr/colorAccent"
android:contentDescription="@null" />
<LinearLayout
android:layout_width="match_parent"
diff --git a/res/layout/see_all.xml b/res/layout/see_all.xml
index 56405bb..44b263c 100644
--- a/res/layout/see_all.xml
+++ b/res/layout/see_all.xml
@@ -18,11 +18,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="@dimen/dashboard_tile_minimum_height"
android:clickable="true"
- android:focusable="true"
- android:background="@drawable/selectable_card">
+ android:focusable="true">
<View
android:layout_width="@dimen/dashboard_tile_image_size"
diff --git a/res/layout/settings_main_dashboard.xml b/res/layout/settings_main_dashboard.xml
index c10193c..1b7506e 100644
--- a/res/layout/settings_main_dashboard.xml
+++ b/res/layout/settings_main_dashboard.xml
@@ -21,4 +21,5 @@
android:id="@+id/main_content"
android:layout_height="match_parent"
android:layout_width="match_parent"
+ android:background="@color/material_grey_300"
/>
diff --git a/res/layout/setup_choose_lock_generic_fingerprint_header.xml b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
index d16aec4..b19bec1 100644
--- a/res/layout/setup_choose_lock_generic_fingerprint_header.xml
+++ b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
@@ -20,10 +20,10 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="56dp"
- android:paddingBottom="@dimen/suw_description_margin_bottom_lists"
+ android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingTop="@dimen/suw_description_margin_top"
+ android:paddingTop="@dimen/suw_description_glif_margin_top"
android:text="@string/setup_lock_settings_picker_fingerprint_message"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="?android:attr/textAppearanceListItem" />
diff --git a/res/layout/setup_choose_lock_generic_header.xml b/res/layout/setup_choose_lock_generic_header.xml
index 78cd618..9a3547d 100644
--- a/res/layout/setup_choose_lock_generic_header.xml
+++ b/res/layout/setup_choose_lock_generic_header.xml
@@ -20,10 +20,10 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="56dp"
- android:paddingBottom="@dimen/suw_description_margin_bottom_lists"
+ android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingTop="@dimen/suw_description_margin_top"
+ android:paddingTop="@dimen/suw_description_glif_margin_top"
android:text="@string/setup_lock_settings_picker_message"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="?android:attr/textAppearanceListItem" />
diff --git a/res/layout/setup_choose_lock_password.xml b/res/layout/setup_choose_lock_password.xml
deleted file mode 100644
index 164233c..0000000
--- a/res/layout/setup_choose_lock_password.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 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.
--->
-
-<com.android.setupwizardlib.SetupWizardLayout
- 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="match_parent"
- settings:suwBackgroundTile="@drawable/setup_illustration_tile"
- settings:suwHeaderText="@string/wifi_setup_wizard_title"
- settings:suwIllustrationHorizontalTile="@drawable/setup_illustration_horizontal_tile"
- settings:suwIllustrationImage="@drawable/setup_illustration_lock_screen">
-
- <LinearLayout
- style="@style/SuwContentFrame"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal"
- android:orientation="vertical">
-
- <!-- header text ('Enter Pin') -->
- <TextView android:id="@+id/headerText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:lines="2"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <!-- Password entry field -->
- <EditText android:id="@+id/password_entry"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginStart="30dip"
- android:layout_marginEnd="30dip"
- android:gravity="center"
- android:inputType="textPassword"
- android:imeOptions="actionNext|flagNoExtractUi"
- android:textSize="24sp"
- style="@style/TextAppearance.PasswordEntry"/>
-
- <!-- Spacer between password entry and keyboard -->
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:visibility="gone"
- style="@style/SecurityPreferenceButtonContainer">
-
- <!-- left : cancel -->
- <Button android:id="@+id/cancel_button"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/lockpassword_cancel_label"
- style="@style/SecurityPreferenceButton"/>
-
- <!-- right : continue -->
- <Button android:id="@+id/next_button"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/lockpassword_continue_label"
- style="@style/SecurityPreferenceButton"/>
-
- </LinearLayout>
-
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#00000000"
- android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
- android:visibility="gone"/>
-
- </LinearLayout>
-
-</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/layout/setup_choose_lock_pattern_common.xml b/res/layout/setup_choose_lock_pattern_common.xml
deleted file mode 100644
index 0a38637..0000000
--- a/res/layout/setup_choose_lock_pattern_common.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 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.
--->
-
-<!-- Used in phone portrait and tablet, as referenced in alias.xml. -->
-<com.android.setupwizardlib.SetupWizardLayout
- 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="match_parent"
- android:layout="@layout/setup_choose_lock_pattern_template"
- settings:suwBackgroundTile="@drawable/setup_illustration_tile"
- settings:suwHeaderText="@string/wifi_setup_wizard_title"
- settings:suwIllustrationHorizontalTile="@drawable/setup_illustration_horizontal_tile"
- settings:suwIllustrationImage="@drawable/setup_illustration_lock_screen">
-
- <com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
- android:id="@+id/topLayout"
- style="@style/SuwContentFrame"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <!-- takes up all space above button bar at bottom -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:gravity="center"
- android:orientation="vertical">
-
- <TextView android:id="@+id/headerText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:minLines="2"
- android:gravity="center"
- android:textSize="18sp" />
-
- <Button android:id="@+id/retryButton"
- style="@android:style/Widget.Material.Button.Borderless.Colored"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:text="@string/lockpattern_retry_button_text"/>
-
- <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="4" />
-
- </LinearLayout>
-
- <TextView android:id="@+id/footerText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:minHeight="50dip"
- android:textSize="14sp"
- android:visibility="gone"/>
-
- <!-- Buttons are hidden during setup, and use the buttons in setup navigation bar instead -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:visibility="gone"
- style="@style/SecurityPreferenceButtonContainer">
-
- <!-- left : cancel, or re-try -->
- <Button android:id="@+id/footerLeftButton"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/lockpattern_tutorial_cancel_label"
- style="@style/SecurityPreferenceButton"/>
-
- <!-- right : confirm or ok -->
- <Button android:id="@+id/footerRightButton"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/lockpattern_tutorial_continue_label"
- style="@style/SecurityPreferenceButton"/>
-
- </LinearLayout>
-
- </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
-
-</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/layout/setup_encryption_interstitial_header.xml b/res/layout/setup_encryption_interstitial_header.xml
index a6e7c30..9601fa8 100644
--- a/res/layout/setup_encryption_interstitial_header.xml
+++ b/res/layout/setup_encryption_interstitial_header.xml
@@ -20,9 +20,9 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="56dp"
- android:paddingBottom="@dimen/suw_description_margin_bottom_lists"
+ android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingTop="@dimen/suw_description_margin_top"
+ android:paddingTop="@dimen/suw_description_glif_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="?android:attr/textAppearanceListItem" />
diff --git a/res/layout/setup_fingerprint_enroll_find_sensor_base.xml b/res/layout/setup_fingerprint_enroll_find_sensor_base.xml
deleted file mode 100644
index 184d6b9..0000000
--- a/res/layout/setup_fingerprint_enroll_find_sensor_base.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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
- -->
-
-<com.android.setupwizardlib.SetupWizardLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/setup_wizard_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- style="?attr/fingerprint_layout_theme">
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:clipToPadding="false"
- android:clipChildren="false">
-
- <include
- layout="@layout/fingerprint_enroll_find_sensor_graphic"
- android:layout_width="@dimen/fingerprint_find_sensor_graphic_size"
- android:layout_height="@dimen/fingerprint_find_sensor_graphic_size"
- android:layout_gravity="center_horizontal|bottom"/>
-
- <LinearLayout
- style="@style/SuwContentFrame"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:clipToPadding="false"
- android:clipChildren="false">
-
- <TextView
- style="@style/TextAppearance.FingerprintMessage"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suw_description_margin_top"
- android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
-
- <View
- android:layout_height="0dp"
- android:layout_width="match_parent"
- android:layout_weight="1"/>
-
- <Button
- style="@style/Button.FingerprintButton"
- android:id="@+id/next_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="4dp"
- android:layout_marginEnd="-12dp"
- android:layout_gravity="end"
- android:gravity="end|center_vertical"
- android:text="@string/fingerprint_enroll_button_next" />
-
- </LinearLayout>
- </FrameLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/layout/setup_preference.xml b/res/layout/setup_preference.xml
index f5496f4..298bc9a 100644
--- a/res/layout/setup_preference.xml
+++ b/res/layout/setup_preference.xml
@@ -15,11 +15,8 @@
limitations under the License.
-->
-<com.android.setupwizardlib.SetupWizardPreferenceLayout
+<com.android.setupwizardlib.GlifPreferenceLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
android:id="@android:id/list_container"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- settings:suwBackgroundTile="@drawable/setup_illustration_tile"
- settings:suwIllustrationHorizontalTile="@drawable/setup_illustration_horizontal_tile" />
+ android:layout_height="match_parent" />
diff --git a/res/layout/setup_redaction_interstitial.xml b/res/layout/setup_redaction_interstitial.xml
deleted file mode 100644
index e99756a..0000000
--- a/res/layout/setup_redaction_interstitial.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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
--->
-
-<com.android.setupwizardlib.SetupWizardLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:id="@+id/setup_wizard_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- settings:suwBackgroundTile="@drawable/setup_illustration_tile"
- settings:suwHeaderText="@string/lock_screen_notifications_interstitial_title"
- settings:suwIllustrationHorizontalTile="@drawable/setup_illustration_horizontal_tile"
- settings:suwIllustrationImage="@drawable/setup_illustration_lock_screen">
-
- <LinearLayout
- style="@style/SuwContentFrame"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingStart="?attr/side_margin"
- android:paddingEnd="?attr/side_margin">
-
- <TextView
- style="@style/SuwDescription"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
- android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:text="@string/lock_screen_notifications_interstitial_message" />
-
- <RadioGroup
- android:id="@+id/radio_group"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/redaction_vertical_margins"
- android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
- android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:checkedButton="@+id/redact_sensitive">
-
- <com.android.settings.RestrictedRadioButton
- android:id="@+id/show_all"
- style="@style/SuwRadioButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/lock_screen_notifications_summary_show" />
-
- <com.android.settings.RestrictedRadioButton
- android:id="@+id/redact_sensitive"
- style="@style/SuwRadioButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/lock_screen_notifications_summary_hide" />
-
- <RadioButton
- android:id="@+id/hide_all"
- style="@style/SuwRadioButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/lock_screen_notifications_summary_disable" />
- </RadioGroup>
-
- </LinearLayout>
-
-</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/values-sw360dp/aliases.xml b/res/layout/sliding_tab_indicator_view.xml
similarity index 64%
copy from res/values-sw360dp/aliases.xml
copy to res/layout/sliding_tab_indicator_view.xml
index a10585b..b594c8b 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/layout/sliding_tab_indicator_view.xml
@@ -14,7 +14,10 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<View
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/sliding_tab_selected_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/pager_tabs_selected_indicator_height"
+ android:background="?android:attr/colorAccent"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent" />
diff --git a/res/layout/sliding_tab_title_view.xml b/res/layout/sliding_tab_title_view.xml
new file mode 100644
index 0000000..5df8378
--- /dev/null
+++ b/res/layout/sliding_tab_title_view.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 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.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:ellipsize="end"
+ android:fontFamily="sans-serif-medium"
+ android:gravity="center"
+ android:maxLines="1"
+ android:padding="@dimen/pager_tabs_title_padding"
+ android:textColor="@color/sliding_tab_title_text_color"
+ android:textAllCaps="true"/>
diff --git a/res/layout/storage_summary.xml b/res/layout/storage_summary.xml
index 35201e1..7bc51df 100644
--- a/res/layout/storage_summary.xml
+++ b/res/layout/storage_summary.xml
@@ -33,7 +33,7 @@
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
- android:textColor="#ff607d8b"
+ android:textColor="?android:attr/colorAccent"
android:textSize="36sp"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
diff --git a/res/layout/suggestion_header.xml b/res/layout/suggestion_header.xml
index c48553e..f3f39ff 100644
--- a/res/layout/suggestion_header.xml
+++ b/res/layout/suggestion_header.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
@@ -20,27 +21,32 @@
android:layout_height="@dimen/dashboard_category_height"
android:clickable="true"
android:focusable="true"
- android:background="@drawable/selectable_card"
- android:elevation="@dimen/dashboard_category_elevation"
- android:gravity="center_vertical" >
-
- <TextView android:id="@android:id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingStart="16dp"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.TileTitle"
- android:textColor="?android:attr/colorAccent"
- android:alpha=".87"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
-
- <ImageView android:id="@android:id/icon"
+ android:background="@drawable/selectable_card_grey"
+ android:gravity="center_vertical"
+ android:paddingTop="4dp">
+ <ImageView
+ android:id="@android:id/icon"
android:layout_width="@dimen/dashboard_tile_image_size"
android:layout_height="@dimen/dashboard_tile_image_size"
- android:layout_marginStart="@dimen/suggestion_arrow_margin"
- android:layout_marginEnd="@dimen/suggestion_arrow_margin"
- android:src="@drawable/ic_expand_more" />
-
+ android:layout_marginStart="@dimen/dashboard_tile_image_margin_start"
+ android:layout_marginEnd="@dimen/dashboard_tile_image_margin_end"
+ android:src="@drawable/ic_expand_more"/>
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.SuggestionTitle"
+ android:textColor="?android:attr/colorAccent"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"/>
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="end"
+ android:paddingEnd="18dp"
+ android:textAppearance="@style/TextAppearance.SuggestionTitle"
+ android:textColor="?android:attr/colorAccent"/>
</LinearLayout>
diff --git a/res/layout/suggestion_tile.xml b/res/layout/suggestion_tile.xml
index 10c9558..80de8ff 100644
--- a/res/layout/suggestion_tile.xml
+++ b/res/layout/suggestion_tile.xml
@@ -18,70 +18,48 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="@drawable/selectable_card_grey"
android:clickable="true"
android:focusable="true"
- android:background="@drawable/selectable_card"
- android:elevation="@dimen/dashboard_category_elevation"
- android:orientation="vertical" >
+ android:gravity="center_vertical"
+ android:minHeight="@dimen/dashboard_tile_minimum_height">
- <View
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="?android:attr/listDivider" />
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/dashboard_tile_image_size"
+ android:layout_height="@dimen/dashboard_tile_image_size"
+ android:layout_marginStart="@dimen/dashboard_tile_image_margin_start"
+ android:layout_marginEnd="@dimen/dashboard_tile_image_margin_end"
+ android:scaleType="centerInside"/>
- <LinearLayout
- android:layout_width="match_parent"
+ <RelativeLayout
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:minHeight="@dimen/dashboard_tile_minimum_height">
+ android:layout_weight="1">
- <ImageView
- android:id="@android:id/icon"
- android:layout_width="@dimen/dashboard_tile_image_size"
- android:layout_height="@dimen/dashboard_tile_image_size"
- android:scaleType="centerInside"
- android:layout_marginStart="@dimen/dashboard_tile_image_margin_start"
- android:layout_marginEnd="@dimen/dashboard_tile_image_margin_end" />
+ <TextView android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.TileTitle"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"/>
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1">
+ <TextView android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_alignStart="@android:id/title"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:textColor="?android:attr/textColorSecondary"/>
- <TextView android:id="@android:id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.TileTitle"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
+ </RelativeLayout>
- <TextView android:id="@android:id/summary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@android:id/title"
- android:layout_alignStart="@android:id/title"
- android:textAppearance="@style/TextAppearance.Small"
- android:textColor="?android:attr/textColorSecondary" />
+ <ImageView
+ android:id="@+id/overflow"
+ style="?android:attr/actionOverflowButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="16dp"/>
- </RelativeLayout>
-
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent">
-
- <ImageView android:id="@+id/overflow"
- android:layout_width="44dp"
- android:layout_height="44dp"
- android:paddingStart="16dp"
- android:paddingBottom="16dp"
- android:paddingTop="12dp"
- android:paddingEnd="12dp"
- android:gravity="top"
- style="?android:attr/actionOverflowButtonStyle" />
-
- </FrameLayout>
-
- </LinearLayout>
-
-</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/support_disclaimer_content.xml b/res/layout/support_disclaimer_content.xml
new file mode 100644
index 0000000..d6697c3
--- /dev/null
+++ b/res/layout/support_disclaimer_content.xml
@@ -0,0 +1,36 @@
+<?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"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="24dp">
+
+ <com.android.settings.widget.LinkTextView
+ android:id="@+id/support_disclaimer_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="24dp"/>
+
+ <CheckBox
+ android:id="@+id/support_disclaimer_do_not_show_again"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/support_disclaimer_do_not_show"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+</LinearLayout>
diff --git a/res/layout/support_escalation_options.xml b/res/layout/support_escalation_options.xml
new file mode 100644
index 0000000..b214561
--- /dev/null
+++ b/res/layout/support_escalation_options.xml
@@ -0,0 +1,87 @@
+<?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"
+ style="@style/SupportEscalationCard"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/tile_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textAppearance="@style/TextAppearance.SupportTitle"/>
+ <TextView
+ android:id="@+id/tile_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:paddingTop="8dp"
+ android:paddingBottom="30dp"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:textColor="?android:attr/textColorSecondary"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:orientation="horizontal">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <Button
+ android:id="@android:id/text1"
+ style="@style/SupportPrimaryButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"/>
+ <TextView
+ android:id="@+id/summary1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="14dp"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:textColor="?android:attr/textColorSecondary"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <Button
+ android:id="@android:id/text2"
+ style="@style/SupportPrimaryButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"/>
+ <TextView
+ android:id="@+id/summary2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="14dp"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:textColor="?android:attr/textColorSecondary"/>
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/support_fragment.xml b/res/layout/support_fragment.xml
new file mode 100644
index 0000000..7c79a63
--- /dev/null
+++ b/res/layout/support_fragment.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:focusable="false"
+ android:paddingStart="@dimen/dashboard_padding_start"
+ android:paddingEnd="@dimen/dashboard_padding_end">
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/support_items"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="@color/card_background"/>
+</FrameLayout>
diff --git a/res/layout/support_offline_escalation_options.xml b/res/layout/support_offline_escalation_options.xml
new file mode 100644
index 0000000..18d8f98
--- /dev/null
+++ b/res/layout/support_offline_escalation_options.xml
@@ -0,0 +1,71 @@
+<?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"
+ style="@style/SupportEscalationCard"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/tile_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textAppearance="@style/TextAppearance.SupportTitle"/>
+ <TextView
+ android:id="@+id/tile_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:paddingTop="8dp"
+ android:paddingBottom="10dp"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:textColor="?android:attr/textColorSecondary"/>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:id="@+id/support_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingEnd="8dp"
+ android:text="@string/support_country_list_title"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:textColor="?android:attr/textColorSecondary"/>
+ <Spinner
+ android:id="@+id/spinner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:dropDownWidth="196dp"/>
+ </LinearLayout>
+ <Button
+ android:id="@android:id/text1"
+ style="@style/SupportPrimaryButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"
+ android:layoutDirection="ltr"/>
+ <Button
+ android:id="@android:id/text2"
+ style="@style/SupportSecondaryButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="48dp"
+ android:visibility="gone"/>
+</LinearLayout>
diff --git a/res/layout/support_phone_dialog_content.xml b/res/layout/support_phone_dialog_content.xml
new file mode 100644
index 0000000..ce6d2bb
--- /dev/null
+++ b/res/layout/support_phone_dialog_content.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"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="16dp"
+ android:text="@string/support_international_phone_summary"/>
+ <LinearLayout
+ android:id="@+id/phone_number_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:gravity="center_vertical"
+ android:minHeight="48dp"
+ android:orientation="horizontal">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingEnd="32dp"
+ android:src="@drawable/ic_call_24dp"/>
+ <TextView
+ android:id="@+id/phone_number"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:textAppearance="@style/TextAppearance.TileTitle"/>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/support_sign_in_button.xml b/res/layout/support_sign_in_button.xml
new file mode 100644
index 0000000..45de571
--- /dev/null
+++ b/res/layout/support_sign_in_button.xml
@@ -0,0 +1,52 @@
+<?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"
+ style="@style/SupportEscalationCard"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/tile_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textAppearance="@style/TextAppearance.SupportTitle"/>
+ <TextView
+ android:id="@+id/tile_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:paddingTop="8dp"
+ android:paddingBottom="30dp"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:textColor="?android:attr/textColorSecondary"/>
+ <Button
+ android:id="@android:id/text1"
+ style="@style/SupportPrimaryButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"/>
+ <Button
+ android:id="@android:id/text2"
+ style="@style/SupportSecondaryButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:minHeight="48dp"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/support_tile.xml b/res/layout/support_tile.xml
new file mode 100644
index 0000000..e5e49f4
--- /dev/null
+++ b/res/layout/support_tile.xml
@@ -0,0 +1,41 @@
+<?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"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/selectable_card"
+ android:gravity="center_vertical"
+ android:minHeight="@dimen/support_tile_min_height"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/dashboard_tile_image_size"
+ android:layout_height="@dimen/dashboard_tile_image_size"
+ android:scaleType="centerInside"
+ android:layout_marginStart="@dimen/dashboard_tile_image_margin_start"
+ android:layout_marginEnd="@dimen/dashboard_tile_image_margin_end"/>
+ <TextView
+ android:id="@+id/tile_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.TileTitle"
+ android:ellipsize="end"
+ android:fadingEdge="horizontal"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values-sw360dp/aliases.xml b/res/layout/support_tile_spacer.xml
similarity index 68%
copy from res/values-sw360dp/aliases.xml
copy to res/layout/support_tile_spacer.xml
index a10585b..41cc221 100644
--- a/res/values-sw360dp/aliases.xml
+++ b/res/layout/support_tile_spacer.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
@@ -14,7 +15,8 @@
limitations under the License.
-->
-<resources>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template</item>
-</resources>
-
+<View
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/support_spacer_height"
+ android:background="@color/card_background"/>
diff --git a/res/layout/suw_item_link_description.xml b/res/layout/suw_item_link_description.xml
deleted file mode 100644
index 5396de1e..0000000
--- a/res/layout/suw_item_link_description.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?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:tools="http://schemas.android.com/tools"
- style="@style/SuwItemContainer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="@dimen/suw_description_margin_top"
- android:paddingBottom="@dimen/suw_description_margin_bottom_lists">
-
- <FrameLayout
- android:id="@+id/suw_items_icon_container"
- android:layout_width="@dimen/suw_items_icon_container_width"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:gravity="start">
-
- <ImageView
- android:id="@+id/suw_items_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- tools:ignore="ContentDescription" />
-
- </FrameLayout>
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical">
-
- <com.android.settings.widget.LinkTextView
- android:id="@+id/suw_items_title"
- style="@style/SuwItemTitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="start"
- android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
- android:textAlignment="viewStart"
- android:textAppearance="@style/TextAppearance.SuwDescription"
- tools:ignore="UnusedAttribute" />
-
- <com.android.settings.widget.LinkTextView
- android:id="@+id/suw_items_summary"
- style="@style/SuwItemSummary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="start"
- android:textAlignment="viewStart"
- android:visibility="gone"
- tools:ignore="UnusedAttribute" />
-
- </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/switch_bar.xml b/res/layout/switch_bar.xml
index a31bd3e..8b69a1d 100644
--- a/res/layout/switch_bar.xml
+++ b/res/layout/switch_bar.xml
@@ -44,7 +44,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@null"
- android:theme="@style/ThemeOverlay.SwitchBar" />
+ android:theme="@style/ThemeOverlay.SwitchBar.Settings" />
</merge>
diff --git a/res/layout/user_dictionary_add_word.xml b/res/layout/user_dictionary_add_word.xml
index 3624dad..2b8c19a 100644
--- a/res/layout/user_dictionary_add_word.xml
+++ b/res/layout/user_dictionary_add_word.xml
@@ -14,72 +14,73 @@
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/user_dict_settings_add_dialog_top"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:id="@+id/user_dict_settings_add_dialog_top"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
<LinearLayout android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
<com.android.internal.widget.DialogTitle
- style="?android:attr/windowTitleStyle"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_width="match_parent"
- android:layout_height="64dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:gravity="center_vertical|start"
- android:text="@string/user_dict_settings_add_dialog_title" />
- <View android:layout_width="match_parent"
- android:layout_height="2dip"
- android:background="@android:color/holo_blue_light" />
+ style="?android:attr/windowTitleStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip"
+ android:layout_marginTop="24dip"
+ android:layout_marginBottom="0dip"
+ android:ellipsize="end"
+ android:gravity="center_vertical|start"
+ android:singleLine="true"
+ android:text="@string/user_dict_settings_add_dialog_title" />
</LinearLayout>
<EditText android:id="@+id/user_dictionary_add_word_text"
- android:maxLength="@integer/maximum_user_dictionary_word_length"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:layout_gravity="fill_horizontal|center_vertical"
- android:layout_marginStart="8dip"
- android:layout_marginBottom="8dip"
- android:layout_marginTop="8dip"
- android:hint="@string/user_dict_settings_add_word_hint"
- android:inputType="textNoSuggestions"
- android:imeOptions="flagNoFullscreen">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="fill_horizontal|center_vertical"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip"
+ android:layout_marginTop="20dip"
+ android:layout_marginBottom="24dip"
+ android:hint="@string/user_dict_settings_add_word_hint"
+ android:imeOptions="flagNoFullscreen"
+ android:inputType="textNoSuggestions"
+ android:maxLength="@integer/maximum_user_dictionary_word_length">
<requestFocus />
</EditText>
<LinearLayout android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:divider="?android:attr/dividerHorizontal"
- android:showDividers="beginning"
- android:dividerPadding="0dip">
+ android:layout_height="wrap_content"
+ android:divider="?android:attr/dividerHorizontal"
+ android:dividerPadding="0dip"
+ android:orientation="vertical"
+ android:showDividers="beginning">
<LinearLayout style="?android:attr/buttonBarStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:measureWithLargestChild="true">
- <Button android:layout_width="0dip"
- android:layout_gravity="start"
- android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="end"
+ android:orientation="horizontal">
+ <Button style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="36dip"
+ android:layout_marginTop="8dip"
+ android:layout_marginBottom="8dip"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="0dip"
android:maxLines="2"
- style="?android:attr/buttonBarButtonStyle"
+ android:onClick="onClickCancel"
android:textSize="14sp"
- android:text="@string/cancel"
- android:layout_height="wrap_content"
- android:onClick="onClickCancel" />
- <Button android:layout_width="0dip"
- android:layout_gravity="end"
- android:layout_weight="1"
+ android:text="@string/cancel" />
+ <Button style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="36dip"
+ android:layout_margin="8dip"
android:maxLines="2"
- style="?android:attr/buttonBarButtonStyle"
+ android:onClick="onClickConfirm"
android:textSize="14sp"
- android:text="@string/user_dict_settings_add_dialog_confirm"
- android:layout_height="wrap_content"
- android:onClick="onClickConfirm" />
+ android:text="@string/user_dict_settings_add_dialog_confirm" />
</LinearLayout>
</LinearLayout>
-</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/video_preference.xml b/res/layout/video_preference.xml
index 5f7116d..fe7f26f 100644
--- a/res/layout/video_preference.xml
+++ b/res/layout/video_preference.xml
@@ -24,13 +24,15 @@
android:layout_height="wrap_content"
android:src="@drawable/accessibility_screen_magnification_background"
android:scaleType="fitXY"
- android:adjustViewBounds="true" />
+ android:adjustViewBounds="true"
+ android:importantForAccessibility="noHideDescendants" />
<VideoView
android:id="@+id/video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/video_background"
- android:layout_centerHorizontal="true" />
+ android:layout_centerHorizontal="true"
+ android:importantForAccessibility="noHideDescendants" />
</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index ceb7201..ba1f6fc 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -287,11 +287,14 @@
android:layout_height="wrap_content"
style="@style/wifi_item"
android:paddingBottom="4dp"
+ android:importantForAccessibility="yes"
+ android:contentDescription="@string/wifi_advanced_toggle_description_collapsed"
android:visibility="gone">
<CheckBox android:id="@+id/wifi_advanced_togglebox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/wifi_advanced_toggle"
+ android:importantForAccessibility="noHideDescendants"
android:text="@string/wifi_show_advanced" />
</LinearLayout>
diff --git a/res/layout/wifi_display_preference.xml b/res/layout/wifi_display_preference.xml
index d8c4729..99cb89c 100644
--- a/res/layout/wifi_display_preference.xml
+++ b/res/layout/wifi_display_preference.xml
@@ -37,7 +37,7 @@
android:layout_gravity="center_vertical"
android:padding="8dip"
android:background="?android:attr/selectableItemBackground"
- android:src="@drawable/ic_bt_config"
+ android:src="@drawable/ic_settings"
android:contentDescription="@string/wifi_display_details" />
</LinearLayout>
diff --git a/res/menu/storage_volume.xml b/res/menu/storage_volume.xml
index efa468c..bf9f985 100644
--- a/res/menu/storage_volume.xml
+++ b/res/menu/storage_volume.xml
@@ -30,4 +30,7 @@
<item
android:id="@+id/storage_migrate"
android:title="@string/storage_menu_migrate" />
+ <item
+ android:id="@+id/storage_free"
+ android:title="@string/storage_menu_free" />
</menu>
diff --git a/res/raw/gesture_ambient_lift.mp4 b/res/raw/gesture_ambient_lift.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/gesture_ambient_lift.mp4
diff --git a/res/raw/gesture_ambient_tap.mp4 b/res/raw/gesture_ambient_tap.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/gesture_ambient_tap.mp4
diff --git a/res/raw/gesture_double_tap.mp4 b/res/raw/gesture_double_tap.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/gesture_double_tap.mp4
diff --git a/res/raw/gesture_fingerprint_swipe.mp4 b/res/raw/gesture_fingerprint_swipe.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/gesture_fingerprint_swipe.mp4
diff --git a/res/raw/gesture_twist.mp4 b/res/raw/gesture_twist.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/gesture_twist.mp4
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index f18b34b..749a4e9 100755
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -34,4 +34,8 @@
<!-- Display, Screen zoom -->
<dimen name="screen_zoom_preview_height">160dp</dimen>
+
+ <!-- Gestures -->
+ <dimen name="gesture_animation_padding">35dp</dimen>
+
</resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index eb37d0f..eeb677a 100755
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -27,4 +27,6 @@
<!-- CryptKeeper top margin for pattern screen -->
<dimen name="crypt_keeper_pattern_top_margin">128dip</dimen>
+ <dimen name="captioning_preview_height">150dp</dimen>
+
</resources>
diff --git a/res/values-sw600dp/aliases.xml b/res/values-sw600dp/aliases.xml
index 51ee5bc..163e97a 100644
--- a/res/values-sw600dp/aliases.xml
+++ b/res/values-sw600dp/aliases.xml
@@ -19,7 +19,6 @@
<item name="fingerprint_enroll_find_sensor" type="layout">@layout/fingerprint_enroll_find_sensor_base</item>
<item name="fingerprint_enroll_enrolling" type="layout">@layout/fingerprint_enroll_enrolling_base</item>
<item name="fingerprint_enroll_finish" type="layout">@layout/fingerprint_enroll_finish_base</item>
- <item name="setup_choose_lock_pattern" type="layout">@layout/setup_choose_lock_pattern_common</item>
- <item name="setup_fingerprint_enroll_find_sensor" type="layout">@layout/setup_fingerprint_enroll_find_sensor_base</item>
+ <item name="choose_lock_pattern" type="layout">@layout/choose_lock_pattern_common</item>
</resources>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index 56d8318..70faa0f 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -18,8 +18,12 @@
<dimen name="settings_side_margin">112dp</dimen>
<!-- Dashboard padding in its container -->
- <dimen name="dashboard_padding_start">128dp</dimen>
- <dimen name="dashboard_padding_end">128dp</dimen>
+ <dimen name="dashboard_padding_start">160dp</dimen>
+ <dimen name="dashboard_padding_end">160dp</dimen>
+
+ <!-- Dashboard Header margin in its container -->
+ <dimen name="dashboard_header_margin_start">304dp</dimen>
+ <dimen name="dashboard_header_margin_end">304dp</dimen>
<!-- ActionBar contentInsetStart -->
<dimen name="actionbar_contentInsetStart">128dp</dimen>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 981c936..a0be467 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -42,6 +42,10 @@
<dimen name="dashboard_padding_start">80dp</dimen>
<dimen name="dashboard_padding_end">80dp</dimen>
+ <!-- Dashboard Header margin in its container -->
+ <dimen name="dashboard_header_margin_start">176dp</dimen>
+ <dimen name="dashboard_header_margin_end">176dp</dimen>
+
<!-- Dashboard category padding start / end -->
<dimen name="dashboard_category_padding_start">24dp</dimen>
<dimen name="dashboard_category_padding_end">24dp</dimen>
diff --git a/res/values/aliases.xml b/res/values/aliases.xml
index a783c79..951b1bb 100644
--- a/res/values/aliases.xml
+++ b/res/values/aliases.xml
@@ -21,8 +21,6 @@
<item name="fingerprint_enroll_find_sensor" type="layout">@layout/fingerprint_enroll_find_sensor_base</item>
<item name="fingerprint_enroll_enrolling" type="layout">@layout/fingerprint_enroll_enrolling_base</item>
<item name="fingerprint_enroll_finish" type="layout">@layout/fingerprint_enroll_finish_base</item>
- <item name="setup_choose_lock_pattern" type="layout">@layout/setup_choose_lock_pattern_common</item>
- <item name="setup_fingerprint_enroll_find_sensor" type="layout">@layout/setup_fingerprint_enroll_find_sensor_base</item>
- <item name="setup_choose_lock_pattern_template" type="layout">@layout/suw_template_short</item>
+ <item name="choose_lock_pattern" type="layout">@layout/choose_lock_pattern_common</item>
</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 8adf331..6827e5b 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1031,4 +1031,18 @@
<item>Red</item>
</string-array>
+ <!-- Automatic storage management settings. The amount of days for the automatic storage manager
+ to retain. These are shown in a list dialog. [CHAR LIMIT=70] -->
+ <string-array name="automatic_storage_management_days">
+ <item>Over 30 days old</item>
+ <item>Over 60 days old</item>
+ <item>Over 90 days old</item>
+ </string-array>
+
+ <string-array name="automatic_storage_management_days_values" translatable="false">
+ <item>30</item>
+ <item>60</item>
+ <item>90</item>
+ </string-array>
+
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 0a072ae..218d7f2 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -135,4 +135,15 @@
<attr name="allowDividerAbove" format="boolean" />
<attr name="allowDividerBelow" format="boolean" />
</declare-styleable>
+
+ <!-- For GesturePreference -->
+ <declare-styleable name="GesturePreference">
+ <attr name="animation" format="reference" />
+ </declare-styleable>
+
+ <!-- For AspectRatioFrameLayout -->
+ <declare-styleable name="AspectRatioFrameLayout">
+ <attr name="aspectRatio" format="float" />
+ </declare-styleable>
+
</resources>
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 5ee0f7c..13609dc 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -4,9 +4,9 @@
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.
@@ -17,6 +17,8 @@
<resources>
<!-- Whether or not the dock settings are to be displayed for this device when docked -->
<bool name="has_dock_settings">false</bool>
+ <!-- Whether there is a boot sounds checkbox -->
+ <bool name="has_boot_sounds">false</bool>
<!-- Whether there is a silent mode checkbox -->
<bool name="has_silent_mode">true</bool>
<!-- Whether the DEPRECATED power control widget is enabled for this
@@ -40,4 +42,7 @@
<!-- Whether none security option is hide or not (country specific). -->
<bool name="config_hide_none_security_option">false</bool>
+
+ <!--Whether help links are defined. -->
+ <bool name="config_has_help">false</bool>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a9756ad..2155245 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -50,16 +50,14 @@
<color name="setup_wizard_wifi_color_dark">#89ffffff</color>
<color name="setup_wizard_wifi_color_light">#89000000</color>
- <color name="system_warning_color">#fff4511e</color><!-- deep orange 600 -->
-
<color name="lock_pattern_background">#00000000</color>
<color name="lock_pattern_view_regular_color">#ff37474f</color>
- <color name="lock_pattern_view_error_color">@color/warning</color>
+ <color name="lock_pattern_view_error_color">@*android:color/system_error</color>
<color name="lock_pattern_view_regular_color_dark">#ffffff</color>
<color name="unlock_pattern_view_regular_color">@android:color/white</color>
- <color name="unlock_pattern_view_error_color">@color/system_warning_color</color>
+ <color name="unlock_pattern_view_error_color">@*android:color/system_error</color>
<color name="fingerprint_title_area_bg">?android:attr/colorAccent</color>
<color name="fingerprint_title_color">#ffffffff</color>
@@ -69,19 +67,13 @@
<color name="fingerprint_indicator_background_resting">#12000000</color>
<color name="running_processes_system_ram">#ff384248</color>
- <color name="running_processes_apps_ram">#ff009587</color>
<color name="running_processes_free_ram">#ffced7db</color>
- <color name="card_background">#ffffffff</color>
-
- <color name="switchbar_background_color">#ff37474f</color>
- <color name="switch_accent_color">#ff7fcac3</color>
+ <color name="card_background">#fffafafa</color>
<color name="wifi_divider">#ffe0e0e0</color>
<color name="sim_noitification">@*android:color/material_deep_teal_500</color>
- <color name="warning">#ff5621</color>
- <color name="confirm_device_credential_dark_background">#263238</color>
<color name="confirm_device_credential_transparent_black">#60000000</color>
<color name="fab_ripple">#1fffffff</color><!-- 12% white -->
<color name="fab_shape">?android:attr/colorAccent</color>
@@ -96,14 +88,11 @@
<color name="memory_avg_use">#ff384248</color>
- <color name="zen_rule_name_warning">@color/system_warning_color</color>
+ <color name="zen_rule_name_warning">@*android:color/system_error</color>
<!-- Accent color that matches the settings launcher icon -->
<color name="icon_accent">#ffabffec</color>
- <color name="summary_default_start">#ff009587</color>
- <color name="summary_default_end">#ffced7db</color>
-
<color name="importance_icon_tint">#8a000000</color>
<color name="importance_disabled_tint">#4d000000</color>
@@ -125,10 +114,14 @@
<color name="seek_bar_preference_preview_text">#fff</color>
- <color name="importance_slider_color">@*android:color/material_deep_teal_500</color>
<color name="importance_disabled_slider_color">@*android:color/material_grey_300</color>
<color name="importance_secondary_slider_color">#858383</color>
<color name="usage_graph_dots">#B0BEC5</color>
+ <color name="card_background_grey">#eeeeee</color>
+
+ <!-- Gestures settings -->
+ <color name="gestures_setting_background_color">#f5f5f5</color>
+
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 3f25fc6..6d56e18 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -38,4 +38,31 @@
<!-- When true enable color temperature setting. -->
<bool name="config_enableColorTemperature">false</bool>
+ <!-- Fully-qualified class name for the implementation of the FeatureFactory to be instantiated. -->
+ <string name="config_featureFactory" translatable="false">com.android.settings.overlay.FeatureFactoryImpl</string>
+
+ <!-- Package name and fully-qualified class name for the wallpaper picker activity. -->
+ <string name="config_wallpaper_picker_package" translatable="false">com.android.settings</string>
+ <string name="config_wallpaper_picker_class" translatable="false">com.android.settings.Settings$WallpaperSettingsActivity</string>
+
+ <!-- Backup settings to launch -->
+ <string name="config_backup_settings_intent" translatable="false"></string>
+
+ <!-- Double twist sensor name and vendor used by gesture setting -->
+ <string name="gesture_double_twist_sensor_name" translatable="false"></string>
+ <string name="gesture_double_twist_sensor_vendor" translatable="false"></string>
+
+ <!-- Pickup sensor name and vendor used by gesture setting -->
+ <string name="gesture_pickup_sensor_name" translatable="false"></string>
+ <string name="gesture_pickup_sensor_vendor" translatable="false"></string>
+
+ <!-- When true enable gesture setting. -->
+ <bool name="config_gesture_settings_enabled">false</bool>
+
+ <!-- If the Storage Manager settings are enabled. -->
+ <bool name="config_storage_manager_settings_enabled">false</bool>
+
+ <!-- When true show double-tap gesture setting. -->
+ <bool name="config_gesture_double_tap_settings_enabled">false</bool>
+
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index ef7efa2..28bed77 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -59,6 +59,8 @@
<dimen name="appwidget_min_height">40dip</dimen>
<dimen name="pager_tabs_padding">0dp</dimen>
+ <dimen name="pager_tabs_title_padding">16dp</dimen>
+ <dimen name="pager_tabs_selected_indicator_height">3dp</dimen>
<!-- Minimum width for the popup for updating a user's photo. -->
<dimen name="update_user_photo_popup_min_width">300dip</dimen>
@@ -94,6 +96,10 @@
<dimen name="dashboard_padding_top">0dp</dimen>
<dimen name="dashboard_padding_bottom">0dp</dimen>
+ <!-- Dashboard Header margin in its container -->
+ <dimen name="dashboard_header_margin_start">0dp</dimen>
+ <dimen name="dashboard_header_margin_end">0dp</dimen>
+
<!-- Dashboard category padding start / end -->
<dimen name="dashboard_category_padding_start">0dp</dimen>
<dimen name="dashboard_category_padding_end">0dp</dimen>
@@ -117,8 +123,6 @@
<dimen name="dashboard_tile_image_margin_start">16dp</dimen>
<dimen name="dashboard_tile_image_margin_end">32dp</dimen>
- <dimen name="suggestion_arrow_margin">16dp</dimen>
-
<!-- SwitchBar margin start / end -->
<dimen name="switchbar_margin_start">16dp</dimen>
<dimen name="switchbar_margin_end">16dp</dimen>
@@ -201,7 +205,9 @@
<!-- Bluetooth Preferences -->
<dimen name="bluetooth_dialog_padding">8dip</dimen>
<integer name="bluetooth_name_length">32</integer>
- <dimen name="bluetooth_pairing_padding">20dp</dimen>
+ <dimen name="bluetooth_pairing_padding">24dp</dimen>
+ <dimen name="bluetooth_pairing_edittext_padding">21dp</dimen>
+ <dimen name="bluetooth_checkbox_padding">16dp</dimen>
<!-- WiFi Preferences -->
<dimen name="wifi_divider_height">1px</dimen>
@@ -296,4 +302,18 @@
<!-- Padding between the radio buttons/checkbox and text on the redaction interstitial -->
<dimen name="redaction_padding_start">16dp</dimen>
+ <!-- Padding for Gestures settings screen -->
+ <dimen name="gestures_settings_padding_top_bottom">20dp</dimen>
+ <dimen name="gestures_play_button_size">36dp</dimen>
+ <dimen name="gesture_animation_padding">0dp</dimen>
+
+ <!-- Support tile minimum height -->
+ <dimen name="support_tile_min_height">48dp</dimen>
+ <!-- support spacer layout height -->
+ <dimen name="support_spacer_height">8dp</dimen>
+
+ <dimen name="password_requirement_textsize">14sp</dimen>
+ <!-- Visible vertical space we want to show below password edittext field when ime is shown.
+ The unit is sp as it is related to the text size of password requirement item. -->
+ <dimen name="visible_vertical_space_below_password">20sp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3a37705..a8bd8e7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -65,6 +65,12 @@
<!-- VoLTE provisioning flag on. Only shown in diagnostic screen, so precise translation is not needed. -->
<string name="volte_provisioned_switch_string">VoLTE Provisioned</string>
+ <!-- Video calling provisioning flag on. Only shown in diagnostic screen, so precise translation is not needed. -->
+ <string name="vt_provisioned_switch_string">Video Calling Provisioned</string>
+
+ <!-- Wifi Calling provisioning flag on. Only shown in diagnostic screen, so precise translation is not needed. -->
+ <string name="wfc_provisioned_switch_string">Wifi Calling Provisioned</string>
+
<!-- Cell Radio Power. Only shown in diagnostic screen, so precise translation is not needed. -->
<string name="radio_info_radio_power">Cellular Radio Power</string>
@@ -740,8 +746,14 @@
<string name="security_settings_fingerprint_preference_summary_none"></string>
<!-- Introduction title shown in fingerprint enrollment to introduce the fingerprint feature[CHAR LIMIT=29] -->
<string name="security_settings_fingerprint_enroll_introduction_title">Unlock with fingerprint</string>
+ <!-- Introduction title shown in fingerprint enrollment to introduce the fingerprint feature, when fingerprint unlock is disabed by device admin [CHAR LIMIT=29] -->
+ <string name="security_settings_fingerprint_enroll_introduction_title_unlock_disabled">Use your fingerprint</string>
<!-- Introduction detail message shown in fingerprint enrollment dialog [CHAR LIMIT=NONE]-->
- <string name="security_settings_fingerprint_enroll_introduction_message">Just touch the fingerprint sensor to unlock your phone, authorize purchases, or sign in to apps. Be careful whose fingerprints you add. Even one added print can do any of these things.\n\nNote: Your fingerprint may be less secure than a strong pattern or PIN. <annotation id="url">Learn more</annotation></string>
+ <string name="security_settings_fingerprint_enroll_introduction_message">Just touch the fingerprint sensor to unlock your phone, authorize purchases, or sign in to apps. Be careful whose fingerprints you add. Even one added print can do any of these things.\n\nNote: Your fingerprint may be less secure than a strong pattern or PIN.</string>
+ <!-- Introduction detail message shown in fingerprint enrollment dialog, when fingerprint unlock is disabled by device admin [CHAR LIMIT=NONE]-->
+ <string name="security_settings_fingerprint_enroll_introduction_message_unlock_disabled">Just touch the fingerprint sensor to authorize purchases, or sign in to apps. Be careful whose fingerprints you add. Even one added print can do any of these things.\n\nNote: You can\u2019t use your fingerprint to unlock this device. For more information, contact your organization\u2019s admin.</string>
+ <!-- Introduction detail message shown in fingerprint enrollment screen in setup wizard. [CHAR LIMIT=NONE]-->
+ <string name="security_settings_fingerprint_enroll_introduction_message_setup">Just touch the fingerprint sensor to unlock your phone, authorize purchases, or sign in to apps. Be careful whose fingerprints you add. Even one added print can do any of these things.\n\nNote: Your fingerprint may be less secure than a strong pattern or PIN.</string>
<!-- Button text to cancel enrollment from the introduction [CHAR LIMIT=22] -->
<string name="security_settings_fingerprint_enroll_introduction_cancel">Cancel</string>
<!-- Button text to continue to the next screen from the introduction [CHAR LIMIT=22] -->
@@ -780,11 +792,11 @@
<!-- Button text shown in fingerprint dialog that allows the user to delete the fingerprint template [CHAR LIMIT=22] -->
<string name="security_settings_fingerprint_enroll_dialog_delete">Delete</string>
<!-- Title shown in fingerprint enrollment dialog to begin enrollment [CHAR LIMIT=29]-->
- <string name="security_settings_fingerprint_enroll_start_title">Let\u2019s start!</string>
+ <string name="security_settings_fingerprint_enroll_start_title">Let\u2019s start</string>
<!-- Message shown in fingerprint enrollment dialog to begin enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_start_message">Put your finger on the sensor and lift after you feel a vibration</string>
<!-- Title shown in fingerprint enrollment dialog to repeat touching the fingerprint sensor [CHAR LIMIT=29] -->
- <string name="security_settings_fingerprint_enroll_repeat_title">Great! Now repeat</string>
+ <string name="security_settings_fingerprint_enroll_repeat_title">Keep going</string>
<!-- Message shown in fingerprint enrollment dialog to repeat touching the fingerprint sensor [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_repeat_message">Move your finger slightly to add all the different parts of your fingerprint</string>
<!-- Title shown in fingerprint enrollment dialog once enrollment is completed [CHAR LIMIT=29] -->
@@ -794,7 +806,7 @@
<!-- Message shown when fingerprint enrollment is completed during setup wizard [CHAR LIMIT=NONE] -->
<string name="setup_fingerprint_enroll_finish_message">Just touch the fingerprint sensor to wake and unlock your device.</string>
<!-- Message shown when fingerprint enrollment is completed, telling user about the fingerprint icon that will be shown whenever they can use their fingerprint [CHAR LIMIT=NONE] -->
- <string name="setup_fingerprint_enroll_finish_message_secondary">When you see this icon, you can use your fingerprint.</string>
+ <string name="setup_fingerprint_enroll_finish_message_secondary">When you see this icon, you can also authorize purchases or sign in to apps.</string>
<!-- Title of the dialog shown when the user tries to skip fingerprint setup, asking them to confirm the action [CHAR LIMIT=40] -->
<string name="setup_fingerprint_enroll_enrolling_skip_title">Skip fingerprint setup?</string>
<!-- Content of the dialog shown when the user tries to skip fingerprint setup, asking them to confirm the action [CHAR LIMIT=NONE] -->
@@ -825,11 +837,6 @@
<!-- Text shown in fingerprint enroll when we didn't observe progress for a few seconds. [CHAR LIMIT=100] -->
<string name="security_settings_fingerprint_enroll_lift_touch_again">Lift finger, then touch sensor again</string>
- <!-- Message shown in fingerprint enrollment during setup wizard once enrollment is complete. [CHAR LIMIT=NONE] -->
- <string name="setup_fingerprint_enroll_finish_message">Whenever you see this icon, you can use your fingerprint.</string>
- <!-- Secondary message shown in fingerprint enrollment during setup wizard once enrollment is complete, telling the user how to change the settings after they are done with setup. [CHAR LIMIT=NONE] -->
- <string name="setup_fingerprint_enroll_finish_secondary_message">To change your settings, go to Settings > Security > Fingerprint.</string>
-
<!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
@@ -982,11 +989,14 @@
<!-- Security Picker --><skip />
<!-- Title for suggested actions for screen lock -->
- <string name="suggested_lock_settings_title">Screen lock</string>
+ <string name="suggested_lock_settings_title">Set screen lock</string>
<!-- Summary for suggested actions for screen lock -->
<string name="suggested_lock_settings_summary">Protect your device</string>
+ <!-- Title for suggested actions for settings up a fingerprint lock -->
+ <string name="suggested_fingerprint_lock_settings_title">Use fingerprint</string>
+
<!-- Summary for suggested actions for settings up a fingerprint lock -->
<string name="suggested_fingerprint_lock_settings_summary">Unlock with your fingerprint</string>
@@ -1004,7 +1014,7 @@
<string name="setup_lock_settings_picker_title" product="default">Protect your phone</string>
<!-- Title for screen in setup wizard, prompting user to choose the their backup screen lock method [CHAR LIMIT=NONE] -->
- <string name="setup_lock_settings_picker_fingerprint_message">Your fingerprint may be less secure than a strong pattern, PIN, or password. For added security, set up a backup screen lock.</string>
+ <string name="setup_lock_settings_picker_fingerprint_message">For added security, set up a backup screen lock.</string>
<!-- Description text for screen in setup wizard asking user to set up screen lock, explaining to the user how setting up a screen lock protect them from losing data. (tablet) [CHAR LIMIT=NONE] -->
<string name="setup_lock_settings_picker_message" product="tablet">Prevent others from using this tablet without your permission by activating device protection features. Choose the screen lock you want to use.</string>
@@ -1073,6 +1083,12 @@
<!-- Title for preference that guides the user through creating a backup unlock password for fingerprint [CHAR LIMIT=45]-->
<string name="fingerprint_unlock_set_unlock_password">Fingerprint + Password</string>
+ <!-- Title for preference that guides the user to skip fingerprint setup [CHAR LIMIT=60]-->
+ <string name="fingerprint_unlock_skip_fingerprint">Continue without fingerprint</string>
+
+ <!-- Message shown in screen lock picker while setting up the new screen lock with fingerprint option. [CHAR LIMIT=NONE]-->
+ <string name="fingerprint_unlock_title">You can unlock your phone using your fingerprint. For security, this option requires a backup screen lock.</string>
+
<!-- Summary for preference that has been disabled by because of the DevicePolicyAdmin, or because device encryption is enabled, or because there are credentials in the credential storage [CHAR LIMIT=50] -->
<string name="unlock_set_unlock_disabled_summary">Disabled by administrator, encryption policy, or credential storage</string>
@@ -1160,7 +1176,7 @@
<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>
+ <string name="lockpassword_password_too_short">Must be at least %d characters</string>
<!-- Hint shown in dialog screen when PIN is too short -->
<string name="lockpassword_pin_too_short">PIN must be at least %d digits</string>
@@ -1168,62 +1184,62 @@
<string name="lockpassword_continue_label">Continue</string>
<!-- Error shown in popup when password is too long -->
- <string name="lockpassword_password_too_long">Password must be fewer than <xliff:g id="number" example="17">%d</xliff:g> characters.</string>
+ <string name="lockpassword_password_too_long">Must be fewer than <xliff:g id="number" example="17">%d</xliff:g> characters.</string>
<!-- Error shown in popup when PIN is too long -->
- <string name="lockpassword_pin_too_long">PIN must be fewer than <xliff:g id="number" example="17">%d</xliff:g> digits.</string>
+ <string name="lockpassword_pin_too_long">Must be fewer than <xliff:g id="number" example="17">%d</xliff:g> digits.</string>
<!-- Error shown when in PIN mode and user enters a non-digit -->
- <string name="lockpassword_pin_contains_non_digits">PIN must contain only digits 0-9.</string>
+ <string name="lockpassword_pin_contains_non_digits">Must contain only digits 0-9.</string>
<!-- Error shown when in PIN mode and PIN has been used recently. Please keep this string short! -->
<string name="lockpassword_pin_recently_used">Device administrator doesn\u2019t allow using a recent PIN.</string>
<!-- Error shown when in PASSWORD mode and user enters an invalid character -->
- <string name="lockpassword_illegal_character">Password contains an illegal character.</string>
+ <string name="lockpassword_illegal_character">This can\'t include an invalid character</string>
<!-- Error shown when in PASSWORD mode and password is all digits -->
- <string name="lockpassword_password_requires_alpha">Password must contain at least one letter.</string>
+ <string name="lockpassword_password_requires_alpha">Must contain at least one letter</string>
<!-- Error shown when in PASSWORD mode and password doesn't contain any digits -->
- <string name="lockpassword_password_requires_digit">Password must contain at least one digit.</string>
+ <string name="lockpassword_password_requires_digit">Must contain at least one digit</string>
<!-- Error shown when in PASSWORD mode and password doesn't contain any symbols -->
- <string name="lockpassword_password_requires_symbol">Password must contain at least one symbol.</string>
+ <string name="lockpassword_password_requires_symbol">Must contain at least one symbol</string>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of letters -->
<plurals name="lockpassword_password_requires_letters">
- <item quantity="one">Password must contain at least 1 letter.</item>
- <item quantity="other">Password must contain at least %d letters.</item>
+ <item quantity="one">Must contain at least 1 letter</item>
+ <item quantity="other">Must contain at least %d letters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of lowercase letters -->
<plurals name="lockpassword_password_requires_lowercase">
- <item quantity="one">Password must contain at least 1 lowercase letter.</item>
- <item quantity="other">Password must contain at least %d lowercase letters.</item>
+ <item quantity="one">Must contain at least 1 lowercase letter</item>
+ <item quantity="other">Must contain at least %d lowercase letters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of uppercase letters -->
<plurals name="lockpassword_password_requires_uppercase">
- <item quantity="one">Password must contain at least 1 uppercase letter.</item>
- <item quantity="other">Password must contain at least %d uppercase letters.</item>
+ <item quantity="one">Must contain at least 1 uppercase letter</item>
+ <item quantity="other">Must contain at least %d uppercase letters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of numerical digits -->
<plurals name="lockpassword_password_requires_numeric">
- <item quantity="one">Password must contain at least 1 numerical digit.</item>
- <item quantity="other">Password must contain at least %d numerical digits.</item>
+ <item quantity="one">Must contain at least 1 numerical digit</item>
+ <item quantity="other">Must contain at least %d numerical digits</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of special symbols -->
<plurals name="lockpassword_password_requires_symbols">
- <item quantity="one">Password must contain at least 1 special symbol.</item>
- <item quantity="other">Password must contain at least %d special symbols.</item>
+ <item quantity="one">Must contain at least 1 special symbol</item>
+ <item quantity="other">Must contain at least %d special symbols</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of non-letter characters -->
<plurals name="lockpassword_password_requires_nonletter">
- <item quantity="one">Password must contain at least 1 non-letter character.</item>
- <item quantity="other">Password must contain at least %d non-letter characters.</item>
+ <item quantity="one">Must contain at least 1 non-letter character</item>
+ <item quantity="other">Must contain at least %d non-letter characters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password has been used recently. Please keep this string short! -->
@@ -1489,6 +1505,10 @@
<string name="nfc_quick_toggle_summary" product="tablet">Allow data exchange when the tablet touches another device</string>
<!-- Description of NFC in the 1st level settings screen, for a phone. [CHAR LIMIT=NONE] -->
<string name="nfc_quick_toggle_summary" product="default">Allow data exchange when the phone touches another device</string>
+ <!-- Dialog title for NFC disclaimr [CHAR_LIMIT=40]-->
+ <string name="nfc_disclaimer_title">Turn on NFC</string>
+ <!-- Dialog title for NFC disclaimr [CHAR_LIMIT=NONE]-->
+ <string name="nfc_disclaimer_content">NFC exchanges data between this device and other nearby devices or targets, such as payment terminals, access readers, and interactive ads or tags.</string>
<!-- Used to enter the Android Beam sharing preferences screen. This phrase is a trademark. [CHAR LIMIT=32] -->
<string name="android_beam_settings_title">Android Beam</string>
@@ -1573,7 +1593,10 @@
<string name="wifi_limit_optimizations_summary">Limit battery used by Wi\u2011Fi</string>
<!-- Checkbox title. Should we switch to using cellular data if Wi-Fi is still connected but the Wi-Fi network we're connected to no longer has Internet access (e.g., due to an outage)? -->
<string name="wifi_switch_away_when_unvalidated">Switch to cellular data if Wi\u2011Fi loses Internet access.</string>
-
+ <!-- Preference title for option to automatically switch away from bad wifi networks [CHAR LIMIT=60]-->
+ <string name="wifi_cellular_data_fallback_title">Switch to cellular data automatically</string>
+ <!-- Preference summary for option to automatically switch away from bad wifi networks [CHAR LIMIT=None]-->
+ <string name="wifi_cellular_data_fallback_summary">Use cellular data when Wi\u2011Fi has no Internet access. Data usage may apply.</string>
<!-- Action bar text message to manually add a wifi network [CHAR LIMIT=20]-->
<string name="wifi_add_network">Add network</string>
<!-- Header for the list of wifi networks-->
@@ -1618,6 +1641,10 @@
<!-- Dialog for Access Points --> <skip />
<!-- Label to show/hide advanced options [CHAR LIMIT=40] -->
<string name="wifi_show_advanced">Advanced options</string>
+ <!-- Message for talkback to say when Advanced Options expanded [CHAR LIMIT=NONE] -->
+ <string name="wifi_advanced_toggle_description_expanded">Drop down list Advanced Options. Double-tap to collapse.</string>
+ <!-- Message for talkback to say when Advanced Options is collapsed [CHAR LIMIT=NONE] -->
+ <string name="wifi_advanced_toggle_description_collapsed">Drop down list Advanced Options. Double-tap to expand.</string>
<!-- Title for the WPS setup dialog [CHAR LIMIT=50] -->
<string name="wifi_wps_setup_title">Wi\u2011Fi Protected Setup</string>
<!-- Message in WPS dialog at start up [CHAR LIMIT=150] -->
@@ -1733,6 +1760,13 @@
<string name="no_internet_access_text">This network has no Internet access. Stay connected?</string>
<string name="no_internet_access_remember">Don\u2019t ask again for this network</string>
+ <!-- Dialog text to tell the user that the selected network has lost Internet access, and asking the user whether they want to avoid this network. -->
+ <string name="lost_internet_access_title">Wi\u2011Fi is not connected to the Internet</string>
+ <string name="lost_internet_access_text">You can switch to the cellular network whenever Wi\u2011Fi has a bad connection. Data usage may apply.</string>
+ <string name="lost_internet_access_switch">Switch to cellular</string>
+ <string name="lost_internet_access_cancel">Stay on Wi\u2011Fi</string>
+ <string name="lost_internet_access_persist">Never show again</string>
+
<!-- Button label to connect to a Wi-Fi network -->
<string name="wifi_connect">Connect</string>
<!-- Failured notification for connect -->
@@ -1959,15 +1993,26 @@
<string name="wifi_calling_suggestion_title">Turn on Wi-Fi Calling</string>
<!-- Summary of suggestion to turn on wifi calling [CHAR LIMIT=60] -->
<string name="wifi_calling_suggestion_summary">Use Wi-Fi instead of mobile network</string>
- <!-- WFC mode [CHAR LIMIT=30] -->
+ <!-- Title of WFC preference item [CHAR LIMIT=30] -->
<string name="wifi_calling_mode_title">Calling preference</string>
- <!-- WFC mode dialog [CHAR LIMIT=30] -->
+ <!-- Title of WFC preference selection dialog [CHAR LIMIT=30] -->
<string name="wifi_calling_mode_dialog_title">Wi-Fi calling mode</string>
+ <!-- Title of WFC roaming preference item [CHAR LIMIT=45] -->
+ <string name="wifi_calling_roaming_mode_title">Roaming preference</string>
+ <!-- Summary of WFC roaming preference item [CHAR LIMIT=NONE]-->
+ <string name="wifi_calling_roaming_mode_summary"><xliff:g id="wfc_roaming_preference" example="Wi-Fi">%1$s</xliff:g></string>
+ <!-- WFC mode dialog [CHAR LIMIT=45] -->
+ <string name="wifi_calling_roaming_mode_dialog_title">Roaming preference</string>
<string-array name="wifi_calling_mode_choices">
<item>Wi-Fi preferred</item>
<item>Cellular preferred</item>
<item>Wi-Fi only</item>
</string-array>
+ <string-array name="wifi_calling_mode_choices_v2">
+ <item>Wi-Fi</item>
+ <item>Cellular</item>
+ <item>Wi-Fi only</item>
+ </string-array>
<string-array name="wifi_calling_mode_values">
<item>"2"</item>
<item>"1"</item>
@@ -1977,12 +2022,21 @@
<item>Wi-Fi preferred</item>
<item>Cellular preferred</item>
</string-array>
+ <string-array name="wifi_calling_mode_choices_v2_without_wifi_only">
+ <item>Wi-Fi</item>
+ <item>Cellular</item>
+ </string-array>
<string-array name="wifi_calling_mode_values_without_wifi_only">
<item>"2"</item>
<item>"1"</item>
</string-array>
<!-- Wi-Fi Calling settings. Text displayed when Wi-Fi Calling is off -->
<string name="wifi_calling_off_explanation">When Wi-Fi calling is on, your phone can route calls via Wi-Fi networks or your carrier\u2019s network, depending on your preference and which signal is stronger. Before turning on this feature, check with your carrier regarding fees and other details.</string>
+ <!-- Title of a preference for updating emergency address [CHAR LIMIT=40] -->
+ <string name="emergency_address_title">Update Emergency Address</string>
+ <!-- Summary of Update Emergency Address preference, explaining usage of emergency address [CHAR LIMIT=NONE] -->
+ <string name="emergency_address_summary">Address used by emergency services as your location if you make a 911 call using WiFi</string>
+
<!-- Sound and alerts settings -->
<skip/>
@@ -1998,7 +2052,7 @@
<!-- Sound settings screen, music effects title [CHAR LIMIT=30]-->
<string name="musicfx_title">Music effects</string>
<!-- Sound settings screen, setting option name -->
- <string name="ring_volume_title">Ringer volume</string>
+ <string name="ring_volume_title">Ring volume</string>
<!-- Sound settings screen, setting option name checkbox -->
<string name="vibrate_in_silent_title">Vibrate when silent</string>
<!-- Sound settings screen, setting option name -->
@@ -2042,7 +2096,7 @@
<string name="volume_notification_description">Notifications</string>
<!-- Volume description for alarm volume -->
<string name="volume_alarm_description">Alarms</string>
- <!-- Image description for ringer volume mute button. -->
+ <!-- Image description for ring volume mute button. -->
<string name="volume_ring_mute">Mute ringtone & notifications</string>
<!-- Image description for media volume mute button. -->
<string name="volume_media_mute">Mute music & other media</string>
@@ -2124,6 +2178,43 @@
<!-- Sound & display settings screen, setting option summary to enable adaptive brightness [CHAR LIMIT=100] -->
<string name="auto_brightness_summary">Optimize brightness level for available light</string>
+ <!-- Night display screen, setting option name to enable night display (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
+ <string name="night_display_title">Night Light</string>
+ <!-- Night display screen, description of night display feature (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
+ <string name="night_display_text">Night Light tints your screen amber. This makes it easier to look at your screen or read in dim light, and may help you fall asleep more easily.</string>
+ <!-- Night display screen, category title for settings to schedule when night display activates automatically. [CHAR LIMIT=30] -->
+ <string name="night_display_category_schedule">Schedule</string>
+ <!-- Night display screen, category title for settings to manually activate night display. [CHAR LIMIT=30] -->
+ <string name="night_display_category_status">Status</string>
+ <!-- Night display screen, setting option name to configure whether night display turn on/off automatically. [CHAR LIMIT=30] -->
+ <string name="night_display_auto_mode_title">Turn on automatically</string>
+ <!-- Night display screen, setting option value for night display to *never* turn on/off automatically. [CHAR LIMIT=30] -->
+ <string name="night_display_auto_mode_never">Never</string>
+ <!-- Night display screen, setting option value for night display to turn on/off automatically according to a user defined schedule. [CHAR LIMIT=30] -->
+ <string name="night_display_auto_mode_custom">Custom schedule</string>
+ <!-- Night display screen, setting option value for night display to turn on/off automatically at sunset/sunrise. [CHAR LIMIT=30] -->
+ <string name="night_display_auto_mode_twilight">Sunset to sunrise</string>
+ <!-- Night display screen, setting option name to configure time to automatically turn on night display. [CHAR LIMIT=30] -->
+ <string name="night_display_start_time_title">Start time</string>
+ <!-- Night display screen, setting option name to configure time to automatically turn off night display. [CHAR LIMIT=30] -->
+ <string name="night_display_end_time_title">End time</string>
+ <!-- Display settings screen, summary format of night display when off. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_off">Off. <xliff:g name="auto_mode_summary" example="Never turn on automatically">%1$s</xliff:g></string>
+ <!-- Display settings screen, summary of night display when off and will *never* turn on automatically. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_off_auto_mode_never">Will never turn on automatically.</string>
+ <!-- Display settings screen, summary format of night display when off and will turn on automatically at a user defined time. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_off_auto_mode_custom">Will turn on automatically at <xliff:g name="time" example="6 AM">%1$s</xliff:g>.</string>
+ <!-- Display settings screen, summary of night display when off and will turn on automatically at sunset. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_off_auto_mode_twilight">Will turn on automatically at sunset.</string>
+ <!-- Display settings screen, summary format of night display when on. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_on">On. <xliff:g name="auto_mode_summary" example="Never turn off automatically">%1$s</xliff:g></string>
+ <!-- Display settings screen, summary of night display when on and will *never* turn off automatically. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_on_auto_mode_never">Will never turn off automatically.</string>
+ <!-- Display settings screen, summary format of night display when on and will turn off automatically at a user defined time. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_on_auto_mode_custom">Will turn off automatically at <xliff:g name="time" example="10 PM">%1$s</xliff:g>.</string>
+ <!-- Display settings screen, summary of night display when on and will turn off automatically at sunrise. [CHAR LIMIT=NONE] -->
+ <string name="night_display_summary_on_auto_mode_twilight">Will turn off automatically at sunrise.</string>
+
<!-- Sound & display settings screen, setting option name to change screen timeout -->
<string name="screen_timeout">Sleep</string>
<!-- Sound & display settings screen, setting option name to change screen timeout [CHAR LIMIT=30] -->
@@ -2165,7 +2256,7 @@
<!-- [CHAR LIMIT=30] Display settings screen, setting option name to change whether the ambient display feature is enabled. -->
<string name="doze_title">Ambient display</string>
<!-- [CHAR LIMIT=NONE] Display settings screen, setting description for the ambient display feature. -->
- <string name="doze_summary">Wake screen when you pick up device or receive notifications</string>
+ <string name="doze_summary">Wake screen when you receive notifications</string>
<!-- [CHAR LIMIT=30] Sound & display settings screen, setting option name to change font size -->
<string name="title_font_size">Font size</string>
<!-- Summary for Font size. Lets the user know that this will make text larger or smaller. Appears in the accessibility portion of setup wizard. [CHAR LIMIT=NONE] -->
@@ -2258,7 +2349,7 @@
<!-- About phone screen, status item label [CHAR LIMIT=60] -->
<string name="security_patch">Android security patch level</string>
<!-- About phone screen, status item label [CHAR LIMIT=40] -->
- <string name="model_number">Model number</string>
+ <string name="model_info">Model</string>
<!-- About phone screen, fcc equipment id label [CHAR LIMIT=40] -->
<string name="fcc_equipment_id">Equipment ID</string>
<!-- About phone screen, setting option name [CHAR LIMIT=40] -->
@@ -2456,6 +2547,10 @@
<string name="storage_menu_set_up">Set up</string>
<!-- Storage setting. Menu option for exploring a storage device [CHAR LIMIT=30]-->
<string name="storage_menu_explore">Explore</string>
+ <!-- Storage setting. Menu option for using the deletion helper. [CHAR LIMIT=30] -->
+ <string name="storage_menu_free">Free up space</string>
+ <!-- Storage setting. Menu option for accessing the storage manager settings. [CHAR LIMIT=30] -->
+ <string name="storage_menu_manage">Manage storage</string>
<!-- Storage setting. Title for USB transfer settings [CHAR LIMIT=30]-->
<string name="storage_title_usb">USB computer connection</string>
@@ -2556,12 +2651,17 @@
<string name="storage_detail_cached">Cached data</string>
<!-- Item title describing storage used by other data [CHAR LIMIT=48]-->
<string name="storage_detail_other">Other</string>
+ <!-- Item title describing internal storage used by the Android System [CHAR LIMIT=48]-->
+ <string name="storage_detail_system">System</string>
<!-- Item title that will launch a file explorer [CHAR LIMIT=48]-->
<string name="storage_detail_explore">Explore <xliff:g id="name" example="SD card">^1</xliff:g></string>
<!-- Body of dialog informing user about other files on a storage device [CHAR LIMIT=NONE]-->
<string name="storage_detail_dialog_other">Other includes shared files saved by apps, files downloaded from the Internet or Bluetooth, Android files, and so on.
-\n\nTo see the entire contents of this <xliff:g id="name" example="SD card">^1</xliff:g>, tap Explore.</string>
+\n\nTo see the visible contents of this <xliff:g id="name" example="SD card">^1</xliff:g>, tap Explore.</string>
+
+ <!-- Body of dialog informing user about the storage used by the Android System [CHAR LIMIT=NONE]-->
+ <string name="storage_detail_dialog_system">System includes files that Android can\u2019t display individually.</string>
<!-- Body of dialog informing user about other users on a storage device [CHAR LIMIT=NONE]-->
<string name="storage_detail_dialog_user"><xliff:g id="user" example="Guest user">^1</xliff:g> may have saved photos, music, movies, apps, or other data that is taking up <xliff:g id="size" example="1.2 GB">^2</xliff:g> of storage.
@@ -3005,8 +3105,10 @@
<string name="contributors_title">Contributors</string>
<!-- About phone settings screen, setting option name to show Manual [CHAR LIMIT=25] -->
<string name="manual">Manual</string>
- <!-- About phone settings screen, setting option name to show regulatory information [CHAR LIMIT=25] -->
- <string name="regulatory_information">Regulatory information</string>
+ <!-- About phone settings screen, setting option name to show regulatory labels [CHAR LIMIT=25] -->
+ <string name="regulatory_labels">Regulatory labels</string>
+ <!-- About phone settings screen, setting option name to show the safety and regulatory manual [CHAR LIMIT=40] -->
+ <string name="safety_and_regulatory_info">Safety & regulatory manual</string>
<!-- Note: this may be replaced by a more-specific title of the activity that will get launched --> <skip />
<!-- About phone settings screen, setting option name to see copyright-related info -->
<string name="copyright_title">Copyright</string>
@@ -3177,19 +3279,19 @@
<!-- 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 the same lock</string>
+ <string name="lock_settings_profile_unification_title">Use one lock</string>
<!-- Security & location settings screen, setting option explanation to unify work and personal locks -->
- <string name="lock_settings_profile_unification_summary">Change device screen lock to match work profile</string>
+ <string name="lock_settings_profile_unification_summary">Use one lock for work profile and device screen</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 lock?</string>
+ <string name="lock_settings_profile_unification_dialog_title">Use one 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 your work profile lock for your device screen lock as well. If you do, any work lock policies will also apply to your device screen lock.</string>
+ <string name="lock_settings_profile_unification_dialog_body">Your work profile and device screen will use the same lock. Any work lock policies will also apply to your device screen lock.</string>
<!-- Security & location settings screen, explanation in the dialog asking if the user wants to create a new lock for personal and work as the current work lock is not enough for the device. -->
- <string name="lock_settings_profile_unification_dialog_uncompliant_body">Your work profile lock doesn\'t meet your organization\'s security requirements.\n\nYou can set a new screen lock for both your device and your work profile, but any work lock policies will apply to your device screen lock as well.</string>
+ <string name="lock_settings_profile_unification_dialog_uncompliant_body">Your work profile lock doesn\'t meet your organization\'s security requirements. You can use the same lock for your device screen and your work profile, but any work lock policies will apply.</string>
<!-- Security & location settings screen, confirmation button of the dialog for user with compliant lock, asking to create a new lock for both personal and work profiles. -->
- <string name="lock_settings_profile_unification_dialog_confirm">Change device lock</string>
+ <string name="lock_settings_profile_unification_dialog_confirm">Use one lock</string>
<!-- Security & location settings screen, confirmation button of the dialog for user with uncompliant lock, asking to create a new lock for both personal and work profiles. -->
- <string name="lock_settings_profile_unification_dialog_uncompliant_confirm">Change lock</string>
+ <string name="lock_settings_profile_unification_dialog_uncompliant_confirm">Use one lock</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 device screen lock</string>
@@ -5238,6 +5340,8 @@
<string name="vpn_no_vpns_added">No VPNs added.</string>
<!-- Preference summary for active always-on vpn [CHAR LIMIT=40] -->
<string name="vpn_always_on_active">Always-on active</string>
+ <!-- Preference summary for app not supporting always-on vpn [CHAR LIMIT=NONE] -->
+ <string name="vpn_not_supported_by_this_app">Not supported by this app</string>
<!-- Summary describing the always-on VPN feature. [CHAR LIMIT=NONE] -->
<string name="vpn_lockdown_summary">Select a VPN profile to always remain connected to. Network traffic will only be allowed when connected to this VPN.</string>
@@ -5535,8 +5639,6 @@
<!-- Help URI, Default [DO NOT TRANSLATE] -->
<string name="help_uri_default" translatable="false"></string>
- <!-- Help URI, Dashboard [DO NOT TRANSLATE] -->
- <string name="help_uri_dashboard" translatable="false"></string>
<!-- Help URI, Android beam [DO NOT TRANSLATE] -->
<string name="help_uri_beam" translatable="false"></string>
<!-- Help URI, Display [DO NOT TRANSLATE] -->
@@ -5600,6 +5702,12 @@
<string name="help_url_remote_display" translatable="false"></string>
<!-- Help URL, Fingerprint [DO NOT TRANSLATE] -->
<string name="help_url_fingerprint" translatable="false"></string>
+ <!-- Help URL, Gesture settings -->
+ <string name="help_url_gestures" translatable="false"></string>
+ <!-- Help URL, Manage Storage [DO NOT TRANSLATE]-->
+ <string name="help_url_manage_storage" translatable="false"></string>
+ <!-- Help URL, Android is upgrading [DO NOT TRANSLATE] -->
+ <string name="help_url_upgrading" translatable="false"></string>
<!-- User account title [CHAR LIMIT=30] -->
<string name="user_account_title">Account for content</string>
@@ -5779,6 +5887,12 @@
<!--Dashboard strings-->
<!-- Text to describe the dashboard fragment title [CHAR LIMIT=16] -->
<string name="dashboard_title">Settings</string>
+ <!-- Text to describe the items to be expanded as suggested settings [CHAR LIMIT=none] -->
+ <plurals name="settings_suggestion_header_summary_hidden_items">
+ <item quantity="one">Show %d hidden item</item>
+ <item quantity="other">Show %d hidden items</item>
+ </plurals>
+
<!-- Search strings -->
<!-- Text to describe the search results fragment title [CHAR LIMIT=16] -->
@@ -5802,6 +5916,7 @@
<string name="keywords_display">screen, touchscreen</string>
<string name="keywords_display_brightness_level">dim screen, touchscreen, battery</string>
<string name="keywords_display_auto_brightness">dim screen, touchscreen, battery</string>
+ <string name="keywords_display_night_display">dim screen, night, tint</string>
<string name="keywords_display_wallpaper">background, personalize, customize display</string>
<string name="keywords_display_font_size">text size</string>
<string name="keywords_display_cast_screen">project, cast</string>
@@ -5834,6 +5949,7 @@
<string name="keywords_lockscreen">slide to unlock, password, pattern, PIN</string>
<string name="keywords_profile_challenge">work challenge, work, profile</string>
<string name="keywords_unification">work profile, managed profile, unify, unification, work, profile</string>
+ <string name="keywords_gesture">gesture</string>
<!-- NFC Wi-Fi pairing/setup strings-->
@@ -5857,11 +5973,18 @@
<!-- Sounds and Notification -->
- <!-- 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 indicating the volume of ringtone. example: Ring volume at 20%.
+ [CHAR LIMIT=100] -->
+ <string name="sound_settings_summary">Ring volume at <xliff:g id="percentage" example="2%">%1$s</xliff:g></string>
+
+ <!-- Sound: Dashboard summary indicating the volume of ringtone when at 0% with vibrate enabled. [CHAR LIMIT=100] -->
+ <string name="sound_settings_summary_vibrate">Ringer set to vibrate</string>
+
+ <!-- Sound: Dashboard summary indicating the volume of ringtone when at 0% with vibrate disabled [CHAR LIMIT=100] -->
+ <string name="sound_settings_summary_silent">Ringer set to silent</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>
+ <string name="sound_settings_example_summary">Ring volume at 80%</string>
<!-- Sound: Title for the option managing media volume. [CHAR LIMIT=30] -->
<string name="media_volume_option_title">Media volume</string>
@@ -5869,7 +5992,7 @@
<!-- Sound: Title for the option managing alarm volume. [CHAR LIMIT=30] -->
<string name="alarm_volume_option_title">Alarm volume</string>
- <!-- Sound: Title for the option managing ringer volume. [CHAR LIMIT=30] -->
+ <!-- Sound: Title for the option managing ring volume. [CHAR LIMIT=30] -->
<string name="ring_volume_option_title">Ring volume</string>
<!-- Sound: Title for the option managing notification volume. [CHAR LIMIT=30] -->
@@ -5926,6 +6049,9 @@
<!-- Sound: Other sounds: Value for the emergency tone option with value 2: vibrate. [CHAR LIMIT=30] -->
<string name="emergency_tone_vibrate">Vibrate</string>
+ <!-- Sound: Other sounds: Title for the option enabling boot sounds. [CHAR LIMIT=30] -->
+ <string name="boot_sounds_title">Power on sounds</string>
+
<!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=30] -->
<string name="zen_mode_settings_title">Do not disturb</string>
@@ -6103,13 +6229,14 @@
</string>
<!-- Title for what display preferences are applied when device is in VR mode -->
- <string name="display_vr_pref_title">When device is in VR mode</string>
+ <string name="display_vr_pref_title">When device is in VR</string>
<!-- [CHAR LIMIT=70] Put display into low-persistence mode, this decreases motion blur. -->
- <string name="display_vr_pref_low_persistence">Use low motion blur settings</string>
+ <string name="display_vr_pref_low_persistence">Reduce blur (recommended)</string>
- <!-- [CHAR LIMIT=70] Do not change display settings. -->
- <string name="display_vr_pref_off">Do nothing</string>
+ <!-- [CHAR LIMIT=70] Do not change default display settings, this may reduce perceived screen
+ flicker while in VR mode. -->
+ <string name="display_vr_pref_off">Reduce flicker</string>
<!-- Sound & notification > Advanced section: Title for managing Do Not Disturb access option. [CHAR LIMIT=40] -->
<string name="manage_zen_access_title">Do Not Disturb access</string>
@@ -6480,6 +6607,9 @@
<!-- Message for encryption dialog telling the user that Talkback and other accessibility services will be disabled. -->
<string name="encrypt_talkback_dialog_message_password">When you enter your password to start this device, accessibility services like <xliff:g id="service" example="TalkBack">%1$s</xliff:g> won\u2019t yet be available.</string>
+ <!-- [CHAR LIMIT=NONE] Dialog body explaining that the app just selected by the user will not work after a reboot until until after the user enters their credentials, such as a PIN or password. -->
+ <string name="direct_boot_unaware_dialog_message">Note: After a reboot, this app can\'t start until you unlock your phone</string>
+
<!-- Title and summary for SIM Status -->
<string name="imei_information_title">IMEI information</string>
<string name="imei_information_summary">IMEI relative information</string>
@@ -6873,6 +7003,11 @@
<!-- Summary for the "screenshot" preference to determine whether assist can access the screenshot of your screen [CHAR LIMIT=NONE] -->
<string name="assist_access_screenshot_summary">Allow the assist app to access an image of the screen</string>
+ <!-- Title for the "flash" preference to determine whether a flash is shown on screen when an assistant accesses the contents of the screeen. [CHAR LIMIT=40] -->
+ <string name="assist_flash_title">Flash screen</string>
+
+ <!-- Summary for the "flash" preference to determine whether a flash is shown on screen when an assistant accesses the contents of the screeen. [CHAR LIMIT=NONE] -->
+ <string name="assist_flash_summary">Flash edges of screen when assist app accesses text from screen or screenshot</string>
<!-- Footer text in the manage assist screen. [CHAR LIMIT=NONE] -->
<string name="assist_footer">Assist apps can help you based on information from the screen you\u2019re viewing. Some apps support both launcher and voice input services to give you integrated assistance.</string>
@@ -7201,8 +7336,17 @@
<!-- Summary of condition that work mode is off [CHAR LIMIT=NONE] -->
<string name="condition_work_summary">Apps, background sync, and other features related to your work profile are turned off.</string>
+ <!-- Title of condition that night display is on (renamed "Night Light" with title caps) [CHAR LIMIT=30] -->
+ <string name="condition_night_display_title">Night Light is on</string>
+
+ <!-- Summary of condition that night display is on (renamed "Night Light" with title caps) [CHAR LIMIT=NONE] -->
+ <string name="condition_night_display_summary">Screen is tinted amber. This may help you fall asleep.</string>
+
<!-- Title for the suggestions section on the dashboard [CHAR LIMIT=30] -->
- <string name="suggestions_title">Suggestions (<xliff:g name="count" example="3">%1$d</xliff:g>)</string>
+ <string name="suggestions_title">Suggestions</string>
+
+ <!-- Summary for the suggestions section on the dashboard, representing number of suggestions. [CHAR LIMIT=10] -->
+ <string name="suggestions_summary">+<xliff:g name="count" example="3">%1$d</xliff:g></string>
<!-- Name of option to remove a suggestion from the list [CHAR LIMIT=30] -->
<string name="suggestion_remove">Remove</string>
@@ -7270,6 +7414,9 @@
<!-- Format string describing how much data has been used [CHAR LIMIT=20] -->
<string name="data_used_template"><xliff:g name="amount" example="1 GB">%1$s</xliff:g> used</string>
+ <!-- Label for switch about whether to warn user about usage [CHAR LIMIT=30] -->
+ <string name="set_data_warning">Set data warning</string>
+
<!-- Label for button to set the amount of data before user is warned about usage [CHAR LIMIT=30] -->
<string name="data_warning">Data warning</string>
@@ -7338,7 +7485,7 @@
<string name="suggestion_additional_fingerprints">Add another fingerprint</string>
<!-- Summary for suggestion adding more fingerprints [CHAR LIMIT=60] -->
- <string name="suggestion_additional_fingerprints_summary">Unlock with a different fingerprint</string>
+ <string name="suggestion_additional_fingerprints_summary">Unlock with a different finger</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>
@@ -7437,19 +7584,23 @@
<!-- Developer option to convert to file encryption - final button -->
<string name="button_confirm_convert_fbe">Wipe and convert</string>
- <!-- Reset rate-limiting in the system service ShortcutManager. [CHAR_LIMIT=none] -->
- <string name="reset_shortcut_manager_throttling">Reset ShortcutManager rate-limiting counters</string>
+ <!-- Reset rate-limiting in the system service ShortcutManager. "ShortcutManager" is the name of a system service and not translatable.
+ If the word "rate-limit" is hard to translate, use "Reset ShortcutManager API call limit" as the source text, which means
+ the same thing in this context.
+ [CHAR_LIMIT=none] -->
+ <string name="reset_shortcut_manager_throttling">Reset ShortcutManager rate-limiting</string>
- <!-- Title of the dialog box to confirm resetting rate-limiting in the system service ShortcutManager. [CHAR_LIMIT=none] -->
- <string name="confirm_reset_shortcut_manager_throttling_title">Reset ShortcutManager rate-limiting?</string>
-
- <!-- Message of the dialog box to confirm resetting rate-limiting in the system service ShortcutManager. [CHAR_LIMIT=none] -->
- <string name="confirm_reset_shortcut_manager_throttling_message">Reset ShortcutManager rate-limiting counters?</string>
+ <!-- Toast message shown when "Reset ShortcutManager rate-limiting" has been performed. [CHAR_LIMIT=none] -->
+ <string name="reset_shortcut_manager_throttling_complete">ShortcutManager rate-limiting has been reset</string>
<!-- Title of notification suggestion during optional steps of setup. [CHAR_LIMIT=60] -->
<string name="notification_suggestion_title">Control lock screen notifications</string>
<!-- Summary of notification suggestion during optional steps of setup. [CHAR_LIMIT=80] -->
<string name="notification_suggestion_summary">Show or hide notification content</string>
+ <!-- Setting tab title for all setting options. [CHAR LIMIT=20] -->
+ <string name="page_tab_title_summary">All</string>
+ <!-- Setting tab title for support setting options. [CHAR LIMIT=20] -->
+ <string name="page_tab_title_support">Support</string>
<!-- Summary of developer options to set the smallest width of the screen [CHAR LIMIT=60]-->
<string name="developer_density_summary"><xliff:g name="count" example="320">%d</xliff:g> dp</string>
@@ -7472,6 +7623,84 @@
<!-- [CHAR LIMIT=60] Name of dev option called demo mode -->
<string name="demo_mode">Demo mode</string>
+ <!-- Title text for connecting to customer support [CHAR LIMIT=80]-->
+ <string name="support_escalation_title">We\'re here to help</string>
+
+ <!-- Title text for connecting to 24/7 available customer support [CHAR LIMIT=80]-->
+ <string name="support_escalation_24_7_title">We\'re here for you 24/7</string>
+
+ <!-- Content description for connecting customer support. The "24 7" part indicates
+ support is available 24 hours a day, 7 days a week. It's used by screenreaders so it
+ cannot contain any symbol other that space. [CHAR LIMIT=80]-->
+ <string name="support_escalation_24_7_content_description">We\'re here for you 24 7</string>
+
+ <!-- Summary text for connecting to customer support [CHAR LIMIT=NONE]-->
+ <string name="support_escalation_summary">Our support team is here to help address any issue</string>
+
+ <!-- Summary text for connecting to 24/7 customer support [CHAR LIMIT=NONE]-->
+ <string name="support_escalation_24_7_summary">Our support team is available all day, every day</string>
+
+ <!-- Summary text when customer support is closed. [CHAR LIMIT=NONE]-->
+ <string name="support_escalation_closed_summary">Search help or come back during support hours (local time):<br><b><xliff:g id="operation_hours">%s</xliff:g></b></string>
+
+ <!-- Summary text to call customer support when there is no internet. [CHAR LIMIT=NONE]-->
+ <string name="support_escalation_no_internet_summary">Phone support hours (local time)<br><b><xliff:g id="operation_hours">%s</xliff:g></b></string>
+
+ <!-- Summary text when customer support is unavailable in the region. [CHAR LIMIT=NONE]-->
+ <string name="support_escalation_unavailable_summary">Search help or explore tips & tricks</string>
+
+ <!-- Template for formatting support hours eg Mon - Fri, 8:00 AM - 19:30 PM. [CHAR LIMIT=NONE]-->
+ <string name="support_hour_format" translatable="false">
+ <xliff:g id="start_day">%s</xliff:g> - <xliff:g id="end_day">%s</xliff:g>, <xliff:g id="start_time">%s</xliff:g> - <xliff:g id="end_time">%s</xliff:g><br>
+ </string>
+
+ <!-- Button label for choosing country for phone support. [CHAR LIMIT=40]-->
+ <string name="support_country_list_title">Support for:</string>
+
+ <!-- Template for formatting country and language. eg Canada - French [CHAR LIMIT=NONE]-->
+ <string name="support_country_format"><xliff:g id="country" example="Canada">%s</xliff:g> - <xliff:g id="language" example="French">%s</xliff:g></string>
+
+ <!-- Template for formatting phone number and language. eg English (800-000-0000) [CHAR LIMIT=NONE]-->
+ <string name ="support_phone_international_format">
+ <xliff:g id="language" example="English">%s</xliff:g> (<xliff:g id="phone" example="800-000-0000">%s</xliff:g>)
+ </string>
+
+ <!-- Title text for a list of international support phone numbers. [CHAR LIMIT=60]-->
+ <string name="support_international_phone_title">Traveling abroad?</string>
+
+ <!-- Description text warning international phone charge may apply when dialing support numbers. [CHAR LIMIT=NONE]-->
+ <string name="support_international_phone_summary">International charges may apply</string>
+
+ <!-- Button label for contacting customer support by phone [CHAR LIMIT=20]-->
+ <string name="support_escalation_by_phone">Phone</string>
+
+ <!-- Button label for contacting customer support by chat [CHAR LIMIT=20]-->
+ <string name="support_escalation_by_chat">Chat</string>
+
+ <!-- Button label for visiting the tips & tricks site [CHAR LIMIT=60]-->
+ <string name="support_tips_and_tricks_title">Explore tips & tricks</string>
+
+ <!-- Button label for visiting help and/or send feedback [CHAR LIMIT=60]-->
+ <string name="support_help_feedback_title">Search help & send feedback</string>
+
+ <!-- Title text that indicates user needs to sign in to get customer support. [CHAR LIMIT=80]-->
+ <string name="support_sign_in_required_title">Contact support</string>
+
+ <!-- Summary text that indicates user needs to sign-in to get real time customer support. [CHAR LIMIT=NONE]-->
+ <string name="support_sign_in_required_summary" translatable="false"></string>
+
+ <!-- Button label for signing in an account [CHAR LIMIT=40]-->
+ <string name="support_sign_in_button_text">Sign in</string>
+
+ <!-- Button label that redirects user who needs help for signin to help screen [CHAR LIMIT=NONE]-->
+ <string name="support_sign_in_required_help">Can\'t sign in?</string>
+
+ <!-- Dialog title displayed before initiating real time support [CHAR LIMIT=80]-->
+ <string name="support_disclaimer_title">Send system information</string>
+
+ <!-- Checkbox text, when checked dialog will not show again [CHAR LIMIT=80] -->
+ <string name="support_disclaimer_do_not_show">Do not show again</string>
+
<!-- [CHAR LIMIT=60] Title of work profile setting page -->
<string name="managed_profile_settings_title">Work profile settings</string>
<!-- [CHAR LIMIT=60] The preference title for enabling cross-profile remote contact search -->
@@ -7479,6 +7708,27 @@
<!-- [CHAR LIMIT=NONE] The preference summary for enabling cross-profile remote contact search -->
<string name="managed_profile_contact_search_summary">Allow contact searches by your organization to identify callers and contacts</string>
+ <!-- Time in hours -->
+ <plurals name="hours">
+ <item quantity="one">1 hour</item>
+ <item quantity="other"><xliff:g id="number" example="7">%s</xliff:g> hours</item>
+ </plurals>
+
+ <!-- Time in minutes -->
+ <plurals name="minutes">
+ <item quantity="one">1 minute</item>
+ <item quantity="other"><xliff:g id="number" example="7">%s</xliff:g> minutes</item>
+ </plurals>
+
+ <!-- Time in seconds -->
+ <plurals name="seconds">
+ <item quantity="one">1 second</item>
+ <item quantity="other"><xliff:g id="number" example="7">%s</xliff:g> seconds</item>
+ </plurals>
+
+ <!-- Estimated wait time range for real time supports -->
+ <string name="support_estimated_wait_time">~<xliff:g id="ESTIMATE" example="2 minutes">%1$s</xliff:g> wait</string>
+
<!-- Message for telling the user the kind of BT device being displayed in list. -->
<string name="bluetooth_talkback_computer">Computer</string>
@@ -7499,4 +7749,112 @@
<!-- Message for telling the user the kind of BT device being displayed in list. -->
<string name="bluetooth_talkback_bluetooth">Bluetooth</string>
+
+ <!-- Used as title on the automatic storage manager settings. [CHAR LIMIT=60] -->
+ <string name="automatic_storage_manager_settings">Manage storage</string>
+
+ <!-- Used as wall of text to describe the feature. [CHAR LIMIT=NONE] -->
+ <string name="automatic_storage_manager_text">To help free up storage space, storage manager removes backed up photos and videos from your device.</string>
+
+ <!-- Dropdown preference title for dropdown describing how many days of data to retain.-->
+ <string name="automatic_storage_manager_days_title">Remove photos & videos</string>
+
+ <!-- Preference title for the automatic storage manager toggle. [CHAR LIMIT=60]-->
+ <string name="automatic_storage_manager_preference_title">Storage manager</string>
+
+ <!-- Category title for the automatic settings in the storage manager settings. [CHAR LIMIT=40] -->
+ <string name="deletion_helper_automatic_title">Automatic</string>
+
+ <!-- Category title for the manual settings in the storage manager settings. [CHAR LIMIT=40] -->
+ <string name="deletion_helper_manual_title">Manual</string>
+
+ <!-- Preference menu title for accessing the deletion helper from the storage manager settings. [CHAR LIMIT=30]-->
+ <string name="deletion_helper_preference_title">Free up space now</string>
+
+ <!-- Preference title for gesture settings [CHAR LIMIT=25]-->
+ <string name="gesture_preference_title">Gestures</string>
+
+ <!-- Preference summary for gesture settings (phone) [CHAR LIMIT=NONE]-->
+ <string name="gesture_preference_summary" product="default">Quick gestures to control your phone</string>
+ <!-- Preference summary for gesture settings (tablet) [CHAR LIMIT=NONE]-->
+ <string name="gesture_preference_summary" product="tablet">Quick gestures to control your tablet</string>
+ <!-- Preference summary for gesture settings (device) [CHAR LIMIT=NONE]-->
+ <string name="gesture_preference_summary" product="device">Quick gestures to control your device</string>
+
+ <!-- Title text for double tap power for camera [CHAR LIMIT=60]-->
+ <string name="double_tap_power_for_camera_title">Jump to Camera</string>
+
+ <!-- Summary text for double tap power for camera [CHAR LIMIT=160]-->
+ <string name="double_tap_power_for_camera_summary">To quickly open camera, press the power button twice. Works from any screen</string>
+
+ <!-- Title text for double twist for camera mode [CHAR LIMIT=60]-->
+ <string name="double_twist_for_camera_mode_title">Flip camera</string>
+
+ <!-- Summary text for double twist for camera mode [CHAR LIMIT=160]-->
+ <string name="double_twist_for_camera_mode_summary"></string>
+
+ <!-- Title text for ambient display double tap (phone) [CHAR LIMIT=60]-->
+ <string name="ambient_display_title" product="default">Double-tap to check phone</string>
+ <!-- Title text for ambient display double tap (tablet) [CHAR LIMIT=60]-->
+ <string name="ambient_display_title" product="tablet">Double-tap to check tablet</string>
+ <!-- Title text for ambient display double tap (device) [CHAR LIMIT=60]-->
+ <string name="ambient_display_title" product="device">Double-tap to check device</string>
+
+ <!-- Summary text for ambient display double tap [CHAR LIMIT=160]-->
+ <string name="ambient_display_summary">To quickly check your notifications, double-tap your screen</string>
+
+ <!-- Title text for ambient display pick up (phone) [CHAR LIMIT=60]-->
+ <string name="ambient_display_pickup_title" product="default">Lift to check phone</string>
+ <!-- Title text for ambient display pick up (tablet) [CHAR LIMIT=60]-->
+ <string name="ambient_display_pickup_title" product="tablet">Lift to check tablet</string>
+ <!-- Title text for ambient display pick up (device) [CHAR LIMIT=60]-->
+ <string name="ambient_display_pickup_title" product="device">Lift to check device</string>
+
+ <!-- Summary text for ambient display (phone) [CHAR LIMIT=160]-->
+ <string name="ambient_display_pickup_summary" product="default">To quickly check your notifications, pick up your phone</string>
+ <!-- Summary text for ambient display (tablet) [CHAR LIMIT=160]-->
+ <string name="ambient_display_pickup_summary" product="tablet">To quickly check your notifications, pick up your tablet</string>
+ <!-- Summary text for ambient display (device) [CHAR LIMIT=160]-->
+ <string name="ambient_display_pickup_summary" product="device">To quickly check your notifications, pick up your device</string>
+
+ <!-- Title text for fingerprint swipe for notifications [CHAR LIMIT=60]-->
+ <string name="fingerprint_swipe_for_notifications_title">Swipe for notifications</string>
+
+ <!-- Summary text for fingerprint swipe for notifications (phone) [CHAR LIMIT=160]-->
+ <string name="fingerprint_swipe_for_notifications_summary" product="default">To check your notifications, swipe down on the fingerprint sensor on the back of your phone</string>
+ <!-- Summary text for fingerprint swipe for notifications (tablet) [CHAR LIMIT=160]-->
+ <string name="fingerprint_swipe_for_notifications_summary" product="tablet">To check your notifications, swipe down on the fingerprint sensor on the back of your tablet</string>
+ <!-- Summary text for fingerprint swipe for notifications (device) [CHAR LIMIT=160]-->
+ <string name="fingerprint_swipe_for_notifications_summary" product="device">To check your notifications, swipe down on the fingerprint sensor on the back of your device</string>
+
+ <!-- Switch text for each gesture setting state -->
+ <string name="gesture_setting_on">On</string>
+ <string name="gesture_setting_off">Off</string>
+
+ <!-- setting enable OEM unlock Checkbox's summary to explain this Checkbox is disabled because the bootloader has been unlocked [CHAR_LIMIT=60] -->
+ <string name="oem_unlock_enable_disabled_summary_bootloader_unlocked">Bootloader is already unlocked</string>
+ <!-- setting enable OEM unlock Checkbox's summary to explain this Checkbox is disabled because there is no connectivity. [CHAR_LIMIT=60] -->
+ <string name="oem_unlock_enable_disabled_summary_connectivity">Connect to the Internet first</string>
+ <!-- setting enable OEM unlock Checkbox's summary to explain this Checkbox is disabled because there is no connectivity or the device is locked by the carrier [CHAR_LIMIT=60] -->
+ <string name="oem_unlock_enable_disabled_summary_connectivity_or_locked">Connect to the Internet or contact your carrier</string>
+ <!-- setting enable OEM unlock Checkbox's summary to explain this Checkbox is disabled because this setting is unavailable on sim-locked devices. [CHAR_LIMIT=60] -->
+ <string name="oem_unlock_enable_disabled_summary_sim_locked_device">Unavailable on carrier-locked devices</string>
+
+ <string name="automatic_storage_manager_freed_bytes"><xliff:g id="size" example="3.25MB">%1$s</xliff:g> total made available\n\nLast ran on <xliff:g id="date" example="Jan 12">%2$s</xliff:g></string>
+
+ <!-- Title text for enabling web actions. [CHAR_LIMIT=60] -->
+ <string name="web_action_enable_title">Open links in apps</string>
+
+ <!-- Summary text for enabling web actions. [CHAR_LIMIT=250] -->
+ <string name="web_action_enable_summary">Open links in supported apps, even if the
+ apps aren’t installed on your device</string>
+
+ <!-- Section title for the Web Action preference [CHAR LIMIT=60] -->
+ <string name="web_action_section_title">Apps not installed</string>
+
+ <!-- Section title for the Domain URL app preference list [CHAR LIMIT=60]-->
+ <string name="domain_url_section_title">Installed apps</string>
+
+ <!-- Warning when activating the automatic storage manager on legacy devices. [CHAR LIMIT=NONE] -->
+ <string name="automatic_storage_manager_activation_warning">Your storage is now being managed by the storage manager</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index bfe2d1c..11e4afb 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -219,7 +219,7 @@
<item name="android:textSize">12sp</item>
<item name="android:textAlignment">viewStart</item>
<item name="android:textAppearance">@android:style/TextAppearance.Material.Body1</item>
- <item name="android:textColor">@color/warning</item>
+ <item name="android:textColor">@*android:color/system_error</item>
</style>
<style name="wifi_item_content">
@@ -286,6 +286,18 @@
<item name="android:singleLine">true</item>
</style>
+ <style name="SetupWizardButton.Negative" parent="@android:style/Widget.Material.Button.Borderless.Colored">
+ <item name="android:minWidth">0dp</item>
+ <item name="android:textAllCaps">false</item>
+ <item name="android:theme">@style/AccentColorHighlightBorderlessButton</item>
+ </style>
+
+ <style name="SetupWizardButton.Positive" parent="@android:style/Widget.Material.Button.Colored" />
+
+ <style name="AccentColorHighlightBorderlessButton">
+ <item name="android:colorControlHighlight">?android:attr/colorAccent</item>
+ </style>
+
<style name="vpn_label">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
@@ -329,6 +341,12 @@
<style name="TextAppearance.RecentsTitle" parent="TextAppearance.CategoryTitle" />
<style name="TextAppearance.ResultTitle" parent="TextAppearance.CategoryTitle" />
+ <style name="TextAppearance.SuggestionTitle"
+ parent="@android:style/TextAppearance.Material.Subhead">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
<style name="TextAppearance.FingerprintMessage"
parent="android:TextAppearance.Material.Subhead">
<item name="android:lineSpacingExtra">@dimen/suw_description_line_spacing_extra</item>
@@ -347,24 +365,31 @@
<style name="TextAppearance.FingerprintErrorText"
parent="android:TextAppearance.Material.Body1">
- <item name="android:textColor">@color/warning</item>
+ <item name="android:textColor">@*android:color/system_error</item>
+ </style>
+
+ <style name="TextAppearance.SupportTitle"
+ parent="@android:style/TextAppearance.Material.Subhead">
+ <item name="android:textColor">?android:attr/colorAccent</item>
+ <item name="android:textSize">24sp</item>
+ </style>
+
+ <style name="TextAppearance.SupportSummary" parent="TextAppearance.CategoryTitle"/>
+
+ <style name="SupportPrimaryButton" parent="android:Widget.Material.Button.Colored"/>
+
+ <style name="SupportSecondaryButton"
+ parent="android:Widget.Material.Button.Borderless.Colored">
+ <item name="android:textSize">12sp</item>
</style>
<style name="FingerprintLayoutTheme">
- <item name="suwBackground">@drawable/fp_enrollment_header</item>
- <item name="suwIllustrationAspectRatio">@dimen/fingerprint_illustration_aspect_ratio</item>
- <item name="suwDecorPaddingTop">@dimen/fingerprint_decor_padding_top</item>
- </style>
-
- <style name="SetupWizardFingerprintLayoutTheme">
- <item name="suwBackgroundTile">@drawable/setup_illustration_tile</item>
- <item name="suwIllustration">@drawable/setup_illustration_lock_screen</item>
- <item name="suwIllustrationHorizontalTile">@drawable/setup_illustration_horizontal_tile</item>
+ <item name="android:icon">@drawable/ic_fingerprint_header</item>
</style>
<style name="TextAppearance.ConfirmDeviceCredentialsErrorText"
parent="android:TextAppearance.Material.Body1">
- <item name="android:textColor">@color/warning</item>
+ <item name="android:textColor">@*android:color/system_error</item>
</style>
<style name="TextAppearance.Small.SwitchBar">
@@ -402,4 +427,18 @@
<item name="android:textAppearance">@android:style/TextAppearance.Material.Subhead</item>
</style>
+ <style name="SupportEscalationCard">
+ <item name="android:background">@color/card_background_grey</item>
+ <item name="android:gravity">center</item>
+ <item name="android:minHeight">368dp</item>
+ <item name="android:paddingStart">56dp</item>
+ <item name="android:paddingEnd">56dp</item>
+ </style>
+
+ <style name="FingerprintHeaderStyle" parent="android:style/TextAppearance.Material.Subhead">
+ <item name="android:paddingTop">16dp</item>
+ <item name="android:textColor">@color/primary_dark_material_light</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ </style>
+
</resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index ef9e1e0..0009bed 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -18,7 +18,6 @@
<attr name="fingerprint_layout_theme" format="reference" />
<attr name="fingerprint_progress_bar_size" format="reference|dimension" />
<attr name="fingerprint_ring_radius" format="reference|dimension" />
- <attr name="ic_menu_add" format="reference" />
<attr name="ic_menu_moreoverflow" format="reference" />
<attr name="ic_wps" format="reference" />
<attr name="setup_divider_color" format="reference" />
@@ -32,18 +31,15 @@
<item name="android:windowBackground">@null</item>
</style>
- <style name="SetupWizardTheme" parent="SuwThemeMaterial">
+ <style name="SetupWizardTheme" parent="SuwThemeGlif">
<!-- For all Alert Dialogs -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
<item name="android:colorPrimary">@color/suw_color_accent_dark</item>
- <item name="android:listPreferredItemPaddingEnd">@dimen/suw_layout_margin_sides</item>
- <item name="android:listPreferredItemPaddingStart">@dimen/suw_layout_margin_sides</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="@*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
- <item name="fingerprint_layout_theme">@style/SetupWizardFingerprintLayoutTheme</item>
+ <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
<item name="fingerprint_progress_bar_size">@dimen/setup_fingerprint_progress_bar_size</item>
<item name="fingerprint_ring_radius">@dimen/setup_fingerprint_ring_radius</item>
- <item name="ic_menu_add">@drawable/ic_menu_add_dark</item>
<item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_material</item>
<item name="ic_wps">@drawable/ic_wps_dark</item>
<item name="setup_divider_color">@color/setup_divider_color_dark</item>
@@ -59,18 +55,15 @@
<item name="@*android:errorColor">@color/setup_lock_pattern_view_error_color_dark</item>
</style>
- <style name="SetupWizardTheme.Light" parent="SuwThemeMaterial.Light">
+ <style name="SetupWizardTheme.Light" parent="SuwThemeGlif.Light">
<!-- For all Alert Dialogs -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
<item name="android:colorPrimary">@color/suw_color_accent_light</item>
- <item name="android:listPreferredItemPaddingEnd">@dimen/suw_layout_margin_sides</item>
- <item name="android:listPreferredItemPaddingStart">@dimen/suw_layout_margin_sides</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="@*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
- <item name="fingerprint_layout_theme">@style/SetupWizardFingerprintLayoutTheme</item>
+ <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
<item name="fingerprint_progress_bar_size">@dimen/setup_fingerprint_progress_bar_size</item>
<item name="fingerprint_ring_radius">@dimen/setup_fingerprint_ring_radius</item>
- <item name="ic_menu_add">@drawable/ic_menu_add_light</item>
<item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_material</item>
<item name="ic_wps">@drawable/ic_wps_light</item>
<item name="setup_divider_color">@color/setup_divider_color_light</item>
@@ -78,7 +71,7 @@
<item name="wifi_signal_color">@color/setup_wizard_wifi_color_light</item>
<item name="wifi_signal">@drawable/wifi_signal</item>
<item name="preferenceBackgroundColor">?android:attr/colorBackground</item>
- <item name="preferenceTheme">@style/PreferenceTheme.SetupWizard</item>
+ <item name="preferenceTheme">@style/PreferenceTheme.SetupWizard.Light</item>
<!-- LockPatternView colors -->
<item name="@*android:regularColor">@color/setup_lock_pattern_view_regular_color_light</item>
@@ -100,17 +93,20 @@
<item name="android:windowAnimationStyle">@null</item>
</style>
- <style name="PreferenceTheme" parent="@android:style/Theme.DeviceDefault.Settings">
+ <style name="PreferenceTheme" parent="@style/PreferenceThemeOverlay.v14.Material">
<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>
+ <item name="android:scrollbars">vertical</item>
</style>
- <style name="PreferenceTheme.SetupWizard">
- <item name="android:listPreferredItemPaddingEnd">@dimen/suw_layout_margin_sides</item>
- <item name="android:listPreferredItemPaddingStart">@dimen/suw_layout_margin_sides</item>
+ <style name="PreferenceTheme.SetupWizard" parent="SetupWizardTheme">
+ <item name="preferenceFragmentStyle">@style/SetupWizardPreferenceFragmentStyle</item>
+ </style>
+
+ <style name="PreferenceTheme.SetupWizard.Light" parent="SetupWizardTheme.Light">
<item name="preferenceFragmentStyle">@style/SetupWizardPreferenceFragmentStyle</item>
</style>
@@ -134,7 +130,7 @@
layouts against a remote context using our local theme colors. Due to the implementation
details of Theme, we can't reference any local resources and MUST instead use the values
directly. So use #ff263238 instead of @color/theme_primary and so on. -->
- <style name="Theme.SettingsBase" parent="@android:style/Theme.Material.Settings" />
+ <style name="Theme.SettingsBase" parent="@android:style/Theme.DeviceDefault.Settings" />
<style name="Theme.Settings" parent="Theme.SettingsBase">
<item name="preferenceTheme">@style/PreferenceTheme</item>
@@ -147,7 +143,6 @@
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
<item name="fingerprint_progress_bar_size">@dimen/fingerprint_progress_bar_size</item>
<item name="fingerprint_ring_radius">@dimen/fingerprint_ring_radius</item>
- <item name="ic_menu_add">@drawable/ic_menu_add_dark</item>
<item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_holo_dark</item>
<item name="ic_wps">@drawable/ic_wps_light</item>
<item name="wifi_signal">@drawable/wifi_signal</item>
@@ -197,19 +192,19 @@
<item name="android:contentInsetStart">@dimen/actionbar_subsettings_contentInsetStart</item>
</style>
- <style name="ThemeOverlay.SwitchBar.Settings" parent="@android:style/ThemeOverlay.Material.Dark.ActionBar">
+ <style name="ThemeOverlay.SwitchBar.Settings" parent="@*android:style/ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent">
<item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
<item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
- <item name="switchBarBackgroundColor">@color/switchbar_background_color</item>
+ <item name="switchBarBackgroundColor">?android:attr/colorSecondary</item>
</style>
<style name="ThemeOverlay.SwitchBar.SubSettings" parent="@android:style/ThemeOverlay.Material.Dark.ActionBar">
<item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
<item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
- <item name="switchBarBackgroundColor">@color/switchbar_background_color</item>
+ <item name="switchBarBackgroundColor">?android:attr/colorSecondary</item>
</style>
- <style name="Theme.DialogWhenLarge" parent="@*android:style/Theme.Material.Settings.DialogWhenLarge">
+ <style name="Theme.DialogWhenLarge" parent="@*android:style/Theme.DeviceDefault.Settings.DialogWhenLarge">
<!-- Redefine the ActionBar style for contentInsetStart -->
<item name="android:actionBarStyle">@style/Theme.ActionBar</item>
@@ -240,7 +235,7 @@
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
- <style name="Theme.AlertDialog" parent="@*android:style/Theme.Material.Settings.Dialog.Alert">
+ <style name="Theme.AlertDialog" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog.Alert">
<item name="android:windowSoftInputMode">adjustResize</item>
<!-- Redefine the ActionBar style for contentInsetStart -->
@@ -255,24 +250,15 @@
<item name="preferenceBackgroundColor">@android:color/transparent</item>
</style>
- <!-- Used to color the switch bar controls -->
- <style name="ThemeOverlay.SwitchBar" parent="@android:style/ThemeOverlay">
- <!-- Used by controls, e.g. CheckBox, ProgressBar, etc. -->
- <item name="android:colorAccent">@color/switch_accent_color</item>
- <item name="switchBarBackgroundColor">@color/switchbar_background_color</item>
- </style>
-
<style name="Theme.ConfirmDeviceCredentials" parent="Theme.SubSettings">
<item name="confirmDeviceCredentialsSideMargin">16dp</item>
<item name="confirmDeviceCredentialsTopMargin">16dp</item>
</style>
- <style name="Theme.ConfirmDeviceCredentialsDark" parent="@android:style/Theme.Material">
- <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
- <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
+ <style name="Theme.ConfirmDeviceCredentialsDark" parent="@android:style/Theme.DeviceDefault">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
- <item name="android:windowBackground">@color/confirm_device_credential_dark_background</item>
+ <item name="android:windowBackground">?android:attr/colorPrimary</item>
<item name="confirmDeviceCredentialsSideMargin">32dp</item>
<item name="confirmDeviceCredentialsTopMargin">32dp</item>
@@ -289,20 +275,14 @@
<item name="android:colorAccent">@*android:color/white</item>
</style>
- <style name="Theme.FingerprintEnroll" parent="@*android:style/Theme.Material.Settings.NoActionBar">
- <item name="android:listPreferredItemHeight">@dimen/suw_items_preferred_height</item>
- <item name="android:listPreferredItemPaddingEnd">@dimen/suw_layout_margin_sides</item>
- <item name="android:listPreferredItemPaddingStart">@dimen/suw_layout_margin_sides</item>
+ <style name="Theme.FingerprintEnroll" parent="SuwThemeGlif.Light">
<item name="android:textAppearanceListItemSmall">@android:style/TextAppearance.Material.Body1</item>
- <item name="android:windowAnimationStyle">@style/Animation.SuwWindowAnimation</item>
- <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
<item name="suwDividerCondition">both</item>
<item name="suwListItemIconColor">?android:attr/colorAccent</item>
- <item name="suwMarginSides">@dimen/suw_layout_margin_sides</item>
</style>
- <style name="FallbackHome" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
+ <style name="FallbackHome" parent="@android:style/Theme.DeviceDefault.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowShowWallpaper">true</item>
@@ -314,4 +294,16 @@
<item name="android:navigationBarColor">#00000000</item>
</style>
+ <style name="FallbackHome.SetupWizard" parent="@android:style/Theme.Material.NoActionBar.Fullscreen">
+ <item name="android:windowBackground">@drawable/fallback_home_unprovisioned_background</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+ <item name="android:statusBarColor">#00000000</item>
+ <item name="android:navigationBarColor">#00000000</item>
+ </style>
+
+ <style name="FallbackHomeProgressBar" parent="FallbackHome">
+ <item name="android:colorControlActivated">?android:attr/textColorPrimary</item>
+ </style>
</resources>
diff --git a/res/xml/advanced_apps.xml b/res/xml/advanced_apps.xml
index 2673569..405d5af 100644
--- a/res/xml/advanced_apps.xml
+++ b/res/xml/advanced_apps.xml
@@ -30,10 +30,7 @@
<PreferenceScreen
android:key="domain_urls"
android:title="@string/domain_urls_title"
- android:fragment="com.android.settings.applications.ManageApplications">
- <extra
- android:name="classname"
- android:value="com.android.settings.Settings$DomainsURLsAppListActivity" />
+ android:fragment="com.android.settings.applications.ManageDomainUrls">
</PreferenceScreen>
<Preference
diff --git a/res/xml/automatic_storage_management_settings.xml b/res/xml/automatic_storage_management_settings.xml
new file mode 100644
index 0000000..2320257
--- /dev/null
+++ b/res/xml/automatic_storage_management_settings.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/automatic_storage_manager_settings" >
+
+ <PreferenceCategory
+ android:key="automatic"
+ android:title="@string/deletion_helper_automatic_title">
+
+ <SwitchPreference
+ android:key="storage_manager_active"
+ android:title="@string/automatic_storage_manager_preference_title"
+ android:summary="@string/automatic_storage_manager_text"/>
+
+
+ <com.android.settings.fuelgauge.WallOfTextPreference
+ android:key="freed_bytes"
+ android:persistent="false"
+ android:selectable="false"
+ settings:allowDividerAbove="false"
+ settings:allowDividerBelow="true" />
+
+ <DropDownPreference
+ android:key="days"
+ android:summary="%s"
+ android:title="@string/automatic_storage_manager_days_title"
+ android:entries="@array/automatic_storage_management_days"
+ android:entryValues="@array/automatic_storage_management_days_values"
+ settings:allowDividerAbove="true" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="manual"
+ android:title="@string/deletion_helper_manual_title">
+
+ <Preference
+ android:key="deletion_helper"
+ android:title="@string/deletion_helper_preference_title"/>
+
+ </PreferenceCategory>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/billing_cycle.xml b/res/xml/billing_cycle.xml
index 9beebce..8c77ad6 100644
--- a/res/xml/billing_cycle.xml
+++ b/res/xml/billing_cycle.xml
@@ -21,6 +21,10 @@
android:key="billing_cycle"
android:title="@string/billing_cycle" />
+ <SwitchPreference
+ android:key="set_data_warning"
+ android:title="@string/set_data_warning"/>
+
<Preference
android:key="data_warning"
android:title="@string/data_warning" />
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index d8f1395..d84b008 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -51,10 +51,11 @@
android:title="@string/bt_hci_snoop_log"
android:summary="@string/bt_hci_snoop_log_summary"/>
- <SwitchPreference
+ <com.android.settingslib.RestrictedSwitchPreference
android:key="oem_unlock_enable"
android:title="@string/oem_unlock_enable"
- android:summary="@string/oem_unlock_enable_summary"/>
+ android:summary="@string/oem_unlock_enable_summary"
+ settings:useAdditionalSummary="true"/>
<PreferenceScreen
android:key="running_apps"
@@ -327,11 +328,6 @@
android:title="@string/strict_mode"
android:summary="@string/strict_mode_summary"/>
- <SwitchPreference
- android:key="show_cpu_usage"
- android:title="@string/show_cpu_usage"
- android:summary="@string/show_cpu_usage_summary"/>
-
<ListPreference
android:key="track_frame_time"
android:title="@string/track_frame_time"
@@ -378,6 +374,10 @@
android:key="force_resizable_activities"
android:title="@string/force_resizable_activities"
android:summary="@string/force_resizable_activities_summary"/>
+
+ <Preference
+ android:key="reset_shortcut_manager_throttling"
+ android:title="@string/reset_shortcut_manager_throttling" />
</PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/device_info_settings.xml b/res/xml/device_info_settings.xml
index 5638f4f..66cf8f4 100644
--- a/res/xml/device_info_settings.xml
+++ b/res/xml/device_info_settings.xml
@@ -15,6 +15,7 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/about_settings">
<!-- System update settings - launches activity -->
@@ -35,10 +36,8 @@
<!-- Device status - launches activity -->
<PreferenceScreen android:key="status_info"
android:title="@string/device_status"
- android:summary="@string/device_status_summary">
- <intent android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.settings"
- android:targetClass="com.android.settings.Settings$StatusActivity" />
+ android:summary="@string/device_status_summary"
+ android:fragment="com.android.settings.deviceinfo.Status">
</PreferenceScreen>
<!-- Manual -->
@@ -56,21 +55,31 @@
<PreferenceScreen
android:key="regulatory_info"
- android:title="@string/regulatory_information">
+ android:title="@string/regulatory_labels">
<intent android:action="android.settings.SHOW_REGULATORY_INFO" />
</PreferenceScreen>
+ <PreferenceScreen
+ android:key="safety_info"
+ android:title="@string/safety_and_regulatory_info">
+ <intent android:action="android.settings.SHOW_SAFETY_AND_REGULATORY_INFO" />
+ </PreferenceScreen>
+
<!-- Feedback on the device -->
<PreferenceScreen android:key="device_feedback"
android:title="@string/device_feedback">
</PreferenceScreen>
<!-- Device hardware model -->
- <Preference android:key="device_model"
+ <com.android.settings.DividerPreference
+ android:key="device_model"
android:enabled="false"
android:shouldDisableView="false"
- android:title="@string/model_number"
- android:summary="@string/device_info_default"/>
+ android:selectable="false"
+ android:title="@string/model_info"
+ android:summary="@string/device_info_default"
+ settings:allowDividerAbove="true"
+ settings:allowDividerBelow="true"/>
<!-- Device firmware version -->
<Preference android:key="firmware_version"
@@ -80,32 +89,45 @@
android:summary="@string/device_info_default"/>
<!-- Security patch level -->
- <Preference android:key="security_patch"
- android:enabled="false"
- android:shouldDisableView="false"
+ <PreferenceScreen android:key="security_patch"
android:title="@string/security_patch"
- android:summary="@string/device_info_default"/>
+ android:summary="@string/device_info_default">
+ <intent android:action="android.intent.action.VIEW"
+ android:data="https://source.android.com/security/bulletin/" />
+ </PreferenceScreen>
<!-- Device FCC equipment id -->
- <Preference android:key="fcc_equipment_id"
+ <com.android.settings.DividerPreference
+ android:key="fcc_equipment_id"
android:enabled="false"
android:shouldDisableView="false"
+ android:selectable="false"
android:title="@string/fcc_equipment_id"
- android:summary="@string/device_info_default"/>
+ android:summary="@string/device_info_default"
+ settings:allowDividerAbove="true"
+ settings:allowDividerBelow="true"/>
<!-- Device Baseband version -->
- <Preference android:key="baseband_version"
+ <com.android.settings.DividerPreference
+ android:key="baseband_version"
android:enabled="false"
android:shouldDisableView="false"
+ android:selectable="false"
android:title="@string/baseband_version"
- android:summary="@string/device_info_default"/>
+ android:summary="@string/device_info_default"
+ settings:allowDividerAbove="true"
+ settings:allowDividerBelow="true"/>
<!-- Device Kernel version -->
- <Preference android:key="kernel_version"
+ <com.android.settings.DividerPreference
+ android:key="kernel_version"
android:enabled="false"
android:shouldDisableView="false"
+ android:selectable="false"
android:title="@string/kernel_version"
- android:summary="@string/device_info_default"/>
+ android:summary="@string/device_info_default"
+ settings:allowDividerAbove="true"
+ settings:allowDividerBelow="true"/>
<!-- Detailed build version -->
<Preference android:key="build_number"
@@ -115,10 +137,14 @@
android:summary="@string/device_info_default"/>
<!-- SELinux status information -->
- <Preference android:key="selinux_status"
+ <com.android.settings.DividerPreference
+ android:key="selinux_status"
android:enabled="false"
android:shouldDisableView="false"
+ android:selectable="false"
android:title="@string/selinux_status"
- android:summary="@string/selinux_status_enforcing"/>
+ android:summary="@string/selinux_status_enforcing"
+ settings:allowDividerAbove="true"
+ settings:allowDividerBelow="true"/>
</PreferenceScreen>
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 816f27b..b5e2848 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -32,6 +32,13 @@
settings:keywords="@string/keywords_display_auto_brightness"
android:summary="@string/auto_brightness_summary" />
+ <com.android.settings.display.NightDisplayPreference
+ android:key="night_display"
+ android:title="@string/night_display_title"
+ android:fragment="com.android.settings.display.NightDisplaySettings"
+ android:widgetLayout="@null"
+ settings:keywords="@string/keywords_display_night_display" />
+
<!-- Hide night mode for now
<ListPreference
android:key="night_mode"
@@ -45,8 +52,11 @@
android:key="wallpaper"
android:title="@string/wallpaper_settings_title"
settings:keywords="@string/keywords_display_wallpaper"
- android:fragment="com.android.settings.WallpaperTypeSettings"
- settings:useAdminDisabledSummary="true" />
+ settings:useAdminDisabledSummary="true" >
+ <intent
+ android:targetPackage="@string/config_wallpaper_picker_package"
+ android:targetClass="@string/config_wallpaper_picker_class" />
+ </com.android.settingslib.RestrictedPreference>
<com.android.settings.TimeoutListPreference
android:key="screen_timeout"
@@ -60,11 +70,6 @@
android:title="@string/camera_gesture_title"
android:summary="@string/camera_gesture_desc" />
- <SwitchPreference
- android:key="camera_double_tap_power_gesture"
- android:title="@string/camera_double_tap_power_gesture_title"
- android:summary="@string/camera_double_tap_power_gesture_desc" />
-
<PreferenceScreen
android:key="screensaver"
android:title="@string/screensaver_settings_title"
diff --git a/res/xml/fingerprint_enroll_introduction_items.xml b/res/xml/fingerprint_enroll_introduction_items.xml
deleted file mode 100644
index 4cb18a6..0000000
--- a/res/xml/fingerprint_enroll_introduction_items.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?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.
--->
-
-<ItemGroup xmlns:android="http://schemas.android.com/apk/res/android">
-
- <Item
- android:enabled="false"
- android:id="@+id/fingerprint_introduction_message"
- android:layout="@layout/suw_item_link_description"/>
-
- <Item
- android:id="@+id/next_button"
- android:icon="@drawable/ic_fingerprint_list_icon"
- android:title="@string/security_settings_fingerprint_enroll_introduction_continue" />
-
- <Item
- android:id="@+id/cancel_button"
- android:icon="@drawable/ic_skip"
- android:title="@string/security_settings_fingerprint_enroll_introduction_cancel" />
-
-</ItemGroup>
\ No newline at end of file
diff --git a/res/xml/gesture_settings.xml b/res/xml/gesture_settings.xml
new file mode 100644
index 0000000..af365bf
--- /dev/null
+++ b/res/xml/gesture_settings.xml
@@ -0,0 +1,52 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/gesture_preference_title"
+ settings:keywords="@string/keywords_gesture">
+
+ <com.android.settings.gestures.GesturePreference
+ android:key="gesture_swipe_down_fingerprint"
+ android:title="@string/fingerprint_swipe_for_notifications_title"
+ android:summary="@string/fingerprint_swipe_for_notifications_summary"
+ settings:animation="@raw/gesture_fingerprint_swipe"/>
+
+ <com.android.settings.gestures.GesturePreference
+ android:key="gesture_double_tap_power"
+ android:title="@string/double_tap_power_for_camera_title"
+ android:summary="@string/double_tap_power_for_camera_summary"
+ settings:animation="@raw/gesture_double_tap"/>
+
+ <com.android.settings.gestures.GesturePreference
+ android:key="gesture_double_twist"
+ android:title="@string/double_twist_for_camera_mode_title"
+ android:summary="@string/double_twist_for_camera_mode_summary"
+ settings:animation="@raw/gesture_twist"/>
+
+ <com.android.settings.gestures.GesturePreference
+ android:key="gesture_double_tap_screen"
+ android:title="@string/ambient_display_title"
+ android:summary="@string/ambient_display_summary"
+ settings:animation="@raw/gesture_ambient_tap"/>
+
+ <com.android.settings.gestures.GesturePreference
+ android:key="gesture_pick_up"
+ android:title="@string/ambient_display_pickup_title"
+ android:summary="@string/ambient_display_pickup_summary"
+ settings:animation="@raw/gesture_ambient_lift"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/manage_assist.xml b/res/xml/manage_assist.xml
index 6984f88..7d4928d 100644
--- a/res/xml/manage_assist.xml
+++ b/res/xml/manage_assist.xml
@@ -36,6 +36,12 @@
android:title="@string/assist_access_screenshot_title"
android:summary="@string/assist_access_screenshot_summary"/>
+ <SwitchPreference
+ android:key="flash"
+ android:title="@string/assist_flash_title"
+ android:summary="@string/assist_flash_summary"
+ />
+
<com.android.settings.voice.VoiceInputListPreference
android:key="voice_input_settings"
android:title="@string/voice_input_settings_title"
diff --git a/res/xml/night_display_settings.xml b/res/xml/night_display_settings.xml
new file mode 100644
index 0000000..76b9323
--- /dev/null
+++ b/res/xml/night_display_settings.xml
@@ -0,0 +1,54 @@
+<?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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/night_display_title">
+
+ <PreferenceCategory
+ android:title="@string/night_display_category_schedule">
+
+ <DropDownPreference
+ android:key="night_display_auto_mode"
+ android:title="@string/night_display_auto_mode_title"
+ android:summary="%s" />
+
+ <Preference
+ android:key="night_display_start_time"
+ android:title="@string/night_display_start_time_title" />
+
+ <Preference
+ android:key="night_display_end_time"
+ android:title="@string/night_display_end_time_title" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/night_display_category_status">
+
+ <com.android.settings.display.NightDisplayPreference
+ android:key="night_display_activated"
+ android:title="@string/night_display_title" />
+
+ </PreferenceCategory>
+
+ <com.android.settings.fuelgauge.WallOfTextPreference
+ android:summary="@string/night_display_text"
+ android:selectable="false"
+ settings:allowDividerAbove="true" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/other_sound_settings.xml b/res/xml/other_sound_settings.xml
index 66535e3..da67d03 100644
--- a/res/xml/other_sound_settings.xml
+++ b/res/xml/other_sound_settings.xml
@@ -55,6 +55,11 @@
android:title="@string/dock_audio_media_title"
android:summary="%s" />
+ <!-- Boot sounds -->
+ <SwitchPreference
+ android:key="boot_sounds"
+ android:title="@string/boot_sounds_title" />
+
<!-- Emergency tone -->
<DropDownPreference
android:key="emergency_tone"
diff --git a/res/xml/privacy_settings.xml b/res/xml/privacy_settings.xml
index 8c66fe1..f2af8f3 100644
--- a/res/xml/privacy_settings.xml
+++ b/res/xml/privacy_settings.xml
@@ -50,15 +50,6 @@
android:enabled="false"
android:selectable="false" />
- <!-- Network reset -->
- <com.android.settingslib.RestrictedPreference
- android:key="network_reset"
- android:title="@string/reset_network_title"
- settings:keywords="@string/keywords_network_reset"
- settings:userRestriction="no_network_reset"
- settings:useAdminDisabledSummary="true"
- android:fragment="com.android.settings.ResetNetwork" />
-
<!-- Factory reset -->
<com.android.settingslib.RestrictedPreference
android:key="factory_reset"
diff --git a/res/xml/security_settings_picker.xml b/res/xml/security_settings_picker.xml
index 7b6069d..6b52156 100644
--- a/res/xml/security_settings_picker.xml
+++ b/res/xml/security_settings_picker.xml
@@ -47,4 +47,9 @@
android:key="unlock_set_managed"
android:persistent="false"/>
+ <com.android.settingslib.RestrictedPreference
+ android:key="unlock_skip_fingerprint"
+ android:title="@string/fingerprint_unlock_skip_fingerprint"
+ android:persistent="false"/>
+
</PreferenceScreen>
diff --git a/res/xml/shortcuts.xml b/res/xml/shortcuts.xml
new file mode 100644
index 0000000..afb2104
--- /dev/null
+++ b/res/xml/shortcuts.xml
@@ -0,0 +1,39 @@
+<?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
+ -->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="manifest-shortcut-wifi"
+ android:icon="@drawable/ic_shortcut_wireless"
+ android:shortcutShortLabel="@string/wifi_settings" >
+ <intent android:action="android.settings.WIFI_SETTINGS" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="manifest-shortcut-data-usage"
+ android:icon="@drawable/ic_shortcut_data_usage"
+ android:shortcutShortLabel="@string/data_usage_summary_title">
+ <intent
+ android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.Settings$DataUsageSummaryActivity" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="manifest-shortcut-battery"
+ android:icon="@drawable/ic_shortcut_battery"
+ android:shortcutShortLabel="@string/power_usage_summary_title" >
+ <intent android:action="android.intent.action.POWER_USAGE_SUMMARY" />
+ </shortcut>
+</shortcuts>
\ No newline at end of file
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index cd0103d..1375ed4 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -26,7 +26,7 @@
<com.android.settings.DimmableIconPreference
android:key="user_add"
android:title="@string/user_add_user_or_profile_menu"
- android:icon="@drawable/ic_menu_add_dark" />
+ android:icon="@drawable/ic_menu_add" />
<PreferenceCategory
android:key="lock_screen_settings"
diff --git a/res/xml/wifi_calling_settings.xml b/res/xml/wifi_calling_settings.xml
index ca4e560..0adb1e8 100644
--- a/res/xml/wifi_calling_settings.xml
+++ b/res/xml/wifi_calling_settings.xml
@@ -26,4 +26,17 @@
android:entryValues="@array/wifi_calling_mode_values"
android:dialogTitle="@string/wifi_calling_mode_dialog_title" />
+ <ListPreference
+ android:key="wifi_calling_roaming_mode"
+ android:title="@string/wifi_calling_roaming_mode_title"
+ android:summary="@string/wifi_calling_roaming_mode_summary"
+ android:entries="@array/wifi_calling_mode_choices_v2"
+ android:entryValues="@array/wifi_calling_mode_values"
+ android:dialogTitle="@string/wifi_calling_roaming_mode_dialog_title" />
+
+ <Preference
+ android:key="emergency_address_key"
+ android:title="@string/emergency_address_title"
+ android:summary="@string/emergency_address_summary" />
+
</PreferenceScreen>
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index 3aeb83e..863007c 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -41,6 +41,11 @@
android:summary="@string/wifi_automatically_connect_summary"
android:dialogTitle="@string/wifi_select_assistant_dialog_title" />
+ <SwitchPreference
+ android:key="wifi_cellular_data_fallback"
+ android:title="@string/wifi_cellular_data_fallback_title"
+ android:summary="@string/wifi_cellular_data_fallback_summary"/>
+
<com.android.settings.DividerPreference
android:key="mac_address"
android:title="@string/wifi_advanced_mac_address_title"
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index 0461bf8..e94db56 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -89,4 +89,13 @@
android:key="proxy_settings"
android:title="@string/proxy_settings_title" />
+ <!-- Network reset -->
+ <com.android.settingslib.RestrictedPreference
+ android:key="network_reset"
+ android:title="@string/reset_network_title"
+ settings:keywords="@string/keywords_network_reset"
+ settings:userRestriction="no_network_reset"
+ settings:useAdminDisabledSummary="true"
+ android:fragment="com.android.settings.ResetNetwork" />
+
</PreferenceScreen>
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index 8a397f1..7383366 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -24,11 +24,13 @@
import android.app.DialogFragment;
import android.content.ContentUris;
import android.content.ContentValues;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.provider.Telephony;
import android.support.v14.preference.MultiSelectListPreference;
import android.support.v14.preference.SwitchPreference;
@@ -36,6 +38,7 @@
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -49,8 +52,12 @@
import android.view.View.OnKeyListener;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.util.ArrayUtils;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
public class ApnEditor extends SettingsPreferenceFragment
@@ -105,6 +112,9 @@
private int mBearerInitialVal = 0;
private String mMvnoTypeStr;
private String mMvnoMatchDataStr;
+ private String[] mReadOnlyApnTypes;
+ private String[] mReadOnlyApnFields;
+ private boolean mReadOnlyApn;
/**
* Standard projection for the interesting columns of a normal note.
@@ -132,7 +142,8 @@
Telephony.Carriers.BEARER_BITMASK, // 19
Telephony.Carriers.ROAMING_PROTOCOL, // 20
Telephony.Carriers.MVNO_TYPE, // 21
- Telephony.Carriers.MVNO_MATCH_DATA // 22
+ Telephony.Carriers.MVNO_MATCH_DATA, // 22
+ Telephony.Carriers.EDITED // 23
};
private static final int ID_INDEX = 0;
@@ -157,6 +168,7 @@
private static final int ROAMING_PROTOCOL_INDEX = 20;
private static final int MVNO_TYPE_INDEX = 21;
private static final int MVNO_MATCH_DATA_INDEX = 22;
+ private static final int EDITED_INDEX = 23;
@Override
@@ -206,6 +218,9 @@
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mFirstTime = icicle == null;
+ mReadOnlyApn = false;
+ mReadOnlyApnTypes = null;
+ mReadOnlyApnFields = null;
if (action.equals(Intent.ACTION_EDIT)) {
Uri uri = intent.getData();
@@ -214,6 +229,17 @@
finish();
return;
}
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfig();
+ if (b != null) {
+ mReadOnlyApnTypes = b.getStringArray(
+ CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
+ mReadOnlyApnFields = b.getStringArray(
+ CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY);
+ }
+ }
mUri = uri;
} else if (action.equals(Intent.ACTION_INSERT)) {
if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
@@ -255,6 +281,17 @@
mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
+ Log.d(TAG, "onCreate: EDITED " + mCursor.getInt(EDITED_INDEX));
+ // if it's not a USER_EDITED apn, check if it's read-only
+ if (mCursor.getInt(EDITED_INDEX) != Telephony.Carriers.USER_EDITED &&
+ apnTypesMatch(mReadOnlyApnTypes, mCursor.getString(TYPE_INDEX))) {
+ Log.d(TAG, "onCreate: apnTypesMatch; read-only APN");
+ mReadOnlyApn = true;
+ disableAllFields();
+ } else if (!ArrayUtils.isEmpty(mReadOnlyApnFields)) {
+ disableFields(mReadOnlyApnFields);
+ }
+
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
getPreferenceScreen().getPreference(i).setOnPreferenceChangeListener(this);
}
@@ -262,6 +299,153 @@
fillUi();
}
+ /**
+ * Check if passed in array of APN types indicates all APN types
+ * @param apnTypes array of APN types. "*" indicates all types.
+ * @return true if all apn types are included in the array, false otherwise
+ */
+ private boolean hasAllApns(String[] apnTypes) {
+ if (ArrayUtils.isEmpty(apnTypes)) {
+ return false;
+ }
+
+ List apnList = Arrays.asList(apnTypes);
+ if (apnList.contains(PhoneConstants.APN_TYPE_ALL)) {
+ Log.d(TAG, "hasAllApns: true because apnList.contains(PhoneConstants.APN_TYPE_ALL)");
+ return true;
+ }
+ for (String apn : PhoneConstants.APN_TYPES) {
+ if (!apnList.contains(apn)) {
+ return false;
+ }
+ }
+
+ Log.d(TAG, "hasAllApns: true");
+ return true;
+ }
+
+ /**
+ * Check if APN types overlap.
+ * @param apnTypesArray1 array of APNs. Empty array indicates no APN type; "*" indicates all
+ * types
+ * @param apnTypes2 comma separated string of APN types. Empty string represents all types.
+ * @return if any apn type matches return true, otherwise return false
+ */
+ private boolean apnTypesMatch(String[] apnTypesArray1, String apnTypes2) {
+ if (ArrayUtils.isEmpty(apnTypesArray1)) {
+ return false;
+ }
+
+ if (hasAllApns(apnTypesArray1) || TextUtils.isEmpty(apnTypes2)) {
+ return true;
+ }
+
+ List apnTypesList1 = Arrays.asList(apnTypesArray1);
+ String[] apnTypesArray2 = apnTypes2.split(",");
+
+ for (String apn : apnTypesArray2) {
+ if (apnTypesList1.contains(apn.trim())) {
+ Log.d(TAG, "apnTypesMatch: true because match found for " + apn.trim());
+ return true;
+ }
+ }
+
+ Log.d(TAG, "apnTypesMatch: false");
+ return false;
+ }
+
+ /**
+ * Function to get Preference obj corresponding to an apnField
+ * @param apnField apn field name for which pref is needed
+ * @return Preference obj corresponding to passed in apnField
+ */
+ private Preference getPreferenceFromFieldName(String apnField) {
+ switch (apnField) {
+ case Telephony.Carriers.NAME:
+ return mName;
+ case Telephony.Carriers.APN:
+ return mApn;
+ case Telephony.Carriers.PROXY:
+ return mProxy;
+ case Telephony.Carriers.PORT:
+ return mPort;
+ case Telephony.Carriers.USER:
+ return mUser;
+ case Telephony.Carriers.SERVER:
+ return mServer;
+ case Telephony.Carriers.PASSWORD:
+ return mPassword;
+ case Telephony.Carriers.MMSPROXY:
+ return mMmsProxy;
+ case Telephony.Carriers.MMSPORT:
+ return mMmsPort;
+ case Telephony.Carriers.MMSC:
+ return mMmsc;
+ case Telephony.Carriers.MCC:
+ return mMcc;
+ case Telephony.Carriers.MNC:
+ return mMnc;
+ case Telephony.Carriers.TYPE:
+ return mApnType;
+ case Telephony.Carriers.AUTH_TYPE:
+ return mAuthType;
+ case Telephony.Carriers.PROTOCOL:
+ return mProtocol;
+ case Telephony.Carriers.ROAMING_PROTOCOL:
+ return mRoamingProtocol;
+ case Telephony.Carriers.CARRIER_ENABLED:
+ return mCarrierEnabled;
+ case Telephony.Carriers.BEARER:
+ case Telephony.Carriers.BEARER_BITMASK:
+ return mBearerMulti;
+ case Telephony.Carriers.MVNO_TYPE:
+ return mMvnoType;
+ case Telephony.Carriers.MVNO_MATCH_DATA:
+ return mMvnoMatchData;
+ }
+ return null;
+ }
+
+ /**
+ * Disables given fields so that user cannot modify them
+ *
+ * @param apnFields fields to be disabled
+ */
+ private void disableFields(String[] apnFields) {
+ for (String apnField : apnFields) {
+ Preference preference = getPreferenceFromFieldName(apnField);
+ if (preference != null) {
+ preference.setEnabled(false);
+ }
+ }
+ }
+
+ /**
+ * Disables all fields so that user cannot modify the APN
+ */
+ private void disableAllFields() {
+ mName.setEnabled(false);
+ mApn.setEnabled(false);
+ mProxy.setEnabled(false);
+ mPort.setEnabled(false);
+ mUser.setEnabled(false);
+ mServer.setEnabled(false);
+ mPassword.setEnabled(false);
+ mMmsProxy.setEnabled(false);
+ mMmsPort.setEnabled(false);
+ mMmsc.setEnabled(false);
+ mMcc.setEnabled(false);
+ mMnc.setEnabled(false);
+ mApnType.setEnabled(false);
+ mAuthType.setEnabled(false);
+ mProtocol.setEnabled(false);
+ mRoamingProtocol.setEnabled(false);
+ mCarrierEnabled.setEnabled(false);
+ mBearerMulti.setEnabled(false);
+ mMvnoType.setEnabled(false);
+ mMvnoMatchData.setEnabled(false);
+ }
+
@Override
protected int getMetricsCategory() {
return MetricsEvent.APN_EDITOR;
@@ -552,7 +736,7 @@
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// If it's a new APN, then cancel will delete the new entry in onPause
- if (!mNewApn) {
+ if (!mNewApn && !mReadOnlyApn) {
menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
.setIcon(R.drawable.ic_menu_delete);
}
diff --git a/src/com/android/settings/AppListPreference.java b/src/com/android/settings/AppListPreference.java
index 61b4260..1ebeeaa 100644
--- a/src/com/android/settings/AppListPreference.java
+++ b/src/com/android/settings/AppListPreference.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -265,6 +266,24 @@
}
}
+ /**
+ * Sets app label as summary if there is only 1 app applicable to this preference.
+ */
+ protected void setSoleAppLabelAsSummary() {
+ final CharSequence soleLauncherLabel = getSoleAppLabel();
+ if (!TextUtils.isEmpty(soleLauncherLabel)) {
+ setSummary(soleLauncherLabel);
+ }
+ }
+
+ /**
+ * Returns app label if there is only 1 app applicable to this preference.
+ */
+ protected CharSequence getSoleAppLabel() {
+ // Intentionally left empty so subclasses can override with necessary logic.
+ return null;
+ }
+
private static class SavedState implements Parcelable {
public final CharSequence[] entryValues;
diff --git a/src/com/android/settings/BackupSettingsActivity.java b/src/com/android/settings/BackupSettingsActivity.java
new file mode 100644
index 0000000..a4cc4b7
--- /dev/null
+++ b/src/com/android/settings/BackupSettingsActivity.java
@@ -0,0 +1,72 @@
+/*
+ * 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.app.Activity;
+import android.app.backup.BackupManager;
+import android.app.backup.IBackupManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+
+import java.net.URISyntaxException;
+
+/**
+ * A trampoline activity used to launch the configured Backup activity.
+ * This activity used the theme NoDisplay to minimize the flicker that might be seen for the launch-
+ * finsih transition.
+ */
+public class BackupSettingsActivity extends Activity {
+ private static final String TAG = "BackupSettingsActivity";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String backup = getResources().getString(R.string.config_backup_settings_intent);
+ if (!TextUtils.isEmpty(backup)) {
+ try {
+ Intent intent = Intent.parseUri(backup, 0);
+ if (intent.resolveActivity(getPackageManager()) != null) {
+ // use startActivityForResult to let the activity check the caller signature
+ IBackupManager bmgr = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ boolean backupOkay;
+ try {
+ backupOkay = bmgr.isBackupServiceActive(UserHandle.myUserId());
+ } catch (Exception e) {
+ // things go wrong talking to the backup system => ignore and
+ // pass the default 'false' as the "backup is a thing?" state.
+ backupOkay = false;
+ }
+ intent.putExtra(BackupManager.EXTRA_BACKUP_SERVICES_AVAILABLE, backupOkay);
+ startActivityForResult(intent, -1);
+ } else {
+ Log.e(TAG, "Backup component not found!");
+ }
+ } catch (URISyntaxException e) {
+ Log.e(TAG, "Invalid backup component URI!", e);
+ }
+ }
+ finish();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 5eb5132..3b592d4 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -16,6 +16,11 @@
package com.android.settings;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+import static com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity;
import android.app.AlertDialog;
@@ -32,7 +37,6 @@
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.RemovalCallback;
import android.os.Bundle;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
@@ -42,19 +46,18 @@
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
-import android.view.View;
import android.view.accessibility.AccessibilityManager;
-import android.widget.Toast;
+import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.fingerprint.FingerprintEnrollBase;
+import com.android.settings.fingerprint.FingerprintEnrollFindSensor;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
import java.util.List;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
public class ChooseLockGeneric extends SettingsActivity {
public static final String CONFIRM_CREDENTIALS = "confirm_credentials";
@@ -64,8 +67,8 @@
modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName());
String action = modIntent.getAction();
- if (DevicePolicyManager.ACTION_SET_NEW_PASSWORD.equals(action)
- || DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(action)) {
+ if (ACTION_SET_NEW_PASSWORD.equals(action)
+ || ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(action)) {
modIntent.putExtra(EXTRA_HIDE_DRAWER, true);
}
return modIntent;
@@ -93,6 +96,7 @@
private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
private static final String KEY_UNLOCK_SET_MANAGED = "unlock_set_managed";
+ private static final String KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
private static final String PASSWORD_CONFIRMED = "password_confirmed";
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
public static final String MINIMUM_QUALITY_KEY = "minimum_quality";
@@ -104,6 +108,8 @@
private static final int CONFIRM_EXISTING_REQUEST = 100;
private static final int ENABLE_ENCRYPTION_REQUEST = 101;
private static final int CHOOSE_LOCK_REQUEST = 102;
+ private static final int CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST = 103;
+ private static final int SKIP_FINGERPRINT_REQUEST = 104;
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private DevicePolicyManager mDPM;
@@ -122,6 +128,7 @@
private int mUserId;
private boolean mHideDrawer = false;
private ManagedLockPasswordProvider mManagedPasswordProvider;
+ private boolean mIsSetNewPassword = false;
protected boolean mForFingerprint = false;
@@ -134,12 +141,15 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ String chooseLockAction = getActivity().getIntent().getAction();
mFingerprintManager =
(FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE);
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mKeyStore = KeyStore.getInstance();
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity());
mLockPatternUtils = new LockPatternUtils(getActivity());
+ mIsSetNewPassword = ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
+ || ACTION_SET_NEW_PASSWORD.equals(chooseLockAction);
// Defaults to needing to confirm credentials
final boolean confirmCredentials = getActivity().getIntent()
@@ -157,6 +167,16 @@
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
+ if (mIsSetNewPassword) {
+ // In ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or ACTION_SET_NEW_PASSWORD, the user
+ // will be asked to confirm the password if one has been set.
+ // On fingerprint supported device, fingerprint options are represented in the
+ // options. If the user chooses to skip fingerprint setup, ChooseLockGeneric is
+ // relaunched to only show options without fingerprint. In this case, we shouldn't
+ // ask the user to confirm the password again.
+ mPasswordConfirmed = getActivity().getIntent().getBooleanExtra(
+ PASSWORD_CONFIRMED, false);
+ }
if (savedInstanceState != null) {
mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
@@ -171,9 +191,8 @@
UserManager.get(getActivity()),
null,
getActivity().getIntent().getExtras()).getIdentifier();
- if (DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(
- getActivity().getIntent().getAction()) ||
- !mLockPatternUtils.isSeparateProfileChallengeAllowed(targetUser)) {
+ if (ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
+ || !mLockPatternUtils.isSeparateProfileChallengeAllowed(targetUser)) {
// Always use parent if explicitely requested or if profile challenge is not
// supported
Bundle arguments = getArguments();
@@ -183,8 +202,7 @@
mUserId = targetUser;
}
- if (DevicePolicyManager.ACTION_SET_NEW_PASSWORD
- .equals(getActivity().getIntent().getAction())
+ if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
&& Utils.isManagedProfile(UserManager.get(getActivity()), mUserId)
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
getActivity().setTitle(R.string.lock_settings_picker_title_profile);
@@ -219,6 +237,10 @@
protected void addHeaderView() {
if (mForFingerprint) {
setHeaderView(R.layout.choose_lock_generic_fingerprint_header);
+ if (mIsSetNewPassword) {
+ ((TextView) getHeaderView().findViewById(R.id.fingerprint_header_description))
+ .setText(R.string.fingerprint_unlock_title);
+ }
}
}
@@ -231,6 +253,12 @@
// unlock method to an insecure one
showFactoryResetProtectionWarningDialog(key);
return true;
+ } else if (KEY_SKIP_FINGERPRINT.equals(key)) {
+ Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
+ chooseLockGenericIntent.setAction(getIntent().getAction());
+ chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
+ startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
+ return true;
} else {
return setUnlockMethod(key);
}
@@ -305,6 +333,20 @@
getActivity().setResult(resultCode, data);
finish();
}
+ } else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
+ && resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
+ Intent intent = new Intent(getActivity(), FingerprintEnrollFindSensor.class);
+ if (data != null) {
+ intent.putExtras(data.getExtras());
+ }
+ startActivity(intent);
+ finish();
+ } else if (requestCode == SKIP_FINGERPRINT_REQUEST) {
+ if (resultCode != RESULT_CANCELED) {
+ getActivity().setResult(
+ resultCode == RESULT_FINISHED ? RESULT_OK : resultCode, data);
+ finish();
+ }
} else {
getActivity().setResult(Activity.RESULT_CANCELED);
finish();
@@ -352,20 +394,25 @@
// Used for testing purposes
findPreference(KEY_UNLOCK_SET_NONE).setViewId(R.id.lock_none);
+ findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
findPreference(KEY_UNLOCK_SET_PIN).setViewId(R.id.lock_pin);
findPreference(KEY_UNLOCK_SET_PASSWORD).setViewId(R.id.lock_password);
}
private void updatePreferenceText() {
if (mForFingerprint) {
- Preference pattern = findPreference(KEY_UNLOCK_SET_PATTERN);
- pattern.setTitle(R.string.fingerprint_unlock_set_unlock_pattern);
-
- Preference pin = findPreference(KEY_UNLOCK_SET_PIN);
- pin.setTitle(R.string.fingerprint_unlock_set_unlock_pin);
-
- Preference password = findPreference(KEY_UNLOCK_SET_PASSWORD);
- password.setTitle(R.string.fingerprint_unlock_set_unlock_password);
+ final String key[] = { KEY_UNLOCK_SET_PATTERN,
+ KEY_UNLOCK_SET_PIN,
+ KEY_UNLOCK_SET_PASSWORD };
+ final int res[] = { R.string.fingerprint_unlock_set_unlock_pattern,
+ R.string.fingerprint_unlock_set_unlock_pin,
+ R.string.fingerprint_unlock_set_unlock_password };
+ for (int i = 0; i < key.length; i++) {
+ Preference pref = findPreference(key[i]);
+ if (pref != null) { // can be removed by device admin
+ pref.setTitle(res[i]);
+ }
+ }
}
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
@@ -374,6 +421,10 @@
} else {
removePreference(KEY_UNLOCK_SET_MANAGED);
}
+
+ if (!(mForFingerprint && mIsSetNewPassword)) {
+ removePreference(KEY_SKIP_FINGERPRINT);
+ }
}
private void updateCurrentPreference() {
@@ -606,7 +657,10 @@
quality = upgradeQuality(quality);
Intent intent = getIntentForUnlockMethod(quality, disabled);
if (intent != null) {
- startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
+ startActivityForResult(intent,
+ mIsSetNewPassword && mHasChallenge
+ ? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
+ : CHOOSE_LOCK_REQUEST);
return;
}
@@ -614,8 +668,8 @@
mLockPatternUtils.setSeparateProfileChallengeEnabled(mUserId, true, mUserPassword);
mChooseLockSettingsHelper.utils().clearLock(mUserId);
mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
- removeAllFingerprintForUserAndFinish(mUserId);
getActivity().setResult(Activity.RESULT_OK);
+ removeAllFingerprintForUserAndFinish(mUserId);
} else {
removeAllFingerprintForUserAndFinish(mUserId);
}
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index b3826b7..86696bb 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -21,11 +21,12 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
-import android.inputmethodservice.KeyboardView;
+import android.graphics.drawable.InsetDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.os.UserHandle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
@@ -33,23 +34,34 @@
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
+import android.view.inputmethod.EditorInfo;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
-import com.android.internal.widget.PasswordEntryKeyboardHelper;
-import com.android.internal.widget.PasswordEntryKeyboardView;
import com.android.internal.widget.TextViewInputDisabler;
import com.android.settings.notification.RedactionInterstitial;
+import com.android.settings.password.PasswordRequirementAdapter;
+import com.android.setupwizardlib.GlifLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
public class ChooseLockPassword extends SettingsActivity {
public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
@@ -136,17 +148,15 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
- // TODO: Fix on phones
- // Disable IME on our window since we provide our own keyboard
- //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_choose_your_password_header);
setTitle(msg);
+ LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
+ layout.setFitsSystemWindows(false);
}
public static class ChooseLockPasswordFragment extends InstrumentedFragment
- implements OnClickListener, OnEditorActionListener, TextWatcher,
+ implements OnClickListener, OnEditorActionListener, TextWatcher,
SaveAndFinishWorker.Listener {
private static final String KEY_FIRST_PIN = "first_pin";
private static final String KEY_UI_STAGE = "ui_stage";
@@ -157,7 +167,7 @@
private String mChosenPassword;
private boolean mHasChallenge;
private long mChallenge;
- private TextView mPasswordEntry;
+ private EditText mPasswordEntry;
private TextViewInputDisabler mPasswordEntryInputDisabler;
private int mPasswordMinLength = LockPatternUtils.MIN_LOCK_PASSWORD_SIZE;
private int mPasswordMaxLength = 16;
@@ -167,35 +177,54 @@
private int mPasswordMinSymbols = 0;
private int mPasswordMinNumeric = 0;
private int mPasswordMinNonLetter = 0;
+ private int mPasswordMinLengthToFulfillAllPolicies = 0;
+ private int mUserId;
+ private boolean mHideDrawer = false;
+ /**
+ * Password requirements that we need to verify.
+ */
+ private int[] mPasswordRequirements;
+
private LockPatternUtils mLockPatternUtils;
private SaveAndFinishWorker mSaveAndFinishWorker;
private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private Stage mUiStage = Stage.Introduction;
+ private PasswordRequirementAdapter mPasswordRequirementAdapter;
private TextView mHeaderText;
private String mFirstPin;
- private KeyboardView mKeyboardView;
- private PasswordEntryKeyboardHelper mKeyboardHelper;
+ private RecyclerView mPasswordRestrictionView;
private boolean mIsAlphaMode;
private Button mCancelButton;
private Button mNextButton;
+
+ private TextChangedHandler mTextChangedHandler;
+
private static final int CONFIRM_EXISTING_REQUEST = 58;
static final int RESULT_FINISHED = RESULT_FIRST_USER;
- private static final long ERROR_MESSAGE_TIMEOUT = 3000;
- private static final int MSG_SHOW_ERROR = 1;
- private int mUserId;
- private boolean mHideDrawer = false;
+ private static final int MIN_LETTER_IN_PASSWORD = 0;
+ private static final int MIN_UPPER_LETTERS_IN_PASSWORD = 1;
+ private static final int MIN_LOWER_LETTERS_IN_PASSWORD = 2;
+ private static final int MIN_SYMBOLS_IN_PASSWORD = 3;
+ private static final int MIN_NUMBER_IN_PASSWORD = 4;
+ private static final int MIN_NON_LETTER_IN_PASSWORD = 5;
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_SHOW_ERROR) {
- updateStage((Stage) msg.obj);
- }
- }
- };
+ // Error code returned from {@link #validatePassword(String)}.
+ private static final int NO_ERROR = 0;
+ private static final int CONTAIN_INVALID_CHARACTERS = 1 << 0;
+ private static final int TOO_SHORT = 1 << 1;
+ private static final int TOO_LONG = 1 << 2;
+ private static final int CONTAIN_NON_DIGITS = 1 << 3;
+ private static final int CONTAIN_SEQUENTIAL_DIGITS = 1 << 4;
+ private static final int RECENTLY_USED = 1 << 5;
+ private static final int NOT_ENOUGH_LETTER = 1 << 6;
+ private static final int NOT_ENOUGH_UPPER_CASE = 1 << 7;
+ private static final int NOT_ENOUGH_LOWER_CASE = 1 << 8;
+ private static final int NOT_ENOUGH_DIGITS = 1 << 9;
+ private static final int NOT_ENOUGH_SYMBOLS = 1 << 10;
+ private static final int NOT_ENOUGH_NON_LETTER = 1 << 11;
/**
* Keep track internally of where the user is in choosing a pattern.
@@ -240,33 +269,7 @@
}
// Only take this argument into account if it belongs to the current profile.
mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
- mRequestedQuality = Math.max(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
- mRequestedQuality), mLockPatternUtils.getRequestedPasswordQuality(
- mUserId));
- mPasswordMinLength = Math.max(Math.max(
- LockPatternUtils.MIN_LOCK_PASSWORD_SIZE,
- intent.getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength)),
- mLockPatternUtils.getRequestedMinimumPasswordLength(mUserId));
- mPasswordMaxLength = intent.getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
- mPasswordMinLetters = Math.max(intent.getIntExtra(PASSWORD_MIN_LETTERS_KEY,
- mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters(
- mUserId));
- mPasswordMinUpperCase = Math.max(intent.getIntExtra(PASSWORD_MIN_UPPERCASE_KEY,
- mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase(
- mUserId));
- mPasswordMinLowerCase = Math.max(intent.getIntExtra(PASSWORD_MIN_LOWERCASE_KEY,
- mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase(
- mUserId));
- mPasswordMinNumeric = Math.max(intent.getIntExtra(PASSWORD_MIN_NUMERIC_KEY,
- mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric(
- mUserId));
- mPasswordMinSymbols = Math.max(intent.getIntExtra(PASSWORD_MIN_SYMBOLS_KEY,
- mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols(
- mUserId));
- mPasswordMinNonLetter = Math.max(intent.getIntExtra(PASSWORD_MIN_NONLETTER_KEY,
- mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter(
- mUserId));
-
+ processPasswordRequirements(intent);
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
@@ -282,6 +285,7 @@
w.start(mChooseLockSettingsHelper.utils(), required,
false, 0, current, current, mRequestedQuality, mUserId);
}
+ mTextChangedHandler = new TextChangedHandler();
}
@Override
@@ -302,21 +306,18 @@
mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
|| DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality
|| DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality;
- mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
- mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
+
+ setupPasswordRequirementsView(view);
+
+ mPasswordRestrictionView.setLayoutManager(new LinearLayoutManager(getActivity()));
+ mPasswordEntry = (EditText) view.findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.addTextChangedListener(this);
+ mPasswordEntry.requestFocus();
mPasswordEntryInputDisabler = new TextViewInputDisabler(mPasswordEntry);
final Activity activity = getActivity();
- mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
- mKeyboardView, mPasswordEntry);
- mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
- PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
- : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
-
mHeaderText = (TextView) view.findViewById(R.id.headerText);
- mKeyboardView.requestFocus();
int currentType = mPasswordEntry.getInputType();
mPasswordEntry.setInputType(mIsAlphaMode ? currentType
@@ -353,15 +354,88 @@
mSaveAndFinishWorker = (SaveAndFinishWorker) getFragmentManager().findFragmentByTag(
FRAGMENT_TAG_SAVE_AND_FINISH);
}
+
+ // Workaround to show one password requirement below EditText when IME is shown.
+ // By adding an inset to the edit text background, we make the EditText occupy more
+ // vertical space, and the keyboard will then avoid hiding it. We have also set
+ // negative margin in the layout below in order to have them show in the correct
+ // position.
+ final int visibleVerticalSpaceBelowPassword =
+ getResources().getDimensionPixelOffset(
+ R.dimen.visible_vertical_space_below_password);
+ InsetDrawable drawable =
+ new InsetDrawable(
+ mPasswordEntry.getBackground(), 0, 0, 0, visibleVerticalSpaceBelowPassword);
+ mPasswordEntry.setBackgroundDrawable(drawable);
+ LinearLayout bottomContainer = (LinearLayout) view.findViewById(R.id.bottom_container);
+ LinearLayout.LayoutParams bottomContainerLp =
+ (LinearLayout.LayoutParams) bottomContainer.getLayoutParams();
+ bottomContainerLp.setMargins(0, -visibleVerticalSpaceBelowPassword, 0, 0);
+
if (activity instanceof SettingsActivity) {
final SettingsActivity sa = (SettingsActivity) activity;
int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header
: R.string.lockpassword_choose_your_pin_header;
CharSequence title = getText(id);
sa.setTitle(title);
+ ((GlifLayout) view).setHeaderText(title);
}
}
+ private void setupPasswordRequirementsView(View view) {
+ // Construct passwordRequirements and requirementDescriptions.
+ List<Integer> passwordRequirements = new ArrayList<>();
+ List<String> requirementDescriptions = new ArrayList<>();
+ if (mPasswordMinUpperCase > 0) {
+ passwordRequirements.add(MIN_UPPER_LETTERS_IN_PASSWORD);
+ requirementDescriptions.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase,
+ mPasswordMinUpperCase));
+ }
+ if (mPasswordMinLowerCase > 0) {
+ passwordRequirements.add(MIN_LOWER_LETTERS_IN_PASSWORD);
+ requirementDescriptions.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase,
+ mPasswordMinLowerCase));
+ }
+ if (mPasswordMinLetters > 0) {
+ if (mPasswordMinLetters > mPasswordMinUpperCase + mPasswordMinLowerCase) {
+ passwordRequirements.add(MIN_LETTER_IN_PASSWORD);
+ requirementDescriptions.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters,
+ mPasswordMinLetters));
+ }
+ }
+ if (mPasswordMinNumeric > 0) {
+ passwordRequirements.add(MIN_NUMBER_IN_PASSWORD);
+ requirementDescriptions.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric,
+ mPasswordMinNumeric));
+ }
+ if (mPasswordMinSymbols > 0) {
+ passwordRequirements.add(MIN_SYMBOLS_IN_PASSWORD);
+ requirementDescriptions.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols,
+ mPasswordMinSymbols));
+ }
+ if (mPasswordMinNonLetter > 0) {
+ if (mPasswordMinNonLetter > mPasswordMinNumeric + mPasswordMinSymbols) {
+ passwordRequirements.add(MIN_NON_LETTER_IN_PASSWORD);
+ requirementDescriptions.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter,
+
+ mPasswordMinNonLetter));
+ }
+ }
+ // Convert list to array.
+ mPasswordRequirements = passwordRequirements.stream().mapToInt(i -> i).toArray();
+ mPasswordRestrictionView =
+ (RecyclerView) view.findViewById(R.id.password_requirements_view);
+ mPasswordRestrictionView.setLayoutManager(new LinearLayoutManager(getActivity()));
+ mPasswordRequirementAdapter = new PasswordRequirementAdapter();
+ mPasswordRestrictionView.setAdapter(mPasswordRequirementAdapter);
+ }
+
@Override
protected int getMetricsCategory() {
return MetricsEvent.CHOOSE_LOCK_PASSWORD;
@@ -374,17 +448,15 @@
if (mSaveAndFinishWorker != null) {
mSaveAndFinishWorker.setListener(this);
} else {
- mKeyboardView.requestFocus();
+ mPasswordEntry.requestFocus();
}
}
@Override
public void onPause() {
- mHandler.removeMessages(MSG_SHOW_ERROR);
if (mSaveAndFinishWorker != null) {
mSaveAndFinishWorker.setListener(null);
}
-
super.onPause();
}
@@ -430,21 +502,98 @@
}
/**
- * Validates PIN and returns a message to display if PIN fails test.
- * @param password the raw password the user typed in
- * @return error message to show to user or null if password is OK
+ * Read the requirements from {@link DevicePolicyManager} and intent and aggregate them.
+ *
+ * @param intent the incoming intent
*/
- private String validatePassword(String password) {
+ private void processPasswordRequirements(Intent intent) {
+ final int dpmPasswordQuality = mLockPatternUtils.getRequestedPasswordQuality(mUserId);
+ mRequestedQuality = Math.max(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
+ mRequestedQuality), dpmPasswordQuality);
+ mPasswordMinLength = Math.max(Math.max(
+ LockPatternUtils.MIN_LOCK_PASSWORD_SIZE,
+ intent.getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength)),
+ mLockPatternUtils.getRequestedMinimumPasswordLength(mUserId));
+ mPasswordMaxLength = intent.getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
+ mPasswordMinLetters = Math.max(intent.getIntExtra(PASSWORD_MIN_LETTERS_KEY,
+ mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters(
+ mUserId));
+ mPasswordMinUpperCase = Math.max(intent.getIntExtra(PASSWORD_MIN_UPPERCASE_KEY,
+ mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase(
+ mUserId));
+ mPasswordMinLowerCase = Math.max(intent.getIntExtra(PASSWORD_MIN_LOWERCASE_KEY,
+ mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase(
+ mUserId));
+ mPasswordMinNumeric = Math.max(intent.getIntExtra(PASSWORD_MIN_NUMERIC_KEY,
+ mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric(
+ mUserId));
+ mPasswordMinSymbols = Math.max(intent.getIntExtra(PASSWORD_MIN_SYMBOLS_KEY,
+ mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols(
+ mUserId));
+ mPasswordMinNonLetter = Math.max(intent.getIntExtra(PASSWORD_MIN_NONLETTER_KEY,
+ mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter(
+ mUserId));
+
+ // Modify the value based on dpm policy.
+ switch (dpmPasswordQuality) {
+ case PASSWORD_QUALITY_ALPHABETIC:
+ if (mPasswordMinLetters == 0) {
+ mPasswordMinLetters = 1;
+ }
+ break;
+ case PASSWORD_QUALITY_ALPHANUMERIC:
+ if (mPasswordMinLetters == 0) {
+ mPasswordMinLetters = 1;
+ }
+ if (mPasswordMinNumeric == 0) {
+ mPasswordMinNumeric = 1;
+ }
+ break;
+ case PASSWORD_QUALITY_COMPLEX:
+ // Reserve all the requirements.
+ break;
+ default:
+ mPasswordMinNumeric = 0;
+ mPasswordMinLetters = 0;
+ mPasswordMinUpperCase = 0;
+ mPasswordMinLowerCase = 0;
+ mPasswordMinSymbols = 0;
+ mPasswordMinNonLetter = 0;
+ }
+ mPasswordMinLengthToFulfillAllPolicies = getMinLengthToFulfillAllPolicies();
+ }
+
+ /**
+ * Validates PIN and returns the validation result.
+ *
+ * @param password the raw password the user typed in
+ * @return the validation result.
+ */
+ private int validatePassword(String password) {
+ int errorCode = NO_ERROR;
+
if (password.length() < mPasswordMinLength) {
- return getString(mIsAlphaMode ?
- R.string.lockpassword_password_too_short
- : R.string.lockpassword_pin_too_short, mPasswordMinLength);
+ if (mPasswordMinLength > mPasswordMinLengthToFulfillAllPolicies) {
+ errorCode |= TOO_SHORT;
+ }
+ } else if (password.length() > mPasswordMaxLength) {
+ errorCode |= TOO_LONG;
+ } else {
+ // The length requirements are fulfilled.
+ if (mRequestedQuality == PASSWORD_QUALITY_NUMERIC_COMPLEX) {
+ // Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
+ final int sequence = LockPatternUtils.maxLengthSequence(password);
+ if (sequence > LockPatternUtils.MAX_ALLOWED_SEQUENCE) {
+ errorCode |= CONTAIN_SEQUENTIAL_DIGITS;
+ }
+ }
+ // Is the password recently used?
+ if (mLockPatternUtils.checkPasswordHistory(password, mUserId)) {
+ errorCode |= RECENTLY_USED;
+ }
}
- if (password.length() > mPasswordMaxLength) {
- return getString(mIsAlphaMode ?
- R.string.lockpassword_password_too_long
- : R.string.lockpassword_pin_too_long, mPasswordMaxLength + 1);
- }
+
+ // Count different types of character.
int letters = 0;
int numbers = 0;
int lowercase = 0;
@@ -455,7 +604,8 @@
char c = password.charAt(i);
// allow non control Latin-1 characters only
if (c < 32 || c > 127) {
- return getString(R.string.lockpassword_illegal_character);
+ errorCode |= CONTAIN_INVALID_CHARACTERS;
+ continue;
}
if (c >= '0' && c <= '9') {
numbers++;
@@ -471,63 +621,53 @@
nonletter++;
}
}
- if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
- || DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality) {
+
+ // Ensure no non-digits if we are requesting numbers. This shouldn't be possible unless
+ // user finds some way to bring up soft keyboard.
+ if (mRequestedQuality == PASSWORD_QUALITY_NUMERIC
+ || mRequestedQuality == PASSWORD_QUALITY_NUMERIC_COMPLEX) {
if (letters > 0 || symbols > 0) {
- // This shouldn't be possible unless user finds some way to bring up
- // soft keyboard
- return getString(R.string.lockpassword_pin_contains_non_digits);
+ errorCode |= CONTAIN_NON_DIGITS;
}
- // Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
- final int sequence = LockPatternUtils.maxLengthSequence(password);
- if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality
- && sequence > LockPatternUtils.MAX_ALLOWED_SEQUENCE) {
- return getString(R.string.lockpassword_pin_no_sequential_digits);
- }
- } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) {
- if (letters < mPasswordMinLetters) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters),
- mPasswordMinLetters);
- } else if (numbers < mPasswordMinNumeric) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric),
- mPasswordMinNumeric);
- } else if (lowercase < mPasswordMinLowerCase) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase),
- mPasswordMinLowerCase);
- } else if (uppercase < mPasswordMinUpperCase) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase),
- mPasswordMinUpperCase);
- } else if (symbols < mPasswordMinSymbols) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols),
- mPasswordMinSymbols);
- } else if (nonletter < mPasswordMinNonLetter) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter),
- mPasswordMinNonLetter);
- }
- } else {
- final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
- == mRequestedQuality;
- final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
- == mRequestedQuality;
- if ((alphabetic || alphanumeric) && letters == 0) {
- return getString(R.string.lockpassword_password_requires_alpha);
- }
- if (alphanumeric && numbers == 0) {
- return getString(R.string.lockpassword_password_requires_digit);
- }
- }
- if(mLockPatternUtils.checkPasswordHistory(password, mUserId)) {
- return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used
- : R.string.lockpassword_pin_recently_used);
}
- return null;
+ // Check the requirements one by one.
+ for (int i = 0; i < mPasswordRequirements.length; i++) {
+ int passwordRestriction = mPasswordRequirements[i];
+ switch (passwordRestriction) {
+ case MIN_LETTER_IN_PASSWORD:
+ if (letters < mPasswordMinLetters) {
+ errorCode |= NOT_ENOUGH_LETTER;
+ }
+ break;
+ case MIN_UPPER_LETTERS_IN_PASSWORD:
+ if (uppercase < mPasswordMinUpperCase) {
+ errorCode |= NOT_ENOUGH_UPPER_CASE;
+ }
+ break;
+ case MIN_LOWER_LETTERS_IN_PASSWORD:
+ if (lowercase < mPasswordMinLowerCase) {
+ errorCode |= NOT_ENOUGH_LOWER_CASE;
+ }
+ break;
+ case MIN_SYMBOLS_IN_PASSWORD:
+ if (symbols < mPasswordMinSymbols) {
+ errorCode |= NOT_ENOUGH_SYMBOLS;
+ }
+ break;
+ case MIN_NUMBER_IN_PASSWORD:
+ if (numbers < mPasswordMinNumeric) {
+ errorCode |= NOT_ENOUGH_DIGITS;
+ }
+ break;
+ case MIN_NON_LETTER_IN_PASSWORD:
+ if (nonletter < mPasswordMinNonLetter) {
+ errorCode |= NOT_ENOUGH_NON_LETTER;
+ }
+ break;
+ }
+ }
+ return errorCode;
}
public void handleNext() {
@@ -536,10 +676,8 @@
if (TextUtils.isEmpty(mChosenPassword)) {
return;
}
- String errorMsg = null;
if (mUiStage == Stage.Introduction) {
- errorMsg = validatePassword(mChosenPassword);
- if (errorMsg == null) {
+ if (validatePassword(mChosenPassword) == NO_ERROR) {
mFirstPin = mChosenPassword;
mPasswordEntry.setText("");
updateStage(Stage.NeedToConfirm);
@@ -555,9 +693,6 @@
updateStage(Stage.ConfirmWrong);
}
}
- if (errorMsg != null) {
- showError(errorMsg, mUiStage);
- }
}
protected void setNextEnabled(boolean enabled) {
@@ -580,14 +715,6 @@
}
}
- private void showError(String msg, final Stage next) {
- mHeaderText.setText(msg);
- mHeaderText.announceForAccessibility(mHeaderText.getText());
- Message mesg = mHandler.obtainMessage(MSG_SHOW_ERROR, next);
- mHandler.removeMessages(MSG_SHOW_ERROR);
- mHandler.sendMessageDelayed(mesg, ERROR_MESSAGE_TIMEOUT);
- }
-
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter or "done" key
if (actionId == EditorInfo.IME_NULL
@@ -600,6 +727,76 @@
}
/**
+ * @param errorCode error code returned from {@link #validatePassword(String)}.
+ * @return an array of messages describing the error, important messages come first.
+ */
+ private String[] convertErrorCodeToMessages(int errorCode) {
+ List<String> messages = new ArrayList<>();
+ if ((errorCode & CONTAIN_INVALID_CHARACTERS) > 0) {
+ messages.add(getString(R.string.lockpassword_illegal_character));
+ }
+ if ((errorCode & CONTAIN_NON_DIGITS) > 0) {
+ messages.add(getString(R.string.lockpassword_pin_contains_non_digits));
+ }
+ if ((errorCode & NOT_ENOUGH_UPPER_CASE) > 0) {
+ messages.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase,
+ mPasswordMinUpperCase));
+ }
+ if ((errorCode & NOT_ENOUGH_LOWER_CASE) > 0) {
+ messages.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase,
+ mPasswordMinLowerCase));
+ }
+ if ((errorCode & NOT_ENOUGH_LETTER) > 0) {
+ messages.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters,
+ mPasswordMinLetters));
+ }
+ if ((errorCode & NOT_ENOUGH_DIGITS) > 0) {
+ messages.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric,
+ mPasswordMinNumeric));
+ }
+ if ((errorCode & NOT_ENOUGH_SYMBOLS) > 0) {
+ messages.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols,
+ mPasswordMinSymbols));
+ }
+ if ((errorCode & NOT_ENOUGH_NON_LETTER) > 0) {
+ messages.add(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter,
+ mPasswordMinNonLetter));
+ }
+ if ((errorCode & TOO_SHORT) > 0) {
+ messages.add(getString(mIsAlphaMode ?
+ R.string.lockpassword_password_too_short
+ : R.string.lockpassword_pin_too_short, mPasswordMinLength));
+ }
+ if ((errorCode & TOO_LONG) > 0) {
+ messages.add(getString(mIsAlphaMode ?
+ R.string.lockpassword_password_too_long
+ : R.string.lockpassword_pin_too_long, mPasswordMaxLength + 1));
+ }
+ if ((errorCode & CONTAIN_SEQUENTIAL_DIGITS) > 0) {
+ messages.add(getString(R.string.lockpassword_pin_no_sequential_digits));
+ }
+ if ((errorCode & RECENTLY_USED) > 0) {
+ messages.add(getString((mIsAlphaMode) ? R.string.lockpassword_password_recently_used
+ : R.string.lockpassword_pin_recently_used));
+ }
+ return messages.toArray(new String[0]);
+ }
+
+ private int getMinLengthToFulfillAllPolicies() {
+ final int minLengthForLetters = Math.max(mPasswordMinLetters,
+ mPasswordMinUpperCase + mPasswordMinLowerCase);
+ final int minLengthForNonLetters = Math.max(mPasswordMinNonLetter,
+ mPasswordMinSymbols + mPasswordMinNumeric);
+ return minLengthForLetters + minLengthForNonLetters;
+ }
+
+ /**
* Update the hint based on current Stage and length of password entry
*/
private void updateUi() {
@@ -607,35 +804,40 @@
String password = mPasswordEntry.getText().toString();
final int length = password.length();
if (mUiStage == Stage.Introduction) {
- if (length < mPasswordMinLength) {
- String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
- : R.string.lockpassword_pin_too_short, mPasswordMinLength);
- mHeaderText.setText(msg);
- setNextEnabled(false);
- } else {
- String error = validatePassword(password);
- if (error != null) {
- mHeaderText.setText(error);
- setNextEnabled(false);
- } else {
- mHeaderText.setText(null);
- setNextEnabled(true);
- }
- }
+ mPasswordRestrictionView.setVisibility(View.VISIBLE);
+ final int errorCode = validatePassword(password);
+ String[] messages = convertErrorCodeToMessages(errorCode);
+ // Update the fulfillment of requirements.
+ mPasswordRequirementAdapter.setRequirements(messages);
+ // Enable/Disable the next button accordingly.
+ setNextEnabled(errorCode == NO_ERROR);
} else {
- mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
+ // Hide password requirement view when we are just asking user to confirm the pw.
+ mPasswordRestrictionView.setVisibility(View.GONE);
+ setHeaderText(getString(
+ mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint));
setNextEnabled(canInput && length > 0);
}
setNextText(mUiStage.buttonText);
mPasswordEntryInputDisabler.setInputEnabled(canInput);
}
+ private void setHeaderText(String text) {
+ // Only set the text if it is different than the existing one to avoid announcing again.
+ if (!TextUtils.isEmpty(mHeaderText.getText())
+ && mHeaderText.getText().toString().equals(text)) {
+ return;
+ }
+ mHeaderText.setText(text);
+ }
+
public void afterTextChanged(Editable s) {
// Changing the text while error displayed resets to NeedToConfirm state
if (mUiStage == Stage.ConfirmWrong) {
mUiStage = Stage.NeedToConfirm;
}
- updateUi();
+ // Schedule the UI update.
+ mTextChangedHandler.notifyAfterTextChanged();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -681,6 +883,30 @@
}
getActivity().finish();
}
+
+ class TextChangedHandler extends Handler {
+ private static final int ON_TEXT_CHANGED = 1;
+ private static final int DELAY_IN_MILLISECOND = 100;
+
+ /**
+ * With the introduction of delay, we batch processing the text changed event to reduce
+ * unnecessary UI updates.
+ */
+ private void notifyAfterTextChanged() {
+ removeMessages(ON_TEXT_CHANGED);
+ sendEmptyMessageDelayed(ON_TEXT_CHANGED, DELAY_IN_MILLISECOND);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (getActivity() == null) {
+ return;
+ }
+ if (msg.what == ON_TEXT_CHANGED) {
+ updateUi();
+ }
+ }
+ }
}
private static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 2e9f767..59fa2c7 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -21,12 +21,12 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.os.UserHandle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
@@ -37,6 +37,7 @@
import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockPatternView.DisplayMode;
import com.android.settings.notification.RedactionInterstitial;
+import com.android.setupwizardlib.GlifLayout;
import com.google.android.collect.Lists;
import java.util.ArrayList;
@@ -113,6 +114,8 @@
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_choose_your_pattern_header);
setTitle(msg);
+ LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
+ layout.setFitsSystemWindows(false);
}
@Override
@@ -391,7 +394,10 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- return inflater.inflate(R.layout.choose_lock_pattern, container, false);
+ final GlifLayout layout = (GlifLayout) inflater.inflate(
+ R.layout.choose_lock_pattern, container, false);
+ layout.setHeaderText(getActivity().getTitle());
+ return layout;
}
@Override
diff --git a/src/com/android/settings/ColorModePreference.java b/src/com/android/settings/ColorModePreference.java
index 94b6499..74abf5d 100644
--- a/src/com/android/settings/ColorModePreference.java
+++ b/src/com/android/settings/ColorModePreference.java
@@ -24,7 +24,6 @@
import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
import android.view.Display;
-import android.view.Display.ColorTransform;
import java.util.ArrayList;
@@ -34,14 +33,14 @@
private Display mDisplay;
private int mCurrentIndex;
- private ArrayList<ColorTransformDescription> mDescriptions;
+ private ArrayList<ColorModeDescription> mDescriptions;
public ColorModePreference(Context context, AttributeSet attrs) {
super(context, attrs);
mDisplayManager = getContext().getSystemService(DisplayManager.class);
}
- public int getTransformsCount() {
+ public int getColorModeCount() {
return mDescriptions.size();
}
@@ -77,43 +76,24 @@
mDescriptions = new ArrayList<>();
Resources resources = getContext().getResources();
- int[] transforms = resources.getIntArray(
- com.android.internal.R.array.config_colorTransforms);
+ int[] colorModes = resources.getIntArray(R.array.color_mode_ids);
String[] titles = resources.getStringArray(R.array.color_mode_names);
String[] descriptions = resources.getStringArray(R.array.color_mode_descriptions);
- // Map the resource information describing color transforms.
- for (int i = 0; i < transforms.length; i++) {
- if (transforms[i] != -1 && i != 1 /* Skip Natural for now. */) {
- ColorTransformDescription desc = new ColorTransformDescription();
- desc.colorTransform = transforms[i];
+ // Map the resource information describing color modes.
+ for (int i = 0; i < colorModes.length; i++) {
+ if (colorModes[i] != -1 && i != 1 /* Skip Natural for now. */) {
+ ColorModeDescription desc = new ColorModeDescription();
+ desc.colorMode = colorModes[i];
desc.title = titles[i];
desc.summary = descriptions[i];
mDescriptions.add(desc);
}
}
- // Match up a ColorTransform to every description.
- ColorTransform[] supportedColorTransforms = mDisplay.getSupportedColorTransforms();
- for (int i = 0; i < supportedColorTransforms.length; i++) {
- for (int j = 0; j < mDescriptions.size(); j++) {
- if (mDescriptions.get(j).colorTransform
- == supportedColorTransforms[i].getColorTransform()
- && mDescriptions.get(j).transform == null) {
- mDescriptions.get(j).transform = supportedColorTransforms[i];
- break;
- }
- }
- }
- // Remove any extras that don't have a transform for some reason.
- for (int i = 0; i < mDescriptions.size(); i++) {
- if (mDescriptions.get(i).transform == null) {
- mDescriptions.remove(i--);
- }
- }
- ColorTransform currentTransform = mDisplay.getColorTransform();
+ int currentColorMode = mDisplay.getColorMode();
mCurrentIndex = -1;
for (int i = 0; i < mDescriptions.size(); i++) {
- if (mDescriptions.get(i).colorTransform == currentTransform.getColorTransform()) {
+ if (mDescriptions.get(i).colorMode == currentColorMode) {
mCurrentIndex = i;
break;
}
@@ -125,19 +105,18 @@
protected boolean persistBoolean(boolean value) {
// Right now this is a switch, so we only support two modes.
if (mDescriptions.size() == 2) {
- ColorTransformDescription desc = mDescriptions.get(value ? 1 : 0);
+ ColorModeDescription desc = mDescriptions.get(value ? 1 : 0);
- mDisplay.requestColorTransform(desc.transform);
+ mDisplay.requestColorMode(desc.colorMode);
mCurrentIndex = mDescriptions.indexOf(desc);
}
return true;
}
- private static class ColorTransformDescription {
- private int colorTransform;
+ private static class ColorModeDescription {
+ private int colorMode;
private String title;
private String summary;
- private ColorTransform transform;
}
}
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index ef19c2a..dd76b79 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -142,8 +142,16 @@
@Override
public void onResume() {
super.onResume();
+ refreshLockScreen();
+ }
+
+ protected void refreshLockScreen() {
if (mAllowFpAuthentication) {
mFingerprintHelper.startListening();
+ } else {
+ if (mFingerprintHelper.isListening()) {
+ mFingerprintHelper.stopListening();
+ }
}
if (isProfileChallenge()) {
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
@@ -168,7 +176,7 @@
@Override
public void onPause() {
super.onPause();
- if (mAllowFpAuthentication) {
+ if (mFingerprintHelper.isListening()) {
mFingerprintHelper.stopListening();
}
}
@@ -181,7 +189,6 @@
(TrustManager) getActivity().getSystemService(Context.TRUST_SERVICE);
trustManager.setDeviceLockedForUser(mEffectiveUserId, false);
authenticationSucceeded();
- authenticationSucceeded();
checkForPendingIntent();
}
}
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 4797012..01e9902 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -320,11 +320,15 @@
return;
}
- mPasswordEntryInputDisabler.setInputEnabled(false);
-
final String pin = mPasswordEntry.getText().toString();
+ if (TextUtils.isEmpty(pin)) {
+ return;
+ }
+
+ mPasswordEntryInputDisabler.setInputEnabled(false);
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
+
Intent intent = new Intent();
if (verifyChallenge) {
if (isInternalActivity()) {
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index dd8640c..34dad58 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -461,7 +461,8 @@
private void startCheckPattern(final List<LockPatternView.Cell> pattern,
final Intent intent) {
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
- mCredentialCheckResultTracker.setResult(false, intent, 0, mEffectiveUserId);
+ // Pattern size is less than the minimum, do not count it as an fail attempt.
+ onPatternChecked(false, intent, 0, mEffectiveUserId, false /* newResult */);
return;
}
@@ -498,6 +499,7 @@
checkForPendingIntent();
} else {
if (timeoutMs > 0) {
+ refreshLockScreen();
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
effectiveUserId, timeoutMs);
handleAttemptLockout(deadline);
diff --git a/src/com/android/settings/CustomListPreference.java b/src/com/android/settings/CustomListPreference.java
index ae83013..e7c7600 100644
--- a/src/com/android/settings/CustomListPreference.java
+++ b/src/com/android/settings/CustomListPreference.java
@@ -18,8 +18,13 @@
import android.app.AlertDialog;
import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
import android.os.Bundle;
import android.support.v14.preference.ListPreferenceDialogFragment;
import android.support.v7.preference.ListPreference;
@@ -50,6 +55,18 @@
return true;
}
+ /**
+ * Called when a user is about to choose the given value, to determine if we
+ * should show a confirmation dialog.
+ *
+ * @param value the value the user is about to choose
+ * @return the message to show in a confirmation dialog, or {@code null} to
+ * not request confirmation
+ */
+ protected CharSequence getConfirmationMessage(String value) {
+ return null;
+ }
+
protected void onDialogStateRestored(Dialog dialog, Bundle savedInstanceState) {
}
@@ -82,9 +99,7 @@
builder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- CustomListPreferenceDialogFragment.this.onClick(dialog,
- DialogInterface.BUTTON_POSITIVE);
- dialog.dismiss();
+ onItemChosen();
}
});
}
@@ -115,18 +130,11 @@
protected DialogInterface.OnClickListener getOnItemClickListener() {
return new DialogInterface.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int which) {
setClickedDialogEntryIndex(which);
-
-
if (getCustomizablePreference().isAutoClosePreference()) {
- /*
- * Clicking on an item simulates the positive button
- * click, and dismisses the dialog.
- */
- CustomListPreferenceDialogFragment.this.onClick(dialog,
- DialogInterface.BUTTON_POSITIVE);
- dialog.dismiss();
+ onItemChosen();
}
}
};
@@ -136,17 +144,74 @@
mClickedDialogEntryIndex = which;
}
+ private String getValue() {
+ final ListPreference preference = getCustomizablePreference();
+ if (mClickedDialogEntryIndex >= 0 && preference.getEntryValues() != null) {
+ return preference.getEntryValues()[mClickedDialogEntryIndex].toString();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Called when user has made a concrete item choice, but we might need
+ * to make a quick detour to confirm that choice with a second dialog.
+ */
+ protected void onItemChosen() {
+ final CharSequence message = getCustomizablePreference()
+ .getConfirmationMessage(getValue());
+ if (message != null) {
+ final Fragment f = new ConfirmDialogFragment();
+ final Bundle args = new Bundle();
+ args.putCharSequence(Intent.EXTRA_TEXT, message);
+ f.setArguments(args);
+ f.setTargetFragment(CustomListPreferenceDialogFragment.this, 0);
+ final FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.add(f, getTag() + "-Confirm");
+ ft.commitAllowingStateLoss();
+ } else {
+ onItemConfirmed();
+ }
+ }
+
+ /**
+ * Called when user has made a concrete item choice and we've fully
+ * confirmed they want to move forward (if we took a detour above).
+ */
+ protected void onItemConfirmed() {
+ onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
+ getDialog().dismiss();
+ }
+
@Override
public void onDialogClosed(boolean positiveResult) {
getCustomizablePreference().onDialogClosed(positiveResult);
final ListPreference preference = getCustomizablePreference();
- if (positiveResult && mClickedDialogEntryIndex >= 0 &&
- preference.getEntryValues() != null) {
- String value = preference.getEntryValues()[mClickedDialogEntryIndex].toString();
+ final String value = getValue();
+ if (positiveResult && value != null) {
if (preference.callChangeListener(value)) {
preference.setValue(value);
}
}
}
}
+
+ public static class ConfirmDialogFragment extends DialogFragment {
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(getArguments().getCharSequence(Intent.EXTRA_TEXT))
+ .setPositiveButton(android.R.string.ok, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final Fragment f = getTargetFragment();
+ if (f != null) {
+ ((CustomListPreferenceDialogFragment) f).onItemConfirmed();
+ }
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null)
+ .create();
+ }
+ }
}
diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index 3ed3e82..94589f0 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -28,6 +28,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
+import android.os.UserManager;
+import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.support.v14.preference.SwitchPreference;
@@ -38,17 +40,21 @@
import android.widget.TimePicker;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.dashboard.SummaryLoader;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.datetime.ZoneGetter;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
+import java.util.List;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
public class DateTimeSettings extends SettingsPreferenceFragment
- implements OnTimeSetListener, OnDateSetListener, OnPreferenceChangeListener {
+ implements OnTimeSetListener, OnDateSetListener, OnPreferenceChangeListener, Indexable {
private static final String HOURS_12 = "12";
private static final String HOURS_24 = "24";
@@ -380,4 +386,26 @@
return new SummaryProvider(activity, summaryLoader);
}
};
+
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new DateTimeSearchIndexProvider();
+
+ private static class DateTimeSearchIndexProvider extends BaseSearchIndexProvider {
+
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ List<SearchIndexableResource> result = new ArrayList<>();
+ // Remove data/time settings from search in demo mode
+ if (UserManager.isDeviceInDemoMode(context)) {
+ return result;
+ }
+
+ SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.date_time_prefs;
+ result.add(sir);
+
+ return result;
+ }
+ }
}
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 714f7d0..a77f7b1 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -53,22 +53,23 @@
import android.os.StrictMode;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.service.persistentdata.PersistentDataBlockManager;
import android.os.UserManager;
import android.os.storage.IMountService;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
+import android.service.persistentdata.PersistentDataBlockManager;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
-import android.view.ThreadedRenderer;
import android.view.IWindowManager;
import android.view.LayoutInflater;
+import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
@@ -143,7 +144,6 @@
private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
private static final String SIMULATE_COLOR_SPACE = "simulate_color_space";
private static final String USB_AUDIO_KEY = "usb_audio";
- private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
private static final String FORCE_HARDWARE_UI_KEY = "force_hw_ui";
private static final String FORCE_MSAA_KEY = "force_msaa";
private static final String TRACK_FRAME_TIME_KEY = "track_frame_time";
@@ -233,6 +233,7 @@
private UserManager mUm;
private WifiManager mWifiManager;
private PersistentDataBlockManager mOemUnlockManager;
+ private TelephonyManager mTelephonyManager;
private SwitchBar mSwitchBar;
private boolean mLastEnabledState;
@@ -246,7 +247,7 @@
private SwitchPreference mBugreportInPower;
private RestrictedSwitchPreference mKeepScreenOn;
private SwitchPreference mBtHciSnoopLog;
- private SwitchPreference mEnableOemUnlock;
+ private RestrictedSwitchPreference mEnableOemUnlock;
private SwitchPreference mDebugViewAttributes;
private SwitchPreference mForceAllowOnExternal;
@@ -272,7 +273,6 @@
private SwitchPreference mShowTouches;
private SwitchPreference mShowScreenUpdates;
private SwitchPreference mDisableOverlays;
- private SwitchPreference mShowCpuUsage;
private SwitchPreference mForceHardwareUi;
private SwitchPreference mForceMsaa;
private SwitchPreference mShowHwScreenUpdates;
@@ -345,6 +345,7 @@
IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
mOemUnlockManager = (PersistentDataBlockManager)getActivity()
.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+ mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
mUm = (UserManager) getSystemService(Context.USER_SERVICE);
@@ -382,7 +383,7 @@
mBugreportInPower = findAndInitSwitchPref(BUGREPORT_IN_POWER_KEY);
mKeepScreenOn = (RestrictedSwitchPreference) findAndInitSwitchPref(KEEP_SCREEN_ON);
mBtHciSnoopLog = findAndInitSwitchPref(BT_HCI_SNOOP_LOG);
- mEnableOemUnlock = findAndInitSwitchPref(ENABLE_OEM_UNLOCK);
+ mEnableOemUnlock = (RestrictedSwitchPreference) findAndInitSwitchPref(ENABLE_OEM_UNLOCK);
if (!showEnableOemUnlockPreference()) {
removePreference(mEnableOemUnlock);
mEnableOemUnlock = null;
@@ -420,7 +421,6 @@
mShowTouches = findAndInitSwitchPref(SHOW_TOUCHES_KEY);
mShowScreenUpdates = findAndInitSwitchPref(SHOW_SCREEN_UPDATES_KEY);
mDisableOverlays = findAndInitSwitchPref(DISABLE_OVERLAYS_KEY);
- mShowCpuUsage = findAndInitSwitchPref(SHOW_CPU_USAGE_KEY);
mForceHardwareUi = findAndInitSwitchPref(FORCE_HARDWARE_UI_KEY);
mForceMsaa = findAndInitSwitchPref(FORCE_MSAA_KEY);
mTrackFrameTime = addListPreference(TRACK_FRAME_TIME_KEY);
@@ -500,7 +500,7 @@
mColorModePreference = (ColorModePreference) findPreference(KEY_COLOR_MODE);
mColorModePreference.updateCurrentAndSupported();
- if (mColorModePreference.getTransformsCount() < 2) {
+ if (mColorModePreference.getColorModeCount() < 2) {
removePreference(KEY_COLOR_MODE);
mColorModePreference = null;
}
@@ -681,9 +681,6 @@
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
updateSwitchPreference(mBtHciSnoopLog, Settings.Secure.getInt(cr,
Settings.Secure.BLUETOOTH_HCI_LOG, 0) != 0);
- if (mEnableOemUnlock != null) {
- updateSwitchPreference(mEnableOemUnlock, Utils.isOemUnlockEnabled(getActivity()));
- }
updateSwitchPreference(mDebugViewAttributes, Settings.Global.getInt(cr,
Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0);
updateSwitchPreference(mForceAllowOnExternal, Settings.Global.getInt(cr,
@@ -696,7 +693,6 @@
updatePointerLocationOptions();
updateShowTouchesOptions();
updateFlingerOptions();
- updateCpuUsageOptions();
updateHardwareUiOptions();
updateMsaaOptions();
updateTrackFrameTimeOptions();
@@ -1030,17 +1026,24 @@
}
private boolean enableOemUnlockPreference() {
- int flashLockState = PersistentDataBlockManager.FLASH_LOCK_UNKNOWN;
- if (mOemUnlockManager != null) {
- flashLockState = mOemUnlockManager.getFlashLockState();
- }
-
- return flashLockState != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED;
+ return !isBootloaderUnlocked() && isOemUnlockAllowed();
}
private void updateOemUnlockOptions() {
if (mEnableOemUnlock != null) {
+ updateSwitchPreference(mEnableOemUnlock, Utils.isOemUnlockEnabled(getActivity()));
+ updateOemUnlockSettingDescription();
+ // Showing mEnableOemUnlock preference as device has persistent data block.
+ mEnableOemUnlock.setDisabledByAdmin(null);
mEnableOemUnlock.setEnabled(enableOemUnlockPreference());
+ if (mEnableOemUnlock.isEnabled()) {
+ // Check restriction, disable mEnableOemUnlock and apply policy transparency.
+ mEnableOemUnlock.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
+ }
+ if (mEnableOemUnlock.isEnabled()) {
+ // Check restriction, disable mEnableOemUnlock and apply policy transparency.
+ mEnableOemUnlock.checkRestrictionAndSetDisabled(UserManager.DISALLOW_OEM_UNLOCK);
+ }
}
}
@@ -1712,25 +1715,6 @@
}
}
- private void updateCpuUsageOptions() {
- updateSwitchPreference(mShowCpuUsage,
- Settings.Global.getInt(getActivity().getContentResolver(),
- Settings.Global.SHOW_PROCESSES, 0) != 0);
- }
-
- private void writeCpuUsageOptions() {
- boolean value = mShowCpuUsage.isChecked();
- Settings.Global.putInt(getActivity().getContentResolver(),
- Settings.Global.SHOW_PROCESSES, value ? 1 : 0);
- Intent service = (new Intent())
- .setClassName("com.android.systemui", "com.android.systemui.LoadAverageService");
- if (value) {
- getActivity().startService(service);
- } else {
- getActivity().stopService(service);
- }
- }
-
private void writeImmediatelyDestroyActivitiesOptions() {
try {
ActivityManagerNative.getDefault().setAlwaysFinish(
@@ -2019,8 +2003,6 @@
writeShowUpdatesOption();
} else if (preference == mDisableOverlays) {
writeDisableOverlaysOption();
- } else if (preference == mShowCpuUsage) {
- writeCpuUsageOptions();
} else if (preference == mImmediatelyDestroyActivities) {
writeImmediatelyDestroyActivitiesOptions();
} else if (preference == mShowAllANRs) {
@@ -2062,7 +2044,7 @@
} else if (preference == mWebViewMultiprocess) {
writeWebViewMultiprocessOptions();
} else if (SHORTCUT_MANAGER_RESET_KEY.equals(preference.getKey())) {
- confirmResetShortcutManagerThrottling();
+ resetShortcutManagerThrottling();
} else {
return super.onPreferenceTreeClick(preference);
}
@@ -2319,29 +2301,70 @@
}
};
- private void confirmResetShortcutManagerThrottling() {
+ private void resetShortcutManagerThrottling() {
final IShortcutService service = IShortcutService.Stub.asInterface(
ServiceManager.getService(Context.SHORTCUT_SERVICE));
-
- DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- try {
- service.resetThrottling();
- } catch (RemoteException e) {
- }
- }
+ if (service != null) {
+ try {
+ service.resetThrottling();
+ Toast.makeText(getActivity(), R.string.reset_shortcut_manager_throttling_complete,
+ Toast.LENGTH_SHORT).show();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to reset rate limiting", e);
}
- };
+ }
+ }
- new AlertDialog.Builder(getActivity())
- .setTitle(R.string.confirm_reset_shortcut_manager_throttling_title)
- .setMessage(R.string.confirm_reset_shortcut_manager_throttling_message)
- .setPositiveButton(R.string.okay, onClickListener)
- .setNegativeButton(android.R.string.cancel, null)
- .create()
- .show();
+ private void updateOemUnlockSettingDescription() {
+ if (mEnableOemUnlock != null) {
+ int oemUnlockSummary = R.string.oem_unlock_enable_summary;
+ if (isBootloaderUnlocked()) {
+ oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_bootloader_unlocked;
+ } else if (isSimLockedDevice()) {
+ oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_sim_locked_device;
+ } else if (!isOemUnlockAllowed()) {
+ // If the device isn't SIM-locked but OEM unlock is disabled by the system via the
+ // user restriction, this means either some other carrier restriction is in place or
+ // the device hasn't been able to confirm which restrictions (SIM-lock or otherwise)
+ // apply.
+ oemUnlockSummary =
+ R.string.oem_unlock_enable_disabled_summary_connectivity_or_locked;
+ }
+ mEnableOemUnlock.setSummary(getString(oemUnlockSummary));
+ }
+ }
+ /** Returns {@code true} if the device is SIM-locked. Otherwise, returns {@code false}. */
+ private boolean isSimLockedDevice() {
+ int phoneCount = mTelephonyManager.getPhoneCount();
+ for (int i = 0; i < phoneCount; i++) {
+ if (mTelephonyManager.getAllowedCarriers(i).size() > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if the bootloader has been unlocked. Otherwise, returns {code false}.
+ */
+ private boolean isBootloaderUnlocked() {
+ int flashLockState = PersistentDataBlockManager.FLASH_LOCK_UNKNOWN;
+ if (mOemUnlockManager != null) {
+ flashLockState = mOemUnlockManager.getFlashLockState();
+ }
+
+ return flashLockState == PersistentDataBlockManager.FLASH_LOCK_UNLOCKED;
+ }
+
+ /**
+ * Returns {@code true} if OEM unlock is disallowed by user restriction
+ * {@link UserManager#DISALLOW_FACTORY_RESET} or {@link UserManager#DISALLOW_OEM_UNLOCK}.
+ * Otherwise, returns {@code false}.
+ */
+ private boolean isOemUnlockAllowed() {
+ UserHandle userHandle = UserHandle.of(UserHandle.myUserId());
+ return !(mUm.hasBaseUserRestriction(UserManager.DISALLOW_OEM_UNLOCK, userHandle)
+ || mUm.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, userHandle));
}
}
diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java
index ff7334b..dd8064f 100644
--- a/src/com/android/settings/DeviceInfoSettings.java
+++ b/src/com/android/settings/DeviceInfoSettings.java
@@ -175,14 +175,12 @@
// Remove manual entry if none present.
removePreferenceIfBoolFalse(KEY_MANUAL, R.bool.config_show_manual);
- // Remove regulatory information if none present.
- final Intent intent = new Intent(Settings.ACTION_SHOW_REGULATORY_INFO);
- if (getPackageManager().queryIntentActivities(intent, 0).isEmpty()) {
- Preference pref = findPreference(KEY_REGULATORY_INFO);
- if (pref != null) {
- getPreferenceScreen().removePreference(pref);
- }
- }
+ // Remove regulatory labels if no activity present to handle intent.
+ removePreferenceIfActivityMissing(
+ KEY_REGULATORY_INFO, Settings.ACTION_SHOW_REGULATORY_INFO);
+
+ removePreferenceIfActivityMissing(
+ "safety_info", "android.settings.SHOW_SAFETY_AND_REGULATORY_INFO");
}
@Override
@@ -285,7 +283,7 @@
CarrierConfigManager configManager =
(CarrierConfigManager) getSystemService(Context.CARRIER_CONFIG_SERVICE);
PersistableBundle b = configManager.getConfig();
- if (b.getBoolean(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)) {
+ if (b != null && b.getBoolean(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)) {
ciActionOnSysUpdate(b);
}
}
@@ -327,6 +325,16 @@
}
}
+ private void removePreferenceIfActivityMissing(String preferenceKey, String action) {
+ final Intent intent = new Intent(action);
+ if (getPackageManager().queryIntentActivities(intent, 0).isEmpty()) {
+ Preference pref = findPreference(preferenceKey);
+ if (pref != null) {
+ getPreferenceScreen().removePreference(pref);
+ }
+ }
+ }
+
private void removePreferenceIfBoolFalse(String preference, int resId) {
if (!getResources().getBoolean(resId)) {
Preference pref = findPreference(preference);
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 8e389a9..f7b9443 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -44,6 +44,7 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.app.NightDisplayController;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.view.RotationPolicy;
@@ -57,7 +58,6 @@
import java.util.ArrayList;
import java.util.List;
-import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED;
import static android.provider.Settings.Secure.CAMERA_GESTURE_DISABLED;
import static android.provider.Settings.Secure.DOUBLE_TAP_TO_WAKE;
import static android.provider.Settings.Secure.DOZE_ENABLED;
@@ -84,10 +84,9 @@
private static final String KEY_TAP_TO_WAKE = "tap_to_wake";
private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness";
private static final String KEY_AUTO_ROTATE = "auto_rotate";
+ private static final String KEY_NIGHT_DISPLAY = "night_display";
private static final String KEY_NIGHT_MODE = "night_mode";
private static final String KEY_CAMERA_GESTURE = "camera_gesture";
- private static final String KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE
- = "camera_double_tap_power_gesture";
private static final String KEY_WALLPAPER = "wallpaper";
private static final String KEY_VR_DISPLAY_PREF = "vr_display_pref";
@@ -101,7 +100,6 @@
private SwitchPreference mTapToWakePreference;
private SwitchPreference mAutoBrightnessPreference;
private SwitchPreference mCameraGesturePreference;
- private SwitchPreference mCameraDoubleTapPowerGesturePreference;
@Override
protected int getMetricsCategory() {
@@ -134,6 +132,10 @@
removePreference(KEY_AUTO_BRIGHTNESS);
}
+ if (!NightDisplayController.isAvailable(activity)) {
+ removePreference(KEY_NIGHT_DISPLAY);
+ }
+
if (isLiftToWakeAvailable(activity)) {
mLiftToWakePreference = (SwitchPreference) findPreference(KEY_LIFT_TO_WAKE);
mLiftToWakePreference.setOnPreferenceChangeListener(this);
@@ -162,14 +164,6 @@
removePreference(KEY_CAMERA_GESTURE);
}
- if (isCameraDoubleTapPowerGestureAvailable(getResources())) {
- mCameraDoubleTapPowerGesturePreference
- = (SwitchPreference) findPreference(KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE);
- mCameraDoubleTapPowerGesturePreference.setOnPreferenceChangeListener(this);
- } else {
- removePreference(KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE);
- }
-
if (RotationPolicy.isRotationLockToggleVisible(activity)) {
DropDownPreference rotatePreference =
(DropDownPreference) findPreference(KEY_AUTO_ROTATE);
@@ -288,11 +282,6 @@
!SystemProperties.getBoolean("gesture.disable_camera_launch", false);
}
- private static boolean isCameraDoubleTapPowerGestureAvailable(Resources res) {
- return res.getBoolean(
- com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
- }
-
private static boolean isVrDisplayModeAvailable(Context context) {
PackageManager pm = context.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
@@ -365,30 +354,23 @@
mLiftToWakePreference.setChecked(value != 0);
}
- // Update doze if it is available.
- if (mDozePreference != null) {
- int value = Settings.Secure.getInt(getContentResolver(), DOZE_ENABLED, 1);
- mDozePreference.setChecked(value != 0);
- }
-
// Update tap to wake if it is available.
if (mTapToWakePreference != null) {
int value = Settings.Secure.getInt(getContentResolver(), DOUBLE_TAP_TO_WAKE, 0);
mTapToWakePreference.setChecked(value != 0);
}
+ // Update doze if it is available.
+ if (mDozePreference != null) {
+ int value = Settings.Secure.getInt(getContentResolver(), DOZE_ENABLED, 1);
+ mDozePreference.setChecked(value != 0);
+ }
+
// Update camera gesture #1 if it is available.
if (mCameraGesturePreference != null) {
int value = Settings.Secure.getInt(getContentResolver(), CAMERA_GESTURE_DISABLED, 0);
mCameraGesturePreference.setChecked(value == 0);
}
-
- // Update camera gesture #2 if it is available.
- if (mCameraDoubleTapPowerGesturePreference != null) {
- int value = Settings.Secure.getInt(
- getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
- mCameraDoubleTapPowerGesturePreference.setChecked(value == 0);
- }
}
private void updateScreenSaverSummary() {
@@ -444,11 +426,6 @@
Settings.Secure.putInt(getContentResolver(), CAMERA_GESTURE_DISABLED,
value ? 0 : 1 /* Backwards because setting is for disabling */);
}
- if (preference == mCameraDoubleTapPowerGesturePreference) {
- boolean value = (Boolean) objValue;
- Settings.Secure.putInt(getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
- value ? 0 : 1 /* Backwards because setting is for disabling */);
- }
if (preference == mNightModePreference) {
try {
final int value = Integer.parseInt((String) objValue);
@@ -463,6 +440,14 @@
}
@Override
+ public boolean onPreferenceTreeClick(Preference preference) {
+ if (preference == mDozePreference) {
+ MetricsLogger.action(getActivity(), MetricsEvent.ACTION_AMBIENT_DISPLAY);
+ }
+ return super.onPreferenceTreeClick(preference);
+ }
+
+ @Override
protected int getHelpResource() {
return R.string.help_uri_display;
}
@@ -539,6 +524,9 @@
if (!isAutomaticBrightnessAvailable(context.getResources())) {
result.add(KEY_AUTO_BRIGHTNESS);
}
+ if (!NightDisplayController.isAvailable(context)) {
+ result.add(KEY_NIGHT_DISPLAY);
+ }
if (!isLiftToWakeAvailable(context)) {
result.add(KEY_LIFT_TO_WAKE);
}
@@ -554,9 +542,6 @@
if (!isCameraGestureAvailable(context.getResources())) {
result.add(KEY_CAMERA_GESTURE);
}
- if (!isCameraDoubleTapPowerGestureAvailable(context.getResources())) {
- result.add(KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE);
- }
if (!isVrDisplayModeAvailable(context)) {
result.add(KEY_VR_DISPLAY_PREF);
}
diff --git a/src/com/android/settings/EncryptionInterstitial.java b/src/com/android/settings/EncryptionInterstitial.java
index e9e2a7c..d34b456 100644
--- a/src/com/android/settings/EncryptionInterstitial.java
+++ b/src/com/android/settings/EncryptionInterstitial.java
@@ -23,19 +23,26 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.preference.Preference;
+import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.utils.SettingsDividerItemDecoration;
+import com.android.setupwizardlib.GlifPreferenceLayout;
import java.util.List;
public class EncryptionInterstitial extends SettingsActivity {
- private final static String TAG = EncryptionInterstitial.class.getSimpleName();
+ private static final String TAG = EncryptionInterstitial.class.getSimpleName();
protected static final String EXTRA_PASSWORD_QUALITY = "extra_password_quality";
protected static final String EXTRA_UNLOCK_METHOD_INTENT = "extra_unlock_method_intent";
@@ -63,6 +70,13 @@
.putExtra(EXTRA_UNLOCK_METHOD_INTENT, unlockMethodIntent);
}
+ @Override
+ protected void onCreate(Bundle savedInstance) {
+ super.onCreate(savedInstance);
+ LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
+ layout.setFitsSystemWindows(false);
+ }
+
public static class EncryptionInterstitialFragment extends SettingsPreferenceFragment
implements DialogInterface.OnClickListener {
@@ -126,7 +140,8 @@
disableId = R.string.encrypt_dont_require_password;
break;
}
- TextView message = createHeaderView();
+ TextView message = (TextView) LayoutInflater.from(getActivity()).inflate(
+ R.layout.encryption_interstitial_header, null, false);
message.setText(msgId);
setHeaderView(message);
@@ -138,10 +153,25 @@
EXTRA_REQUIRE_PASSWORD, true));
}
- protected TextView createHeaderView() {
- TextView message = (TextView) LayoutInflater.from(getActivity()).inflate(
- R.layout.encryption_interstitial_header, null, false);
- return message;
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
+ layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext()));
+
+ layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
+ layout.setHeaderText(getActivity().getTitle());
+
+ // Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
+ // PreferenceFragment.
+ setDivider(null);
+ }
+
+ @Override
+ public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+ Bundle savedInstanceState) {
+ GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
+ return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
protected void startLockIntent() {
diff --git a/src/com/android/settings/FallbackHome.java b/src/com/android/settings/FallbackHome.java
index deb01a1..f2e8152 100644
--- a/src/com/android/settings/FallbackHome.java
+++ b/src/com/android/settings/FallbackHome.java
@@ -17,6 +17,7 @@
package com.android.settings;
import android.app.Activity;
+import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -25,14 +26,37 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.PowerManager;
+import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.animation.AnimationUtils;
import java.util.Objects;
public class FallbackHome extends Activity {
private static final String TAG = "FallbackHome";
+ private static final int PROGRESS_TIMEOUT = 2000;
+
+ private boolean mProvisioned;
+
+ private final Runnable mProgressTimeoutRunnable = () -> {
+ View v = getLayoutInflater().inflate(
+ R.layout.fallback_home_finishing_boot, null /* root */);
+ setContentView(v);
+ v.setAlpha(0f);
+ v.animate()
+ .alpha(1f)
+ .setDuration(500)
+ .setInterpolator(AnimationUtils.loadInterpolator(
+ this, android.R.interpolator.fast_out_slow_in))
+ .start();
+ getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
+ };
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -40,9 +64,15 @@
// Set ourselves totally black before the device is provisioned so that
// we don't flash the wallpaper before SUW
- if (Settings.Global.getInt(getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
- setTheme(android.R.style.Theme_Black_NoTitleBar_Fullscreen);
+ mProvisioned = Settings.Global.getInt(getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+ if (!mProvisioned) {
+ setTheme(R.style.FallbackHome_SetupWizard);
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ } else {
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
@@ -50,6 +80,19 @@
}
@Override
+ protected void onResume() {
+ super.onResume();
+ if (mProvisioned) {
+ mHandler.postDelayed(mProgressTimeoutRunnable, PROGRESS_TIMEOUT);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mHandler.removeCallbacks(mProgressTimeoutRunnable);
+ }
+
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
@@ -72,6 +115,8 @@
mHandler.sendEmptyMessageDelayed(0, 500);
} else {
Log.d(TAG, "User unlocked and real home found; let's go!");
+ getSystemService(PowerManager.class).userActivity(
+ SystemClock.uptimeMillis(), false);
finish();
}
}
diff --git a/src/com/android/settings/HelpTrampoline.java b/src/com/android/settings/HelpTrampoline.java
new file mode 100644
index 0000000..7eb28a0
--- /dev/null
+++ b/src/com/android/settings/HelpTrampoline.java
@@ -0,0 +1,51 @@
+/*
+ * 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.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.settingslib.HelpUtils;
+
+public class HelpTrampoline extends Activity {
+ private static final String TAG = "HelpTrampoline";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ try {
+ final String name = getIntent().getStringExtra(Intent.EXTRA_TEXT);
+ final int id = getResources().getIdentifier(name, "string", getPackageName());
+ final String value = getResources().getString(id);
+
+ final Intent intent = HelpUtils.getHelpIntent(this, value, null);
+ if (intent != null) {
+ startActivity(intent);
+ }
+
+ } catch (Resources.NotFoundException | ActivityNotFoundException e) {
+ Log.w(TAG, "Failed to resolve help", e);
+ }
+
+ finish();
+ }
+}
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index 0e3528a..8bab2cf 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -16,11 +16,11 @@
package com.android.settings;
-import com.android.internal.logging.MetricsLogger;
-
import android.os.Bundle;
import android.support.v14.preference.PreferenceFragment;
+import com.android.internal.logging.MetricsLogger;
+
/**
* Instrumented fragment that logs visibility state.
*/
diff --git a/src/com/android/settings/PreviewPagerAdapter.java b/src/com/android/settings/PreviewPagerAdapter.java
index 7e4ebf3..5001518 100644
--- a/src/com/android/settings/PreviewPagerAdapter.java
+++ b/src/com/android/settings/PreviewPagerAdapter.java
@@ -23,6 +23,8 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
+import android.view.ViewStub.OnInflateListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -53,10 +55,13 @@
private int mAnimationCounter;
+ private boolean[][] mViewStubInflated;
+
public PreviewPagerAdapter(Context context, boolean isLayoutRtl,
int[] previewSampleResIds, Configuration[] configurations) {
mIsLayoutRtl = isLayoutRtl;
mPreviewFrames = new FrameLayout[previewSampleResIds.length];
+ mViewStubInflated = new boolean[previewSampleResIds.length][configurations.length];
for (int i = 0; i < previewSampleResIds.length; ++i) {
int p = mIsLayoutRtl ? previewSampleResIds.length - 1 - i : i;
@@ -65,18 +70,25 @@
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
- for (Configuration configuration : configurations) {
+ for (int j = 0; j < configurations.length; ++j) {
// Create a new configuration for the specified value. It won't
// have any theme set, so manually apply the current theme.
- final Context configContext = context.createConfigurationContext(configuration);
+ final Context configContext = context.createConfigurationContext(configurations[j]);
configContext.setTheme(context.getThemeResId());
final LayoutInflater configInflater = LayoutInflater.from(configContext);
- final View sampleView = configInflater.inflate(previewSampleResIds[i],
- mPreviewFrames[p], false);
- sampleView.setAlpha(0);
- sampleView.setVisibility(View.INVISIBLE);
- mPreviewFrames[p].addView(sampleView);
+ final ViewStub sampleViewStub = new ViewStub(configContext);
+ sampleViewStub.setLayoutResource(previewSampleResIds[i]);
+ final int fi = i, fj = j;
+ sampleViewStub.setOnInflateListener(new OnInflateListener() {
+ @Override
+ public void onInflate(ViewStub stub, View inflated) {
+ inflated.setVisibility(stub.getVisibility());
+ mViewStubInflated[fi][fj] = true;
+ }
+ });
+
+ mPreviewFrames[p].addView(sampleViewStub);
}
}
}
@@ -110,44 +122,71 @@
mAnimationEndAction = action;
}
- void setPreviewLayer(int newIndex, int currentIndex, int currentItem, boolean animate) {
+ void setPreviewLayer(int newLayerIndex, int currentLayerIndex, int currentFrameIndex,
+ final boolean animate) {
for (FrameLayout previewFrame : mPreviewFrames) {
- if (currentIndex >= 0) {
- final View lastLayer = previewFrame.getChildAt(currentIndex);
- if (animate && previewFrame == mPreviewFrames[currentItem]) {
- lastLayer.animate()
- .alpha(0)
- .setInterpolator(FADE_OUT_INTERPOLATOR)
- .setDuration(CROSS_FADE_DURATION_MS)
- .setListener(new PreviewFrameAnimatorListener())
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- lastLayer.setVisibility(View.INVISIBLE);
- }
- });
- } else {
- lastLayer.setAlpha(0);
- lastLayer.setVisibility(View.INVISIBLE);
+ if (currentLayerIndex >= 0) {
+ final View lastLayer = previewFrame.getChildAt(currentLayerIndex);
+ if (mViewStubInflated[currentFrameIndex][currentLayerIndex]) {
+ // Explicitly set to INVISIBLE only when the stub has
+ // already been inflated.
+ if (previewFrame == mPreviewFrames[currentFrameIndex]) {
+ setVisibility(lastLayer, View.INVISIBLE, animate);
+ } else {
+ setVisibility(lastLayer, View.INVISIBLE, false);
+ }
}
}
- final View nextLayer = previewFrame.getChildAt(newIndex);
- if (animate && previewFrame == mPreviewFrames[currentItem]) {
- nextLayer.animate()
- .alpha(1)
- .setInterpolator(FADE_IN_INTERPOLATOR)
- .setDuration(CROSS_FADE_DURATION_MS)
- .setListener(new PreviewFrameAnimatorListener())
- .withStartAction(new Runnable() {
- @Override
- public void run() {
- nextLayer.setVisibility(View.VISIBLE);
- }
- });
+ // Set next layer visible, as well as inflate necessary views.
+ View nextLayer = previewFrame.getChildAt(newLayerIndex);
+ if (previewFrame == mPreviewFrames[currentFrameIndex]) {
+ // Inflate immediately if the stub has not yet been inflated.
+ if (!mViewStubInflated[currentFrameIndex][newLayerIndex]) {
+ nextLayer = ((ViewStub) nextLayer).inflate();
+ nextLayer.setAlpha(0.0f);
+ }
+ setVisibility(nextLayer, View.VISIBLE, animate);
} else {
- nextLayer.setVisibility(View.VISIBLE);
- nextLayer.setAlpha(1);
+ setVisibility(nextLayer, View.VISIBLE, false);
+ }
+ }
+ }
+
+ private void setVisibility(final View view, final int visibility, boolean animate) {
+ final float alpha = (visibility == View.VISIBLE ? 1.0f : 0.0f);
+ if (!animate) {
+ view.setAlpha(alpha);
+ view.setVisibility(visibility);
+ } else {
+ final Interpolator interpolator = (visibility == View.VISIBLE ? FADE_IN_INTERPOLATOR
+ : FADE_OUT_INTERPOLATOR);
+ if (visibility == View.VISIBLE) {
+ // Fade in animation.
+ view.animate()
+ .alpha(alpha)
+ .setInterpolator(FADE_IN_INTERPOLATOR)
+ .setDuration(CROSS_FADE_DURATION_MS)
+ .setListener(new PreviewFrameAnimatorListener())
+ .withStartAction(new Runnable() {
+ @Override
+ public void run() {
+ view.setVisibility(visibility);
+ }
+ });
+ } else {
+ // Fade out animation.
+ view.animate()
+ .alpha(alpha)
+ .setInterpolator(FADE_OUT_INTERPOLATOR)
+ .setDuration(CROSS_FADE_DURATION_MS)
+ .setListener(new PreviewFrameAnimatorListener())
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ view.setVisibility(visibility);
+ }
+ });
}
}
}
diff --git a/src/com/android/settings/PreviewSeekBarPreferenceFragment.java b/src/com/android/settings/PreviewSeekBarPreferenceFragment.java
index 9d4a09e..544999a 100644
--- a/src/com/android/settings/PreviewSeekBarPreferenceFragment.java
+++ b/src/com/android/settings/PreviewSeekBarPreferenceFragment.java
@@ -21,7 +21,6 @@
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
-import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -34,8 +33,6 @@
import com.android.settings.widget.DotsPageIndicator;
import com.android.settings.widget.LabeledSeekBar;
-import java.util.Locale;
-
/**
* Preference fragment shows a preview and a seek bar to adjust a specific settings.
*/
@@ -147,7 +144,7 @@
seekBar.setEnabled(false);
}
- final Context context = getPrefContext();
+ final Context context = getContext();
final Configuration origConfig = context.getResources().getConfiguration();
final boolean isLayoutRtl = origConfig.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
Configuration[] configurations = new Configuration[mEntries.length];
diff --git a/src/com/android/settings/PrivacySettings.java b/src/com/android/settings/PrivacySettings.java
index 7732837..396e5fa 100644
--- a/src/com/android/settings/PrivacySettings.java
+++ b/src/com/android/settings/PrivacySettings.java
@@ -61,7 +61,6 @@
private static final String CONFIGURE_ACCOUNT = "configure_account";
private static final String DATA_MANAGEMENT = "data_management";
private static final String BACKUP_INACTIVE = "backup_inactive";
- private static final String NETWORK_RESET = "network_reset";
private static final String FACTORY_RESET = "factory_reset";
private static final String TAG = "PrivacySettings";
private IBackupManager mBackupManager;
@@ -219,51 +218,6 @@
return R.string.help_url_backup_reset;
}
- private static class SummaryProvider implements SummaryLoader.SummaryProvider {
-
- private final Context mContext;
- private final SummaryLoader mSummaryLoader;
-
- public SummaryProvider(Context context, SummaryLoader summaryLoader) {
- mContext = context;
- mSummaryLoader = summaryLoader;
- }
-
- @Override
- public void setListening(boolean listening) {
- if (listening) {
- IBackupManager backupManager = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- try {
- boolean backupEnabled = backupManager.isBackupEnabled();
- if (backupEnabled) {
- String transport = backupManager.getCurrentTransport();
- String configSummary = backupManager.getDestinationString(transport);
- if (configSummary != null) {
- mSummaryLoader.setSummary(this, configSummary);
- } else {
- mSummaryLoader.setSummary(this, mContext.getString(
- R.string.backup_configure_account_default_summary));
- }
- } else {
- mSummaryLoader.setSummary(this, mContext.getString(
- R.string.backup_disabled));
- }
- } catch (RemoteException e) {
- }
- }
- }
- }
-
- public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
- = new SummaryLoader.SummaryProviderFactory() {
- @Override
- public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
- SummaryLoader summaryLoader) {
- return new SummaryProvider(activity, summaryLoader);
- }
- };
-
/**
* For Search.
*/
@@ -331,9 +285,5 @@
UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId())) {
nonVisibleKeys.add(FACTORY_RESET);
}
- if (RestrictedLockUtils.hasBaseUserRestriction(context,
- UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
- nonVisibleKeys.add(NETWORK_RESET);
- }
}
}
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 031a1ae..54ff4db 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -29,7 +29,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.os.SystemProperties;
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
import android.telephony.CellInfoGsm;
@@ -118,6 +117,16 @@
private static final int CELL_INFO_LIST_RATE_DISABLED = Integer.MAX_VALUE;
private static final int CELL_INFO_LIST_RATE_MAX = 0;
+
+ private static final int IMS_VOLTE_PROVISIONED_CONFIG_ID =
+ ImsConfig.ConfigConstants.VLT_SETTING_ENABLED;
+
+ private static final int IMS_VT_PROVISIONED_CONFIG_ID =
+ ImsConfig.ConfigConstants.LVC_SETTING_ENABLED;
+
+ private static final int IMS_WFC_PROVISIONED_CONFIG_ID =
+ ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED;
+
//Values in must match mCellInfoRefreshRates
private static final String[] mCellInfoRefreshRateLabels = {
"Disabled",
@@ -184,7 +193,9 @@
private Button updateSmscButton;
private Button refreshSmscButton;
private Button oemInfoButton;
- private Switch imsVoLteProvisionedSwitch;
+ private Switch imsVolteProvisionedSwitch;
+ private Switch imsVtProvisionedSwitch;
+ private Switch imsWfcProvisionedSwitch;
private Spinner preferredNetworkType;
private Spinner cellInfoRefreshRateSpinner;
@@ -270,7 +281,7 @@
updateServiceState(serviceState);
updateRadioPowerState();
updateNetworkType();
- updateImsVoLteProvisionedState();
+ updateImsProvisionedState();
}
};
@@ -331,6 +342,11 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ if (!android.os.Process.myUserHandle().isSystem()) {
+ Log.e(TAG, "Not run from system user, don't do anything.");
+ finish();
+ return;
+ }
setContentView(R.layout.radio_info);
@@ -382,7 +398,9 @@
cellInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cellInfoRefreshRateSpinner.setAdapter(cellInfoAdapter);
- imsVoLteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch);
+ imsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch);
+ imsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch);
+ imsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
radioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
@@ -425,7 +443,7 @@
updateDataState();
updateDataStats2();
updateRadioPowerState();
- updateImsVoLteProvisionedState();
+ updateImsProvisionedState();
updateProperties();
updateDnsCheckState();
updateNetworkType();
@@ -447,7 +465,9 @@
preferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
radioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
- imsVoLteProvisionedSwitch.setOnCheckedChangeListener(mImsVoLteCheckedChangeListener);
+ imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
+ imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
+ imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
mTelephonyManager.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE
@@ -1099,6 +1119,37 @@
radioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
}
+ void setImsVolteProvisionedState( boolean state ) {
+ Log.d(TAG, "setImsVolteProvisioned state: " + ((state)? "on":"off"));
+ setImsConfigProvisionedState( IMS_VOLTE_PROVISIONED_CONFIG_ID, state );
+ }
+
+ void setImsVtProvisionedState( boolean state ) {
+ Log.d(TAG, "setImsVtProvisioned() state: " + ((state)? "on":"off"));
+ setImsConfigProvisionedState( IMS_VT_PROVISIONED_CONFIG_ID, state );
+ }
+
+ void setImsWfcProvisionedState( boolean state ) {
+ Log.d(TAG, "setImsWfcProvisioned() state: " + ((state)? "on":"off"));
+ setImsConfigProvisionedState( IMS_WFC_PROVISIONED_CONFIG_ID, state );
+ }
+
+ void setImsConfigProvisionedState( int configItem, boolean state ) {
+ if (phone != null && mImsManager != null) {
+ QueuedWork.singleThreadExecutor().submit(new Runnable() {
+ public void run() {
+ try {
+ mImsManager.getConfigInterface().setProvisionedValue(
+ configItem,
+ state? 1 : 0);
+ } catch (ImsException e) {
+ Log.e(TAG, "setImsConfigProvisioned() exception:", e);
+ }
+ }
+ });
+ }
+ }
+
OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -1107,25 +1158,7 @@
}
};
- void setImsVoLteProvisionedState( boolean state ) {
- log(String.format("toggle VoLTE provisioned: %s", ((state) ? "on":"off")));
-
- if (phone != null && mImsManager != null) {
- QueuedWork.singleThreadExecutor().submit(new Runnable() {
- public void run() {
- try {
- mImsManager.getConfigInterface().setProvisionedValue(
- ImsConfig.ConfigConstants.VLT_SETTING_ENABLED,
- state? 1 : 0);
- } catch (ImsException e) {
- Log.e(TAG, "setImsVoLteProvisioned() exception:", e);
- }
- }
- });
- }
- }
-
- private boolean isImsVoLteProvisioned() {
+ private boolean isImsVolteProvisioned() {
if (phone != null && mImsManager != null) {
return mImsManager.isVolteEnabledByPlatform(phone.getContext())
&& mImsManager.isVolteProvisionedOnDevice(phone.getContext());
@@ -1133,20 +1166,58 @@
return false;
}
- OnCheckedChangeListener mImsVoLteCheckedChangeListener = new OnCheckedChangeListener() {
+ OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- setImsVoLteProvisionedState(isChecked);
+ setImsVolteProvisionedState(isChecked);
}
};
- private void updateImsVoLteProvisionedState() {
- log("updateImsVoLteProvisionedState isImsVoLteProvisioned()=" + isImsVoLteProvisioned());
+ private boolean isImsVtProvisioned() {
+ if (phone != null && mImsManager != null) {
+ return mImsManager.isVtEnabledByPlatform(phone.getContext())
+ && mImsManager.isVtProvisionedOnDevice(phone.getContext());
+ }
+ return false;
+ }
+
+ OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ setImsVtProvisionedState(isChecked);
+ }
+ };
+
+ private boolean isImsWfcProvisioned() {
+ if (phone != null && mImsManager != null) {
+ return mImsManager.isWfcEnabledByPlatform(phone.getContext())
+ && mImsManager.isWfcProvisionedOnDevice(phone.getContext());
+ }
+ return false;
+ }
+
+ OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ setImsWfcProvisionedState(isChecked);
+ }
+ };
+
+ private void updateImsProvisionedState() {
+ log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned());
//delightful hack to prevent on-checked-changed calls from
//actually forcing the ims provisioning to its transient/current value.
- imsVoLteProvisionedSwitch.setOnCheckedChangeListener(null);
- imsVoLteProvisionedSwitch.setChecked(isImsVoLteProvisioned());
- imsVoLteProvisionedSwitch.setOnCheckedChangeListener(mImsVoLteCheckedChangeListener);
+ imsVolteProvisionedSwitch.setOnCheckedChangeListener(null);
+ imsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned());
+ imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
+
+ imsVtProvisionedSwitch.setOnCheckedChangeListener(null);
+ imsVtProvisionedSwitch.setChecked(isImsVtProvisioned());
+ imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
+
+ imsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
+ imsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned());
+ imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
}
OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
diff --git a/src/com/android/settings/RegulatoryInfoDisplayActivity.java b/src/com/android/settings/RegulatoryInfoDisplayActivity.java
index c674f13..fd94b67 100644
--- a/src/com/android/settings/RegulatoryInfoDisplayActivity.java
+++ b/src/com/android/settings/RegulatoryInfoDisplayActivity.java
@@ -56,7 +56,7 @@
}
AlertDialog.Builder builder = new AlertDialog.Builder(this)
- .setTitle(R.string.regulatory_information)
+ .setTitle(R.string.regulatory_labels)
.setOnDismissListener(this);
boolean regulatoryInfoDrawableExists = false;
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 995fe95..a2acc37 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -172,7 +172,11 @@
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSubscriptionSpinner.setAdapter(adapter);
mSubscriptionSpinner.setSelection(selectedIndex);
- mSubscriptionSpinner.setVisibility(View.VISIBLE);
+ if (mSubscriptions.size() > 1) {
+ mSubscriptionSpinner.setVisibility(View.VISIBLE);
+ } else {
+ mSubscriptionSpinner.setVisibility(View.INVISIBLE);
+ }
} else {
mSubscriptionSpinner.setVisibility(View.INVISIBLE);
}
diff --git a/src/com/android/settings/RestrictedListPreference.java b/src/com/android/settings/RestrictedListPreference.java
index 521b698..25d4fc9 100644
--- a/src/com/android/settings/RestrictedListPreference.java
+++ b/src/com/android/settings/RestrictedListPreference.java
@@ -46,6 +46,7 @@
public RestrictedListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
+ setWidgetLayoutResource(R.layout.restricted_icon);
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
}
@@ -59,6 +60,10 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mHelper.onBindViewHolder(holder);
+ final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+ if (restrictedIcon != null) {
+ restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+ }
}
@Override
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 3c589cc..559b9ce 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -50,6 +50,7 @@
public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ }
public static class HomeSettingsActivity extends SettingsActivity { /* empty */ }
public static class DisplaySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class NightDisplaySettingsActivity extends SettingsActivity { /* empty */ }
public static class DeviceInfoSettingsActivity extends SettingsActivity { /* empty */ }
public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ }
@@ -77,6 +78,7 @@
public static class UsageAccessSettingsActivity extends SettingsActivity { /* empty */ }
public static class LocationSettingsActivity extends SettingsActivity { /* empty */ }
public static class PrivacySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class FactoryResetActivity extends SettingsActivity { /* empty */ }
public static class RunningServicesActivity extends SettingsActivity { /* empty */ }
public static class ManageAccountsSettingsActivity extends SettingsActivity { /* empty */ }
public static class PowerUsageSummaryActivity extends SettingsActivity { /* empty */ }
@@ -84,6 +86,7 @@
public static class AccountSyncSettingsActivity extends SettingsActivity { /* empty */ }
public static class AccountSettingsActivity extends SettingsActivity { /* empty */ }
public static class AccountSyncSettingsInAddAccountActivity extends SettingsActivity { /* empty */ }
+ public static class GestureSettingsActivity extends SettingsActivity { /* empty */ }
public static class CryptKeeperSettingsActivity extends SettingsActivity { /* empty */ }
public static class DeviceAdminSettingsActivity extends SettingsActivity { /* empty */ }
public static class DataUsageSummaryActivity extends SettingsActivity { /* empty */ }
@@ -116,7 +119,8 @@
public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ }
public static class OtherSoundSettingsActivity extends SettingsActivity { /* empty */ }
- public static class DomainsURLsAppListActivity extends SettingsActivity { /* empty */ }
+ public static class ManageDomainUrlsActivity extends SettingsActivity { /* empty */ }
+ public static class AutomaticStorageManagerSettingsActivity extends SettingsActivity { /* empty */ }
public static class TopLevelSettings extends SettingsActivity { /* empty */ }
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
@@ -131,7 +135,6 @@
public static class WifiCallingSuggestionActivity extends SettingsActivity { /* empty */ }
public static class ZenModeAutomationSuggestionActivity extends SettingsActivity { /* empty */ }
- public static class WallpaperSuggestionActivity extends SettingsActivity { /* empty */ }
public static class FingerprintSuggestionActivity extends FingerprintSettings { /* empty */ }
public static class FingerprintEnrollSuggestionActivity extends FingerprintEnrollIntroduction {
/* empty */
@@ -139,6 +142,7 @@
public static class ScreenLockSuggestionActivity extends ChooseLockGeneric { /* empty */ }
public static class WallpaperSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManagedProfileSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class DeletionHelperActivity extends SettingsActivity { /* empty */ }
public static class ApnEditorActivity extends SettingsActivity { /* empty */ }
public static class ChooseAccountActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index c597d16..f92df9d 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -16,10 +16,11 @@
package com.android.settings;
-import android.app.ActionBar;
+import android.app.ActivityManager;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
+import android.app.ActionBar;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -49,6 +50,7 @@
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.SearchView;
+
import com.android.internal.util.ArrayUtils;
import com.android.settings.Settings.WifiSettingsActivity;
import com.android.settings.accessibility.AccessibilitySettings;
@@ -63,16 +65,18 @@
import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.applications.ManageApplications;
import com.android.settings.applications.ManageAssist;
+import com.android.settings.applications.ManageDomainUrls;
import com.android.settings.applications.NotificationApps;
import com.android.settings.applications.ProcessStatsSummary;
import com.android.settings.applications.ProcessStatsUi;
import com.android.settings.applications.UsageAccessDetails;
-import com.android.settings.applications.WriteSettingsDetails;
import com.android.settings.applications.VrListenerSettings;
+import com.android.settings.applications.WriteSettingsDetails;
import com.android.settings.bluetooth.BluetoothSettings;
-import com.android.settings.dashboard.DashboardSummary;
+import com.android.settings.dashboard.DashboardContainerFragment;
import com.android.settings.dashboard.SearchResultsSummary;
import com.android.settings.datausage.DataUsageSummary;
+import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
import com.android.settings.deviceinfo.ImeiInformation;
import com.android.settings.deviceinfo.PrivateVolumeForget;
import com.android.settings.deviceinfo.PrivateVolumeSettings;
@@ -80,9 +84,11 @@
import com.android.settings.deviceinfo.SimStatus;
import com.android.settings.deviceinfo.Status;
import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.display.NightDisplaySettings;
import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageDetail;
import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.gestures.GestureSettings;
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
@@ -128,6 +134,7 @@
import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.settingslib.drawer.Tile;
+import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -239,6 +246,7 @@
Settings.StorageSettingsActivity.class.getName(),
Settings.ManageApplicationsActivity.class.getName(),
Settings.PowerUsageSummaryActivity.class.getName(),
+ Settings.GestureSettingsActivity.class.getName(),
//personal_section
Settings.LocationSettingsActivity.class.getName(),
Settings.SecuritySettingsActivity.class.getName(),
@@ -298,6 +306,7 @@
PowerUsageSummary.class.getName(),
AccountSyncSettings.class.getName(),
AccountSettings.class.getName(),
+ GestureSettings.class.getName(),
CryptKeeperSettings.class.getName(),
DataUsageSummary.class.getName(),
DreamSettings.class.getName(),
@@ -345,6 +354,10 @@
TestingSettings.class.getName(),
WifiAPITest.class.getName(),
WifiInfo.class.getName(),
+ MasterClear.class.getName(),
+ NightDisplaySettings.class.getName(),
+ ManageDomainUrls.class.getName(),
+ AutomaticStorageManagerSettings.class.getName()
};
@@ -396,7 +409,6 @@
private boolean mIsShowingDashboard;
private boolean mIsShortcut;
- private int mMainContentId = R.id.main_content;
private ViewGroup mContent;
private SearchView mSearchView;
@@ -421,12 +433,7 @@
@Override
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
- // Override the fragment title for Wallpaper settings
- CharSequence title = pref.getTitle();
- if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
- title = getString(R.string.wallpaper_settings_fragment_title);
- }
- startPreferencePanel(pref.getFragment(), pref.getExtras(), -1, title,
+ startPreferencePanel(pref.getFragment(), pref.getExtras(), -1, pref.getTitle(),
null, 0);
return true;
}
@@ -443,6 +450,15 @@
}
@Override
+ protected void onStart() {
+ super.onStart();
+
+ if (mNeedToRevertToInitialFragment) {
+ revertToInitialFragment();
+ }
+ }
+
+ @Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mDisplaySearch) {
return false;
@@ -565,7 +581,7 @@
setContentView(mIsShowingDashboard ?
R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
- mContent = (ViewGroup) findViewById(mMainContentId);
+ mContent = (ViewGroup) findViewById(R.id.main_content);
getFragmentManager().addOnBackStackChangedListener(this);
@@ -586,7 +602,6 @@
// of starting fresh.
mSearchMenuItemExpanded = savedState.getBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED);
mSearchQuery = savedState.getString(SAVE_KEY_SEARCH_QUERY);
-
setTitleFromIntent(intent);
ArrayList<DashboardCategory> categories =
@@ -599,6 +614,7 @@
mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
+
} else {
if (!mIsShowingDashboard) {
mDisplaySearch = false;
@@ -621,7 +637,13 @@
// Show Search affordance
mDisplaySearch = true;
mInitialTitleResId = R.string.dashboard_title;
- switchToFragment(DashboardSummary.class.getName(), null, false, false,
+
+ // add argument to indicate which settings tab should be initially selected
+ final Bundle args = new Bundle();
+ final String extraName = DashboardContainerFragment.EXTRA_SELECT_SETTINGS_TAB;
+ args.putString(extraName, intent.getStringExtra(extraName));
+
+ switchToFragment(DashboardContainerFragment.class.getName(), args, false, false,
mInitialTitleResId, mInitialTitle, false);
}
}
@@ -694,12 +716,11 @@
+ " ms");
}
- /**
- * Sets the id of the view continaing the main content. Should be called before calling super's
- * onCreate.
- */
- protected void setMainContentId(int contentId) {
- mMainContentId = contentId;
+ public void setDisplaySearchMenu(boolean displaySearch) {
+ if (displaySearch != mDisplaySearch) {
+ mDisplaySearch = displaySearch;
+ invalidateOptionsMenu();
+ }
}
private void setTitleFromIntent(Intent intent) {
@@ -737,7 +758,7 @@
setTitleFromBackStack();
}
- private int setTitleFromBackStack() {
+ private void setTitleFromBackStack() {
final int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
@@ -746,13 +767,11 @@
} else {
setTitle(mInitialTitle);
}
- return 0;
+ return;
}
FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1);
setTitleFromBackStackEntry(bse);
-
- return count;
}
private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) {
@@ -794,12 +813,8 @@
}
@Override
- protected void onStart() {
- super.onStart();
-
- if (mNeedToRevertToInitialFragment) {
- revertToInitialFragment();
- }
+ protected void onResume() {
+ super.onResume();
mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
@@ -823,8 +838,8 @@
}
@Override
- protected void onStop() {
- super.onStop();
+ protected void onPause() {
+ super.onPause();
unregisterReceiver(mBatteryInfoReceiver);
unregisterReceiver(mUserAddRemoveReceiver);
mDynamicIndexableContentMonitor.unregister();
@@ -988,7 +1003,7 @@
*/
public void startPreferenceFragment(Fragment fragment, boolean push) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.replace(mMainContentId, fragment);
+ transaction.replace(R.id.main_content, fragment);
if (push) {
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(BACK_STACK_PREFS);
@@ -1009,7 +1024,7 @@
}
Fragment f = Fragment.instantiate(this, fragmentName, args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.replace(mMainContentId, f);
+ transaction.replace(R.id.main_content, f);
if (withTransition) {
TransitionManager.beginDelayedTransition(mContent);
}
@@ -1068,6 +1083,13 @@
UserHandle.MU_ENABLED && UserManager.supportsMultipleUsers()
&& !Utils.isMonkeyRunning(), isAdmin, pm);
+ setTileEnabled(new ComponentName(packageName,
+ Settings.WirelessSettingsActivity.class.getName()),
+ !UserManager.isDeviceInDemoMode(this), isAdmin, pm);
+
+ setTileEnabled(new ComponentName(packageName,
+ Settings.DateTimeSettingsActivity.class.getName()),
+ !UserManager.isDeviceInDemoMode(this), isAdmin, pm);
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
setTileEnabled(new ComponentName(packageName,
Settings.PaymentSettingsActivity.class.getName()),
@@ -1102,6 +1124,23 @@
}
}
}
+
+ String backupIntent = getResources().getString(R.string.config_backup_settings_intent);
+ boolean useDefaultBackup = TextUtils.isEmpty(backupIntent);
+ setTileEnabled(new ComponentName(packageName,
+ Settings.PrivacySettingsActivity.class.getName()), useDefaultBackup, isAdmin, pm);
+ boolean hasBackupActivity = false;
+ if (!useDefaultBackup) {
+ try {
+ Intent intent = Intent.parseUri(backupIntent, 0);
+ hasBackupActivity = !getPackageManager().queryIntentActivities(intent, 0).isEmpty();
+ } catch (URISyntaxException e) {
+ Log.e(LOG_TAG, "Invalid backup intent URI!", e);
+ }
+ }
+ setTileEnabled(new ComponentName(packageName,
+ BackupSettingsActivity.class.getName()), hasBackupActivity, isAdmin, pm);
+
}
private void setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin,
@@ -1199,10 +1238,11 @@
if (mSearchResultsFragment != null) {
return;
}
- Fragment current = getFragmentManager().findFragmentById(mMainContentId);
+ Fragment current = getFragmentManager().findFragmentById(R.id.main_content);
if (current != null && current instanceof SearchResultsSummary) {
mSearchResultsFragment = (SearchResultsSummary) current;
} else {
+ setContentHeaderView(null);
mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
SearchResultsSummary.class.getName(), null, false, true,
R.string.search_results_title, null, true);
@@ -1235,6 +1275,9 @@
}
public void startSuggestion(Intent intent) {
+ if (intent == null || ActivityManager.isUserAMonkey()) {
+ return;
+ }
mCurrentSuggestion = intent.getComponent();
startActivityForResult(intent, REQUEST_SUGGESTION);
}
@@ -1248,5 +1291,4 @@
}
super.onActivityResult(requestCode, resultCode, data);
}
-
}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index d910825..16a60fd 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -399,10 +399,11 @@
for (Preference p : mPreferenceCache.values()) {
group.removePreference(p);
}
+ mPreferenceCache = null;
}
protected int getCachedCount() {
- return mPreferenceCache.size();
+ return mPreferenceCache != null ? mPreferenceCache.size() : 0;
}
private void highlightPreference(String key) {
@@ -519,7 +520,7 @@
// To be able to dismiss dialog at that time, don't check
// mDialogFragment.isVisible().
if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) {
- mDialogFragment.dismiss();
+ mDialogFragment.dismissAllowingStateLoss();
}
mDialogFragment = null;
}
diff --git a/src/com/android/settings/SetupChooseLockGeneric.java b/src/com/android/settings/SetupChooseLockGeneric.java
index bc3a2ec..71679f3 100644
--- a/src/com/android/settings/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/SetupChooseLockGeneric.java
@@ -16,7 +16,6 @@
package com.android.settings;
-import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
@@ -25,20 +24,18 @@
import android.content.res.Resources;
import android.os.Bundle;
import android.os.UserHandle;
-import android.support.v7.preference.Preference;
import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.LinearLayout;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.fingerprint.SetupSkipDialog;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.SetupWizardPreferenceLayout;
-import com.android.setupwizardlib.view.NavigationBar;
+import com.android.settings.utils.SettingsDividerItemDecoration;
+import com.android.setupwizardlib.GlifPreferenceLayout;
/**
* Setup Wizard's version of ChooseLockGeneric screen. It inherits the logic and basic structure
@@ -74,8 +71,7 @@
layout.setFitsSystemWindows(false);
}
- public static class SetupChooseLockGenericFragment extends ChooseLockGenericFragment
- implements NavigationBar.NavigationBarListener {
+ public static class SetupChooseLockGenericFragment extends ChooseLockGenericFragment {
public static final String EXTRA_PASSWORD_QUALITY = ":settings:password_quality";
@@ -83,25 +79,20 @@
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- SetupWizardUtils.setImmersiveMode(getActivity());
-
- SetupWizardPreferenceLayout layout = (SetupWizardPreferenceLayout) view;
+ GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
+ layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext()));
layout.setDividerInset(getContext().getResources().getDimensionPixelSize(
- R.dimen.suw_items_text_divider_inset));
- final NavigationBar navigationBar = layout.getNavigationBar();
- Button nextButton = navigationBar.getNextButton();
- nextButton.setText(null);
- nextButton.setEnabled(false);
- navigationBar.setNavigationBarListener(this);
+ R.dimen.suw_items_glif_text_divider_inset));
- layout.setIllustration(R.drawable.setup_illustration_lock_screen,
- R.drawable.setup_illustration_horizontal_tile);
- if (!mForFingerprint) {
- layout.setHeaderText(R.string.setup_lock_settings_picker_title);
- } else {
- layout.setHeaderText(R.string.lock_settings_picker_title);
+ layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
+
+ int titleResource = mForFingerprint ?
+ R.string.lock_settings_picker_title : R.string.setup_lock_settings_picker_title;
+ if (getActivity() != null) {
+ getActivity().setTitle(titleResource);
}
+ layout.setHeaderText(titleResource);
// Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
// PreferenceFragment.
setDivider(null);
@@ -143,7 +134,7 @@
@Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
- SetupWizardPreferenceLayout layout = (SetupWizardPreferenceLayout) parent;
+ GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
@@ -251,17 +242,5 @@
SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
return intent;
}
-
- @Override
- public void onNavigateBack() {
- Activity activity = getActivity();
- if (activity != null) {
- activity.onBackPressed();
- }
- }
-
- @Override
- public void onNavigateNext() {
- }
}
}
diff --git a/src/com/android/settings/SetupChooseLockPassword.java b/src/com/android/settings/SetupChooseLockPassword.java
index d483d8f..f0a9a26 100644
--- a/src/com/android/settings/SetupChooseLockPassword.java
+++ b/src/com/android/settings/SetupChooseLockPassword.java
@@ -16,21 +16,13 @@
package com.android.settings;
-import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
import android.widget.LinearLayout;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.util.SystemBarHelper;
-import com.android.setupwizardlib.view.NavigationBar;
-
/**
* Setup Wizard's version of ChooseLockPassword screen. It inherits the logic and basic structure
* from ChooseLockPassword class, and should remain similar to that behaviorally. This class should
@@ -91,56 +83,11 @@
super.onApplyThemeResource(theme, resid, first);
}
- public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment
- implements NavigationBar.NavigationBarListener {
-
- private SetupWizardLayout mLayout;
- private NavigationBar mNavigationBar;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- mLayout = (SetupWizardLayout) inflater.inflate(
- R.layout.setup_choose_lock_password, container, false);
- mNavigationBar = mLayout.getNavigationBar();
- mNavigationBar.setNavigationBarListener(this);
- return mLayout;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- SystemBarHelper.setImeInsetView(mLayout);
- SetupWizardUtils.setImmersiveMode(getActivity());
- mLayout.setHeaderText(getActivity().getTitle());
- }
+ public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment {
@Override
protected Intent getRedactionInterstitialIntent(Context context) {
return null;
}
-
- @Override
- protected void setNextEnabled(boolean enabled) {
- mNavigationBar.getNextButton().setEnabled(enabled);
- }
-
- @Override
- protected void setNextText(int text) {
- mNavigationBar.getNextButton().setText(text);
- }
-
- @Override
- public void onNavigateBack() {
- final Activity activity = getActivity();
- if (activity != null) {
- activity.onBackPressed();
- }
- }
-
- @Override
- public void onNavigateNext() {
- handleNext();
- }
}
}
diff --git a/src/com/android/settings/SetupChooseLockPattern.java b/src/com/android/settings/SetupChooseLockPattern.java
index 8a7842d..09b951e 100644
--- a/src/com/android/settings/SetupChooseLockPattern.java
+++ b/src/com/android/settings/SetupChooseLockPattern.java
@@ -16,21 +16,11 @@
package com.android.settings;
-import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.os.Bundle;
import android.os.UserHandle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.LinearLayout;
-
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.view.NavigationBar;
/**
* Setup Wizard's version of ChooseLockPattern screen. It inherits the logic and basic structure
@@ -74,99 +64,16 @@
}
@Override
- protected void onCreate(Bundle savedInstance) {
- super.onCreate(savedInstance);
- LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
- layout.setFitsSystemWindows(false);
- }
-
- @Override
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
resid = SetupWizardUtils.getTheme(getIntent());
super.onApplyThemeResource(theme, resid, first);
}
- public static class SetupChooseLockPatternFragment extends ChooseLockPatternFragment
- implements NavigationBar.NavigationBarListener {
-
- private NavigationBar mNavigationBar;
- private Button mRetryButton;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- final SetupWizardLayout layout = (SetupWizardLayout) inflater.inflate(
- R.layout.setup_choose_lock_pattern, container, false);
- mNavigationBar = layout.getNavigationBar();
- mNavigationBar.setNavigationBarListener(this);
- layout.setHeaderText(getActivity().getTitle());
- return layout;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- mRetryButton = (Button) view.findViewById(R.id.retryButton);
- mRetryButton.setOnClickListener(this);
- super.onViewCreated(view, savedInstanceState);
- SetupWizardUtils.setImmersiveMode(getActivity());
- }
+ public static class SetupChooseLockPatternFragment extends ChooseLockPatternFragment {
@Override
protected Intent getRedactionInterstitialIntent(Context context) {
return null;
}
-
- @Override
- public void onClick(View v) {
- if (v == mRetryButton) {
- handleLeftButton();
- } else {
- super.onClick(v);
- }
- }
-
- @Override
- protected void setRightButtonEnabled(boolean enabled) {
- mNavigationBar.getNextButton().setEnabled(enabled);
- }
-
- @Override
- protected void setRightButtonText(int text) {
- mNavigationBar.getNextButton().setText(text);
- }
-
- @Override
- protected void updateStage(Stage stage) {
- super.updateStage(stage);
- // Only enable the button for retry
- mRetryButton.setEnabled(stage == Stage.FirstChoiceValid);
-
- switch (stage) {
- case Introduction:
- case HelpScreen:
- case ChoiceTooShort:
- case FirstChoiceValid:
- mRetryButton.setVisibility(View.VISIBLE);
- break;
- case NeedToConfirm:
- case ConfirmWrong:
- case ChoiceConfirmed:
- mRetryButton.setVisibility(View.INVISIBLE);
- break;
- }
- }
-
- @Override
- public void onNavigateBack() {
- final Activity activity = getActivity();
- if (activity != null) {
- activity.onBackPressed();
- }
- }
-
- @Override
- public void onNavigateNext() {
- handleRightButton();
- }
}
}
diff --git a/src/com/android/settings/SetupEncryptionInterstitial.java b/src/com/android/settings/SetupEncryptionInterstitial.java
index 39c8af1..59e4d07 100644
--- a/src/com/android/settings/SetupEncryptionInterstitial.java
+++ b/src/com/android/settings/SetupEncryptionInterstitial.java
@@ -16,7 +16,6 @@
package com.android.settings;
-import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -25,13 +24,10 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.LinearLayout;
-import android.widget.TextView;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.SetupWizardPreferenceLayout;
-import com.android.setupwizardlib.view.NavigationBar;
+import com.android.settings.utils.SettingsDividerItemDecoration;
+import com.android.setupwizardlib.GlifPreferenceLayout;
/**
* Setup Wizard's version of EncryptionInterstitial screen. It inherits the logic and basic
@@ -78,30 +74,19 @@
layout.setFitsSystemWindows(false);
}
- public static class SetupEncryptionInterstitialFragment extends EncryptionInterstitialFragment
- implements NavigationBar.NavigationBarListener {
+ public static class SetupEncryptionInterstitialFragment extends EncryptionInterstitialFragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- final SetupWizardPreferenceLayout layout = (SetupWizardPreferenceLayout) view;
+ final GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
+ layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext()));
layout.setDividerInset(getContext().getResources().getDimensionPixelSize(
- R.dimen.suw_items_icon_divider_inset));
- layout.setIllustration(R.drawable.setup_illustration_lock_screen,
- R.drawable.setup_illustration_horizontal_tile);
-
- final NavigationBar navigationBar = layout.getNavigationBar();
- navigationBar.setNavigationBarListener(this);
- Button nextButton = navigationBar.getNextButton();
- nextButton.setText(null);
- nextButton.setEnabled(false);
+ R.dimen.suw_items_glif_icon_divider_inset));
+ layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
layout.setHeaderText(R.string.encryption_interstitial_header);
- Activity activity = getActivity();
- if (activity != null) {
- SetupWizardUtils.setImmersiveMode(activity);
- }
// Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
// PreferenceFragment.
@@ -109,30 +94,10 @@
}
@Override
- protected TextView createHeaderView() {
- TextView message = (TextView) LayoutInflater.from(getActivity()).inflate(
- R.layout.setup_encryption_interstitial_header, null, false);
- return message;
- }
-
- @Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
- SetupWizardPreferenceLayout layout = (SetupWizardPreferenceLayout) parent;
+ GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
-
- @Override
- public void onNavigateBack() {
- final Activity activity = getActivity();
- if (activity != null) {
- activity.onBackPressed();
- }
- }
-
- @Override
- public void onNavigateNext() {
- // next is handled via the onPreferenceTreeClick method in EncryptionInterstitial
- }
}
}
diff --git a/src/com/android/settings/SetupRedactionInterstitial.java b/src/com/android/settings/SetupRedactionInterstitial.java
index e487a50..d527585 100644
--- a/src/com/android/settings/SetupRedactionInterstitial.java
+++ b/src/com/android/settings/SetupRedactionInterstitial.java
@@ -16,20 +16,13 @@
package com.android.settings;
-import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
-import android.os.UserHandle;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
+import android.widget.Button;
import com.android.settings.notification.RedactionInterstitial;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.view.NavigationBar;
/**
* Setup Wizard's version of RedactionInterstitial screen. It inherits the logic and basic structure
@@ -59,49 +52,8 @@
super.onApplyThemeResource(theme, resid, first);
}
- @Override
- protected void onCreate(Bundle savedInstance) {
- super.onCreate(savedInstance);
- LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
- layout.setFitsSystemWindows(false);
- }
+ public static class SetupRedactionInterstitialFragment extends RedactionInterstitialFragment {
- public static class SetupRedactionInterstitialFragment extends RedactionInterstitialFragment
- implements NavigationBar.NavigationBarListener {
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- return inflater.inflate(R.layout.setup_redaction_interstitial, container, false);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- final SetupWizardLayout layout =
- (SetupWizardLayout) view.findViewById(R.id.setup_wizard_layout);
-
- final NavigationBar navigationBar = layout.getNavigationBar();
- navigationBar.setNavigationBarListener(this);
- navigationBar.getBackButton().setVisibility(View.GONE);
- SetupWizardUtils.setImmersiveMode(getActivity());
- }
-
- @Override
- public void onNavigateBack() {
- final Activity activity = getActivity();
- if (activity != null) {
- activity.onBackPressed();
- }
- }
-
- @Override
- public void onNavigateNext() {
- final SetupRedactionInterstitial activity = (SetupRedactionInterstitial) getActivity();
- if (activity != null) {
- activity.setResult(RESULT_OK, activity.getResultIntentData());
- finish();
- }
- }
+ // Setup wizard specific UI customizations can be done here
}
}
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index 71501b1..5563c3b 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -24,14 +24,6 @@
import com.android.setupwizardlib.util.WizardManagerHelper;
public class SetupWizardUtils {
- private static final String TAG = "SetupWizardUtils";
-
- // From WizardManager (must match constants maintained there)
- public static final String EXTRA_SCRIPT_URI = "scriptUri";
-
- public static boolean isUsingWizardManager(Activity activity) {
- return activity.getIntent().hasExtra(EXTRA_SCRIPT_URI);
- }
public static int getTheme(Intent intent) {
if (WizardManagerHelper.isLightTheme(intent, true)) {
diff --git a/src/com/android/settings/ShowAdminSupportDetailsDialog.java b/src/com/android/settings/ShowAdminSupportDetailsDialog.java
index 8ee07f9..2f65bb5 100644
--- a/src/com/android/settings/ShowAdminSupportDetailsDialog.java
+++ b/src/com/android/settings/ShowAdminSupportDetailsDialog.java
@@ -17,17 +17,14 @@
package com.android.settings;
import android.app.Activity;
-import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.AppGlobals;
-import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Process;
@@ -47,8 +44,6 @@
private static final String TAG = "AdminSupportDialog";
- private DevicePolicyManager mDpm;
-
private EnforcedAdmin mEnforcedAdmin;
private View mDialogView;
@@ -56,7 +51,6 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mDpm = getSystemService(DevicePolicyManager.class);
mEnforcedAdmin = getAdminDetailsFromIntent(getIntent());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -84,26 +78,11 @@
if (intent == null) {
return admin;
}
- // Only allow apps with MANAGE_DEVICE_ADMINS permission to specify admin and user.
- if (checkIfCallerHasPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS)) {
- admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
- admin.userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
- }
+ admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
+ admin.userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
return admin;
}
- private boolean checkIfCallerHasPermission(String permission) {
- IActivityManager am = ActivityManagerNative.getDefault();
- try {
- final int uid = am.getLaunchedFromUid(getActivityToken());
- return AppGlobals.getPackageManager().checkUidPermission(permission, uid)
- == PackageManager.PERMISSION_GRANTED;
- } catch (RemoteException e) {
- Log.e(TAG, "Could not talk to activity manager.", e);
- }
- return false;
- }
-
private void initializeDialogViews(View root, ComponentName admin, int userId) {
if (admin != null) {
if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(this, admin)
diff --git a/src/com/android/settings/SmsDefaultDialog.java b/src/com/android/settings/SmsDefaultDialog.java
index e38c9b8..830187c 100644
--- a/src/com/android/settings/SmsDefaultDialog.java
+++ b/src/com/android/settings/SmsDefaultDialog.java
@@ -109,11 +109,11 @@
// Compose dialog; get
if (oldSmsApplicationData != null) {
p.mMessage = getString(R.string.sms_change_default_dialog_text,
- mNewSmsApplicationData.mApplicationName,
- oldSmsApplicationData.mApplicationName);
+ mNewSmsApplicationData.getApplicationName(this),
+ oldSmsApplicationData.getApplicationName(this));
} else {
p.mMessage = getString(R.string.sms_change_default_no_previous_dialog_text,
- mNewSmsApplicationData.mApplicationName);
+ mNewSmsApplicationData.getApplicationName(this));
}
p.mPositiveButtonText = getString(R.string.yes);
p.mNegativeButtonText = getString(R.string.no);
diff --git a/src/com/android/settings/SummaryPreference.java b/src/com/android/settings/SummaryPreference.java
index 0943a2b..d129661 100644
--- a/src/com/android/settings/SummaryPreference.java
+++ b/src/com/android/settings/SummaryPreference.java
@@ -33,6 +33,8 @@
private String mUnits;
private int mLeft, mMiddle, mRight;
+ private boolean mColorsSet = false;
+ private boolean mChartEnabled = true;
private float mLeftRatio, mMiddleRatio, mRightRatio;
private String mStartLabel;
private String mEndLabel;
@@ -40,8 +42,13 @@
public SummaryPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.settings_summary_preference);
- mLeft = context.getColor(R.color.summary_default_start);
- mRight = context.getColor(R.color.summary_default_end);
+ }
+
+ public void setChartEnabled(boolean enabled) {
+ if (mChartEnabled != enabled) {
+ mChartEnabled = enabled;
+ notifyChanged();
+ }
}
public void setAmount(String amount) {
@@ -77,6 +84,7 @@
mLeft = left;
mMiddle = middle;
mRight = right;
+ mColorsSet = true;
notifyChanged();
}
@@ -85,10 +93,18 @@
super.onBindViewHolder(holder);
LinearColorBar colorBar = (LinearColorBar) holder.itemView.findViewById(R.id.color_bar);
- colorBar.setRatios(mLeftRatio, mMiddleRatio, mRightRatio);
- colorBar.setColors(mLeft, mMiddle, mRight);
- if (!TextUtils.isEmpty(mStartLabel) || !TextUtils.isEmpty(mEndLabel)) {
+ if (mChartEnabled) {
+ colorBar.setVisibility(View.VISIBLE);
+ colorBar.setRatios(mLeftRatio, mMiddleRatio, mRightRatio);
+ if (mColorsSet) {
+ colorBar.setColors(mLeft, mMiddle, mRight);
+ }
+ } else {
+ colorBar.setVisibility(View.GONE);
+ }
+
+ if (mChartEnabled && (!TextUtils.isEmpty(mStartLabel) || !TextUtils.isEmpty(mEndLabel))) {
holder.findViewById(R.id.label_bar).setVisibility(View.VISIBLE);
((TextView) holder.findViewById(android.R.id.text1)).setText(mStartLabel);
((TextView) holder.findViewById(android.R.id.text2)).setText(mEndLabel);
diff --git a/src/com/android/settings/TetherService.java b/src/com/android/settings/TetherService.java
index ad0e41f..6d359f2 100644
--- a/src/com/android/settings/TetherService.java
+++ b/src/com/android/settings/TetherService.java
@@ -20,6 +20,7 @@
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
+import android.app.usage.UsageStatsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -29,6 +30,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.net.ConnectivityManager;
import android.os.IBinder;
import android.os.ResultReceiver;
@@ -63,6 +66,7 @@
private int mCurrentTypeIndex;
private boolean mInProvisionCheck;
+ private UsageStatsManagerWrapper mUsageManagerWrapper;
private ArrayList<Integer> mCurrentTethers;
private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
@@ -87,6 +91,9 @@
mPendingCallbacks.put(ConnectivityManager.TETHERING_USB, new ArrayList<ResultReceiver>());
mPendingCallbacks.put(
ConnectivityManager.TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
+ if (mUsageManagerWrapper == null) {
+ mUsageManagerWrapper = new UsageStatsManagerWrapper(this);
+ }
}
@Override
@@ -228,20 +235,46 @@
private void startProvisioning(int index) {
if (index < mCurrentTethers.size()) {
- String provisionAction = getResources().getString(
- com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
- if (DEBUG) Log.d(TAG, "Sending provisioning broadcast: " + provisionAction + " type: "
- + mCurrentTethers.get(index));
- Intent intent = new Intent(provisionAction);
- int type = mCurrentTethers.get(index);
- intent.putExtra(TETHER_CHOICE, type);
- intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ Intent intent = getProvisionBroadcastIntent(index);
+ setEntitlementAppActive(index);
+
+ if (DEBUG) Log.d(TAG, "Sending provisioning broadcast: " + intent.getAction()
+ + " type: " + mCurrentTethers.get(index));
sendBroadcast(intent);
mInProvisionCheck = true;
}
}
+ private Intent getProvisionBroadcastIntent(int index) {
+ String provisionAction = getResources().getString(
+ com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
+ Intent intent = new Intent(provisionAction);
+ int type = mCurrentTethers.get(index);
+ intent.putExtra(TETHER_CHOICE, type);
+ intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ return intent;
+ }
+
+ private void setEntitlementAppActive(int index) {
+ final PackageManager packageManager = getPackageManager();
+ Intent intent = getProvisionBroadcastIntent(index);
+ List<ResolveInfo> resolvers =
+ packageManager.queryBroadcastReceivers(intent, PackageManager.MATCH_ALL);
+ if (resolvers.isEmpty()) {
+ Log.e(TAG, "No found BroadcastReceivers for provision intent.");
+ return;
+ }
+
+ for (ResolveInfo resolver : resolvers) {
+ if (resolver.activityInfo.applicationInfo.isSystemApp()) {
+ String packageName = resolver.activityInfo.packageName;
+ mUsageManagerWrapper.setAppInactive(packageName, false);
+ }
+ }
+ }
+
private void scheduleAlarm() {
Intent intent = new Intent(this, TetherService.class);
intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
@@ -335,4 +368,26 @@
}
};
+ @VisibleForTesting
+ void setUsageStatsManagerWrapper(UsageStatsManagerWrapper wrapper) {
+ mUsageManagerWrapper = wrapper;
+ }
+
+ /**
+ * A static helper class used for tests. UsageStatsManager cannot be mocked out becasue
+ * it's marked final. This class can be mocked out instead.
+ */
+ @VisibleForTesting
+ public static class UsageStatsManagerWrapper {
+ private final UsageStatsManager mUsageStatsManager;
+
+ UsageStatsManagerWrapper(Context context) {
+ mUsageStatsManager = (UsageStatsManager)
+ context.getSystemService(Context.USAGE_STATS_SERVICE);
+ }
+
+ void setAppInactive(String packageName, boolean isInactive) {
+ mUsageStatsManager.setAppInactive(packageName, isInactive);
+ }
+ }
}
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index be73aab..6b5a721 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -516,6 +516,9 @@
private static boolean isIntentAvailable(Context context) {
String[] provisionApp = context.getResources().getStringArray(
com.android.internal.R.array.config_mobile_hotspot_provision_app);
+ if (provisionApp.length < 2) {
+ return false;
+ }
final PackageManager packageManager = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(provisionApp[0], provisionApp[1]);
diff --git a/src/com/android/settings/UserDictionarySettings.java b/src/com/android/settings/UserDictionarySettings.java
index 19d34ef..bdeab92 100644
--- a/src/com/android/settings/UserDictionarySettings.java
+++ b/src/com/android/settings/UserDictionarySettings.java
@@ -160,7 +160,7 @@
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem actionItem =
menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
- .setIcon(R.drawable.ic_menu_add_dark);
+ .setIcon(R.drawable.ic_menu_add_white);
actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index d309867..dd62c6f 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -25,6 +25,7 @@
import android.app.Dialog;
import android.app.Fragment;
import android.app.IActivityManager;
+import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -49,8 +50,6 @@
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Looper;
@@ -92,6 +91,7 @@
import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.UserIcons;
+import com.android.internal.widget.LockPatternUtils;
import java.io.IOException;
import java.io.InputStream;
@@ -515,7 +515,7 @@
if (resultTo == null) {
context.startActivity(intent);
} else {
- resultTo.startActivityForResult(intent, resultRequestCode);
+ resultTo.getActivity().startActivityForResult(intent, resultRequestCode);
}
}
@@ -761,9 +761,13 @@
* devices allow users to flash other OSes to them.
*/
static void setOemUnlockEnabled(Context context, boolean enabled) {
- PersistentDataBlockManager manager =(PersistentDataBlockManager)
- context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
- manager.setOemUnlockEnabled(enabled);
+ try {
+ PersistentDataBlockManager manager = (PersistentDataBlockManager)
+ context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+ manager.setOemUnlockEnabled(enabled);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Fail to set oem unlock.", e);
+ }
}
/**
@@ -1125,6 +1129,30 @@
return false;
}
+ public static boolean unlockWorkProfileIfNecessary(Context context, int userId) {
+ try {
+ if (!ActivityManagerNative.getDefault().isUserRunning(userId,
+ ActivityManager.FLAG_AND_LOCKED)) {
+ return false;
+ }
+ } catch (RemoteException e) {
+ return false;
+ }
+ if (!(new LockPatternUtils(context)).isSecure(userId)) {
+ return false;
+ }
+ final KeyguardManager km = (KeyguardManager) context.getSystemService(
+ Context.KEYGUARD_SERVICE);
+ final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, userId);
+ if (unlockIntent != null) {
+ context.startActivity(unlockIntent);
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
public static CharSequence getApplicationLabel(Context context, String packageName) {
try {
final ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
@@ -1146,5 +1174,14 @@
}
return false;
}
-}
+ public static boolean isPackageDirectBootAware(Context context, String packageName) {
+ try {
+ final ApplicationInfo ai = context.getPackageManager().getApplicationInfo(
+ packageName, 0);
+ return ai.isDirectBootAware() || ai.isPartiallyDirectBootAware();
+ } catch (NameNotFoundException ignored) {
+ }
+ return false;
+ }
+}
diff --git a/src/com/android/settings/WallpaperSuggestionActivity.java b/src/com/android/settings/WallpaperSuggestionActivity.java
new file mode 100644
index 0000000..d264e4a
--- /dev/null
+++ b/src/com/android/settings/WallpaperSuggestionActivity.java
@@ -0,0 +1,35 @@
+/*
+ * 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.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class WallpaperSuggestionActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = new Intent()
+ .setClassName(getString(R.string.config_wallpaper_picker_package),
+ getString(R.string.config_wallpaper_picker_class))
+ .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ startActivity(intent);
+ finish();
+ }
+}
diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java
index 3602295..3e9da17 100644
--- a/src/com/android/settings/WifiCallingSettings.java
+++ b/src/com/android/settings/WifiCallingSettings.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -26,10 +27,12 @@
import android.os.PersistableBundle;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.support.v7.preference.PreferenceScreen;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.Log;
import android.widget.Switch;
import android.widget.TextView;
@@ -53,15 +56,27 @@
//String keys for preference lookup
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
+ private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
+ private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
+
+ private static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
+
+ public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP";
+
+ public static final int LAUCH_APP_ACTIVATE = 0;
+ public static final int LAUCH_APP_UPDATE = 1;
//UI objects
private SwitchBar mSwitchBar;
private Switch mSwitch;
private ListPreference mButtonWfcMode;
+ private ListPreference mButtonWfcRoamingMode;
+ private Preference mUpdateAddress;
private TextView mEmptyView;
private boolean mValidListener = false;
private boolean mEditableWfcMode = true;
+ private boolean mEditableWfcRoamingMode = true;
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
/*
@@ -82,14 +97,50 @@
switchBar.setEnabled((state == TelephonyManager.CALL_STATE_IDLE)
&& isNonTtyOrTtyOnVolteEnabled);
+ boolean isWfcModeEditable = true;
+ boolean isWfcRoamingModeEditable = false;
+ final CarrierConfigManager configManager = (CarrierConfigManager)
+ activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfig();
+ if (b != null) {
+ isWfcModeEditable = b.getBoolean(
+ CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
+ isWfcRoamingModeEditable = b.getBoolean(
+ CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
+ }
+ }
+
Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
if (pref != null) {
- pref.setEnabled(isWfcEnabled
+ pref.setEnabled(isWfcEnabled && isWfcModeEditable
+ && (state == TelephonyManager.CALL_STATE_IDLE));
+ }
+ Preference pref_roam = getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE);
+ if (pref_roam != null) {
+ pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable
&& (state == TelephonyManager.CALL_STATE_IDLE));
}
}
};
+ private final OnPreferenceClickListener mUpdateAddressListener =
+ new OnPreferenceClickListener() {
+ /*
+ * Launch carrier emergency address managemnent activity
+ */
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ final Context context = getActivity();
+ Intent carrierAppIntent = getCarrierActivityIntent(context);
+ if (carrierAppIntent != null) {
+ carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
+ startActivity(carrierAppIntent);
+ }
+ return true;
+ }
+ };
+
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -163,6 +214,12 @@
mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
mButtonWfcMode.setOnPreferenceChangeListener(this);
+ mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE);
+ mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
+
+ mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
+ mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener);
+
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(ImsManager.ACTION_IMS_REGISTRATION_ERROR);
@@ -173,6 +230,8 @@
PersistableBundle b = configManager.getConfig();
if (b != null) {
mEditableWfcMode = b.getBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
+ mEditableWfcRoamingMode = b.getBoolean(
+ CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
isWifiOnlySupported = b.getBoolean(
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true);
}
@@ -181,6 +240,10 @@
if (!isWifiOnlySupported) {
mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only);
mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only);
+ mButtonWfcRoamingMode.setEntries(
+ R.array.wifi_calling_mode_choices_v2_without_wifi_only);
+ mButtonWfcRoamingMode.setEntryValues(
+ R.array.wifi_calling_mode_values_without_wifi_only);
}
}
@@ -203,9 +266,11 @@
boolean wfcEnabled = ImsManager.isWfcEnabledByUser(context)
&& ImsManager.isNonTtyOrTtyOnVolteEnabled(context);
mSwitch.setChecked(wfcEnabled);
- int wfcMode = ImsManager.getWfcMode(context);
+ int wfcMode = ImsManager.getWfcMode(context, false);
+ int wfcRoamingMode = ImsManager.getWfcMode(context, true);
mButtonWfcMode.setValue(Integer.toString(wfcMode));
- updateButtonWfcMode(context, wfcEnabled, wfcMode);
+ mButtonWfcRoamingMode.setValue(Integer.toString(wfcRoamingMode));
+ updateButtonWfcMode(context, wfcEnabled, wfcMode, wfcRoamingMode);
context.registerReceiver(mIntentReceiver, mIntentFilter);
@@ -239,29 +304,112 @@
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
final Context context = getActivity();
+ Log.d(TAG, "onSwitchChanged(" + isChecked + ")");
- ImsManager.setWfcSetting(context, isChecked);
+ if (!isChecked) {
+ updateWfcMode(context, false);
+ return;
+ }
- int wfcMode = ImsManager.getWfcMode(context);
- updateButtonWfcMode(context, isChecked, wfcMode);
- if (isChecked) {
+ // Call address management activity before turning on WFC
+ Intent carrierAppIntent = getCarrierActivityIntent(context);
+ if (carrierAppIntent != null) {
+ carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
+ startActivityForResult(carrierAppIntent, REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
+ } else {
+ updateWfcMode(context, true);
+ }
+ }
+
+ /*
+ * Get the Intent to launch carrier emergency address management activity.
+ * Return null when no activity found.
+ */
+ private static Intent getCarrierActivityIntent(Context context) {
+ // Retrive component name from carrirt config
+ CarrierConfigManager configManager = context.getSystemService(CarrierConfigManager.class);
+ if (configManager == null) return null;
+
+ PersistableBundle bundle = configManager.getConfig();
+ if (bundle == null) return null;
+
+ String carrierApp = bundle.getString(
+ CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING);
+ if (TextUtils.isEmpty(carrierApp)) return null;
+
+ ComponentName componentName = ComponentName.unflattenFromString(carrierApp);
+ if (componentName == null) return null;
+
+ // Build and return intent
+ Intent intent = new Intent();
+ intent.setComponent(componentName);
+ return intent;
+ }
+
+ /*
+ * Turn on/off WFC mode with ImsManager and update UI accordingly
+ */
+ private void updateWfcMode(Context context, boolean wfcEnabled) {
+ Log.i(TAG, "updateWfcMode(" + wfcEnabled + ")");
+ ImsManager.setWfcSetting(context, wfcEnabled);
+
+ int wfcMode = ImsManager.getWfcMode(context, false);
+ int wfcRoamingMode = ImsManager.getWfcMode(context, true);
+ updateButtonWfcMode(context, wfcEnabled, wfcMode, wfcRoamingMode);
+ if (wfcEnabled) {
MetricsLogger.action(getActivity(), getMetricsCategory(), wfcMode);
} else {
MetricsLogger.action(getActivity(), getMetricsCategory(), -1);
}
}
- private void updateButtonWfcMode(Context context, boolean wfcEnabled, int wfcMode) {
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ final Context context = getActivity();
+
+ if (requestCode == REQUEST_CHECK_WFC_EMERGENCY_ADDRESS) {
+ Log.d(TAG, "WFC emergency address activity result = " + resultCode);
+
+ if (resultCode == Activity.RESULT_OK) {
+ updateWfcMode(context, true);
+ }
+ }
+ }
+
+ private void updateButtonWfcMode(Context context, boolean wfcEnabled,
+ int wfcMode, int wfcRoamingMode) {
mButtonWfcMode.setSummary(getWfcModeSummary(context, wfcMode));
- mButtonWfcMode.setEnabled(wfcEnabled);
+ mButtonWfcMode.setEnabled(wfcEnabled && mEditableWfcMode);
+ // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
+ mButtonWfcRoamingMode.setEnabled(wfcEnabled && mEditableWfcRoamingMode);
final PreferenceScreen preferenceScreen = getPreferenceScreen();
+ boolean updateAddressEnabled = (getCarrierActivityIntent(context) != null);
if (wfcEnabled) {
- preferenceScreen.addPreference(mButtonWfcMode);
+ if (mEditableWfcMode) {
+ preferenceScreen.addPreference(mButtonWfcMode);
+ } else {
+ // Don't show WFC (home) preference if it's not editable.
+ preferenceScreen.removePreference(mButtonWfcMode);
+ }
+ if (mEditableWfcRoamingMode) {
+ preferenceScreen.addPreference(mButtonWfcRoamingMode);
+ } else {
+ // Don't show WFC roaming preference if it's not editable.
+ preferenceScreen.removePreference(mButtonWfcRoamingMode);
+ }
+ if (updateAddressEnabled) {
+ preferenceScreen.addPreference(mUpdateAddress);
+ } else {
+ preferenceScreen.removePreference(mUpdateAddress);
+ }
} else {
preferenceScreen.removePreference(mButtonWfcMode);
+ preferenceScreen.removePreference(mButtonWfcRoamingMode);
+ preferenceScreen.removePreference(mUpdateAddress);
}
- preferenceScreen.setEnabled(mEditableWfcMode);
}
@Override
@@ -270,12 +418,28 @@
if (preference == mButtonWfcMode) {
mButtonWfcMode.setValue((String) newValue);
int buttonMode = Integer.valueOf((String) newValue);
- int currentMode = ImsManager.getWfcMode(context);
- if (buttonMode != currentMode) {
- ImsManager.setWfcMode(context, buttonMode);
+ int currentWfcMode = ImsManager.getWfcMode(context, false);
+ if (buttonMode != currentWfcMode) {
+ ImsManager.setWfcMode(context, buttonMode, false);
mButtonWfcMode.setSummary(getWfcModeSummary(context, buttonMode));
MetricsLogger.action(getActivity(), getMetricsCategory(), buttonMode);
}
+ if (!mEditableWfcRoamingMode) {
+ int currentWfcRoamingMode = ImsManager.getWfcMode(context, true);
+ if (buttonMode != currentWfcRoamingMode) {
+ ImsManager.setWfcMode(context, buttonMode, true);
+ // mButtonWfcRoamingMode.setSummary is not needed; summary is selected value
+ }
+ }
+ } else if (preference == mButtonWfcRoamingMode) {
+ mButtonWfcRoamingMode.setValue((String) newValue);
+ int buttonMode = Integer.valueOf((String) newValue);
+ int currentMode = ImsManager.getWfcMode(context, true);
+ if (buttonMode != currentMode) {
+ ImsManager.setWfcMode(context, buttonMode, true);
+ // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
+ MetricsLogger.action(getActivity(), getMetricsCategory(), buttonMode);
+ }
}
return true;
}
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 5b1d644..7434e67 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -57,6 +57,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
public class WirelessSettings extends SettingsPreferenceFragment implements Indexable {
@@ -72,6 +73,7 @@
private static final String KEY_MOBILE_NETWORK_SETTINGS = "mobile_network_settings";
private static final String KEY_MANAGE_MOBILE_PLAN = "manage_mobile_plan";
private static final String KEY_WFC_SETTINGS = "wifi_calling_settings";
+ private static final String KEY_NETWORK_RESET = "network_reset";
public static final String EXIT_ECM_RESULT = "exit_ecm_result";
public static final int REQUEST_CODE_EXIT_ECM = 1;
@@ -336,6 +338,12 @@
p.setEnabled(!TetherSettings
.isProvisioningNeededButUnavailable(getActivity()));
}
+
+ // Remove network reset if not allowed
+ if (RestrictedLockUtils.hasBaseUserRestriction(activity,
+ UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
+ removePreference(KEY_NETWORK_RESET);
+ }
}
@Override
@@ -349,11 +357,12 @@
// update WFC setting
final Context context = getActivity();
- if (ImsManager.isWfcEnabledByPlatform(context)) {
+ if (ImsManager.isWfcEnabledByPlatform(context) &&
+ ImsManager.isWfcProvisionedOnDevice(context)) {
getPreferenceScreen().addPreference(mButtonWfc);
mButtonWfc.setSummary(WifiCallingSettings.getWfcModeSummary(
- context, ImsManager.getWfcMode(context)));
+ context, ImsManager.getWfcMode(context, mTm.isNetworkRoaming())));
} else {
removePreference(KEY_WFC_SETTINGS);
}
@@ -402,6 +411,10 @@
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
+ // Remove wireless settings from search in demo mode
+ if (UserManager.isDeviceInDemoMode(context)) {
+ return Collections.emptyList();
+ }
SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.wireless_settings;
return Arrays.asList(sir);
@@ -466,10 +479,16 @@
result.add(KEY_TETHER_SETTINGS);
}
- if (!ImsManager.isWfcEnabledByPlatform(context)) {
+ if (!ImsManager.isWfcEnabledByPlatform(context) ||
+ !ImsManager.isWfcProvisionedOnDevice(context)) {
result.add(KEY_WFC_SETTINGS);
}
+ if (RestrictedLockUtils.hasBaseUserRestriction(context,
+ UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
+ result.add(KEY_NETWORK_RESET);
+ }
+
return result;
}
};
diff --git a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivity.java b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivity.java
index edc0282..0ccf6d8 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivity.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivity.java
@@ -42,46 +42,11 @@
@Override
protected void onCreate(Bundle savedState) {
- // Main content frame id should be set before calling super as that is where the first
- // Fragment is inflated.
- setMainContentId(R.id.suw_main_content);
super.onCreate(savedState);
// Finish configuring the content view.
- FrameLayout parentLayout = (FrameLayout) findViewById(R.id.main_content);
- LayoutInflater.from(this)
- .inflate(R.layout.accessibility_settings_for_suw, parentLayout);
-
getActionBar().setDisplayHomeAsUpEnabled(true);
setIsDrawerPresent(false);
-
- // Hide System Nav Bar.
- SystemBarHelper.hideSystemBars(getWindow());
- LinearLayout parentView = (LinearLayout) findViewById(R.id.content_parent);
- parentView.setFitsSystemWindows(false);
- // Adjust for the Status Bar.
- parentView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
- @Override
- public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
- parentView.setPadding(0, insets.getSystemWindowInsetTop(), 0, 0);
- return insets;
- }
- });
-
- // Show SUW Nav Bar.
- NavigationBar navigationBar = (NavigationBar) findViewById(R.id.suw_navigation_bar);
- navigationBar.getNextButton().setVisibility(View.GONE);
- navigationBar.setNavigationBarListener(new NavigationBar.NavigationBarListener() {
- @Override
- public void onNavigateBack() {
- onNavigateUp();
- }
-
- @Override
- public void onNavigateNext() {
- // Do nothing. We don't show this button.
- }
- });
}
@Override
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index 4e2ebce..196a4ab 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -34,6 +34,9 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
@@ -80,6 +83,21 @@
}
@Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater infalter) {
+ // Do not call super. We don't want to see the "Help & feedback" option on this page so as
+ // not to confuse users who think they might be able to send feedback about a specific
+ // accessibility service from this page.
+
+ // We still want to show the "Settings" menu.
+ if (mSettingsTitle != null && mSettingsIntent != null) {
+ MenuItem menuItem = menu.add(mSettingsTitle);
+ menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ menuItem.setIntent(mSettingsIntent);
+ }
+
+ }
+
+ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLockPatternUtils = new LockPatternUtils(getActivity());
@@ -185,10 +203,8 @@
}
private void updateSwitchBarToggleSwitch() {
- final String settingValue = Settings.Secure.getString(getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
- final boolean checked = settingValue != null
- && settingValue.contains(mComponentName.flattenToString());
+ final boolean checked = AccessibilityUtils.getEnabledServicesFromSettings(getActivity())
+ .contains(mComponentName);
mSwitchBar.setCheckedInternal(checked);
}
diff --git a/src/com/android/settings/accounts/AccountSettings.java b/src/com/android/settings/accounts/AccountSettings.java
index 22c9de7..bfc45a9 100644
--- a/src/com/android/settings/accounts/AccountSettings.java
+++ b/src/com/android/settings/accounts/AccountSettings.java
@@ -316,9 +316,11 @@
if (userInfo.isEnabled()) {
profileData.authenticatorHelper = new AuthenticatorHelper(context,
userInfo.getUserHandle(), this);
- if (!RestrictedLockUtils.hasBaseUserRestriction(context,
+ profileData.addAccountPreference = newAddAccountPreference(context);
+ if (RestrictedLockUtils.hasBaseUserRestriction(context,
UserManager.DISALLOW_MODIFY_ACCOUNTS, userInfo.id)) {
- profileData.addAccountPreference = newAddAccountPreference(context);
+ profileData.addAccountPreference.setEnabled(false);
+ } else {
profileData.addAccountPreference.checkRestrictionAndSetDisabled(
DISALLOW_MODIFY_ACCOUNTS, userInfo.id);
}
@@ -350,7 +352,7 @@
private Preference newManagedProfileSettings() {
Preference preference = new Preference(getPrefContext());
preference.setTitle(R.string.managed_profile_settings_title);
- preference.setIcon(R.drawable.ic_sysbar_quicksettings);
+ preference.setIcon(R.drawable.ic_settings);
preference.setOnPreferenceClickListener(this);
preference.setOrder(ORDER_NEXT_TO_LAST);
return preference;
@@ -552,6 +554,14 @@
@Override
public boolean onPreferenceClick(Preference preference) {
if (mFragment != null) {
+ UserHandle user = mFragmentArguments.getParcelable(EXTRA_USER);
+ if (user != null && Utils.startQuietModeDialogIfNecessary(getContext(), mUm,
+ user.getIdentifier())) {
+ return true;
+ } else if (user != null && Utils.unlockWorkProfileIfNecessary(getContext(),
+ user.getIdentifier())) {
+ return true;
+ }
Utils.startWithFragment(getContext(), mFragment, mFragmentArguments,
null /* resultTo */, 0 /* resultRequestCode */, mTitleResPackageName,
mTitleResId, null /* title */);
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index f809474..8ceb5e5 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -28,9 +28,12 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentSender;
import android.content.SyncAdapterType;
import android.content.SyncInfo;
import android.content.SyncStatusInfo;
+import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.UserInfo;
import android.os.Binder;
@@ -58,7 +61,6 @@
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -73,6 +75,7 @@
private static final int REALLY_REMOVE_DIALOG = 100;
private static final int FAILED_REMOVAL_DIALOG = 101;
private static final int CANT_DO_ONETIME_SYNC_DIALOG = 102;
+
private TextView mUserId;
private TextView mProviderId;
private ImageView mProviderIcon;
@@ -234,13 +237,15 @@
mAuthenticatorHelper.stopListeningToAccountUpdates();
}
- private void addSyncStateSwitch(Account account, String authority) {
+ private void addSyncStateSwitch(Account account, String authority,
+ String packageName, int uid) {
SyncStateSwitchPreference item = (SyncStateSwitchPreference) getCachedPreference(authority);
if (item == null) {
- item = new SyncStateSwitchPreference(getPrefContext(), account, authority);
+ item = new SyncStateSwitchPreference(getPrefContext(), account, authority,
+ packageName, uid);
getPreferenceScreen().addPreference(item);
} else {
- item.setup(account, authority);
+ item.setup(account, authority, packageName, uid);
}
item.setPersistent(false);
final ProviderInfo providerInfo = getPackageManager().resolveContentProviderAsUser(
@@ -267,13 +272,16 @@
MenuItem syncCancel = menu.add(0, MENU_SYNC_CANCEL_ID, 0,
getString(R.string.sync_menu_sync_cancel))
.setIcon(com.android.internal.R.drawable.ic_menu_close_clear_cancel);
- if (!RestrictedLockUtils.hasBaseUserRestriction(getPrefContext(),
+
+ MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0,
+ getString(R.string.remove_account_label))
+ .setIcon(R.drawable.ic_menu_delete);
+ removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
+ MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ if (RestrictedLockUtils.hasBaseUserRestriction(getPrefContext(),
UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle.getIdentifier())) {
- MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0,
- getString(R.string.remove_account_label))
- .setIcon(R.drawable.ic_menu_delete);
- removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
- MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ removeAccount.setEnabled(false);
+ } else {
EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
getPrefContext(), UserManager.DISALLOW_MODIFY_ACCOUNTS,
mUserHandle.getIdentifier());
@@ -284,6 +292,7 @@
RestrictedLockUtils.setMenuItemAsDisabledByAdmin(getPrefContext(),
removeAccount, admin);
}
+
syncNow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
syncCancel.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
@@ -319,20 +328,56 @@
}
@Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_OK) {
+ final int uid = requestCode;
+ final int count = getPreferenceScreen().getPreferenceCount();
+ for (int i = 0; i < count; i++) {
+ Preference preference = getPreferenceScreen().getPreference(i);
+ if (preference instanceof SyncStateSwitchPreference) {
+ SyncStateSwitchPreference syncPref = (SyncStateSwitchPreference) preference;
+ if (syncPref.getUid() == uid) {
+ onPreferenceTreeClick(syncPref);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
public boolean onPreferenceTreeClick(Preference preference) {
+ if (getActivity() == null) {
+ return false;
+ }
if (preference instanceof SyncStateSwitchPreference) {
SyncStateSwitchPreference syncPref = (SyncStateSwitchPreference) preference;
String authority = syncPref.getAuthority();
Account account = syncPref.getAccount();
final int userId = mUserHandle.getIdentifier();
+ String packageName = syncPref.getPackageName();
+
boolean syncAutomatically = ContentResolver.getSyncAutomaticallyAsUser(account,
authority, userId);
if (syncPref.isOneTimeSyncMode()) {
+ // If the sync adapter doesn't have access to the account we either
+ // request access by starting an activity if possible or kick off the
+ // sync which will end up posting an access request notification.
+ if (requestAccountAccessIfNeeded(packageName)) {
+ return true;
+ }
requestOrCancelSync(account, authority, true);
} else {
boolean syncOn = syncPref.isChecked();
boolean oldSyncState = syncAutomatically;
if (syncOn != oldSyncState) {
+ // Toggling this switch triggers sync but we may need a user approval.
+ // If the sync adapter doesn't have access to the account we either
+ // request access by starting an activity if possible or kick off the
+ // sync which will end up posting an access request notification.
+ if (syncOn && requestAccountAccessIfNeeded(packageName)) {
+ return true;
+ }
// if we're enabling sync, this will request a sync as well
ContentResolver.setSyncAutomaticallyAsUser(account, authority, syncOn, userId);
// if the master sync switch is off, the request above will
@@ -349,6 +394,36 @@
}
}
+ private boolean requestAccountAccessIfNeeded(String packageName) {
+ if (packageName == null) {
+ return false;
+ }
+
+ final int uid;
+ try {
+ uid = getContext().getPackageManager().getPackageUidAsUser(
+ packageName, mUserHandle.getIdentifier());
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Invalid sync ", e);
+ return false;
+ }
+
+ AccountManager accountManager = getContext().getSystemService(AccountManager.class);
+ if (!accountManager.hasAccountAccess(mAccount, packageName, mUserHandle)) {
+ IntentSender intent = accountManager.createRequestAccountAccessIntentSenderAsUser(
+ mAccount, packageName, mUserHandle);
+ if (intent != null) {
+ try {
+ startIntentSenderForResult(intent, uid, null, 0, 0, 0, null);
+ return true;
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "Error requesting account access", e);
+ }
+ }
+ }
+ return false;
+ }
+
private void startSyncForEnabledProviders() {
requestOrCancelSyncForEnabledProviders(true /* start them */);
final Activity activity = getActivity();
@@ -516,7 +591,7 @@
SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
mUserHandle.getIdentifier());
- ArrayList<String> authorities = new ArrayList<String>();
+ ArrayList<SyncAdapterType> authorities = new ArrayList<>();
for (int i = 0, n = syncAdapters.length; i < n; i++) {
final SyncAdapterType sa = syncAdapters[i];
// Only keep track of sync adapters for this account
@@ -526,7 +601,7 @@
Log.d(TAG, "updateAccountSwitches: added authority " + sa.authority
+ " to accountType " + sa.accountType);
}
- authorities.add(sa.authority);
+ authorities.add(sa);
} else {
// keep track of invisible sync adapters, so sync now forces
// them to sync as well.
@@ -539,15 +614,23 @@
}
cacheRemoveAllPrefs(getPreferenceScreen());
for (int j = 0, m = authorities.size(); j < m; j++) {
- final String authority = authorities.get(j);
+ final SyncAdapterType syncAdapter = authorities.get(j);
// We could check services here....
- int syncState = ContentResolver.getIsSyncableAsUser(mAccount, authority,
+ int syncState = ContentResolver.getIsSyncableAsUser(mAccount, syncAdapter.authority,
mUserHandle.getIdentifier());
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.d(TAG, " found authority " + authority + " " + syncState);
+ Log.d(TAG, " found authority " + syncAdapter.authority + " " + syncState);
}
if (syncState > 0) {
- addSyncStateSwitch(mAccount, authority);
+ final int uid;
+ try {
+ uid = getContext().getPackageManager().getPackageUidAsUser(
+ syncAdapter.getPackageName(), mUserHandle.getIdentifier());
+ addSyncStateSwitch(mAccount, syncAdapter.authority,
+ syncAdapter.getPackageName(), uid);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "No uid for package" + syncAdapter.getPackageName(), e);
+ }
}
}
removeCachedPrefs(getPreferenceScreen());
diff --git a/src/com/android/settings/accounts/SyncStateSwitchPreference.java b/src/com/android/settings/accounts/SyncStateSwitchPreference.java
index c6632d0..058fedd 100644
--- a/src/com/android/settings/accounts/SyncStateSwitchPreference.java
+++ b/src/com/android/settings/accounts/SyncStateSwitchPreference.java
@@ -36,6 +36,8 @@
private boolean mFailed = false;
private Account mAccount;
private String mAuthority;
+ private String mPackageName;
+ private int mUid;
/**
* A mode for this preference where clicking does a one-time sync instead of
@@ -47,16 +49,21 @@
super(context, attrs, 0, R.style.SyncSwitchPreference);
mAccount = null;
mAuthority = null;
+ mPackageName = null;
+ mUid = 0;
}
- public SyncStateSwitchPreference(Context context, Account account, String authority) {
+ public SyncStateSwitchPreference(Context context, Account account, String authority,
+ String packageName, int uid) {
super(context, null, 0, R.style.SyncSwitchPreference);
- setup(account, authority);
+ setup(account, authority, packageName, uid);
}
- public void setup(Account account, String authority) {
+ public void setup(Account account, String authority, String packageName, int uid) {
mAccount = account;
mAuthority = authority;
+ mPackageName = packageName;
+ mUid = uid;
notifyChanged();
}
@@ -152,4 +159,12 @@
public String getAuthority() {
return mAuthority;
}
+
+ public String getPackageName() {
+ return mPackageName;
+ };
+
+ public int getUid() {
+ return mUid;
+ };
}
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 8a99e03..f7992cc 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -22,8 +22,10 @@
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -74,6 +76,7 @@
protected static final int DLG_BASE = 0;
protected boolean mFinishing;
+ protected boolean mListeningToPackageRemove;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -90,6 +93,7 @@
mUsbManager = IUsbManager.Stub.asInterface(b);
retrieveAppEntry();
+ startListeningToPackageRemove();
}
@Override
@@ -114,6 +118,7 @@
@Override
public void onDestroy() {
+ stopListeningToPackageRemove();
mSession.release();
super.onDestroy();
}
@@ -246,4 +251,37 @@
return dialogFragment;
}
}
+
+ protected void startListeningToPackageRemove() {
+ if (mListeningToPackageRemove) {
+ return;
+ }
+ mListeningToPackageRemove = true;
+ final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ getContext().registerReceiver(mPackageRemovedReceiver, filter);
+ }
+
+ protected void stopListeningToPackageRemove() {
+ if (!mListeningToPackageRemove) {
+ return;
+ }
+ mListeningToPackageRemove = false;
+ getContext().unregisterReceiver(mPackageRemovedReceiver);
+ }
+
+ protected void onPackageRemoved() {
+ getActivity().finishAndRemoveTask();
+ }
+
+ protected final BroadcastReceiver mPackageRemovedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String packageName = intent.getData().getSchemeSpecificPart();
+ if (!mFinishing && mAppEntry.info.packageName.equals(packageName)) {
+ onPackageRemoved();
+ }
+ }
+ };
+
}
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 357ec1e..7c7d5a5 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -60,6 +60,9 @@
import java.util.Objects;
import java.util.TreeMap;
+import static android.content.pm.ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
+import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+
public class AppStorageSettings extends AppInfoWithHeader
implements OnClickListener, Callbacks, DialogInterface.OnClickListener {
private static final String TAG = AppStorageSettings.class.getSimpleName();
@@ -354,19 +357,27 @@
}
private void initDataButtons() {
- // If the app doesn't have its own space management UI
- // And it's a system app that doesn't allow clearing user data or is an active admin
- // Then disable the Clear Data button.
- if (mAppEntry.info.manageSpaceActivityName == null
- && ((mAppEntry.info.flags&(ApplicationInfo.FLAG_SYSTEM
- | ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA))
- == ApplicationInfo.FLAG_SYSTEM
- || mDpm.packageHasActiveAdmins(mPackageName))) {
+ final boolean appHasSpaceManagementUI = mAppEntry.info.manageSpaceActivityName != null;
+ final boolean appHasActiveAdmins = mDpm.packageHasActiveAdmins(mPackageName);
+ // Check that SYSTEM_APP flag is set, and ALLOW_CLEAR_USER_DATA is not set.
+ final boolean isNonClearableSystemApp =
+ (mAppEntry.info.flags & (FLAG_SYSTEM | FLAG_ALLOW_CLEAR_USER_DATA)) == FLAG_SYSTEM;
+ final boolean appRestrictsClearingData = isNonClearableSystemApp || appHasActiveAdmins;
+
+ final Intent intent = new Intent(Intent.ACTION_DEFAULT);
+ if (appHasSpaceManagementUI) {
+ intent.setClassName(mAppEntry.info.packageName, mAppEntry.info.manageSpaceActivityName);
+ }
+ final boolean isManageSpaceActivityAvailable =
+ getPackageManager().resolveActivity(intent, 0) != null;
+
+ if ((!appHasSpaceManagementUI && appRestrictsClearingData)
+ || !isManageSpaceActivityAvailable) {
mClearDataButton.setText(R.string.clear_user_data_text);
mClearDataButton.setEnabled(false);
mCanClearData = false;
} else {
- if (mAppEntry.info.manageSpaceActivityName != null) {
+ if (appHasSpaceManagementUI) {
mClearDataButton.setText(R.string.manage_space_text);
} else {
mClearDataButton.setText(R.string.clear_user_data_text);
diff --git a/src/com/android/settings/applications/DefaultBrowserPreference.java b/src/com/android/settings/applications/DefaultBrowserPreference.java
index d25e224..9d84e1e 100644
--- a/src/com/android/settings/applications/DefaultBrowserPreference.java
+++ b/src/com/android/settings/applications/DefaultBrowserPreference.java
@@ -26,6 +26,7 @@
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
+
import com.android.internal.content.PackageMonitor;
import com.android.settings.AppListPreference;
import com.android.settings.R;
@@ -36,12 +37,16 @@
public class DefaultBrowserPreference extends AppListPreference {
private static final String TAG = "DefaultBrowserPref";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final long DELAY_UPDATE_BROWSER_MILLIS = 500;
+ private static final Intent BROWSE_PROBE = new Intent()
+ .setAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .setData(Uri.parse("http:"));
private final Handler mHandler = new Handler();
-
- final private PackageManager mPm;
+ private final PackageManager mPm;
public DefaultBrowserPreference(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -65,11 +70,7 @@
@Override
protected boolean persistString(String newValue) {
-
- if (newValue == null) {
- return false;
- }
- final CharSequence packageName = (CharSequence) newValue;
+ final CharSequence packageName = newValue;
if (TextUtils.isEmpty(packageName)) {
return false;
}
@@ -95,13 +96,10 @@
String packageName = pm.getDefaultBrowserPackageNameAsUser(mUserId);
if (!TextUtils.isEmpty(packageName)) {
// Check if the default Browser package is still there
- Intent intent = new Intent();
- intent.setPackage(packageName);
- intent.setAction(Intent.ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- intent.setData(Uri.parse("http:"));
+ final Intent intent = new Intent(BROWSE_PROBE)
+ .setPackage(packageName);
- ResolveInfo info = mPm.resolveActivityAsUser(intent, 0, mUserId);
+ final ResolveInfo info = mPm.resolveActivityAsUser(intent, 0, mUserId);
if (info != null) {
setValue(packageName);
setSummary("%s");
@@ -109,26 +107,20 @@
setSummary(R.string.default_browser_title_none);
}
} else {
- setSummary(R.string.default_browser_title_none);
- Log.d(TAG, "Cannot set empty default Browser value!");
+ if (DEBUG) Log.d(TAG, "No default browser app.");
+ setSoleAppLabelAsSummary();
}
}
private List<String> resolveBrowserApps() {
List<String> result = new ArrayList<>();
- // Create an Intent that will match ALL Browser Apps
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- intent.setData(Uri.parse("http:"));
-
// Resolve that intent and check that the handleAllWebDataURI boolean is set
- List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(intent, PackageManager.MATCH_ALL,
- mUserId);
+ List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(BROWSE_PROBE,
+ PackageManager.MATCH_ALL, mUserId);
final int count = list.size();
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
ResolveInfo info = list.get(i);
if (info.activityInfo == null || result.contains(info.activityInfo.packageName)
|| !info.handleAllWebDataURI) {
@@ -141,6 +133,17 @@
return result;
}
+ @Override
+ protected CharSequence getSoleAppLabel() {
+ // Resolve that intent and check that the handleAllWebDataURI boolean is set
+ List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(BROWSE_PROBE,
+ PackageManager.MATCH_ALL, mUserId);
+ if (list.size() == 1) {
+ return list.get(0).loadLabel(mPm);
+ }
+ return null;
+ }
+
private final Runnable mUpdateRunnable = new Runnable() {
@Override
public void run() {
diff --git a/src/com/android/settings/applications/DefaultEmergencyPreference.java b/src/com/android/settings/applications/DefaultEmergencyPreference.java
index f0a97b1..dd4dc2e 100644
--- a/src/com/android/settings/applications/DefaultEmergencyPreference.java
+++ b/src/com/android/settings/applications/DefaultEmergencyPreference.java
@@ -16,7 +16,6 @@
package com.android.settings.applications;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -30,9 +29,11 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
-import com.android.internal.telephony.SmsApplication;
+
import com.android.settings.AppListPreference;
+import com.android.settings.R;
import com.android.settings.SelfAvailablePreference;
+import com.android.settings.Utils;
import java.util.List;
import java.util.Objects;
@@ -57,6 +58,12 @@
}
@Override
+ protected CharSequence getConfirmationMessage(String value) {
+ return Utils.isPackageDirectBootAware(getContext(), value) ? null
+ : getContext().getText(R.string.direct_boot_unaware_dialog_message);
+ }
+
+ @Override
protected boolean persistString(String value) {
String previousValue = Settings.Secure.getString(mContentResolver,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION);
diff --git a/src/com/android/settings/applications/DefaultHomePreference.java b/src/com/android/settings/applications/DefaultHomePreference.java
index 9f4a913..46fba66 100644
--- a/src/com/android/settings/applications/DefaultHomePreference.java
+++ b/src/com/android/settings/applications/DefaultHomePreference.java
@@ -26,6 +26,7 @@
import android.os.Build;
import android.os.UserManager;
import android.util.AttributeSet;
+
import com.android.settings.AppListPreference;
import com.android.settings.R;
@@ -36,9 +37,11 @@
private final ArrayList<ComponentName> mAllHomeComponents = new ArrayList<>();
private final IntentFilter mHomeFilter;
+ private final String mPackageName;
public DefaultHomePreference(Context context, AttributeSet attrs) {
super(context, attrs);
+ mPackageName = getContext().getPackageName();
mHomeFilter = new IntentFilter(Intent.ACTION_MAIN);
mHomeFilter.addCategory(Intent.CATEGORY_HOME);
mHomeFilter.addCategory(Intent.CATEGORY_DEFAULT);
@@ -59,26 +62,44 @@
IntentFilter.MATCH_CATEGORY_EMPTY,
mAllHomeComponents.toArray(new ComponentName[0]), component);
setSummary(getEntry());
+ } else {
+ // If there is only 1 launcher, use its label as summary text.
+ setSoleAppLabelAsSummary();
}
return super.persistString(value);
}
+ @Override
+ protected CharSequence getSoleAppLabel() {
+ final PackageManager pm = getContext().getPackageManager();
+ final List<ResolveInfo> homeActivities = new ArrayList<>();
+ final List<CharSequence> appLabels = new ArrayList<>();
+
+ pm.getHomeActivities(homeActivities);
+ for (ResolveInfo candidate : homeActivities) {
+ final ActivityInfo info = candidate.activityInfo;
+ if (info.packageName.equals(mPackageName)) {
+ continue;
+ }
+ appLabels.add(info.loadLabel(pm));
+ }
+ return appLabels.size() == 1 ? appLabels.get(0) : null;
+ }
+
public void refreshHomeOptions() {
- final String myPkg = getContext().getPackageName();
- ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
+ ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
PackageManager pm = getContext().getPackageManager();
- ComponentName currentDefaultHome = pm.getHomeActivities(homeActivities);
+ ComponentName currentDefaultHome = pm.getHomeActivities(homeActivities);
ArrayList<ComponentName> components = new ArrayList<>();
mAllHomeComponents.clear();
List<CharSequence> summaries = new ArrayList<>();
boolean mustSupportManagedProfile = hasManagedProfile();
- for (int i = 0; i < homeActivities.size(); i++) {
- final ResolveInfo candidate = homeActivities.get(i);
+ for (ResolveInfo candidate : homeActivities) {
final ActivityInfo info = candidate.activityInfo;
ComponentName activityName = new ComponentName(info.packageName, info.name);
mAllHomeComponents.add(activityName);
- if (info.packageName.equals(myPkg)) {
+ if (info.packageName.equals(mPackageName)) {
continue;
}
components.add(activityName);
diff --git a/src/com/android/settings/applications/DefaultPhonePreference.java b/src/com/android/settings/applications/DefaultPhonePreference.java
index fdaf7ad..e151274 100644
--- a/src/com/android/settings/applications/DefaultPhonePreference.java
+++ b/src/com/android/settings/applications/DefaultPhonePreference.java
@@ -24,23 +24,28 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
+
import com.android.settings.AppListPreference;
+import com.android.settings.R;
import com.android.settings.SelfAvailablePreference;
+import com.android.settings.Utils;
import java.util.List;
import java.util.Objects;
public class DefaultPhonePreference extends AppListPreference implements SelfAvailablePreference {
- private final Context mContext;
-
public DefaultPhonePreference(Context context, AttributeSet attrs) {
super(context, attrs);
-
- mContext = context.getApplicationContext();
loadDialerApps();
}
@Override
+ protected CharSequence getConfirmationMessage(String value) {
+ return Utils.isPackageDirectBootAware(getContext(), value) ? null
+ : getContext().getText(R.string.direct_boot_unaware_dialog_message);
+ }
+
+ @Override
protected boolean persistString(String value) {
if (!TextUtils.isEmpty(value) && !Objects.equals(value, getDefaultPackage())) {
DefaultDialerManager.setDefaultDialerApplication(getContext(), value, mUserId);
@@ -77,9 +82,13 @@
return false;
}
- final UserManager um =
- (UserManager) context.getSystemService(Context.USER_SERVICE);
- return !um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
+ final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ final boolean hasUserRestriction =
+ um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
+ final CharSequence[] entries = getEntries();
+ return !hasUserRestriction
+ && entries != null
+ && entries.length > 0;
}
public static boolean hasPhonePreference(String pkg, Context context) {
diff --git a/src/com/android/settings/applications/DefaultSmsPreference.java b/src/com/android/settings/applications/DefaultSmsPreference.java
index 9315102..96ac9a2 100644
--- a/src/com/android/settings/applications/DefaultSmsPreference.java
+++ b/src/com/android/settings/applications/DefaultSmsPreference.java
@@ -22,19 +22,20 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
+
import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.SmsApplication.SmsApplicationData;
import com.android.settings.AppListPreference;
+import com.android.settings.R;
import com.android.settings.SelfAvailablePreference;
+import com.android.settings.Utils;
import java.util.Collection;
import java.util.Objects;
public class DefaultSmsPreference extends AppListPreference implements SelfAvailablePreference {
-
public DefaultSmsPreference(Context context, AttributeSet attrs) {
super(context, attrs);
-
loadSmsApps();
}
@@ -60,6 +61,12 @@
}
@Override
+ protected CharSequence getConfirmationMessage(String value) {
+ return Utils.isPackageDirectBootAware(getContext(), value) ? null
+ : getContext().getText(R.string.direct_boot_unaware_dialog_message);
+ }
+
+ @Override
protected boolean persistString(String value) {
if (!TextUtils.isEmpty(value) && !Objects.equals(value, getDefaultPackage())) {
SmsApplication.setDefaultApplication(value, getContext());
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 0964abe..977f0b0 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -102,7 +102,6 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -185,7 +184,7 @@
// by not allowing disabling of apps signed with the
// system cert and any launcher app in the system.
if (mHomePackages.contains(mAppEntry.info.packageName)
- || Utils.isSystemPackage(mPm, mPackageInfo)) {
+ || Utils.isSystemPackage(getContext().getResources(), mPm, mPackageInfo)) {
// Disable button for core system applications.
button.setText(R.string.disable_text);
} else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
@@ -231,6 +230,11 @@
enabled = false;
}
+ // Don't allow uninstalling the device provisioning package.
+ if (Utils.isDeviceProvisioningPackage(getResources(), mAppEntry.info.packageName)) {
+ enabled = false;
+ }
+
// If the uninstall intent is already queued, disable the uninstall button
if (mDpm.isUninstallInQueue(mPackageName)) {
enabled = false;
@@ -479,21 +483,22 @@
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == REQUEST_UNINSTALL) {
- if (mDisableAfterUninstall) {
- mDisableAfterUninstall = false;
- new DisableChanger(this, mAppEntry.info,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
- .execute((Object)null);
- }
- if (!refreshUi()) {
- setIntentAndFinish(true, true);
- }
- }
- if (requestCode == REQUEST_REMOVE_DEVICE_ADMIN) {
- if (!refreshUi()) {
- setIntentAndFinish(true, true);
- }
+ switch (requestCode) {
+ case REQUEST_UNINSTALL:
+ if (mDisableAfterUninstall) {
+ mDisableAfterUninstall = false;
+ new DisableChanger(this, mAppEntry.info,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
+ .execute((Object)null);
+ }
+ // continue with following operations
+ case REQUEST_REMOVE_DEVICE_ADMIN:
+ if (!refreshUi()) {
+ setIntentAndFinish(true, true);
+ } else {
+ startListeningToPackageRemove();
+ }
+ break;
}
}
@@ -671,6 +676,7 @@
}
private void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) {
+ stopListeningToPackageRemove();
// Create new intent to launch Uninstaller activity
Uri packageURI = Uri.parse("package:"+packageName);
Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageURI);
@@ -726,7 +732,7 @@
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName);
intent.putExtra(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
try {
- startActivity(intent);
+ getActivity().startActivityForResult(intent, SUB_INFO_FRAGMENT);
} catch (ActivityNotFoundException e) {
Log.w(LOG_TAG, "No app can handle android.intent.action.MANAGE_APP_PERMISSIONS");
}
@@ -760,6 +766,7 @@
String packageName = mAppEntry.info.packageName;
if (v == mUninstallButton) {
if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
+ stopListeningToPackageRemove();
Activity activity = getActivity();
Intent uninstallDAIntent = new Intent(activity, DeviceAdminAdd.class);
uninstallDAIntent.putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME,
@@ -1073,6 +1080,12 @@
return summary.toString();
}
+ @Override
+ protected void onPackageRemoved() {
+ getActivity().finishActivity(SUB_INFO_FRAGMENT);
+ super.onPackageRemoved();
+ }
+
private class MemoryUpdater extends AsyncTask<Void, Void, ProcStatsPackageEntry> {
@Override
diff --git a/src/com/android/settings/applications/LinearColorBar.java b/src/com/android/settings/applications/LinearColorBar.java
index 158a625..b637671 100644
--- a/src/com/android/settings/applications/LinearColorBar.java
+++ b/src/com/android/settings/applications/LinearColorBar.java
@@ -14,10 +14,10 @@
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.widget.LinearLayout;
+import com.android.settings.Utils;
public class LinearColorBar extends LinearLayout {
- static final int LEFT_COLOR = 0xff009688;
- static final int MIDDLE_COLOR = 0xff009688;
+
static final int RIGHT_COLOR = 0xffced7db;
static final int GRAY_COLOR = 0xff555555;
static final int WHITE_COLOR = 0xffffffff;
@@ -26,8 +26,8 @@
private float mYellowRatio;
private float mGreenRatio;
- private int mLeftColor = LEFT_COLOR;
- private int mMiddleColor = MIDDLE_COLOR;
+ private int mLeftColor;
+ private int mMiddleColor;
private int mRightColor = RIGHT_COLOR;
private boolean mShowIndicator = true;
@@ -70,7 +70,7 @@
? 2 : 1;
mEdgeGradientPaint.setStrokeWidth(mLineWidth);
mEdgeGradientPaint.setAntiAlias(true);
-
+ mLeftColor = mMiddleColor = Utils.getColorAccent(context);
}
public void setOnRegionTappedListener(OnRegionTappedListener listener) {
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index dae5d7a..1594e23 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -57,7 +57,6 @@
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.Settings.AllApplicationsActivity;
-import com.android.settings.Settings.DomainsURLsAppListActivity;
import com.android.settings.Settings.HighPowerApplicationsActivity;
import com.android.settings.Settings.NotificationAppListActivity;
import com.android.settings.Settings.OverlaySettingsActivity;
@@ -136,7 +135,6 @@
public static final int FILTER_APPS_PRIORITY = 9;
public static final int FILTER_APPS_PERSONAL = 10;
public static final int FILTER_APPS_WORK = 11;
- public static final int FILTER_APPS_WITH_DOMAIN_URLS = 12;
public static final int FILTER_APPS_USAGE_ACCESS = 13;
public static final int FILTER_APPS_WITH_OVERLAY = 14;
public static final int FILTER_APPS_WRITE_SETTINGS = 15;
@@ -217,7 +215,6 @@
public static final int LIST_TYPE_MAIN = 0;
public static final int LIST_TYPE_NOTIFICATION = 1;
- public static final int LIST_TYPE_DOMAINS_URLS = 2;
public static final int LIST_TYPE_STORAGE = 3;
public static final int LIST_TYPE_USAGE_ACCESS = 4;
public static final int LIST_TYPE_HIGH_POWER = 5;
@@ -251,8 +248,6 @@
} else if (className.equals(NotificationAppListActivity.class.getName())) {
mListType = LIST_TYPE_NOTIFICATION;
mNotifBackend = new NotificationBackend();
- } else if (className.equals(DomainsURLsAppListActivity.class.getName())) {
- mListType = LIST_TYPE_DOMAINS_URLS;
} else if (className.equals(StorageUseActivity.class.getName())) {
if (args != null && args.containsKey(EXTRA_VOLUME_UUID)) {
mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
@@ -382,8 +377,6 @@
private int getDefaultFilter() {
switch (mListType) {
- case LIST_TYPE_DOMAINS_URLS:
- return FILTER_APPS_WITH_DOMAIN_URLS;
case LIST_TYPE_USAGE_ACCESS:
return FILTER_APPS_USAGE_ACCESS;
case LIST_TYPE_HIGH_POWER:
@@ -415,8 +408,6 @@
return MetricsEvent.MANAGE_APPLICATIONS;
case LIST_TYPE_NOTIFICATION:
return MetricsEvent.MANAGE_APPLICATIONS_NOTIFICATIONS;
- case LIST_TYPE_DOMAINS_URLS:
- return MetricsEvent.MANAGE_DOMAIN_URLS;
case LIST_TYPE_STORAGE:
return MetricsEvent.APPLICATIONS_STORAGE_APPS;
case LIST_TYPE_USAGE_ACCESS:
@@ -502,9 +493,6 @@
startAppInfoFragment(AppNotificationSettings.class,
R.string.app_notifications_title);
break;
- case LIST_TYPE_DOMAINS_URLS:
- startAppInfoFragment(AppLaunchSettings.class, R.string.auto_launch_label);
- break;
case LIST_TYPE_USAGE_ACCESS:
startAppInfoFragment(UsageAccessDetails.class, R.string.usage_access);
break;
@@ -537,9 +525,6 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (mListType == LIST_TYPE_DOMAINS_URLS) {
- return;
- }
HelpUtils.prepareHelpMenuItem(getActivity(), menu, mListType == LIST_TYPE_MAIN
? R.string.help_uri_apps : R.string.help_uri_notifications, getClass().getName());
mOptionsMenu = menu;
@@ -760,7 +745,7 @@
private boolean mHasReceivedLoadEntries;
private boolean mHasReceivedBridgeCallback;
- private AlphabeticIndex.ImmutableIndex mIndex;
+ private AlphabeticIndex.ImmutableIndex<Locale> mIndex;
private SectionInfo[] mSections = EMPTY_SECTIONS;
private int[] mPositionToSectionIndex;
@@ -902,6 +887,8 @@
comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
break;
}
+ filterObj = new CompoundFilter(filterObj, ApplicationsState.FILTER_NOT_HIDE);
+
AppFilter finalFilterObj = filterObj;
mBgHandler.post(() -> {
final ArrayList<AppEntry> entries = mSession.rebuild(finalFilterObj,
@@ -984,7 +971,7 @@
if (locales.size() == 0) {
locales = new LocaleList(Locale.ENGLISH);
}
- AlphabeticIndex index = new AlphabeticIndex<>(locales.get(0));
+ AlphabeticIndex<Locale> index = new AlphabeticIndex<>(locales.get(0));
int localeCount = locales.size();
for (int i = 1; i < localeCount; i++) {
index.addLabels(locales.get(i));
@@ -1181,10 +1168,6 @@
}
break;
- case LIST_TYPE_DOMAINS_URLS:
- holder.summary.setText(getDomainsSummary(holder.entry.info.packageName));
- break;
-
case LIST_TYPE_USAGE_ACCESS:
if (holder.entry.extraInfo != null) {
holder.summary.setText((new UsageState((PermissionState) holder.entry
@@ -1224,25 +1207,6 @@
mActive.remove(view);
}
- private CharSequence getDomainsSummary(String packageName) {
- // If the user has explicitly said "no" for this package, that's the
- // string we should show.
- int domainStatus = mPm.getIntentVerificationStatusAsUser(packageName, UserHandle.myUserId());
- if (domainStatus == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
- return mContext.getString(R.string.domain_urls_summary_none);
- }
- // Otherwise, ask package manager for the domains for this package,
- // and show the first one (or none if there aren't any).
- ArraySet<String> result = Utils.getHandledDomains(mPm, packageName);
- if (result.size() == 0) {
- return mContext.getString(R.string.domain_urls_summary_none);
- } else if (result.size() == 1) {
- return mContext.getString(R.string.domain_urls_summary_one, result.valueAt(0));
- } else {
- return mContext.getString(R.string.domain_urls_summary_some, result.valueAt(0));
- }
- }
-
@Override
public Object[] getSections() {
return mSections;
diff --git a/src/com/android/settings/applications/ManageAssist.java b/src/com/android/settings/applications/ManageAssist.java
index 6fe966d..9947aa2 100644
--- a/src/com/android/settings/applications/ManageAssist.java
+++ b/src/com/android/settings/applications/ManageAssist.java
@@ -24,6 +24,8 @@
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
+
+import com.android.internal.app.AssistUtils;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -39,10 +41,12 @@
private static final String KEY_CONTEXT = "context";
private static final String KEY_SCREENSHOT = "screenshot";
private static final String KEY_VOICE_INPUT = "voice_input_settings";
+ private static final String KEY_FLASH = "flash";
private DefaultAssistPreference mDefaultAssitPref;
private SwitchPreference mContextPref;
private SwitchPreference mScreenshotPref;
+ private SwitchPreference mFlashPref;
private VoiceInputListPreference mVoiceInputPref;
private Handler mHandler = new Handler();
@@ -62,6 +66,9 @@
mScreenshotPref = (SwitchPreference) findPreference(KEY_SCREENSHOT);
mScreenshotPref.setOnPreferenceChangeListener(this);
+ mFlashPref = (SwitchPreference) findPreference(KEY_FLASH);
+ mFlashPref.setOnPreferenceChangeListener(this);
+
mVoiceInputPref = (VoiceInputListPreference) findPreference(KEY_VOICE_INPUT);
updateUi();
}
@@ -76,7 +83,10 @@
if (preference == mContextPref) {
Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_STRUCTURE_ENABLED,
(boolean) newValue ? 1 : 0);
- postUpdateUi();
+ mHandler.post(() -> {
+ guardScreenshotPref();
+ guardFlashPref();
+ });
return true;
}
if (preference == mScreenshotPref) {
@@ -84,6 +94,11 @@
(boolean) newValue ? 1 : 0);
return true;
}
+ if (preference == mFlashPref) {
+ Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
+ (boolean) newValue ? 1 : 0);
+ return true;
+ }
if (preference == mDefaultAssitPref) {
String newAssitPackage = (String)newValue;
if (newAssitPackage == null ||
@@ -101,13 +116,23 @@
return false;
}
- private void postUpdateUi() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- updateUi();
- }
- });
+ private void guardScreenshotPref() {
+ boolean isChecked = mContextPref.isChecked();
+ boolean screenshotPrefWasSet = Settings.Secure.getInt(
+ getContentResolver(), Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1) != 0;
+ mScreenshotPref.setEnabled(isChecked);
+ mScreenshotPref.setChecked(isChecked && screenshotPrefWasSet);
+ }
+
+ private void guardFlashPref() {
+ ComponentName assistant = mDefaultAssitPref.getCurrentAssist();
+
+ boolean isContextChecked = mContextPref.isChecked();
+ boolean willShowFlash = AssistUtils.shouldDisclose(getContext(), assistant);
+ boolean isSystemAssistant = AssistUtils.isPreinstalledAssistant(getContext(), assistant);
+
+ mFlashPref.setEnabled(isContextChecked && isSystemAssistant);
+ mFlashPref.setChecked(willShowFlash);
}
private void updateUi() {
@@ -122,6 +147,13 @@
} else {
getPreferenceScreen().removePreference(mContextPref);
getPreferenceScreen().removePreference(mScreenshotPref);
+ getPreferenceScreen().removePreference(mFlashPref);
+ }
+
+ if (hasAssistant && AssistUtils.allowDisablingAssistDisclosure(getContext())) {
+ getPreferenceScreen().addPreference(mFlashPref);
+ } else {
+ getPreferenceScreen().removePreference(mFlashPref);
}
if (isCurrentAssistVoiceService()) {
@@ -131,9 +163,8 @@
mVoiceInputPref.setAssistRestrict(currentAssist);
}
- mScreenshotPref.setEnabled(mContextPref.isChecked());
- mScreenshotPref.setChecked(mContextPref.isChecked() && Settings.Secure.getInt(
- getContentResolver(), Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1) != 0);
+ guardScreenshotPref();
+ guardFlashPref();
}
private boolean isCurrentAssistVoiceService() {
diff --git a/src/com/android/settings/applications/ManageDomainUrls.java b/src/com/android/settings/applications/ManageDomainUrls.java
new file mode 100644
index 0000000..4ffdbf4
--- /dev/null
+++ b/src/com/android/settings/applications/ManageDomainUrls.java
@@ -0,0 +1,277 @@
+/*
+ * 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.applications;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.ArraySet;
+import android.view.View;
+
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+
+import java.util.ArrayList;
+
+/**
+ * Activity to manage how Android handles URL resolution. Includes both per-app
+ * handling as well as system handling for Web Actions.
+ */
+public class ManageDomainUrls extends SettingsPreferenceFragment
+ implements ApplicationsState.Callbacks, OnPreferenceChangeListener,
+ OnPreferenceClickListener {
+
+ // constant value that can be used to check return code from sub activity.
+ private static final int INSTALLED_APP_DETAILS = 1;
+
+ private ApplicationsState mApplicationsState;
+ private ApplicationsState.Session mSession;
+ private PreferenceGroup mDomainAppList;
+ private SwitchPreference mWebAction;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setAnimationAllowed(true);
+ setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
+ mApplicationsState = ApplicationsState.getInstance(
+ (Application) getContext().getApplicationContext());
+ mSession = mApplicationsState.newSession(this);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mSession.resume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mSession.pause();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mSession.release();
+ }
+
+ @Override
+ public void onRunningStateChanged(boolean running) {
+ }
+
+ @Override
+ public void onPackageListChanged() {
+ }
+
+ @Override
+ public void onRebuildComplete(ArrayList<AppEntry> apps) {
+ if (getContext() == null) {
+ return;
+ }
+
+ final boolean disableWebActions = Global.getInt(getContext().getContentResolver(),
+ Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0;
+ if (disableWebActions) {
+ mDomainAppList = getPreferenceScreen();
+ } else {
+ final PreferenceGroup preferenceScreen = getPreferenceScreen();
+ if (preferenceScreen.getPreferenceCount() == 0) {
+ // add preferences
+ final PreferenceCategory webActionCategory =
+ new PreferenceCategory(getPrefContext());
+ webActionCategory.setTitle(R.string.web_action_section_title);
+ preferenceScreen.addPreference(webActionCategory);
+
+ // toggle to enable / disable Web Actions [aka Instant Apps]
+ mWebAction = new SwitchPreference(getPrefContext());
+ mWebAction.setTitle(R.string.web_action_enable_title);
+ mWebAction.setSummary(R.string.web_action_enable_summary);
+ mWebAction.setChecked(Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.WEB_ACTION_ENABLED, 1) != 0);
+ mWebAction.setOnPreferenceChangeListener(this);
+ webActionCategory.addPreference(mWebAction);
+
+ // list to manage link handling per app
+ mDomainAppList = new PreferenceCategory(getPrefContext());
+ mDomainAppList.setTitle(R.string.domain_url_section_title);
+ preferenceScreen.addPreference(mDomainAppList);
+ }
+ }
+ rebuildAppList(mDomainAppList, apps);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mWebAction) {
+ final int enabled = (boolean) newValue ? 1 : 0;
+ Settings.Secure.putInt(
+ getContentResolver(), Settings.Secure.WEB_ACTION_ENABLED, enabled);
+ return true;
+ }
+ return false;
+ }
+
+ private void rebuild() {
+ final ArrayList<AppEntry> apps = mSession.rebuild(
+ ApplicationsState.FILTER_WITH_DOMAIN_URLS, ApplicationsState.ALPHA_COMPARATOR);
+ if (apps != null) {
+ onRebuildComplete(apps);
+ }
+ }
+
+ private void rebuildAppList(PreferenceGroup group, ArrayList<AppEntry> apps) {
+ cacheRemoveAllPrefs(group);
+ final int N = apps.size();
+ for (int i = 0; i < N; i++) {
+ AppEntry entry = apps.get(i);
+ String key = entry.info.packageName + "|" + entry.info.uid;
+ DomainAppPreference preference = (DomainAppPreference) getCachedPreference(key);
+ if (preference == null) {
+ preference = new DomainAppPreference(getPrefContext(), entry);
+ preference.setKey(key);
+ preference.setOnPreferenceClickListener(this);
+ group.addPreference(preference);
+ } else {
+ preference.reuse();
+ }
+ preference.setOrder(i);
+ }
+ removeCachedPrefs(group);
+ }
+
+ @Override
+ public void onPackageIconChanged() {
+ }
+
+ @Override
+ public void onPackageSizeChanged(String packageName) {
+ }
+
+ @Override
+ public void onAllSizesComputed() {
+ }
+
+ @Override
+ public void onLauncherInfoChanged() {
+ }
+
+ @Override
+ public void onLoadEntriesCompleted() {
+ rebuild();
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsEvent.MANAGE_DOMAIN_URLS;
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (preference.getClass() == DomainAppPreference.class) {
+ ApplicationsState.AppEntry entry = ((DomainAppPreference) preference).mEntry;
+ AppInfoBase.startAppInfoFragment(AppLaunchSettings.class, R.string.auto_launch_label,
+ entry.info.packageName, entry.info.uid, this,
+ INSTALLED_APP_DETAILS);
+ return true;
+ }
+ return false;
+ }
+
+ private class DomainAppPreference extends Preference {
+ private final AppEntry mEntry;
+ private final PackageManager mPm;
+
+ public DomainAppPreference(final Context context, AppEntry entry) {
+ super(context);
+ mPm = context.getPackageManager();
+ mEntry = entry;
+ mEntry.ensureLabel(getContext());
+ setState();
+ if (mEntry.icon != null) {
+ setIcon(mEntry.icon);
+ }
+ }
+
+ private void setState() {
+ setTitle(mEntry.label);
+ setSummary(getDomainsSummary(mEntry.info.packageName));
+ }
+
+ public void reuse() {
+ setState();
+ notifyChanged();
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ if (mEntry.icon == null) {
+ holder.itemView.post(new Runnable() {
+ @Override
+ public void run() {
+ // Ensure we have an icon before binding.
+ mApplicationsState.ensureIcon(mEntry);
+ // This might trigger us to bind again, but it gives an easy way to only
+ // load the icon once its needed, so its probably worth it.
+ setIcon(mEntry.icon);
+ }
+ });
+ }
+ super.onBindViewHolder(holder);
+ }
+
+ private CharSequence getDomainsSummary(String packageName) {
+ // If the user has explicitly said "no" for this package, that's the
+ // string we should show.
+ int domainStatus =
+ mPm.getIntentVerificationStatusAsUser(packageName, UserHandle.myUserId());
+ if (domainStatus == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
+ return getContext().getString(R.string.domain_urls_summary_none);
+ }
+ // Otherwise, ask package manager for the domains for this package,
+ // and show the first one (or none if there aren't any).
+ ArraySet<String> result = Utils.getHandledDomains(mPm, packageName);
+ if (result.size() == 0) {
+ return getContext().getString(R.string.domain_urls_summary_none);
+ } else if (result.size() == 1) {
+ return getContext().getString(R.string.domain_urls_summary_one, result.valueAt(0));
+ } else {
+ return getContext().getString(R.string.domain_urls_summary_some, result.valueAt(0));
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java
index 36d397e..90ef5d7 100644
--- a/src/com/android/settings/applications/ProcStatsEntry.java
+++ b/src/com/android/settings/applications/ProcStatsEntry.java
@@ -20,12 +20,13 @@
import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
-import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessState;
+import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ServiceState;
import java.util.ArrayList;
@@ -33,6 +34,7 @@
import java.util.Comparator;
public final class ProcStatsEntry implements Parcelable {
+
private static final String TAG = "ProcStatsEntry";
private static boolean DEBUG = ProcessStatsUi.DEBUG;
@@ -40,7 +42,7 @@
final int mUid;
final String mName;
public CharSequence mLabel;
- final ArrayList<String> mPackages = new ArrayList<String>();
+ final ArrayList<String> mPackages = new ArrayList<>();
final long mBgDuration;
final long mAvgBgMem;
final long mMaxBgMem;
@@ -52,7 +54,7 @@
String mBestTargetPackage;
- ArrayMap<String, ArrayList<Service>> mServices = new ArrayMap<String, ArrayList<Service>>(1);
+ ArrayMap<String, ArrayList<Service>> mServices = new ArrayMap<>(1);
public ProcStatsEntry(ProcessState proc, String packageName,
ProcessStats.ProcessDataCollection tmpBgTotals,
@@ -249,6 +251,10 @@
+ " not as good as last " + bestRunTime);
}
}
+ // Final fallback, just pick the first subProc.
+ if (TextUtils.isEmpty(mBestTargetPackage)) {
+ mBestTargetPackage = subProcs.get(0).mPackage;
+ }
} else if (subProcs.size() == 1) {
mBestTargetPackage = subProcs.get(0).mPackage;
}
diff --git a/src/com/android/settings/applications/ProcessStatsSummary.java b/src/com/android/settings/applications/ProcessStatsSummary.java
index 30701dc..01dbf09 100644
--- a/src/com/android/settings/applications/ProcessStatsSummary.java
+++ b/src/com/android/settings/applications/ProcessStatsSummary.java
@@ -53,10 +53,6 @@
addPreferencesFromResource(R.xml.process_stats_summary);
mSummaryPref = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
- int memColor = getContext().getColor(R.color.running_processes_apps_ram);
- mSummaryPref.setColors(memColor, memColor,
- getContext().getColor(R.color.running_processes_free_ram));
-
mPerformance = findPreference(KEY_PERFORMANCE);
mTotalMemory = findPreference(KEY_TOTAL_MEMORY);
mAverageUsed = findPreference(KEY_AVERAGY_USED);
diff --git a/src/com/android/settings/applications/RunningProcessesView.java b/src/com/android/settings/applications/RunningProcessesView.java
index af60996..7ba83c2 100644
--- a/src/com/android/settings/applications/RunningProcessesView.java
+++ b/src/com/android/settings/applications/RunningProcessesView.java
@@ -42,6 +42,7 @@
import com.android.internal.util.MemInfoReader;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
import java.util.ArrayList;
import java.util.Collections;
@@ -450,7 +451,7 @@
mColorBar = (LinearColorBar)mHeader.findViewById(R.id.color_bar);
final Context context = getContext();
mColorBar.setColors(context.getColor(R.color.running_processes_system_ram),
- context.getColor(R.color.running_processes_apps_ram),
+ Utils.getColorAccent(context),
context.getColor(R.color.running_processes_free_ram));
mBackgroundProcessPrefix = (TextView)mHeader.findViewById(R.id.freeSizePrefix);
mAppsProcessPrefix = (TextView)mHeader.findViewById(R.id.appsSizePrefix);
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialog.java b/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
index 48ca5a9..b176efd 100755
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
@@ -67,7 +67,7 @@
private EditText mPairingView;
private Button mOkButton;
private LocalBluetoothProfile mPbapClientProfile;
-
+ private boolean mReceiverRegistered;
/**
* Dismiss the dialog if the bond state changes to bonded or none,
@@ -98,8 +98,7 @@
super.onCreate(savedInstanceState);
Intent intent = getIntent();
- if (!intent.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST))
- {
+ if (!intent.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
Log.e(TAG, "Error: this activity may be started only with intent " +
BluetoothDevice.ACTION_PAIRING_REQUEST);
finish();
@@ -167,6 +166,7 @@
*/
registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_CANCEL));
registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
+ mReceiverRegistered = true;
}
private void createUserEntryDialog() {
@@ -373,7 +373,10 @@
@Override
protected void onDestroy() {
super.onDestroy();
- unregisterReceiver(mReceiver);
+ if (mReceiverRegistered) {
+ mReceiverRegistered = false;
+ unregisterReceiver(mReceiver);
+ }
}
public void afterTextChanged(Editable s) {
@@ -387,6 +390,7 @@
}
private void onPair(String value) {
+ Log.i(TAG, "Pairing dialog accepted");
switch (mType) {
case BluetoothDevice.PAIRING_VARIANT_PIN:
case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
@@ -422,6 +426,7 @@
}
private void onCancel() {
+ Log.i(TAG, "Pairing dialog canceled");
mDevice.cancelPairingUserInput();
}
diff --git a/src/com/android/settings/bluetooth/DeviceProfilesSettings.java b/src/com/android/settings/bluetooth/DeviceProfilesSettings.java
index ca4d4f5..d45bea4 100755
--- a/src/com/android/settings/bluetooth/DeviceProfilesSettings.java
+++ b/src/com/android/settings/bluetooth/DeviceProfilesSettings.java
@@ -103,7 +103,7 @@
deviceName.setText(mCachedDevice.getName(), TextView.BufferType.EDITABLE);
return new AlertDialog.Builder(getContext())
.setView(mRootView)
- .setNegativeButton(R.string.forget, this)
+ .setNeutralButton(R.string.forget, this)
.setPositiveButton(R.string.okay, this)
.setTitle(R.string.bluetooth_preference_paired_devices)
.create();
@@ -116,7 +116,7 @@
EditText deviceName = (EditText) mRootView.findViewById(R.id.name);
mCachedDevice.setName(deviceName.getText().toString());
break;
- case DialogInterface.BUTTON_NEGATIVE:
+ case DialogInterface.BUTTON_NEUTRAL:
mCachedDevice.unpair();
com.android.settings.bluetooth.Utils.updateSearchIndex(getContext(),
BluetoothSettings.class.getName(), mCachedDevice.getName(),
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index c54311a..6b2e145 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -15,11 +15,11 @@
*/
package com.android.settings.dashboard;
-import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.os.Bundle;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
@@ -32,6 +32,7 @@
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
@@ -49,6 +50,10 @@
public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.DashboardItemHolder>
implements View.OnClickListener {
public static final String TAG = "DashboardAdapter";
+ private static final String STATE_SUGGESTION_LIST = "suggestion_list";
+ private static final String STATE_CATEGORY_LIST = "category_list";
+ private static final String STATE_IS_SHOWING_ALL = "is_showing_all";
+ private static final String STATE_SUGGESTION_MODE = "suggestion_mode";
private static final int NS_SPACER = 0;
private static final int NS_SUGGESTION = 1000;
private static final int NS_ITEMS = 2000;
@@ -80,37 +85,33 @@
private Condition mExpandedCondition = null;
private SuggestionParser mSuggestionParser;
- public DashboardAdapter(Context context, SuggestionParser parser) {
+ public DashboardAdapter(Context context, SuggestionParser parser, Bundle savedInstanceState,
+ List<Condition> conditions) {
mContext = context;
mCache = new IconCache(context);
mSuggestionParser = parser;
+ mConditions = conditions;
setHasStableIds(true);
- setShowingAll(true);
+
+ boolean showAll = true;
+ if (savedInstanceState != null) {
+ mSuggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
+ mCategories = savedInstanceState.getParcelableArrayList(STATE_CATEGORY_LIST);
+ showAll = savedInstanceState.getBoolean(STATE_IS_SHOWING_ALL, true);
+ mSuggestionMode = savedInstanceState.getInt(
+ STATE_SUGGESTION_MODE, SUGGESTION_MODE_DEFAULT);
+ }
+ setShowingAll(showAll);
}
public List<Tile> getSuggestions() {
return mSuggestions;
}
- public void setSuggestions(List<Tile> suggestions) {
+ public void setCategoriesAndSuggestions(List<DashboardCategory> categories,
+ List<Tile> suggestions) {
mSuggestions = suggestions;
- recountItems();
- }
-
- public Tile getTile(ComponentName component) {
- for (int i = 0; i < mCategories.size(); i++) {
- for (int j = 0; j < mCategories.get(i).tiles.size(); j++) {
- Tile tile = mCategories.get(i).tiles.get(j);
- if (component.equals(tile.intent.getComponent())) {
- return tile;
- }
- }
- }
- return null;
- }
-
- public void setCategories(List<DashboardCategory> categories) {
mCategories = categories;
// TODO: Better place for tinting?
@@ -163,16 +164,12 @@
countItem(null, R.layout.suggestion_header, hasSuggestions, NS_SPACER);
resetCount();
if (mSuggestions != null) {
- int maxSuggestions = mSuggestionMode == SUGGESTION_MODE_DEFAULT
- ? Math.min(DEFAULT_SUGGESTION_COUNT, mSuggestions.size())
- : mSuggestionMode == SUGGESTION_MODE_EXPANDED ? mSuggestions.size()
- : 0;
+ int maxSuggestions = getDisplayableSuggestionCount();
for (int i = 0; i < mSuggestions.size(); i++) {
countItem(mSuggestions.get(i), R.layout.suggestion_tile, i < maxSuggestions,
NS_SUGGESTION);
}
}
- countItem(null, R.layout.dashboard_spacer, true, NS_SPACER);
resetCount();
for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
DashboardCategory category = mCategories.get(i);
@@ -208,6 +205,14 @@
mId++;
}
+ private int getDisplayableSuggestionCount() {
+ final int suggestionSize = mSuggestions.size();
+ return mSuggestionMode == SUGGESTION_MODE_DEFAULT
+ ? Math.min(DEFAULT_SUGGESTION_COUNT, suggestionSize)
+ : mSuggestionMode == SUGGESTION_MODE_EXPANDED
+ ? suggestionSize : 0;
+ }
+
@Override
public DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new DashboardItemHolder(LayoutInflater.from(parent.getContext()).inflate(
@@ -296,9 +301,28 @@
}
private void onBindSuggestionHeader(final DashboardItemHolder holder) {
- holder.icon.setImageResource(hasMoreSuggestions() ? R.drawable.ic_expand_more
+ final boolean moreSuggestions = hasMoreSuggestions();
+ final int undisplayedSuggestionCount =
+ mSuggestions.size() - getDisplayableSuggestionCount();
+ holder.icon.setImageResource(moreSuggestions ? R.drawable.ic_expand_more
: R.drawable.ic_expand_less);
holder.title.setText(mContext.getString(R.string.suggestions_title, mSuggestions.size()));
+ String summaryContentDescription;
+ if (moreSuggestions) {
+ summaryContentDescription = mContext.getResources().getQuantityString(
+ R.plurals.settings_suggestion_header_summary_hidden_items,
+ undisplayedSuggestionCount, undisplayedSuggestionCount);
+ } else {
+ summaryContentDescription = mContext.getString(R.string.condition_expand_hide);
+ }
+ holder.summary.setContentDescription(summaryContentDescription);
+
+ if (undisplayedSuggestionCount == 0) {
+ holder.summary.setText(null);
+ } else {
+ holder.summary.setText(
+ mContext.getString(R.string.suggestions_summary, undisplayedSuggestionCount));
+ }
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -409,6 +433,19 @@
return packageName;
}
+ void onSaveInstanceState(Bundle outState) {
+ if (mSuggestions != null) {
+ outState.putParcelableArrayList(STATE_SUGGESTION_LIST,
+ new ArrayList<Tile>(mSuggestions));
+ }
+ if (mCategories != null) {
+ outState.putParcelableArrayList(STATE_CATEGORY_LIST,
+ new ArrayList<DashboardCategory>(mCategories));
+ }
+ outState.putBoolean(STATE_IS_SHOWING_ALL, mIsShowingAll);
+ outState.putInt(STATE_SUGGESTION_MODE, mSuggestionMode);
+ }
+
private static class IconCache {
private final Context mContext;
diff --git a/src/com/android/settings/dashboard/DashboardContainerFragment.java b/src/com/android/settings/dashboard/DashboardContainerFragment.java
new file mode 100644
index 0000000..cd42f7d
--- /dev/null
+++ b/src/com/android/settings/dashboard/DashboardContainerFragment.java
@@ -0,0 +1,191 @@
+/*
+ * 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.dashboard;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.overlay.SupportFeatureProvider;
+import com.android.settings.widget.RtlCompatibleViewPager;
+import com.android.settings.widget.SlidingTabLayout;
+import com.android.settingslib.drawer.SettingsDrawerActivity;
+
+/**
+ * Container for Dashboard fragments.
+ */
+public final class DashboardContainerFragment extends InstrumentedFragment {
+
+ public static final String EXTRA_SELECT_SETTINGS_TAB = ":settings:select_settings_tab";
+
+ private static final String ARG_SUPPORT_TAB = "SUPPORT";
+ private static final String ARG_SUMMARY_TAB = "SUMMARY";
+ private static final int INDEX_SUMMARY_FRAGMENT = 0;
+ private static final int INDEX_SUPPORT_FRAGMENT = 1;
+
+ private RtlCompatibleViewPager mViewPager;
+ private View mHeaderView;
+ private DashboardViewPagerAdapter mPagerAdapter;
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.DASHBOARD_CONTAINER;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+ final View content = inflater.inflate(R.layout.dashboard_container, parent, false);
+ mViewPager = (RtlCompatibleViewPager) content.findViewById(R.id.pager);
+ mPagerAdapter = new DashboardViewPagerAdapter(getContext(),
+ getChildFragmentManager(), mViewPager);
+ mViewPager.setAdapter(mPagerAdapter);
+ mViewPager.addOnPageChangeListener(
+ new TabChangeListener((SettingsActivity) getActivity()));
+
+ // check if support tab needs to be selected
+ final String selectedTab = getArguments().
+ getString(EXTRA_SELECT_SETTINGS_TAB, ARG_SUMMARY_TAB);
+ if (TextUtils.equals(selectedTab, ARG_SUPPORT_TAB)) {
+ mViewPager.setCurrentItem(INDEX_SUPPORT_FRAGMENT);
+ } else {
+ mViewPager.setCurrentItem(INDEX_SUMMARY_FRAGMENT);
+ }
+
+ mHeaderView = inflater.inflate(R.layout.dashboard_container_header, parent, false);
+ ((SlidingTabLayout) mHeaderView).setViewPager(mViewPager);
+ return content;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mPagerAdapter.getCount() > 1) {
+ final Activity activity = getActivity();
+ if (activity instanceof SettingsDrawerActivity) {
+ ((SettingsDrawerActivity) getActivity()).setContentHeaderView(mHeaderView);
+ }
+ }
+ }
+
+ private static final class DashboardViewPagerAdapter extends FragmentPagerAdapter {
+
+ private final Context mContext;
+ private final SupportFeatureProvider mSupportFeatureProvider;
+ private final RtlCompatibleViewPager mViewPager;
+
+ public DashboardViewPagerAdapter(Context context, FragmentManager fragmentManager,
+ RtlCompatibleViewPager viewPager) {
+ super(fragmentManager);
+ mContext = context;
+ mSupportFeatureProvider =
+ FeatureFactory.getFactory(context).getSupportFeatureProvider(context);
+ mViewPager = viewPager;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ switch (position) {
+ case INDEX_SUMMARY_FRAGMENT:
+ return mContext.getString(R.string.page_tab_title_summary);
+ case INDEX_SUPPORT_FRAGMENT:
+ return mContext.getString(R.string.page_tab_title_support);
+ }
+ return super.getPageTitle(position);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ switch (position) {
+ case INDEX_SUMMARY_FRAGMENT:
+ return new DashboardSummary();
+ case INDEX_SUPPORT_FRAGMENT:
+ return new SupportFragment();
+ default:
+ throw new IllegalArgumentException(
+ String.format(
+ "Position %d does not map to a valid dashboard fragment",
+ position));
+ }
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ return super.instantiateItem(container,
+ mViewPager.getRtlAwareIndex(position));
+ }
+
+ @Override
+ public int getCount() {
+ return mSupportFeatureProvider == null ? 1 : 2;
+ }
+ }
+
+ private static final class TabChangeListener
+ implements RtlCompatibleViewPager.OnPageChangeListener {
+
+ private final SettingsActivity mActivity;
+
+ public TabChangeListener(SettingsActivity activity) {
+ mActivity = activity;
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ // Do nothing
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ switch (position) {
+ case INDEX_SUMMARY_FRAGMENT:
+ MetricsLogger.action(
+ mActivity, MetricsProto.MetricsEvent.ACTION_SELECT_SUMMARY);
+ mActivity.setDisplaySearchMenu(true);
+ break;
+ case INDEX_SUPPORT_FRAGMENT:
+ MetricsLogger.action(
+ mActivity, MetricsProto.MetricsEvent.ACTION_SELECT_SUPPORT_FRAGMENT);
+ mActivity.setDisplaySearchMenu(false);
+ break;
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index a53f41b..e10bbdc 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -16,16 +16,16 @@
package com.android.settings.dashboard;
+import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.InstrumentedFragment;
@@ -42,6 +42,7 @@
import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.settingslib.drawer.Tile;
+import java.util.ArrayList;
import java.util.List;
public class DashboardSummary extends InstrumentedFragment
@@ -63,6 +64,8 @@
private static final String SUGGESTIONS = "suggestions";
private static final String EXTRA_SCROLL_POSITION = "scroll_position";
+ private static final String EXTRA_SUGGESTION_SHOWN_LOGGED = "suggestions_shown_logged";
+ private static final String EXTRA_SUGGESTION_HIDDEN_LOGGED = "suggestions_hidden_logged";
private FocusRecyclerView mDashboard;
private DashboardAdapter mAdapter;
@@ -71,6 +74,8 @@
private SuggestionParser mSuggestionParser;
private LinearLayoutManager mLayoutManager;
private SuggestionsChecks mSuggestionsChecks;
+ private ArrayList<String> mSuggestionsShownLogged;
+ private ArrayList<String> mSuggestionsHiddenLogged;
@Override
protected int getMetricsCategory() {
@@ -85,12 +90,20 @@
List<DashboardCategory> categories =
((SettingsActivity) getActivity()).getDashboardCategories();
mSummaryLoader = new SummaryLoader(getActivity(), categories);
- setHasOptionsMenu(true);
Context context = getContext();
mConditionManager = ConditionManager.get(context, false);
mSuggestionParser = new SuggestionParser(context,
context.getSharedPreferences(SUGGESTIONS, 0), R.xml.suggestion_ordering);
mSuggestionsChecks = new SuggestionsChecks(getContext());
+ if (savedInstanceState == null) {
+ mSuggestionsShownLogged = new ArrayList<>();
+ mSuggestionsHiddenLogged = new ArrayList<>();
+ } else {
+ mSuggestionsShownLogged =
+ savedInstanceState.getStringArrayList(EXTRA_SUGGESTION_SHOWN_LOGGED);
+ mSuggestionsHiddenLogged =
+ savedInstanceState.getStringArrayList(EXTRA_SUGGESTION_HIDDEN_LOGGED);
+ }
if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+ " ms");
}
@@ -102,17 +115,9 @@
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- if (getActivity() == null) return;
- HelpUtils.prepareHelpMenuItem(getActivity(), menu, R.string.help_uri_dashboard,
- getClass().getName());
- }
-
- @Override
- public void onStart() {
+ public void onResume() {
long startTime = System.currentTimeMillis();
- super.onStart();
+ super.onResume();
((SettingsDrawerActivity) getActivity()).addCategoryListener(this);
mSummaryLoader.setListening(true);
@@ -121,19 +126,13 @@
MetricsLogger.visible(getContext(), c.getMetricsConstant());
}
}
- if (mAdapter.getSuggestions() != null) {
- for (Tile suggestion : mAdapter.getSuggestions()) {
- MetricsLogger.action(getContext(), MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION,
- DashboardAdapter.getSuggestionIdentifier(getContext(), suggestion));
- }
- }
- if (DEBUG_TIMING) Log.d(TAG, "onStart took " + (System.currentTimeMillis() - startTime)
+ if (DEBUG_TIMING) Log.d(TAG, "onResume took " + (System.currentTimeMillis() - startTime)
+ " ms");
}
@Override
- public void onStop() {
- super.onStop();
+ public void onPause() {
+ super.onPause();
((SettingsDrawerActivity) getActivity()).remCategoryListener(this);
mSummaryLoader.setListening(false);
@@ -145,9 +144,15 @@
if (mAdapter.getSuggestions() == null) {
return;
}
- for (Tile suggestion : mAdapter.getSuggestions()) {
- MetricsLogger.action(getContext(), MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION,
- DashboardAdapter.getSuggestionIdentifier(getContext(), suggestion));
+ if (!getActivity().isChangingConfigurations()) {
+ for (Tile suggestion : mAdapter.getSuggestions()) {
+ String id = DashboardAdapter.getSuggestionIdentifier(getContext(), suggestion);
+ if (!mSuggestionsHiddenLogged.contains(id)) {
+ mSuggestionsHiddenLogged.add(id);
+ MetricsLogger.action(getContext(),
+ MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, id);
+ }
+ }
}
}
@@ -173,8 +178,13 @@
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
+ outState.putStringArrayList(EXTRA_SUGGESTION_HIDDEN_LOGGED, mSuggestionsHiddenLogged);
+ outState.putStringArrayList(EXTRA_SUGGESTION_SHOWN_LOGGED, mSuggestionsShownLogged);
if (mLayoutManager == null) return;
outState.putInt(EXTRA_SCROLL_POSITION, mLayoutManager.findFirstVisibleItemPosition());
+ if (mAdapter != null) {
+ mAdapter.onSaveInstanceState(outState);
+ }
}
@Override
@@ -191,14 +201,13 @@
mDashboard.setHasFixedSize(true);
mDashboard.setListener(this);
mDashboard.addItemDecoration(new DashboardDecorator(getContext()));
- mAdapter = new DashboardAdapter(getContext(), mSuggestionParser);
- mAdapter.setConditions(mConditionManager.getConditions());
+ mAdapter = new DashboardAdapter(getContext(), mSuggestionParser, bundle,
+ mConditionManager.getConditions());
mDashboard.setAdapter(mAdapter);
mSummaryLoader.setAdapter(mAdapter);
ConditionAdapterUtils.addDismiss(mDashboard);
if (DEBUG_TIMING) Log.d(TAG, "onViewCreated took "
+ (System.currentTimeMillis() - startTime) + " ms");
-
rebuildUI();
}
@@ -208,10 +217,6 @@
return;
}
- List<DashboardCategory> categories =
- ((SettingsActivity) getActivity()).getDashboardCategories();
- mAdapter.setCategories(categories);
-
// recheck to see if any suggestions have been changed.
new SuggestionLoader().execute();
}
@@ -231,11 +236,20 @@
@Override
protected List<Tile> doInBackground(Void... params) {
+ final Context context = getContext();
List<Tile> suggestions = mSuggestionParser.getSuggestions();
for (int i = 0; i < suggestions.size(); i++) {
- if (mSuggestionsChecks.isSuggestionComplete(suggestions.get(i))) {
- mAdapter.disableSuggestion(suggestions.get(i));
+ Tile suggestion = suggestions.get(i);
+ if (mSuggestionsChecks.isSuggestionComplete(suggestion)) {
+ mAdapter.disableSuggestion(suggestion);
suggestions.remove(i--);
+ } else if (context != null) {
+ String id = DashboardAdapter.getSuggestionIdentifier(context, suggestion);
+ if (!mSuggestionsShownLogged.contains(id)) {
+ mSuggestionsShownLogged.add(id);
+ MetricsLogger.action(context,
+ MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, id);
+ }
}
}
return suggestions;
@@ -243,7 +257,13 @@
@Override
protected void onPostExecute(List<Tile> tiles) {
- mAdapter.setSuggestions(tiles);
+ final Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+ List<DashboardCategory> categories =
+ ((SettingsActivity) activity).getDashboardCategories();
+ mAdapter.setCategoriesAndSuggestions(categories, tiles);
}
}
}
diff --git a/src/com/android/settings/dashboard/SuggestionsChecks.java b/src/com/android/settings/dashboard/SuggestionsChecks.java
index 0ce82ad..b816a79 100644
--- a/src/com/android/settings/dashboard/SuggestionsChecks.java
+++ b/src/com/android/settings/dashboard/SuggestionsChecks.java
@@ -21,6 +21,7 @@
import android.app.KeyguardManager;
import android.app.NotificationManager;
import android.app.WallpaperManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
@@ -32,9 +33,9 @@
import com.android.settings.Settings.FingerprintEnrollSuggestionActivity;
import com.android.settings.Settings.FingerprintSuggestionActivity;
import com.android.settings.Settings.ScreenLockSuggestionActivity;
-import com.android.settings.Settings.WallpaperSuggestionActivity;
import com.android.settings.Settings.WifiCallingSuggestionActivity;
import com.android.settings.Settings.ZenModeAutomationSuggestionActivity;
+import com.android.settings.WallpaperSuggestionActivity;
import com.android.settingslib.drawer.Tile;
import java.util.Collection;
@@ -59,10 +60,11 @@
} else if (className.equals(WifiCallingSuggestionActivity.class.getName())) {
return isWifiCallingUnavailableOrEnabled();
} else if (className.equals(FingerprintSuggestionActivity.class.getName())) {
- return isNotSingleFingerprintEnrolled();
- } else if (className.equals(ScreenLockSuggestionActivity.class.getName())
- || className.equals(FingerprintEnrollSuggestionActivity.class.getName())) {
+ return isNotSingleFingerprintEnrolled() || !isFingerprintEnabled();
+ } else if (className.equals(ScreenLockSuggestionActivity.class.getName())) {
return isDeviceSecured();
+ } else if (className.equals(FingerprintEnrollSuggestionActivity.class.getName())) {
+ return isDeviceSecured() || !isFingerprintEnabled();
}
return false;
}
@@ -78,7 +80,8 @@
}
public boolean isWifiCallingUnavailableOrEnabled() {
- if (!ImsManager.isWfcEnabledByPlatform(mContext)) {
+ if (!ImsManager.isWfcEnabledByPlatform(mContext) ||
+ !ImsManager.isWfcProvisionedOnDevice(mContext)) {
return true;
}
return ImsManager.isWfcEnabledByUser(mContext)
@@ -100,13 +103,22 @@
IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
IWallpaperManager service = Stub.asInterface(b);
try {
- return service.getWallpaper(mCallback, WallpaperManager.FLAG_SYSTEM,
- new Bundle(), mContext.getUserId()) != null;
+ return !service.isSetWallpaperAllowed(mContext.getOpPackageName()) ||
+ service.getWallpaper(mCallback, WallpaperManager.FLAG_SYSTEM,
+ new Bundle(), mContext.getUserId()) != null;
} catch (RemoteException e) {
}
return false;
}
+ private boolean isFingerprintEnabled() {
+ DevicePolicyManager dpManager =
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ final int dpmFlags = dpManager.getKeyguardDisabledFeatures(null, /* admin */
+ mContext.getUserId());
+ return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) == 0;
+ }
+
private final IWallpaperManagerCallback mCallback = new IWallpaperManagerCallback.Stub() {
@Override
public void onWallpaperChanged() throws RemoteException {
diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java
index 778d620..4232852 100644
--- a/src/com/android/settings/dashboard/SummaryLoader.java
+++ b/src/com/android/settings/dashboard/SummaryLoader.java
@@ -28,8 +28,10 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+
import com.android.settings.SettingsActivity;
import com.android.settingslib.drawer.DashboardCategory;
+import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.settingslib.drawer.Tile;
import java.lang.reflect.Field;
@@ -87,9 +89,24 @@
public void run() {
// Since tiles are not always cached (like on locale change for instance),
// we need to always get the latest one.
- Tile tile = mAdapter.getTile(component);
- if (tile == null) return;
- if (DEBUG) Log.d(TAG, "setSummary " + tile.title + " - " + summary);
+ if (!(mActivity instanceof SettingsDrawerActivity)) {
+ if (DEBUG) {
+ Log.d(TAG, "Can't get category list.");
+ }
+ return;
+ }
+ final List<DashboardCategory> categories =
+ ((SettingsDrawerActivity) mActivity).getDashboardCategories();
+ final Tile tile = getTileFromCategory(categories, component);
+ if (tile == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Can't find tile for " + component);
+ }
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "setSummary " + tile.title + " - " + summary);
+ }
tile.summary = summary;
mAdapter.notifyChanged(tile);
}
@@ -187,6 +204,27 @@
}
}
+ private Tile getTileFromCategory(List<DashboardCategory> categories, ComponentName component) {
+ if (categories == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Category is null, can't find tile");
+ }
+ return null;
+ }
+ final int categorySize = categories.size();
+ for (int i = 0; i < categorySize; i++) {
+ final DashboardCategory category = categories.get(i);
+ final int tileCount = category.tiles.size();
+ for (int j = 0; j < tileCount; j++) {
+ final Tile tile = category.tiles.get(j);
+ if (component.equals(tile.intent.getComponent())) {
+ return tile;
+ }
+ }
+ }
+ return null;
+ }
+
public interface SummaryProvider {
void setListening(boolean listening);
}
diff --git a/src/com/android/settings/dashboard/SupportFragment.java b/src/com/android/settings/dashboard/SupportFragment.java
new file mode 100644
index 0000000..58f79a8
--- /dev/null
+++ b/src/com/android/settings/dashboard/SupportFragment.java
@@ -0,0 +1,167 @@
+/*
+ * 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.dashboard;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.OnAccountsUpdateListener;
+import android.app.Activity;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkRequest;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsProto;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.overlay.SupportFeatureProvider;
+
+/**
+ * Fragment for support tab in SettingsGoogle.
+ */
+public final class SupportFragment extends InstrumentedFragment implements View.OnClickListener,
+ OnAccountsUpdateListener {
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final ConnectivityManager.NetworkCallback mNetworkCallback =
+ new ConnectivityManager.NetworkCallback() {
+
+ @Override
+ public void onCapabilitiesChanged(Network network,
+ NetworkCapabilities capabilities) {
+ postConnectivityChanged();
+ }
+
+ @Override
+ public void onAvailable(Network network) {
+ postConnectivityChanged();
+ }
+
+ @Override
+ public void onLost(Network network) {
+ postConnectivityChanged();
+ }
+ };
+
+ private Activity mActivity;
+ private View mContent;
+ private RecyclerView mRecyclerView;
+ private SupportItemAdapter mSupportItemAdapter;
+ private AccountManager mAccountManager;
+ private SupportFeatureProvider mSupportFeatureProvider;
+ private ConnectivityManager mConnectivityManager;
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.SUPPORT_FRAGMENT;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mActivity = getActivity();
+ mAccountManager = AccountManager.get(mActivity);
+ mSupportFeatureProvider =
+ FeatureFactory.getFactory(mActivity).getSupportFeatureProvider(mActivity);
+ mSupportItemAdapter = new SupportItemAdapter(mActivity, savedInstanceState,
+ mSupportFeatureProvider, this /* itemClickListener */);
+ mConnectivityManager =
+ (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mContent = inflater.inflate(R.layout.support_fragment, container, false);
+ mRecyclerView = (RecyclerView) mContent.findViewById(R.id.support_items);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(
+ getActivity(), LinearLayoutManager.VERTICAL, false /* reverseLayout */));
+ mRecyclerView.setAdapter(mSupportItemAdapter);
+ return mContent;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Monitor account change.
+ mAccountManager.addOnAccountsUpdatedListener(
+ this /* listener */, null /* handler */, true /* updateImmediately */);
+ // Monitor connectivity
+ mConnectivityManager.registerNetworkCallback(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build(),
+ mNetworkCallback);
+ mSupportItemAdapter.setHasInternet(hasInternet());
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Stop monitor account change.
+ mAccountManager.removeOnAccountsUpdatedListener(this /* listener */);
+ // Stop monitor connectivity.
+ mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mSupportItemAdapter.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onAccountsUpdated(Account[] accounts) {
+ // Account changed, update support items.
+ mSupportItemAdapter.setAccount(
+ mSupportFeatureProvider.getSupportEligibleAccount(mActivity));
+ }
+
+ @Override
+ public void onClick(View v) {
+ final SupportItemAdapter.ViewHolder vh =
+ (SupportItemAdapter.ViewHolder) mRecyclerView.getChildViewHolder(v);
+ mSupportItemAdapter.onItemClicked(vh.getAdapterPosition());
+ }
+
+ private void postConnectivityChanged() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mSupportItemAdapter != null) {
+ mSupportItemAdapter.setHasInternet(hasInternet());
+ }
+ }
+ });
+ }
+
+ private boolean hasInternet() {
+ final NetworkInfo activeNetwork = mConnectivityManager.getActiveNetworkInfo();
+ return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
+ }
+}
diff --git a/src/com/android/settings/dashboard/SupportItemAdapter.java b/src/com/android/settings/dashboard/SupportItemAdapter.java
new file mode 100644
index 0000000..9ef69883
--- /dev/null
+++ b/src/com/android/settings/dashboard/SupportItemAdapter.java
@@ -0,0 +1,747 @@
+/*
+ * 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.dashboard;
+
+import android.accounts.Account;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
+import android.annotation.StringRes;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.overlay.SupportFeatureProvider;
+import com.android.settings.support.SupportDisclaimerDialogFragment;
+import com.android.settings.support.SupportPhone;
+import com.android.settings.support.SupportPhoneDialogFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import static com.android.settings.overlay.SupportFeatureProvider.SupportType.CHAT;
+import static com.android.settings.overlay.SupportFeatureProvider.SupportType.PHONE;
+
+/**
+ * Item adapter for support tiles.
+ */
+public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAdapter.ViewHolder> {
+
+ private static final String STATE_SELECTED_COUNTRY = "STATE_SELECTED_COUNTRY";
+ private static final int TYPE_ESCALATION_OPTIONS = R.layout.support_escalation_options;
+ private static final int TYPE_ESCALATION_OPTIONS_OFFLINE =
+ R.layout.support_offline_escalation_options;
+ private static final int TYPE_SUPPORT_TILE = R.layout.support_tile;
+ private static final int TYPE_SUPPORT_TILE_SPACER = R.layout.support_tile_spacer;
+ private static final int TYPE_SIGN_IN_BUTTON = R.layout.support_sign_in_button;
+
+ private final Activity mActivity;
+ private final EscalationClickListener mEscalationClickListener;
+ private final SpinnerItemSelectListener mSpinnerItemSelectListener;
+ private final SupportFeatureProvider mSupportFeatureProvider;
+ private final View.OnClickListener mItemClickListener;
+ private final List<SupportData> mSupportData;
+
+ private String mSelectedCountry;
+ private boolean mHasInternet;
+ private Account mAccount;
+
+ public SupportItemAdapter(Activity activity, Bundle savedInstanceState,
+ SupportFeatureProvider supportFeatureProvider, View.OnClickListener itemClickListener) {
+ mActivity = activity;
+ mSupportFeatureProvider = supportFeatureProvider;
+ mItemClickListener = itemClickListener;
+ mEscalationClickListener = new EscalationClickListener();
+ mSpinnerItemSelectListener = new SpinnerItemSelectListener();
+ mSupportData = new ArrayList<>();
+ // Optimistically assume we have Internet access. It will be updated later to correct value.
+ mHasInternet = true;
+ if (savedInstanceState != null) {
+ mSelectedCountry = savedInstanceState.getString(STATE_SELECTED_COUNTRY);
+ } else {
+ mSelectedCountry = mSupportFeatureProvider.getCurrentCountryCodeIfHasConfig(PHONE);
+ }
+ mAccount = mSupportFeatureProvider.getSupportEligibleAccount(mActivity);
+ refreshData();
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(
+ viewType, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ final SupportData data = mSupportData.get(position);
+ switch (holder.getItemViewType()) {
+ case TYPE_SIGN_IN_BUTTON:
+ bindSignInPromoTile(holder, (EscalationData) data);
+ break;
+ case TYPE_ESCALATION_OPTIONS:
+ bindEscalationOptions(holder, (EscalationData) data);
+ break;
+ case TYPE_ESCALATION_OPTIONS_OFFLINE:
+ bindOfflineEscalationOptions(holder, (OfflineEscalationData) data);
+ break;
+ case TYPE_SUPPORT_TILE_SPACER:
+ break;
+ default:
+ bindSupportTile(holder, data);
+ break;
+ }
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mSupportData.get(position).type;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mSupportData.size();
+ }
+
+ /**
+ * Called when a support item is clicked.
+ */
+ public void onItemClicked(int position) {
+ if (position >= 0 && position < mSupportData.size()) {
+ final SupportData data = mSupportData.get(position);
+ if (data.intent != null &&
+ mActivity.getPackageManager().resolveActivity(data.intent, 0) != null) {
+ if (data.metricsEvent >= 0) {
+ MetricsLogger.action(mActivity, data.metricsEvent);
+ }
+ mActivity.startActivityForResult(data.intent, 0);
+ }
+ }
+ }
+
+ public void setHasInternet(boolean hasInternet) {
+ if (mHasInternet != hasInternet) {
+ mHasInternet = hasInternet;
+ refreshEscalationCards();
+ }
+ }
+
+ public void setAccount(Account account) {
+ if (!Objects.equals(mAccount, account)) {
+ mAccount = account;
+ mSupportFeatureProvider.refreshOperationRules();
+ refreshEscalationCards();
+ }
+ }
+
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putString(STATE_SELECTED_COUNTRY, mSelectedCountry);
+ }
+
+ /**
+ * Create data for the adapter. If there is already data in the adapter, they will be
+ * destroyed and recreated.
+ */
+ private void refreshData() {
+ mSupportData.clear();
+ addEscalationCards();
+ addMoreHelpItems();
+ notifyDataSetChanged();
+ }
+
+ /**
+ * Adds 1 escalation card. Based on current phone state, the escalation card can display
+ * different content.
+ */
+ private void addEscalationCards() {
+ if (mAccount == null) {
+ addSignInPromo();
+ } else if (mHasInternet) {
+ addOnlineEscalationCards();
+ } else {
+ addOfflineEscalationCards();
+ }
+ }
+
+ /**
+ * Finds and refreshes escalation card data.
+ */
+ private void refreshEscalationCards() {
+ if (getItemCount() > 0) {
+ final int itemType = getItemViewType(0 /* position */);
+ if (itemType == TYPE_SIGN_IN_BUTTON
+ || itemType == TYPE_ESCALATION_OPTIONS
+ || itemType == TYPE_ESCALATION_OPTIONS_OFFLINE) {
+ mSupportData.remove(0 /* position */);
+ addEscalationCards();
+ notifyItemChanged(0 /* position */);
+ }
+ }
+ }
+
+ private void addOnlineEscalationCards() {
+ final boolean hasPhoneOperation =
+ mSupportFeatureProvider.isSupportTypeEnabled(mActivity, PHONE);
+ final boolean hasChatOperation =
+ mSupportFeatureProvider.isSupportTypeEnabled(mActivity, CHAT);
+ final EscalationData.Builder builder = new EscalationData.Builder(mActivity);
+ if (!hasPhoneOperation && !hasChatOperation) {
+ // No support at all.
+ builder.setTileTitle(R.string.support_escalation_title)
+ .setTileSummary(R.string.support_escalation_unavailable_summary);
+ } else if (mSupportFeatureProvider.isAlwaysOperating(PHONE, null /* countryCode */)
+ || mSupportFeatureProvider.isAlwaysOperating(CHAT, null /* countryCode */)) {
+ // Support is available.
+ builder.setTileTitle(R.string.support_escalation_24_7_title)
+ .setTileTitleDescription(R.string.support_escalation_24_7_content_description)
+ .setTileSummary(mActivity.getString(R.string.support_escalation_24_7_summary));
+ } else if (mSupportFeatureProvider.isOperatingNow(PHONE)
+ || mSupportFeatureProvider.isOperatingNow(CHAT)) {
+ // Support is available now.
+ builder.setTileTitle(R.string.support_escalation_title)
+ .setTileSummary(R.string.support_escalation_summary);
+ } else {
+ // Support is now temporarily unavailable.
+ builder.setTileTitle(R.string.support_escalation_title)
+ .setTileSummary(
+ mSupportFeatureProvider.getOperationHours(mActivity, PHONE, null,
+ true /* hasInternet */));
+ }
+ if (hasPhoneOperation) {
+ builder.setText1(R.string.support_escalation_by_phone)
+ .setSummary1(mSupportFeatureProvider.getEstimatedWaitTime(mActivity, PHONE))
+ .setEnabled1(mSupportFeatureProvider.isOperatingNow(PHONE));
+ }
+ if (hasChatOperation) {
+ builder.setText2(R.string.support_escalation_by_chat)
+ .setSummary2(mSupportFeatureProvider.getEstimatedWaitTime(mActivity, CHAT))
+ .setEnabled2(mSupportFeatureProvider.isOperatingNow(CHAT));
+ }
+ mSupportData.add(0 /* index */, builder.build());
+ }
+
+ private void addOfflineEscalationCards() {
+ final CharSequence operatingHours;
+ final boolean isPhoneSupportAlwaysOperating =
+ mSupportFeatureProvider.isAlwaysOperating(PHONE, mSelectedCountry);
+ if (isPhoneSupportAlwaysOperating) {
+ operatingHours = mActivity.getString(R.string.support_escalation_24_7_summary);
+ } else {
+ operatingHours = mSupportFeatureProvider.getOperationHours(mActivity,
+ PHONE, mSelectedCountry, false /* hasInternet */);
+ }
+ mSupportData.add(0 /* index */, new OfflineEscalationData.Builder(mActivity)
+ .setCountries(mSupportFeatureProvider.getPhoneSupportCountries())
+ .setTollFreePhone(mSupportFeatureProvider.getSupportPhones(
+ mSelectedCountry, true /* isTollFree */))
+ .setTolledPhone(mSupportFeatureProvider.getSupportPhones(
+ mSelectedCountry, false /* isTollFree */))
+ .setTileTitle(isPhoneSupportAlwaysOperating
+ ? R.string.support_escalation_24_7_title
+ : R.string.support_escalation_title)
+ .setTileTitleDescription(isPhoneSupportAlwaysOperating
+ ? R.string.support_escalation_24_7_content_description
+ : R.string.support_escalation_title)
+ .setTileSummary(operatingHours)
+ .build());
+ }
+
+ private void addSignInPromo() {
+ mSupportData.add(0 /* index */, new EscalationData.Builder(mActivity, TYPE_SIGN_IN_BUTTON)
+ .setText1(R.string.support_sign_in_button_text)
+ .setText2(R.string.support_sign_in_required_help)
+ .setTileTitle(R.string.support_sign_in_required_title)
+ .setTileSummary(R.string.support_sign_in_required_summary)
+ .build());
+ }
+
+ private void addMoreHelpItems() {
+ mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE_SPACER).build());
+ PackageManager packageManager = mActivity.getPackageManager();
+ Intent intent = mSupportFeatureProvider.getHelpIntent(mActivity);
+ if (packageManager.resolveActivity(intent, 0) != null) {
+ mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE)
+ .setIcon(R.drawable.ic_help_24dp)
+ .setTileTitle(R.string.support_help_feedback_title)
+ .setIntent(intent)
+ .setMetricsEvent(MetricsProto.MetricsEvent.ACTION_SUPPORT_HELP_AND_FEEDBACK)
+ .build());
+ }
+ intent = mSupportFeatureProvider.getTipsAndTricksIntent(mActivity);
+ if (packageManager.resolveActivity(intent, 0) != null) {
+ mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE)
+ .setIcon(R.drawable.ic_lightbulb_outline_24)
+ .setTileTitle(R.string.support_tips_and_tricks_title)
+ .setIntent(intent)
+ .setMetricsEvent(MetricsProto.MetricsEvent.ACTION_SUPPORT_TIPS_AND_TRICKS)
+ .build());
+ }
+ }
+
+ private void bindEscalationOptions(ViewHolder holder, EscalationData data) {
+ holder.tileTitleView.setText(data.tileTitle);
+ holder.tileTitleView.setContentDescription(data.tileTitleDescription);
+ holder.tileSummaryView.setText(data.tileSummary);
+ if (data.text1 == 0) {
+ holder.text1View.setVisibility(View.GONE);
+ } else {
+ holder.text1View.setText(data.text1);
+ holder.text1View.setOnClickListener(mEscalationClickListener);
+ holder.text1View.setEnabled(data.enabled1 && mHasInternet);
+ holder.text1View.setVisibility(View.VISIBLE);
+ }
+ if (TextUtils.isEmpty(data.text2)) {
+ holder.text2View.setVisibility(View.GONE);
+ } else {
+ holder.text2View.setText(data.text2);
+ holder.text2View.setOnClickListener(mEscalationClickListener);
+ holder.text2View.setEnabled(data.enabled2 && mHasInternet);
+ holder.text2View.setVisibility(View.VISIBLE);
+ }
+ if (holder.summary1View != null) {
+ holder.summary1View.setText(data.summary1);
+ holder.summary1View.setVisibility(mHasInternet && !TextUtils.isEmpty(data.summary1)
+ ? View.VISIBLE : View.GONE);
+ }
+ if (holder.summary2View != null) {
+ holder.summary2View.setText(data.summary2);
+ holder.summary2View.setVisibility(mHasInternet && !TextUtils.isEmpty(data.summary2)
+ ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ private void bindOfflineEscalationOptions(ViewHolder holder, OfflineEscalationData data) {
+ // Bind Title
+ holder.tileTitleView.setText(data.tileTitle);
+ holder.tileTitleView.setContentDescription(data.tileTitleDescription);
+ holder.tileSummaryView.setText(data.tileSummary);
+ // Bind spinner
+ final Spinner spinner = (Spinner) holder.itemView.findViewById(R.id.spinner);
+ final ArrayAdapter<String> adapter = new ArrayAdapter(
+ mActivity, android.R.layout.simple_spinner_dropdown_item, data.countries);
+ spinner.setAdapter(adapter);
+ final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes();
+ for (int i = 0; i < countryCodes.size(); i++) {
+ if (TextUtils.equals(countryCodes.get(i), mSelectedCountry)) {
+ spinner.setSelection(i);
+ break;
+ }
+ }
+ spinner.setOnItemSelectedListener(mSpinnerItemSelectListener);
+ // Bind buttons
+ if (data.tollFreePhone != null) {
+ holder.text1View.setText(data.tollFreePhone.number);
+ holder.text1View.setVisibility(View.VISIBLE);
+ holder.text1View.setOnClickListener(mEscalationClickListener);
+ } else {
+ holder.text1View.setVisibility(View.GONE);
+ }
+ if (data.tolledPhone != null) {
+ holder.text2View.setText(
+ mActivity.getString(R.string.support_international_phone_title));
+ holder.text2View.setVisibility(View.VISIBLE);
+ holder.text2View.setOnClickListener(mEscalationClickListener);
+ } else {
+ holder.text2View.setVisibility(View.GONE);
+ }
+
+ if (ActivityManager.isUserAMonkey()) {
+ holder.text1View.setVisibility(View.GONE);
+ holder.text2View.setVisibility(View.GONE);
+ spinner.setVisibility(View.GONE);
+ holder.itemView.findViewById(R.id.support_text).setVisibility(View.GONE);
+ }
+ }
+
+ private void bindSignInPromoTile(ViewHolder holder, EscalationData data) {
+ holder.tileTitleView.setText(data.tileTitle);
+ holder.tileTitleView.setContentDescription(data.tileTitleDescription);
+ holder.tileSummaryView.setText(data.tileSummary);
+ holder.text1View.setText(data.text1);
+ holder.text2View.setText(data.text2);
+ holder.text1View.setOnClickListener(mEscalationClickListener);
+ holder.text2View.setOnClickListener(mEscalationClickListener);
+ }
+
+ private void bindSupportTile(ViewHolder holder, SupportData data) {
+ if (holder.iconView != null) {
+ holder.iconView.setImageResource(data.icon);
+ }
+ if (holder.tileTitleView != null) {
+ holder.tileTitleView.setText(data.tileTitle);
+ holder.tileTitleView.setContentDescription(data.tileTitleDescription);
+ }
+ if (holder.tileSummaryView != null) {
+ holder.tileSummaryView.setText(data.tileSummary);
+ }
+ holder.itemView.setOnClickListener(mItemClickListener);
+ }
+
+ /**
+ * Show a disclaimer dialog and start support action after disclaimer has been acknowledged.
+ */
+ private void tryStartDisclaimerAndSupport(final @SupportFeatureProvider.SupportType int type) {
+ if (mSupportFeatureProvider.shouldShowDisclaimerDialog(mActivity)) {
+ DialogFragment fragment = SupportDisclaimerDialogFragment.newInstance(mAccount, type);
+ fragment.show(mActivity.getFragmentManager(), SupportDisclaimerDialogFragment.TAG);
+ return;
+ }
+ mSupportFeatureProvider.startSupport(mActivity, mAccount, type);
+ }
+
+ /**
+ * Click handler for starting escalation options.
+ */
+ private final class EscalationClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(final View v) {
+ if (mAccount == null) {
+ switch (v.getId()) {
+ case android.R.id.text1:
+ MetricsLogger.action(mActivity,
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_SIGN_IN);
+ mActivity.startActivityForResult(
+ mSupportFeatureProvider.getAccountLoginIntent(),
+ 0 /* requestCode */);
+ break;
+ case android.R.id.text2:
+ mActivity.startActivityForResult(
+ mSupportFeatureProvider.getSignInHelpIntent(mActivity),
+ 0 /* requestCode */);
+ break;
+ }
+ } else if (mHasInternet) {
+ switch (v.getId()) {
+ case android.R.id.text1:
+ MetricsLogger.action(mActivity,
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_PHONE);
+ tryStartDisclaimerAndSupport(PHONE);
+ break;
+ case android.R.id.text2:
+ MetricsLogger.action(mActivity,
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_CHAT);
+ tryStartDisclaimerAndSupport(CHAT);
+ break;
+ }
+ } else {
+ switch (v.getId()) {
+ case android.R.id.text1: {
+ final SupportPhone phone = mSupportFeatureProvider
+ .getSupportPhones(mSelectedCountry, true /* isTollFree */);
+ if (phone != null) {
+ final Intent intent = phone.getDialIntent();
+ final boolean canDial = !mActivity.getPackageManager()
+ .queryIntentActivities(intent, 0)
+ .isEmpty();
+ if (canDial) {
+ MetricsLogger.action(mActivity,
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_DAIL_TOLLFREE);
+ mActivity.startActivity(intent);
+ }
+ }
+ break;
+ }
+ case android.R.id.text2: {
+ final SupportPhone phone = mSupportFeatureProvider
+ .getSupportPhones(mSelectedCountry, false /* isTollFree */);
+ final SupportPhoneDialogFragment fragment =
+ SupportPhoneDialogFragment.newInstance(phone);
+ MetricsLogger.action(mActivity,
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_VIEW_TRAVEL_ABROAD_DIALOG);
+ fragment.show(mActivity.getFragmentManager(),
+ SupportPhoneDialogFragment.TAG);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private final class SpinnerItemSelectListener implements AdapterView.OnItemSelectedListener {
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes();
+ final String selectedCountry = countryCodes.get(position);
+ if (!TextUtils.equals(selectedCountry, mSelectedCountry)) {
+ mSelectedCountry = selectedCountry;
+ refreshEscalationCards();
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // Do nothing.
+ }
+ }
+
+ /**
+ * {@link RecyclerView.ViewHolder} for support items.
+ */
+ static final class ViewHolder extends RecyclerView.ViewHolder {
+
+ final ImageView iconView;
+ final TextView tileTitleView;
+ final TextView tileSummaryView;
+ final TextView text1View;
+ final TextView text2View;
+ final TextView summary1View;
+ final TextView summary2View;
+
+ ViewHolder(View itemView) {
+ super(itemView);
+ iconView = (ImageView) itemView.findViewById(android.R.id.icon);
+ tileTitleView = (TextView) itemView.findViewById(R.id.tile_title);
+ tileSummaryView = (TextView) itemView.findViewById(R.id.tile_summary);
+ text1View = (TextView) itemView.findViewById(android.R.id.text1);
+ text2View = (TextView) itemView.findViewById(android.R.id.text2);
+ summary1View = (TextView) itemView.findViewById(R.id.summary1);
+ summary2View = (TextView) itemView.findViewById(R.id.summary2);
+ }
+ }
+
+ /**
+ * Data for a single support item.
+ */
+ private static class SupportData {
+
+ final Intent intent;
+ final int metricsEvent;
+ @LayoutRes
+ final int type;
+ @DrawableRes
+ final int icon;
+ @StringRes
+ final int tileTitle;
+ final CharSequence tileTitleDescription;
+ final CharSequence tileSummary;
+
+
+ private SupportData(Builder builder) {
+ this.type = builder.mType;
+ this.icon = builder.mIcon;
+ this.tileTitle = builder.mTileTitle;
+ this.tileTitleDescription = builder.mTileTitleDescription;
+ this.tileSummary = builder.mTileSummary;
+ this.intent = builder.mIntent;
+ this.metricsEvent = builder.mMetricsEvent;
+ }
+
+ static class Builder {
+
+ protected final Context mContext;
+ @LayoutRes
+ private final int mType;
+ @DrawableRes
+ private int mIcon;
+ @StringRes
+ private int mTileTitle;
+ private CharSequence mTileTitleDescription;
+ private CharSequence mTileSummary;
+ private Intent mIntent;
+ private int mMetricsEvent = -1;
+
+ Builder(Context context, @LayoutRes int type) {
+ mContext = context;
+ mType = type;
+ }
+
+ Builder setIcon(@DrawableRes int icon) {
+ mIcon = icon;
+ return this;
+ }
+
+ Builder setTileTitle(@StringRes int title) {
+ mTileTitle = title;
+ return this;
+ }
+
+ Builder setTileTitleDescription(@StringRes int titleDescription) {
+ mTileTitleDescription = mContext.getString(titleDescription);
+ return this;
+ }
+
+ Builder setTileSummary(@StringRes int summary) {
+ mTileSummary = mContext.getString(summary);
+ return this;
+ }
+
+ Builder setTileSummary(CharSequence summary) {
+ mTileSummary = summary;
+ return this;
+ }
+
+ Builder setMetricsEvent(int metricsEvent) {
+ mMetricsEvent = metricsEvent;
+ return this;
+ }
+
+ Builder setIntent(Intent intent) {
+ mIntent = intent;
+ return this;
+ }
+
+ SupportData build() {
+ return new SupportData(this);
+ }
+ }
+ }
+
+ /**
+ * Data model for escalation cards.
+ */
+ private static class EscalationData extends SupportData {
+
+ @StringRes
+ final int text1;
+ final CharSequence text2;
+ final boolean enabled1;
+ final boolean enabled2;
+ final CharSequence summary1;
+ final CharSequence summary2;
+
+ private EscalationData(Builder builder) {
+ super(builder);
+ this.text1 = builder.mText1;
+ this.text2 = builder.mText2;
+ this.summary1 = builder.mSummary1;
+ this.summary2 = builder.mSummary2;
+ this.enabled1 = builder.mEnabled1;
+ this.enabled2 = builder.mEnabled2;
+ }
+
+ static class Builder extends SupportData.Builder {
+
+ @StringRes
+ private int mText1;
+ private CharSequence mText2;
+ private CharSequence mSummary1;
+ private CharSequence mSummary2;
+ private boolean mEnabled1;
+ private boolean mEnabled2;
+
+ protected Builder(Context context, @LayoutRes int type) {
+ super(context, type);
+ }
+
+ Builder(Context context) {
+ this(context, TYPE_ESCALATION_OPTIONS);
+ }
+
+ Builder setEnabled1(boolean enabled) {
+ mEnabled1 = enabled;
+ return this;
+ }
+
+ Builder setText1(@StringRes int text1) {
+ mText1 = text1;
+ return this;
+ }
+
+ Builder setText2(@StringRes int text2) {
+ mText2 = mContext.getString(text2);
+ return this;
+ }
+
+ Builder setText2(CharSequence text2) {
+ mText2 = text2;
+ return this;
+ }
+
+ Builder setSummary1(String summary1) {
+ mSummary1 = summary1;
+ return this;
+ }
+
+ Builder setEnabled2(boolean enabled) {
+ mEnabled2 = enabled;
+ return this;
+ }
+
+ Builder setSummary2(String summary2) {
+ mSummary2 = summary2;
+ return this;
+ }
+
+ EscalationData build() {
+ return new EscalationData(this);
+ }
+ }
+ }
+
+ /**
+ * Support data for offline mode.
+ */
+ private static final class OfflineEscalationData extends EscalationData {
+
+ final List<String> countries;
+ final SupportPhone tollFreePhone;
+ final SupportPhone tolledPhone;
+
+ private OfflineEscalationData(Builder builder) {
+ super(builder);
+ countries = builder.mCountries;
+ tollFreePhone = builder.mTollFreePhone;
+ tolledPhone = builder.mTolledPhone;
+ }
+
+ static final class Builder extends EscalationData.Builder {
+
+ private List<String> mCountries;
+ private SupportPhone mTollFreePhone;
+ private SupportPhone mTolledPhone;
+
+ Builder(Context context) {
+ super(context, TYPE_ESCALATION_OPTIONS_OFFLINE);
+ }
+
+ Builder setCountries(List<String> countries) {
+ mCountries = countries;
+ return this;
+ }
+
+ Builder setTollFreePhone(SupportPhone phone) {
+ mTollFreePhone = phone;
+ return this;
+ }
+
+ Builder setTolledPhone(SupportPhone phone) {
+ mTolledPhone = phone;
+ return this;
+ }
+
+ OfflineEscalationData build() {
+ return new OfflineEscalationData(this);
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/Condition.java b/src/com/android/settings/dashboard/conditional/Condition.java
index 1d48d5d..0454fe8 100644
--- a/src/com/android/settings/dashboard/conditional/Condition.java
+++ b/src/com/android/settings/dashboard/conditional/Condition.java
@@ -23,6 +23,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import static android.content.pm.PackageManager.DONT_KILL_APP;
+
public abstract class Condition {
private static final String KEY_SILENCE = "silence";
@@ -38,6 +40,12 @@
// All conditions must live in this package.
Condition(ConditionManager manager) {
mManager = manager;
+ Class<?> receiverClass = getReceiverClass();
+ if (receiverClass != null && shouldAlwaysListenToBroadcast()) {
+ PackageManager pm = mManager.getContext().getPackageManager();
+ pm.setComponentEnabledSetting(new ComponentName(mManager.getContext(), receiverClass),
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
+ }
}
void restoreState(PersistableBundle bundle) {
@@ -93,6 +101,10 @@
}
private void onSilenceChanged(boolean silenced) {
+ if (shouldAlwaysListenToBroadcast()) {
+ // Don't try to disable BroadcastReceiver if we want it always on.
+ return;
+ }
Class<?> clz = getReceiverClass();
if (clz == null) {
return;
@@ -102,13 +114,17 @@
pm.setComponentEnabledSetting(new ComponentName(mManager.getContext(), clz),
silenced ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
+ DONT_KILL_APP);
}
protected Class<?> getReceiverClass() {
return null;
}
+ protected boolean shouldAlwaysListenToBroadcast() {
+ return false;
+ }
+
public boolean shouldShow() {
return isActive() && !isSilenced();
}
diff --git a/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
index 51fd132..a16de50 100644
--- a/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
+++ b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
@@ -68,12 +68,13 @@
card.setOnClickListener(onClickListener);
view.icon.setImageIcon(condition.getIcon());
view.title.setText(condition.getTitle());
- ImageView expand = (ImageView) view.itemView.findViewById(R.id.expand_indicator);
- expand.setTag(condition);
+ final View collapsedGroup = view.itemView.findViewById(R.id.collapsed_group);
+ collapsedGroup.setTag(condition);
+ final ImageView expand = (ImageView) view.itemView.findViewById(R.id.expand_indicator);
expand.setImageResource(isExpanded ? R.drawable.ic_expand_less : R.drawable.ic_expand_more);
expand.setContentDescription(expand.getContext().getString(isExpanded
? R.string.condition_expand_hide : R.string.condition_expand_show));
- expand.setOnClickListener(onExpandListener);
+ collapsedGroup.setOnClickListener(onExpandListener);
View detailGroup = view.itemView.findViewById(R.id.detail_group);
CharSequence[] actions = condition.getActions();
diff --git a/src/com/android/settings/dashboard/conditional/ConditionManager.java b/src/com/android/settings/dashboard/conditional/ConditionManager.java
index ad0e839..691821a 100644
--- a/src/com/android/settings/dashboard/conditional/ConditionManager.java
+++ b/src/com/android/settings/dashboard/conditional/ConditionManager.java
@@ -20,6 +20,7 @@
import android.os.PersistableBundle;
import android.util.Log;
import android.util.Xml;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -142,6 +143,7 @@
addIfMissing(CellularDataCondition.class, conditions);
addIfMissing(BackgroundDataCondition.class, conditions);
addIfMissing(WorkModeCondition.class, conditions);
+ addIfMissing(NightDisplayCondition.class, conditions);
Collections.sort(conditions, CONDITION_COMPARATOR);
}
@@ -167,6 +169,8 @@
return new BackgroundDataCondition(this);
} else if (WorkModeCondition.class == clz) {
return new WorkModeCondition(this);
+ } else if (NightDisplayCondition.class == clz) {
+ return new NightDisplayCondition(this);
}
throw new RuntimeException("Unexpected Condition " + clz);
}
@@ -238,10 +242,7 @@
protected void onPostExecute(ArrayList<Condition> conditions) {
mConditions.clear();
mConditions.addAll(conditions);
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- mListeners.get(i).onConditionsChanged();
- }
+ refreshAll();
}
}
diff --git a/src/com/android/settings/dashboard/conditional/DndCondition.java b/src/com/android/settings/dashboard/conditional/DndCondition.java
index 2a5aa8a..49d67c2 100644
--- a/src/com/android/settings/dashboard/conditional/DndCondition.java
+++ b/src/com/android/settings/dashboard/conditional/DndCondition.java
@@ -26,6 +26,7 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
+
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -138,9 +139,17 @@
public void onReceive(Context context, Intent intent) {
if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL
.equals(intent.getAction())) {
- ConditionManager.get(context).getCondition(DndCondition.class)
- .refreshState();
+ final Condition condition =
+ ConditionManager.get(context).getCondition(DndCondition.class);
+ if (condition != null) {
+ condition.refreshState();
+ }
}
}
}
+
+ @Override
+ protected boolean shouldAlwaysListenToBroadcast() {
+ return true;
+ }
}
diff --git a/src/com/android/settings/dashboard/conditional/NightDisplayCondition.java b/src/com/android/settings/dashboard/conditional/NightDisplayCondition.java
new file mode 100644
index 0000000..132a0a4
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/NightDisplayCondition.java
@@ -0,0 +1,87 @@
+/*
+ * 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.dashboard.conditional;
+
+import android.graphics.drawable.Icon;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.display.NightDisplaySettings;
+
+public final class NightDisplayCondition extends Condition
+ implements NightDisplayController.Callback {
+
+ private NightDisplayController mController;
+
+ NightDisplayCondition(ConditionManager manager) {
+ super(manager);
+ mController = new NightDisplayController(manager.getContext());
+ mController.setListener(this);
+ }
+
+ @Override
+ public int getMetricsConstant() {
+ return MetricsEvent.SETTINGS_CONDITION_NIGHT_DISPLAY;
+ }
+
+ @Override
+ public Icon getIcon() {
+ return Icon.createWithResource(mManager.getContext(), R.drawable.ic_settings_night_display);
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mManager.getContext().getString(R.string.condition_night_display_title);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mManager.getContext().getString(R.string.condition_night_display_summary);
+ }
+
+ @Override
+ public CharSequence[] getActions() {
+ return new CharSequence[] { mManager.getContext().getString(R.string.condition_turn_off) };
+ }
+
+ @Override
+ public void onPrimaryClick() {
+ Utils.startWithFragment(mManager.getContext(), NightDisplaySettings.class.getName(), null,
+ null, 0, R.string.night_display_title, null);
+ }
+
+ @Override
+ public void onActionClick(int index) {
+ if (index == 0) {
+ mController.setActivated(false);
+ } else {
+ throw new IllegalArgumentException("Unexpected index " + index);
+ }
+ }
+
+ @Override
+ public void refreshState() {
+ setActive(mController.isActivated());
+ }
+
+ @Override
+ public void onActivated(boolean activated) {
+ refreshState();
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/WorkModeCondition.java b/src/com/android/settings/dashboard/conditional/WorkModeCondition.java
index 3d9958b..7924eef 100644
--- a/src/com/android/settings/dashboard/conditional/WorkModeCondition.java
+++ b/src/com/android/settings/dashboard/conditional/WorkModeCondition.java
@@ -90,7 +90,9 @@
@Override
public void onActionClick(int index) {
if (index == 0) {
- mUm.trySetQuietModeDisabled(mUserHandle.getIdentifier(), null);
+ if (mUserHandle != null) {
+ mUm.trySetQuietModeDisabled(mUserHandle.getIdentifier(), null);
+ }
setActive(false);
} else {
throw new IllegalArgumentException("Unexpected index " + index);
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index d0823d4..45fdc1d 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -38,6 +38,7 @@
import android.support.v7.preference.PreferenceCategory;
import android.text.format.Formatter;
import android.util.ArraySet;
+import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
@@ -50,11 +51,19 @@
import com.android.settingslib.net.ChartDataLoader;
import com.android.settingslib.net.UidDetailProvider;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
public class AppDataUsage extends DataUsageBase implements Preference.OnPreferenceChangeListener,
DataSaverBackend.Listener {
+ private static final String TAG = "AppDataUsage";
+
public static final String ARG_APP_ITEM = "app_item";
public static final String ARG_NETWORK_TEMPLATE = "network_template";
@@ -94,6 +103,12 @@
private SwitchPreference mUnrestrictedData;
private DataSaverBackend mDataSaverBackend;
+ // Parameters to construct an efficient ThreadPoolExecutor
+ private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+ private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
+ private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
+ private static final int KEEP_ALIVE_SECONDS = 30;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -149,7 +164,7 @@
} catch (PackageManager.NameNotFoundException e) {
}
}
- if (mAppItem.key == Process.SYSTEM_UID) {
+ if (!UserHandle.isApp(mAppItem.key)) {
removePreference(KEY_UNRESTRICTED_DATA);
removePreference(KEY_RESTRICT_BACKGROUND);
} else {
@@ -180,9 +195,13 @@
if (mPackages.size() > 1) {
mAppList = (PreferenceCategory) findPreference(KEY_APP_LIST);
- for (int i = 1 ; i < mPackages.size(); i++) {
- new AppPrefLoader().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
- mPackages.valueAt(i));
+ final int packageSize = mPackages.size();
+ final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(packageSize);
+ final ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_POOL_SIZE,
+ MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, workQueue);
+ for (int i = 1; i < mPackages.size(); i++) {
+ final AppPrefLoader loader = new AppPrefLoader();
+ loader.executeOnExecutor(executor, mPackages.valueAt(i));
}
} else {
removePreference(KEY_APP_LIST);
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index a17c8fc..d755a7b 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -17,6 +17,7 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
+import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
@@ -33,6 +34,7 @@
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.Spinner;
+
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settingslib.NetworkPolicyEditor;
@@ -44,7 +46,7 @@
import static android.net.TrafficStats.MB_IN_BYTES;
public class BillingCycleSettings extends DataUsageBase implements
- Preference.OnPreferenceChangeListener {
+ Preference.OnPreferenceChangeListener, DataUsageEditController {
private static final String TAG = "BillingCycleSettings";
private static final boolean LOGD = false;
@@ -54,6 +56,7 @@
private static final String TAG_WARNING_EDITOR = "warningEditor";
private static final String KEY_BILLING_CYCLE = "billing_cycle";
+ private static final String KEY_SET_DATA_WARNING = "set_data_warning";
private static final String KEY_DATA_WARNING = "data_warning";
private static final String KEY_SET_DATA_LIMIT = "set_data_limit";
private static final String KEY_DATA_LIMIT = "data_limit";
@@ -61,6 +64,7 @@
private NetworkTemplate mNetworkTemplate;
private Preference mBillingCycle;
private Preference mDataWarning;
+ private SwitchPreference mEnableDataWarning;
private SwitchPreference mEnableDataLimit;
private Preference mDataLimit;
private DataUsageController mDataUsageController;
@@ -76,6 +80,8 @@
addPreferencesFromResource(R.xml.billing_cycle);
mBillingCycle = findPreference(KEY_BILLING_CYCLE);
+ mEnableDataWarning = (SwitchPreference) findPreference(KEY_SET_DATA_WARNING);
+ mEnableDataWarning.setOnPreferenceChangeListener(this);
mDataWarning = findPreference(KEY_DATA_WARNING);
mEnableDataLimit = (SwitchPreference) findPreference(KEY_SET_DATA_LIMIT);
mEnableDataLimit.setOnPreferenceChangeListener(this);
@@ -92,8 +98,15 @@
NetworkPolicy policy = services.mPolicyEditor.getPolicy(mNetworkTemplate);
mBillingCycle.setSummary(getString(R.string.billing_cycle_summary, policy != null ?
policy.cycleDay : 1));
- mDataWarning.setSummary(Formatter.formatFileSize(getContext(), policy != null
- ? policy.warningBytes : DataUsageController.DEFAULT_WARNING_LEVEL));
+ if (policy != null && policy.warningBytes != WARNING_DISABLED) {
+ mDataWarning.setSummary(Formatter.formatFileSize(getContext(), policy.warningBytes));
+ mDataWarning.setEnabled(true);
+ mEnableDataWarning.setChecked(true);
+ } else {
+ mDataWarning.setSummary(null);
+ mDataWarning.setEnabled(false);
+ mEnableDataWarning.setChecked(false);
+ }
if (policy != null && policy.limitBytes != LIMIT_DISABLED) {
mDataLimit.setSummary(Formatter.formatFileSize(getContext(), policy.limitBytes));
mDataLimit.setEnabled(true);
@@ -130,6 +143,14 @@
setPolicyLimitBytes(LIMIT_DISABLED);
}
return true;
+ } else if (mEnableDataWarning == preference) {
+ boolean enabled = (Boolean) newValue;
+ if (enabled) {
+ setPolicyWarningBytes(mDataUsageController.getDefaultWarningLevel());
+ } else {
+ setPolicyWarningBytes(WARNING_DISABLED);
+ }
+ return true;
}
return false;
}
@@ -145,33 +166,58 @@
updatePrefs();
}
+ private void setPolicyWarningBytes(long warningBytes) {
+ if (LOGD) Log.d(TAG, "setPolicyWarningBytes()");
+ services.mPolicyEditor.setPolicyWarningBytes(mNetworkTemplate, warningBytes);
+ updatePrefs();
+ }
+
+ @Override
+ public NetworkPolicyEditor getNetworkPolicyEditor() {
+ return services.mPolicyEditor;
+ }
+
+ @Override
+ public NetworkTemplate getNetworkTemplate() {
+ return mNetworkTemplate;
+ }
+
+ @Override
+ public void updateDataUsage() {
+ updatePrefs();
+ }
+
/**
* Dialog to edit {@link NetworkPolicy#warningBytes}.
*/
public static class BytesEditorFragment extends DialogFragment
- implements DialogInterface.OnClickListener{
+ implements DialogInterface.OnClickListener {
private static final String EXTRA_TEMPLATE = "template";
private static final String EXTRA_LIMIT = "limit";
private View mView;
- public static void show(BillingCycleSettings parent, boolean isLimit) {
- if (!parent.isAdded()) return;
+ public static void show(DataUsageEditController parent, boolean isLimit) {
+ if (!(parent instanceof Fragment)) {
+ return;
+ }
+ Fragment targetFragment = (Fragment) parent;
+ if (!targetFragment.isAdded()) {
+ return;
+ }
final Bundle args = new Bundle();
- args.putParcelable(EXTRA_TEMPLATE, parent.mNetworkTemplate);
+ args.putParcelable(EXTRA_TEMPLATE, parent.getNetworkTemplate());
args.putBoolean(EXTRA_LIMIT, isLimit);
final BytesEditorFragment dialog = new BytesEditorFragment();
dialog.setArguments(args);
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG_WARNING_EDITOR);
+ dialog.setTargetFragment(targetFragment, 0);
+ dialog.show(targetFragment.getFragmentManager(), TAG_WARNING_EDITOR);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity();
-
-
final LayoutInflater dialogInflater = LayoutInflater.from(context);
final boolean isLimit = getArguments().getBoolean(EXTRA_LIMIT);
mView = dialogInflater.inflate(R.layout.data_usage_bytes_editor, null, false);
@@ -186,8 +232,8 @@
}
private void setupPicker(EditText bytesPicker, Spinner type) {
- final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
- final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+ final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+ final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
final boolean isLimit = getArguments().getBoolean(EXTRA_LIMIT);
@@ -196,10 +242,16 @@
final long limitDisabled = isLimit ? LIMIT_DISABLED : WARNING_DISABLED;
if (bytes > 1.5f * GB_IN_BYTES) {
- bytesPicker.setText(formatText(bytes / (float) GB_IN_BYTES));
+ final String bytesText = formatText(bytes / (float) GB_IN_BYTES);
+ bytesPicker.setText(bytesText);
+ bytesPicker.setSelection(0, bytesText.length());
+
type.setSelection(1);
} else {
- bytesPicker.setText(formatText(bytes / (float) MB_IN_BYTES));
+ final String bytesText = formatText(bytes / (float) MB_IN_BYTES);
+ bytesPicker.setText(bytesText);
+ bytesPicker.setSelection(0, bytesText.length());
+
type.setSelection(0);
}
}
@@ -214,8 +266,8 @@
if (which != DialogInterface.BUTTON_POSITIVE) {
return;
}
- final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
- final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+ final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+ final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
final boolean isLimit = getArguments().getBoolean(EXTRA_LIMIT);
@@ -227,13 +279,13 @@
bytesString = "0";
}
final long bytes = (long) (Float.valueOf(bytesString)
- * (spinner.getSelectedItemPosition() == 0 ? MB_IN_BYTES : GB_IN_BYTES));
+ * (spinner.getSelectedItemPosition() == 0 ? MB_IN_BYTES : GB_IN_BYTES));
if (isLimit) {
editor.setPolicyLimitBytes(template, bytes);
} else {
editor.setPolicyWarningBytes(template, bytes);
}
- target.updatePrefs();
+ target.updateDataUsage();
}
}
@@ -241,7 +293,7 @@
* Dialog to edit {@link NetworkPolicy#cycleDay}.
*/
public static class CycleEditorFragment extends DialogFragment implements
- DialogInterface.OnClickListener{
+ DialogInterface.OnClickListener {
private static final String EXTRA_TEMPLATE = "template";
private NumberPicker mCycleDayPicker;
@@ -260,8 +312,8 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity();
- final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
- final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+ final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+ final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
@@ -286,8 +338,8 @@
@Override
public void onClick(DialogInterface dialog, int which) {
final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
- final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
- final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+ final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+ final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
// clear focus to finish pending text edits
mCycleDayPicker.clearFocus();
@@ -295,7 +347,7 @@
final int cycleDay = mCycleDayPicker.getValue();
final String cycleTimezone = new Time().timezone;
editor.setPolicyCycleDay(template, cycleDay, cycleTimezone);
- target.updatePrefs();
+ target.updateDataUsage();
}
}
@@ -304,7 +356,7 @@
* {@link NetworkPolicy#limitBytes}.
*/
public static class ConfirmLimitFragment extends DialogFragment implements
- DialogInterface.OnClickListener{
+ DialogInterface.OnClickListener {
private static final String EXTRA_MESSAGE = "message";
private static final String EXTRA_LIMIT_BYTES = "limitBytes";
public static final float FLOAT = 1.2f;
diff --git a/src/com/android/settings/datausage/DataUsageEditController.java b/src/com/android/settings/datausage/DataUsageEditController.java
new file mode 100644
index 0000000..adc0fe7
--- /dev/null
+++ b/src/com/android/settings/datausage/DataUsageEditController.java
@@ -0,0 +1,38 @@
+/*
+ * 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.datausage;
+
+import android.net.NetworkTemplate;
+import com.android.settingslib.NetworkPolicyEditor;
+
+/**
+ * Used to create a dialog that modifies the Cellular data warning amount.
+ */
+public interface DataUsageEditController {
+ /**
+ * @return NetworkPolicyEditor to update the values of the data warning and usage limits.
+ */
+ NetworkPolicyEditor getNetworkPolicyEditor();
+
+ /**
+ * @return NetworkTemplate to get the currently set values of the data warning and usage limits.
+ */
+ NetworkTemplate getNetworkTemplate();
+
+ /**
+ * Callback to update the UI and values changed by the Dialog.
+ */
+ void updateDataUsage();
+}
diff --git a/src/com/android/settings/datausage/DataUsageInfoController.java b/src/com/android/settings/datausage/DataUsageInfoController.java
new file mode 100644
index 0000000..115e45e
--- /dev/null
+++ b/src/com/android/settings/datausage/DataUsageInfoController.java
@@ -0,0 +1,54 @@
+/*
+ * 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.datausage;
+
+import android.net.NetworkPolicy;
+import com.android.settingslib.net.DataUsageController.DataUsageInfo;
+
+/**
+ * Controller to handle caching and mobile data logic.
+ */
+public class DataUsageInfoController {
+ /**
+ * Take the cached data usage values in the NetworkPolicy to update DataUsageInfo.
+ */
+ public void updateDataLimit(DataUsageInfo info, NetworkPolicy policy) {
+ if (info == null || policy == null) {
+ return;
+ }
+ if (policy.warningBytes >= 0) {
+ info.warningLevel = policy.warningBytes;
+ }
+ if (policy.limitBytes >= 0) {
+ info.limitLevel = policy.limitBytes;
+ }
+ }
+
+ /**
+ * @returns the most appropriate limit for the data usage summary. Use the total usage when it
+ * is higher than the limit and warning level. Use the limit when it is set and less than usage.
+ * Otherwise use warning level.
+ */
+ public long getSummaryLimit(DataUsageInfo info) {
+ long limit = info.limitLevel;
+ if (limit <= 0) {
+ limit = info.warningLevel;
+ }
+ if (info.usageLevel > limit) {
+ limit = info.usageLevel;
+ }
+ return limit;
+ }
+}
diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java
index a1d19c0..fb05699 100644
--- a/src/com/android/settings/datausage/DataUsageSummary.java
+++ b/src/com/android/settings/datausage/DataUsageSummary.java
@@ -48,6 +48,7 @@
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
+import com.android.settingslib.NetworkPolicyEditor;
import com.android.settingslib.net.DataUsageController;
import java.util.ArrayList;
@@ -56,7 +57,7 @@
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_WIFI;
-public class DataUsageSummary extends DataUsageBase implements Indexable {
+public class DataUsageSummary extends DataUsageBase implements Indexable, DataUsageEditController {
private static final String TAG = "DataUsageSummary";
static final boolean LOGD = false;
@@ -69,6 +70,7 @@
private static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
private DataUsageController mDataUsageController;
+ private DataUsageInfoController mDataInfoController;
private SummaryPreference mSummaryPreference;
private Preference mLimitPreference;
private NetworkTemplate mDefaultTemplate;
@@ -80,6 +82,7 @@
boolean hasMobileData = hasMobileData(getContext());
mDataUsageController = new DataUsageController(getContext());
+ mDataInfoController = new DataUsageInfoController();
addPreferencesFromResource(R.xml.data_usage);
int defaultSubId = getDefaultSubscriptionId(getContext());
@@ -87,15 +90,13 @@
hasMobileData = false;
}
mDefaultTemplate = getDefaultTemplate(getContext(), defaultSubId);
- if (hasMobileData) {
- mLimitPreference = findPreference(KEY_LIMIT_SUMMARY);
- } else {
- removePreference(KEY_LIMIT_SUMMARY);
- }
+ mSummaryPreference = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
+
if (!hasMobileData || !isAdmin()) {
removePreference(KEY_RESTRICT_BACKGROUND);
}
if (hasMobileData) {
+ mLimitPreference = findPreference(KEY_LIMIT_SUMMARY);
List<SubscriptionInfo> subscriptions =
services.mSubscriptionManager.getActiveSubscriptionInfoList();
if (subscriptions == null || subscriptions.size() == 0) {
@@ -104,6 +105,10 @@
for (int i = 0; subscriptions != null && i < subscriptions.size(); i++) {
addMobileSection(subscriptions.get(i).getSubscriptionId());
}
+ mSummaryPreference.setSelectable(true);
+ } else {
+ removePreference(KEY_LIMIT_SUMMARY);
+ mSummaryPreference.setSelectable(false);
}
boolean hasWifiRadio = hasWifiRadio(getContext());
if (hasWifiRadio) {
@@ -116,7 +121,6 @@
: hasWifiRadio ? R.string.wifi_data_template
: R.string.ethernet_data_template;
- mSummaryPreference = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
setHasOptionsMenu(true);
}
@@ -142,6 +146,15 @@
return false;
}
+ @Override
+ public boolean onPreferenceTreeClick(Preference preference) {
+ if (preference == findPreference(KEY_STATUS_HEADER)) {
+ BillingCycleSettings.BytesEditorFragment.show(this, false);
+ return false;
+ }
+ return super.onPreferenceTreeClick(preference);
+ }
+
private void addMobileSection(int subId) {
TemplatePreferenceCategory category = (TemplatePreferenceCategory)
inflatePreferences(R.xml.data_usage_cellular);
@@ -224,27 +237,33 @@
DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
mDefaultTemplate);
Context context = getContext();
+
+ mDataInfoController.updateDataLimit(info,
+ services.mPolicyEditor.getPolicy(mDefaultTemplate));
+
if (mSummaryPreference != null) {
mSummaryPreference.setTitle(
formatTitle(context, getString(mDataUsageTemplate), info.usageLevel));
- long limit = info.limitLevel;
- if (limit <= 0) {
- limit = info.warningLevel;
- }
- if (info.usageLevel > limit) {
- limit = info.usageLevel;
- }
+ long limit = mDataInfoController.getSummaryLimit(info);
mSummaryPreference.setSummary(info.period);
- mSummaryPreference.setLabels(Formatter.formatFileSize(context, 0),
- Formatter.formatFileSize(context, limit));
- mSummaryPreference.setRatios(info.usageLevel / (float) limit, 0,
- (limit - info.usageLevel) / (float) limit);
+
+ if (limit <= 0) {
+ mSummaryPreference.setChartEnabled(false);
+ } else {
+ mSummaryPreference.setChartEnabled(true);
+ mSummaryPreference.setLabels(Formatter.formatFileSize(context, 0),
+ Formatter.formatFileSize(context, limit));
+ mSummaryPreference.setRatios(info.usageLevel / (float) limit, 0,
+ (limit - info.usageLevel) / (float) limit);
+ }
}
- if (mLimitPreference != null) {
+ if (mLimitPreference != null && (info.warningLevel > 0 || info.limitLevel > 0)) {
String warning = Formatter.formatFileSize(context, info.warningLevel);
String limit = Formatter.formatFileSize(context, info.limitLevel);
mLimitPreference.setSummary(getString(info.limitLevel <= 0 ? R.string.cell_warning_only
: R.string.cell_warning_and_limit, warning, limit));
+ } else if (mLimitPreference != null) {
+ mLimitPreference.setSummary(null);
}
PreferenceScreen screen = getPreferenceScreen();
@@ -258,6 +277,21 @@
return MetricsEvent.DATA_USAGE_SUMMARY;
}
+ @Override
+ public NetworkPolicyEditor getNetworkPolicyEditor() {
+ return services.mPolicyEditor;
+ }
+
+ @Override
+ public NetworkTemplate getNetworkTemplate() {
+ return mDefaultTemplate;
+ }
+
+ @Override
+ public void updateDataUsage() {
+ updateState();
+ }
+
/**
* Test if device has an ethernet network connection.
*/
diff --git a/src/com/android/settings/deletionhelper/ActivationWarningFragment.java b/src/com/android/settings/deletionhelper/ActivationWarningFragment.java
new file mode 100644
index 0000000..f7d46d1
--- /dev/null
+++ b/src/com/android/settings/deletionhelper/ActivationWarningFragment.java
@@ -0,0 +1,44 @@
+/*
+ * 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.deletionhelper;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import com.android.settings.R;
+
+/**
+ * Fragment to warn the user about activating the storage manager.
+ */
+public class ActivationWarningFragment extends DialogFragment {
+ public static final String TAG = "ActivationWarningFragment";
+
+ public static ActivationWarningFragment newInstance() {
+ return new ActivationWarningFragment();
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(R.string.automatic_storage_manager_activation_warning)
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
+ }
+
+}
diff --git a/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
new file mode 100644
index 0000000..f9b1a57
--- /dev/null
+++ b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
@@ -0,0 +1,186 @@
+/**
+ * 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.deletionhelper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.SystemProperties;
+import android.os.storage.StorageManager;
+import android.provider.Settings;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+import android.util.Log;
+import android.view.View;
+import android.widget.Switch;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.DropDownPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.R;
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBar.OnSwitchChangeListener;
+
+/**
+ * AutomaticStorageManagerSettings is the Settings screen for configuration and management of the
+ * automatic storage manager.
+ */
+public class AutomaticStorageManagerSettings extends SettingsPreferenceFragment implements
+ OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
+ public static final int DEFAULT_DAYS_TO_RETAIN = 90;
+
+ private static final String KEY_DAYS = "days";
+ private static final String KEY_DELETION_HELPER = "deletion_helper";
+ private static final String KEY_FREED = "freed_bytes";
+ private static final String KEY_STORAGE_MANAGER_SWITCH = "storage_manager_active";
+ private static final String STORAGE_MANAGER_ENABLED_BY_DEFAULT_PROPERTY =
+ "ro.storage_manager.enabled";
+
+ private DropDownPreference mDaysToRetain;
+ private Preference mFreedBytes;
+ private Preference mDeletionHelper;
+ private SwitchPreference mStorageManagerSwitch;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.automatic_storage_management_settings);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mDaysToRetain = (DropDownPreference) findPreference(KEY_DAYS);
+ mDaysToRetain.setOnPreferenceChangeListener(this);
+
+ mFreedBytes = findPreference(KEY_FREED);
+
+ mDeletionHelper = findPreference(KEY_DELETION_HELPER);
+ mDeletionHelper.setOnPreferenceClickListener(this);
+
+ mStorageManagerSwitch = (SwitchPreference) findPreference(KEY_STORAGE_MANAGER_SWITCH);
+ mStorageManagerSwitch.setOnPreferenceChangeListener(this);
+
+ ContentResolver cr = getContentResolver();
+ int value = Settings.Secure.getInt(cr,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_DEFAULT);
+ String[] stringValues =
+ getResources().getStringArray(R.array.automatic_storage_management_days_values);
+ mDaysToRetain.setValue(stringValues[daysValueToIndex(value, stringValues)]);
+
+ long freedBytes = Settings.Secure.getLong(cr,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
+ 0);
+ long lastRunMillis = Settings.Secure.getLong(cr,
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
+ 0);
+ if (freedBytes == 0 || lastRunMillis == 0) {
+ mFreedBytes.setVisible(false);
+ } else {
+ Activity activity = getActivity();
+ mFreedBytes.setSummary(activity.getString(
+ R.string.automatic_storage_manager_freed_bytes,
+ Formatter.formatFileSize(activity, freedBytes),
+ DateUtils.formatDateTime(activity, lastRunMillis, DateUtils.FORMAT_SHOW_DATE)));
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ boolean isChecked =
+ Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0) != 0;
+ mStorageManagerSwitch.setChecked(isChecked);
+ mDaysToRetain.setEnabled(isChecked);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ switch (preference.getKey()) {
+ case KEY_STORAGE_MANAGER_SWITCH:
+ boolean checked = (boolean) newValue;
+ MetricsLogger.action(getContext(), MetricsEvent.ACTION_TOGGLE_STORAGE_MANAGER,
+ checked);
+ mDaysToRetain.setEnabled(checked);
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, checked ? 1 : 0);
+ // Only show a warning if enabling.
+ if (checked) {
+ maybeShowWarning();
+ }
+ break;
+ case KEY_DAYS:
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
+ Integer.parseInt((String) newValue));
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsEvent.STORAGE_MANAGER_SETTINGS;
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (KEY_DELETION_HELPER.equals(preference.getKey())) {
+ Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
+ getContext().startActivity(intent);
+ }
+ return true;
+ }
+
+ @Override
+ protected int getHelpResource() {
+ return R.string.help_uri_storage;
+ }
+
+ private static int daysValueToIndex(int value, String[] indices) {
+ for (int i = 0; i < indices.length; i++) {
+ int thisValue = Integer.parseInt(indices[i]);
+ if (value == thisValue) {
+ return i;
+ }
+ }
+ return indices.length - 1;
+ }
+
+ private void maybeShowWarning() {
+ // If the storage manager is on by default, we can use the normal message.
+ boolean warningUnneeded = SystemProperties.getBoolean(
+ STORAGE_MANAGER_ENABLED_BY_DEFAULT_PROPERTY, false);
+ if (warningUnneeded) {
+ return;
+ }
+ ActivationWarningFragment fragment = ActivationWarningFragment.newInstance();
+ fragment.show(getFragmentManager(), ActivationWarningFragment.TAG);
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/ImeiInformation.java b/src/com/android/settings/deviceinfo/ImeiInformation.java
index 7145212..dc6d3d7 100644
--- a/src/com/android/settings/deviceinfo/ImeiInformation.java
+++ b/src/com/android/settings/deviceinfo/ImeiInformation.java
@@ -21,8 +21,13 @@
import android.support.v7.preference.PreferenceScreen;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
import android.text.TextUtils;
+import android.text.style.TtsSpan;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
@@ -75,21 +80,22 @@
}
setSummaryText(KEY_PRL_VERSION, phone.getCdmaPrlVersion());
- removePreferenceFromScreen(KEY_IMEI_SV);
if (phone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
// Show ICC ID and IMEI for LTE device
setSummaryText(KEY_ICC_ID, phone.getIccSerialNumber());
- setSummaryText(KEY_IMEI, phone.getImei());
+ setSummaryTextAsDigit(KEY_IMEI, phone.getImei());
+ setSummaryTextAsDigit(KEY_IMEI_SV, phone.getDeviceSvn());
} else {
// device is not GSM/UMTS, do not display GSM/UMTS features
// check Null in case no specified preference in overlay xml
+ removePreferenceFromScreen(KEY_IMEI_SV);
removePreferenceFromScreen(KEY_IMEI);
removePreferenceFromScreen(KEY_ICC_ID);
}
} else {
- setSummaryText(KEY_IMEI, phone.getImei());
- setSummaryText(KEY_IMEI_SV, phone.getDeviceSvn());
+ setSummaryTextAsDigit(KEY_IMEI, phone.getImei());
+ setSummaryTextAsDigit(KEY_IMEI_SV, phone.getDeviceSvn());
// device is not CDMA, do not display CDMA features
// check Null in case no specified preference in overlay xml
removePreferenceFromScreen(KEY_PRL_VERSION);
@@ -128,10 +134,23 @@
}
private void setSummaryText(String key, String text) {
+ setSummaryText(key, text, false /* forceDigit */);
+ }
+
+ private void setSummaryTextAsDigit(String key, String text) {
+ setSummaryText(key, text, true /* forceDigit */);
+ }
+
+ private void setSummaryText(String key, CharSequence text, boolean forceDigit) {
final Preference preference = findPreference(key);
if (TextUtils.isEmpty(text)) {
text = getResources().getString(R.string.device_info_default);
+ } else if (forceDigit && TextUtils.isDigitsOnly(text)) {
+ final Spannable spannable = new SpannableStringBuilder(text);
+ final TtsSpan span = new TtsSpan.DigitsBuilder(text.toString()).build();
+ spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text = spannable;
}
if (preference != null) {
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
index 5341c3c..9828f8c 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
@@ -34,10 +34,10 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
-public class PrivateVolumeForget extends InstrumentedFragment {
+public class PrivateVolumeForget extends SettingsPreferenceFragment {
private static final String TAG_FORGET_CONFIRM = "forget_confirm";
private VolumeRecord mRecord;
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
index c9a1fb7..1eb409b 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
@@ -37,6 +37,7 @@
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.provider.DocumentsContract;
+import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceGroup;
@@ -58,6 +59,7 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.applications.ManageApplications;
+import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
import com.android.settings.deviceinfo.StorageSettings.MountTask;
import com.android.settingslib.deviceinfo.StorageMeasurement;
import com.android.settingslib.deviceinfo.StorageMeasurement.MeasurementDetails;
@@ -69,8 +71,6 @@
import java.util.List;
import java.util.Objects;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
/**
* Panel showing summary and actions for a {@link VolumeInfo#TYPE_PRIVATE}
* storage volume.
@@ -79,15 +79,22 @@
// TODO: disable unmount when providing over MTP/PTP
// TODO: warn when mounted read-only
+ private static final String TAG = "PrivateVolumeSettings";
+ private static final boolean LOGV = false;
+
private static final String TAG_RENAME = "rename";
private static final String TAG_OTHER_INFO = "otherInfo";
+ private static final String TAG_SYSTEM_INFO = "systemInfo";
private static final String TAG_USER_INFO = "userInfo";
private static final String TAG_CONFIRM_CLEAR_CACHE = "confirmClearCache";
+ private static final String EXTRA_VOLUME_SIZE = "volume_size";
+
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
private static final int[] ITEMS_NO_SHOW_SHARED = new int[] {
R.string.storage_detail_apps,
+ R.string.storage_detail_system,
};
private static final int[] ITEMS_SHOW_SHARED = new int[] {
@@ -95,15 +102,21 @@
R.string.storage_detail_images,
R.string.storage_detail_videos,
R.string.storage_detail_audio,
- R.string.storage_detail_other
+ R.string.storage_detail_system,
+ R.string.storage_detail_other,
};
+ private static final int DELETION_HELPER_SETTINGS = 1;
+ private static final int DELETION_HELPER_CLEAR = 1;
+
private StorageManager mStorageManager;
private UserManager mUserManager;
private String mVolumeId;
private VolumeInfo mVolume;
private VolumeInfo mSharedVolume;
+ private long mTotalSize;
+ private long mSystemSize;
private StorageMeasurement mMeasure;
@@ -116,6 +129,7 @@
private int mItemPoolIndex;
private Preference mExplore;
+ private Preference mAutomaticStorageManagement;
private boolean mNeedsUpdate;
@@ -145,6 +159,17 @@
mVolumeId = getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID);
mVolume = mStorageManager.findVolumeById(mVolumeId);
+ final long sharedDataSize = mVolume.getPath().getTotalSpace();
+ mTotalSize = getArguments().getLong(EXTRA_VOLUME_SIZE, 0);
+ mSystemSize = mTotalSize - sharedDataSize;
+ if (LOGV) Log.v(TAG,
+ "onCreate() mTotalSize: " + mTotalSize + " sharedDataSize: " + sharedDataSize);
+
+ if (mTotalSize <= 0) {
+ mTotalSize = sharedDataSize;
+ mSystemSize = 0;
+ }
+
// Find the emulated shared storage layered above this private volume
mSharedVolume = mStorageManager.findEmulatedForPrivate(mVolume);
@@ -163,6 +188,7 @@
mCurrentUser = mUserManager.getUserInfo(UserHandle.myUserId());
mExplore = buildAction(R.string.storage_menu_explore);
+ mAutomaticStorageManagement = buildAction(R.string.storage_menu_manage);
mNeedsUpdate = true;
@@ -189,6 +215,9 @@
screen.removeAll();
+ if (getResources().getBoolean(R.bool.config_storage_manager_settings_enabled)) {
+ addPreference(screen, mAutomaticStorageManagement);
+ }
addPreference(screen, mSummary);
List<UserInfo> allUsers = mUserManager.getUsers();
@@ -229,17 +258,17 @@
addPreference(screen, mExplore);
}
- final File file = mVolume.getPath();
- final long totalBytes = file.getTotalSpace();
- final long freeBytes = file.getFreeSpace();
- final long usedBytes = totalBytes - freeBytes;
+ final long freeBytes = mVolume.getPath().getFreeSpace();
+ final long usedBytes = mTotalSize - freeBytes;
+
+ if (LOGV) Log.v(TAG, "update() freeBytes: " + freeBytes + " usedBytes: " + usedBytes);
final BytesResult result = Formatter.formatBytes(getResources(), usedBytes, 0);
mSummary.setTitle(TextUtils.expandTemplate(getText(R.string.storage_size_large),
result.value, result.units));
mSummary.setSummary(getString(R.string.storage_volume_used,
- Formatter.formatFileSize(context, totalBytes)));
- mSummary.setPercent((int) ((usedBytes * 100) / totalBytes));
+ Formatter.formatFileSize(context, mTotalSize)));
+ mSummary.setPercent((int) ((usedBytes * 100) / mTotalSize));
mMeasure.forceMeasure();
mNeedsUpdate = false;
@@ -274,6 +303,16 @@
}
private void addItem(PreferenceGroup group, int titleRes, CharSequence title, int userId) {
+ if (titleRes == R.string.storage_detail_system) {
+ if (mSystemSize <= 0) {
+ Log.w(TAG, "Skipping System storage because its size is " + mSystemSize);
+ return;
+ }
+ if (userId != UserHandle.myUserId()) {
+ // Only display system on current user.
+ return;
+ }
+ }
StorageItemPreference item;
if (mItemPoolIndex < mItemPreferencePool.size()) {
item = mItemPreferencePool.get(mItemPoolIndex);
@@ -306,6 +345,10 @@
return pref;
}
+ static void setVolumeSize(Bundle args, long size) {
+ args.putLong(EXTRA_VOLUME_SIZE, size);
+ }
+
@Override
public void onResume() {
super.onResume();
@@ -355,6 +398,7 @@
final MenuItem unmount = menu.findItem(R.id.storage_unmount);
final MenuItem format = menu.findItem(R.id.storage_format);
final MenuItem migrate = menu.findItem(R.id.storage_migrate);
+ final MenuItem manage = menu.findItem(R.id.storage_free);
// Actions live in menu for non-internal private volumes; they're shown
// as preference items for public volumes.
@@ -363,11 +407,14 @@
mount.setVisible(false);
unmount.setVisible(false);
format.setVisible(false);
+ manage.setVisible(getResources().getBoolean(
+ R.bool.config_storage_manager_settings_enabled));
} else {
rename.setVisible(mVolume.getType() == VolumeInfo.TYPE_PRIVATE);
mount.setVisible(mVolume.getState() == VolumeInfo.STATE_UNMOUNTED);
unmount.setVisible(mVolume.isMountedReadable());
format.setVisible(true);
+ manage.setVisible(false);
}
format.setTitle(R.string.storage_menu_format_public);
@@ -406,6 +453,11 @@
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
startActivity(intent);
return true;
+ case R.id.storage_free:
+ final Intent deletion_helper_intent =
+ new Intent(StorageManager.ACTION_MANAGE_STORAGE);
+ startActivity(deletion_helper_intent);
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -415,7 +467,7 @@
// TODO: launch better intents for specific volume
final int userId = (pref instanceof StorageItemPreference ?
- ((StorageItemPreference)pref).userHandle : -1);
+ ((StorageItemPreference) pref).userHandle : -1);
int itemTitleId;
try {
itemTitleId = Integer.parseInt(pref.getKey());
@@ -453,9 +505,14 @@
intent.addCategory(Intent.CATEGORY_DEFAULT);
} break;
+ case R.string.storage_detail_system: {
+ SystemInfoFragment.show(this);
+ return true;
+
+ }
case R.string.storage_detail_other: {
OtherInfoFragment.show(this, mStorageManager.getBestVolumeDescription(mVolume),
- mSharedVolume);
+ mSharedVolume, userId);
return true;
}
@@ -467,6 +524,11 @@
case R.string.storage_menu_explore: {
intent = mSharedVolume.buildBrowseIntent();
} break;
+ case R.string.storage_menu_manage: {
+ startFragment(this, AutomaticStorageManagerSettings.class.getCanonicalName(),
+ R.string.automatic_storage_manager_settings, 0, null);
+ return true;
+ }
case 0: {
UserInfoFragment.show(this, pref.getTitle(), pref.getSummary());
return true;
@@ -474,15 +536,9 @@
}
if (intent != null) {
- try {
- if (userId == -1) {
- startActivity(intent);
- } else {
- getActivity().startActivityAsUser(intent, new UserHandle(userId));
- }
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "No activity found for " + intent);
- }
+ intent.putExtra(Intent.EXTRA_USER_ID, userId);
+
+ launchIntent(this, intent);
return true;
}
return super.onPreferenceTreeClick(pref);
@@ -496,6 +552,11 @@
};
private void updateDetails(MeasurementDetails details) {
+ StorageItemPreference otherItem = null;
+ long accountedSize = 0;
+ long totalMiscSize = 0;
+ long totalDownloadsSize = 0;
+
for (int i = 0; i < mItemPoolIndex; ++i) {
StorageItemPreference item = mItemPreferencePool.get(i);
final int userId = item.userHandle;
@@ -506,19 +567,33 @@
itemTitleId = 0;
}
switch (itemTitleId) {
+ case R.string.storage_detail_system: {
+ updatePreference(item, mSystemSize);
+ accountedSize += mSystemSize;
+ if (LOGV) Log.v(TAG, "mSystemSize: " + mSystemSize
+ + " accountedSize: " + accountedSize);
+ } break;
case R.string.storage_detail_apps: {
updatePreference(item, details.appsSize.get(userId));
+ accountedSize += details.appsSize.get(userId);
+ if (LOGV) Log.v(TAG, "appsSize: " + details.appsSize.get(userId)
+ + " accountedSize: " + accountedSize);
} break;
case R.string.storage_detail_images: {
final long imagesSize = totalValues(details, userId,
- Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MOVIES,
- Environment.DIRECTORY_PICTURES);
+ Environment.DIRECTORY_DCIM, Environment.DIRECTORY_PICTURES);
updatePreference(item, imagesSize);
+ accountedSize += imagesSize;
+ if (LOGV) Log.v(TAG, "imagesSize: " + imagesSize
+ + " accountedSize: " + accountedSize);
} break;
case R.string.storage_detail_videos: {
final long videosSize = totalValues(details, userId,
Environment.DIRECTORY_MOVIES);
updatePreference(item, videosSize);
+ accountedSize += videosSize;
+ if (LOGV) Log.v(TAG, "videosSize: " + videosSize
+ + " accountedSize: " + accountedSize);
} break;
case R.string.storage_detail_audio: {
final long audioSize = totalValues(details, userId,
@@ -526,23 +601,58 @@
Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS);
updatePreference(item, audioSize);
+ accountedSize += audioSize;
+ if (LOGV) Log.v(TAG, "audioSize: " + audioSize
+ + " accountedSize: " + accountedSize);
} break;
case R.string.storage_detail_other: {
- updatePreference(item, details.miscSize.get(userId));
+ final long downloadsSize = totalValues(details, userId,
+ Environment.DIRECTORY_DOWNLOADS);
+ final long miscSize = details.miscSize.get(userId);
+ totalDownloadsSize += downloadsSize;
+ totalMiscSize += miscSize;
+ accountedSize += miscSize + downloadsSize;
+
+ if (LOGV)
+ Log.v(TAG, "miscSize for " + userId + ": " + miscSize + "(total: "
+ + totalMiscSize + ") \ndownloadsSize: " + downloadsSize + "(total: "
+ + totalDownloadsSize + ") accountedSize: " + accountedSize);
+
+ // Cannot display 'Other' until all known items are accounted for.
+ otherItem = item;
} break;
case R.string.storage_detail_cached: {
updatePreference(item, details.cacheSize);
+ accountedSize += details.cacheSize;
+ if (LOGV)
+ Log.v(TAG, "cacheSize: " + details.cacheSize + " accountedSize: "
+ + accountedSize);
} break;
case 0: {
final long userSize = details.usersSize.get(userId);
updatePreference(item, userSize);
+ accountedSize += userSize;
+ if (LOGV) Log.v(TAG, "userSize: " + userSize
+ + " accountedSize: " + accountedSize);
} break;
}
}
+ if (otherItem != null) {
+ final long usedSize = mTotalSize - details.availSize;
+ final long unaccountedSize = usedSize - accountedSize;
+ final long otherSize = totalMiscSize + totalDownloadsSize + unaccountedSize;
+ if (LOGV)
+ Log.v(TAG, "Other items: \n\tmTotalSize: " + mTotalSize + " availSize: "
+ + details.availSize + " usedSize: " + usedSize + "\n\taccountedSize: "
+ + accountedSize + " unaccountedSize size: " + unaccountedSize
+ + "\n\ttotalMiscSize: " + totalMiscSize + " totalDownloadsSize: "
+ + totalDownloadsSize + "\n\tdetails: " + details);
+ updatePreference(otherItem, otherSize);
+ }
}
private void updatePreference(StorageItemPreference pref, long size) {
- pref.setStorageSize(size, mVolume.getPath().getTotalSpace());
+ pref.setStorageSize(size, mTotalSize);
}
private boolean isProfileOf(UserInfo user, UserInfo profile) {
@@ -566,6 +676,20 @@
return total;
}
+ private static void launchIntent(Fragment fragment, Intent intent) {
+ try {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
+
+ if (userId == -1) {
+ fragment.startActivity(intent);
+ } else {
+ fragment.getActivity().startActivityAsUser(intent, new UserHandle(userId));
+ }
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "No activity found for " + intent);
+ }
+ }
+
private final StorageEventListener mStorageListener = new StorageEventListener() {
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
@@ -633,15 +757,36 @@
}
}
+ public static class SystemInfoFragment extends DialogFragment {
+ public static void show(Fragment parent) {
+ if (!parent.isAdded()) return;
+
+ final SystemInfoFragment dialog = new SystemInfoFragment();
+ dialog.setTargetFragment(parent, 0);
+ dialog.show(parent.getFragmentManager(), TAG_SYSTEM_INFO);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(R.string.storage_detail_dialog_system)
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
+ }
+ }
+
public static class OtherInfoFragment extends DialogFragment {
- public static void show(Fragment parent, String title, VolumeInfo sharedVol) {
+ public static void show(Fragment parent, String title, VolumeInfo sharedVol, int userId) {
if (!parent.isAdded()) return;
final OtherInfoFragment dialog = new OtherInfoFragment();
dialog.setTargetFragment(parent, 0);
final Bundle args = new Bundle();
args.putString(Intent.EXTRA_TITLE, title);
- args.putParcelable(Intent.EXTRA_INTENT, sharedVol.buildBrowseIntent());
+
+ final Intent intent = sharedVol.buildBrowseIntent();
+ intent.putExtra(Intent.EXTRA_USER_ID, userId);
+ args.putParcelable(Intent.EXTRA_INTENT, intent);
dialog.setArguments(args);
dialog.show(parent.getFragmentManager(), TAG_OTHER_INFO);
}
@@ -661,7 +806,7 @@
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- startActivity(intent);
+ launchIntent(OtherInfoFragment.this, intent);
}
});
builder.setNegativeButton(android.R.string.cancel, null);
diff --git a/src/com/android/settings/deviceinfo/SimStatus.java b/src/com/android/settings/deviceinfo/SimStatus.java
index 79c8d64..ad77083 100644
--- a/src/com/android/settings/deviceinfo/SimStatus.java
+++ b/src/com/android/settings/deviceinfo/SimStatus.java
@@ -16,9 +16,6 @@
package com.android.settings.deviceinfo;
-import static android.content.Context.CARRIER_CONFIG_SERVICE;
-import static android.content.Context.TELEPHONY_SERVICE;
-
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -32,7 +29,6 @@
import android.support.v7.preference.Preference;
import android.telephony.CarrierConfigManager;
import android.telephony.CellBroadcastMessage;
-import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -58,9 +54,13 @@
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
+import com.android.settingslib.DeviceInfoUtils;
import java.util.List;
+import static android.content.Context.CARRIER_CONFIG_SERVICE;
+import static android.content.Context.TELEPHONY_SERVICE;
+
/**
* Display the following information
@@ -128,7 +128,8 @@
return;
}
CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
- if (cbMessage != null && cbMessage.getServiceCategory() == 50) {
+ if (cbMessage != null && cbMessage.getServiceCategory() == 50
+ && mSir.getSubscriptionId() == cbMessage.getSubId()) {
String latestAreaInfo = cbMessage.getMessageBody();
updateAreaInfo(latestAreaInfo);
}
@@ -392,13 +393,10 @@
mShowICCID = carrierConfig.getBoolean(
CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL);
- String rawNumber = mTelephonyManager.getLine1Number(mSir.getSubscriptionId());
- String formattedNumber = null;
- if (!TextUtils.isEmpty(rawNumber)) {
- formattedNumber = PhoneNumberUtils.formatNumber(rawNumber);
- }
+
// If formattedNumber is null or empty, it'll display as "Unknown".
- setSummaryText(KEY_PHONE_NUMBER, formattedNumber);
+ setSummaryText(KEY_PHONE_NUMBER,
+ DeviceInfoUtils.getFormattedPhoneNumber(getContext(), mSir));
setSummaryText(KEY_IMEI, mPhone.getImei());
setSummaryText(KEY_IMEI_SV, mPhone.getDeviceSvn());
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
index 5ae3986..7757efc 100644
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
@@ -35,6 +35,7 @@
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.support.annotation.NonNull;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.text.TextUtils;
@@ -42,6 +43,7 @@
import android.text.format.Formatter.BytesResult;
import android.util.Log;
import android.widget.Toast;
+
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -50,7 +52,6 @@
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
-
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.drawer.SettingsDrawerActivity;
@@ -58,6 +59,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -88,6 +90,7 @@
private PreferenceCategory mExternalCategory;
private StorageSummaryPreference mInternalSummary;
+ private static long sTotalInternalStorage;
@Override
protected int getMetricsCategory() {
@@ -108,6 +111,10 @@
mStorageManager = context.getSystemService(StorageManager.class);
mStorageManager.registerListener(mStorageListener);
+ if (sTotalInternalStorage <= 0) {
+ sTotalInternalStorage = mStorageManager.getPrimaryStorageSize();
+ }
+
addPreferencesFromResource(R.xml.device_info_storage);
mInternalCategory = (PreferenceCategory) findPreference("storage_internal");
@@ -160,17 +167,18 @@
for (VolumeInfo vol : volumes) {
if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
+ final long volumeTotalBytes = getTotalSize(vol);
final int color = COLOR_PRIVATE[privateCount++ % COLOR_PRIVATE.length];
mInternalCategory.addPreference(
- new StorageVolumePreference(context, vol, color));
+ new StorageVolumePreference(context, vol, color, volumeTotalBytes));
if (vol.isMountedReadable()) {
final File path = vol.getPath();
- privateUsedBytes += path.getTotalSpace() - path.getFreeSpace();
- privateTotalBytes += path.getTotalSpace();
+ privateUsedBytes += (volumeTotalBytes - path.getFreeSpace());
+ privateTotalBytes += volumeTotalBytes;
}
} else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
mExternalCategory.addPreference(
- new StorageVolumePreference(context, vol, COLOR_PUBLIC));
+ new StorageVolumePreference(context, vol, COLOR_PUBLIC, 0));
}
}
@@ -211,7 +219,6 @@
result.value, result.units));
mInternalSummary.setSummary(getString(R.string.storage_volume_used_total,
Formatter.formatFileSize(context, privateTotalBytes)));
-
if (mInternalCategory.getPreferenceCount() > 0) {
getPreferenceScreen().addPreference(mInternalCategory);
}
@@ -224,6 +231,7 @@
// Only showing primary internal storage, so just shortcut
final Bundle args = new Bundle();
args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
+ PrivateVolumeSettings.setVolumeSize(args, sTotalInternalStorage);
Intent intent = Utils.onBuildStartFragmentIntent(getActivity(),
PrivateVolumeSettings.class.getName(), args, null, R.string.apps_storage, null,
false);
@@ -268,6 +276,7 @@
if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
final Bundle args = new Bundle();
args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
+ PrivateVolumeSettings.setVolumeSize(args, getTotalSize(vol));
startFragment(this, PrivateVolumeSettings.class.getCanonicalName(),
-1, 0, args);
return true;
@@ -399,18 +408,37 @@
builder.setPositiveButton(R.string.storage_menu_mount,
new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
+ /**
+ * Check if an {@link RestrictedLockUtils#sendShowAdminSupportDetailsIntent admin
+ * details intent} should be shown for the restriction and show it.
+ *
+ * @param restriction The restriction to check
+ * @return {@code true} iff a intent was shown.
+ */
+ private boolean wasAdminSupportIntentShown(@NonNull String restriction) {
EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
- getActivity(), UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
- UserHandle.myUserId());
+ getActivity(), restriction, UserHandle.myUserId());
boolean hasBaseUserRestriction = RestrictedLockUtils.hasBaseUserRestriction(
- getActivity(), UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
- UserHandle.myUserId());
+ getActivity(), restriction, UserHandle.myUserId());
if (admin != null && !hasBaseUserRestriction) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(), admin);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (wasAdminSupportIntentShown(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA)) {
return;
}
+
+ if (vol.disk != null && vol.disk.isUsb() &&
+ wasAdminSupportIntentShown(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
+ return;
+ }
+
new MountTask(context, vol).execute();
}
});
@@ -477,28 +505,49 @@
private void updateSummary() {
// TODO: Register listener.
- StorageManager storageManager = mContext.getSystemService(StorageManager.class);
+ final StorageManager storageManager = mContext.getSystemService(StorageManager.class);
+ if (sTotalInternalStorage <= 0) {
+ sTotalInternalStorage = storageManager.getPrimaryStorageSize();
+ }
final List<VolumeInfo> volumes = storageManager.getVolumes();
- long privateUsedBytes = 0;
+ long privateFreeBytes = 0;
long privateTotalBytes = 0;
for (VolumeInfo info : volumes) {
- if (info.getType() != VolumeInfo.TYPE_PUBLIC
- && info.getType() != VolumeInfo.TYPE_PRIVATE) {
- continue;
- }
final File path = info.getPath();
- if (path == null) {
+ if (info.getType() != VolumeInfo.TYPE_PRIVATE || path == null) {
continue;
}
- privateUsedBytes += path.getTotalSpace() - path.getFreeSpace();
- privateTotalBytes += path.getTotalSpace();
+ privateTotalBytes += getTotalSize(info);
+ privateFreeBytes += path.getFreeSpace();
}
+ long privateUsedBytes = privateTotalBytes - privateFreeBytes;
mLoader.setSummary(this, mContext.getString(R.string.storage_summary,
Formatter.formatFileSize(mContext, privateUsedBytes),
Formatter.formatFileSize(mContext, privateTotalBytes)));
}
}
+ private static long getTotalSize(VolumeInfo info) {
+ // Device could have more than one primary storage, which could be located in the
+ // internal flash (UUID_PRIVATE_INTERNAL) or in an external disk.
+ // If it's internal, try to get its total size from StorageManager first
+ // (sTotalInternalStorage), since that size is more precise because it accounts for
+ // the system partition.
+ if (info.getType() == VolumeInfo.TYPE_PRIVATE
+ && Objects.equals(info.getFsUuid(), StorageManager.UUID_PRIVATE_INTERNAL)
+ && sTotalInternalStorage > 0) {
+ return sTotalInternalStorage;
+ } else {
+ final File path = info.getPath();
+ if (path == null) {
+ // Should not happen, caller should have checked.
+ Log.e(TAG, "info's path is null on getTotalSize(): " + info);
+ return 0;
+ }
+ return path.getTotalSpace();
+ }
+ }
+
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
= new SummaryLoader.SummaryProviderFactory() {
@Override
diff --git a/src/com/android/settings/deviceinfo/StorageSummaryPreference.java b/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
index 9fc1363..e1cf774 100644
--- a/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
+++ b/src/com/android/settings/deviceinfo/StorageSummaryPreference.java
@@ -46,6 +46,7 @@
if (mPercent != -1) {
progress.setVisibility(View.VISIBLE);
progress.setProgress(mPercent);
+ progress.setScaleY(7f);
} else {
progress.setVisibility(View.GONE);
}
diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreference.java b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
index dba636c..2ef42fa 100644
--- a/src/com/android/settings/deviceinfo/StorageVolumePreference.java
+++ b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
@@ -46,7 +46,8 @@
private int mColor;
private int mUsedPercent = -1;
- public StorageVolumePreference(Context context, VolumeInfo volume, int color) {
+ // TODO: ideally, VolumeInfo should have a total physical size.
+ public StorageVolumePreference(Context context, VolumeInfo volume, int color, long totalBytes) {
super(context);
mStorageManager = context.getSystemService(StorageManager.class);
@@ -68,8 +69,10 @@
if (volume.isMountedReadable()) {
// TODO: move statfs() to background thread
final File path = volume.getPath();
+ if (totalBytes <= 0) {
+ totalBytes = path.getTotalSpace();
+ }
final long freeBytes = path.getFreeSpace();
- final long totalBytes = path.getTotalSpace();
final long usedBytes = totalBytes - freeBytes;
final String used = Formatter.formatFileSize(context, usedBytes);
diff --git a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
index b44bc33..42b727d 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
@@ -86,7 +86,6 @@
private volatile int mProgress = 20;
- private volatile long mInternalBench;
private volatile long mPrivateBench;
@Override
@@ -98,11 +97,9 @@
storage.partitionPrivate(activity.mDisk.getId());
publishProgress(40);
- mInternalBench = storage.benchmark(null);
- publishProgress(60);
-
final VolumeInfo privateVol = activity.findFirstVolume(VolumeInfo.TYPE_PRIVATE);
mPrivateBench = storage.benchmark(privateVol.getId());
+ mPrivateBench /= 1000000;
// If we just adopted the device that had been providing
// physical storage, then automatically move storage to the
@@ -150,13 +147,39 @@
}
if (activity.mFormatPrivate) {
- final float pct = (float) mInternalBench / (float) mPrivateBench;
- Log.d(TAG, "New volume is " + pct + "x the speed of internal");
+ // When the adoptable storage feature originally launched, we
+ // benchmarked both internal storage and the newly adopted
+ // storage and we warned if the adopted device was less than
+ // 0.25x the speed of internal. (The goal was to help set user
+ // expectations and encourage use of devices comparable to
+ // internal storage performance.)
- // To help set user expectations around device performance, we
- // warn if the adopted media is 0.25x the speed of internal
- // storage or slower.
- if (Float.isNaN(pct) || pct < 0.25) {
+ // However, since then, internal storage has started moving from
+ // eMMC to UFS, which can significantly outperform adopted
+ // devices, causing the speed warning to always trigger. To
+ // mitigate this, we've switched to using a static threshold.
+
+ // The static threshold was derived by running the benchmark on
+ // a wide selection of SD cards from several vendors; here are
+ // some 50th percentile results from 20+ runs of each card:
+
+ // 8GB C4 40MB/s+: 3282ms
+ // 16GB C10 40MB/s+: 1881ms
+ // 32GB C10 40MB/s+: 2897ms
+ // 32GB U3 80MB/s+: 1595ms
+ // 32GB C10 80MB/s+: 1680ms
+ // 128GB U1 80MB/s+: 1532ms
+
+ // Thus a 2000ms static threshold strikes a reasonable balance
+ // to help us identify slower cards. Users can still proceed
+ // with these slower cards; we're just showing a warning.
+
+ // The above analysis was done using the "r1572:w1001:s285"
+ // benchmark, and it should be redone any time the benchmark
+ // changes.
+
+ Log.d(TAG, "New volume took " + mPrivateBench + "ms to run benchmark");
+ if (mPrivateBench > 2000) {
final SlowWarningFragment dialog = new SlowWarningFragment();
dialog.showAllowingStateLoss(activity.getFragmentManager(), TAG_SLOW_WARNING);
} else {
diff --git a/src/com/android/settings/display/NightDisplayPreference.java b/src/com/android/settings/display/NightDisplayPreference.java
new file mode 100644
index 0000000..38b57a2
--- /dev/null
+++ b/src/com/android/settings/display/NightDisplayPreference.java
@@ -0,0 +1,127 @@
+/*
+ * 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.display;
+
+import android.content.Context;
+import android.support.v14.preference.SwitchPreference;
+import android.util.AttributeSet;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.settings.R;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+public class NightDisplayPreference extends SwitchPreference
+ implements NightDisplayController.Callback {
+
+ private NightDisplayController mController;
+ private DateFormat mTimeFormatter;
+
+ public NightDisplayPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mController = new NightDisplayController(context);
+ mTimeFormatter = android.text.format.DateFormat.getTimeFormat(context);
+ mTimeFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
+
+ @Override
+ public void onAttached() {
+ super.onAttached();
+
+ // Listen for changes only while attached.
+ mController.setListener(this);
+
+ // Update the summary since the state may have changed while not attached.
+ updateSummary();
+ }
+
+ @Override
+ public void onDetached() {
+ super.onDetached();
+
+ // Stop listening for state changes.
+ mController.setListener(null);
+ }
+
+ private String getFormattedTimeString(NightDisplayController.LocalTime localTime) {
+ final Calendar c = Calendar.getInstance();
+ c.setTimeZone(mTimeFormatter.getTimeZone());
+ c.set(Calendar.HOUR_OF_DAY, localTime.hourOfDay);
+ c.set(Calendar.MINUTE, localTime.minute);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ return mTimeFormatter.format(c.getTime());
+ }
+
+ private void updateSummary() {
+ final Context context = getContext();
+
+ final boolean isActivated = mController.isActivated();
+ final int autoMode = mController.getAutoMode();
+
+ final String autoModeSummary;
+ switch (autoMode) {
+ default:
+ case NightDisplayController.AUTO_MODE_DISABLED:
+ autoModeSummary = context.getString(isActivated
+ ? R.string.night_display_summary_on_auto_mode_never
+ : R.string.night_display_summary_off_auto_mode_never);
+ break;
+ case NightDisplayController.AUTO_MODE_CUSTOM:
+ if (isActivated) {
+ autoModeSummary = context.getString(
+ R.string.night_display_summary_on_auto_mode_custom,
+ getFormattedTimeString(mController.getCustomEndTime()));
+ } else {
+ autoModeSummary = context.getString(
+ R.string.night_display_summary_off_auto_mode_custom,
+ getFormattedTimeString(mController.getCustomStartTime()));
+ }
+ break;
+ case NightDisplayController.AUTO_MODE_TWILIGHT:
+ autoModeSummary = context.getString(isActivated
+ ? R.string.night_display_summary_on_auto_mode_twilight
+ : R.string.night_display_summary_off_auto_mode_twilight);
+ break;
+ }
+
+ final int summaryFormatResId = isActivated ? R.string.night_display_summary_on
+ : R.string.night_display_summary_off;
+ setSummary(context.getString(summaryFormatResId, autoModeSummary));
+ }
+
+ @Override
+ public void onActivated(boolean activated) {
+ updateSummary();
+ }
+
+ @Override
+ public void onAutoModeChanged(int autoMode) {
+ updateSummary();
+ }
+
+ @Override
+ public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+ updateSummary();
+ }
+
+ @Override
+ public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+ updateSummary();
+ }
+}
diff --git a/src/com/android/settings/display/NightDisplaySettings.java b/src/com/android/settings/display/NightDisplaySettings.java
new file mode 100644
index 0000000..7eb1217
--- /dev/null
+++ b/src/com/android/settings/display/NightDisplaySettings.java
@@ -0,0 +1,206 @@
+/*
+ * 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.display;
+
+import android.app.Dialog;
+import android.app.TimePickerDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v7.preference.DropDownPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.TwoStatePreference;
+import android.widget.TimePicker;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Settings screen for Night display.
+ */
+public class NightDisplaySettings extends SettingsPreferenceFragment
+ implements NightDisplayController.Callback, Preference.OnPreferenceChangeListener {
+
+ private static final String KEY_NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
+ private static final String KEY_NIGHT_DISPLAY_START_TIME = "night_display_start_time";
+ private static final String KEY_NIGHT_DISPLAY_END_TIME = "night_display_end_time";
+ private static final String KEY_NIGHT_DISPLAY_ACTIVATED = "night_display_activated";
+
+ private static final int DIALOG_START_TIME = 0;
+ private static final int DIALOG_END_TIME = 1;
+
+ private NightDisplayController mController;
+ private DateFormat mTimeFormatter;
+
+ private DropDownPreference mAutoModePreference;
+ private Preference mStartTimePreference;
+ private Preference mEndTimePreference;
+ private TwoStatePreference mActivatedPreference;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Context context = getContext();
+ mController = new NightDisplayController(context);
+
+ mTimeFormatter = android.text.format.DateFormat.getTimeFormat(context);
+ mTimeFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ super.onCreatePreferences(savedInstanceState, rootKey);
+
+ // Load the preferences from xml.
+ addPreferencesFromResource(R.xml.night_display_settings);
+
+ mAutoModePreference = (DropDownPreference) findPreference(KEY_NIGHT_DISPLAY_AUTO_MODE);
+ mStartTimePreference = findPreference(KEY_NIGHT_DISPLAY_START_TIME);
+ mEndTimePreference = findPreference(KEY_NIGHT_DISPLAY_END_TIME);
+ mActivatedPreference = (TwoStatePreference) findPreference(KEY_NIGHT_DISPLAY_ACTIVATED);
+
+ mAutoModePreference.setEntries(new CharSequence[] {
+ getString(R.string.night_display_auto_mode_never),
+ getString(R.string.night_display_auto_mode_custom),
+ getString(R.string.night_display_auto_mode_twilight)
+ });
+ mAutoModePreference.setEntryValues(new CharSequence[] {
+ String.valueOf(NightDisplayController.AUTO_MODE_DISABLED),
+ String.valueOf(NightDisplayController.AUTO_MODE_CUSTOM),
+ String.valueOf(NightDisplayController.AUTO_MODE_TWILIGHT)
+ });
+ mAutoModePreference.setOnPreferenceChangeListener(this);
+ mActivatedPreference.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ // Listen for changes only while visible.
+ mController.setListener(this);
+
+ // Update the current state since it have changed while not visible.
+ onActivated(mController.isActivated());
+ onAutoModeChanged(mController.getAutoMode());
+ onCustomStartTimeChanged(mController.getCustomStartTime());
+ onCustomEndTimeChanged(mController.getCustomEndTime());
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+
+ // Stop listening for state changes.
+ mController.setListener(null);
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(Preference preference) {
+ if (preference == mStartTimePreference) {
+ showDialog(DIALOG_START_TIME);
+ return true;
+ } else if (preference == mEndTimePreference) {
+ showDialog(DIALOG_END_TIME);
+ return true;
+ }
+ return super.onPreferenceTreeClick(preference);
+ }
+
+ @Override
+ public Dialog onCreateDialog(final int dialogId) {
+ if (dialogId == DIALOG_START_TIME || dialogId == DIALOG_END_TIME) {
+ final NightDisplayController.LocalTime initialTime;
+ if (dialogId == DIALOG_START_TIME) {
+ initialTime = mController.getCustomStartTime();
+ } else {
+ initialTime = mController.getCustomEndTime();
+ }
+
+ final Context context = getContext();
+ final boolean use24HourFormat = android.text.format.DateFormat.is24HourFormat(context);
+ return new TimePickerDialog(context, new TimePickerDialog.OnTimeSetListener() {
+ @Override
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ final NightDisplayController.LocalTime time =
+ new NightDisplayController.LocalTime(hourOfDay, minute);
+ if (dialogId == DIALOG_START_TIME) {
+ mController.setCustomStartTime(time);
+ } else {
+ mController.setCustomEndTime(time);
+ }
+ }
+ }, initialTime.hourOfDay, initialTime.minute, use24HourFormat);
+ }
+ return super.onCreateDialog(dialogId);
+ }
+
+ @Override
+ public void onActivated(boolean activated) {
+ mActivatedPreference.setChecked(activated);
+ }
+
+ @Override
+ public void onAutoModeChanged(int autoMode) {
+ mAutoModePreference.setValue(String.valueOf(autoMode));
+
+ final boolean showCustomSchedule = autoMode == NightDisplayController.AUTO_MODE_CUSTOM;
+ mStartTimePreference.setVisible(showCustomSchedule);
+ mEndTimePreference.setVisible(showCustomSchedule);
+ }
+
+ private String getFormattedTimeString(NightDisplayController.LocalTime localTime) {
+ final Calendar c = Calendar.getInstance();
+ c.setTimeZone(mTimeFormatter.getTimeZone());
+ c.set(Calendar.HOUR_OF_DAY, localTime.hourOfDay);
+ c.set(Calendar.MINUTE, localTime.minute);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ return mTimeFormatter.format(c.getTime());
+ }
+
+ @Override
+ public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+ mStartTimePreference.setSummary(getFormattedTimeString(startTime));
+ }
+
+ @Override
+ public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+ mEndTimePreference.setSummary(getFormattedTimeString(endTime));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mAutoModePreference) {
+ return mController.setAutoMode(Integer.parseInt((String) newValue));
+ } else if (preference == mActivatedPreference) {
+ return mController.setActivated((Boolean) newValue);
+ }
+ return false;
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsEvent.NIGHT_DISPLAY_SETTINGS;
+ }
+}
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollBase.java b/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
index 150a01a..f36321d 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
@@ -23,22 +23,20 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.view.View;
-import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.android.settings.ChooseLockSettingsHelper;
import com.android.settings.InstrumentedActivity;
import com.android.settings.R;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.view.NavigationBar;
+import com.android.setupwizardlib.GlifLayout;
/**
* Base activity for all fingerprint enrollment steps.
*/
public abstract class FingerprintEnrollBase extends InstrumentedActivity
implements View.OnClickListener {
- static final int RESULT_FINISHED = FingerprintSettings.RESULT_FINISHED;
+ public static final int RESULT_FINISHED = FingerprintSettings.RESULT_FINISHED;
static final int RESULT_SKIP = FingerprintSettings.RESULT_SKIP;
static final int RESULT_TIMEOUT = FingerprintSettings.RESULT_TIMEOUT;
@@ -71,38 +69,26 @@
}
protected void initViews() {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS |
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
- WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
-
- getWindow().getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-
getWindow().setStatusBarColor(Color.TRANSPARENT);
- getNavigationBar().setVisibility(View.GONE);
Button nextButton = getNextButton();
if (nextButton != null) {
nextButton.setOnClickListener(this);
}
}
- protected NavigationBar getNavigationBar() {
- return (NavigationBar) findViewById(R.id.suw_layout_navigation_bar);
- }
-
- protected SetupWizardLayout getSetupWizardLayout() {
- return (SetupWizardLayout) findViewById(R.id.setup_wizard_layout);
+ protected GlifLayout getLayout() {
+ return (GlifLayout) findViewById(R.id.setup_wizard_layout);
}
protected void setHeaderText(int resId, boolean force) {
- TextView layoutTitle = getSetupWizardLayout().getHeaderTextView();
+ TextView layoutTitle = getLayout().getHeaderTextView();
CharSequence previousTitle = layoutTitle.getText();
CharSequence title = getText(resId);
if (previousTitle != title || force) {
if (!TextUtils.isEmpty(previousTitle)) {
layoutTitle.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
}
- getSetupWizardLayout().setHeaderText(title);
+ getLayout().setHeaderText(title);
setTitle(title);
}
}
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
index 1719289..627cb78 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
@@ -18,39 +18,31 @@
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
-import android.content.Context;
import android.content.Intent;
-import android.graphics.Typeface;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings.Global;
-import android.text.Annotation;
-import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.style.URLSpan;
import android.util.Log;
import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.internal.util.CharSequences;
import com.android.settings.ChooseLockGeneric;
import com.android.settings.ChooseLockSettingsHelper;
-import com.android.settingslib.HelpUtils;
import com.android.settings.R;
-import com.android.setupwizardlib.SetupWizardRecyclerLayout;
-import com.android.setupwizardlib.items.IItem;
-import com.android.setupwizardlib.items.Item;
-import com.android.setupwizardlib.items.RecyclerItemAdapter;
+import com.android.settingslib.HelpUtils;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.setupwizardlib.span.LinkSpan;
/**
* Onboarding activity for fingerprint enrollment.
*/
public class FingerprintEnrollIntroduction extends FingerprintEnrollBase
- implements RecyclerItemAdapter.OnItemSelectedListener {
+ implements View.OnClickListener, LinkSpan.OnClickListener {
+
+ private static final String TAG = "FingerprintIntro";
protected static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
protected static final int FINGERPRINT_FIND_SENSOR_REQUEST = 2;
@@ -58,31 +50,26 @@
private UserManager mUserManager;
private boolean mHasPassword;
+ private boolean mFingerprintUnlockDisabledByAdmin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mFingerprintUnlockDisabledByAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ this, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId) != null;
+
setContentView(R.layout.fingerprint_enroll_introduction);
- setHeaderText(R.string.security_settings_fingerprint_enroll_introduction_title);
- final SetupWizardRecyclerLayout layout =
- (SetupWizardRecyclerLayout) findViewById(R.id.setup_wizard_layout);
- mUserManager = UserManager.get(this);
- final RecyclerItemAdapter adapter = (RecyclerItemAdapter) layout.getAdapter();
- adapter.setOnItemSelectedListener(this);
- Item item = (Item) adapter.findItemById(R.id.fingerprint_introduction_message);
- String linkUrl = getString(R.string.help_url_fingerprint);
- if (Global.getInt(getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) {
- // If the device is not provisioned, help intents from HelpUtils will be null, so don't
- // show the link at all.
- linkUrl = "";
+ if (mFingerprintUnlockDisabledByAdmin) {
+ setHeaderText(R.string
+ .security_settings_fingerprint_enroll_introduction_title_unlock_disabled);
+ } else {
+ setHeaderText(R.string.security_settings_fingerprint_enroll_introduction_title);
}
- item.setTitle(LearnMoreSpan.linkify(
- getText(R.string.security_settings_fingerprint_enroll_introduction_message),
- linkUrl));
- // setupwizard library automatically sets the divider inset to
- // R.dimen.suw_items_icon_divider_inset. We adjust this back to 0 as we do not want
- // an inset within settings.
- layout.setDividerInset(0);
+
+ final Button cancelButton = (Button) findViewById(R.id.fingerprint_cancel_button);
+ cancelButton.setOnClickListener(this);
+
+ mUserManager = UserManager.get(this);
updatePasswordQuality();
}
@@ -93,6 +80,11 @@
}
@Override
+ protected Button getNextButton() {
+ return (Button) findViewById(R.id.fingerprint_next_button);
+ }
+
+ @Override
protected void onNextButtonClick() {
if (!mHasPassword) {
// No fingerprints registered, launch into enrollment wizard.
@@ -134,8 +126,7 @@
}
protected Intent getFindSensorIntent() {
- Intent intent = new Intent(this, FingerprintEnrollFindSensor.class);
- return intent;
+ return new Intent(this, FingerprintEnrollFindSensor.class);
}
@Override
@@ -156,19 +147,18 @@
launchFindSensor(token);
return;
}
+ } else if (requestCode == LEARN_MORE_REQUEST) {
+ overridePendingTransition(R.anim.suw_slide_back_in, R.anim.suw_slide_back_out);
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
- public void onItemSelected(IItem item) {
- switch (((Item) item).getId()) {
- case R.id.next_button:
- onNextButtonClick();
- break;
- case R.id.cancel_button:
- onCancelButtonClick();
- break;
+ public void onClick(View v) {
+ if (v.getId() == R.id.fingerprint_cancel_button) {
+ onCancelButtonClick();
+ } else {
+ super.onClick(v);
}
}
@@ -181,61 +171,32 @@
finish();
}
- private static class LearnMoreSpan extends URLSpan {
- private static final String TAG = "LearnMoreSpan";
- private static final Typeface TYPEFACE_MEDIUM =
- Typeface.create("sans-serif-medium", Typeface.NORMAL);
+ @Override
+ protected void initViews() {
+ super.initViews();
- private LearnMoreSpan(String url) {
- super(url);
+ TextView description = (TextView) findViewById(R.id.description_text);
+ if (mFingerprintUnlockDisabledByAdmin) {
+ description.setText(R.string
+ .security_settings_fingerprint_enroll_introduction_message_unlock_disabled);
}
+ }
- @Override
- public void onClick(View widget) {
- Context ctx = widget.getContext();
- Intent intent = HelpUtils.getHelpIntent(ctx, getURL(), ctx.getClass().getName());
+ @Override
+ public void onClick(LinkSpan span) {
+ if ("url".equals(span.getId())) {
+ String url = getString(R.string.help_url_fingerprint);
+ Intent intent = HelpUtils.getHelpIntent(this, url, getClass().getName());
if (intent == null) {
- Log.w(LearnMoreSpan.TAG, "Null help intent.");
+ Log.w(TAG, "Null help intent.");
return;
}
try {
// This needs to be startActivityForResult even though we do not care about the
// actual result because the help app needs to know about who invoked it.
- widget.startActivityForResult(intent, LEARN_MORE_REQUEST);
+ startActivityForResult(intent, LEARN_MORE_REQUEST);
} catch (ActivityNotFoundException e) {
- Log.w(LearnMoreSpan.TAG,
- "Actvity was not found for intent, " + intent.toString());
- }
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- super.updateDrawState(ds);
- ds.setUnderlineText(false);
- ds.setTypeface(TYPEFACE_MEDIUM);
- }
-
- public static CharSequence linkify(CharSequence rawText, String uri) {
- SpannableString msg = new SpannableString(rawText);
- Annotation[] spans = msg.getSpans(0, msg.length(), Annotation.class);
- if (TextUtils.isEmpty(uri)) {
- CharSequence ret = rawText;
- for (Annotation annotation : spans) {
- int start = msg.getSpanStart(annotation);
- int end = msg.getSpanEnd(annotation);
- ret = TextUtils.concat(ret.subSequence(0, start),
- msg.subSequence(end, msg.length()));
- }
- return ret;
- } else {
- SpannableStringBuilder builder = new SpannableStringBuilder(msg);
- for (Annotation annotation : spans) {
- int start = msg.getSpanStart(annotation);
- int end = msg.getSpanEnd(annotation);
- LearnMoreSpan link = new LearnMoreSpan(uri);
- builder.setSpan(link, start, end, msg.getSpanFlags(link));
- }
- return builder;
+ Log.w(TAG, "Activity was not found for intent, " + e);
}
}
}
diff --git a/src/com/android/settings/fingerprint/FingerprintLocationAnimationVideoView.java b/src/com/android/settings/fingerprint/FingerprintLocationAnimationVideoView.java
index 5236272..9f12286 100644
--- a/src/com/android/settings/fingerprint/FingerprintLocationAnimationVideoView.java
+++ b/src/com/android/settings/fingerprint/FingerprintLocationAnimationVideoView.java
@@ -41,7 +41,6 @@
public FingerprintLocationAnimationVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
-
}
@Override
@@ -52,15 +51,28 @@
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
+ protected Uri getFingerprintLocationAnimation() {
+ return resourceEntryToUri(getContext(), R.raw.fingerprint_location_animation);
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
setSurfaceTextureListener(new SurfaceTextureListener() {
+ private SurfaceTexture mTextureToDestroy = null;
+
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
int height) {
setVisibility(View.INVISIBLE);
- Uri videoUri = resourceEntryToUri(mContext, R.raw.fingerprint_location_animation);
+ Uri videoUri = getFingerprintLocationAnimation();
+ if (mMediaPlayer != null) {
+ mMediaPlayer.release();
+ }
+ if (mTextureToDestroy != null) {
+ mTextureToDestroy.release();
+ mTextureToDestroy = null;
+ }
mMediaPlayer = MediaPlayer.create(mContext, videoUri);
mMediaPlayer.setSurface(new Surface(surfaceTexture));
mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
@@ -91,6 +103,7 @@
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ mTextureToDestroy = surfaceTexture;
return false;
}
@@ -100,7 +113,7 @@
});
}
- private static Uri resourceEntryToUri (Context context, int id) {
+ protected static Uri resourceEntryToUri (Context context, int id) {
Resources res = context.getResources();
return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
res.getResourcePackageName(id) + '/' +
diff --git a/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
index cc1d4fd..a26883a 100644
--- a/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
+++ b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
@@ -19,17 +19,18 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.annotation.ColorInt;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
-import android.util.TypedValue;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.settings.R;
+import com.android.settings.Utils;
/**
* View which plays an animation to indicate where the sensor is on the device.
@@ -61,13 +62,11 @@
R.fraction.fingerprint_sensor_location_fraction_x, 1, 1);
mFractionCenterY = getResources().getFraction(
R.fraction.fingerprint_sensor_location_fraction_y, 1, 1);
- TypedValue typedValue = new TypedValue();
- context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
- int color = getResources().getColor(typedValue.resourceId, null);
+ @ColorInt int colorAccent = Utils.getColorAccent(context);
mDotPaint.setAntiAlias(true);
mPulsePaint.setAntiAlias(true);
- mDotPaint.setColor(color);
- mPulsePaint.setColor(color);
+ mDotPaint.setColor(colorAccent);
+ mPulsePaint.setColor(colorAccent);
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
android.R.interpolator.linear_out_slow_in);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
diff --git a/src/com/android/settings/fingerprint/FingerprintSettings.java b/src/com/android/settings/fingerprint/FingerprintSettings.java
index 6fd2d14..c1d5d7e 100644
--- a/src/com/android/settings/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/fingerprint/FingerprintSettings.java
@@ -357,6 +357,7 @@
pref.setTitle(item.getName());
pref.setFingerprint(item);
pref.setPersistent(false);
+ pref.setIcon(R.drawable.ic_fingerprint_24dp);
root.addPreference(pref);
pref.setOnPreferenceChangeListener(this);
}
@@ -717,15 +718,15 @@
super(context, attrs, defStyleAttr, defStyleRes);
}
public FingerprintPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
+ super(context, attrs, defStyleAttr);
}
public FingerprintPreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.preferenceStyle);
+ super(context, attrs);
}
public FingerprintPreference(Context context) {
- this(context, null);
+ super(context);
}
public View getView() { return mView; }
diff --git a/src/com/android/settings/fingerprint/FingerprintUiHelper.java b/src/com/android/settings/fingerprint/FingerprintUiHelper.java
index 6e7f8ec..f7ec97b 100644
--- a/src/com/android/settings/fingerprint/FingerprintUiHelper.java
+++ b/src/com/android/settings/fingerprint/FingerprintUiHelper.java
@@ -67,7 +67,7 @@
}
}
- private boolean isListening() {
+ public boolean isListening() {
return mCancellationSignal != null && !mCancellationSignal.isCanceled();
}
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
index b037c2b..8bd495e 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
@@ -31,11 +31,8 @@
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
-import com.android.setupwizardlib.util.SystemBarHelper;
-import com.android.setupwizardlib.view.NavigationBar;
-public class SetupFingerprintEnrollEnrolling extends FingerprintEnrollEnrolling
- implements NavigationBar.NavigationBarListener {
+public class SetupFingerprintEnrollEnrolling extends FingerprintEnrollEnrolling {
private static final String TAG_DIALOG = "dialog";
@@ -54,32 +51,21 @@
@Override
protected void initViews() {
- SetupWizardUtils.setImmersiveMode(this);
+ super.initViews();
+ final Button skipButton = (Button) findViewById(R.id.skip_button);
+ skipButton.setVisibility(View.VISIBLE);
+ skipButton.setOnClickListener(this);
+ }
- final View buttonBar = findViewById(R.id.button_bar);
- if (buttonBar != null) {
- buttonBar.setVisibility(View.GONE);
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.skip_button:
+ new SkipDialog().show(getFragmentManager(), TAG_DIALOG);
+ break;
+ default:
+ super.onClick(v);
}
-
- final NavigationBar navigationBar = getNavigationBar();
- navigationBar.setNavigationBarListener(this);
- navigationBar.getNextButton().setText(R.string.skip_label);
- navigationBar.getBackButton().setVisibility(View.GONE);
- }
-
- @Override
- protected Button getNextButton() {
- return getNavigationBar().getNextButton();
- }
-
- @Override
- public void onNavigateBack() {
- onBackPressed();
- }
-
- @Override
- public void onNavigateNext() {
- new SkipDialog().show(getFragmentManager(), TAG_DIALOG);
}
@Override
@@ -102,7 +88,7 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final AlertDialog dialog = new AlertDialog.Builder(getActivity())
+ return new AlertDialog.Builder(getActivity())
.setTitle(R.string.setup_fingerprint_enroll_enrolling_skip_title)
.setMessage(R.string.setup_fingerprint_enroll_enrolling_skip_message)
.setCancelable(false)
@@ -124,8 +110,6 @@
}
})
.create();
- SystemBarHelper.hideSystemBars(dialog);
- return dialog;
}
}
}
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
index 9cf5369..baf4fcd 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
@@ -19,21 +19,17 @@
import android.content.Intent;
import android.content.res.Resources;
import android.os.UserHandle;
-import android.view.View;
-import android.widget.Button;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.ChooseLockSettingsHelper;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
-import com.android.setupwizardlib.view.NavigationBar;
-public class SetupFingerprintEnrollFindSensor extends FingerprintEnrollFindSensor
- implements NavigationBar.NavigationBarListener {
+public class SetupFingerprintEnrollFindSensor extends FingerprintEnrollFindSensor {
@Override
protected int getContentView() {
- return R.layout.setup_fingerprint_enroll_find_sensor;
+ return R.layout.fingerprint_enroll_find_sensor;
}
@Override
@@ -54,34 +50,6 @@
}
@Override
- protected void initViews() {
- SetupWizardUtils.setImmersiveMode(this);
-
- final View nextButton = findViewById(R.id.next_button);
- if (nextButton != null) {
- nextButton.setVisibility(View.GONE);
- }
-
- getNavigationBar().setNavigationBarListener(this);
- getNavigationBar().getBackButton().setVisibility(View.GONE);
- }
-
- @Override
- protected Button getNextButton() {
- return getNavigationBar().getNextButton();
- }
-
- @Override
- public void onNavigateBack() {
- onBackPressed();
- }
-
- @Override
- public void onNavigateNext() {
- onNextButtonClick();
- }
-
- @Override
protected int getMetricsCategory() {
return MetricsEvent.FINGERPRINT_FIND_SENSOR_SETUP;
}
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java
index b17ed09..f6602f3 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java
@@ -20,17 +20,14 @@
import android.content.res.Resources;
import android.os.UserHandle;
import android.view.View;
-import android.widget.Button;
import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.ChooseLockSettingsHelper;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
-import com.android.setupwizardlib.view.NavigationBar;
-public class SetupFingerprintEnrollFinish extends FingerprintEnrollFinish
- implements NavigationBar.NavigationBarListener {
+public class SetupFingerprintEnrollFinish extends FingerprintEnrollFinish {
@Override
protected Intent getEnrollingIntent() {
@@ -51,16 +48,7 @@
@Override
protected void initViews() {
- SetupWizardUtils.setImmersiveMode(this);
-
- final View nextButton = findViewById(R.id.next_button);
- if (nextButton != null) {
- nextButton.setVisibility(View.GONE);
- }
-
- final NavigationBar navigationBar = getNavigationBar();
- navigationBar.setNavigationBarListener(this);
- navigationBar.getBackButton().setVisibility(View.GONE);
+ super.initViews();
final TextView message = (TextView) findViewById(R.id.message);
message.setText(R.string.setup_fingerprint_enroll_finish_message);
@@ -70,21 +58,6 @@
}
@Override
- protected Button getNextButton() {
- return getNavigationBar().getNextButton();
- }
-
- @Override
- public void onNavigateBack() {
- onBackPressed();
- }
-
- @Override
- public void onNavigateNext() {
- onNextButtonClick();
- }
-
- @Override
protected int getMetricsCategory() {
return MetricsEvent.FINGERPRINT_ENROLL_FINISH_SETUP;
}
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
index f816682..e7f4cfe 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -20,19 +20,15 @@
import android.content.res.Resources;
import android.os.UserHandle;
import android.widget.Button;
+import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupChooseLockGeneric;
import com.android.settings.SetupWizardUtils;
-import com.android.setupwizardlib.SetupWizardRecyclerLayout;
-import com.android.setupwizardlib.items.Item;
-import com.android.setupwizardlib.items.RecyclerItemAdapter;
-import com.android.setupwizardlib.view.NavigationBar;
-public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction
- implements NavigationBar.NavigationBarListener {
+public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
@Override
protected Intent getChooseLockIntent() {
@@ -56,24 +52,19 @@
@Override
protected void initViews() {
- final SetupWizardRecyclerLayout layout =
- (SetupWizardRecyclerLayout) findViewById(R.id.setup_wizard_layout);
- final RecyclerItemAdapter adapter = (RecyclerItemAdapter) layout.getAdapter();
- final Item nextItem = (Item) adapter.findItemById(R.id.next_button);
- nextItem.setTitle(
- getText(R.string.security_settings_fingerprint_enroll_introduction_continue_setup));
+ super.initViews();
- final Item cancelItem = (Item) adapter.findItemById(R.id.cancel_button);
- cancelItem.setTitle(
- getText(R.string.security_settings_fingerprint_enroll_introduction_cancel_setup));
+ TextView description = (TextView) findViewById(R.id.description_text);
+ description.setText(
+ R.string.security_settings_fingerprint_enroll_introduction_message_setup);
- SetupWizardUtils.setImmersiveMode(this);
- getNavigationBar().setNavigationBarListener(this);
- Button nextButton = getNavigationBar().getNextButton();
- nextButton.setText(null);
- nextButton.setEnabled(false);
- layout.setDividerInset(getResources().getDimensionPixelSize(
- R.dimen.suw_items_icon_divider_inset));
+ Button nextButton = getNextButton();
+ nextButton.setText(
+ R.string.security_settings_fingerprint_enroll_introduction_continue_setup);
+
+ final Button cancelButton = (Button) findViewById(R.id.fingerprint_cancel_button);
+ cancelButton.setText(
+ R.string.security_settings_fingerprint_enroll_introduction_cancel_setup);
}
@Override
@@ -98,16 +89,6 @@
}
@Override
- public void onNavigateBack() {
- onBackPressed();
- }
-
- @Override
- public void onNavigateNext() {
- // next is handled via the onNextButtonClick method in FingerprintEnrollIntroduction
- }
-
- @Override
protected int getMetricsCategory() {
return MetricsEvent.FINGERPRINT_ENROLL_INTRO_SETUP;
}
diff --git a/src/com/android/settings/fingerprint/SetupSkipDialog.java b/src/com/android/settings/fingerprint/SetupSkipDialog.java
index 11e6936..c6e04d7 100644
--- a/src/com/android/settings/fingerprint/SetupSkipDialog.java
+++ b/src/com/android/settings/fingerprint/SetupSkipDialog.java
@@ -22,17 +22,10 @@
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
-import android.os.Build.VERSION;
-import android.os.Build.VERSION_CODES;
import android.os.Bundle;
-import android.os.Handler;
import android.support.annotation.NonNull;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
import com.android.settings.R;
-import com.android.setupwizardlib.util.SystemBarHelper;
public class SetupSkipDialog extends DialogFragment implements DialogInterface.OnClickListener {
@@ -52,10 +45,7 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final AlertDialog dialog = onCreateDialogBuilder().create();
- // hide system status bar.
- SystemBarHelper.hideSystemBars(dialog);
- return dialog;
+ return onCreateDialogBuilder().create();
}
@NonNull
diff --git a/src/com/android/settings/fuelgauge/BatterySaverSettings.java b/src/com/android/settings/fuelgauge/BatterySaverSettings.java
index bd19db8..e19f683 100644
--- a/src/com/android/settings/fuelgauge/BatterySaverSettings.java
+++ b/src/com/android/settings/fuelgauge/BatterySaverSettings.java
@@ -25,6 +25,7 @@
import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
@@ -186,23 +187,36 @@
};
private final class Receiver extends BroadcastReceiver {
+
private boolean mRegistered;
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Received " + intent.getAction());
- mHandler.post(mUpdateSwitch);
+ String action = intent.getAction();
+ if (action.equals(ACTION_POWER_SAVE_MODE_CHANGING)) {
+ mHandler.post(mUpdateSwitch);
+ } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+ // disable BSM switch if phone is plugged in or at 100% while plugged in
+ mSwitchBar.setEnabled(
+ !(status == BatteryManager.BATTERY_STATUS_CHARGING
+ || status == BatteryManager.BATTERY_STATUS_FULL));
+ }
}
-
public void setListening(boolean listening) {
if (listening && !mRegistered) {
- mContext.registerReceiver(this, new IntentFilter(ACTION_POWER_SAVE_MODE_CHANGING));
+ final IntentFilter ifilter = new IntentFilter();
+ ifilter.addAction(ACTION_POWER_SAVE_MODE_CHANGING);
+ ifilter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ mContext.registerReceiver(this, ifilter);
mRegistered = true;
} else if (!listening && mRegistered) {
mContext.unregisterReceiver(this);
mRegistered = false;
}
}
+
}
private final class SettingsObserver extends ContentObserver {
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index 80adb67..4faa832 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -274,4 +274,14 @@
public Timer getBluetoothScanTimer() {
return null;
}
+
+ @Override
+ public long getWifiRadioApWakeupCount(int which) {
+ return 0;
+ }
+
+ @Override
+ public long getMobileRadioApWakeupCount(int which) {
+ return 0;
+ }
}
diff --git a/src/com/android/settings/gestures/GesturePreference.java b/src/com/android/settings/gestures/GesturePreference.java
new file mode 100644
index 0000000..4536aa2
--- /dev/null
+++ b/src/com/android/settings/gestures/GesturePreference.java
@@ -0,0 +1,241 @@
+/*
+ * 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.gestures;
+
+import android.app.LoaderManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Loader;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.SurfaceTexture;
+import android.media.MediaMetadataRetriever;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.view.View;
+import android.view.Surface;
+import android.view.TextureView;
+import android.widget.ImageView;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.utils.AsyncLoader;
+
+/**
+ * Preference item for a gesture with a switch to signify if it should be enabled.
+ * This shows the title and description of the gesture along with an animation showing how to do
+ * the gesture
+ */
+public final class GesturePreference extends SwitchPreference implements
+ LoaderManager.LoaderCallbacks<Bitmap> {
+ private static final String TAG = "GesturePreference";
+ private final Context mContext;
+
+ private Uri mVideoPath;
+ private MediaPlayer mMediaPlayer;
+ private boolean mAnimationAvailable;
+ private boolean mVideoReady;
+ private boolean mScrolling;
+ private BitmapDrawable mPreviewImage;
+
+ public GesturePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ TypedArray attributes = context.getTheme().obtainStyledAttributes(
+ attrs,
+ R.styleable.GesturePreference,
+ 0, 0);
+ try {
+ int animation = attributes.getResourceId(R.styleable.GesturePreference_animation, 0);
+ mVideoPath = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(context.getPackageName())
+ .appendPath(String.valueOf(animation))
+ .build();
+ mMediaPlayer = MediaPlayer.create(mContext, mVideoPath);
+ if (mMediaPlayer != null && mMediaPlayer.getDuration() > 0) {
+ setLayoutResource(R.layout.gesture_preference);
+ mMediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
+ @Override
+ public void onSeekComplete(MediaPlayer mp) {
+ mVideoReady = true;
+ }
+ });
+
+ mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mediaPlayer) {
+ mediaPlayer.setLooping(true);
+ }
+ });
+ mAnimationAvailable = true;
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Animation resource not found. Will not show animation.");
+ } finally {
+ attributes.recycle();
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ if (!mAnimationAvailable) {
+ return;
+ }
+
+ final TextureView video = (TextureView) holder.findViewById(R.id.gesture_video);
+ final ImageView imageView = (ImageView) holder.findViewById(R.id.gesture_image);
+ final ImageView playButton = (ImageView) holder.findViewById(R.id.gesture_play_button);
+
+ video.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mMediaPlayer != null) {
+ if (mMediaPlayer.isPlaying()) {
+ mMediaPlayer.pause();
+ playButton.setVisibility(View.VISIBLE);
+ } else {
+ mMediaPlayer.start();
+ playButton.setVisibility(View.GONE);
+ }
+ }
+ }
+ });
+
+ video.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
+ int height) {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.setSurface(new Surface(surfaceTexture));
+ mVideoReady = false;
+ mMediaPlayer.seekTo(0);
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
+ int height) {
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ if (mPreviewImage != null && imageView.getDrawable() == null) {
+ imageView.setImageDrawable(mPreviewImage);
+ }
+ imageView.setVisibility(View.VISIBLE);
+ return false;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+ if (mVideoReady && imageView.getVisibility() == View.VISIBLE) {
+ imageView.setVisibility(View.GONE);
+ } else if (mScrolling) {
+ mScrolling = false;
+ if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
+ mMediaPlayer.pause();
+ playButton.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+ });
+
+ if (mPreviewImage != null) {
+ imageView.setImageDrawable(mPreviewImage);
+ }
+
+ }
+
+ @Override
+ public void onDetached() {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.stop();
+ mMediaPlayer.reset();
+ mMediaPlayer.release();
+ }
+ super.onDetached();
+ }
+
+ void setScrolling(boolean scrolling) {
+ mScrolling = scrolling;
+ }
+
+ void loadPreview(LoaderManager manager, int id) {
+ if (mAnimationAvailable) {
+ Loader<Bitmap> loader = manager.initLoader(id, Bundle.EMPTY, this);
+ }
+ }
+
+ void onViewVisible() {
+ if (mVideoReady && mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
+ mMediaPlayer.seekTo(0);
+ }
+ }
+
+ private static final class PreviewRetriever extends AsyncLoader<Bitmap> {
+ private Uri mVideoPath;
+
+ public PreviewRetriever(Context context, Uri videoPath) {
+ super(context);
+ mVideoPath = videoPath;
+ }
+
+ @Override
+ public Bitmap loadInBackground() {
+ MediaMetadataRetriever mediaMetadata = new MediaMetadataRetriever();
+ try {
+ mediaMetadata.setDataSource(getContext(), mVideoPath);
+ return mediaMetadata.getFrameAtTime(0);
+ } catch (Exception e) {
+ Log.w(TAG, "Unable to get animation preview.");
+ } finally {
+ mediaMetadata.release();
+ }
+ return null;
+ }
+
+ @Override
+ public void onDiscardResult(final Bitmap result) {
+ if (result != null && !result.isRecycled()) {
+ result.recycle();
+ }
+ }
+
+ }
+
+ @Override
+ public Loader<Bitmap> onCreateLoader(int id, Bundle args) {
+ return new PreviewRetriever(mContext, mVideoPath);
+ }
+
+ @Override
+ public void onLoadFinished(final Loader<Bitmap> loader, final Bitmap bitmap) {
+ if (bitmap != null) {
+ mPreviewImage = new BitmapDrawable(mContext.getResources(), bitmap);
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Bitmap> loader) {
+ }
+
+}
diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java
new file mode 100644
index 0000000..14df471
--- /dev/null
+++ b/src/com/android/settings/gestures/GestureSettings.java
@@ -0,0 +1,282 @@
+/*
+ * 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.gestures;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.SystemProperties;
+import android.provider.SearchIndexableResource;
+import android.provider.Settings.Secure;
+import android.support.v7.preference.Preference;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Top level fragment for gesture settings.
+ * This will create individual switch preference for each gesture and handle updates when each
+ * preference is updated
+ */
+public class GestureSettings extends SettingsPreferenceFragment implements
+ Preference.OnPreferenceChangeListener, Indexable {
+
+ private static final String TAG = "GestureSettings";
+ private static final String PREF_KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
+ private static final String PREF_KEY_DOUBLE_TWIST = "gesture_double_twist";
+ private static final String PREF_KEY_PICK_UP = "gesture_pick_up";
+ private static final String PREF_KEY_SWIPE_DOWN_FINGERPRINT = "gesture_swipe_down_fingerprint";
+ private static final String PREF_KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
+ private static final String DEBUG_DOZE_COMPONENT = "debug.doze.component";
+ private static final int PREF_ID_DOUBLE_TAP_POWER = 0;
+ private static final int PREF_ID_DOUBLE_TWIST = 1;
+ private static final int PREF_ID_PICK_UP = 2;
+ private static final int PREF_ID_SWIPE_DOWN_FINGERPRINT = 3;
+ private static final int PREF_ID_DOUBLE_TAP_SCREEN = 4;
+
+ private List<GesturePreference> mPreferences;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.gesture_settings);
+ Context context = getActivity();
+ mPreferences = new ArrayList();
+
+ // Double tap power for camera
+ if (isCameraDoubleTapPowerGestureAvailable(getResources())) {
+ int cameraDisabled = Secure.getInt(
+ getContentResolver(), Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
+ addPreference(PREF_KEY_DOUBLE_TAP_POWER, cameraDisabled == 0, PREF_ID_DOUBLE_TAP_POWER);
+ } else {
+ removePreference(PREF_KEY_DOUBLE_TAP_POWER);
+ }
+
+ // Ambient Display
+ boolean dozeEnabled = isDozeAvailable(context);
+ if (dozeEnabled && isPickupAvailable(context)) {
+ int pickup = Secure.getInt(getContentResolver(), Secure.DOZE_PULSE_ON_PICK_UP, 1);
+ addPreference(PREF_KEY_PICK_UP, pickup != 0, PREF_ID_PICK_UP);
+ } else {
+ removePreference(PREF_KEY_PICK_UP);
+ }
+ if (dozeEnabled && isDoubleTapAvailable(context)) {
+ int doubleTap = Secure.getInt(getContentResolver(), Secure.DOZE_PULSE_ON_DOUBLE_TAP, 1);
+ addPreference(PREF_KEY_DOUBLE_TAP_SCREEN, doubleTap != 0, PREF_ID_DOUBLE_TAP_SCREEN);
+ } else {
+ removePreference(PREF_KEY_DOUBLE_TAP_SCREEN);
+ }
+
+ // Fingerprint slide for notifications
+ if (isSystemUINavigationAvailable(context)) {
+ addPreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT, isSystemUINavigationEnabled(context),
+ PREF_ID_SWIPE_DOWN_FINGERPRINT);
+ } else {
+ removePreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT);
+ }
+
+ // Double twist for camera mode
+ if (isDoubleTwistAvailable(context)) {
+ int doubleTwistEnabled = Secure.getInt(
+ getContentResolver(), Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1);
+ addPreference(PREF_KEY_DOUBLE_TWIST, doubleTwistEnabled != 0, PREF_ID_DOUBLE_TWIST);
+ } else {
+ removePreference(PREF_KEY_DOUBLE_TWIST);
+ }
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+ RecyclerView listview = getListView();
+ listview.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
+ for (GesturePreference pref : mPreferences) {
+ pref.setScrolling(true);
+ }
+ } else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+ for (GesturePreference pref : mPreferences) {
+ pref.setScrolling(false);
+ }
+ }
+ }
+
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ }
+ });
+ return view;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ for (GesturePreference preference : mPreferences) {
+ preference.onViewVisible();
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enabled = (boolean) newValue;
+ String key = preference.getKey();
+ if (PREF_KEY_DOUBLE_TAP_POWER.equals(key)) {
+ Secure.putInt(getContentResolver(),
+ Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, enabled ? 0 : 1);
+ } else if (PREF_KEY_PICK_UP.equals(key)) {
+ Secure.putInt(getContentResolver(), Secure.DOZE_PULSE_ON_PICK_UP, enabled ? 1 : 0);
+ } else if (PREF_KEY_DOUBLE_TAP_SCREEN.equals(key)) {
+ Secure.putInt(getContentResolver(), Secure.DOZE_PULSE_ON_DOUBLE_TAP, enabled ? 1 : 0);
+ } else if (PREF_KEY_SWIPE_DOWN_FINGERPRINT.equals(key)) {
+ Secure.putInt(getContentResolver(),
+ Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, enabled ? 1 : 0);
+ } else if (PREF_KEY_DOUBLE_TWIST.equals(key)) {
+ Secure.putInt(getContentResolver(),
+ Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, enabled ? 1 : 0);
+ }
+ return true;
+ }
+
+ @Override
+ protected int getHelpResource() {
+ return R.string.help_url_gestures;
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsEvent.SETTINGS_GESTURES;
+ }
+
+ private static boolean isCameraDoubleTapPowerGestureAvailable(Resources res) {
+ return res.getBoolean(
+ com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
+ }
+
+ private static boolean isDozeAvailable(Context context) {
+ String name = Build.IS_DEBUGGABLE ? SystemProperties.get(DEBUG_DOZE_COMPONENT) : null;
+ if (TextUtils.isEmpty(name)) {
+ name = context.getResources().getString(
+ com.android.internal.R.string.config_dozeComponent);
+ }
+ return !TextUtils.isEmpty(name);
+ }
+
+ private static boolean isSystemUINavigationAvailable(Context context) {
+ return context.getResources().getBoolean(
+ com.android.internal.R.bool.config_supportSystemNavigationKeys);
+ }
+
+ private static boolean isSystemUINavigationEnabled(Context context) {
+ return Secure.getInt(context.getContentResolver(), Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0)
+ == 1;
+ }
+
+ private static boolean isDoubleTwistAvailable(Context context) {
+ return hasSensor(context, R.string.gesture_double_twist_sensor_name,
+ R.string.gesture_double_twist_sensor_vendor);
+ }
+
+ private static boolean isPickupAvailable(Context context) {
+ return hasSensor(context, R.string.gesture_pickup_sensor_name,
+ R.string.gesture_pickup_sensor_vendor);
+ }
+
+ private static boolean hasSensor(Context context, int nameResId, int vendorResId) {
+ Resources resources = context.getResources();
+ String name = resources.getString(nameResId);
+ String vendor = resources.getString(vendorResId);
+ if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(vendor)) {
+ SensorManager sensorManager =
+ (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ for (Sensor s : sensorManager.getSensorList(Sensor.TYPE_ALL)) {
+ if (name.equals(s.getName()) && vendor.equals(s.getVendor())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean isDoubleTapAvailable(Context context) {
+ return context.getResources().getBoolean(
+ R.bool.config_gesture_double_tap_settings_enabled);
+ }
+
+ private void addPreference(String key, boolean enabled, int id) {
+ GesturePreference preference = (GesturePreference) findPreference(key);
+ preference.setChecked(enabled);
+ preference.setOnPreferenceChangeListener(this);
+ preference.loadPreview(getLoaderManager(), id);
+ mPreferences.add(preference);
+ }
+
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ ArrayList<SearchIndexableResource> result =
+ new ArrayList<SearchIndexableResource>();
+
+ SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.gesture_settings;
+ result.add(sir);
+
+ return result;
+ }
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ ArrayList<String> result = new ArrayList<String>();
+ if (!isCameraDoubleTapPowerGestureAvailable(context.getResources())) {
+ result.add(PREF_KEY_DOUBLE_TAP_POWER);
+ }
+ if (!isDozeAvailable(context) || !isPickupAvailable(context)) {
+ result.add(PREF_KEY_PICK_UP);
+ }
+ if (!isDozeAvailable(context) || !isDoubleTapAvailable(context)) {
+ result.add(PREF_KEY_DOUBLE_TAP_SCREEN);
+ }
+ if (!isSystemUINavigationAvailable(context)) {
+ result.add(PREF_KEY_SWIPE_DOWN_FINGERPRINT);
+ }
+ if (!isDoubleTwistAvailable(context)) {
+ result.add(PREF_KEY_DOUBLE_TWIST);
+ }
+ return result;
+ }
+ };
+
+}
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
index 1d4fa67..b2c2800 100755
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -142,18 +142,22 @@
}
if (isChecked()) {
// Disable this IME.
- setChecked(false);
- mOnSaveListener.onSaveInputMethodPreference(this);
+ setCheckedInternal(false);
return false;
}
if (InputMethodUtils.isSystemIme(mImi)) {
- // Enable a system IME. No need to show a security warning dialog.
- setChecked(true);
- mOnSaveListener.onSaveInputMethodPreference(this);
- return false;
+ // Enable a system IME. No need to show a security warning dialog,
+ // but we might need to prompt if it's not Direct Boot aware.
+ if (mImi.getServiceInfo().directBootAware) {
+ setCheckedInternal(true);
+ } else {
+ showDirectBootWarnDialog();
+ }
+ } else {
+ // Once security is confirmed, we might prompt if the IME isn't
+ // Direct Boot aware.
+ showSecurityWarnDialog();
}
- // Enable a 3rd party IME.
- showSecurityWarnDialog(mImi);
return false;
}
@@ -218,7 +222,13 @@
subtypes, getContext(), mImi);
}
- private void showSecurityWarnDialog(final InputMethodInfo imi) {
+ private void setCheckedInternal(boolean checked) {
+ super.setChecked(checked);
+ mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
+ notifyChanged();
+ }
+
+ private void showSecurityWarnDialog() {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
@@ -226,25 +236,50 @@
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true /* cancelable */);
builder.setTitle(android.R.string.dialog_alert_title);
- final CharSequence label = imi.getServiceInfo().applicationInfo.loadLabel(
+ final CharSequence label = mImi.getServiceInfo().applicationInfo.loadLabel(
context.getPackageManager());
builder.setMessage(context.getString(R.string.ime_security_warning, label));
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
- // The user confirmed to enable a 3rd party IME.
- setChecked(true);
- mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
- notifyChanged();
+ // The user confirmed to enable a 3rd party IME, but we might
+ // need to prompt if it's not Direct Boot aware.
+ if (mImi.getServiceInfo().directBootAware) {
+ setCheckedInternal(true);
+ } else {
+ showDirectBootWarnDialog();
+ }
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
// The user canceled to enable a 3rd party IME.
- setChecked(false);
- mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
- notifyChanged();
+ setCheckedInternal(false);
+ }
+ });
+ mDialog = builder.create();
+ mDialog.show();
+ }
+
+ private void showDirectBootWarnDialog() {
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ final Context context = getContext();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setCancelable(true /* cancelable */);
+ builder.setMessage(context.getText(R.string.direct_boot_unaware_dialog_message));
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(final DialogInterface dialog, final int which) {
+ setCheckedInternal(true);
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(final DialogInterface dialog, final int which) {
+ setCheckedInternal(false);
}
});
mDialog = builder.create();
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 84223b7..0f263f2 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -212,9 +212,9 @@
clearLoader();
mLastHardKeyboards.clear();
mLastHardKeyboards.addAll(newHardKeyboards);
+ mLoaderIDs.add(mNextLoaderId);
getLoaderManager().initLoader(mNextLoaderId, null,
new Callbacks(getContext(), this, mLastHardKeyboards));
- mLoaderIDs.add(mNextLoaderId);
++mNextLoaderId;
}
}
@@ -266,7 +266,7 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mSettings.setShowImeWithHardKeyboard((Boolean) newValue);
- return false;
+ return true;
}
};
diff --git a/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java b/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
index 638818a..98c4db2 100644
--- a/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
+++ b/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
@@ -87,7 +87,7 @@
mMode = MODE_EDIT;
mOldWord = oldInstanceToBeEdited.mSavedWord;
mOldShortcut = oldInstanceToBeEdited.mSavedShortcut;
- updateLocale(mLocale);
+ updateLocale(oldInstanceToBeEdited.getCurrentUserDictionaryLocale());
}
// locale may be null, this means default locale
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index f718b3c..fd7a750 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -33,10 +33,8 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.AppHeader;
import com.android.settings.R;
-import com.android.settings.applications.LayoutPreference;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.RestrictedPreference;
import java.util.List;
@@ -92,7 +90,8 @@
rows.put(mAppRow.pkg, mAppRow);
collectConfigActivities(rows);
- setupImportancePrefs(mAppRow.systemApp, mAppRow.appImportance, mAppRow.banned);
+ setupImportancePrefs(mAppRow.cantBlock, mAppRow.cantSilence,
+ mAppRow.appImportance, mAppRow.banned);
setupPriorityPref(mAppRow.appBypassDnd);
setupVisOverridePref(mAppRow.appVisOverride);
updateDependents(mAppRow.appImportance);
@@ -113,7 +112,8 @@
mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW);
}
setVisible(mPriority, checkCanBeVisible(Ranking.IMPORTANCE_DEFAULT, importance)
- && !mDndVisualEffectsSuppressed);
+ || (checkCanBeVisible(Ranking.IMPORTANCE_LOW, importance)
+ && mDndVisualEffectsSuppressed));
setVisible(mVisibilityOverride,
checkCanBeVisible(Ranking.IMPORTANCE_MIN, importance) && lockscreenSecure);
}
diff --git a/src/com/android/settings/notification/ImportanceSeekBarPreference.java b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
index b21f9ce..0617df9 100644
--- a/src/com/android/settings/notification/ImportanceSeekBarPreference.java
+++ b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
@@ -31,6 +31,7 @@
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
+import com.android.settings.Utils;
/**
* A slider preference that controls notification importance.
@@ -55,8 +56,7 @@
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setLayoutResource(R.layout.preference_importance_slider);
- mActiveSliderTint = ColorStateList.valueOf(
- context.getColor(R.color.importance_slider_color));
+ mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(context));
mInactiveSliderTint = ColorStateList.valueOf(
context.getColor(R.color.importance_disabled_slider_color));
mHandler = new Handler();
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index 9b05da4..f8c6788 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -59,7 +59,17 @@
public AppRow loadAppRow(Context context, PackageManager pm, PackageInfo app) {
final AppRow row = loadAppRow(context, pm, app.applicationInfo);
- row.systemApp = Utils.isSystemPackage(pm, app);
+ row.cantBlock = Utils.isSystemPackage(context.getResources(), pm, app);
+ final String[] nonBlockablePkgs = context.getResources().getStringArray(
+ com.android.internal.R.array.config_nonBlockableNotificationPackages);
+ if (nonBlockablePkgs != null) {
+ int N = nonBlockablePkgs.length;
+ for (int i = 0; i < N; i++) {
+ if (app.packageName.equals(nonBlockablePkgs[i])) {
+ row.cantBlock = row.cantSilence = true;
+ }
+ }
+ }
return row;
}
@@ -143,7 +153,8 @@
public Intent settingsIntent;
public boolean banned;
public boolean first; // first app in section
- public boolean systemApp;
+ public boolean cantBlock;
+ public boolean cantSilence;
public int appImportance;
public boolean appBypassDnd;
public int appVisOverride;
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
index bce42eb..0e637a7 100644
--- a/src/com/android/settings/notification/NotificationSettingsBase.java
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -154,13 +154,14 @@
}
}
- protected void setupImportancePrefs(boolean isSystemApp, int importance, boolean banned) {
- if (mShowSlider) {
+ protected void setupImportancePrefs(boolean notBlockable, boolean notSilenceable,
+ int importance, boolean banned) {
+ if (mShowSlider && !notSilenceable) {
setVisible(mBlock, false);
setVisible(mSilent, false);
mImportance.setDisabledByAdmin(mSuspendedAppsAdmin);
mImportance.setMinimumProgress(
- isSystemApp ? Ranking.IMPORTANCE_MIN : Ranking.IMPORTANCE_NONE);
+ notBlockable ? Ranking.IMPORTANCE_MIN : Ranking.IMPORTANCE_NONE);
mImportance.setMax(Ranking.IMPORTANCE_MAX);
mImportance.setProgress(importance);
mImportance.setAutoOn(importance == Ranking.IMPORTANCE_UNSPECIFIED);
@@ -175,7 +176,7 @@
});
} else {
setVisible(mImportance, false);
- if (isSystemApp) {
+ if (notBlockable) {
setVisible(mBlock, false);
} else {
boolean blocked = importance == Ranking.IMPORTANCE_NONE || banned;
@@ -191,7 +192,11 @@
return true;
}
});
-
+ }
+ if (notSilenceable) {
+ setVisible(mSilent, false);
+ } else {
+ mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW);
mSilent.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
@@ -203,8 +208,8 @@
return true;
}
});
- updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance);
}
+ updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance);
}
}
diff --git a/src/com/android/settings/notification/OtherSoundSettings.java b/src/com/android/settings/notification/OtherSoundSettings.java
index 2ea6a79..5fdb83a 100644
--- a/src/com/android/settings/notification/OtherSoundSettings.java
+++ b/src/com/android/settings/notification/OtherSoundSettings.java
@@ -25,10 +25,13 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
+import android.os.SystemProperties;
import android.os.Vibrator;
import android.provider.SearchIndexableResource;
import android.provider.Settings.Global;
import android.provider.Settings.System;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
import android.telephony.TelephonyManager;
import com.android.internal.logging.MetricsProto.MetricsEvent;
@@ -68,6 +71,10 @@
private static final String KEY_DOCK_AUDIO_MEDIA = "dock_audio_media";
private static final String KEY_EMERGENCY_TONE = "emergency_tone";
+ // Boot Sounds needs to be a system property so it can be accessed during boot.
+ private static final String KEY_BOOT_SOUNDS = "boot_sounds";
+ private static final String PROPERTY_BOOT_SOUNDS = "persist.sys.bootanim.play_sound";
+
private static final SettingPref PREF_DIAL_PAD_TONES = new SettingPref(
TYPE_SYSTEM, KEY_DIAL_PAD_TONES, System.DTMF_TONE_WHEN_DIALING, DEFAULT_ON) {
@Override
@@ -174,6 +181,8 @@
PREF_EMERGENCY_TONE,
};
+ private SwitchPreference mBootSounds;
+
private final SettingsObserver mSettingsObserver = new SettingsObserver();
private Context mContext;
@@ -199,6 +208,13 @@
for (SettingPref pref : PREFS) {
pref.init(this);
}
+
+ if (mContext.getResources().getBoolean(R.bool.has_boot_sounds)) {
+ mBootSounds = (SwitchPreference) findPreference(KEY_BOOT_SOUNDS);
+ mBootSounds.setChecked(SystemProperties.getBoolean(PROPERTY_BOOT_SOUNDS, true));
+ } else {
+ removePreference(KEY_BOOT_SOUNDS);
+ }
}
@Override
@@ -213,6 +229,16 @@
mSettingsObserver.register(false);
}
+ @Override
+ public boolean onPreferenceTreeClick(Preference preference) {
+ if (mBootSounds != null && preference == mBootSounds) {
+ SystemProperties.set(PROPERTY_BOOT_SOUNDS, mBootSounds.isChecked() ? "1" : "0");
+ return false;
+ } else {
+ return super.onPreferenceTreeClick(preference);
+ }
+ }
+
private static boolean hasDockSettings(Context context) {
return context.getResources().getBoolean(R.bool.has_dock_settings);
}
diff --git a/src/com/android/settings/notification/RedactionInterstitial.java b/src/com/android/settings/notification/RedactionInterstitial.java
index 4aa5ec8..ab5d834 100644
--- a/src/com/android/settings/notification/RedactionInterstitial.java
+++ b/src/com/android/settings/notification/RedactionInterstitial.java
@@ -25,8 +25,9 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.CheckBox;
+import android.widget.Button;
import android.widget.CompoundButton;
+import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
@@ -59,6 +60,13 @@
return RedactionInterstitialFragment.class.getName().equals(fragmentName);
}
+ @Override
+ protected void onCreate(Bundle savedInstance) {
+ super.onCreate(savedInstance);
+ LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
+ layout.setFitsSystemWindows(false);
+ }
+
/**
* Create an intent for launching RedactionInterstitial.
* @return An intent to launch the activity is if is available, @null if the activity is not
@@ -66,10 +74,6 @@
*/
public static Intent createStartIntent(Context ctx, int userId) {
return new Intent(ctx, RedactionInterstitial.class)
- .putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, true)
- .putExtra(EXTRA_PREFS_SET_BACK_TEXT, (String) null)
- .putExtra(EXTRA_PREFS_SET_NEXT_TEXT, ctx.getString(
- R.string.app_notifications_dialog_done))
.putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID,
Utils.isManagedProfile(UserManager.get(ctx), userId)
? R.string.lock_screen_notifications_interstitial_title_profile
@@ -78,7 +82,7 @@
}
public static class RedactionInterstitialFragment extends SettingsPreferenceFragment
- implements RadioGroup.OnCheckedChangeListener {
+ implements RadioGroup.OnCheckedChangeListener, View.OnClickListener {
private RadioGroup mRadioGroup;
private RestrictedRadioButton mShowAllButton;
@@ -116,6 +120,20 @@
((RadioButton) view.findViewById(R.id.hide_all))
.setText(R.string.lock_screen_notifications_summary_disable_profile);
}
+
+ final Button button = (Button) view.findViewById(R.id.redaction_done_button);
+ button.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.redaction_done_button) {
+ final RedactionInterstitial activity = (RedactionInterstitial) getActivity();
+ if (activity != null) {
+ activity.setResult(RESULT_OK, activity.getResultIntentData());
+ finish();
+ }
+ }
}
@Override
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 566bb9a..30dd129 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -594,10 +594,21 @@
@Override
public void onReceive(Context context, Intent intent) {
- String percent = NumberFormat.getPercentInstance().format(
- (double) mAudioManager.getStreamVolume(AudioManager.STREAM_RING) / maxVolume);
- mSummaryLoader.setSummary(this,
- mContext.getString(R.string.sound_settings_summary, percent));
+ final int ringerMode = mAudioManager.getRingerMode();
+ int resId;
+ String percent = "";
+ if (ringerMode == mAudioManager.RINGER_MODE_SILENT) {
+ resId = R.string.sound_settings_summary_silent;
+ } else if (ringerMode == mAudioManager.RINGER_MODE_VIBRATE){
+ resId = R.string.sound_settings_summary_vibrate;
+ }
+ else {
+ percent = NumberFormat.getPercentInstance().format(
+ (double) mAudioManager.getStreamVolume(
+ AudioManager.STREAM_RING) / maxVolume);
+ resId = R.string.sound_settings_summary;
+ }
+ mSummaryLoader.setSummary(this, mContext.getString(resId, percent));
}
}
diff --git a/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java
index 3e88046..fdf4707 100644
--- a/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java
+++ b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java
@@ -32,16 +32,6 @@
import java.util.Calendar;
public class ZenModeScheduleDaysSelection extends ScrollView {
- public static final int[] DAYS = {
- Calendar.SUNDAY,
- Calendar.MONDAY,
- Calendar.TUESDAY,
- Calendar.WEDNESDAY,
- Calendar.THURSDAY,
- Calendar.FRIDAY,
- Calendar.SATURDAY,
- };
-
// per-instance to ensure we're always using the current locale
private final SimpleDateFormat mDayFormat = new SimpleDateFormat("EEEE");
private final SparseBooleanArray mDays = new SparseBooleanArray();
@@ -61,9 +51,10 @@
}
mLayout.setOrientation(LinearLayout.VERTICAL);
final Calendar c = Calendar.getInstance();
+ int[] daysOfWeek = getDaysOfWeekForLocale(c);
final LayoutInflater inflater = LayoutInflater.from(context);
- for (int i = 0; i < DAYS.length; i++) {
- final int day = DAYS[i];
+ for (int i = 0; i < daysOfWeek.length; i++) {
+ final int day = daysOfWeek[i];
final CheckBox checkBox = (CheckBox) inflater.inflate(R.layout.zen_schedule_rule_day,
this, false);
c.set(Calendar.DAY_OF_WEEK, day);
@@ -95,6 +86,17 @@
return rta;
}
+ protected static int[] getDaysOfWeekForLocale(Calendar c) {
+ int[] daysOfWeek = new int[7];
+ int currentDay = c.getFirstDayOfWeek();
+ for (int i = 0; i < daysOfWeek.length; i++) {
+ if (currentDay > 7) currentDay = 1;
+ daysOfWeek[i] = currentDay;
+ currentDay++;
+ }
+ return daysOfWeek;
+ }
+
protected void onChanged(int[] days) {
// event hook for subclasses
}
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
index 1c5027e..ad54689 100644
--- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -44,8 +44,6 @@
import java.util.Arrays;
import java.util.Calendar;
-import static com.android.settings.notification.ZenModeScheduleDaysSelection.DAYS;
-
public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
private static final String KEY_DAYS = "days";
private static final String KEY_START_TIME = "start_time";
@@ -158,8 +156,9 @@
if (days != null && days.length > 0) {
final StringBuilder sb = new StringBuilder();
final Calendar c = Calendar.getInstance();
- for (int i = 0; i < DAYS.length; i++) {
- final int day = DAYS[i];
+ int[] daysOfWeek = ZenModeScheduleDaysSelection.getDaysOfWeekForLocale(c);
+ for (int i = 0; i < daysOfWeek.length; i++) {
+ final int day = daysOfWeek[i];
for (int j = 0; j < days.length; j++) {
if (day == days[j]) {
c.set(Calendar.DAY_OF_WEEK, day);
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
new file mode 100644
index 0000000..1bffc2b
--- /dev/null
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -0,0 +1,69 @@
+/*
+ * 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.overlay;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+
+/**
+ * Abstract class for creating feature controllers. Allows OEM implementations to define their own
+ * factories with their own controllers containing whatever code is needed to implement
+ * the features. To provide a factory implementation, implementors should override
+ * {@link R.string#config_featureFactory} in their override.
+ */
+public abstract class FeatureFactory {
+ private static final String LOG_TAG = "FeatureFactory";
+ private static final boolean DEBUG = false;
+
+ private static FeatureFactory sFactory;
+
+ /**
+ * Returns a factory for creating feature controllers. Creates the factory if it does not
+ * already exist. Uses the value of {@link R.string#config_featureFactory} to instantiate
+ * a factory implementation.
+ */
+ public static FeatureFactory getFactory(Context context) {
+ if (sFactory != null) {
+ return sFactory;
+ }
+
+ if (DEBUG) Log.d(LOG_TAG, "getFactory");
+ final String clsName = context.getString(R.string.config_featureFactory);
+ if (TextUtils.isEmpty(clsName)) {
+ throw new UnsupportedOperationException("No feature factory configured");
+ }
+ try {
+ sFactory = (FeatureFactory) context.getClassLoader().loadClass(clsName).newInstance();
+ } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+ throw new FactoryNotFoundException(e);
+ }
+
+ if (DEBUG) Log.d(LOG_TAG, "started " + sFactory.getClass().getSimpleName());
+ return sFactory;
+ }
+
+ public abstract SupportFeatureProvider getSupportFeatureProvider(Context context);
+
+ public static final class FactoryNotFoundException extends RuntimeException {
+ public FactoryNotFoundException(Throwable throwable) {
+ super("Unable to create factory. Did you misconfigure Proguard?", throwable);
+ }
+ }
+}
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
new file mode 100644
index 0000000..ce561f3
--- /dev/null
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.overlay;
+
+import android.content.Context;
+
+/**
+ * {@link FeatureFactory} implementation for AOSP Settings.
+ */
+public final class FeatureFactoryImpl extends FeatureFactory {
+
+ @Override
+ public SupportFeatureProvider getSupportFeatureProvider(Context context) {
+ return null;
+ }
+
+}
diff --git a/src/com/android/settings/overlay/SupportFeatureProvider.java b/src/com/android/settings/overlay/SupportFeatureProvider.java
new file mode 100644
index 0000000..506d1bc
--- /dev/null
+++ b/src/com/android/settings/overlay/SupportFeatureProvider.java
@@ -0,0 +1,147 @@
+/*
+ * 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.overlay;
+
+import android.accounts.Account;
+import android.annotation.IntDef;
+import android.annotation.StringRes;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.settings.support.SupportPhone;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * Feature provider for support tab.
+ */
+public interface SupportFeatureProvider {
+
+ @IntDef({SupportType.EMAIL, SupportType.PHONE, SupportType.CHAT})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface SupportType {
+ int EMAIL = 1;
+ int PHONE = 2;
+ int CHAT = 3;
+ }
+
+ /**
+ * Returns a intent that will open help & feedback.
+ */
+ Intent getHelpIntent(Context context);
+
+ /**
+ * Whether or not a support type is enabled.
+ */
+ boolean isSupportTypeEnabled(Context context, @SupportType int type);
+
+ /**
+ * Refreshes all operation rules.
+ */
+ void refreshOperationRules();
+
+ /**
+ * Whether or not a support type is in operation 24/7. If country is null, use
+ * current country.
+ */
+ boolean isAlwaysOperating(@SupportType int type, String countryCode);
+
+ /**
+ * Whether or not a support type is operating now.
+ */
+ boolean isOperatingNow(@SupportType int type);
+
+ /**
+ * Returns the current country code if it has a operation config, otherwise returns null.
+ */
+ String getCurrentCountryCodeIfHasConfig(@SupportType int type);
+
+ /**
+ * Returns localized string for operation hours in specified country. If country is null, use
+ * current country to figure out operation hours.
+ */
+ CharSequence getOperationHours(Context context, @SupportType int type, String countryCode,
+ boolean hasInternet);
+
+ /**
+ * Returns a localized string indicating estimated wait time for a support time.
+ */
+ String getEstimatedWaitTime(Context context, @SupportType int type);
+
+ /**
+ * Returns a list of country codes that have phone support.
+ */
+ List<String> getPhoneSupportCountryCodes();
+
+ /**
+ * Returns a list of countries that have phone support.
+ */
+ List<String> getPhoneSupportCountries();
+
+ /**
+ * Returns a support phone for specified country.
+ */
+ SupportPhone getSupportPhones(String countryCode, boolean isTollfree);
+
+ /**
+ * Whether or not a disclaimer dialog should be displayed.
+ */
+ boolean shouldShowDisclaimerDialog(Context context);
+
+ /**
+ * Sets whether or not a disclaimer dialog should be displayed.
+ */
+ void setShouldShowDisclaimerDialog(Context context, boolean shouldShow);
+
+ /**
+ * Returns an {@link Account} that's eligible for support options.
+ */
+ Account getSupportEligibleAccount(Context context);
+
+ /**
+ * Starts support activity of specified type
+ *
+ * @param activity Calling activity
+ * @param account A account returned by {@link #getSupportEligibleAccount}
+ * @param type The type of support account needs.
+ */
+ void startSupport(Activity activity, Account account, @SupportType int type);
+
+ /**
+ * Returns an {@link Intent} that opens help and allow user get help on sign in.
+ */
+ Intent getSignInHelpIntent(Context context);
+
+ /**
+ * Returns an intent that will start the add account UI.
+ */
+ Intent getAccountLoginIntent();
+
+ /**
+ * Returns an intent that will launch the tips and tricks UI.
+ */
+ Intent getTipsAndTricksIntent(Context context);
+
+ /**
+ * Returns the string for the disclaimer in the Support dialog
+ */
+ @StringRes
+ int getDisclaimerStringResId();
+}
diff --git a/src/com/android/settings/password/PasswordRequirementAdapter.java b/src/com/android/settings/password/PasswordRequirementAdapter.java
new file mode 100644
index 0000000..b05d8b8
--- /dev/null
+++ b/src/com/android/settings/password/PasswordRequirementAdapter.java
@@ -0,0 +1,77 @@
+/*
+ * 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.password;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import static com.android.settings.password.PasswordRequirementAdapter
+ .PasswordRequirementViewHolder;
+
+/**
+ * Used in {@link com.android.settings.ChooseLockPassword} to show password requirements.
+ */
+public class PasswordRequirementAdapter extends
+ RecyclerView.Adapter<PasswordRequirementViewHolder> {
+ private String[] mRequirements;
+
+ public PasswordRequirementAdapter() {
+ setHasStableIds(true);
+ }
+
+ @Override
+ public PasswordRequirementViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.password_requirement_item, parent, false);
+ return new PasswordRequirementViewHolder(v);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mRequirements.length;
+ }
+
+ public void setRequirements(String[] requirements) {
+ mRequirements = requirements;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mRequirements[position].hashCode();
+ }
+
+ @Override
+ public void onBindViewHolder(PasswordRequirementViewHolder holder, int position) {
+ holder.mDescriptionText.setText(mRequirements[position]);
+ }
+
+ public static class PasswordRequirementViewHolder extends RecyclerView.ViewHolder {
+ private TextView mDescriptionText;
+
+ public PasswordRequirementViewHolder(View itemView) {
+ super(itemView);
+ mDescriptionText = (TextView) itemView;
+ }
+ }
+
+}
diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java
new file mode 100644
index 0000000..7cdf006
--- /dev/null
+++ b/src/com/android/settings/password/SetNewPasswordActivity.java
@@ -0,0 +1,55 @@
+/*
+ * 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.password;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.settings.ChooseLockGeneric;
+
+/**
+ * Trampolines {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} and
+ * {@link DevicePolicyManager#ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} intent to the appropriate UI
+ * activity for handling set new password.
+ */
+public class SetNewPasswordActivity extends Activity implements SetNewPasswordController.Ui {
+ private String mNewPasswordAction;
+ private SetNewPasswordController mSetNewPasswordController;
+
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ mNewPasswordAction = getIntent().getAction();
+ mSetNewPasswordController = new SetNewPasswordController(this, this);
+ mSetNewPasswordController.dispatchSetNewPasswordIntent();
+ }
+
+ @Override
+ public void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras) {
+ Intent intent = new Intent(this, ChooseLockGeneric.class)
+ .setAction(mNewPasswordAction);
+ if (chooseLockFingerprintExtras != null) {
+ intent.putExtras(chooseLockFingerprintExtras);
+ }
+ startActivity(intent);
+ finish();
+ }
+}
diff --git a/src/com/android/settings/password/SetNewPasswordController.java b/src/com/android/settings/password/SetNewPasswordController.java
new file mode 100644
index 0000000..470723b
--- /dev/null
+++ b/src/com/android/settings/password/SetNewPasswordController.java
@@ -0,0 +1,114 @@
+/*
+ * 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.password;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.Nullable;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.ChooseLockGeneric;
+import com.android.settings.ChooseLockSettingsHelper;
+
+/**
+ * Business logic for {@link SetNewPasswordActivity}.
+ *
+ * <p>On devices that supports fingerprint, this controller directs the user to configure
+ * fingerprint + a backup password if the device admin allows fingerprint for keyguard and
+ * the user has never configured a fingerprint before.
+ */
+final class SetNewPasswordController {
+
+ interface Ui {
+ /** Starts the {@link ChooseLockGeneric} activity with the given extras. */
+ void launchChooseLock(@Nullable Bundle chooseLockFingerprintExtras);
+ }
+
+ private final int mCurrentUserId;
+ private final PackageManager mPackageManager;
+ @Nullable private final FingerprintManager mFingerprintManager;
+ private final DevicePolicyManager mDevicePolicyManager;
+ private final Ui mUi;
+
+ public SetNewPasswordController(Context context, Ui ui) {
+ this(context.getUserId(),
+ context.getPackageManager(),
+ (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE),
+ (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE),
+ ui);
+ }
+
+ @VisibleForTesting
+ SetNewPasswordController(
+ int currentUserId,
+ PackageManager packageManager,
+ FingerprintManager fingerprintManager,
+ DevicePolicyManager devicePolicyManager,
+ Ui ui) {
+ mCurrentUserId = currentUserId;
+ mPackageManager = checkNotNull(packageManager);
+ mFingerprintManager = fingerprintManager;
+ mDevicePolicyManager = checkNotNull(devicePolicyManager);
+ mUi = checkNotNull(ui);
+ }
+
+ /**
+ * Dispatches the set new password intent to the correct activity that handles it.
+ */
+ public void dispatchSetNewPasswordIntent() {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
+ && mFingerprintManager != null
+ && mFingerprintManager.isHardwareDetected()
+ && !mFingerprintManager.hasEnrolledFingerprints()
+ && !isFingerprintDisabledByAdmin()) {
+ mUi.launchChooseLock(getFingerprintChooseLockExtras());
+ } else {
+ mUi.launchChooseLock(null);
+ }
+ }
+
+ private Bundle getFingerprintChooseLockExtras() {
+ Bundle chooseLockExtras = new Bundle();
+ if (mFingerprintManager != null) {
+ long challenge = mFingerprintManager.preEnroll();
+ chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ chooseLockExtras.putBoolean(
+ ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
+ chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
+ chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
+ chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
+ if (mCurrentUserId != UserHandle.USER_NULL) {
+ chooseLockExtras.putInt(Intent.EXTRA_USER_ID, mCurrentUserId);
+ }
+ }
+ return chooseLockExtras;
+ }
+
+ private boolean isFingerprintDisabledByAdmin() {
+ int disabledFeatures = mDevicePolicyManager.getKeyguardDisabledFeatures(
+ null, mCurrentUserId);
+ return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
+ }
+}
diff --git a/src/com/android/settings/print/PrintJobSettingsFragment.java b/src/com/android/settings/print/PrintJobSettingsFragment.java
index 08bbd97..dc7df52 100644
--- a/src/com/android/settings/print/PrintJobSettingsFragment.java
+++ b/src/com/android/settings/print/PrintJobSettingsFragment.java
@@ -26,11 +26,13 @@
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.text.format.DateUtils;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -70,8 +72,9 @@
}
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
addPreferencesFromResource(R.xml.print_job_settings);
mPrintJobPreference = findPreference(PRINT_JOB_PREFERENCE);
@@ -86,6 +89,8 @@
processArguments();
setHasOptionsMenu(true);
+
+ return view;
}
@Override
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index 42d8a8d..db84a6f 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -39,6 +39,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -116,10 +117,6 @@
private PrintersAdapter mPrintersAdapter;
- // TODO: Showing sub-sub fragment does not handle the activity title
- // so we do it but this is wrong. Do a real fix when there is time.
- private CharSequence mOldActivityTitle;
-
private int mLastUnfilteredItemCount;
private boolean mServiceEnabled;
@@ -135,8 +132,6 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- mServiceEnabled = getArguments().getBoolean(PrintSettingsFragment.EXTRA_CHECKED);
-
String title = getArguments().getString(PrintSettingsFragment.EXTRA_TITLE);
if (!TextUtils.isEmpty(title)) {
getActivity().setTitle(title);
@@ -144,6 +139,16 @@
}
@Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = super.onCreateView(inflater, container, savedInstanceState);
+
+ mServiceEnabled = getArguments().getBoolean(PrintSettingsFragment.EXTRA_CHECKED);
+
+ return root;
+ }
+
+ @Override
public void onStart() {
super.onStart();
updateEmptyView();
@@ -168,14 +173,12 @@
super.onViewCreated(view, savedInstanceState);
initComponents();
updateUiForArguments();
+ getListView().setVisibility(View.GONE);
getBackupListView().setVisibility(View.VISIBLE);
}
@Override
public void onDestroyView() {
- if (mOldActivityTitle != null) {
- getActivity().getActionBar().setTitle(mOldActivityTitle);
- }
super.onDestroyView();
mSwitchBar.removeOnSwitchChangeListener(this);
mSwitchBar.hide();
diff --git a/src/com/android/settings/print/PrintSettingsFragment.java b/src/com/android/settings/print/PrintSettingsFragment.java
index 82a18ee..49d254c 100644
--- a/src/com/android/settings/print/PrintSettingsFragment.java
+++ b/src/com/android/settings/print/PrintSettingsFragment.java
@@ -43,6 +43,7 @@
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@@ -104,8 +105,9 @@
}
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = super.onCreateView(inflater, container, savedInstanceState);
addPreferencesFromResource(R.xml.print_settings);
mActivePrintJobsCategory = (PreferenceCategory) findPreference(
@@ -119,6 +121,8 @@
mPrintServicesController = new PrintServicesController();
getLoaderManager().initLoader(LOADER_ID_PRINT_SERVICES, null, mPrintServicesController);
+
+ return root;
}
@Override
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index fd67ea6..ccedd62 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -177,8 +177,8 @@
public List<SearchIndexableData> dataToDelete;
public Map<String, List<String>> nonIndexableKeys;
- public boolean forceUpdate = false;
- public boolean fullIndex = true;
+ public boolean forceUpdate;
+ public boolean fullIndex;
public UpdateData() {
dataToUpdate = new ArrayList<SearchIndexableData>();
@@ -1165,17 +1165,6 @@
return result.toString();
}
- private int getResId(Context context, AttributeSet set, int[] attrs, int resId) {
- final TypedArray sa = context.obtainStyledAttributes(set, attrs);
- final TypedValue tv = sa.peekValue(resId);
-
- if (tv != null && tv.type == TypedValue.TYPE_STRING) {
- return tv.resourceId;
- } else {
- return 0;
- }
- }
-
/**
* A private class for updating the Index database
*/
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 80eb6d4..2137bd5 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -38,6 +38,7 @@
import com.android.settings.display.ScreenZoomSettings;
import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.gestures.GestureSettings;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
import com.android.settings.location.LocationSettings;
import com.android.settings.location.ScanningSettings;
@@ -85,6 +86,7 @@
public static final int RANK_PRINTING = 21;
public static final int RANK_DEVELOPEMENT = 22;
public static final int RANK_DEVICE_INFO = 23;
+ public static final int RANK_GESTURE = 24;
public static final int RANK_UNDEFINED = -1;
public static final int RANK_OTHERS = 1024;
@@ -146,6 +148,9 @@
// Users
sRankMap.put(UserSettings.class.getName(), RANK_USERS);
+ // Gestures
+ sRankMap.put(GestureSettings.class.getName(), RANK_GESTURE);
+
// Location
sRankMap.put(LocationSettings.class.getName(), RANK_LOCATION);
sRankMap.put(ScanningSettings.class.getName(), RANK_LOCATION);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 08a0d0c..5332d99 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -39,6 +39,7 @@
import com.android.settings.display.ScreenZoomSettings;
import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.gestures.GestureSettings;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
import com.android.settings.location.LocationSettings;
import com.android.settings.location.ScanningSettings;
@@ -220,6 +221,13 @@
UserSettings.class.getName(),
R.drawable.ic_settings_multiuser));
+ sResMap.put(GestureSettings.class.getName(),
+ new SearchIndexableResource(
+ Ranking.getRankForClassName(GestureSettings.class.getName()),
+ NO_DATA_RES_ID,
+ GestureSettings.class.getName(),
+ R.drawable.ic_settings_gestures));
+
sResMap.put(LocationSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(LocationSettings.class.getName()),
@@ -272,7 +280,7 @@
sResMap.put(DateTimeSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(DateTimeSettings.class.getName()),
- R.xml.date_time_prefs,
+ NO_DATA_RES_ID,
DateTimeSettings.class.getName(),
R.drawable.ic_settings_date_time));
diff --git a/src/com/android/settings/support/SupportDisclaimerDialogFragment.java b/src/com/android/settings/support/SupportDisclaimerDialogFragment.java
new file mode 100644
index 0000000..1df9673
--- /dev/null
+++ b/src/com/android/settings/support/SupportDisclaimerDialogFragment.java
@@ -0,0 +1,135 @@
+/*
+ * 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.support;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.TextPaint;
+import android.text.style.URLSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.overlay.SupportFeatureProvider;
+
+/**
+ * {@link DialogFragment} for support disclaimer.
+ */
+public final class SupportDisclaimerDialogFragment extends DialogFragment implements
+ DialogInterface.OnClickListener {
+
+ public static final String TAG = "SupportDisclaimerDialog";
+ private static final String EXTRA_TYPE = "extra_type";
+ private static final String EXTRA_ACCOUNT = "extra_account";
+
+ public static SupportDisclaimerDialogFragment newInstance(Account account,
+ @SupportFeatureProvider.SupportType int type) {
+ final SupportDisclaimerDialogFragment fragment = new SupportDisclaimerDialogFragment();
+ final Bundle bundle = new Bundle(2);
+ bundle.putParcelable(SupportDisclaimerDialogFragment.EXTRA_ACCOUNT, account);
+ bundle.putInt(SupportDisclaimerDialogFragment.EXTRA_TYPE, type);
+ fragment.setArguments(bundle);
+ return fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.support_disclaimer_title)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this);
+ final View content = LayoutInflater.from(builder.getContext())
+ .inflate(R.layout.support_disclaimer_content, null);
+ final TextView disclaimer = (TextView) content.findViewById(R.id.support_disclaimer_text);
+ final Activity activity = getActivity();
+ final SupportFeatureProvider supportFeatureProvider =
+ FeatureFactory.getFactory(activity).getSupportFeatureProvider(activity);
+ disclaimer.setText(supportFeatureProvider.getDisclaimerStringResId());
+ stripUnderlines((Spannable) disclaimer.getText());
+ return builder
+ .setView(content)
+ .create();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == Dialog.BUTTON_NEGATIVE) {
+ MetricsLogger.action(getContext(),
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_DISCLAIMER_CANCEL);
+ return;
+ }
+ final Activity activity = getActivity();
+ final CheckBox doNotShow =
+ (CheckBox) getDialog().findViewById(R.id.support_disclaimer_do_not_show_again);
+ final SupportFeatureProvider supportFeatureProvider =
+ FeatureFactory.getFactory(activity).getSupportFeatureProvider(activity);
+ supportFeatureProvider.setShouldShowDisclaimerDialog(getContext(), !doNotShow.isChecked());
+ final Bundle bundle = getArguments();
+ MetricsLogger.action(activity, MetricsProto.MetricsEvent.ACTION_SUPPORT_DISCLAIMER_OK);
+ supportFeatureProvider.startSupport(getActivity(),
+ (Account) bundle.getParcelable(EXTRA_ACCOUNT), bundle.getInt(EXTRA_TYPE));
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ MetricsLogger.action(getContext(),
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_DISCLAIMER_CANCEL);
+ }
+
+ /**
+ * Removes the underlines of {@link android.text.style.URLSpan}s.
+ */
+ private static void stripUnderlines(Spannable input) {
+ final URLSpan[] urls = input.getSpans(0, input.length(), URLSpan.class);
+
+ for (URLSpan span : urls) {
+ final int start = input.getSpanStart(span);
+ final int end = input.getSpanEnd(span);
+ input.removeSpan(span);
+ input.setSpan(new NoUnderlineUrlSpan(span.getURL()), start, end,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+
+ /**
+ * A {@link URLSpan} that doesn't decorate the link with underline.
+ */
+ public static class NoUnderlineUrlSpan extends URLSpan {
+
+ public NoUnderlineUrlSpan(String url) {
+ super(url);
+ }
+
+ @Override
+ public void updateDrawState(TextPaint ds) {
+ super.updateDrawState(ds);
+ ds.setUnderlineText(false);
+ }
+ }
+}
diff --git a/src/com/android/settings/support/SupportPhone.java b/src/com/android/settings/support/SupportPhone.java
new file mode 100644
index 0000000..d27dca5
--- /dev/null
+++ b/src/com/android/settings/support/SupportPhone.java
@@ -0,0 +1,84 @@
+/*
+ * 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.support;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.text.ParseException;
+
+/**
+ * Data model for a support phone number.
+ */
+public final class SupportPhone implements Parcelable {
+
+ public final String language;
+ public final String number;
+ public final boolean isTollFree;
+
+ public SupportPhone(String config) throws ParseException {
+ // Config follows this format: language:[tollfree|tolled]:number
+ final String[] tokens = config.split(":");
+ if (tokens.length != 3) {
+ throw new ParseException("Phone config is invalid " + config, 0);
+ }
+ language = tokens[0];
+ isTollFree = TextUtils.equals(tokens[1], "tollfree");
+ number = tokens[2];
+ }
+
+ protected SupportPhone(Parcel in) {
+ language = in.readString();
+ number = in.readString();
+ isTollFree = in.readInt() != 0;
+ }
+
+ public Intent getDialIntent() {
+ return new Intent(Intent.ACTION_DIAL)
+ .setData(new Uri.Builder()
+ .scheme("tel")
+ .appendPath(number)
+ .build());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(language);
+ dest.writeString(number);
+ dest.writeInt(isTollFree ? 1 : 0);
+ }
+
+ public static final Creator<SupportPhone> CREATOR = new Creator<SupportPhone>() {
+ @Override
+ public SupportPhone createFromParcel(Parcel in) {
+ return new SupportPhone(in);
+ }
+
+ @Override
+ public SupportPhone[] newArray(int size) {
+ return new SupportPhone[size];
+ }
+ };
+}
diff --git a/src/com/android/settings/support/SupportPhoneDialogFragment.java b/src/com/android/settings/support/SupportPhoneDialogFragment.java
new file mode 100644
index 0000000..4dde547
--- /dev/null
+++ b/src/com/android/settings/support/SupportPhoneDialogFragment.java
@@ -0,0 +1,85 @@
+/*
+ * 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.support;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+import com.android.settings.R;
+
+import java.util.Locale;
+
+/**
+ * A dialog fragment that displays support phone numbers.
+ */
+public final class SupportPhoneDialogFragment extends DialogFragment implements
+ View.OnClickListener {
+
+ public static final String TAG = "SupportPhoneDialog";
+ private static final String EXTRA_PHONE = "extra_phone";
+
+ public static SupportPhoneDialogFragment newInstance(SupportPhone phone) {
+ final SupportPhoneDialogFragment fragment = new SupportPhoneDialogFragment();
+ final Bundle bundle = new Bundle(2);
+ bundle.putParcelable(EXTRA_PHONE, phone);
+ fragment.setArguments(bundle);
+ return fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final SupportPhone phone = getArguments().getParcelable(EXTRA_PHONE);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.support_international_phone_title);
+ final View content = LayoutInflater.from(builder.getContext())
+ .inflate(R.layout.support_phone_dialog_content, null);
+ final View phoneNumberContainer = content.findViewById(R.id.phone_number_container);
+ final TextView phoneView = (TextView) content.findViewById(R.id.phone_number);
+ final String formattedPhoneNumber = getContext().getString(
+ R.string.support_phone_international_format,
+ new Locale(phone.language).getDisplayLanguage(), phone.number);
+ phoneView.setText(formattedPhoneNumber);
+ phoneNumberContainer.setOnClickListener(this);
+ return builder
+ .setView(content)
+ .create();
+ }
+
+ @Override
+ public void onClick(View v) {
+ final SupportPhone phone = getArguments().getParcelable(EXTRA_PHONE);
+ final Activity activity = getActivity();
+ final Intent intent = phone.getDialIntent();
+ final boolean canDial = !activity.getPackageManager()
+ .queryIntentActivities(intent, 0)
+ .isEmpty();
+ if (canDial) {
+ MetricsLogger.action(getActivity(),
+ MetricsProto.MetricsEvent.ACTION_SUPPORT_DIAL_TOLLED);
+ getActivity().startActivity(intent);
+ }
+ dismiss();
+ }
+}
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index 63d688a..f72bf9e 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -560,8 +560,9 @@
}
}
}
+ return true;
}
- return true;
+ return false;
}
private void removeRestrictionsForApp(AppRestrictionsPreference preference) {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 02fd677..4e0d8fa 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -224,6 +224,7 @@
mMePreference.setSummary(R.string.user_admin);
}
mAddUser = (DimmableIconPreference) findPreference(KEY_ADD_USER);
+ mAddUser.useAdminDisabledSummary(false);
// Determine if add user/profile button should be visible
if (mUserCaps.mCanAddUser && Utils.isDeviceProvisioned(getActivity())) {
mAddUser.setOnPreferenceClickListener(this);
@@ -621,9 +622,9 @@
}
}
- private boolean emergencyInfoActivityPresent() {
+ private static boolean emergencyInfoActivityPresent(Context context) {
Intent intent = new Intent(ACTION_EDIT_EMERGENCY_INFO).setPackage("com.android.emergency");
- List<ResolveInfo> infos = getContext().getPackageManager().queryIntentActivities(intent, 0);
+ List<ResolveInfo> infos = context.getPackageManager().queryIntentActivities(intent, 0);
if (infos == null || infos.isEmpty()) {
return false;
}
@@ -869,7 +870,7 @@
mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
}
- if (emergencyInfoActivityPresent()) {
+ if (emergencyInfoActivityPresent(getContext())) {
mEmergencyInfoPreference.setOnPreferenceClickListener(this);
mEmergencyInfoPreference.setOrder(Preference.DEFAULT_ORDER);
preferenceScreen.addPreference(mEmergencyInfoPreference);
@@ -1153,6 +1154,12 @@
data.screenTitle = res.getString(R.string.user_settings_title);
result.add(data);
}
+ if (emergencyInfoActivityPresent(context)) {
+ data = new SearchIndexableRaw(context);
+ data.title = res.getString(R.string.emergency_info_title);
+ data.screenTitle = res.getString(R.string.emergency_info_title);
+ result.add(data);
+ }
return result;
}
};
diff --git a/src/com/android/settings/utils/AsyncLoader.java b/src/com/android/settings/utils/AsyncLoader.java
new file mode 100644
index 0000000..76c99fa
--- /dev/null
+++ b/src/com/android/settings/utils/AsyncLoader.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ * Licensed to 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.utils;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+
+/**
+ * This class fills in some boilerplate for AsyncTaskLoader to actually load things.
+ *
+ * Subclasses need to implement {@link AsyncLoader#loadInBackground()} to perform the actual
+ * background task, and {@link AsyncLoader#onDiscardResult(T)} to clean up previously loaded
+ * results.
+ *
+ * This loader is based on the MailAsyncTaskLoader from the AOSP EmailUnified repo.
+ */
+public abstract class AsyncLoader<T> extends AsyncTaskLoader<T> {
+ private T mResult;
+
+ public AsyncLoader(final Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onStartLoading() {
+ if (mResult != null) {
+ deliverResult(mResult);
+ }
+
+ if (takeContentChanged() || mResult == null) {
+ forceLoad();
+ }
+ }
+
+ @Override
+ protected void onStopLoading() {
+ cancelLoad();
+ }
+
+ @Override
+ public void deliverResult(final T data) {
+ if (isReset()) {
+ if (data != null) {
+ onDiscardResult(data);
+ }
+ return;
+ }
+
+ final T oldResult = mResult;
+ mResult = data;
+
+ if (isStarted()) {
+ super.deliverResult(data);
+ }
+
+ if (oldResult != null && oldResult != mResult) {
+ onDiscardResult(oldResult);
+ }
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+
+ onStopLoading();
+
+ if (mResult != null) {
+ onDiscardResult(mResult);
+ }
+ mResult = null;
+ }
+
+ @Override
+ public void onCanceled(final T data) {
+ super.onCanceled(data);
+
+ if (data != null) {
+ onDiscardResult(data);
+ }
+ }
+
+ /**
+ * Called when discarding the load results so subclasses can take care of clean-up or
+ * recycling tasks. This is not called if the same result (by way of pointer equality) is
+ * returned again by a subsequent call to loadInBackground, or if result is null.
+ *
+ * Note that this may be called concurrently with loadInBackground(), and in some circumstances
+ * may be called more than once for a given object.
+ *
+ * @param result The value returned from {@link AsyncLoader#loadInBackground()} which
+ * is to be discarded.
+ */
+ protected abstract void onDiscardResult(final T result);
+}
diff --git a/src/com/android/settings/utils/SettingsDividerItemDecoration.java b/src/com/android/settings/utils/SettingsDividerItemDecoration.java
new file mode 100644
index 0000000..451d532
--- /dev/null
+++ b/src/com/android/settings/utils/SettingsDividerItemDecoration.java
@@ -0,0 +1,46 @@
+/*
+ * 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.utils;
+
+import android.content.Context;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.support.v7.widget.RecyclerView;
+
+import com.android.setupwizardlib.DividerItemDecoration;
+
+public class SettingsDividerItemDecoration extends DividerItemDecoration {
+
+ public SettingsDividerItemDecoration(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected boolean isDividerAllowedAbove(RecyclerView.ViewHolder viewHolder) {
+ if (viewHolder instanceof PreferenceViewHolder) {
+ return ((PreferenceViewHolder) viewHolder).isDividerAllowedAbove();
+ }
+ return super.isDividerAllowedAbove(viewHolder);
+ }
+
+ @Override
+ protected boolean isDividerAllowedBelow(RecyclerView.ViewHolder viewHolder) {
+ if (viewHolder instanceof PreferenceViewHolder) {
+ return ((PreferenceViewHolder) viewHolder).isDividerAllowedBelow();
+ }
+ return super.isDividerAllowedBelow(viewHolder);
+ }
+}
diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java
index 170b128..b306577 100644
--- a/src/com/android/settings/vpn2/AppManagementFragment.java
+++ b/src/com/android/settings/vpn2/AppManagementFragment.java
@@ -80,7 +80,7 @@
public void onForget() {
// Unset always-on-vpn when forgetting the VPN
if (isVpnAlwaysOn()) {
- setAlwaysOnVpnByUI(false);
+ setAlwaysOnVpn(false);
}
// Also dismiss and go back to VPN list
finish();
@@ -187,14 +187,18 @@
if (mUserId == UserHandle.USER_SYSTEM) {
VpnUtils.clearLockdownVpn(getContext());
}
- final boolean success = mConnectivityManager.setAlwaysOnVpnPackageForUser(mUserId,
- isEnabled ? mPackageName : null, /* lockdownEnabled */ false);
+ final boolean success = setAlwaysOnVpn(isEnabled);
if (isEnabled && (!success || !isVpnAlwaysOn())) {
CannotConnectFragment.show(this, mVpnLabel);
}
return success;
}
+ private boolean setAlwaysOnVpn(boolean isEnabled) {
+ return mConnectivityManager.setAlwaysOnVpnPackageForUser(mUserId,
+ isEnabled ? mPackageName : null, /* lockdownEnabled */ false);
+ }
+
private boolean checkTargetVersion() {
if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
return true;
@@ -224,8 +228,14 @@
mPreferenceForget.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
mUserId);
- if (!checkTargetVersion()) {
+ if (checkTargetVersion()) {
+ // setSummary doesn't override the admin message when user restriction is applied
+ mPreferenceAlwaysOn.setSummary(null);
+ // setEnabled is not required here, as checkRestrictionAndSetDisabled
+ // should have refreshed the enable state.
+ } else {
mPreferenceAlwaysOn.setEnabled(false);
+ mPreferenceAlwaysOn.setSummary(R.string.vpn_not_supported_by_this_app);
}
}
}
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index 92050e9..dd63d13 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -316,12 +316,12 @@
}
private boolean validate(boolean editing) {
- if (!editing) {
- return mUsername.getText().length() != 0 && mPassword.getText().length() != 0;
- }
if (mAlwaysOnVpn.isChecked() && !getProfile().isValidLockdownProfile()) {
return false;
}
+ if (!editing) {
+ return mUsername.getText().length() != 0 && mPassword.getText().length() != 0;
+ }
if (mName.getText().length() == 0 || mServer.getText().length() == 0 ||
!validateAddresses(mDnsServers.getText().toString(), false) ||
!validateAddresses(mRoutes.getText().toString(), true)) {
diff --git a/src/com/android/settings/widget/AspectRatioFrameLayout.java b/src/com/android/settings/widget/AspectRatioFrameLayout.java
new file mode 100644
index 0000000..14d7921
--- /dev/null
+++ b/src/com/android/settings/widget/AspectRatioFrameLayout.java
@@ -0,0 +1,57 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import com.android.settings.R;
+
+/**
+ * A {@link FrameLayout} with customizable aspect ration.
+ * This is used to avoid dynamically calculating the height for the frame. Default aspect
+ * ratio will be 1 if none is set in layout attribute.
+ */
+public final class AspectRatioFrameLayout extends FrameLayout {
+
+ private float mAspectRatio = 1.0f;
+
+ public AspectRatioFrameLayout(Context context) {
+ this(context, null);
+ }
+
+ public AspectRatioFrameLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AspectRatioFrameLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ if (attrs != null) {
+ TypedArray array =
+ context.obtainStyledAttributes(attrs, R.styleable.AspectRatioFrameLayout);
+ mAspectRatio = array.getFloat(
+ R.styleable.AspectRatioFrameLayout_aspectRatio, 1.0f);
+ array.recycle();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, (int) (widthMeasureSpec / mAspectRatio));
+ }
+
+}
diff --git a/src/com/android/settings/widget/LinkAccessibilityHelper.java b/src/com/android/settings/widget/LinkAccessibilityHelper.java
deleted file mode 100644
index 2d4d585..0000000
--- a/src/com/android/settings/widget/LinkAccessibilityHelper.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2014 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.graphics.Rect;
-import android.os.Bundle;
-import android.text.Layout;
-import android.text.Spanned;
-import android.text.style.ClickableSpan;
-import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.TextView;
-
-import java.util.List;
-
-/**
- * Copied from setup wizard.
- */
-public class LinkAccessibilityHelper extends ExploreByTouchHelper {
-
- private static final String TAG = "LinkAccessibilityHelper";
-
- private final TextView mView;
- private final Rect mTempRect = new Rect();
-
- public LinkAccessibilityHelper(TextView view) {
- super(view);
- mView = view;
- }
-
- @Override
- protected int getVirtualViewAt(float x, float y) {
- final CharSequence text = mView.getText();
- if (text instanceof Spanned) {
- final Spanned spannedText = (Spanned) text;
- final int offset = mView.getOffsetForPosition(x, y);
- ClickableSpan[] linkSpans = spannedText.getSpans(offset, offset, ClickableSpan.class);
- if (linkSpans.length == 1) {
- ClickableSpan linkSpan = linkSpans[0];
- return spannedText.getSpanStart(linkSpan);
- }
- }
- return INVALID_ID;
- }
-
- @Override
- protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
- final CharSequence text = mView.getText();
- if (text instanceof Spanned) {
- final Spanned spannedText = (Spanned) text;
- ClickableSpan[] linkSpans = spannedText.getSpans(0, spannedText.length(),
- ClickableSpan.class);
- for (ClickableSpan span : linkSpans) {
- virtualViewIds.add(spannedText.getSpanStart(span));
- }
- }
- }
-
- @Override
- protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
- final ClickableSpan span = getSpanForOffset(virtualViewId);
- if (span != null) {
- event.setContentDescription(getTextForSpan(span));
- } else {
- Log.e(TAG, "ClickableSpan is null for offset: " + virtualViewId);
- event.setContentDescription(mView.getText());
- }
- }
-
- @Override
- protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo info) {
- final ClickableSpan span = getSpanForOffset(virtualViewId);
- if (span != null) {
- info.setContentDescription(getTextForSpan(span));
- } else {
- Log.e(TAG, "ClickableSpan is null for offset: " + virtualViewId);
- info.setContentDescription(mView.getText());
- }
- info.setFocusable(true);
- info.setClickable(true);
- getBoundsForSpan(span, mTempRect);
- if (!mTempRect.isEmpty()) {
- info.setBoundsInParent(getBoundsForSpan(span, mTempRect));
- } else {
- Log.e(TAG, "LinkSpan bounds is empty for: " + virtualViewId);
- mTempRect.set(0, 0, 1, 1);
- info.setBoundsInParent(mTempRect);
- }
- info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
- }
-
- @Override
- protected boolean onPerformActionForVirtualView(int virtualViewId, int action,
- Bundle arguments) {
- if (action == AccessibilityNodeInfo.ACTION_CLICK) {
- ClickableSpan span = getSpanForOffset(virtualViewId);
- if (span != null) {
- span.onClick(mView);
- return true;
- } else {
- Log.e(TAG, "LinkSpan is null for offset: " + virtualViewId);
- }
- }
- return false;
- }
-
- private ClickableSpan getSpanForOffset(int offset) {
- CharSequence text = mView.getText();
- if (text instanceof Spanned) {
- Spanned spannedText = (Spanned) text;
- ClickableSpan[] spans = spannedText.getSpans(offset, offset, ClickableSpan.class);
- if (spans.length == 1) {
- return spans[0];
- }
- }
- return null;
- }
-
- private CharSequence getTextForSpan(ClickableSpan span) {
- CharSequence text = mView.getText();
- if (text instanceof Spanned) {
- Spanned spannedText = (Spanned) text;
- return spannedText.subSequence(spannedText.getSpanStart(span),
- spannedText.getSpanEnd(span));
- }
- return text;
- }
-
- // Find the bounds of a span. If it spans multiple lines, it will only return the bounds for the
- // section on the first line.
- private Rect getBoundsForSpan(ClickableSpan span, Rect outRect) {
- CharSequence text = mView.getText();
- outRect.setEmpty();
- if (text instanceof Spanned) {
- Spanned spannedText = (Spanned) text;
- final int spanStart = spannedText.getSpanStart(span);
- final int spanEnd = spannedText.getSpanEnd(span);
- final Layout layout = mView.getLayout();
- final float xStart = layout.getPrimaryHorizontal(spanStart);
- final float xEnd = layout.getPrimaryHorizontal(spanEnd);
- final int lineStart = layout.getLineForOffset(spanStart);
- final int lineEnd = layout.getLineForOffset(spanEnd);
- layout.getLineBounds(lineStart, outRect);
- outRect.left = (int) xStart;
- if (lineEnd == lineStart) {
- outRect.right = (int) xEnd;
- } // otherwise just leave it at the end of the start line
-
- // Offset for padding
- outRect.offset(mView.getTotalPaddingLeft(), mView.getTotalPaddingTop());
- }
- return outRect;
- }
-}
diff --git a/src/com/android/settings/widget/LinkTextView.java b/src/com/android/settings/widget/LinkTextView.java
index 9142e39..e0fa723 100644
--- a/src/com/android/settings/widget/LinkTextView.java
+++ b/src/com/android/settings/widget/LinkTextView.java
@@ -18,12 +18,14 @@
import android.content.Context;
import android.support.annotation.NonNull;
+import android.support.v13.view.ViewCompat;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.TextView;
+import com.android.setupwizardlib.util.LinkAccessibilityHelper;
/**
* Copied from setup wizard.
@@ -39,7 +41,7 @@
public LinkTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mAccessibilityHelper = new LinkAccessibilityHelper(this);
- setAccessibilityDelegate(mAccessibilityHelper);
+ ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
}
@Override
diff --git a/src/com/android/settings/widget/RtlCompatibleViewPager.java b/src/com/android/settings/widget/RtlCompatibleViewPager.java
new file mode 100644
index 0000000..f74ea24
--- /dev/null
+++ b/src/com/android/settings/widget/RtlCompatibleViewPager.java
@@ -0,0 +1,73 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.support.v4.view.ViewPager;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.Locale;
+
+/**
+ * A {@link ViewPager} that's aware of RTL changes when used with FragmentPagerAdapter.
+ */
+public final class RtlCompatibleViewPager extends ViewPager {
+
+ /**
+ * Callback interface for responding to changing state of the selected page.
+ * Positions supplied will always be the logical position in the adapter -
+ * that is, the 0 index corresponds to the left-most page in LTR and the
+ * right-most page in RTL.
+ */
+
+ public RtlCompatibleViewPager(Context context) {
+ this(context, null /* attrs */);
+ }
+
+ public RtlCompatibleViewPager(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public int getCurrentItem() {
+ return getRtlAwareIndex(super.getCurrentItem());
+ }
+
+ @Override
+ public void setCurrentItem(int item) {
+ super.setCurrentItem(getRtlAwareIndex(item));
+ }
+
+ /**
+ * Get a "RTL friendly" index. If the locale is LTR, the index is returned as is.
+ * Otherwise it's transformed so view pager can render views using the new index for RTL. For
+ * example, the second view will be rendered to the left of first view.
+ *
+ * @param index The logical index.
+ */
+ public int getRtlAwareIndex(int index) {
+ // Using TextUtils rather than View.getLayoutDirection() because LayoutDirection is not
+ // defined until onMeasure, and this is called before then.
+ if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
+ == View.LAYOUT_DIRECTION_RTL) {
+ return getAdapter().getCount() - index - 1;
+ }
+ return index;
+ }
+}
diff --git a/src/com/android/settings/widget/SlidingTabLayout.java b/src/com/android/settings/widget/SlidingTabLayout.java
new file mode 100644
index 0000000..7099646
--- /dev/null
+++ b/src/com/android/settings/widget/SlidingTabLayout.java
@@ -0,0 +1,186 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.support.v4.view.PagerAdapter;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+/**
+ * To be used with ViewPager to provide a tab indicator component which give constant feedback as
+ * to the user's scroll progress.
+ */
+public final class SlidingTabLayout extends FrameLayout implements View.OnClickListener {
+
+ private final LinearLayout mTitleView;
+ private final View mIndicatorView;
+ private final LayoutInflater mLayoutInflater;
+
+ private RtlCompatibleViewPager mViewPager;
+ private int mSelectedPosition;
+ private float mSelectionOffset;
+
+ public SlidingTabLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mLayoutInflater = LayoutInflater.from(context);
+ mTitleView = new LinearLayout(context);
+ mTitleView.setGravity(Gravity.CENTER_HORIZONTAL);
+ mIndicatorView = mLayoutInflater.inflate(R.layout.sliding_tab_indicator_view, this, false);
+
+ addView(mTitleView, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ addView(mIndicatorView, mIndicatorView.getLayoutParams());
+ }
+
+ /**
+ * Sets the associated view pager. Note that the assumption here is that the pager content
+ * (number of tabs and tab titles) does not change after this call has been made.
+ */
+ public void setViewPager(RtlCompatibleViewPager viewPager) {
+ mTitleView.removeAllViews();
+
+ mViewPager = viewPager;
+ if (viewPager != null) {
+ viewPager.addOnPageChangeListener(new InternalViewPagerListener());
+ populateTabStrip();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ final int titleCount = mTitleView.getChildCount();
+ if (titleCount > 0) {
+ final int width = MeasureSpec.makeMeasureSpec(
+ mTitleView.getMeasuredWidth() / titleCount, MeasureSpec.EXACTLY);
+ final int height = MeasureSpec.makeMeasureSpec(
+ mIndicatorView.getMeasuredHeight(), MeasureSpec.EXACTLY);
+ mIndicatorView.measure(width, height);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ if (mTitleView.getChildCount() > 0) {
+ final int indicatorBottom = getMeasuredHeight();
+ final int indicatorHeight = mIndicatorView.getMeasuredHeight();
+ final int indicatorWidth = mIndicatorView.getMeasuredWidth();
+ final int totalWidth = getMeasuredWidth();
+ final int leftPadding = getPaddingLeft();
+ final int rightPadding = getPaddingRight();
+
+ mTitleView.layout(leftPadding, 0, mTitleView.getMeasuredWidth() + rightPadding,
+ mTitleView.getMeasuredHeight());
+ // IndicatorView should start on the right when RTL mode is enabled
+ if (isRtlMode()) {
+ mIndicatorView.layout(totalWidth - indicatorWidth,
+ indicatorBottom - indicatorHeight, totalWidth,
+ indicatorBottom);
+ } else {
+ mIndicatorView.layout(0, indicatorBottom - indicatorHeight,
+ indicatorWidth, indicatorBottom);
+ }
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ final int titleCount = mTitleView.getChildCount();
+ for (int i = 0; i < titleCount; i++) {
+ if (v == mTitleView.getChildAt(i)) {
+ mViewPager.setCurrentItem(i);
+ return;
+ }
+ }
+ }
+
+ private void onViewPagerPageChanged(int position, float positionOffset) {
+ mSelectedPosition = position;
+ mSelectionOffset = positionOffset;
+ // Translation should be reversed in RTL mode
+ final int leftIndicator = isRtlMode() ? -getIndicatorLeft() : getIndicatorLeft();
+ mIndicatorView.setTranslationX(leftIndicator);
+ }
+
+ private void populateTabStrip() {
+ final PagerAdapter adapter = mViewPager.getAdapter();
+
+ for (int i = 0; i < adapter.getCount(); i++) {
+ final TextView tabTitleView = (TextView) mLayoutInflater.inflate(
+ R.layout.sliding_tab_title_view, mTitleView, false);
+
+ tabTitleView.setText(adapter.getPageTitle(i));
+ tabTitleView.setOnClickListener(this);
+
+ mTitleView.addView(tabTitleView);
+ tabTitleView.setSelected(i == mViewPager.getCurrentItem());
+ }
+ }
+
+ private int getIndicatorLeft() {
+ View selectedTitle = mTitleView.getChildAt(mSelectedPosition);
+ int left = selectedTitle.getLeft();
+ if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
+ View nextTitle = mTitleView.getChildAt(mSelectedPosition + 1);
+ left = (int) (mSelectionOffset * nextTitle.getLeft()
+ + (1.0f - mSelectionOffset) * left);
+ }
+ return left;
+ }
+
+ private boolean isRtlMode() {
+ return getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ }
+
+ private final class InternalViewPagerListener implements
+ RtlCompatibleViewPager.OnPageChangeListener {
+ private int mScrollState;
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ final int titleCount = mTitleView.getChildCount();
+ if ((titleCount == 0) || (position < 0) || (position >= titleCount)) {
+ return;
+ }
+ onViewPagerPageChanged(position, positionOffset);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ mScrollState = state;
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ position = mViewPager.getRtlAwareIndex(position);
+ if (mScrollState == RtlCompatibleViewPager.SCROLL_STATE_IDLE) {
+ onViewPagerPageChanged(position, 0f);
+ }
+ final int titleCount = mTitleView.getChildCount();
+ for (int i = 0; i < titleCount; i++) {
+ mTitleView.getChildAt(i).setSelected(position == i);
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
index a25929c..240c062 100644
--- a/src/com/android/settings/widget/SwitchBar.java
+++ b/src/com/android/settings/widget/SwitchBar.java
@@ -45,7 +45,7 @@
public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedChangeListener,
View.OnClickListener {
- public static interface OnSwitchChangeListener {
+ public interface OnSwitchChangeListener {
/**
* Called when the checked state of the Switch has changed.
*
@@ -63,7 +63,8 @@
private String mLabel;
private String mSummary;
- private boolean mDisabledByAdmin = false;
+ private boolean mLoggingIntialized;
+ private boolean mDisabledByAdmin;
private EnforcedAdmin mEnforcedAdmin = null;
private String mMetricsTag;
@@ -233,7 +234,6 @@
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mEnforcedAdmin);
} else {
final boolean isChecked = !mSwitch.isChecked();
- MetricsLogger.count(mContext, mMetricsTag + "/switch_bar|" + isChecked, 1);
setChecked(isChecked);
}
}
@@ -247,6 +247,10 @@
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (mLoggingIntialized) {
+ MetricsLogger.count(mContext, mMetricsTag + "/switch_bar|" + isChecked, 1);
+ }
+ mLoggingIntialized = true;
propagateChecked(isChecked);
}
@@ -337,6 +341,14 @@
return Switch.class.getName();
}
+ @Override
+ public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ // Since the children are marked as not important for accessibility, re-dispatch all
+ // of their events as if they came from this view
+ event.setSource(this);
+ return true;
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index aa79080..077d601 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.wifi.WifiConfiguration;
@@ -51,6 +52,7 @@
private static final String KEY_CURRENT_IP_ADDRESS = "current_ip_address";
private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks";
private static final String KEY_SLEEP_POLICY = "sleep_policy";
+ private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
private static final String KEY_WIFI_ASSISTANT = "wifi_assistant";
private WifiManager mWifiManager;
@@ -103,6 +105,20 @@
notifyOpenNetworks.setEnabled(mWifiManager.isWifiEnabled());
final Context context = getActivity();
+ if (avoidBadWifiConfig()) {
+ // Hide preference toggle, always avoid bad wifi networks.
+ removePreference(KEY_CELLULAR_FALLBACK);
+ } else {
+ // Show preference toggle, initialized based on current settings value.
+ boolean currentSetting = avoidBadWifiCurrentSettings();
+ SwitchPreference pref = (SwitchPreference) findPreference(KEY_CELLULAR_FALLBACK);
+ // TODO: can this ever be null? The return value of avoidBadWifiConfig() can only
+ // change if the resources change, but if that happens the activity will be recreated...
+ if (pref != null) {
+ pref.setChecked(currentSetting);
+ }
+ }
+
mWifiAssistantPreference = (AppListSwitchPreference) findPreference(KEY_WIFI_ASSISTANT);
Collection<NetworkScorerAppManager.NetworkScorerAppData> scorers =
NetworkScorerAppManager.getAllValidScorers(context);
@@ -148,6 +164,16 @@
Log.e(TAG, "Invalid sleep policy value: " + value);
}
+ private boolean avoidBadWifiConfig() {
+ return getActivity().getResources().getInteger(
+ com.android.internal.R.integer.config_networkAvoidBadWifi) == 1;
+ }
+
+ private boolean avoidBadWifiCurrentSettings() {
+ return "1".equals(Settings.Global.getString(getContentResolver(),
+ Settings.Global.NETWORK_AVOID_BAD_WIFI));
+ }
+
@Override
public boolean onPreferenceTreeClick(Preference preference) {
String key = preference.getKey();
@@ -156,6 +182,11 @@
Settings.Global.putInt(getContentResolver(),
Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
((SwitchPreference) preference).isChecked() ? 1 : 0);
+ } else if (KEY_CELLULAR_FALLBACK.equals(key)) {
+ // On: avoid bad wifi. Off: prompt.
+ String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
+ Settings.Global.putString(getContentResolver(), settingName,
+ ((SwitchPreference) preference).isChecked() ? "1" : null);
} else {
return super.onPreferenceTreeClick(preference);
}
diff --git a/src/com/android/settings/wifi/LongPressAccessPointPreference.java b/src/com/android/settings/wifi/LongPressAccessPointPreference.java
index 46746cb..79f29ef 100644
--- a/src/com/android/settings/wifi/LongPressAccessPointPreference.java
+++ b/src/com/android/settings/wifi/LongPressAccessPointPreference.java
@@ -17,21 +17,8 @@
import android.app.Fragment;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.net.wifi.WifiConfiguration;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
-import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.view.View;
-import android.widget.TextView;
-
-import com.android.settings.R;
import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.AccessPointPreference;
@@ -51,6 +38,12 @@
mFragment = fragment;
}
+ public LongPressAccessPointPreference(AccessPoint accessPoint, Context context,
+ UserBadgeCache cache, boolean forSavedNetworks, int iconResId, Fragment fragment) {
+ super(accessPoint, context, cache, iconResId, forSavedNetworks);
+ mFragment = fragment;
+ }
+
@Override
public void onBindViewHolder(final PreferenceViewHolder view) {
super.onBindViewHolder(view);
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 350e0c3..460d210 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -54,6 +54,7 @@
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
+import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
@@ -262,13 +263,13 @@
showSecurityFields();
showIpConfigFields();
showProxyFields();
+ final CheckBox advancedTogglebox =
+ (CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox);
mView.findViewById(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE);
- ((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox))
- .setOnCheckedChangeListener(this);
- if (showAdvancedFields) {
- ((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox)).setChecked(true);
- mView.findViewById(R.id.wifi_advanced_fields).setVisibility(View.VISIBLE);
- }
+ advancedTogglebox.setOnCheckedChangeListener(this);
+ advancedTogglebox.setChecked(showAdvancedFields);
+ mView.findViewById(R.id.wifi_advanced_fields)
+ .setVisibility(showAdvancedFields ? View.VISIBLE : View.GONE);
}
if (mMode == WifiConfigUiBase.MODE_MODIFY) {
@@ -1210,11 +1211,18 @@
((EditText) mPasswordView).setSelection(pos);
}
} else if (view.getId() == R.id.wifi_advanced_togglebox) {
+ final View advancedToggle = mView.findViewById(R.id.wifi_advanced_toggle);
+ final int toggleVisibility;
+ final int stringID;
if (isChecked) {
- mView.findViewById(R.id.wifi_advanced_fields).setVisibility(View.VISIBLE);
+ toggleVisibility = View.VISIBLE;
+ stringID = R.string.wifi_advanced_toggle_description_expanded;
} else {
- mView.findViewById(R.id.wifi_advanced_fields).setVisibility(View.GONE);
+ toggleVisibility = View.GONE;
+ stringID = R.string.wifi_advanced_toggle_description_collapsed;
}
+ mView.findViewById(R.id.wifi_advanced_fields).setVisibility(toggleVisibility);
+ advancedToggle.setContentDescription(mContext.getString(stringID));
}
}
diff --git a/src/com/android/settings/wifi/WifiNoInternetDialog.java b/src/com/android/settings/wifi/WifiNoInternetDialog.java
index b655344..6b7b2db 100644
--- a/src/com/android/settings/wifi/WifiNoInternetDialog.java
+++ b/src/com/android/settings/wifi/WifiNoInternetDialog.java
@@ -26,6 +26,7 @@
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.os.Bundle;
+import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -35,6 +36,8 @@
import com.android.internal.app.AlertController;
import com.android.settings.R;
+import static android.net.ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
+import static android.net.ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
public final class WifiNoInternetDialog extends AlertActivity implements
@@ -46,20 +49,26 @@
private String mNetworkName;
private ConnectivityManager.NetworkCallback mNetworkCallback;
private CheckBox mAlwaysAllow;
+ private String mAction;
+
+ private boolean isKnownAction(Intent intent) {
+ return intent.getAction().equals(ACTION_PROMPT_UNVALIDATED) ||
+ intent.getAction().equals(ACTION_PROMPT_LOST_VALIDATION);
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
- if (intent == null ||
- !intent.getAction().equals(ConnectivityManager.ACTION_PROMPT_UNVALIDATED) ||
- !"netId".equals(intent.getScheme())) {
+ if (intent == null || !isKnownAction(intent) || !"netId".equals(intent.getScheme())) {
Log.e(TAG, "Unexpected intent " + intent + ", exiting");
finish();
return;
}
+ mAction = intent.getAction();
+
try {
mNetwork = new Network(Integer.parseInt(intent.getData().getSchemeSpecificPart()));
} catch (NullPointerException|NumberFormatException e) {
@@ -115,10 +124,17 @@
mAlert.setIcon(R.drawable.ic_settings_wireless);
final AlertController.AlertParams ap = mAlertParams;
- ap.mTitle = mNetworkName;
- ap.mMessage = getString(R.string.no_internet_access_text);
- ap.mPositiveButtonText = getString(R.string.yes);
- ap.mNegativeButtonText = getString(R.string.no);
+ if (ACTION_PROMPT_UNVALIDATED.equals(mAction)) {
+ ap.mTitle = mNetworkName;
+ ap.mMessage = getString(R.string.no_internet_access_text);
+ ap.mPositiveButtonText = getString(R.string.yes);
+ ap.mNegativeButtonText = getString(R.string.no);
+ } else {
+ ap.mTitle = getString(R.string.lost_internet_access_title);
+ ap.mMessage = getString(R.string.lost_internet_access_text);
+ ap.mPositiveButtonText = getString(R.string.lost_internet_access_switch);
+ ap.mNegativeButtonText = getString(R.string.lost_internet_access_cancel);
+ }
ap.mPositiveButtonListener = this;
ap.mNegativeButtonListener = this;
@@ -126,9 +142,13 @@
final View checkbox = inflater.inflate(
com.android.internal.R.layout.always_use_checkbox, null);
ap.mView = checkbox;
-
mAlwaysAllow = (CheckBox) checkbox.findViewById(com.android.internal.R.id.alwaysUse);
- mAlwaysAllow.setText(getString(R.string.no_internet_access_remember));
+
+ if (ACTION_PROMPT_UNVALIDATED.equals(mAction)) {
+ mAlwaysAllow.setText(getString(R.string.no_internet_access_remember));
+ } else {
+ mAlwaysAllow.setText(getString(R.string.lost_internet_access_persist));
+ }
setupAlert();
}
@@ -143,18 +163,27 @@
}
public void onClick(DialogInterface dialog, int which) {
- final boolean accept = (which == BUTTON_POSITIVE);
- final String action = (accept ? "Connect" : "Ignore");
+ if (which != BUTTON_NEGATIVE && which != BUTTON_POSITIVE) return;
final boolean always = mAlwaysAllow.isChecked();
+ final String what, action;
- switch (which) {
- case BUTTON_POSITIVE:
- case BUTTON_NEGATIVE:
- mCM.setAcceptUnvalidated(mNetwork, accept, always);
- Log.d(TAG, action + " network=" + mNetwork + (always ? " and remember" : ""));
- break;
- default:
- break;
+ if (ACTION_PROMPT_UNVALIDATED.equals(mAction)) {
+ what = "NO_INTERNET";
+ final boolean accept = (which == BUTTON_POSITIVE);
+ action = (accept ? "Connect" : "Ignore");
+ mCM.setAcceptUnvalidated(mNetwork, accept, always);
+ } else {
+ what = "LOST_INTERNET";
+ final boolean avoid = (which == BUTTON_POSITIVE);
+ action = (avoid ? "Switch away" : "Get stuck");
+ if (always) {
+ Settings.Global.putString(mAlertParams.mContext.getContentResolver(),
+ Settings.Global.NETWORK_AVOID_BAD_WIFI, avoid ? "1" : "0");
+ } else if (avoid) {
+ mCM.setAvoidUnvalidated(mNetwork);
+ }
}
+ Log.d(TAG, what + ": " + action + " network=" + mNetwork +
+ (always ? " and remember" : ""));
}
}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 1ca28b2..7007d19 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -636,10 +636,10 @@
}
LongPressAccessPointPreference
preference = new LongPressAccessPointPreference(accessPoint,
- getPrefContext(), mUserBadgeCache, false, this);
+ getPrefContext(), mUserBadgeCache, false,
+ R.drawable.ic_wifi_signal_0, this);
preference.setKey(key);
preference.setOrder(index++);
-
if (mOpenSsid != null && mOpenSsid.equals(accessPoint.getSsidStr())
&& !accessPoint.isSaved()
&& accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
@@ -648,6 +648,7 @@
}
getPreferenceScreen().addPreference(preference);
accessPoint.setListener(this);
+ preference.refresh();
}
}
removeCachedPrefs(getPreferenceScreen());
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index bb31539..979c27d 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -7,6 +7,14 @@
LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ mockito-target \
+ espresso-core \
+ espresso-contrib-nodep \
+ espresso-intents-nodep \
+ ub-uiautomator
+
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/app/AndroidManifest.xml b/tests/app/AndroidManifest.xml
index 2ef96cf..1c50700 100644
--- a/tests/app/AndroidManifest.xml
+++ b/tests/app/AndroidManifest.xml
@@ -51,9 +51,9 @@
</activity>
</application>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.settings"
- android:label="Settings App Tests">
+ android:label="Settings Test Cases">
</instrumentation>
<instrumentation android:name="SettingsLaunchPerformance"
diff --git a/tests/app/src/com/android/settings/dashboard/TabSelectionOnLaunchTest.java b/tests/app/src/com/android/settings/dashboard/TabSelectionOnLaunchTest.java
new file mode 100644
index 0000000..24c1ead
--- /dev/null
+++ b/tests/app/src/com/android/settings/dashboard/TabSelectionOnLaunchTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.dashboard;
+
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.settings.Settings;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isSelected;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.core.IsNot.not;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TabSelectionOnLaunchTest {
+ @Rule
+ public ActivityTestRule<Settings> mActivityRule =
+ new ActivityTestRule<>(Settings.class, true, false);
+
+ private final int FLAG_RESTART = Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK;
+ private final String ARG_SELECT_SUPPORT_TAB = "SUPPORT";
+ private final String ARG_SELECT_FAKE_TAB = "NOT_SUPPORT";
+
+ @Test
+ /* cold start for settings app with correct flags and extra always selects support tab */
+ public void test_ColdStartWithCorrectArgsCorrectFlags_SupportSelected() {
+ launchSettingsWithFlags(ARG_SELECT_SUPPORT_TAB, FLAG_RESTART);
+ verifySupportSelected();
+ }
+
+ @Test
+ /* cold start with correct flags and wrong extra defaults to all tab */
+ public void test_ColdStartWithWrongExtra_DoesNotSelectSupport() {
+ launchSettingsWithFlags(ARG_SELECT_FAKE_TAB, FLAG_RESTART);
+ verifySupportNotSelected();
+ }
+
+ @Test
+ /* warm start from elsewhere in settings with wrong flags does not select support */
+ public void test_WarmStartSummarySelectedCorrectExtraWrongFlags_DoesNotSelectSupport() {
+ InstrumentationRegistry.getContext().
+ startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
+ launchSettingsNoFlags(ARG_SELECT_SUPPORT_TAB);
+ verifySupportNotSelected();
+ }
+
+ @Test
+ /* warm start from elsewhere in settings with with wrong flags & extra does not select support*/
+ public void test_WarmStartSummarySelectedWrongExtraWrongFlags_DoesNotSelectSupport() {
+ InstrumentationRegistry.getContext().
+ startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
+ launchSettingsNoFlags(ARG_SELECT_FAKE_TAB);
+ verifySupportNotSelected();
+ }
+
+ @Test
+ /* settings does not crash on null string */
+ public void test_DoesNotCrashOnNullExtra_DoesNotSelectSupport() {
+ launchSettingsWithFlags(null, FLAG_RESTART);
+ verifySupportNotSelected();
+ }
+
+ private void verifySupportNotSelected() {
+ onView(withText(mActivityRule.getActivity().getApplicationContext().
+ getString(com.android.settings.R.string.page_tab_title_support))).
+ check(matches(not(isSelected())));
+ }
+
+ private void verifySupportSelected() {
+ onView(withText(mActivityRule.getActivity().getApplicationContext().
+ getString(com.android.settings.R.string.page_tab_title_support))).
+ check(matches(isSelected()));
+ }
+
+ private void launchSettingsWithFlags(String extra, int flags) {
+ Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
+ intent.setFlags(flags);
+ intent.putExtra(DashboardContainerFragment.EXTRA_SELECT_SETTINGS_TAB, extra);
+ mActivityRule.launchActivity(intent);
+ }
+
+ private void launchSettingsNoFlags(String extra) {
+ Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
+ intent.putExtra(DashboardContainerFragment.EXTRA_SELECT_SETTINGS_TAB, extra);
+ mActivityRule.launchActivity(intent);
+ }
+}
\ No newline at end of file
diff --git a/tests/app/src/com/android/settings/gesture/GestureSettingsTest.java b/tests/app/src/com/android/settings/gesture/GestureSettingsTest.java
new file mode 100644
index 0000000..4f3a524
--- /dev/null
+++ b/tests/app/src/com/android/settings/gesture/GestureSettingsTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.gesture;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings.Secure;
+import android.support.test.filters.MediumTest;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.UiScrollable;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+import android.widget.RelativeLayout;
+import android.widget.Switch;
+
+import com.android.settings.R;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+import org.junit.Test;
+
+/**
+ * Test for Gesture preferences.
+ */
+@MediumTest
+public class GestureSettingsTest extends InstrumentationTestCase {
+
+ private static final String TAG = "GestureSettingsTest";
+
+ private UiDevice mDevice;
+ private Context mTargetContext;
+ private String mTargetPackage;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mTargetContext = getInstrumentation().getTargetContext();
+ mTargetPackage = mTargetContext.getPackageName();
+ }
+
+ @Test
+ public void testAmbientDisplaySwitchPreference() throws Exception {
+ launchSettings();
+ UiObject dozeSwitch = getDozeSwitch();
+ assertNotNull(dozeSwitch);
+ assertTrue(dozeSwitch.exists());
+ assertToggleStateMatchesSettingValue(dozeSwitch, Secure.DOZE_ENABLED, 1, 1);
+ }
+
+ @Test
+ public void testGestureSettingsExists() throws Exception {
+ launchMoves();
+ UiObject titleObj = mDevice.findObject(new UiSelector().text(
+ mTargetContext.getResources().getString(R.string.gesture_preference_title)));
+ assertNotNull(titleObj);
+ assertTrue(titleObj.exists());
+ }
+
+ @Test
+ public void testCameraDoubleTapToggle() throws Exception {
+ assertSwitchToggle(mTargetContext.getResources().getString(
+ R.string.double_tap_power_for_camera_title),
+ Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0, 0);
+ }
+
+ @Test
+ public void testCameraDoubleTwistToggle() throws Exception {
+ assertSwitchToggle(mTargetContext.getResources().getString(
+ R.string.double_twist_for_camera_mode_title),
+ Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1, 1);
+ }
+
+ @Test
+ public void testFingerprintSwipeToggle() throws Exception {
+ assertSwitchToggle(mTargetContext.getResources().getString(
+ R.string.fingerprint_swipe_for_notifications_title),
+ Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, 1);
+ }
+
+ @Test
+ public void testDozeDoubleTapToggle() throws Exception {
+ assertSwitchToggle(mTargetContext.getResources().getString(
+ R.string.ambient_display_title),
+ Secure.DOZE_PULSE_ON_DOUBLE_TAP, 1, 1);
+ }
+
+ @Test
+ public void testDozePickupToggle() throws Exception {
+ assertSwitchToggle(mTargetContext.getResources().getString(
+ R.string.ambient_display_pickup_title),
+ Secure.DOZE_PULSE_ON_PICK_UP, 1, 1);
+ }
+
+ private void launchSettings() {
+ Intent settingsIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .setPackage(mTargetPackage)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getInstrumentation().getContext().startActivity(settingsIntent);
+ }
+
+ private void launchMoves() throws Exception {
+ launchSettings();
+ UiScrollable settings = new UiScrollable(
+ new UiSelector().packageName(mTargetPackage).scrollable(true));
+ String titleMoves =
+ mTargetContext.getResources().getString(R.string.gesture_preference_title);
+ settings.scrollTextIntoView(titleMoves);
+ mDevice.findObject(new UiSelector().text(titleMoves)).click();
+ }
+
+ private void navigateToMovesSetting(String title) throws Exception {
+ launchMoves();
+ UiScrollable moves = new UiScrollable(
+ new UiSelector().packageName(mTargetPackage).scrollable(true));
+ moves.scrollTextIntoView(title);
+ }
+
+ private UiScrollable navigateToAmbientDisplay() throws Exception {
+ UiScrollable settings = new UiScrollable(
+ new UiSelector().packageName(mTargetPackage).scrollable(true));
+ String titleDisplay =
+ mTargetContext.getResources().getString(R.string.display_settings_title);
+ settings.scrollTextIntoView(titleDisplay);
+ mDevice.findObject(new UiSelector().text(titleDisplay)).click();
+ settings.scrollTextIntoView(mTargetContext.getResources().getString(R.string.doze_title));
+ return settings;
+ }
+
+ private UiObject getGestureSwitch(String title) throws Exception {
+ UiObject titleView = mDevice.findObject(new UiSelector().text(title));
+ UiObject gestureSwitch =
+ titleView.getFromParent(new UiSelector().className(Switch.class.getName()));
+ assertNotNull(gestureSwitch);
+ assertTrue(gestureSwitch.exists());
+ return gestureSwitch;
+ }
+
+ private UiObject getDozeSwitch() throws Exception {
+ UiScrollable settings = navigateToAmbientDisplay();
+ UiObject dozeSwitch = null;
+ UiSelector relativeLayoutSelector =
+ new UiSelector().className(RelativeLayout.class.getName());
+ String titleDoze = mTargetContext.getResources().getString(R.string.doze_title);
+ for (int i = 0; i <= settings.getChildCount(relativeLayoutSelector); i++) {
+ UiObject relativeLayout = settings.getChild(relativeLayoutSelector.instance(i));
+ if (relativeLayout.getChildCount() != 2) {
+ continue;
+ }
+ UiObject obj1 = relativeLayout.getChild(new UiSelector().index(0));
+ if (obj1.getText() == titleDoze) {
+ return relativeLayout.getFromParent(
+ new UiSelector().className(Switch.class.getName()));
+ }
+ }
+ return null;
+ }
+
+ private void assertSwitchToggle(String title, String key, int defaultVal, int enabledVal)
+ throws Exception {
+ navigateToMovesSetting(title);
+ assertToggleStateMatchesSettingValue(getGestureSwitch(title), key, defaultVal, enabledVal);
+ }
+
+ private void assertToggleStateMatchesSettingValue (
+ UiObject testSwitch, String key, int defaultVal, int enabledVal) throws Exception {
+ // check initial state
+ int currentValue = Secure.getInt(mTargetContext.getContentResolver(), key, defaultVal);
+ boolean enabled = currentValue == enabledVal;
+ assertEquals(enabled, testSwitch.isChecked());
+ // toggle the preference
+ testSwitch.click();
+ assertEquals(!enabled, testSwitch.isChecked());
+ int newValue = currentValue == 1 ? 0 : 1;
+ assertEquals(newValue, Secure.getInt(mTargetContext.getContentResolver(), key, defaultVal));
+ }
+
+}
diff --git a/tests/app/src/com/android/settings/notification/SoundSettingsIntegrationTest.java b/tests/app/src/com/android/settings/notification/SoundSettingsIntegrationTest.java
new file mode 100644
index 0000000..dff7e61
--- /dev/null
+++ b/tests/app/src/com/android/settings/notification/SoundSettingsIntegrationTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.notification;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.support.test.espresso.contrib.RecyclerViewActions;
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.settings.R;
+import com.android.settings.Settings;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SoundSettingsIntegrationTest {
+
+ private AudioManager mAudioManager;
+ private final String TRUNCATED_SUMMARY = "Ring volume at";
+
+ @Rule
+ public ActivityTestRule<Settings> mActivityRule =
+ new ActivityTestRule<>(Settings.class, true);
+
+ @Test
+ public void soundPreferenceShowsCorrectSummaryOnSilentMode() {
+ mAudioManager = (AudioManager) mActivityRule.getActivity().getApplicationContext()
+ .getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+ onView(withId(R.id.dashboard_container))
+ .perform(RecyclerViewActions.scrollTo(
+ hasDescendant(withText(R.string.sound_settings))));
+ onView(withText(R.string.sound_settings_summary_silent)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void soundPreferenceShowsCorrectSummaryOnVibrateMode() {
+ mAudioManager = (AudioManager) mActivityRule.getActivity().getApplicationContext()
+ .getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
+ onView(withId(R.id.dashboard_container)).perform(RecyclerViewActions
+ .scrollTo(hasDescendant(withText(R.string.sound_settings))));
+ onView(withText(R.string.sound_settings_summary_vibrate)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void soundPreferenceShowsCorrectSummaryOnMaxVolume() {
+ mAudioManager = (AudioManager) mActivityRule.getActivity().getApplicationContext()
+ .getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+ mAudioManager.setStreamVolume(AudioManager.STREAM_RING,
+ mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING), 0);
+ onView(withId(R.id.dashboard_container))
+ .perform(RecyclerViewActions.scrollTo(
+ hasDescendant(withText(R.string.sound_settings))));
+ onView(withText(containsString(TRUNCATED_SUMMARY))).check(matches(isDisplayed()));
+ }
+}
\ No newline at end of file
diff --git a/tests/app/src/com/android/settings/tests/PrivateVolumeSettingsTest.java b/tests/app/src/com/android/settings/tests/PrivateVolumeSettingsTest.java
new file mode 100644
index 0000000..6289f1b
--- /dev/null
+++ b/tests/app/src/com/android/settings/tests/PrivateVolumeSettingsTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.tests;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.settings.Settings;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PrivateVolumeSettingsTest {
+ @Test
+ public void test_ManageStorageNotShown() {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ instrumentation.startActivitySync(
+ new Intent(android.provider.Settings.ACTION_INTERNAL_STORAGE_SETTINGS));
+ onView(withText(com.android.settings.R.string.storage_menu_manage)).check(doesNotExist());
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java b/tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java
new file mode 100644
index 0000000..61dbe08
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.password;
+
+import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
+import static com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS;
+import static com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY;
+import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE;
+import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
+import static com.android.settings.ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+/**
+ * Tests for {@link SetNewPasswordController}.
+ */
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class SetNewPasswordControllerTest {
+ private static final int CURRENT_UID = 101;
+ private static final long FINGERPRINT_CHALLENGE = -9876512313131L;
+
+ @Mock PackageManager mPackageManager;
+ @Mock FingerprintManager mFingerprintManager;
+ @Mock DevicePolicyManager mDevicePolicyManager;
+
+ @Mock private SetNewPasswordController.Ui mUi;
+ private SetNewPasswordController mSetNewPasswordController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mSetNewPasswordController = new SetNewPasswordController(
+ CURRENT_UID, mPackageManager, mFingerprintManager, mDevicePolicyManager, mUi);
+
+ when(mFingerprintManager.preEnroll()).thenReturn(FINGERPRINT_CHALLENGE);
+ when(mPackageManager.hasSystemFeature(eq(FEATURE_FINGERPRINT))).thenReturn(true);
+ }
+
+ @Test
+ public void launchChooseLockWithFingerprint() {
+ // GIVEN the device supports fingerprint.
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ // GIVEN there are no enrolled fingerprints.
+ when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false);
+ // GIVEN DPC does not disallow fingerprint for keyguard usage.
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
+ .thenReturn(0);
+
+ // WHEN the controller dispatches a set new password intent.
+ mSetNewPasswordController.dispatchSetNewPasswordIntent();
+
+ // THEN the choose lock activity is launched with fingerprint extras.
+ ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mUi).launchChooseLock(bundleArgumentCaptor.capture());
+ // THEN the extras have all values for fingerprint setup.
+ compareFingerprintExtras(bundleArgumentCaptor.getValue());
+ }
+
+ @Test
+ public void launchChooseLockWithoutFingerprint_noFingerprintFeature() {
+ // GIVEN the device does NOT support fingerprint feature.
+ when(mPackageManager.hasSystemFeature(eq(FEATURE_FINGERPRINT))).thenReturn(false);
+
+ // WHEN the controller dispatches a set new password intent.
+ mSetNewPasswordController.dispatchSetNewPasswordIntent();
+
+ // THEN the choose lock activity is launched without fingerprint extras.
+ verify(mUi).launchChooseLock(null);
+ }
+
+ @Test
+ public void launchChooseLockWithoutFingerprint_noFingerprintSensor() {
+ // GIVEN the device does NOT support fingerprint.
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+ // GIVEN there are no enrolled fingerprints.
+ when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false);
+ // GIVEN DPC does not disallow fingerprint for keyguard usage.
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
+ .thenReturn(0);
+
+ // WHEN the controller dispatches a set new password intent.
+ mSetNewPasswordController.dispatchSetNewPasswordIntent();
+
+ // THEN the choose lock activity is launched without fingerprint extras.
+ verify(mUi).launchChooseLock(null);
+ }
+
+ @Test
+ public void launchChooseLockWithoutFingerprint_hasFingerprintEnrolled() {
+ // GIVEN the device supports fingerprint.
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ // GIVEN there are no enrolled fingerprints.
+ when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(true);
+ // GIVEN DPC does not disallow fingerprint for keyguard usage.
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
+ .thenReturn(0);
+
+ // WHEN the controller dispatches a set new password intent.
+ mSetNewPasswordController.dispatchSetNewPasswordIntent();
+
+ // THEN the choose lock activity is launched without fingerprint extras.
+ verify(mUi).launchChooseLock(null);
+ }
+
+ @Test
+ public void launchChooseLockWithoutFingerprint_deviceAdminDisallowFingerprintForKeyguard() {
+ // GIVEN the device supports fingerprint.
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ // GIVEN there is an enrolled fingerprint.
+ when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(true);
+ // GIVEN DPC disallows fingerprint for keyguard usage.
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
+
+ // WHEN the controller dispatches a set new password intent.
+ mSetNewPasswordController.dispatchSetNewPasswordIntent();
+
+ // THEN the choose lock activity is launched without fingerprint extras.
+ verify(mUi).launchChooseLock(null);
+ }
+
+ private void compareFingerprintExtras(Bundle actualBundle) {
+ assertEquals(
+ "Password quality must be something in order to config fingerprint.",
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
+ actualBundle.getInt(MINIMUM_QUALITY_KEY));
+ assertTrue(
+ "All disabled preference should be removed.",
+ actualBundle.getBoolean(HIDE_DISABLED_PREFS));
+ assertTrue(
+ "There must be a fingerprint challenge.",
+ actualBundle.getBoolean(EXTRA_KEY_HAS_CHALLENGE));
+ assertEquals(
+ "The fingerprint challenge must come from the FingerprintManager",
+ FINGERPRINT_CHALLENGE,
+ actualBundle.getLong(EXTRA_KEY_CHALLENGE));
+ assertTrue(
+ "The request must be a fingerprint set up request.",
+ actualBundle.getBoolean(EXTRA_KEY_FOR_FINGERPRINT));
+ assertEquals(
+ "User id must be equaled to the input one.",
+ CURRENT_UID,
+ actualBundle.getInt(Intent.EXTRA_USER_ID));
+ }
+}
diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk
index 3ba4606..5b20173 100644
--- a/tests/unit/Android.mk
+++ b/tests/unit/Android.mk
@@ -7,7 +7,10 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ mockito-target \
+ espresso-core
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/unit/src/com/android/settings/TetherServiceTest.java b/tests/unit/src/com/android/settings/TetherServiceTest.java
index 09c6119..bec3e7e 100644
--- a/tests/unit/src/com/android/settings/TetherServiceTest.java
+++ b/tests/unit/src/com/android/settings/TetherServiceTest.java
@@ -35,11 +35,16 @@
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
+import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
@@ -61,10 +66,16 @@
import org.mockito.MockitoAnnotations;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
public class TetherServiceTest extends ServiceTestCase<TetherService> {
private static final String TAG = "TetherServiceTest";
+ private static final String FAKE_PACKAGE_NAME = "com.some.package.name";
+ private static final String ENTITLEMENT_PACKAGE_NAME = "com.some.entitlement.name";
private static final String TEST_RESPONSE_ACTION = "testProvisioningResponseAction";
private static final String TEST_NO_UI_ACTION = "testNoUiProvisioningRequestAction";
private static final int BOGUS_RECEIVER_RESULT = -5;
@@ -75,6 +86,7 @@
private TetherService mService;
private MockResources mResources;
+ private FakeUsageStatsManagerWrapper mUsageStatsManagerWrapper;
int mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
private int mLastTetherRequestType = TETHERING_INVALID;
private int mProvisionResponse = BOGUS_RECEIVER_RESULT;
@@ -83,6 +95,7 @@
@Mock private AlarmManager mAlarmManager;
@Mock private ConnectivityManager mConnectivityManager;
+ @Mock private PackageManager mPackageManager;
@Mock private WifiManager mWifiManager;
@Mock private SharedPreferences mPrefs;
@Mock private Editor mPrefEditor;
@@ -115,6 +128,27 @@
when(mPrefs.edit()).thenReturn(mPrefEditor);
when(mPrefEditor.putString(eq(CURRENT_TYPES), mStoredTypes.capture())).thenReturn(
mPrefEditor);
+ mUsageStatsManagerWrapper = new FakeUsageStatsManagerWrapper(mContext);
+
+ ResolveInfo systemAppResolveInfo = new ResolveInfo();
+ ActivityInfo systemActivityInfo = new ActivityInfo();
+ systemActivityInfo.packageName = ENTITLEMENT_PACKAGE_NAME;
+ ApplicationInfo systemAppInfo = new ApplicationInfo();
+ systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ systemActivityInfo.applicationInfo = systemAppInfo;
+ systemAppResolveInfo.activityInfo = systemActivityInfo;
+
+ ResolveInfo nonSystemResolveInfo = new ResolveInfo();
+ ActivityInfo nonSystemActivityInfo = new ActivityInfo();
+ nonSystemActivityInfo.packageName = FAKE_PACKAGE_NAME;
+ nonSystemActivityInfo.applicationInfo = new ApplicationInfo();
+ nonSystemResolveInfo.activityInfo = nonSystemActivityInfo;
+
+ List<ResolveInfo> resolvers = new ArrayList();
+ resolvers.add(nonSystemResolveInfo);
+ resolvers.add(systemAppResolveInfo);
+ when(mPackageManager.queryBroadcastReceivers(
+ any(Intent.class), eq(PackageManager.MATCH_ALL))).thenReturn(resolvers);
}
@Override
@@ -139,6 +173,19 @@
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
}
+ public void testStartKeepsProvisionAppActive() {
+ setupService();
+ getService().setUsageStatsManagerWrapper(mUsageStatsManagerWrapper);
+
+ runProvisioningForType(TETHERING_WIFI);
+
+ assertTrue(waitForProvisionRequest(TETHERING_WIFI));
+ assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
+ assertFalse(mUsageStatsManagerWrapper.isAppInactive(ENTITLEMENT_PACKAGE_NAME));
+ // Non-system handler of the intent action should stay idle.
+ assertTrue(mUsageStatsManagerWrapper.isAppInactive(FAKE_PACKAGE_NAME));
+ }
+
public void testScheduleRechecks() {
Intent intent = new Intent();
intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
@@ -192,7 +239,7 @@
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
- verify(mWifiManager).setWifiApEnabled(isNull(WifiConfiguration.class), eq(false));
+ verify(mConnectivityManager).stopTethering(ConnectivityManager.TETHERING_WIFI);
}
public void testFailureStopsTethering_Usb() {
@@ -229,6 +276,19 @@
startService(intent);
}
+ private boolean waitForAppInactive(UsageStatsManager usageStatsManager, String packageName) {
+ long startTime = SystemClock.uptimeMillis();
+ while (true) {
+ if (usageStatsManager.isAppInactive(packageName)) {
+ return true;
+ }
+ if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
+ return false;
+ }
+ SystemClock.sleep(SHORT_TIMEOUT);
+ }
+ }
+
private boolean waitForProvisionRequest(int expectedType) {
long startTime = SystemClock.uptimeMillis();
while (true) {
@@ -308,6 +368,11 @@
}
@Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+
+ @Override
public Object getSystemService(String name) {
if (ALARM_SERVICE.equals(name)) {
return mAlarmManager;
@@ -355,4 +420,27 @@
responseIntent, android.Manifest.permission.CONNECTIVITY_INTERNAL);
}
}
+
+ private static class FakeUsageStatsManagerWrapper
+ extends TetherService.UsageStatsManagerWrapper {
+ private final Set<String> mActivePackages;
+
+ FakeUsageStatsManagerWrapper(Context context) {
+ super(context);
+ mActivePackages = new HashSet<>();
+ }
+
+ @Override
+ void setAppInactive(String packageName, boolean isInactive) {
+ if (!isInactive) {
+ mActivePackages.add(packageName);
+ } else {
+ mActivePackages.remove(packageName);
+ }
+ }
+
+ boolean isAppInactive(String packageName) {
+ return !mActivePackages.contains(packageName);
+ }
+ }
}