diff --git a/Android.bp b/Android.bp index 619a390d8b85..50e6c1306112 100644 --- a/Android.bp +++ b/Android.bp @@ -84,6 +84,11 @@ android_library { "ims-common", "app-compat-annotations", ], + + resource_dirs: [ + "res-axiom", + "res", + ], } platform_compat_config { diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a8e0390d4d82..c92e126e1b0e 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -61,6 +61,7 @@ + @@ -1817,6 +1818,7 @@ + + + + + + + + diff --git a/proguard.flags b/proguard.flags index 5482f1c52d04..c86b7f0919c0 100644 --- a/proguard.flags +++ b/proguard.flags @@ -71,3 +71,5 @@ -keep class androidx.window.extensions.** { *; } -dontwarn androidx.window.extensions.** -keep class androidx.window.** { *; } + +-keep class com.axiom.settings.** diff --git a/res-axiom/layout/preference_custom_seekbar.xml b/res-axiom/layout/preference_custom_seekbar.xml new file mode 100644 index 000000000000..d5284b1d9026 --- /dev/null +++ b/res-axiom/layout/preference_custom_seekbar.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res-axiom/values/attrs.xml b/res-axiom/values/attrs.xml new file mode 100644 index 000000000000..4e32e42a3754 --- /dev/null +++ b/res-axiom/values/attrs.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res-axiom/values/strings.xml b/res-axiom/values/strings.xml new file mode 100644 index 000000000000..2286683c04d7 --- /dev/null +++ b/res-axiom/values/strings.xml @@ -0,0 +1,33 @@ + + + + + Default + + + AxiomOS version + + + Network monitor + Show net activity in statusbar + Net activity autohide threshold (KB/s) + CloudFlare DNS + AxiomPrivacy + + diff --git a/res/drawable-night/ic_dark_mode_preview.xml b/res/drawable-night/ic_dark_mode_preview.xml new file mode 100644 index 000000000000..0dab778060b4 --- /dev/null +++ b/res/drawable-night/ic_dark_mode_preview.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + diff --git a/res/drawable-nodpi/swipe_to_screenshot.png b/res/drawable-nodpi/swipe_to_screenshot.png new file mode 100644 index 000000000000..853c09e7afc9 Binary files /dev/null and b/res/drawable-nodpi/swipe_to_screenshot.png differ diff --git a/res/drawable/axiomos_logo.png b/res/drawable/axiomos_logo.png new file mode 100644 index 000000000000..5f08bdbc4600 Binary files /dev/null and b/res/drawable/axiomos_logo.png differ diff --git a/res/drawable/ic_audio_ring.xml b/res/drawable/ic_audio_ring.xml new file mode 100644 index 000000000000..a7f04a8c51f4 --- /dev/null +++ b/res/drawable/ic_audio_ring.xml @@ -0,0 +1,28 @@ + + + + + + diff --git a/res/drawable/ic_dark_mode_preview.xml b/res/drawable/ic_dark_mode_preview.xml new file mode 100644 index 000000000000..b54b915a0ef8 --- /dev/null +++ b/res/drawable/ic_dark_mode_preview.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + diff --git a/res/drawable/ic_dark_switch_bg.xml b/res/drawable/ic_dark_switch_bg.xml new file mode 100644 index 000000000000..32696b41fb97 --- /dev/null +++ b/res/drawable/ic_dark_switch_bg.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/res/drawable/ic_menu_play_store.xml b/res/drawable/ic_menu_play_store.xml new file mode 100644 index 000000000000..1ffc79e17f0e --- /dev/null +++ b/res/drawable/ic_menu_play_store.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/res/drawable/ic_settings_mobile_plan.xml b/res/drawable/ic_settings_mobile_plan.xml new file mode 100644 index 000000000000..20e8f1bdd27a --- /dev/null +++ b/res/drawable/ic_settings_mobile_plan.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/res/drawable/ic_settings_private_dns.xml b/res/drawable/ic_settings_private_dns.xml new file mode 100644 index 000000000000..f9bd6746a63c --- /dev/null +++ b/res/drawable/ic_settings_private_dns.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/res/layout/axiomos_logo_layout.xml b/res/layout/axiomos_logo_layout.xml new file mode 100644 index 000000000000..94e9efe58f09 --- /dev/null +++ b/res/layout/axiomos_logo_layout.xml @@ -0,0 +1,33 @@ + + + + + + diff --git a/res/layout/battery_usage_graph.xml b/res/layout/battery_usage_graph.xml index e79c7b94f858..310d5c7b2c31 100644 --- a/res/layout/battery_usage_graph.xml +++ b/res/layout/battery_usage_graph.xml @@ -19,7 +19,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="16dp" - android:paddingStart="@dimen/preference_no_icon_padding_start" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:orientation="vertical"> diff --git a/res/layout/dark_mode_preview.xml b/res/layout/dark_mode_preview.xml new file mode 100644 index 000000000000..ccf68f1d59bd --- /dev/null +++ b/res/layout/dark_mode_preview.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml index a01f3a9fa463..d39a94f022be 100644 --- a/res/layout/fingerprint_enroll_introduction.xml +++ b/res/layout/fingerprint_enroll_introduction.xml @@ -164,6 +164,7 @@ @@ -199,6 +200,7 @@ android:layout_width="16dp" android:layout_height="wrap_content"/> + + + + @@ -62,4 +70,3 @@ - diff --git a/res/layout/settings_homepage_app_bar_regular_phone_layout.xml b/res/layout/settings_homepage_app_bar_regular_phone_layout.xml index f817dd49f402..b5b2a85aa0e7 100644 --- a/res/layout/settings_homepage_app_bar_regular_phone_layout.xml +++ b/res/layout/settings_homepage_app_bar_regular_phone_layout.xml @@ -22,21 +22,28 @@ android:background="?android:attr/colorBackground" android:orientation="vertical"> - - - + + + + + + - \ No newline at end of file + diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml index 89d40d08b44d..a082854e22de 100644 --- a/res/layout/settings_homepage_container.xml +++ b/res/layout/settings_homepage_container.xml @@ -66,6 +66,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:gravity="bottom" app:layout_scrollFlags="scroll|exitUntilCollapsed"> "Memory usage" "App usage" "Details" - "%1$s avg memory used in last 3 hours" + "%1$s average memory used in last 3 hours" "No memory used in last 3 hours" "Sort by avg. use" "Sort by max. use" diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index cb095bb39041..f7017b626bb8 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -4564,7 +4564,7 @@ "Memory usage" "App usage" "Details" - "%1$s avg memory used in last 3 hours" + "%1$s average memory used in last 3 hours" "No memory used in last 3 hours" "Sort by avg. use" "Sort by max. use" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index aba928f6e3e8..f6a6e507c38e 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -4564,7 +4564,7 @@ "Memory usage" "App usage" "Details" - "%1$s avg memory used in last 3 hours" + "%1$s average memory used in last 3 hours" "No memory used in last 3 hours" "Sort by avg. use" "Sort by max. use" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 63093e3ee1c6..bf9fa6b9049b 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -4564,7 +4564,7 @@ "Memory usage" "App usage" "Details" - "%1$s avg memory used in last 3 hours" + "%1$s average memory used in last 3 hours" "No memory used in last 3 hours" "Sort by avg. use" "Sort by max. use" diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index a8576ba62cc4..a110a96357a2 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -4564,7 +4564,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎Memory usage‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎App usage‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎Details‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ avg memory used in last 3 hours‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ average memory used in last 3 hours‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‎No memory used in last 3 hours‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎Sort by avg use‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎Sort by max use‎‏‎‎‏‎" diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 0632f72eb09a..370e0af06136 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -39,6 +39,94 @@ All + + + @string/bluetooth_timeout_summary_never + @string/bluetooth_timeout_summary_15secs + @string/bluetooth_timeout_summary_30secs + @string/bluetooth_timeout_summary_1min + @string/bluetooth_timeout_summary_2mins + @string/bluetooth_timeout_summary_5mins + @string/bluetooth_timeout_summary_10mins + @string/bluetooth_timeout_summary_30mins + @string/bluetooth_timeout_summary_1hour + @string/bluetooth_timeout_summary_2hours + @string/bluetooth_timeout_summary_4hours + @string/bluetooth_timeout_summary_8hours + + + + + + 0 + + 15000 + + 30000 + + 60000 + + 120000 + + 300000 + + 600000 + + 1800000 + + 3600000 + + 7200000 + + 14400000 + + 28800000 + + + + + @string/wifi_timeout_summary_never + @string/wifi_timeout_summary_15secs + @string/wifi_timeout_summary_30secs + @string/wifi_timeout_summary_1min + @string/wifi_timeout_summary_2mins + @string/wifi_timeout_summary_5mins + @string/wifi_timeout_summary_10mins + @string/wifi_timeout_summary_30mins + @string/wifi_timeout_summary_1hour + @string/wifi_timeout_summary_2hours + @string/wifi_timeout_summary_4hours + @string/wifi_timeout_summary_8hours + + + + + + 0 + + 15000 + + 30000 + + 60000 + + 120000 + + 300000 + + 600000 + + 1800000 + + 3600000 + + 7200000 + + 14400000 + + 28800000 + + 15 seconds @@ -165,10 +253,31 @@ Largest + + 80% + 85% + 90% + 95% + 100% + 105% + 110% + 115% + 120% + 125% + 130% + + + 0.80 0.85 - 1.0 + 0.90 + 0.95 + 1.00 + 1.05 + 1.10 1.15 + 1.20 + 1.25 1.30 diff --git a/res/values/axiom_arrays.xml b/res/values/axiom_arrays.xml new file mode 100644 index 000000000000..14929420ca90 --- /dev/null +++ b/res/values/axiom_arrays.xml @@ -0,0 +1,29 @@ + + + + + + + @string/default_string + @string/navigation_bar_ime_space_value_narrow + @string/hidden_string + + + + 0 + 1 + 2 + + + diff --git a/res/values/axiom_config.xml b/res/values/axiom_config.xml new file mode 100644 index 000000000000..5e71d3921cb0 --- /dev/null +++ b/res/values/axiom_config.xml @@ -0,0 +1,27 @@ + + + + + com.android.localtransport/.LocalTransport + + + + false + + + false + diff --git a/res/values/axiom_strings.xml b/res/values/axiom_strings.xml new file mode 100644 index 000000000000..dd83d62c1d85 --- /dev/null +++ b/res/values/axiom_strings.xml @@ -0,0 +1,108 @@ + + + + + + SELinux status + Disabled + Permissive + Enforcing + + + AxiomOS Version + + + Tap to show info + + + Google Play + + + Battery temperature + + + AxiomOS Build Date + + + Change backup provider + Select backup provider + + + Swipe to screenshot + Swipe 3 fingers down the screen to take a screenshot + + + Navigation bar + + + Remove space under keyboard + Make the navigation bar under the keyboard narrow + + + Hidden + Default + Space under the keyboard + Narrow + + + Full + Bottom + Options + Amount of screen height used as touchable region for back gesture. + + + reTicker + Replace heads-up notification with slim and less invasive version of redesigned ticker + Use app colored background + Replace reTicker background color using notification app main color + + + Sensor block per-package + Block access to certain sensors for some apps to save battery + + + Peak refresh rate + + + Minimum refresh rate + + + Automatically raises the refresh rate from 60 to %1$d Hz for some content. Increases battery usage. + + + Link ring & notification volumes + + + Volume dialog + Show volume panel on left + Move volume panel to the left side of the screen + + + High touch sensitivity + Increase touchscreen sensitivity so it can be used while wearing gloves + + + Touchscreen hovering + Allows you to hover the screen like a mouse in web browsers, remote desktops, etc + + + High touch polling rate + Increase touchscreen polling rate + + + Use better black theme + Try to force black background colors + diff --git a/res/values/config.xml b/res/values/config.xml index d7528c63bd00..1b1b0b9e22a9 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -63,7 +63,7 @@ - false + true false @@ -217,10 +217,10 @@ Whether or not the homepage should be powered by legacy suggestion (versus contextual cards) Default to true as not all devices support contextual cards. --> - true + false - false + true true @@ -229,7 +229,7 @@ true - true + false true @@ -289,7 +289,7 @@ false - + intent:#Intent;action=com.android.settings.action.VIEW_ACCOUNT;category=android.intent.category.DEFAULT;launchFlags=0x8000;S.extra.callingPackageName=com.android.settings;end false diff --git a/res/values/dimens.xml b/res/values/dimens.xml index b88d01d12b98..519afad5eb93 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -143,6 +143,8 @@ 20dp + + 104dp 8dp 24dp 24dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 8f7c1c26eeb8..6123f4c51140 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -27,6 +27,45 @@ Turn on + + Bluetooth timeout + + + Bluetooth will turn off after %1$s if no devices connected + Do not automatically turn off Bluetooth + Never + 15 seconds + 30 seconds + 1 minute + 2 minutes + 5 minutes + 10 minutes + 30 minutes + 1 hour + 2 hours + 4 hours + 8 hours + + + Turn off Wi-Fi automatically + + + Automatically turn off Wi-Fi after a set amount of time. + Wi-Fi will turn off after %1$s if no network connected + Disabled + Never + 15 seconds + 30 seconds + 1 minute + 2 minutes + 5 minutes + 10 minutes + 30 minutes + 1 hour + 2 hours + 4 hours + 8 hours + Unknown @@ -10920,7 +10959,7 @@ Details - %1$s avg memory used in last 3 hours + %1$s average memory used in last 3 hours No memory used in last 3 hours @@ -12586,7 +12625,7 @@ - + com.google @@ -12597,7 +12636,7 @@ - Account + Google Account Device name @@ -12760,6 +12799,8 @@ Preferred network mode: CDMA/EvDo/GSM/WCDMA Preferred network mode: LTE + + Preferred network mode: LTE only Preferred network mode: GSM/WCDMA/LTE @@ -12825,8 +12866,12 @@ 4G LTE (recommended) + + LTE only 4G (recommended) + + 4G only 3G @@ -13293,7 +13338,7 @@ %1$s copied to clipboard. - + Profile picture, double tap to open Google Account 0 apps used permissions @@ -14181,4 +14226,11 @@ QR code isn\u0027t a valid format + + Game Space + Enhance your gaming experience + + Save screenshot timestamp to EXIF + Enables adding a timestamp to screenshot EXIF metadata + diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml index 0287fc65d2d1..e79e99393fea 100644 --- a/res/xml/accessibility_settings.xml +++ b/res/xml/accessibility_settings.xml @@ -52,15 +52,6 @@ android:title="@string/accessibility_color_and_motion_title" settings:searchable="true"/> - - + + diff --git a/res/xml/apps.xml b/res/xml/apps.xml index ea1e69213632..3c38aa21b5ed 100644 --- a/res/xml/apps.xml +++ b/res/xml/apps.xml @@ -62,6 +62,14 @@ + + + diff --git a/res/xml/backup_transport_settings.xml b/res/xml/backup_transport_settings.xml new file mode 100644 index 000000000000..cc8cc9ac1437 --- /dev/null +++ b/res/xml/backup_transport_settings.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml index 4e58e66887d2..e97169a6b1e2 100644 --- a/res/xml/configure_notification_settings.xml +++ b/res/xml/configure_notification_settings.xml @@ -111,6 +111,22 @@ + + + + + + settings:controller="com.android.settings.slices.SlicePreferenceController"/> + + + + + + - + android:summary="@string/ota_disable_automatic_update_summary" /--> @@ -460,10 +460,6 @@ android:entries="@array/overlay_display_devices_entries" android:entryValues="@array/overlay_display_devices_values" /> - - - + + + + + + + + + + - - + + + + + + + + + + + + + + diff --git a/res/xml/firmware_version.xml b/res/xml/firmware_version.xml index 41f7733cfb2b..8e1a6ec692e4 100644 --- a/res/xml/firmware_version.xml +++ b/res/xml/firmware_version.xml @@ -21,29 +21,44 @@ android:title="@string/firmware_version" settings:keywords="@string/keywords_android_version"> - + - + + + settings:searchable="false" + settings:controller="com.android.settings.deviceinfo.firmwareversion.axiomVersionDetailPreferenceController"/> - + settings:controller="com.android.settings.deviceinfo.firmwareversion.BuildDatePreferenceController"/> + + + + + + + + + + + + + + + + + + + - diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml index 48813606fe94..180b92ac03b1 100644 --- a/res/xml/gestures.xml +++ b/res/xml/gestures.xml @@ -33,6 +33,12 @@ settings:searchable="false" settings:controller="com.android.settings.gestures.SwipeToNotificationPreferenceController" /> + + + + + android:selectable="false"/> - + + + + + + + + + + settings:controller="com.android.settings.fuelgauge.SmartBatteryPreferenceController"/> @@ -89,6 +89,14 @@ android:order="-140" settings:controller="com.android.settings.notification.NotificationVolumePreferenceController"/> + + + + + + + + + diff --git a/res/xml/swipe_to_screenshot_gesture_settings.xml b/res/xml/swipe_to_screenshot_gesture_settings.xml new file mode 100644 index 000000000000..6d8b927a9436 --- /dev/null +++ b/res/xml/swipe_to_screenshot_gesture_settings.xml @@ -0,0 +1,37 @@ + + + + + + + + + + diff --git a/res/xml/usb_details_fragment.xml b/res/xml/usb_details_fragment.xml index 96a449b5dd46..c9889e5e7bcf 100644 --- a/res/xml/usb_details_fragment.xml +++ b/res/xml/usb_details_fragment.xml @@ -17,7 +17,7 @@ + + buildPreferenceControllers( final List controllers = new ArrayList<>(); controllers.add(new CameraGesturePreferenceController(context)); controllers.add(new LiftToWakePreferenceController(context)); - controllers.add(new ScreenSaverPreferenceController(context)); controllers.add(new TapToWakePreferenceController(context)); controllers.add(new VrDisplayPreferenceController(context)); controllers.add(new ShowOperatorNamePreferenceController(context)); @@ -88,6 +92,25 @@ private static List buildPreferenceControllers( public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.display_settings) { + @Override + public List getNonIndexableKeys(Context context) { + List keys = super.getNonIndexableKeys(context); + LineageHardwareManager hardware = LineageHardwareManager.getInstance(context); + if (!context.getResources().getBoolean( + com.android.internal.R.bool.config_proximityCheckOnWake)) { + keys.add(KEY_PROXIMITY_ON_WAKE); + } + if (!hardware.isSupported( + LineageHardwareManager.FEATURE_HIGH_TOUCH_POLLING_RATE)) { + keys.add(KEY_HIGH_TOUCH_POLLING_RATE); + } + if (!hardware.isSupported( + LineageHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + keys.add(KEY_HIGH_TOUCH_SENSITIVITY); + } + return keys; + } + @Override public List createPreferenceControllers( Context context) { diff --git a/src/com/android/settings/accounts/AccountFeatureProviderImpl.java b/src/com/android/settings/accounts/AccountFeatureProviderImpl.java index 90b581ba80e4..716cdcba6d6e 100644 --- a/src/com/android/settings/accounts/AccountFeatureProviderImpl.java +++ b/src/com/android/settings/accounts/AccountFeatureProviderImpl.java @@ -1,16 +1,20 @@ package com.android.settings.accounts; import android.accounts.Account; +import android.accounts.AccountManager; import android.content.Context; +import com.android.settings.R; +import com.android.settings.overlay.FeatureFactory; + public class AccountFeatureProviderImpl implements AccountFeatureProvider { @Override public String getAccountType() { - return null; + return FeatureFactory.getAppContext().getString(R.string.account_type); } @Override public Account[] getAccounts(Context context) { - return new Account[0]; + return AccountManager.get(context).getAccountsByType(getAccountType()); } } diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java index 0f21097f539e..c0003d17dbdb 100644 --- a/src/com/android/settings/applications/AppInfoBase.java +++ b/src/com/android/settings/applications/AppInfoBase.java @@ -179,7 +179,7 @@ protected void showDialogInner(int id, int moveErrorCode) { @Override public void onRunningStateChanged(boolean running) { - // No op. + refreshUi(); } @Override diff --git a/src/com/android/settings/applications/GameSpaceController.java b/src/com/android/settings/applications/GameSpaceController.java new file mode 100644 index 000000000000..ca442f4757fd --- /dev/null +++ b/src/com/android/settings/applications/GameSpaceController.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 Bianca 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.content.Context; +import android.content.pm.PackageManager; +import android.content.Intent; +import android.content.ComponentName; +import android.os.UserHandle; +import android.text.TextUtils; + +import androidx.preference.Preference; + +import com.android.settings.core.BasePreferenceController; + +public class GameSpaceController extends BasePreferenceController { + + private static final String GAME_PACKAGE = "io.chaldeaprjkt.gamespace"; + private static final String GAME_SETTINGS = "io.chaldeaprjkt.gamespace.settings.SettingsActivity"; + + private final PackageManager mPackageManager; + + public GameSpaceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mPackageManager = mContext.getPackageManager(); + } + + private Intent settingsIntent() { + Intent intent = new Intent(); + ComponentName component = new ComponentName(GAME_PACKAGE, GAME_SETTINGS); + intent.setComponent(component); + return intent; + } + + @Override + public int getAvailabilityStatus() { + return mContext.getPackageManager().resolveActivity(settingsIntent(), 0) != null + ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { + return false; + } + + Intent intent = settingsIntent(); + intent.putExtra("referer", this.getClass().getCanonicalName()); + mContext.startActivityAsUser(intent, UserHandle.CURRENT); + return true; + } +} diff --git a/src/com/android/settings/applications/ProcStatsData.java b/src/com/android/settings/applications/ProcStatsData.java index 7742e98b56e8..9ef2bf7b075a 100644 --- a/src/com/android/settings/applications/ProcStatsData.java +++ b/src/com/android/settings/applications/ProcStatsData.java @@ -282,7 +282,7 @@ private ArrayList getProcs(ProcessDataCollection bgTotals, final ProcessState proc = mStats.mProcesses.get(pkgProc.getName(), pkgProc.getUid()); if (proc == null) { - Log.w(TAG, "No process found for pkg " + st.mPackageName + if (DEBUG) Log.w(TAG, "No process found for pkg " + st.mPackageName + "/" + st.mUid + " proc name " + pkgProc.getName()); continue; } diff --git a/src/com/android/settings/applications/UsageAccessDetails.java b/src/com/android/settings/applications/UsageAccessDetails.java index 8085b691c5b7..bd4bd7b7a52d 100644 --- a/src/com/android/settings/applications/UsageAccessDetails.java +++ b/src/com/android/settings/applications/UsageAccessDetails.java @@ -84,6 +84,12 @@ public void onCreate(Bundle savedInstanceState) { .setPackage(mPackageName); } + @Override + public void onDestroy() { + super.onDestroy(); + mUsageBridge.release(); + } + @Override public boolean onPreferenceClick(Preference preference) { return false; diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index 18cb4b3b80b4..89b2b809de57 100755 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -36,6 +36,7 @@ import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; @@ -55,6 +56,7 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.Utils; import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesDetailsPreferenceController; import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetailPreferenceController; @@ -94,6 +96,8 @@ public class AppInfoDashboardFragment extends DashboardFragment static final int INSTALL_INSTANT_APP_MENU = 3; static final int ACCESS_RESTRICTED_SETTINGS = 4; + public static final int PLAY_STORE = 5; + // Result code identifiers @VisibleForTesting static final int REQUEST_UNINSTALL = 0; @@ -178,6 +182,7 @@ public void onAttach(Context context) { use(AppAllServicesPreferenceController.class).setPackageName(packageName); use(AppStoragePreferenceController.class).setParentFragment(this); use(AppVersionPreferenceController.class).setParentFragment(this); + use(AppPackageNamePreferenceController.class).setParentFragment(this); use(InstantAppDomainsPreferenceController.class).setParentFragment(this); final HibernationSwitchPreferenceController appHibernationSettings = @@ -393,6 +398,9 @@ boolean ensureDisplayableModule(Activity activity) { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); + menu.add(0, PLAY_STORE, 0, R.string.app_play_store) + .setIcon(R.drawable.ic_menu_play_store) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); menu.add(0, UNINSTALL_UPDATES, 0, R.string.app_factory_reset) .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); menu.add(0, UNINSTALL_ALL_USERS_MENU, 1, R.string.uninstall_all_users_text) @@ -422,6 +430,10 @@ public void onPrepareOptionsMenu(Menu menu) { RestrictedLockUtilsInternal.setMenuItemAsDisabledByAdmin(getActivity(), uninstallUpdatesItem, mAppsControlDisallowedAdmin); } + // Utils.isSystemPackage doesn't include all aosp built apps, like Contacts etc. Add them + // and grab the Google Play Store itself (com.android.vending) in the process + menu.findItem(PLAY_STORE).setVisible(!Utils.isSystemPackage(getContext().getResources(), mPm, mPackageInfo) + && !isAospOrStore(mAppEntry.info.packageName)); } private static void showLockScreen(Context context, Runnable successRunnable) { @@ -488,6 +500,9 @@ public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(getContext(), toastString, Toast.LENGTH_LONG).show(); }); return true; + case PLAY_STORE: + openPlayStore(mAppEntry.info.packageName); + return true; } return super.onOptionsItemSelected(item); } @@ -599,6 +614,18 @@ protected boolean shouldSkipForInitialSUW() { return true; } + private void openPlayStore(String packageName) { + // Launch an intent to the play store entry + String playURL = "https://play.google.com/store/apps/details?id=" + packageName; + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse(playURL)); + startActivity(i); + } + + private boolean isAospOrStore(String packageName) { + return packageName.contains("com.android"); + } + private void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) { stopListeningToPackageRemove(); // Create new intent to launch Uninstaller activity diff --git a/src/com/android/settings/applications/appinfo/AppPackageNamePreferenceController.java b/src/com/android/settings/applications/appinfo/AppPackageNamePreferenceController.java new file mode 100644 index 000000000000..bd4f12f50881 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AppPackageNamePreferenceController.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 The LineageOS 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.appinfo; + +import android.content.Context; + +public class AppPackageNamePreferenceController extends AppInfoPreferenceControllerBase { + + public AppPackageNamePreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public CharSequence getSummary() { + return mParent.getPackageInfo().packageName; + } +} diff --git a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java index b72327443652..3a5a8243acbc 100644 --- a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java +++ b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java @@ -62,6 +62,12 @@ public void onCreate(Bundle savedInstanceState) { mSwitchPref.setOnPreferenceChangeListener(this); } + @Override + public void onDestroy() { + super.onDestroy(); + mAppBridge.release(); + } + @Override public boolean onPreferenceChange(Preference preference, Object newValue) { final boolean checked = (Boolean) newValue; diff --git a/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java b/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java index 26adb442acda..4adf212108dd 100644 --- a/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java +++ b/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java @@ -75,6 +75,12 @@ public void onCreate(Bundle savedInstanceState) { .setPackage(mPackageName); } + @Override + public void onDestroy() { + super.onDestroy(); + mAppBridge.release(); + } + @Override public boolean onPreferenceClick(Preference preference) { return false; diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index ead9840af7a0..894117b53d54 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -754,9 +754,11 @@ void updateOptionsMenu() { } mOptionsMenu.findItem(R.id.advanced).setVisible(false); - mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE + mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible( + (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN) && mSortOrder != R.id.sort_order_alpha); - mOptionsMenu.findItem(R.id.sort_order_size).setVisible(mListType == LIST_TYPE_STORAGE + mOptionsMenu.findItem(R.id.sort_order_size).setVisible( + (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN) && mSortOrder != R.id.sort_order_size); mOptionsMenu.findItem(R.id.show_system).setVisible(!mShowSystem diff --git a/src/com/android/settings/backup/BackupSettingsFragment.java b/src/com/android/settings/backup/BackupSettingsFragment.java index 7df19f54660d..7fcbd63b7ce8 100644 --- a/src/com/android/settings/backup/BackupSettingsFragment.java +++ b/src/com/android/settings/backup/BackupSettingsFragment.java @@ -42,6 +42,13 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } + @Override + public void onStart() { + super.onStart(); + // update information when we navigate back from TransportActivity + displayResourceTilesToScreen(getPreferenceScreen()); + } + /** * Get the tag string for logging. */ diff --git a/src/com/android/settings/backup/BackupSettingsPreferenceController.java b/src/com/android/settings/backup/BackupSettingsPreferenceController.java index 4e0e3b4e7482..3208ae4fe76c 100644 --- a/src/com/android/settings/backup/BackupSettingsPreferenceController.java +++ b/src/com/android/settings/backup/BackupSettingsPreferenceController.java @@ -30,24 +30,24 @@ public class BackupSettingsPreferenceController extends AbstractPreferenceContro implements PreferenceControllerMixin { private static final String BACKUP_SETTINGS = "backup_settings"; private static final String MANUFACTURER_SETTINGS = "manufacturer_backup"; - private Intent mBackupSettingsIntent; - private CharSequence mBackupSettingsTitle; - private String mBackupSettingsSummary; + private final BackupSettingsHelper settingsHelper; private Intent mManufacturerIntent; private String mManufacturerLabel; public BackupSettingsPreferenceController(Context context) { super(context); - BackupSettingsHelper settingsHelper = new BackupSettingsHelper(context); - mBackupSettingsIntent = settingsHelper.getIntentForBackupSettings(); - mBackupSettingsTitle = settingsHelper.getLabelForBackupSettings(); - mBackupSettingsSummary = settingsHelper.getSummaryForBackupSettings(); + settingsHelper = new BackupSettingsHelper(context); mManufacturerIntent = settingsHelper.getIntentProvidedByManufacturer(); mManufacturerLabel = settingsHelper.getLabelProvidedByManufacturer(); } @Override public void displayPreference(PreferenceScreen screen) { + // we don't get these in the constructor, so we can get updates for them later + Intent mBackupSettingsIntent = settingsHelper.getIntentForBackupSettings(); + CharSequence mBackupSettingsTitle = settingsHelper.getLabelForBackupSettings(); + String mBackupSettingsSummary = settingsHelper.getSummaryForBackupSettings(); + Preference backupSettings = screen.findPreference(BACKUP_SETTINGS); Preference manufacturerSettings = screen.findPreference(MANUFACTURER_SETTINGS); backupSettings.setIntent(mBackupSettingsIntent); diff --git a/src/com/android/settings/backup/transport/Transport.java b/src/com/android/settings/backup/transport/Transport.java new file mode 100644 index 000000000000..d2fd6e081f93 --- /dev/null +++ b/src/com/android/settings/backup/transport/Transport.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Calyx Institute + * + * 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.backup.transport; + +class Transport { + final String name; + final CharSequence dataManagementLabel; + final CharSequence destinationString; + + Transport(String name, CharSequence dataManagementLabel, CharSequence destinationString) { + this.name = name; + this.dataManagementLabel = dataManagementLabel; + this.destinationString = destinationString; + } +} diff --git a/src/com/android/settings/backup/transport/TransportActivity.java b/src/com/android/settings/backup/transport/TransportActivity.java new file mode 100644 index 000000000000..1adcb9048a0e --- /dev/null +++ b/src/com/android/settings/backup/transport/TransportActivity.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Calyx Institute + * + * 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.backup.transport; + +import android.os.Bundle; +import androidx.fragment.app.FragmentActivity; + +/** + * Activity to allow the user to choose the {@link android.app.backup.BackupTransport}. + * + * Set {@code config_backup_settings_intent} to {@code settings://com.android.settings.backup.transport} to activate. + * Don't forget to also set {@code config_backup_settings_label} or else it won't be shown. + */ +public class TransportActivity extends FragmentActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getSupportFragmentManager().beginTransaction() + .replace(android.R.id.content, new TransportFragment()) + .commit(); + } + +} diff --git a/src/com/android/settings/backup/transport/TransportFragment.java b/src/com/android/settings/backup/transport/TransportFragment.java new file mode 100644 index 000000000000..6c6a8ce9957b --- /dev/null +++ b/src/com/android/settings/backup/transport/TransportFragment.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Calyx Institute + * + * 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.backup.transport; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import com.android.settings.R; +import com.android.settings.backup.transport.TransportPreferenceController.OnTransportChangedListener; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.core.AbstractPreferenceController; + +import java.util.ArrayList; +import java.util.List; + +public class TransportFragment extends DashboardFragment implements OnTransportChangedListener { + + private static final String TAG = "TransportFragment"; + + /** + * Get the tag string for logging. + */ + @Override + protected String getLogTag() { + return TAG; + } + + /** + * Get the res id for static preference xml for this fragment. + */ + @Override + protected int getPreferenceScreenResId() { + return R.xml.backup_transport_settings; + } + + /** + * Get a list of {@link AbstractPreferenceController} for this fragment. + */ + @Override + protected List createPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); + controllers.add(new TransportPreferenceController(context, this)); + return controllers; + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.BACKUP_SETTINGS; + } + + @Override + public void onTransportChanged(String transportName) { + requireActivity().finish(); + } + +} diff --git a/src/com/android/settings/backup/transport/TransportHelper.java b/src/com/android/settings/backup/transport/TransportHelper.java new file mode 100644 index 000000000000..1ab5a596054e --- /dev/null +++ b/src/com/android/settings/backup/transport/TransportHelper.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2020 The Calyx Institute + * + * 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.backup.transport; + +import android.app.backup.IBackupManager; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.util.Log; +import androidx.annotation.Nullable; + +import com.android.settings.R; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Helper class for {@link TransportActivity} that interacts with {@link IBackupManager}. + */ +class TransportHelper { + private static final String TAG = "TransportHelper"; + + private final IBackupManager mBackupManager = IBackupManager.Stub.asInterface( + ServiceManager.getService(Context.BACKUP_SERVICE)); + + private Context mContext; + + TransportHelper(Context context) { + mContext = context; + } + + List getTransports() { + String[] backupTransports = getBackupTransports(); + if (backupTransports == null) return Collections.emptyList(); + ArrayList transports = new ArrayList<>(backupTransports.length); + String[] ignoredTransports = mContext.getResources().getStringArray( + R.array.config_ignored_backup_transports); + for (String name : getBackupTransports()) { + boolean ignored = false; + for (String ignoredTransport : ignoredTransports) { + if (name.equals(ignoredTransport)) ignored = true; + } + if (ignored) continue; + CharSequence label = getLabelFromBackupTransport(name); + if (label == null || label.length() == 0) label = name; + Transport transport = new Transport(name, label, getSummaryFromBackupTransport(name)); + transports.add(transport); + } + return transports; + } + + void selectTransport(String name) { + try { + mBackupManager.selectBackupTransport(name); + } catch (RemoteException e) { + Log.e(TAG, "Error selecting transport: " + name, e); + } + } + + @Nullable + private String[] getBackupTransports() { + try { + String[] transports = mBackupManager.listAllTransports(); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Received all backup transports: " + Arrays.toString(transports)); + } + return transports; + } catch (RemoteException e) { + Log.e(TAG, "Error getting all backup transports", e); + } + return null; + } + + private CharSequence getLabelFromBackupTransport(String transport) { + try { + CharSequence label = mBackupManager.getDataManagementLabelForUser(UserHandle.myUserId(), transport); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Received the backup settings label from " + transport + ": " + label); + } + return label; + } catch (RemoteException e) { + Log.e(TAG, "Error getting data management label for " + transport, e); + } + return null; + } + + private String getSummaryFromBackupTransport(String transport) { + try { + String summary = mBackupManager.getDestinationString(transport); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Received the backup settings summary from " + transport + ": " + summary); + } + return summary; + } catch (RemoteException e) { + Log.e(TAG, "Error getting data management summary", e); + } + return null; + } +} diff --git a/src/com/android/settings/backup/transport/TransportPreferenceController.java b/src/com/android/settings/backup/transport/TransportPreferenceController.java new file mode 100644 index 000000000000..1dc5a5119118 --- /dev/null +++ b/src/com/android/settings/backup/transport/TransportPreferenceController.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2020 The Calyx Institute + * + * 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.backup.transport; + +import android.content.Context; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +import com.android.settingslib.core.AbstractPreferenceController; + +public class TransportPreferenceController extends AbstractPreferenceController { + + interface OnTransportChangedListener { + void onTransportChanged(String transportName); + } + + private final OnTransportChangedListener listener; + private final TransportHelper transportHelper; + + public TransportPreferenceController(Context context, OnTransportChangedListener listener) { + super(context); + this.listener = listener; + transportHelper = new TransportHelper(context); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + for (Transport transport : transportHelper.getTransports()) { + screen.addPreference(getPreferenceForTransport(transport)); + } + } + + private Preference getPreferenceForTransport(Transport transport) { + Preference p = new Preference(mContext); + p.setTitle(transport.dataManagementLabel); + p.setSummary(transport.destinationString); + p.setIconSpaceReserved(false); + p.setOnPreferenceClickListener(preference -> { + transportHelper.selectTransport(transport.name); + listener.onTransportChanged(transport.name); + return true; + }); + return p; + } + + /** + * Returns true if preference is available (should be displayed) + */ + @Override + public boolean isAvailable() { + return true; + } + + /** + * Returns the key for this preference. + */ + @Override + public String getPreferenceKey() { + return null; + } +} diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java index 6fe14e6a9cd8..47034bceca9e 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java @@ -26,6 +26,7 @@ import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; +import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.ImageView; @@ -92,6 +93,7 @@ protected void onCreate(Bundle savedInstanceState) { final TextView footerMessage4 = findViewById(R.id.footer_message_4); final TextView footerMessage5 = findViewById(R.id.footer_message_5); final TextView footerMessage6 = findViewById(R.id.footer_message_6); + final TextView footerMessageLearnMore = findViewById(R.id.footer_message_learn_more); footerMessage2.setText(getFooterMessage2()); footerMessage3.setText(getFooterMessage3()); footerMessage4.setText(getFooterMessage4()); @@ -102,6 +104,10 @@ protected void onCreate(Bundle savedInstanceState) { final TextView footerTitle2 = findViewById(R.id.footer_title_2); footerTitle1.setText(getFooterTitle1()); footerTitle2.setText(getFooterTitle2()); + + if (TextUtils.isEmpty(footerMessageLearnMore.getText())) { + findViewById(R.id.layout_footer_learn_more).setVisibility(View.GONE); + } } @Override diff --git a/src/com/android/settings/bluetooth/BluetoothTimeoutPreferenceController.java b/src/com/android/settings/bluetooth/BluetoothTimeoutPreferenceController.java new file mode 100644 index 000000000000..244147948aa5 --- /dev/null +++ b/src/com/android/settings/bluetooth/BluetoothTimeoutPreferenceController.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2020 The Calyx Institute + * + * 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.bluetooth; + +import android.bluetooth.BluetoothAdapter; +import android.content.Context; +import android.provider.Settings; +import android.util.Log; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.core.PreferenceControllerMixin; + +public class BluetoothTimeoutPreferenceController extends BasePreferenceController implements + PreferenceControllerMixin, Preference.OnPreferenceChangeListener { + private static final String TAG = "BluetoothTimeoutPrefCtrl"; + + public static final int FALLBACK_BLUETOOTH_TIMEOUT_VALUE = 0; + + private final String mBluetoothTimeoutKey; + + protected BluetoothAdapter mBluetoothAdapter; + + public BluetoothTimeoutPreferenceController(Context context, String key) { + super(context, key); + mBluetoothTimeoutKey = key; + + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (mBluetoothAdapter == null) { + Log.e(TAG, "Bluetooth is not supported on this device"); + return; + } + } + + @Override + public int getAvailabilityStatus() { + return mBluetoothAdapter != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public String getPreferenceKey() { + return mBluetoothTimeoutKey; + } + + @Override + public void updateState(Preference preference) { + final ListPreference timeoutListPreference = (ListPreference) preference; + final long currentTimeout = Settings.Global.getLong(mContext.getContentResolver(), + Settings.Global.BLUETOOTH_OFF_TIMEOUT, FALLBACK_BLUETOOTH_TIMEOUT_VALUE); + timeoutListPreference.setValue(String.valueOf(currentTimeout)); + updateTimeoutPreferenceDescription(timeoutListPreference, + Long.parseLong(timeoutListPreference.getValue())); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + try { + long value = Long.parseLong((String) newValue); + Settings.Global.putLong(mContext.getContentResolver(), Settings.Global.BLUETOOTH_OFF_TIMEOUT, value); + updateTimeoutPreferenceDescription((ListPreference) preference, value); + } catch (NumberFormatException e) { + Log.e(TAG, "could not persist bluetooth timeout setting", e); + } + return true; + } + + public static CharSequence getTimeoutDescription( + long currentTimeout, CharSequence[] entries, CharSequence[] values) { + if (currentTimeout < 0 || entries == null || values == null + || values.length != entries.length) { + return null; + } + + for (int i = 0; i < values.length; i++) { + long timeout = Long.parseLong(values[i].toString()); + if (currentTimeout == timeout) { + return entries[i]; + } + } + return null; + } + + private void updateTimeoutPreferenceDescription(ListPreference preference, + long currentTimeout) { + final CharSequence[] entries = preference.getEntries(); + final CharSequence[] values = preference.getEntryValues(); + final CharSequence timeoutDescription = getTimeoutDescription( + currentTimeout, entries, values); + String summary = ""; + if (timeoutDescription != null) { + if (currentTimeout != 0) + summary = mContext.getString(R.string.bluetooth_timeout_summary, timeoutDescription); + else + summary = mContext.getString(R.string.bluetooth_timeout_summary2); + } + preference.setSummary(summary); + } +} diff --git a/src/com/android/settings/connecteddevice/usb/UsbBackend.java b/src/com/android/settings/connecteddevice/usb/UsbBackend.java index 7f3a5987d21f..a4ca40556540 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbBackend.java +++ b/src/com/android/settings/connecteddevice/usb/UsbBackend.java @@ -164,6 +164,30 @@ public boolean areAllRolesSupported() { && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST); } + public boolean isSingleDataRoleSupported() { + return mPort != null && mPortStatus != null + && ((!mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST) + && !mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST)) + || (!mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE) + && !mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE))); + } + + public boolean isSinglePowerRoleSupported() { + return mPort != null && mPortStatus != null + && ((!mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE) + && !mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST)) + || (!mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE) + && !mPortStatus + .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))); + } + public static String usbFunctionsToString(long functions) { // TODO replace with UsbManager.usbFunctionsToString once supported by Roboelectric return Long.toBinaryString(functions); diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java index 6d455a69ebdf..322cb00e3793 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java +++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java @@ -113,7 +113,8 @@ public void onRadioButtonClicked(SelectorWithWidgetPreference preference) { @Override public boolean isAvailable() { - return !Utils.isMonkeyRunning(); + return !Utils.isMonkeyRunning() + && !mUsbBackend.isSingleDataRoleSupported(); } @Override diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java index 13b3076e6f16..e8ff68411cee 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java +++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java @@ -123,7 +123,8 @@ public boolean onPreferenceClick(Preference preference) { @Override public boolean isAvailable() { - return !Utils.isMonkeyRunning(); + return !Utils.isMonkeyRunning() + && !mUsbBackend.isSinglePowerRoleSupported(); } @Override diff --git a/src/com/android/settings/custom/touch/HighTouchPollingRateSettingsPreferenceController.java b/src/com/android/settings/custom/touch/HighTouchPollingRateSettingsPreferenceController.java new file mode 100644 index 000000000000..4ca926e22458 --- /dev/null +++ b/src/com/android/settings/custom/touch/HighTouchPollingRateSettingsPreferenceController.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 PixelExperience + * + * 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.custom.touch; + +import android.content.Context; +import com.android.internal.axiom.hardware.LineageHardwareManager; +import com.android.settings.core.BasePreferenceController; + +public class HighTouchPollingRateSettingsPreferenceController extends BasePreferenceController { + + public static final String KEY = "high_touch_polling_rate_enable"; + + private final LineageHardwareManager mHardware; + + public HighTouchPollingRateSettingsPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + + mHardware = LineageHardwareManager.getInstance(context); + } + + public HighTouchPollingRateSettingsPreferenceController(Context context) { + this(context, KEY); + } + + @Override + public int getAvailabilityStatus() { + if (!mHardware.isSupported(LineageHardwareManager.FEATURE_HIGH_TOUCH_POLLING_RATE)){ + return UNSUPPORTED_ON_DEVICE; + } + return AVAILABLE; + } +} diff --git a/src/com/android/settings/custom/touch/HighTouchSensitivitySettingsPreferenceController.java b/src/com/android/settings/custom/touch/HighTouchSensitivitySettingsPreferenceController.java new file mode 100644 index 000000000000..e98bdf051d32 --- /dev/null +++ b/src/com/android/settings/custom/touch/HighTouchSensitivitySettingsPreferenceController.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 PixelExperience + * + * 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.custom.touch; + +import android.content.Context; +import com.android.internal.axiom.hardware.LineageHardwareManager; +import com.android.settings.core.BasePreferenceController; + +public class HighTouchSensitivitySettingsPreferenceController extends BasePreferenceController { + + public static final String KEY = "high_touch_sensitivity_enable"; + + private final LineageHardwareManager mHardware; + + public HighTouchSensitivitySettingsPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + + mHardware = LineageHardwareManager.getInstance(context); + } + + public HighTouchSensitivitySettingsPreferenceController(Context context) { + this(context, KEY); + } + + @Override + public int getAvailabilityStatus() { + if (!mHardware.isSupported(LineageHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)){ + return UNSUPPORTED_ON_DEVICE; + } + return AVAILABLE; + } +} diff --git a/src/com/android/settings/custom/touch/TouchHoveringSettingsPreferenceController.java b/src/com/android/settings/custom/touch/TouchHoveringSettingsPreferenceController.java new file mode 100644 index 000000000000..361d8e86c797 --- /dev/null +++ b/src/com/android/settings/custom/touch/TouchHoveringSettingsPreferenceController.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 PixelExperience + * + * 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.custom.touch; + +import android.content.Context; +import com.android.internal.axiom.hardware.LineageHardwareManager; +import com.android.settings.core.BasePreferenceController; + +public class TouchHoveringSettingsPreferenceController extends BasePreferenceController { + + public static final String KEY = "feature_touch_hovering"; + + private final LineageHardwareManager mHardware; + + public TouchHoveringSettingsPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + + mHardware = LineageHardwareManager.getInstance(context); + } + + public TouchHoveringSettingsPreferenceController(Context context) { + this(context, KEY); + } + + @Override + public int getAvailabilityStatus() { + if (!mHardware.isSupported(LineageHardwareManager.FEATURE_TOUCH_HOVERING)){ + return UNSUPPORTED_ON_DEVICE; + } + return AVAILABLE; + } +} diff --git a/src/com/android/settings/datausage/DataSaverSummary.java b/src/com/android/settings/datausage/DataSaverSummary.java index 744f692bcb09..2d84c2465660 100644 --- a/src/com/android/settings/datausage/DataSaverSummary.java +++ b/src/com/android/settings/datausage/DataSaverSummary.java @@ -93,6 +93,12 @@ public void onPause() { mDataUsageBridge.pause(); } + @Override + public void onDestroy() { + super.onDestroy(); + mDataUsageBridge.release(); + } + @Override public void onSwitchChanged(Switch switchView, boolean isChecked) { synchronized (this) { diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 3fbea5249a01..9dd90246260e 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -508,7 +508,7 @@ private static List buildPreferenceControllers(Con controllers.add(new PictureColorModePreferenceController(context, lifecycle)); controllers.add(new WebViewAppPreferenceController(context)); controllers.add(new CoolColorTemperaturePreferenceController(context)); - controllers.add(new DisableAutomaticUpdatesPreferenceController(context)); + // controllers.add(new DisableAutomaticUpdatesPreferenceController(context)); controllers.add(new SelectDSUPreferenceController(context)); controllers.add(new AdbPreferenceController(context, fragment)); controllers.add(new ClearAdbKeysPreferenceController(context, fragment)); @@ -585,7 +585,7 @@ private static List buildPreferenceControllers(Con controllers.add(new DefaultLaunchPreferenceController(context, "quick_settings_tiles")); controllers.add(new DefaultLaunchPreferenceController(context, "feature_flags_dashboard")); controllers.add(new DefaultUsbConfigurationPreferenceController(context)); - controllers.add(new DefaultLaunchPreferenceController(context, "density")); + //controllers.add(new DefaultLaunchPreferenceController(context, "density")); controllers.add(new DefaultLaunchPreferenceController(context, "background_check")); controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps")); controllers.add(new AutofillCategoryController(context, lifecycle)); diff --git a/src/com/android/settings/development/NotificationChannelWarningsPreferenceController.java b/src/com/android/settings/development/NotificationChannelWarningsPreferenceController.java index 775b70871f28..a7d51b145a85 100644 --- a/src/com/android/settings/development/NotificationChannelWarningsPreferenceController.java +++ b/src/com/android/settings/development/NotificationChannelWarningsPreferenceController.java @@ -80,6 +80,6 @@ protected void onDeveloperOptionsSwitchDisabled() { @VisibleForTesting boolean isDebuggable() { - return Build.IS_DEBUGGABLE; + return Build.TYPE.equals("eng"); } } diff --git a/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java b/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java index f0b7961bb65b..ead265a35420 100644 --- a/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java +++ b/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java @@ -40,7 +40,7 @@ public FeatureFlagsPreferenceController(Context context, String key) { @Override public int getAvailabilityStatus() { - return Build.IS_DEBUGGABLE ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + return /*Build.IS_DEBUGGABLE ? */AVAILABLE/* : UNSUPPORTED_ON_DEVICE*/; } @Override diff --git a/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java b/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java index c271bc99b97b..dd927a45670c 100644 --- a/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java +++ b/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java @@ -96,15 +96,17 @@ public OnChangeHandler(Context context) { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - boolean enabled = ((Boolean) newValue).booleanValue(); - ComponentName componentName = new ComponentName( + ComponentName cn = new ComponentName( + //boolean enabled = ((Boolean) newValue).booleanValue(); + //ComponentName componentName = new ComponentName( mContext.getPackageName(), preference.getKey()); - mPackageManager.setComponentEnabledSetting(componentName, enabled + mPackageManager.setComponentEnabledSetting(cn, (Boolean) newValue + //mPackageManager.setComponentEnabledSetting(componentName, enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); - try { + /*try { if (mStatusBarService != null) { if (enabled) { mStatusBarService.addTile(componentName); @@ -115,7 +117,7 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { } catch (RemoteException e) { Log.e(TAG, "Failed to modify QS tile for component " + componentName.toString(), e); - } + }*/ return true; } } diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java index 99c572d527ee..67e466b8589f 100644 --- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java +++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java @@ -42,6 +42,7 @@ public class PhoneNumberPreferenceController extends BasePreferenceController { private final TelephonyManager mTelephonyManager; private final SubscriptionManager mSubscriptionManager; private final List mPreferenceList = new ArrayList<>(); + private boolean mTapped = false; public PhoneNumberPreferenceController(Context context, String key) { super(context, key); @@ -51,12 +52,15 @@ public PhoneNumberPreferenceController(Context context, String key) { @Override public int getAvailabilityStatus() { - return mTelephonyManager.isVoiceCapable() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + return UNSUPPORTED_ON_DEVICE; } @Override public CharSequence getSummary() { - return getFirstPhoneNumber(); + if (mTapped) { + return getFirstPhoneNumber(); + } + return mContext.getString(R.string.device_info_protected_single_press); } @Override @@ -90,6 +94,18 @@ public void updateState(Preference preference) { @Override public boolean useDynamicSliceSummary() { + return mTapped; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + final int simSlotNumber = mPreferenceList.indexOf(preference); + if (simSlotNumber == -1) { + return false; + } + mTapped = true; + final Preference simStatusPreference = mPreferenceList.get(simSlotNumber); + simStatusPreference.setSummary(getPhoneNumber(simSlotNumber)); return true; } @@ -110,7 +126,10 @@ private CharSequence getPhoneNumber(int simSlot) { return mContext.getText(R.string.device_info_default); } - return getFormattedPhoneNumber(subscriptionInfo); + if (mTapped) { + return getFormattedPhoneNumber(subscriptionInfo); + } + return mContext.getString(R.string.device_info_protected_single_press); } private CharSequence getPreferenceTitle(int simSlot) { diff --git a/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java index dd3d560282a6..a81993b2e644 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java @@ -18,6 +18,7 @@ import android.content.Context; import android.os.SystemProperties; +import android.text.TextUtils; import androidx.annotation.VisibleForTesting; @@ -41,7 +42,13 @@ public int getAvailabilityStatus() { @Override public CharSequence getSummary() { - return SystemProperties.get(BASEBAND_PROPERTY, + String baseband = SystemProperties.get(BASEBAND_PROPERTY, mContext.getString(R.string.device_info_default)); + for (String str : baseband.split(",")) { + if (!TextUtils.isEmpty(str)) { + return str; + } + } + return baseband; } } diff --git a/src/com/android/settings/deviceinfo/firmwareversion/BuildDatePreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/BuildDatePreferenceController.java new file mode 100644 index 000000000000..a82b241f6db2 --- /dev/null +++ b/src/com/android/settings/deviceinfo/firmwareversion/BuildDatePreferenceController.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 The LineageOS 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.deviceinfo.firmwareversion; + +import android.content.Context; +import android.os.SystemProperties; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +public class BuildDatePreferenceController extends BasePreferenceController { + + private static final String TAG = "BuildDatePreferenceController"; + + private static final String KEY_BUILD_DATE_PROP = "ro.build.date"; + + public BuildDatePreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public CharSequence getSummary() { + return SystemProperties.get(KEY_BUILD_DATE_PROP, + mContext.getString(R.string.unknown)); + } +} diff --git a/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java index 0500c89371aa..9116defce164 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java @@ -20,9 +20,20 @@ import com.android.settings.core.BasePreferenceController; import com.android.settingslib.DeviceInfoUtils; +import androidx.preference.Preference; +import android.text.TextUtils; +import android.util.Log; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; public class KernelVersionPreferenceController extends BasePreferenceController { + private static final String KEY_KERNEL_VERSION = "kernel_version"; + private static final String FILENAME_PROC_VERSION = "/proc/version"; + private static final String LOG_TAG = "KernelVersionPreferenceController"; + public KernelVersionPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); } @@ -36,4 +47,45 @@ public int getAvailabilityStatus() { public CharSequence getSummary() { return DeviceInfoUtils.getFormattedKernelVersion(mContext); } + + @Override + public String getPreferenceKey() { + return KEY_KERNEL_VERSION; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), KEY_KERNEL_VERSION)) { + return false; + } + preference.setSummary(getFullKernelVersion()); + return false; + } + + private String getFullKernelVersion() { + String procVersionStr; + try { + procVersionStr = readLine(FILENAME_PROC_VERSION); + return procVersionStr; + } catch (IOException e) { + Log.e(LOG_TAG, + "IO Exception when getting kernel version for Device Info screen", e); + return "Unavailable"; + } + } + + /** + * Reads a line from the specified file. + * @param filename the file to read from + * @return the first line, if any. + * @throws IOException if the file couldn't be read + */ + private static String readLine(String filename) throws IOException { + BufferedReader reader = new BufferedReader(new FileReader(filename), 256); + try { + return reader.readLine(); + } finally { + reader.close(); + } + } } diff --git a/src/com/android/settings/deviceinfo/firmwareversion/SelinuxStatusPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/SelinuxStatusPreferenceController.java new file mode 100644 index 000000000000..38b1976aa074 --- /dev/null +++ b/src/com/android/settings/deviceinfo/firmwareversion/SelinuxStatusPreferenceController.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 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.deviceinfo.firmwareversion; + +import android.content.Context; +import android.os.SELinux; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +public class SelinuxStatusPreferenceController extends BasePreferenceController { + + private static final String TAG = "SelinuxStatusCtrl"; + + public SelinuxStatusPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public CharSequence getSummary() { + if (!SELinux.isSELinuxEnabled()) { + return (CharSequence) mContext.getString(R.string.selinux_status_disabled); + } else if (!SELinux.isSELinuxEnforced()) { + return (CharSequence) mContext.getString(R.string.selinux_status_permissive); + } else { + return (CharSequence) mContext.getString(R.string.selinux_status_enforcing); + } + } +} diff --git a/src/com/android/settings/deviceinfo/firmwareversion/axiomVersionDetailPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/axiomVersionDetailPreferenceController.java new file mode 100644 index 000000000000..b7896301fb75 --- /dev/null +++ b/src/com/android/settings/deviceinfo/firmwareversion/axiomVersionDetailPreferenceController.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2019 The LineageOS 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.deviceinfo.firmwareversion; + +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.os.UserManager; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedLockUtilsInternal; + +public class axiomVersionDetailPreferenceController extends BasePreferenceController { + + private static final String TAG = "axiomVersionDialogCtrl"; + private static final int DELAY_TIMER_MILLIS = 500; + private static final int ACTIVITY_TRIGGER_COUNT = 3; + + private static final String KEY_AXIOM_VERSION_PROP = "ro.axiom.display.version"; + + private final UserManager mUserManager; + private final long[] mHits = new long[ACTIVITY_TRIGGER_COUNT]; + + private RestrictedLockUtils.EnforcedAdmin mFunDisallowedAdmin; + private boolean mFunDisallowedBySystem; + + public axiomVersionDetailPreferenceController(Context context, String key) { + super(context, key); + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + initializeAdminPermissions(); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public CharSequence getSummary() { + String axiomVer = SystemProperties.get(KEY_AXIOM_VERSION_PROP); + if (!axiomVer.isEmpty()) + return axiomVer; + else + return mContext.getString(R.string.unknown); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { + return false; + } + if (Utils.isMonkeyRunning()) { + return false; + } + arrayCopy(); + mHits[mHits.length - 1] = SystemClock.uptimeMillis(); + if (mHits[0] >= (SystemClock.uptimeMillis() - DELAY_TIMER_MILLIS)) { + if (mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN)) { + if (mFunDisallowedAdmin != null && !mFunDisallowedBySystem) { + RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, + mFunDisallowedAdmin); + } + Log.d(TAG, "Nothing here, stop poking around!"); + return true; + } + final Intent intent = new Intent(Intent.ACTION_MAIN) + .setClassName( + "android", com.android.internal.app.PlatLogoActivity.class.getName()); + try { + mContext.startActivity(intent); + } catch (Exception e) { + Log.e(TAG, "Unable to start activity " + intent.toString()); + } + } + return true; + } + + /** + * Copies the array onto itself to remove the oldest hit. + */ + @VisibleForTesting + void arrayCopy() { + System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); + } + + @VisibleForTesting + void initializeAdminPermissions() { + mFunDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced( + mContext, UserManager.DISALLOW_FUN, UserHandle.myUserId()); + mFunDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction( + mContext, UserManager.DISALLOW_FUN, UserHandle.myUserId()); + } +} diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java index 027e8c806ca5..e02be82d3179 100644 --- a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java +++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java @@ -96,13 +96,7 @@ public void updateState(Preference preference) { @Override public CharSequence getSummary() { - return getSummary(0); - } - - private CharSequence getSummary(int simSlot) { - final int phoneType = getPhoneType(simSlot); - return phoneType == PHONE_TYPE_CDMA ? mTelephonyManager.getMeid(simSlot) - : mTelephonyManager.getImei(simSlot); + return mContext.getString(R.string.device_info_protected_single_press); } @Override @@ -129,7 +123,7 @@ public boolean useDynamicSliceSummary() { private void updatePreference(Preference preference, int simSlot) { preference.setTitle(getTitle(simSlot)); - preference.setSummary(getSummary(simSlot)); + preference.setSummary(getSummary()); } private CharSequence getTitleForGsmPhone(int simSlot) { diff --git a/src/com/android/settings/display/AutoBrightnessObserver.java b/src/com/android/settings/display/AutoBrightnessObserver.java new file mode 100644 index 000000000000..ba27b683527a --- /dev/null +++ b/src/com/android/settings/display/AutoBrightnessObserver.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 Yet Another AOSP 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 static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE; + +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.provider.Settings; + +public class AutoBrightnessObserver { + private final ContentObserver mContentObserver; + private final Context mContext; + private Runnable mCallback; + + public AutoBrightnessObserver(Context context) { + mContext = context; + mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + mCallback.run(); + } + }; + } + + public void subscribe(Runnable callback) { + mCallback = callback; + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(SCREEN_BRIGHTNESS_MODE), + false, mContentObserver); + } + + public void unsubscribe() { + mContext.getContentResolver().unregisterContentObserver(mContentObserver); + } +} diff --git a/src/com/android/settings/display/AutoBrightnessPreference.java b/src/com/android/settings/display/AutoBrightnessPreference.java new file mode 100644 index 000000000000..7a8344391b5f --- /dev/null +++ b/src/com/android/settings/display/AutoBrightnessPreference.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Yet Another AOSP 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 static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE; +import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; + +import android.content.Context; +import android.provider.Settings; +import android.util.AttributeSet; + +import com.android.settings.display.AutoBrightnessObserver; + +import com.android.settingslib.PrimarySwitchPreference; + +/** + * component for the display auto brightness + */ +public class AutoBrightnessPreference extends PrimarySwitchPreference { + + private final AutoBrightnessObserver mAutoBrightnessObserver; + + private final Runnable mCallback = () -> { + final int value = Settings.System.getInt( + getContext().getContentResolver(), + SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + setChecked(value == SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + }; + + public AutoBrightnessPreference(Context context, AttributeSet attrs) { + super(context, attrs); + mAutoBrightnessObserver = new AutoBrightnessObserver(context); + } + + @Override + public void onAttached() { + super.onAttached(); + mAutoBrightnessObserver.subscribe(mCallback); + } + + @Override + public void onDetached() { + super.onDetached(); + mAutoBrightnessObserver.unsubscribe(); + } +} diff --git a/src/com/android/settings/display/AutoBrightnessSettings.java b/src/com/android/settings/display/AutoBrightnessSettings.java index 0c594730d5c2..43ad7fa7415b 100644 --- a/src/com/android/settings/display/AutoBrightnessSettings.java +++ b/src/com/android/settings/display/AutoBrightnessSettings.java @@ -16,12 +16,18 @@ package com.android.settings.display; +import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE; +import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; + import android.app.settings.SettingsEnums; import android.os.Bundle; +import android.provider.Settings; +import com.android.settings.display.AutoBrightnessObserver; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.widget.SettingsMainSwitchPreference; import com.android.settingslib.search.SearchIndexable; @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) @@ -29,9 +35,33 @@ public class AutoBrightnessSettings extends DashboardFragment { private static final String TAG = "AutoBrightnessSettings"; + private AutoBrightnessObserver mAutoBrightnessObserver; + + private final Runnable mCallback = () -> { + final int value = Settings.System.getInt( + getContext().getContentResolver(), + SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + SettingsMainSwitchPreference pref = findPreference("auto_brightness"); + if (pref == null) return; + pref.setChecked(value == SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + }; + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); + mAutoBrightnessObserver = new AutoBrightnessObserver(getContext()); + } + + @Override + public void onStart() { + super.onStart(); + mAutoBrightnessObserver.subscribe(mCallback); + } + + @Override + public void onStop() { + super.onStop(); + mAutoBrightnessObserver.unsubscribe(); } @Override diff --git a/src/com/android/settings/display/ColorModePreferenceController.java b/src/com/android/settings/display/ColorModePreferenceController.java index 6cd4867b588f..40a776ef7d5b 100644 --- a/src/com/android/settings/display/ColorModePreferenceController.java +++ b/src/com/android/settings/display/ColorModePreferenceController.java @@ -28,8 +28,10 @@ public ColorModePreferenceController(Context context, String key) { @Override public int getAvailabilityStatus() { - return mContext.getSystemService(ColorDisplayManager.class) - .isDeviceColorManaged() + final int[] availableColorModes = mContext.getResources().getIntArray( + com.android.internal.R.array.config_availableColorModes); + return availableColorModes.length > 0 && + mContext.getSystemService(ColorDisplayManager.class).isDeviceColorManaged() && !ColorDisplayManager.areAccessibilityTransformsEnabled(mContext) ? AVAILABLE : DISABLED_FOR_USER; } diff --git a/src/com/android/settings/display/FontSizePreferenceController.java b/src/com/android/settings/display/FontSizePreferenceController.java index 28c7922ea363..05a46ce15d19 100644 --- a/src/com/android/settings/display/FontSizePreferenceController.java +++ b/src/com/android/settings/display/FontSizePreferenceController.java @@ -36,7 +36,7 @@ public CharSequence getSummary() { final float currentScale = Settings.System.getFloat(mContext.getContentResolver(), Settings.System.FONT_SCALE, 1.0f); final Resources res = mContext.getResources(); - final String[] entries = res.getStringArray(R.array.entries_font_size); + final String[] entries = res.getStringArray(R.array.entries_font_size_percent); final String[] strEntryValues = res.getStringArray(R.array.entryvalues_font_size); final int index = ToggleFontSizePreferenceFragment.fontSizeValueToIndex(currentScale, strEntryValues); diff --git a/src/com/android/settings/display/MinRefreshRatePreferenceController.java b/src/com/android/settings/display/MinRefreshRatePreferenceController.java new file mode 100644 index 000000000000..caaf11b06e3b --- /dev/null +++ b/src/com/android/settings/display/MinRefreshRatePreferenceController.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 The LineageOS 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 static android.provider.Settings.System.MIN_REFRESH_RATE; + +import android.content.Context; +import android.provider.Settings; +import android.view.Display; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class MinRefreshRatePreferenceController extends BasePreferenceController + implements Preference.OnPreferenceChangeListener { + + private static final String KEY_MIN_REFRESH_RATE = "min_refresh_rate"; + + private ListPreference mListPreference; + + private List mEntries = new ArrayList<>(); + private List mValues = new ArrayList<>(); + + public MinRefreshRatePreferenceController(Context context) { + super(context, KEY_MIN_REFRESH_RATE); + + if (mContext.getResources().getBoolean(R.bool.config_show_min_refresh_rate_switch)) { + Display.Mode mode = mContext.getDisplay().getMode(); + Display.Mode[] modes = mContext.getDisplay().getSupportedModes(); + for (Display.Mode m : modes) { + if (m.getPhysicalWidth() == mode.getPhysicalWidth() && + m.getPhysicalHeight() == mode.getPhysicalHeight()) { + mEntries.add(String.format("%.02fHz", m.getRefreshRate()) + .replaceAll("[\\.,]00", "")); + mValues.add(String.format(Locale.US, "%.02f", m.getRefreshRate())); + } + } + } + } + + @Override + public int getAvailabilityStatus() { + return mEntries.size() > 1 ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public String getPreferenceKey() { + return KEY_MIN_REFRESH_RATE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + mListPreference = screen.findPreference(getPreferenceKey()); + mListPreference.setEntries(mEntries.toArray(new String[mEntries.size()])); + mListPreference.setEntryValues(mValues.toArray(new String[mValues.size()])); + + super.displayPreference(screen); + } + + @Override + public void updateState(Preference preference) { + final float currentValue = Settings.System.getFloat(mContext.getContentResolver(), + MIN_REFRESH_RATE, 60.00f); + int index = mListPreference.findIndexOfValue( + String.format(Locale.US, "%.02f", currentValue)); + if (index < 0) index = 0; + mListPreference.setValueIndex(index); + mListPreference.setSummary(mListPreference.getEntries()[index]); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Settings.System.putFloat(mContext.getContentResolver(), MIN_REFRESH_RATE, + Float.valueOf((String) newValue)); + updateState(preference); + return true; + } + +} diff --git a/src/com/android/settings/display/PeakRefreshRateListPreferenceController.java b/src/com/android/settings/display/PeakRefreshRateListPreferenceController.java new file mode 100644 index 000000000000..e4f4a076716c --- /dev/null +++ b/src/com/android/settings/display/PeakRefreshRateListPreferenceController.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2021 The LineageOS 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.hardware.display.DisplayManager; +import android.os.Handler; +import android.provider.DeviceConfig; +import android.provider.Settings; +import android.util.Log; +import android.view.Display; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +import java.util.ArrayList; +import java.util.concurrent.Executor; +import java.util.List; +import java.util.Locale; + +public class PeakRefreshRateListPreferenceController extends BasePreferenceController + implements LifecycleObserver, OnStart, OnStop, Preference.OnPreferenceChangeListener { + + private static float DEFAULT_REFRESH_RATE = 60f; + + private static final String TAG = "PeakRefreshRatePrefCtr"; + private static final float INVALIDATE_REFRESH_RATE = -1f; + + private final Handler mHandler; + private final IDeviceConfigChange mOnDeviceConfigChange; + private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; + private ListPreference mListPreference; + + private List mEntries = new ArrayList<>(); + private List mValues = new ArrayList<>(); + + private interface IDeviceConfigChange { + void onDefaultRefreshRateChanged(); + } + + public PeakRefreshRateListPreferenceController(Context context, String key) { + super(context, key); + mHandler = new Handler(context.getMainLooper()); + mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings(); + mOnDeviceConfigChange = + new IDeviceConfigChange() { + public void onDefaultRefreshRateChanged() { + updateState(mListPreference); + } + }; + + final DisplayManager dm = mContext.getSystemService(DisplayManager.class); + final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY); + + if (display == null) { + Log.w(TAG, "No valid default display device"); + } else { + Display.Mode mode = display.getMode(); + Display.Mode[] modes = display.getSupportedModes(); + for (Display.Mode m : modes) { + if (m.getPhysicalWidth() == mode.getPhysicalWidth() && + m.getPhysicalHeight() == mode.getPhysicalHeight()) { + mEntries.add(String.format("%.02fHz", m.getRefreshRate()) + .replaceAll("[\\.,]00", "")); + mValues.add(String.format(Locale.US, "%.02f", m.getRefreshRate())); + } + } + } + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + mListPreference = screen.findPreference(getPreferenceKey()); + mListPreference.setEntries(mEntries.toArray(new String[mEntries.size()])); + mListPreference.setEntryValues(mValues.toArray(new String[mValues.size()])); + } + + @Override + public int getAvailabilityStatus() { + if (mContext.getResources().getBoolean(R.bool.config_show_peak_refresh_rate_switch)) { + return AVAILABLE; + } else { + return UNSUPPORTED_ON_DEVICE; + } + } + + @Override + public void updateState(Preference preference) { + final float currentValue = Settings.System.getFloat(mContext.getContentResolver(), + Settings.System.PEAK_REFRESH_RATE, getDefaultPeakRefreshRate()); + int index = mListPreference.findIndexOfValue( + String.format(Locale.US, "%.02f", currentValue)); + if (index < 0) index = 0; + mListPreference.setValueIndex(index); + mListPreference.setSummary(mListPreference.getEntries()[index]); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, + Float.valueOf((String) newValue)); + updateState(preference); + return true; + } + + @Override + public void onStart() { + mDeviceConfigDisplaySettings.startListening(); + } + + @Override + public void onStop() { + mDeviceConfigDisplaySettings.stopListening(); + } + + private float findPeakRefreshRate(Display.Mode[] modes) { + float peakRefreshRate = DEFAULT_REFRESH_RATE; + for (Display.Mode mode : modes) { + if (Math.round(mode.getRefreshRate()) > DEFAULT_REFRESH_RATE) { + peakRefreshRate = mode.getRefreshRate(); + } + } + return peakRefreshRate; + } + + private class DeviceConfigDisplaySettings + implements DeviceConfig.OnPropertiesChangedListener, Executor { + public void startListening() { + DeviceConfig.addOnPropertiesChangedListener( + DeviceConfig.NAMESPACE_DISPLAY_MANAGER, + this /* Executor */, + this /* Listener */); + } + + public void stopListening() { + DeviceConfig.removeOnPropertiesChangedListener(this); + } + + public float getDefaultPeakRefreshRate() { + float defaultPeakRefreshRate = + DeviceConfig.getFloat( + DeviceConfig.NAMESPACE_DISPLAY_MANAGER, + DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, + INVALIDATE_REFRESH_RATE); + Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : " + defaultPeakRefreshRate); + + return defaultPeakRefreshRate; + } + + @Override + public void onPropertiesChanged(DeviceConfig.Properties properties) { + // Got notified if any property has been changed in NAMESPACE_DISPLAY_MANAGER. The + // KEY_PEAK_REFRESH_RATE_DEFAULT value could be added, changed, removed or unchanged. + // Just force a UI update for any case. + if (mOnDeviceConfigChange != null) { + mOnDeviceConfigChange.onDefaultRefreshRateChanged(); + updateState(mListPreference); + } + } + + @Override + public void execute(Runnable runnable) { + if (mHandler != null) { + mHandler.post(runnable); + } + } + } + + private float getDefaultPeakRefreshRate() { + float defaultPeakRefreshRate = mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate(); + if (defaultPeakRefreshRate == INVALIDATE_REFRESH_RATE) { + defaultPeakRefreshRate = (float) mContext.getResources().getInteger( + com.android.internal.R.integer.config_defaultPeakRefreshRate); + } + + return defaultPeakRefreshRate; + } +} diff --git a/src/com/android/settings/display/PeakRefreshRatePreferenceController.java b/src/com/android/settings/display/PeakRefreshRatePreferenceController.java index 27ba340c6bae..7bc34ef55982 100644 --- a/src/com/android/settings/display/PeakRefreshRatePreferenceController.java +++ b/src/com/android/settings/display/PeakRefreshRatePreferenceController.java @@ -89,6 +89,10 @@ public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); + + final String summary = mContext.getString(R.string.peak_refresh_rate_summary_custom, + (int)mPeakRefreshRate); + mPreference.setSummary(summary); } @Override diff --git a/src/com/android/settings/display/ScreenSaverPreferenceController.java b/src/com/android/settings/display/ScreenSaverPreferenceController.java deleted file mode 100644 index c1b0b4e9eb61..000000000000 --- a/src/com/android/settings/display/ScreenSaverPreferenceController.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 androidx.preference.Preference; - -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settings.dream.DreamSettings; -import com.android.settingslib.core.AbstractPreferenceController; - -public class ScreenSaverPreferenceController extends AbstractPreferenceController implements - PreferenceControllerMixin { - - private static final String KEY_SCREEN_SAVER = "screensaver"; - - public ScreenSaverPreferenceController(Context context) { - super(context); - } - - @Override - public boolean isAvailable() { - return mContext.getResources().getBoolean( - com.android.internal.R.bool.config_dreamsSupported); - } - - @Override - public String getPreferenceKey() { - return KEY_SCREEN_SAVER; - } - - @Override - public void updateState(Preference preference) { - preference.setSummary(DreamSettings.getSummaryTextWithDreamName(mContext)); - } -} diff --git a/src/com/android/settings/display/ToggleFontSizePreferenceFragment.java b/src/com/android/settings/display/ToggleFontSizePreferenceFragment.java index db4d899cbb42..3c721b410931 100644 --- a/src/com/android/settings/display/ToggleFontSizePreferenceFragment.java +++ b/src/com/android/settings/display/ToggleFontSizePreferenceFragment.java @@ -54,7 +54,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { final Resources res = getContext().getResources(); final ContentResolver resolver = getContext().getContentResolver(); // Mark the appropriate item in the preferences list. - mEntries = res.getStringArray(R.array.entries_font_size); + mEntries = res.getStringArray(R.array.entries_font_size_percent); final String[] strEntryValues = res.getStringArray(R.array.entryvalues_font_size); final float currentScale = Settings.System.getFloat(resolver, Settings.System.FONT_SCALE, 1.0f); diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java index b1e4c34e6eaf..48ce142eb16b 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfo.java +++ b/src/com/android/settings/fuelgauge/BatteryInfo.java @@ -51,6 +51,7 @@ public class BatteryInfo { public int batteryStatus; public boolean discharging = true; public boolean isOverheated; + static float batteryTemp; public long remainingTimeUs = 0; public long averageTimeToDischarge = EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN; public String batteryPercentString; @@ -258,6 +259,7 @@ public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcas info.isOverheated = batteryBroadcast.getIntExtra( BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN) == BatteryManager.BATTERY_HEALTH_OVERHEAT; + info.batteryTemp = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); info.statusLabel = Utils.getBatteryStatus(context, batteryBroadcast, isCompactStatus); info.batteryStatus = batteryBroadcast.getIntExtra( diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 19a801110c06..896acd66c483 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -59,11 +59,15 @@ public class PowerUsageSummary extends PowerUsageBase implements @VisibleForTesting static final String KEY_BATTERY_USAGE = "battery_usage_summary"; + private static final String KEY_BATTERY_TEMP = "battery_temperature"; + @VisibleForTesting static final int BATTERY_INFO_LOADER = 1; @VisibleForTesting static final int BATTERY_TIP_LOADER = 2; + @VisibleForTesting + PowerGaugePreference mBatteryTempPref; @VisibleForTesting PowerUsageFeatureProvider mPowerFeatureProvider; @VisibleForTesting @@ -161,6 +165,7 @@ public void onCreate(Bundle icicle) { initFeatureProvider(); initPreference(); + mBatteryTempPref = (PowerGaugePreference) findPreference(KEY_BATTERY_TEMP); mBatteryUtils = BatteryUtils.getInstance(getContext()); if (Utils.isBatteryPresent(getContext())) { @@ -232,6 +237,8 @@ protected void refreshUi(@BatteryUpdateType int refreshType) { } // reload BatteryInfo and updateUI restartBatteryInfoLoader(); + + mBatteryTempPref.setSummary(BatteryInfo.batteryTemp / 10 + " °C"); } @VisibleForTesting diff --git a/src/com/android/settings/gestures/BackGestureIndicatorView.java b/src/com/android/settings/gestures/BackGestureIndicatorView.java index c60afd003d39..3bf40ec7c960 100644 --- a/src/com/android/settings/gestures/BackGestureIndicatorView.java +++ b/src/com/android/settings/gestures/BackGestureIndicatorView.java @@ -19,6 +19,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.PixelFormat; +import android.graphics.Point; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -37,6 +38,7 @@ public class BackGestureIndicatorView extends LinearLayout { private ImageView mRightIndicator; private BackGestureIndicatorDrawable mLeftDrawable; private BackGestureIndicatorDrawable mRightDrawable; + private int mHeightScale; public BackGestureIndicatorView(Context context) { super(context); @@ -87,6 +89,10 @@ public void setIndicatorWidth(int width, boolean leftIndicator) { indicator.setWidth(width); } + public void setIndicatorHeightScale(int heightScale) { + mHeightScale = heightScale; + } + public WindowManager.LayoutParams getLayoutParams( WindowManager.LayoutParams parentWindowAttributes) { int copiedFlags = (parentWindowAttributes.flags @@ -99,8 +105,33 @@ public WindowManager.LayoutParams getLayoutParams( | copiedFlags, PixelFormat.TRANSLUCENT); + setCurrentGestureHeight(lp); lp.setTitle("BackGestureIndicatorView"); lp.token = getContext().getActivityToken(); return lp; } + + private void setCurrentGestureHeight(WindowManager.LayoutParams lp) { + Point displaySize = new Point(); + getContext().getDisplay().getRealSize(displaySize); + + // mHeightScale cant be range 0 - 3 + // 0 means full height + // 1 measns half of the screen + // 2 means lower third of the screen + // 3 means lower sicth of the screen + if (mHeightScale == 0) { + lp.height = displaySize.y; + lp.y = 0; + } else if (mHeightScale == 1) { + lp.height = displaySize.y / 2; + lp.y = displaySize.y - lp.height; + } else if (mHeightScale == 2) { + lp.height = displaySize.y / 3; + lp.y = displaySize.y - lp.height; + } else { + lp.height = displaySize.y / 6; + lp.y = displaySize.y - lp.height; + } + } } diff --git a/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java index 546581bd1287..c4669833697d 100644 --- a/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java +++ b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java @@ -44,12 +44,17 @@ public class GestureNavigationSettingsFragment extends DashboardFragment { private static final String LEFT_EDGE_SEEKBAR_KEY = "gesture_left_back_sensitivity"; private static final String RIGHT_EDGE_SEEKBAR_KEY = "gesture_right_back_sensitivity"; + private static final String KEY_BACK_HEIGHT = "gesture_back_height"; + private static final String GESTURE_NAVBAR_LENGTH_KEY = "gesture_navbar_length_preference"; private WindowManager mWindowManager; private BackGestureIndicatorView mIndicatorView; private float[] mBackGestureInsetScales; private float mDefaultBackGestureInset; + private float[] mBackGestureHeightScales = { 0f, 1f, 2f, 3f }; + private int mCurrentRightWidth; + private int mCurrentLefttWidth; public GestureNavigationSettingsFragment() { super(); @@ -75,6 +80,10 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { initSeekBarPreference(LEFT_EDGE_SEEKBAR_KEY); initSeekBarPreference(RIGHT_EDGE_SEEKBAR_KEY); + + initSeekBarPreference(KEY_BACK_HEIGHT); + +// initGestureNavbarLengthPreference(); } @Override @@ -118,17 +127,49 @@ private void initSeekBarPreference(final String key) { pref.setContinuousUpdates(true); pref.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_TICKS); - final String settingsKey = key == LEFT_EDGE_SEEKBAR_KEY - ? Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT - : Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT; - final float initScale = Settings.Secure.getFloat( - getContext().getContentResolver(), settingsKey, 1.0f); + String settingsKey; + + switch(key) { + case LEFT_EDGE_SEEKBAR_KEY: + settingsKey = Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT; + break; + case RIGHT_EDGE_SEEKBAR_KEY: + settingsKey = Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT; + break; + case KEY_BACK_HEIGHT: + settingsKey = Settings.System.BACK_GESTURE_HEIGHT; + break; + default: + settingsKey = ""; + break; + } + + float[] scales = mBackGestureInsetScales; + float initScale = 0; + if (settingsKey != "") { + initScale = Settings.Secure.getFloat( + getContext().getContentResolver(), settingsKey, 1.0f); + } + + // needed if we just change the height + float currentWidthScale = Settings.Secure.getFloat( + getContext().getContentResolver(), Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f); + mCurrentRightWidth = (int) (mDefaultBackGestureInset * currentWidthScale); + currentWidthScale = Settings.Secure.getFloat( + getContext().getContentResolver(), Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f); + mCurrentLefttWidth = (int) (mDefaultBackGestureInset * currentWidthScale); + + if (key == KEY_BACK_HEIGHT) { + scales = mBackGestureHeightScales; + initScale = Settings.System.getInt( + getContext().getContentResolver(), settingsKey, 0); + } // Find the closest value to initScale float minDistance = Float.MAX_VALUE; int minDistanceIndex = -1; - for (int i = 0; i < mBackGestureInsetScales.length; i++) { - float d = Math.abs(mBackGestureInsetScales[i] - initScale); + for (int i = 0; i < scales.length; i++) { + float d = Math.abs(scales[i] - initScale); if (d < minDistance) { minDistance = d; minDistanceIndex = i; @@ -137,15 +178,37 @@ private void initSeekBarPreference(final String key) { pref.setProgress(minDistanceIndex); pref.setOnPreferenceChangeListener((p, v) -> { - final int width = (int) (mDefaultBackGestureInset * mBackGestureInsetScales[(int) v]); - mIndicatorView.setIndicatorWidth(width, key == LEFT_EDGE_SEEKBAR_KEY); + if (key != KEY_BACK_HEIGHT) { + final int width = (int) (mDefaultBackGestureInset * mBackGestureInsetScales[(int) v]); + mIndicatorView.setIndicatorWidth(width, key == LEFT_EDGE_SEEKBAR_KEY); + if (key == LEFT_EDGE_SEEKBAR_KEY) { + mCurrentLefttWidth = width; + } else { + mCurrentRightWidth = width; + } + } else { + final int heightScale = (int) (mBackGestureHeightScales[(int) v]); + mIndicatorView.setIndicatorHeightScale(heightScale); + // dont use updateViewLayout else it will animate + mWindowManager.removeView(mIndicatorView); + mWindowManager.addView(mIndicatorView, mIndicatorView.getLayoutParams( + getActivity().getWindow().getAttributes())); + // peek the indicators + mIndicatorView.setIndicatorWidth(mCurrentRightWidth, false); + mIndicatorView.setIndicatorWidth(mCurrentLefttWidth, true); + } return true; }); pref.setOnPreferenceChangeStopListener((p, v) -> { - mIndicatorView.setIndicatorWidth(0, key == LEFT_EDGE_SEEKBAR_KEY); - final float scale = mBackGestureInsetScales[(int) v]; - Settings.Secure.putFloat(getContext().getContentResolver(), settingsKey, scale); + if (key == KEY_BACK_HEIGHT) { + mIndicatorView.setIndicatorWidth(0, false); + mIndicatorView.setIndicatorWidth(0, true); + Settings.System.putInt(getContext().getContentResolver(), settingsKey, (int) mBackGestureHeightScales[(int) v]); + } else { + mIndicatorView.setIndicatorWidth(0, key == LEFT_EDGE_SEEKBAR_KEY); + Settings.Secure.putFloat(getContext().getContentResolver(), settingsKey, mBackGestureInsetScales[(int) v]); + } return true; }); } @@ -168,5 +231,4 @@ protected boolean isPageSearchEnabled(Context context) { return SystemNavigationPreferenceController.isGestureAvailable(context); } }; - } diff --git a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java index ff069ab35819..7fe9e190d290 100644 --- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java +++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java @@ -77,6 +77,7 @@ private static List buildAllPreferenceControllers( controllers.add(new DoubleTapScreenPreferenceController(context, FAKE_PREF_KEY) .setConfig(ambientDisplayConfiguration)); controllers.add(new PreventRingingParentPreferenceController(context, FAKE_PREF_KEY)); + controllers.add(new SwipeToScreenshotPreferenceController(context, FAKE_PREF_KEY)); return controllers; } } diff --git a/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java b/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java index 32a7ba55158e..25e75c09c76b 100644 --- a/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java +++ b/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java @@ -17,8 +17,28 @@ package com.android.settings.gestures; import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.om.IOverlayManager; +import android.content.om.OverlayInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; import android.provider.Settings; import android.text.TextUtils; +import android.os.AsyncTask; +import android.os.BatteryManager; +import android.os.Handler; +import android.os.Looper; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.os.SystemClock; +import android.os.UserHandle; +import android.os.Vibrator; import com.android.internal.annotations.VisibleForTesting; @@ -40,8 +60,12 @@ public GlobalActionsPanelPreferenceController(Context context, String key) { @Override public int getAvailabilityStatus() { - int enabled = Settings.Secure.getInt(mContext.getContentResolver(), AVAILABLE_SETTING, 0); - return enabled == 1 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; + return hasNFC(mContext) == true ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; + } + + // Check to see if device supports NFC + public static boolean hasNFC(Context context) { + return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC); } @Override diff --git a/src/com/android/settings/gestures/SwipeToScreenshotGestureSettings.java b/src/com/android/settings/gestures/SwipeToScreenshotGestureSettings.java new file mode 100644 index 000000000000..ae0f4e3ae928 --- /dev/null +++ b/src/com/android/settings/gestures/SwipeToScreenshotGestureSettings.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 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.SharedPreferences; +import android.provider.SearchIndexableResource; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.search.SearchIndexable; + +import java.util.Arrays; +import java.util.List; + +@SearchIndexable +public class SwipeToScreenshotGestureSettings extends DashboardFragment { + + private static final String TAG = "SwipeToScreenshotGestureSettings"; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + } + + @Override + public int getMetricsCategory() { + return -1; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.swipe_to_screenshot_gesture_settings; + } + + public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.swipe_to_screenshot_gesture_settings; + return Arrays.asList(sir); + } + }; +} diff --git a/src/com/android/settings/gestures/SwipeToScreenshotPreferenceController.java b/src/com/android/settings/gestures/SwipeToScreenshotPreferenceController.java new file mode 100644 index 000000000000..300948a51682 --- /dev/null +++ b/src/com/android/settings/gestures/SwipeToScreenshotPreferenceController.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 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 static android.provider.Settings.System.SWIPE_TO_SCREENSHOT; + +import android.content.Context; +import android.content.SharedPreferences; +import android.provider.Settings; +import android.text.TextUtils; + +public class SwipeToScreenshotPreferenceController extends GesturePreferenceController { + + private final int ON = 1; + private final int OFF = 0; + + private static final String PREF_KEY_VIDEO = "swipe_to_screenshot_video"; + + public SwipeToScreenshotPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public boolean isSliceable() { + return TextUtils.equals(getPreferenceKey(), "swipe_to_screenshot"); + } + + @Override + protected String getVideoPrefKey() { + return PREF_KEY_VIDEO; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.System.putInt(mContext.getContentResolver(), SWIPE_TO_SCREENSHOT, + isChecked ? ON : OFF); + } + + @Override + public boolean isChecked() { + return Settings.System.getInt(mContext.getContentResolver(), SWIPE_TO_SCREENSHOT, 0) != 0; + } +} diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java index 08b043e22603..2e27ac9f9cfa 100644 --- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java +++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java @@ -113,8 +113,6 @@ public void onAttach(Context context) { mVideoPreference = new IllustrationPreference(context); setIllustrationVideo(mVideoPreference, getDefaultKey()); - - migrateOverlaySensitivityToSettings(context, mOverlayManager); } @Override @@ -216,27 +214,6 @@ protected boolean setDefaultKey(String key) { return true; } - static void migrateOverlaySensitivityToSettings(Context context, - IOverlayManager overlayManager) { - if (!SystemNavigationPreferenceController.isGestureNavigationEnabled(context)) { - return; - } - - OverlayInfo info = null; - try { - info = overlayManager.getOverlayInfo(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT); - } catch (RemoteException e) { /* Do nothing */ } - if (info != null && !info.isEnabled()) { - // Enable the default gesture nav overlay. Back sensitivity for left and right are - // stored as separate settings values, and other gesture nav overlays are deprecated. - setCurrentSystemNavigationMode(overlayManager, KEY_SYSTEM_NAV_GESTURAL); - Settings.Secure.putFloat(context.getContentResolver(), - Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f); - Settings.Secure.putFloat(context.getContentResolver(), - Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f); - } - } - @VisibleForTesting static String getCurrentSystemNavigationMode(Context context) { if (SystemNavigationPreferenceController.isGestureNavigationEnabled(context)) { @@ -248,12 +225,11 @@ static String getCurrentSystemNavigationMode(Context context) { } } - @VisibleForTesting - static void setCurrentSystemNavigationMode(IOverlayManager overlayManager, String key) { - String overlayPackage = NAV_BAR_MODE_GESTURAL_OVERLAY; + void setCurrentSystemNavigationMode(IOverlayManager overlayManager, String key) { + String overlayPackage = getNavBarGesturalOverlay(); switch (key) { case KEY_SYSTEM_NAV_GESTURAL: - overlayPackage = NAV_BAR_MODE_GESTURAL_OVERLAY; + overlayPackage = getNavBarGesturalOverlay(); break; case KEY_SYSTEM_NAV_2BUTTONS: overlayPackage = NAV_BAR_MODE_2BUTTON_OVERLAY; @@ -270,6 +246,20 @@ static void setCurrentSystemNavigationMode(IOverlayManager overlayManager, Strin } } + private String getNavBarGesturalOverlay() { + int state = Settings.System.getInt(getContext().getContentResolver(), + Settings.System.NAVIGATION_BAR_IME_SPACE, 0); + String overlay = NAV_BAR_MODE_GESTURAL_OVERLAY; + switch (state) { + case 1: // narrow + overlay += "_narrow_back"; + break; + case 2: // hidden + overlay += "_wide_back"; + } + return overlay; + } + private static void setIllustrationVideo(IllustrationPreference videoPref, String systemNavKey) { switch (systemNavKey) { diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java index 71b48f9b89f1..6549983dac82 100644 --- a/src/com/android/settings/language/LanguageAndInputSettings.java +++ b/src/com/android/settings/language/LanguageAndInputSettings.java @@ -39,6 +39,8 @@ import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; +import com.android.internal.axiom.hardware.LineageHardwareManager; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -52,6 +54,7 @@ public class LanguageAndInputSettings extends DashboardFragment { private static final String KEY_SPEECH_CATEGORY = "speech_category"; private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary"; private static final String KEY_POINTER_CATEGORY = "pointer_category"; + private static final String KEY_TOUCH_HOVERING = "feature_touch_hovering"; @Override public int getMetricsCategory() { @@ -149,5 +152,15 @@ public List createPreferenceControllers( Context context) { return buildPreferenceControllers(context, null); } + + @Override + public List getNonIndexableKeys(Context context) { + List keys = super.getNonIndexableKeys(context); + LineageHardwareManager hardware = LineageHardwareManager.getInstance(context); + if (!hardware.isSupported(LineageHardwareManager.FEATURE_TOUCH_HOVERING)) { + keys.add(KEY_TOUCH_HOVERING); + } + return keys; + } }; } diff --git a/src/com/android/settings/location/LocationIndicatorsPreferenceController.java b/src/com/android/settings/location/LocationIndicatorsPreferenceController.java index 75ffb3a92861..1b1af8f8f739 100644 --- a/src/com/android/settings/location/LocationIndicatorsPreferenceController.java +++ b/src/com/android/settings/location/LocationIndicatorsPreferenceController.java @@ -34,7 +34,7 @@ public LocationIndicatorsPreferenceController(Context context, String preference @Override public boolean isChecked() { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - Utils.PROPERTY_LOCATION_INDICATORS_ENABLED, false); + Utils.PROPERTY_LOCATION_INDICATORS_ENABLED, true); } @Override diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java index 61682d00a8cc..6b28d921efaa 100644 --- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java +++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java @@ -48,7 +48,7 @@ public class RecentLocationAccessPreferenceController extends LocationBasePrefer RecentAppOpsAccess mRecentLocationApps; private PreferenceCategory mCategoryRecentLocationRequests; private int mType = ProfileSelectFragment.ProfileType.ALL; - private boolean mShowSystem = false; + private boolean mShowSystem = true; private boolean mSystemSettingChanged = false; private static class PackageEntryClickedListener implements @@ -85,9 +85,9 @@ public RecentLocationAccessPreferenceController(Context context, String key, super(context, key); mRecentLocationApps = recentLocationApps; mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; } diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java index ecbcb30eacec..1566712e405d 100644 --- a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java +++ b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java @@ -40,7 +40,7 @@ public class RecentLocationAccessSeeAllFragment extends DashboardFragment { private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 1; private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 2; - private boolean mShowSystem = false; + private boolean mShowSystem = true; private MenuItem mShowSystemMenu; private MenuItem mHideSystemMenu; private RecentLocationAccessSeeAllPreferenceController mController; @@ -61,9 +61,9 @@ public void onAttach(Context context) { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; } diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java index d6586673f89e..abda482a1e5c 100644 --- a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java +++ b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java @@ -51,9 +51,9 @@ public class RecentLocationAccessSeeAllPreferenceController public RecentLocationAccessSeeAllPreferenceController(Context context, String key) { super(context, key); mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; mRecentLocationAccesses = RecentAppOpsAccess.createForLocation(context); diff --git a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java index 39211ee52024..bee904efdc47 100644 --- a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java +++ b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java @@ -87,9 +87,9 @@ public void displayPreference(PreferenceScreen screen) { final List recentLocationRequests = new ArrayList<>(); final UserManager userManager = UserManager.get(mContext); final boolean showSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; for (RecentLocationApps.Request request : mRecentLocationApps.getAppListSorted( diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java index 1a85a7fa3416..22ea99a4ee00 100644 --- a/src/com/android/settings/network/MobileNetworkSummaryController.java +++ b/src/com/android/settings/network/MobileNetworkSummaryController.java @@ -149,7 +149,7 @@ private void initPreference() { mPreference.setOnPreferenceClickListener(null); mPreference.setOnAddClickListener(null); mPreference.setFragment(null); - mPreference.setEnabled(!mChangeListener.isAirplaneModeOn()); + mPreference.setEnabled(true); } private void update() { @@ -176,7 +176,7 @@ private void update() { // We have one or more existing subscriptions, so we want the plus button if eSIM is // supported. if (mStatusCache.isEuiccConfigSupport()) { - mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn()); + mPreference.setAddWidgetEnabled(true); mPreference.setOnAddClickListener(p -> { logPreferenceClick(p); startAddSimFlow(); @@ -216,7 +216,6 @@ public String getPreferenceKey() { @Override public void onAirplaneModeChanged(boolean airplaneModeEnabled) { - mStatusCache.update(mContext, statusCache -> update()); } @Override diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java index ec17dd371b16..962249b40313 100644 --- a/src/com/android/settings/network/NetworkProviderSettings.java +++ b/src/com/android/settings/network/NetworkProviderSettings.java @@ -269,6 +269,7 @@ public void onViewCreated(View view, Bundle savedInstanceState) { if (activity == null) { return; } + mWifiManager = activity.getSystemService(WifiManager.class); setPinnedHeaderView(R.layout.progress_header); setProgressBarVisible(false); diff --git a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java index 5c7c54eda379..23e76699503b 100644 --- a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java +++ b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java @@ -72,9 +72,16 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat // DNS_MODE -> RadioButton id private static final Map PRIVATE_DNS_MAP; + // Must match ConnectivitySettingsUtils + private static final int PRIVATE_DNS_MODE_CLOUDFLARE = 4; + private static final int PRIVATE_DNS_MODE_AXIOM = 5; + + static { PRIVATE_DNS_MAP = new HashMap<>(); PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_OFF, R.id.private_dns_mode_off); + PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_CLOUDFLARE, R.id.private_dns_mode_cloudflare); + PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_AXIOM, R.id.private_dns_mode_axiom); PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_OPPORTUNISTIC, R.id.private_dns_mode_opportunistic); PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, R.id.private_dns_mode_provider); } @@ -156,6 +163,12 @@ protected void onBindDialogView(View view) { // Initial radio button text final RadioButton offRadioButton = view.findViewById(R.id.private_dns_mode_off); offRadioButton.setText(R.string.private_dns_mode_off); + final RadioButton cloudflareRadioButton = + view.findViewById(R.id.private_dns_mode_cloudflare); + cloudflareRadioButton.setText(R.string.private_dns_mode_cloudflare); + final RadioButton axiomRadioButton = + view.findViewById(R.id.private_dns_mode_axiom); + axiomRadioButton.setText(R.string.private_dns_mode_axiom); final RadioButton opportunisticRadioButton = view.findViewById(R.id.private_dns_mode_opportunistic); opportunisticRadioButton.setText(R.string.private_dns_mode_opportunistic); @@ -197,6 +210,10 @@ public void onClick(DialogInterface dialog, int which) { public void onCheckedChanged(RadioGroup group, int checkedId) { if (checkedId == R.id.private_dns_mode_off) { mMode = PRIVATE_DNS_MODE_OFF; + } else if (checkedId == R.id.private_dns_mode_cloudflare) { + mMode = PRIVATE_DNS_MODE_CLOUDFLARE; + } else if (checkedId == R.id.private_dns_mode_axiom) { + mMode = PRIVATE_DNS_MODE_AXIOM; } else if (checkedId == R.id.private_dns_mode_opportunistic) { mMode = PRIVATE_DNS_MODE_OPPORTUNISTIC; } else if (checkedId == R.id.private_dns_mode_provider) { diff --git a/src/com/android/settings/network/PrivateDnsPreferenceController.java b/src/com/android/settings/network/PrivateDnsPreferenceController.java index ed6f9ed955d0..b26ff451009d 100644 --- a/src/com/android/settings/network/PrivateDnsPreferenceController.java +++ b/src/com/android/settings/network/PrivateDnsPreferenceController.java @@ -65,6 +65,11 @@ public class PrivateDnsPreferenceController extends BasePreferenceController Settings.Global.getUriFor(PRIVATE_DNS_SPECIFIER), }; + // Must match ConnectivitySettingsUtils + private static final int PRIVATE_DNS_MODE_CLOUDFLARE = 4; + private static final int PRIVATE_DNS_MODE_AXIOM = 5; + + private final Handler mHandler; private final ContentObserver mSettingsObserver; private final ConnectivityManager mConnectivityManager; @@ -129,6 +134,14 @@ public CharSequence getSummary() { switch (mode) { case PRIVATE_DNS_MODE_OFF: return res.getString(R.string.private_dns_mode_off); + case PRIVATE_DNS_MODE_CLOUDFLARE: + return dnsesResolved + ? res.getString(R.string.private_dns_mode_cloudflare) + : res.getString(R.string.private_dns_mode_provider_failure); + case PRIVATE_DNS_MODE_AXIOM: + return dnsesResolved + ? res.getString(R.string.private_dns_mode_axiom) + : res.getString(R.string.private_dns_mode_provider_failure); case PRIVATE_DNS_MODE_OPPORTUNISTIC: return dnsesResolved ? res.getString(R.string.private_dns_mode_on) : res.getString(R.string.private_dns_mode_opportunistic); diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index 43b3cc0e4c4c..1be4e6f4954f 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -90,7 +90,7 @@ public int getAvailabilityStatus(int subId) { CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL) || carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL)) { - visible = false; + visible = true; } else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { visible = false; } else if (!isCallStateIdle()) { @@ -237,6 +237,7 @@ public void updateConfig() { } void setPreferenceEntries() { + boolean lteOnlyUnsupported = false; mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId); final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(mSubId); final boolean display2gOptions = carrierConfig @@ -254,6 +255,7 @@ void setPreferenceEntries() { .addFormat(UiOptions.PresentFormat.addGlobalEntry); break; case ENABLED_NETWORKS_CDMA_NO_LTE_CHOICES: + lteOnlyUnsupported = true; uiOptions = uiOptions .setChoices(R.array.enabled_networks_cdma_no_lte_values) .addFormat(UiOptions.PresentFormat.add3gEntry) @@ -273,6 +275,7 @@ void setPreferenceEntries() { .addFormat(UiOptions.PresentFormat.add2gEntry); break; case ENABLED_NETWORKS_EXCEPT_GSM_LTE_CHOICES: + lteOnlyUnsupported = true; uiOptions = uiOptions .setChoices(R.array.enabled_networks_except_gsm_lte_values) .addFormat(UiOptions.PresentFormat.add3gEntry); @@ -290,6 +293,7 @@ void setPreferenceEntries() { .addFormat(UiOptions.PresentFormat.add3gEntry); break; case ENABLED_NETWORKS_EXCEPT_LTE_CHOICES: + lteOnlyUnsupported = true; uiOptions = uiOptions .setChoices(R.array.enabled_networks_except_lte_values) .addFormat(UiOptions.PresentFormat.add3gEntry) @@ -328,6 +332,11 @@ void setPreferenceEntries() { throw new IllegalArgumentException( uiOptions.getType().name() + " index error."); } + + if (!lteOnlyUnsupported){ + addLteOnlyEntry(); + } + // Compose options based on given values and formats. IntStream.range(0, formatList.size()).forEach(entryIndex -> { switch (formatList.get(entryIndex)) { @@ -506,6 +515,9 @@ void setPreferenceValueAndSummary(int networkMode) { break; } case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY: + setSummary(mShow4gForLTE + ? R.string.network_4G_only : R.string.network_lte_only); + break; case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA: if (!mIsGlobalCdma) { setSelectedEntry( @@ -771,6 +783,16 @@ private void add1xEntry(int value) { mEntriesValue.add(value); } + private void addLteOnlyEntry() { + if (mShow4gForLTE) { + mEntries.add(mContext.getString(R.string.network_4G_only)); + mEntriesValue.add(TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY); + } else { + mEntries.add(mContext.getString(R.string.network_lte_only)); + mEntriesValue.add(TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY); + } + } + private void addCustomEntry(String name, int value) { mEntries.add(name); mEntriesValue.add(value); diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java index feeed91910c1..2746bbe92e09 100644 --- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java @@ -131,7 +131,7 @@ private int getPreferredNetworkModeSummaryResId(int NetworkMode) { case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA: return R.string.preferred_network_mode_lte_tdscdma_summary; case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY: - return R.string.preferred_network_mode_lte_summary; + return R.string.preferred_network_mode_lte_only_summary; case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM: return R.string.preferred_network_mode_lte_tdscdma_gsm_summary; case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA: diff --git a/src/com/android/settings/notification/LinkedVolumesPreferenceController.java b/src/com/android/settings/notification/LinkedVolumesPreferenceController.java new file mode 100644 index 000000000000..aa567780d10d --- /dev/null +++ b/src/com/android/settings/notification/LinkedVolumesPreferenceController.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 The LineageOS 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 android.content.Context; + +import com.android.settings.Utils; +import com.android.settings.core.BasePreferenceController; + +public class LinkedVolumesPreferenceController extends BasePreferenceController { + public LinkedVolumesPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return Utils.isVoiceCapable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } +} diff --git a/src/com/android/settings/notification/NotificationVolumePreferenceController.java b/src/com/android/settings/notification/NotificationVolumePreferenceController.java index 0fe0d6282e89..820dc9b74573 100644 --- a/src/com/android/settings/notification/NotificationVolumePreferenceController.java +++ b/src/com/android/settings/notification/NotificationVolumePreferenceController.java @@ -35,8 +35,7 @@ public NotificationVolumePreferenceController(Context context) { @Override public int getAvailabilityStatus() { return mContext.getResources().getBoolean(R.bool.config_show_notification_volume) - && !Utils.isVoiceCapable(mContext) && !mHelper.isSingleVolume() - ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + && !mHelper.isSingleVolume() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } @Override @@ -64,4 +63,18 @@ public int getMuteIcon() { return R.drawable.ic_notifications_off_24dp; } + @Override + protected void updatePreferenceIcon() { + if (mPreference != null) { + if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) { + mMuteIcon = R.drawable.ic_volume_ringer_vibrate; + mPreference.showIcon(R.drawable.ic_volume_ringer_vibrate); + } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) { + mMuteIcon = R.drawable.ic_notifications_off_24dp; + mPreference.showIcon(R.drawable.ic_notifications_off_24dp); + } else { + mPreference.showIcon(R.drawable.ic_notifications); + } + } + } } diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java index 5e7d067a8ad8..5e9d0fdf4af6 100644 --- a/src/com/android/settings/notification/RingVolumePreferenceController.java +++ b/src/com/android/settings/notification/RingVolumePreferenceController.java @@ -43,12 +43,12 @@ public class RingVolumePreferenceController extends VolumeSeekBarPreferenceContr private static final String KEY_RING_VOLUME = "ring_volume"; private Vibrator mVibrator; - private int mRingerMode = -1; + protected int mRingerMode = -1; private ComponentName mSuppressor; private final RingReceiver mReceiver = new RingReceiver(); private final H mHandler = new H(); - private int mMuteIcon; + protected int mMuteIcon; public RingVolumePreferenceController(Context context) { this(context, KEY_RING_VOLUME); @@ -133,7 +133,7 @@ private void updateEffectsSuppressor() { updatePreferenceIcon(); } - private void updatePreferenceIcon() { + protected void updatePreferenceIcon() { if (mPreference != null) { if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) { mMuteIcon = R.drawable.ic_volume_ringer_vibrate; @@ -142,7 +142,7 @@ private void updatePreferenceIcon() { mMuteIcon = R.drawable.ic_notifications_off_24dp; mPreference.showIcon(R.drawable.ic_notifications_off_24dp); } else { - mPreference.showIcon(R.drawable.ic_notifications); + mPreference.showIcon(R.drawable.ic_audio_ring); } } } diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java index 08884d5621f9..e94cd88a7aa8 100644 --- a/src/com/android/settings/panel/VolumePanel.java +++ b/src/com/android/settings/panel/VolumePanel.java @@ -24,6 +24,7 @@ import static com.android.settings.slices.CustomSliceRegistry.VOLUME_ALARM_URI; import static com.android.settings.slices.CustomSliceRegistry.VOLUME_CALL_URI; import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI; +import static com.android.settings.slices.CustomSliceRegistry.VOLUME_NOTIFICATION_URI; import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI; import android.app.Activity; @@ -139,6 +140,10 @@ public List getSlices() { uris.add(MEDIA_OUTPUT_INDICATOR_SLICE_URI); uris.add(VOLUME_CALL_URI); uris.add(VOLUME_RINGER_URI); + if (com.android.settings.Utils.isVoiceCapable(mContext) && Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 0) { + uris.add(VOLUME_NOTIFICATION_URI); + } uris.add(VOLUME_ALARM_URI); return uris; } diff --git a/src/com/android/settings/privacy/ScreenshotTimestampExifPreferenceController.java b/src/com/android/settings/privacy/ScreenshotTimestampExifPreferenceController.java new file mode 100644 index 000000000000..f3f037603cd9 --- /dev/null +++ b/src/com/android/settings/privacy/ScreenshotTimestampExifPreferenceController.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 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.privacy; + +import android.content.Context; + +import android.provider.Settings; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.TogglePreferenceController; +import com.android.settings.R; + +import static android.provider.Settings.Secure.DISABLE_SCREENSHOT_TIMESTAMP_EXIF; +import static android.provider.Settings.Secure.ENABLE_SCREENSHOT_TIMESTAMP_EXIF; + +/** + * Controller for preference to toggle whether screenshot EXIF timestamp should be added. + */ +public class ScreenshotTimestampExifPreferenceController extends TogglePreferenceController { + public ScreenshotTimestampExifPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public boolean isChecked() { + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.SCREENSHOT_TIMESTAMP_EXIF, DISABLE_SCREENSHOT_TIMESTAMP_EXIF) + == ENABLE_SCREENSHOT_TIMESTAMP_EXIF; + } + + @Override + public boolean setChecked(boolean checked) { + return Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.SCREENSHOT_TIMESTAMP_EXIF, checked ? + ENABLE_SCREENSHOT_TIMESTAMP_EXIF : DISABLE_SCREENSHOT_TIMESTAMP_EXIF); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_privacy; + } +} \ No newline at end of file diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java index d1b169c29760..df5acdde08c3 100644 --- a/src/com/android/settings/slices/CustomSliceRegistry.java +++ b/src/com/android/settings/slices/CustomSliceRegistry.java @@ -197,6 +197,17 @@ public class CustomSliceRegistry { .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) .appendPath("call_volume") .build(); + + /** + * Full {@link Uri} for the Notification Volume Slice. + */ + public static final Uri VOLUME_NOTIFICATION_URI = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(SettingsSliceProvider.SLICE_AUTHORITY) + .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) + .appendPath("notification_volume") + .build(); + /** * Full {@link Uri} for the Media Volume Slice. */ diff --git a/src/com/android/settings/slices/SlicesDatabaseHelper.java b/src/com/android/settings/slices/SlicesDatabaseHelper.java index 69ad702913c8..9daed69ea242 100644 --- a/src/com/android/settings/slices/SlicesDatabaseHelper.java +++ b/src/com/android/settings/slices/SlicesDatabaseHelper.java @@ -239,6 +239,6 @@ private boolean isLocaleIndexed() { @VisibleForTesting String getBuildTag() { - return Build.FINGERPRINT; + return Build.VERSION.INCREMENTAL; } -} \ No newline at end of file +} diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java index bf0dfc9c5b89..565741678413 100644 --- a/src/com/android/settings/vpn2/ConfigDialog.java +++ b/src/com/android/settings/vpn2/ConfigDialog.java @@ -524,25 +524,7 @@ private void setTypesByFeature(Spinner typeSpinner) { PackageManager.FEATURE_IPSEC_TUNNELS)) { Log.wtf(TAG, "FEATURE_IPSEC_TUNNELS missing from system"); } - // If the vpn is new or is not already a legacy type, - // don't allow the user to set the type to a legacy option. - // Set the mProfile.type to TYPE_IKEV2_IPSEC_USER_PASS if the VPN not exist - if (!mExists) { - mProfile.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; - } - - // Remove all types which are legacy types from the typesList - if (!VpnProfile.isLegacyType(mProfile.type)) { - for (int i = mAllowedTypes.size() - 1; i >= 0; i--) { - // This must be removed from back to front in order to ensure index consistency - if (VpnProfile.isLegacyType(i)) { - mAllowedTypes.remove(i); - } - } - - types = mAllowedTypes.toArray(new String[0]); - } final ArrayAdapter adapter = new ArrayAdapter( getContext(), android.R.layout.simple_spinner_item, types); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); diff --git a/src/com/android/settings/wfd/WifiDisplaySettings.java b/src/com/android/settings/wfd/WifiDisplaySettings.java index 19b6c5457d76..c225c0d18cbc 100755 --- a/src/com/android/settings/wfd/WifiDisplaySettings.java +++ b/src/com/android/settings/wfd/WifiDisplaySettings.java @@ -346,22 +346,26 @@ public void onBindViewHolder(PreferenceViewHolder view) { super.onBindViewHolder(view); Button b = (Button) view.findViewById(R.id.left_button); - b.setText(R.string.wifi_display_pause); - b.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mDisplayManager.pauseWifiDisplay(); - } - }); + if (b != null) { + b.setText(R.string.wifi_display_pause); + b.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mDisplayManager.pauseWifiDisplay(); + } + }); + } b = (Button) view.findViewById(R.id.right_button); - b.setText(R.string.wifi_display_resume); - b.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mDisplayManager.resumeWifiDisplay(); - } - }); + if (b != null) { + b.setText(R.string.wifi_display_resume); + b.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mDisplayManager.resumeWifiDisplay(); + } + }); + } } }); mCertCategory.setLayoutResource(R.layout.two_buttons_panel); diff --git a/src/com/android/settings/wifi/WifiTimeoutPreferenceController.java b/src/com/android/settings/wifi/WifiTimeoutPreferenceController.java new file mode 100644 index 000000000000..dfd087823669 --- /dev/null +++ b/src/com/android/settings/wifi/WifiTimeoutPreferenceController.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2020 The Calyx Institute + * + * 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.wifi; + +import android.content.Context; +import android.net.wifi.WifiManager; +import android.provider.Settings; +import android.util.Log; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.core.PreferenceControllerMixin; + +public class WifiTimeoutPreferenceController extends BasePreferenceController implements + PreferenceControllerMixin, Preference.OnPreferenceChangeListener { + private static final String TAG = "WifiTimeoutPrefCtrl"; + + public static final int FALLBACK_WIFI_TIMEOUT_VALUE = 0; + + private final String mWifiTimeoutKey; + + protected WifiManager mWifiManager; + + public WifiTimeoutPreferenceController(Context context, String key) { + super(context, key); + mWifiTimeoutKey = key; + + mWifiManager = context.getSystemService(WifiManager.class); + if (mWifiManager == null) { + Log.e(TAG, "Wifi is not supported on this device"); + return; + } + } + + @Override + public int getAvailabilityStatus() { + return mWifiManager != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public String getPreferenceKey() { + return mWifiTimeoutKey; + } + + @Override + public void updateState(Preference preference) { + final ListPreference timeoutListPreference = (ListPreference) preference; + final long currentTimeout = Settings.Global.getLong(mContext.getContentResolver(), + Settings.Global.WIFI_OFF_TIMEOUT, FALLBACK_WIFI_TIMEOUT_VALUE); + timeoutListPreference.setValue(String.valueOf(currentTimeout)); + updateTimeoutPreferenceDescription(timeoutListPreference, + Long.parseLong(timeoutListPreference.getValue())); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + try { + long value = Long.parseLong((String) newValue); + Settings.Global.putLong(mContext.getContentResolver(), Settings.Global.WIFI_OFF_TIMEOUT, value); + updateTimeoutPreferenceDescription((ListPreference) preference, value); + } catch (NumberFormatException e) { + Log.e(TAG, "could not persist wifi timeout setting", e); + } + return true; + } + + public static CharSequence getTimeoutDescription( + long currentTimeout, CharSequence[] entries, CharSequence[] values) { + if (currentTimeout < 0 || entries == null || values == null + || values.length != entries.length) { + return null; + } + + for (int i = 0; i < values.length; i++) { + long timeout = Long.parseLong(values[i].toString()); + if (currentTimeout == timeout) { + return entries[i]; + } + } + return null; + } + + private void updateTimeoutPreferenceDescription(ListPreference preference, + long currentTimeout) { + final CharSequence[] entries = preference.getEntries(); + final CharSequence[] values = preference.getEntryValues(); + final CharSequence timeoutDescription = getTimeoutDescription( + currentTimeout, entries, values); + String summary = ""; + if (timeoutDescription != null) { + if (currentTimeout != 0) + summary = mContext.getString(R.string.wifi_timeout_summary1, timeoutDescription); + else + summary = mContext.getString(R.string.wifi_timeout_summary2); + } + preference.setSummary(summary); + } +} diff --git a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java index 8a4be105986f..2203c9684301 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java +++ b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java @@ -126,11 +126,7 @@ void updatePreferenceEntries() { } private boolean is5GhzBandSupported() { - final String countryCode = mWifiManager.getCountryCode(); - if (!mWifiManager.is5GHzBandSupported() || countryCode == null) { - return false; - } - return true; + return mWifiManager.is5GHzBandSupported(); } public int getBandIndex() { diff --git a/src/com/axiom/settings/preference/CustomDialogPreferenceCompat.java b/src/com/axiom/settings/preference/CustomDialogPreferenceCompat.java new file mode 100644 index 000000000000..a8b2f4ed0358 --- /dev/null +++ b/src/com/axiom/settings/preference/CustomDialogPreferenceCompat.java @@ -0,0 +1,215 @@ +/* + * 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. + */ +package com.axiom.settings.preference; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.DialogPreference; +import androidx.preference.PreferenceDialogFragmentCompat; + +public class CustomDialogPreferenceCompat extends DialogPreference { + + private CustomPreferenceDialogFragment mFragment; + + public CustomDialogPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public CustomDialogPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public CustomDialogPreferenceCompat(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CustomDialogPreferenceCompat(Context context) { + super(context); + } + + public boolean isDialogOpen() { + return getDialog() != null && getDialog() instanceof Dialog && ((Dialog)getDialog()).isShowing(); + } + + public T getDialog() { + return (T) (mFragment != null ? mFragment.getDialog() : null); + } + + protected void onPrepareDialogBuilder(AlertDialog.Builder builder, + DialogInterface.OnClickListener listener) { + } + + protected void onDialogClosed(boolean positiveResult) { + } + + protected void onClick(T dialog, int which) { + } + + protected void onBindDialogView(View view) { + } + + protected void onStart() { + } + + protected void onStop() { + } + + protected void onPause() { + } + + protected void onResume() { + } + + public Dialog onCreateDialog(Bundle savedInstanceState) { + return null; + } + + protected View onCreateDialogView(Context context) { + return null; + } + + private void setFragment(CustomPreferenceDialogFragment fragment) { + mFragment = fragment; + } + + protected boolean onDismissDialog(T dialog, int which) { + return true; + } + + public static class CustomPreferenceDialogFragment extends PreferenceDialogFragmentCompat { + + public static CustomPreferenceDialogFragment newInstance(String key) { + final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment(); + final Bundle b = new Bundle(1); + b.putString(ARG_KEY, key); + fragment.setArguments(b); + return fragment; + } + + private CustomDialogPreferenceCompat getCustomizablePreference() { + return (CustomDialogPreferenceCompat) getPreference(); + } + + private class OnDismissListener implements View.OnClickListener { + private final int mWhich; + private final DialogInterface mDialog; + + public OnDismissListener(DialogInterface dialog, int which) { + mWhich = which; + mDialog = dialog; + } + + @Override + public void onClick(View view) { + CustomPreferenceDialogFragment.this.onClick(mDialog, mWhich); + if (getCustomizablePreference().onDismissDialog(mDialog, mWhich)) { + mDialog.dismiss(); + } + } + } + + @Override + public void onStart() { + super.onStart(); + if (getDialog() instanceof AlertDialog) { + AlertDialog a = (AlertDialog)getDialog(); + if (a.getButton(Dialog.BUTTON_NEUTRAL) != null) { + a.getButton(Dialog.BUTTON_NEUTRAL).setOnClickListener( + new OnDismissListener(a, Dialog.BUTTON_NEUTRAL)); + } + if (a.getButton(Dialog.BUTTON_POSITIVE) != null) { + a.getButton(Dialog.BUTTON_POSITIVE).setOnClickListener( + new OnDismissListener(a, Dialog.BUTTON_POSITIVE)); + } + if (a.getButton(Dialog.BUTTON_NEGATIVE) != null) { + a.getButton(Dialog.BUTTON_NEGATIVE).setOnClickListener( + new OnDismissListener(a, Dialog.BUTTON_NEGATIVE)); + } + } + getCustomizablePreference().onStart(); + } + + @Override + public void onStop() { + super.onStop(); + getCustomizablePreference().onStop(); + } + + @Override + public void onPause() { + super.onPause(); + getCustomizablePreference().onPause(); + } + + @Override + public void onResume() { + super.onResume(); + getCustomizablePreference().onResume(); + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + super.onPrepareDialogBuilder(builder); + getCustomizablePreference().setFragment(this); + getCustomizablePreference().onPrepareDialogBuilder(builder, this); + } + + @Override + public void onDialogClosed(boolean positiveResult) { + getCustomizablePreference().onDialogClosed(positiveResult); + } + + @Override + protected void onBindDialogView(View view) { + super.onBindDialogView(view); + getCustomizablePreference().onBindDialogView(view); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + super.onClick(dialog, which); + getCustomizablePreference().onClick(dialog, which); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + getCustomizablePreference().setFragment(this); + final Dialog sub = getCustomizablePreference().onCreateDialog(savedInstanceState); + if (sub == null) { + return super.onCreateDialog(savedInstanceState); + } + return sub; + } + + @Override + protected View onCreateDialogView(Context context) { + final View v = getCustomizablePreference().onCreateDialogView(context); + if (v == null) { + return super.onCreateDialogView(context); + } + return v; + } + } +} diff --git a/src/com/axiom/settings/preference/CustomSecureSeekBarPreference.java b/src/com/axiom/settings/preference/CustomSecureSeekBarPreference.java new file mode 100644 index 000000000000..a7b0cd755011 --- /dev/null +++ b/src/com/axiom/settings/preference/CustomSecureSeekBarPreference.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 AICP + * + * 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.axiom.settings.preference; + +import android.content.Context; +import android.util.AttributeSet; + +public class CustomSecureSeekBarPreference extends CustomSeekBarPreference { + + public CustomSecureSeekBarPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver())); + } + + public CustomSecureSeekBarPreference(Context context, AttributeSet attrs) { + super(context, attrs); + setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver())); + } + + public CustomSecureSeekBarPreference(Context context) { + super(context, null); + setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver())); + } +} diff --git a/src/com/axiom/settings/preference/CustomSeekBarPreference.java b/src/com/axiom/settings/preference/CustomSeekBarPreference.java new file mode 100644 index 000000000000..240d93682aa7 --- /dev/null +++ b/src/com/axiom/settings/preference/CustomSeekBarPreference.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2016 The Dirty Unicorns 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.axiom.settings.preference; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.util.Log; +import android.view.ViewParent; +import android.view.ViewGroup; +import android.widget.SeekBar; +import android.widget.TextView; +import androidx.preference.*; + +import com.android.settings.R; + +public class CustomSeekBarPreference extends Preference implements SeekBar.OnSeekBarChangeListener { + private final String TAG = getClass().getName(); + private static final String SETTINGS_NS = "http://schemas.android.com/apk/res/com.android.settings"; + private static final String ANDROIDNS = "http://schemas.android.com/apk/res/android"; + private static final int DEFAULT_VALUE = 50; + + private int mMin = 0; + private int mInterval = 1; + private int mCurrentValue; + private int mDefaultValue = -1; + private int mMax = 100; + private String mUnits = ""; + private String mDefaultText = ""; + private SeekBar mSeekBar; + private TextView mTitle; + private TextView mStatusText; + + public CustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.CustomSeekBarPreference); + + mMax = attrs.getAttributeIntValue(ANDROIDNS, "max", 100); + mMin = attrs.getAttributeIntValue(SETTINGS_NS, "min", 0); + mDefaultValue = attrs.getAttributeIntValue(ANDROIDNS, "defaultValue", -1); + if (mDefaultValue > mMax) { + mDefaultValue = mMax; + } + mUnits = getAttributeStringValue(attrs, SETTINGS_NS, "units", ""); + mDefaultText = getAttributeStringValue(attrs, SETTINGS_NS, "defaultText", + context.getResources().getString(R.string.default_text)); + Integer id = a.getResourceId(R.styleable.CustomSeekBarPreference_units, 0); + if (id > 0) { + mUnits = context.getResources().getString(id); + } + id = a.getResourceId(R.styleable.CustomSeekBarPreference_defaultText, 0); + if (id > 0) { + mDefaultText = context.getResources().getString(id); + } + + try { + String newInterval = attrs.getAttributeValue(SETTINGS_NS, "interval"); + if (newInterval != null) + mInterval = Integer.parseInt(newInterval); + } catch (Exception e) { + Log.e(TAG, "Invalid interval value", e); + } + + a.recycle(); + mSeekBar = new SeekBar(context, attrs); + mSeekBar.setMax(mMax - mMin); + mSeekBar.setOnSeekBarChangeListener(this); + setLayoutResource(R.layout.preference_custom_seekbar); + } + + public CustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public CustomSeekBarPreference(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CustomSeekBarPreference(Context context) { + this(context, null); + } + + private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, + String defaultValue) { + String value = attrs.getAttributeValue(namespace, name); + if (value == null) + value = defaultValue; + + return value; + } + + @Override + public void onDependencyChanged(Preference dependency, boolean disableDependent) { + super.onDependencyChanged(dependency, disableDependent); + this.setShouldDisableView(true); + if (mTitle != null) + mTitle.setEnabled(!disableDependent); + if (mSeekBar != null) + mSeekBar.setEnabled(!disableDependent); + if (mStatusText != null) + mStatusText.setEnabled(!disableDependent); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder view) { + super.onBindViewHolder(view); + try + { + // move our seekbar to the new view we've been given + ViewParent oldContainer = mSeekBar.getParent(); + ViewGroup newContainer = (ViewGroup) view.findViewById(R.id.seekBarPrefBarContainer); + + if (oldContainer != newContainer) { + // remove the seekbar from the old view + if (oldContainer != null) { + ((ViewGroup) oldContainer).removeView(mSeekBar); + } + // remove the existing seekbar (there may not be one) and add ours + newContainer.removeAllViews(); + newContainer.addView(mSeekBar, ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + } + } catch (Exception ex) { + Log.e(TAG, "Error binding view: " + ex.toString()); + } + mStatusText = (TextView) view.findViewById(R.id.seekBarPrefValue); + if (mCurrentValue == mDefaultValue) { + mStatusText.setText(mDefaultText); + } else { + mStatusText.setText(String.valueOf(mCurrentValue) + mUnits); + } + mSeekBar.setProgress(mCurrentValue - mMin); + mTitle = (TextView) view.findViewById(android.R.id.title); + + view.setDividerAllowedAbove(false); + //view.setDividerAllowedBelow(false); + + mSeekBar.setEnabled(isEnabled()); + } + + public void setMax(int max) { + mMax = max; + mSeekBar.setMax(mMax - mMin); + } + + public void setMin(int min) { + mMin = min; + mSeekBar.setMax(mMax - mMin); + } + + public void setIntervalValue(int value) { + mInterval = value; + } + + public void setValue(int value) { + mCurrentValue = value; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + int newValue = progress + mMin; + if (newValue > mMax) + newValue = mMax; + else if (newValue < mMin) + newValue = mMin; + else if (mInterval != 1 && newValue % mInterval != 0) + newValue = Math.round(((float) newValue) / mInterval) * mInterval; + + // change rejected, revert to the previous value + if (!callChangeListener(newValue)) { + seekBar.setProgress(mCurrentValue - mMin); + return; + } + // change accepted, store it + mCurrentValue = newValue; + if (mStatusText != null) { + if (newValue == mDefaultValue) { + mStatusText.setText(mDefaultText); + } else { + mStatusText.setText(String.valueOf(newValue) + mUnits); + } + } + persistInt(newValue); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + notifyChanged(); + } + + @Override + protected Object onGetDefaultValue(TypedArray ta, int index) { + int defaultValue = ta.getInt(index, DEFAULT_VALUE); + return defaultValue; + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + if (restoreValue) { + mCurrentValue = getPersistedInt(mCurrentValue); + } + else { + int temp = 0; + try { + temp = (Integer) defaultValue; + } catch (Exception ex) { + Log.e(TAG, "Invalid default value: " + defaultValue.toString()); + } + persistInt(temp); + mCurrentValue = temp; + } + } + + public void setDefaultValue(int value) { + mDefaultValue = value; + if (mDefaultValue > mMax) { + mDefaultValue = mMax; + } + if (mCurrentValue == mDefaultValue && mStatusText != null) { + mStatusText.setText(mDefaultText); + } + } + + @Override + public void setEnabled(boolean enabled) { + if (mSeekBar != null && mStatusText != null && mTitle != null) { + mSeekBar.setEnabled(enabled); + mStatusText.setEnabled(enabled); + mTitle.setEnabled(enabled); + } + super.setEnabled(enabled); + } +} diff --git a/src/com/axiom/settings/preference/CustomSystemSeekBarPreference.java b/src/com/axiom/settings/preference/CustomSystemSeekBarPreference.java new file mode 100644 index 000000000000..c76cd749db03 --- /dev/null +++ b/src/com/axiom/settings/preference/CustomSystemSeekBarPreference.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 AICP + * + * 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.axiom.settings.preference; + +import android.content.Context; +import android.util.AttributeSet; + +public class CustomSystemSeekBarPreference extends CustomSeekBarPreference { + + public CustomSystemSeekBarPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } + + public CustomSystemSeekBarPreference(Context context, AttributeSet attrs) { + super(context, attrs); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } + + public CustomSystemSeekBarPreference(Context context) { + super(context, null); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } +} diff --git a/src/com/axiom/settings/preference/GlobalSettingSwitchPreference.java b/src/com/axiom/settings/preference/GlobalSettingSwitchPreference.java new file mode 100644 index 000000000000..909cc6e10b79 --- /dev/null +++ b/src/com/axiom/settings/preference/GlobalSettingSwitchPreference.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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.axiom.settings.preference; + +import android.content.Context; +import android.provider.Settings; +import androidx.preference.SwitchPreference; +import android.util.AttributeSet; + +public class GlobalSettingSwitchPreference extends SwitchPreference { + public GlobalSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public GlobalSettingSwitchPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public GlobalSettingSwitchPreference(Context context) { + super(context, null); + } + + @Override + protected boolean persistBoolean(boolean value) { + if (shouldPersist()) { + if (value == getPersistedBoolean(!value)) { + // It's already there, so the same as persisting + return true; + } + Settings.Global.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0); + return true; + } + return false; + } + + @Override + protected boolean getPersistedBoolean(boolean defaultReturnValue) { + if (!shouldPersist()) { + return defaultReturnValue; + } + return Settings.Global.getInt(getContext().getContentResolver(), + getKey(), defaultReturnValue ? 1 : 0) != 0; + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + setChecked(Settings.Global.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked()) + : (Boolean) defaultValue); + } +} diff --git a/src/com/axiom/settings/preference/ListPreference.java b/src/com/axiom/settings/preference/ListPreference.java new file mode 100644 index 000000000000..05201ff6520c --- /dev/null +++ b/src/com/axiom/settings/preference/ListPreference.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017-2018 AICP + * + * 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.axiom.settings.preference; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; + +public class ListPreference extends androidx.preference.ListPreference { + private boolean mAutoSummary = false; + + public ListPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public ListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ListPreference(Context context) { + super(context); + } + + @Override + public void setValue(String value) { + super.setValue(value); + if (mAutoSummary || TextUtils.isEmpty(getSummary())) { + setSummary(getEntry(), true); + } + } + + @Override + public void setSummary(CharSequence summary) { + setSummary(summary, false); + } + + private void setSummary(CharSequence summary, boolean autoSummary) { + mAutoSummary = autoSummary; + super.setSummary(summary); + } +} diff --git a/src/com/axiom/settings/preference/SecureSettingSwitchPreference.java b/src/com/axiom/settings/preference/SecureSettingSwitchPreference.java new file mode 100644 index 000000000000..c95b31f74388 --- /dev/null +++ b/src/com/axiom/settings/preference/SecureSettingSwitchPreference.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 AICP + * + * 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.axiom.settings.preference; + +import android.content.Context; +import androidx.preference.SwitchPreference; +import android.util.AttributeSet; + +public class SecureSettingSwitchPreference extends SwitchPreference { + + public SecureSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver())); + } + + public SecureSettingSwitchPreference(Context context, AttributeSet attrs) { + super(context, attrs); + setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver())); + } + + public SecureSettingSwitchPreference(Context context) { + super(context); + setPreferenceDataStore(new SecureSettingsStore(context.getContentResolver())); + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + // This is what default TwoStatePreference implementation is doing without respecting + // real default value: + //setChecked(restoreValue ? getPersistedBoolean(mChecked) + // : (Boolean) defaultValue); + // Instead, we better do + setChecked(restoreValue ? getPersistedBoolean((Boolean) defaultValue) + : (Boolean) defaultValue); + } +} diff --git a/src/com/axiom/settings/preference/SecureSettingsStore.java b/src/com/axiom/settings/preference/SecureSettingsStore.java new file mode 100644 index 000000000000..e021bb098fa0 --- /dev/null +++ b/src/com/axiom/settings/preference/SecureSettingsStore.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 AICP + * + * 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.axiom.settings.preference; + +import android.content.ContentResolver; +import android.preference.PreferenceDataStore; +import android.provider.Settings; + +public class SecureSettingsStore extends androidx.preference.PreferenceDataStore + implements PreferenceDataStore { + + private ContentResolver mContentResolver; + + public SecureSettingsStore(ContentResolver contentResolver) { + mContentResolver = contentResolver; + } + + public boolean getBoolean(String key, boolean defValue) { + return getInt(key, defValue ? 1 : 0) != 0; + } + + public float getFloat(String key, float defValue) { + return Settings.Secure.getFloat(mContentResolver, key, defValue); + } + + public int getInt(String key, int defValue) { + return Settings.Secure.getInt(mContentResolver, key, defValue); + } + + public long getLong(String key, long defValue) { + return Settings.Secure.getLong(mContentResolver, key, defValue); + } + + public String getString(String key, String defValue) { + String result = Settings.Secure.getString(mContentResolver, key); + return result == null ? defValue : result; + } + + public void putBoolean(String key, boolean value) { + putInt(key, value ? 1 : 0); + } + + public void putFloat(String key, float value) { + Settings.Secure.putFloat(mContentResolver, key, value); + } + + public void putInt(String key, int value) { + Settings.Secure.putInt(mContentResolver, key, value); + } + + public void putLong(String key, long value) { + Settings.Secure.putLong(mContentResolver, key, value); + } + + public void putString(String key, String value) { + Settings.Secure.putString(mContentResolver, key, value); + } + +} diff --git a/src/com/axiom/settings/preference/SystemSettingListPreference.java b/src/com/axiom/settings/preference/SystemSettingListPreference.java new file mode 100644 index 000000000000..6d6909dadab4 --- /dev/null +++ b/src/com/axiom/settings/preference/SystemSettingListPreference.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017-2018 AICP + * + * 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.axiom.settings.preference; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; + +public class SystemSettingListPreference extends ListPreference { + + public SystemSettingListPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } + + public SystemSettingListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } + + public SystemSettingListPreference(Context context) { + super(context); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + // This is what default ListPreference implementation is doing without respecting + // real default value: + //setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue); + // Instead, we better do + setValue(restoreValue ? getPersistedString((String) defaultValue) : (String) defaultValue); + } + +} diff --git a/src/com/axiom/settings/preference/SystemSettingSeekBarPreference.java b/src/com/axiom/settings/preference/SystemSettingSeekBarPreference.java new file mode 100644 index 000000000000..bbf9477fe654 --- /dev/null +++ b/src/com/axiom/settings/preference/SystemSettingSeekBarPreference.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 AICP + * + * 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.axiom.settings.preference; + +import android.content.Context; +import android.util.AttributeSet; + +public class SystemSettingSeekBarPreference extends CustomSeekBarPreference { + + public SystemSettingSeekBarPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } + + public SystemSettingSeekBarPreference(Context context, AttributeSet attrs) { + super(context, attrs); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } + + public SystemSettingSeekBarPreference(Context context) { + super(context, null); + setPreferenceDataStore(new SystemSettingsStore(context.getContentResolver())); + } +} \ No newline at end of file diff --git a/src/com/axiom/settings/preference/SystemSettingSwitchPreference.java b/src/com/axiom/settings/preference/SystemSettingSwitchPreference.java new file mode 100644 index 000000000000..2df2d7f99579 --- /dev/null +++ b/src/com/axiom/settings/preference/SystemSettingSwitchPreference.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013 The CyanogenMod 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.axiom.settings.preference; + +import android.content.Context; +import android.provider.Settings; +import androidx.preference.SwitchPreference; +import android.util.AttributeSet; + +public class SystemSettingSwitchPreference extends SwitchPreference { + public SystemSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public SystemSettingSwitchPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public SystemSettingSwitchPreference(Context context) { + super(context, null); + } + + @Override + protected boolean persistBoolean(boolean value) { + if (shouldPersist()) { + if (value == getPersistedBoolean(!value)) { + // It's already there, so the same as persisting + return true; + } + Settings.System.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0); + return true; + } + return false; + } + + @Override + protected boolean getPersistedBoolean(boolean defaultReturnValue) { + if (!shouldPersist()) { + return defaultReturnValue; + } + return Settings.System.getInt(getContext().getContentResolver(), + getKey(), defaultReturnValue ? 1 : 0) != 0; + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + setChecked(Settings.System.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked()) + : (Boolean) defaultValue); + } +} diff --git a/src/com/axiom/settings/preference/SystemSettingsStore.java b/src/com/axiom/settings/preference/SystemSettingsStore.java new file mode 100644 index 000000000000..f0f01c049b01 --- /dev/null +++ b/src/com/axiom/settings/preference/SystemSettingsStore.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 AICP + * + * 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.axiom.settings.preference; + +import android.content.ContentResolver; +import android.preference.PreferenceDataStore; +import android.provider.Settings; + +public class SystemSettingsStore extends androidx.preference.PreferenceDataStore + implements PreferenceDataStore { + + private ContentResolver mContentResolver; + + public SystemSettingsStore(ContentResolver contentResolver) { + mContentResolver = contentResolver; + } + + public boolean getBoolean(String key, boolean defValue) { + return getInt(key, defValue ? 1 : 0) != 0; + } + + public float getFloat(String key, float defValue) { + return Settings.System.getFloat(mContentResolver, key, defValue); + } + + public int getInt(String key, int defValue) { + return Settings.System.getInt(mContentResolver, key, defValue); + } + + public long getLong(String key, long defValue) { + return Settings.System.getLong(mContentResolver, key, defValue); + } + + public String getString(String key, String defValue) { + String result = Settings.System.getString(mContentResolver, key); + return result == null ? defValue : result; + } + + public void putBoolean(String key, boolean value) { + putInt(key, value ? 1 : 0); + } + + public void putFloat(String key, float value) { + Settings.System.putFloat(mContentResolver, key, value); + } + + public void putInt(String key, int value) { + Settings.System.putInt(mContentResolver, key, value); + } + + public void putLong(String key, long value) { + Settings.System.putLong(mContentResolver, key, value); + } + + public void putString(String key, String value) { + Settings.System.putString(mContentResolver, key, value); + } + +} diff --git a/src/com/axiom/settings/preference/Utils.java b/src/com/axiom/settings/preference/Utils.java new file mode 100644 index 000000000000..fc4ba3f82082 --- /dev/null +++ b/src/com/axiom/settings/preference/Utils.java @@ -0,0 +1,203 @@ +/** + * Copyright (C) 2016 The Pure Nexus 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.axiom.settings.preference; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.Signature; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraManager; +import android.net.ConnectivityManager; +import android.os.UserManager; +import android.telephony.TelephonyManager; +import android.util.DisplayMetrics; +import android.view.DisplayInfo; +import android.view.Surface; +import android.view.WindowManager; + +public final class Utils { + private static final String TAG = "AxiomSettingsUtils"; + + // Device types + private static final int DEVICE_PHONE = 0; + private static final int DEVICE_HYBRID = 1; + private static final int DEVICE_TABLET = 2; + + // Device type reference + private static int sDeviceType = -1; + + /** + * Returns whether the device is voice-capable (meaning, it is also a phone). + */ + public static boolean isVoiceCapable(Context context) { + TelephonyManager telephony = + (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + return telephony != null && telephony.isVoiceCapable(); + } + + + public static boolean hasMultipleUsers(Context context) { + return ((UserManager) context.getSystemService(Context.USER_SERVICE)) + .getUsers().size() > 1; + } + + private static int getScreenType(Context context) { + if (sDeviceType == -1) { + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + DisplayInfo outDisplayInfo = new DisplayInfo(); + wm.getDefaultDisplay().getDisplayInfo(outDisplayInfo); + int shortSize = Math.min(outDisplayInfo.logicalHeight, outDisplayInfo.logicalWidth); + int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT + / outDisplayInfo.logicalDensityDpi; + if (shortSizeDp < 600) { + // 0-599dp: "phone" UI with a separate status & navigation bar + sDeviceType = DEVICE_PHONE; + } else if (shortSizeDp < 720) { + // 600-719dp: "phone" UI with modifications for larger screens + sDeviceType = DEVICE_HYBRID; + } else { + // 720dp: "tablet" UI with a single combined status & navigation bar + sDeviceType = DEVICE_TABLET; + } + } + return sDeviceType; + } + + public static boolean isPhone(Context context) { + return getScreenType(context) == DEVICE_PHONE; + } + + public static boolean isHybrid(Context context) { + return getScreenType(context) == DEVICE_HYBRID; + } + + public static boolean isTablet(Context context) { + return getScreenType(context) == DEVICE_TABLET; + } + + /** + * Determine whether a package is a "system package", in which case certain things (like + * disabling notifications or disabling the package altogether) should be disallowed. + */ + public static boolean isSystemPackage(PackageManager pm, PackageInfo pkg) { + if (sSystemSignature == null) { + sSystemSignature = new Signature[]{ getSystemSignature(pm) }; + } + return sSystemSignature[0] != null && sSystemSignature[0].equals(getFirstSignature(pkg)); + } + + private static Signature[] sSystemSignature; + + private static Signature getFirstSignature(PackageInfo pkg) { + if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) { + return pkg.signatures[0]; + } + return null; + } + + private static Signature getSystemSignature(PackageManager pm) { + try { + final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES); + return getFirstSignature(sys); + } catch (NameNotFoundException e) { + } + return null; + } + + public static boolean isPackageInstalled(Context context, String pkg, boolean ignoreState) { + if (pkg != null) { + try { + PackageInfo pi = context.getPackageManager().getPackageInfo(pkg, 0); + if (!pi.applicationInfo.enabled && !ignoreState) { + return false; + } + } catch (NameNotFoundException e) { + return false; + } + } + + return true; + } + + public static boolean isPackageInstalled(Context context, String pkg) { + return isPackageInstalled(context, pkg, true); + } + + /** + * Locks the activity orientation to the current device orientation + * @param activity + */ + public static void lockCurrentOrientation(Activity activity) { + int currentRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); + int orientation = activity.getResources().getConfiguration().orientation; + int frozenRotation = 0; + switch (currentRotation) { + case Surface.ROTATION_0: + frozenRotation = orientation == Configuration.ORIENTATION_LANDSCAPE + ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + break; + case Surface.ROTATION_90: + frozenRotation = orientation == Configuration.ORIENTATION_PORTRAIT + ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT + : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + break; + case Surface.ROTATION_180: + frozenRotation = orientation == Configuration.ORIENTATION_LANDSCAPE + ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE + : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; + break; + case Surface.ROTATION_270: + frozenRotation = orientation == Configuration.ORIENTATION_PORTRAIT + ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; + break; + } + activity.setRequestedOrientation(frozenRotation); + } + + public static boolean deviceSupportsFlashLight(Context context) { + CameraManager cameraManager = (CameraManager) context.getSystemService( + Context.CAMERA_SERVICE); + try { + String[] ids = cameraManager.getCameraIdList(); + for (String id : ids) { + CameraCharacteristics c = cameraManager.getCameraCharacteristics(id); + Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); + Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING); + if (flashAvailable != null + && flashAvailable + && lensFacing != null + && lensFacing == CameraCharacteristics.LENS_FACING_BACK) { + return true; + } + } + } catch (CameraAccessException e) { + // Ignore + } + return false; + } +} diff --git a/src/com/axiom/settings/preference/deviceinfo/AxiomOSBuildIdPreferenceController.java b/src/com/axiom/settings/preference/deviceinfo/AxiomOSBuildIdPreferenceController.java new file mode 100644 index 000000000000..65e789d65555 --- /dev/null +++ b/src/com/axiom/settings/preference/deviceinfo/AxiomOSBuildIdPreferenceController.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The LineageOS Project + * Copyright (C) 2019 AxiomOS + * + * 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.axiom.settings.preference.deviceinfo; + +import android.content.Context; +import android.os.SystemProperties; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.R; + +public class AxiomOSBuildIdPreferenceController extends BasePreferenceController { + + private final String KEY_AXIOMOS_BUILD_ID_PROP = "ro.axiom.build_id"; + + public AxiomOSBuildIdPreferenceController(Context context, + String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE_UNSEARCHABLE; + } + + @Override + public CharSequence getSummary() { + return SystemProperties.get(KEY_AXIOMOS_BUILD_ID_PROP, + mContext.getString(R.string.unknown)); + } +} diff --git a/src/com/axiom/settings/preference/deviceinfo/AxiomOSVersionPreferenceController.java b/src/com/axiom/settings/preference/deviceinfo/AxiomOSVersionPreferenceController.java new file mode 100644 index 000000000000..9aa5b7a7d711 --- /dev/null +++ b/src/com/axiom/settings/preference/deviceinfo/AxiomOSVersionPreferenceController.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The LineageOS Project + * Copyright (C) 2019 AxiomOS + * + * 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.axiom.settings.preference.deviceinfo; + +import android.content.Context; +import android.os.SystemProperties; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.R; + +public class AxiomOSVersionPreferenceController extends BasePreferenceController { + + private final String KEY_AXIOMOS_VERSION_PROP = "ro.axiom.version"; + + public AxiomOSVersionPreferenceController(Context context, + String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE_UNSEARCHABLE; + } + + @Override + public CharSequence getSummary() { + return SystemProperties.get(KEY_AXIOMOS_VERSION_PROP, + mContext.getString(R.string.unknown)); + } +} diff --git a/tests/robotests/src/com/android/settings/display/FontSizePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/FontSizePreferenceControllerTest.java index 58e7ccd564b2..53003c91bb93 100644 --- a/tests/robotests/src/com/android/settings/display/FontSizePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/FontSizePreferenceControllerTest.java @@ -43,7 +43,7 @@ public class FontSizePreferenceControllerTest { public void setUp() { mContext = RuntimeEnvironment.application; mController = new FontSizePreferenceController(mContext, TEST_KEY); - mFontSizeArray = mContext.getResources().getStringArray(R.array.entries_font_size); + mFontSizeArray = mContext.getResources().getStringArray(R.array.entries_font_size_percent); } @Test