From fb85a69370578cdb23d2bb091a7736f1fc3d08b9 Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Thu, 9 Jun 2022 11:27:32 +0200 Subject: [PATCH 001/117] Settings: Pass empty lottie resource for quickly open camera animation This lets us hide it properly. Change-Id: I02ac031a835236811b82a7de283335390ffebab9 --- res/drawable/quickly_open_camera.xml | 3 --- res/raw/lottie_quickly_open_camera.json | 0 res/xml/double_tap_power_settings.xml | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 res/drawable/quickly_open_camera.xml create mode 100644 res/raw/lottie_quickly_open_camera.json diff --git a/res/drawable/quickly_open_camera.xml b/res/drawable/quickly_open_camera.xml deleted file mode 100644 index dcbf9f4dc68..00000000000 --- a/res/drawable/quickly_open_camera.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/res/raw/lottie_quickly_open_camera.json b/res/raw/lottie_quickly_open_camera.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/xml/double_tap_power_settings.xml b/res/xml/double_tap_power_settings.xml index 783d045b5d5..a1e133d8e91 100644 --- a/res/xml/double_tap_power_settings.xml +++ b/res/xml/double_tap_power_settings.xml @@ -22,7 +22,7 @@ Date: Tue, 14 Feb 2023 10:05:57 +0200 Subject: [PATCH 002/117] add a toggle for auto-grants of OTHER_SENSORS permission --- res/values/strings_ext.xml | 4 ++++ res/xml/more_security_privacy_settings.xml | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index d80f4360aa0..60a38fd4cef 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -11,4 +11,8 @@ App exploit protection + Allow Sensors permission to apps by default + Sensors is a non-standard permission, apps may malfunction if it’s denied. + A permission prompt will be shown when an app tries to access sensors. Note that some apps may need to be manually restarted after allowing the Sensors permission. + diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml index 56706c3f91a..b22cc9e12ae 100644 --- a/res/xml/more_security_privacy_settings.xml +++ b/res/xml/more_security_privacy_settings.xml @@ -97,6 +97,13 @@ settings:controller= "com.android.settings.sound.MediaControlsLockScreenPreferenceController" /> + + Date: Tue, 14 Feb 2023 10:27:56 +0200 Subject: [PATCH 003/117] add a toggle for camera access from the lock screen --- res/values/strings_ext.xml | 2 ++ res/xml/screen_lock_settings.xml | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 60a38fd4cef..eb282e89d04 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -15,4 +15,6 @@ Sensors is a non-standard permission, apps may malfunction if it’s denied. A permission prompt will be shown when an app tries to access sensors. Note that some apps may need to be manually restarted after allowing the Sensors permission. + Allow camera access when locked + diff --git a/res/xml/screen_lock_settings.xml b/res/xml/screen_lock_settings.xml index 19061d9b855..d2553f61a25 100644 --- a/res/xml/screen_lock_settings.xml +++ b/res/xml/screen_lock_settings.xml @@ -52,4 +52,9 @@ android:key="power_button_instantly_locks" android:title="@string/lockpattern_settings_enable_power_button_instantly_locks" /> + + From b08c1bddea86a35ea75105b8c1ce3f6f30b3ff01 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Tue, 14 Feb 2023 11:23:29 +0200 Subject: [PATCH 004/117] add auto-reboot setting Squashed with: 20d4d3e46ba4a626d6044df499b91c1fc5e5bd96 514f0ddf2adbb7b69b0750806020476cef8ed17e Co-authored-by: Daniel Micay --- res/values/strings_ext.xml | 3 ++ res/xml/exploit_protection_settings.xml | 5 ++ .../security/AutoRebootPrefController.java | 49 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/com/android/settings/security/AutoRebootPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index eb282e89d04..4cfb702a329 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -17,4 +17,7 @@ Allow camera access when locked + Auto reboot + Automatically reboot the device if it hasn\'t been unlocked within the selected duration of time. + diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index 54da29f1394..faaf3b59180 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -5,6 +5,11 @@ android:key="exploit_protection_settings" android:title="@string/exploit_protection_settings"> + + diff --git a/src/com/android/settings/security/AutoRebootPrefController.java b/src/com/android/settings/security/AutoRebootPrefController.java new file mode 100644 index 00000000000..9c00e954e96 --- /dev/null +++ b/src/com/android/settings/security/AutoRebootPrefController.java @@ -0,0 +1,49 @@ +package com.android.settings.security; + +import android.content.Context; +import android.ext.settings.ExtSettings; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.ext.IntSettingPrefController; +import com.android.settings.ext.RadioButtonPickerFragment2; + +import static java.util.concurrent.TimeUnit.DAYS; +import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.MINUTES; + +public class AutoRebootPrefController extends IntSettingPrefController { + + public AutoRebootPrefController(Context ctx, String key) { + super(ctx, key, ExtSettings.AUTO_REBOOT_TIMEOUT); + } + + @Override + public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) { + addFooterPreference(screen, R.string.auto_reboot_footer, + "https://grapheneos.org/features#auto-reboot"); + } + + @Override + protected void getEntries(Entries entries) { + entries.add(R.string.switch_off_text, 0); + entries.add(3, DAYS); + entries.add(2, DAYS); + entries.add(36, HOURS); + entries.add(1, DAYS); + entries.add(18, HOURS); + entries.add(12, HOURS); + entries.add(8, HOURS); + entries.add(4, HOURS); + entries.add(2, HOURS); + entries.add(1, HOURS); + entries.add(30, MINUTES); + entries.add(10, MINUTES); + } + + @Override + protected boolean isCredentialConfirmationRequired() { + return true; + } +} From be2e8e464abcac8d7c4eef04207d03cfe281ebd4 Mon Sep 17 00:00:00 2001 From: r3g_5z Date: Sat, 18 Feb 2023 11:09:31 -0500 Subject: [PATCH 005/117] Add toggle for screenshot timestamp EXIF metadata Signed-off-by: r3g_5z --- res/values/strings_ext.xml | 3 +++ res/xml/more_security_privacy_settings.xml | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 4cfb702a329..813daad375c 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -20,4 +20,7 @@ Auto reboot Automatically reboot the device if it hasn\'t been unlocked within the selected duration of time. + Save screenshot timestamp to EXIF + Enables adding a timestamp to screenshot EXIF metadata + diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml index b22cc9e12ae..c1b98843a45 100644 --- a/res/xml/more_security_privacy_settings.xml +++ b/res/xml/more_security_privacy_settings.xml @@ -104,6 +104,12 @@ android:summaryOff="@string/auto_grant_OTHER_SENSORS_permission_summary_off" settings:boolSettingField="android.ext.settings.ExtSettings AUTO_GRANT_OTHER_SENSORS_PERMISSION"/> + + Date: Fri, 3 Mar 2023 09:53:21 +0200 Subject: [PATCH 006/117] add GNSS SUPL setting --- res/values/strings_ext.xml | 8 ++++ res/xml/location_settings.xml | 5 +++ .../location/GnssSuplPrefController.java | 40 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 src/com/android/settings/location/GnssSuplPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 813daad375c..2ef5fe0ff9d 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -23,4 +23,12 @@ Save screenshot timestamp to EXIF Enables adding a timestamp to screenshot EXIF metadata + Secure User Plane Location (SUPL) + A-GNSS (assisted satellite geolocation) based on nearby cell towers. + + GrapheneOS proxy + Standard server + Off + Will make acquiring location lock significantly slower, especially if PSDS is turned off too + diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml index 3f26d04287e..07c32921981 100644 --- a/res/xml/location_settings.xml +++ b/res/xml/location_settings.xml @@ -69,6 +69,11 @@ android:title="@string/location_services_preference_title" settings:controller="com.android.settings.location.LocationServicesPreferenceController"/> + + Date: Mon, 16 Oct 2023 09:42:40 -0400 Subject: [PATCH 007/117] disable auto confirm PIN toggle by default --- src/com/android/settings/password/ChooseLockPassword.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index eb7d66708b6..e4d53c94d4a 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -1022,9 +1022,6 @@ private void setAutoPinConfirmOption(boolean enabled, int length) { if (enabled && !mIsAlphaMode && isAutoPinConfirmPossible(length)) { mAutoPinConfirmOption.setVisibility(View.VISIBLE); mAutoConfirmSecurityMessage.setVisibility(View.VISIBLE); - if (!mIsAutoPinConfirmOptionSetManually) { - mAutoPinConfirmOption.setChecked(length == MIN_AUTO_PIN_REQUIREMENT_LENGTH); - } } else { mAutoPinConfirmOption.setVisibility(View.GONE); mAutoConfirmSecurityMessage.setVisibility(View.GONE); From 032186846cfb4f318683499addb0f35dbd4f86f9 Mon Sep 17 00:00:00 2001 From: r3g_5z Date: Wed, 15 Mar 2023 21:11:12 -0400 Subject: [PATCH 008/117] remove missing display resolution lottie animation AOSP does not provide these similar to the missing quickly open camera lottie animation Signed-off-by: r3g_5z --- src/com/android/settings/display/ScreenResolutionFragment.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/com/android/settings/display/ScreenResolutionFragment.java b/src/com/android/settings/display/ScreenResolutionFragment.java index d9718f66f93..ae37ab9e1b8 100644 --- a/src/com/android/settings/display/ScreenResolutionFragment.java +++ b/src/com/android/settings/display/ScreenResolutionFragment.java @@ -101,7 +101,6 @@ protected int getPreferenceScreenResId() { @Override protected void addStaticPreferences(PreferenceScreen screen) { - updateIllustrationImage(mImagePreference); screen.addPreference(mImagePreference); final FooterPreference footerPreference = new FooterPreference(screen.getContext()); @@ -223,7 +222,6 @@ protected boolean setDefaultKey(final String key) { } setDisplayMode(width); - updateIllustrationImage(mImagePreference); return true; } From d0b61d815c6ab6d825e83d971841e7228fa9d396 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 24 Jan 2024 19:13:22 +0200 Subject: [PATCH 009/117] add toggle for eSIM support via Google's eSIM LPA package --- res/values/strings_ext.xml | 18 +++ res/xml/network_provider_internet.xml | 8 ++ .../network/GoogleEuiccLpaController.java | 108 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 src/com/android/settings/network/GoogleEuiccLpaController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 2ef5fe0ff9d..9c72938e5aa 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -31,4 +31,22 @@ Off Will make acquiring location lock significantly slower, especially if PSDS is turned off too + eSIM support + +A device restart is required to enable this setting. + + Warning + +"Turning off eSIM support will break the following functionality: + +• adding new eSIMs +• turning existing eSIMs on or off +• removing eSIMs, including from the lock screen (e.g. when eSIM is locked with a forgotten PIN) +• wiping eSIMs during factory reset + +Device will be automatically restarted." + + Restart + Proceed + diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml index 7a333672317..d1acf902104 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -56,6 +56,14 @@ settings:useAdminDisabledSummary="true" settings:controller="com.android.settings.network.MobileNetworkSummaryController" /> + + setEnabled(isChecked)); + b.show(); + + return false; + } +} From b59eb259c45da31a8ae514be454836d1daa2be2f Mon Sep 17 00:00:00 2001 From: r3g_5z Date: Sun, 2 Apr 2023 22:23:41 -0400 Subject: [PATCH 010/117] remote key provisioning server setting Co-authored-by: flawedworld Signed-off-by: r3g_5z --- res/values/strings_ext.xml | 5 +++ res/xml/network_provider_internet.xml | 6 ++++ .../RemoteProvisioningPrefController.java | 36 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/com/android/settings/network/RemoteProvisioningPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 9c72938e5aa..0863ddb28cc 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -49,4 +49,9 @@ Device will be automatically restarted." Restart Proceed + Attestation key provisioning + GrapheneOS proxy + Google server + Off + diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml index d1acf902104..d04f6999b1c 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -126,4 +126,10 @@ android:summary="@string/cellular_security_summary" android:order="30" settings:controller="com.android.settings.network.CellularSecurityPreferenceController"/> + + diff --git a/src/com/android/settings/network/RemoteProvisioningPrefController.java b/src/com/android/settings/network/RemoteProvisioningPrefController.java new file mode 100644 index 00000000000..8617d6bd98c --- /dev/null +++ b/src/com/android/settings/network/RemoteProvisioningPrefController.java @@ -0,0 +1,36 @@ +/* + * 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.network; + +import android.content.Context; +import android.ext.settings.RemoteKeyProvisioningSettings; + +import com.android.settings.R; +import com.android.settings.ext.IntSettingPrefController; + +public class RemoteProvisioningPrefController extends IntSettingPrefController { + + public RemoteProvisioningPrefController(Context ctx, String key) { + super(ctx, key, RemoteKeyProvisioningSettings.SERVER_SETTING); + } + + @Override + protected void getEntries(Entries entries) { + entries.add(R.string.remote_provisioning_enabled_grapheneos_proxy, RemoteKeyProvisioningSettings.GRAPHENEOS_PROXY); + entries.add(R.string.remote_provisioning_enabled_google_server, RemoteKeyProvisioningSettings.STANDARD_SERVER); + } +} From 3259b5cba98f923bcc8088c7fa8783f1baac8ed3 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 6 Apr 2023 12:11:09 +0300 Subject: [PATCH 011/117] add toggle for special access to hardware accelerators by Google apps --- res/values/strings_ext.xml | 15 ++++++ res/xml/special_access.xml | 6 +++ ...oogleSpecialAcceleratorAccessFragment.java | 46 +++++++++++++++++++ ...pecialAcceleratorAccessPrefController.java | 34 ++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java create mode 100644 src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 0863ddb28cc..e6f3d6a9044 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -54,4 +54,19 @@ Device will be automatically restarted." Google server Off + Special access to hardware accelerators for Google apps + Access granted + Access not granted + Grant special access to hardware accelerators to Google apps + +"Some Google apps expect to be able to access hardware accelerators in a special, more capable way than regular apps do. + +Examples of such apps: +• Pixel Camera +• Google Photos +• Google Recorder + +This setting applies to all users on the device." + + diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml index f3a5f3216c7..32867ea63f7 100644 --- a/res/xml/special_access.xml +++ b/res/xml/special_access.xml @@ -231,4 +231,10 @@ android:name="classname" android:value="com.android.settings.Settings$ChangeNfcTagAppsActivity" /> + + diff --git a/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java new file mode 100644 index 00000000000..d681703f4cd --- /dev/null +++ b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java @@ -0,0 +1,46 @@ +package com.android.settings.applications.specialaccess; + +import android.app.ActivityThread; +import android.ext.settings.BoolSetting; +import android.ext.settings.ExtSettings; +import android.os.RemoteException; + +import com.android.internal.util.GoogleCameraUtils; +import com.android.settings.R; +import com.android.settings.ext.BoolSettingFragment; +import com.android.settingslib.widget.FooterPreference; + +public class GoogleSpecialAcceleratorAccessFragment extends BoolSettingFragment { + private static final String TAG = GoogleSpecialAcceleratorAccessFragment.class.getSimpleName(); + + @Override + protected BoolSetting getSetting() { + return ExtSettings.ALLOW_GOOGLE_APPS_SPECIAL_ACCESS_TO_ACCELERATORS; + } + + @Override + protected CharSequence getTitle() { + return resText(R.string.Google_apps_special_accelerator_access_title); + } + + @Override + protected CharSequence getMainSwitchTitle() { + return resText(R.string.Google_apps_special_accelerator_access_main_switch); + } + + @Override + protected void onMainSwitchChanged(boolean state) { + if (GoogleCameraUtils.isCustomSeInfoNeededForAccessToAccelerators(requireContext())) { + try { + ActivityThread.getPackageManager().updateSeInfo(GoogleCameraUtils.PACKAGE_NAME); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + @Override + protected FooterPreference makeFooterPref(FooterPreference.Builder builder) { + return builder.setTitle(R.string.Google_apps_special_accelerator_access_footer).build(); + } +} diff --git a/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java new file mode 100644 index 00000000000..ac7d84fcbb0 --- /dev/null +++ b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java @@ -0,0 +1,34 @@ +package com.android.settings.applications.specialaccess; + +import android.content.Context; +import android.ext.settings.ExtSettings; + +import com.android.settings.R; +import com.android.settings.ext.BoolSettingFragmentPrefController; + +public class GoogleSpecialAcceleratorAccessPrefController extends BoolSettingFragmentPrefController { + + public GoogleSpecialAcceleratorAccessPrefController(Context ctx, String key) { + super(ctx, key, ExtSettings.ALLOW_GOOGLE_APPS_SPECIAL_ACCESS_TO_ACCELERATORS); + } + + @Override + public int getAvailabilityStatus() { + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_Google_apps_can_have_special_access_to_accelerators)) { + return UNSUPPORTED_ON_DEVICE; + } + + return super.getAvailabilityStatus(); + } + + @Override + protected CharSequence getSummaryOn() { + return resText(R.string.Google_apps_special_accelerator_access_summary_granted); + } + + @Override + protected CharSequence getSummaryOff() { + return resText(R.string.Google_apps_special_accelerator_access_summary_not_granted); + } +} From 665015130287626dc34dca8feb79d5a713b4ac36 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 3 May 2023 08:57:01 +0300 Subject: [PATCH 012/117] add GNSS PSDS setting --- res/values/strings_ext.xml | 10 ++++ res/xml/location_settings.xml | 5 ++ .../location/GnssPsdsPrefController.java | 55 +++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 src/com/android/settings/location/GnssPsdsPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index e6f3d6a9044..c10ca2f6d89 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -69,4 +69,14 @@ Examples of such apps: This setting applies to all users on the device." + Predicted Satellite Data Service (PSDS) + +"If PSDS is turned on, static PSDS information files will be downloaded periodically to improve location resolution speed and accuracy. +No query or data is sent to the server. These files contain orbits and statuses of satellites, Earth environmental data and time adjustment information." + + GrapheneOS server + Standard server + Off + Will make acquiring location lock significantly slower, especially if SUPL is turned off too + diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml index 07c32921981..4c99a9ae6a6 100644 --- a/res/xml/location_settings.xml +++ b/res/xml/location_settings.xml @@ -74,6 +74,11 @@ android:title="@string/pref_gnss_supl_title" settings:controller="com.android.settings.location.GnssSuplPrefController"/> + + Date: Wed, 24 May 2023 13:32:14 +0300 Subject: [PATCH 013/117] add connectivity checks setting --- res/values/strings_ext.xml | 10 +++++++ res/xml/network_provider_internet.xml | 6 ++++ .../ConnectivityChecksPrefController.java | 29 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 src/com/android/settings/network/ConnectivityChecksPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index c10ca2f6d89..395d667e9f6 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -79,4 +79,14 @@ No query or data is sent to the server. These files contain orbits and statuses Off Will make acquiring location lock significantly slower, especially if SUPL is turned off too + GrapheneOS server + Standard (Google) server + Off + + Internet connectivity checks + +"Connectivity check is a special empty server request that is made to find out whether the current network has internet connection. +There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. + + diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml index d04f6999b1c..b4becf7c709 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -127,6 +127,12 @@ android:order="30" settings:controller="com.android.settings.network.CellularSecurityPreferenceController"/> + + Date: Wed, 24 May 2023 14:57:01 +0300 Subject: [PATCH 014/117] add common resources for auto-off settings --- res/values/strings_ext.xml | 1 + .../android/settings/ext/AutoOffSetting.java | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/com/android/settings/ext/AutoOffSetting.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 395d667e9f6..0b647684e3e 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -1,6 +1,7 @@ Hardware SKU + Never Enable Enabled diff --git a/src/com/android/settings/ext/AutoOffSetting.java b/src/com/android/settings/ext/AutoOffSetting.java new file mode 100644 index 00000000000..98be94b8589 --- /dev/null +++ b/src/com/android/settings/ext/AutoOffSetting.java @@ -0,0 +1,25 @@ +package com.android.settings.ext; + +import com.android.settings.R; + +import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; + +public class AutoOffSetting { + + public static void getEntries(AbstractListPreferenceController.Entries entries) { + entries.add(R.string.auto_off_never, 0); + entries.add(15, SECONDS); + entries.add(30, SECONDS); + entries.add(1, MINUTES); + entries.add(2, MINUTES); + entries.add(5, MINUTES); + entries.add(10, MINUTES); + entries.add(30, MINUTES); + entries.add(1, HOURS); + entries.add(2, HOURS); + entries.add(4, HOURS); + entries.add(8, HOURS); + } +} From 45f309fbd0d92c1ad058826e15aec1a6cde078ce Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 25 May 2023 16:25:33 +0300 Subject: [PATCH 015/117] add Wi-Fi auto-off setting --- res/values/strings_ext.xml | 2 + res/xml/exploit_protection_settings.xml | 5 +++ .../wifi/WifiAutoOffPrefController.java | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 src/com/android/settings/wifi/WifiAutoOffPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 0b647684e3e..fea4c60d654 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -90,4 +90,6 @@ No query or data is sent to the server. These files contain orbits and statuses There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. + Turn off Wi-Fi automatically + If Wi-Fi is disconnected, it will be turned off after the selected timeout. diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index faaf3b59180..b5f3a0e1dde 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -10,6 +10,11 @@ android:title="@string/auto_reboot_title" settings:controller="com.android.settings.security.AutoRebootPrefController" /> + + diff --git a/src/com/android/settings/wifi/WifiAutoOffPrefController.java b/src/com/android/settings/wifi/WifiAutoOffPrefController.java new file mode 100644 index 00000000000..b8ec16bd69a --- /dev/null +++ b/src/com/android/settings/wifi/WifiAutoOffPrefController.java @@ -0,0 +1,39 @@ +package com.android.settings.wifi; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.ext.settings.ExtSettings; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.ext.AutoOffSetting; +import com.android.settings.ext.IntSettingPrefController; +import com.android.settings.ext.RadioButtonPickerFragment2; + +public class WifiAutoOffPrefController extends IntSettingPrefController { + + public WifiAutoOffPrefController(Context ctx, String key) { + super(ctx, key, ExtSettings.WIFI_AUTO_OFF); + } + + @Override + public int getAvailabilityStatus() { + int r = super.getAvailabilityStatus(); + if (r == AVAILABLE) { + return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI) ? + AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + return r; + } + + @Override + public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) { + addFooterPreference(screen, R.string.wifi_auto_off_footer); + } + + @Override + protected void getEntries(Entries entries) { + AutoOffSetting.getEntries(entries); + } +} From 0e1552b06908bdcc45bfad41c2956c4d7b66511a Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 24 May 2023 15:01:04 +0300 Subject: [PATCH 016/117] add Bluetooth auto-off setting --- res/values/strings_ext.xml | 6 +++ res/xml/exploit_protection_settings.xml | 5 +++ .../BluetoothAutoOffPrefController.java | 39 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index fea4c60d654..dd9938b6b5f 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -92,4 +92,10 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. Turn off Wi-Fi automatically If Wi-Fi is disconnected, it will be turned off after the selected timeout. + + Turn off Bluetooth automatically + +"If there are no connected devices, Bluetooth will turn off after the selected timeout." + + diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index b5f3a0e1dde..bfd7e4dc3d9 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -15,6 +15,11 @@ android:title="@string/wifi_auto_off_title" settings:controller="com.android.settings.wifi.WifiAutoOffPrefController"/> + + diff --git a/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java b/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java new file mode 100644 index 00000000000..14791951802 --- /dev/null +++ b/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java @@ -0,0 +1,39 @@ +package com.android.settings.bluetooth; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.ext.settings.ExtSettings; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.ext.AutoOffSetting; +import com.android.settings.ext.IntSettingPrefController; +import com.android.settings.ext.RadioButtonPickerFragment2; + +public class BluetoothAutoOffPrefController extends IntSettingPrefController { + + public BluetoothAutoOffPrefController(Context ctx, String key) { + super(ctx, key, ExtSettings.BLUETOOTH_AUTO_OFF); + } + + @Override + public int getAvailabilityStatus() { + int r = super.getAvailabilityStatus(); + if (r == AVAILABLE) { + return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH) ? + AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + return r; + } + + @Override + public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) { + addFooterPreference(screen, R.string.bluetooth_auto_off_footer); + } + + @Override + protected void getEntries(Entries entries) { + AutoOffSetting.getEntries(entries); + } +} From e70de75d7fbd851b3d990dd4289833ecab4b7b0e Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 25 May 2023 16:47:42 +0300 Subject: [PATCH 017/117] add exec spawning setting --- res/values/strings_ext.xml | 4 +++ res/xml/exploit_protection_settings.xml | 6 +++- .../security/ExecSpawningFragment.java | 34 +++++++++++++++++++ .../security/ExecSpawningPrefController.java | 13 +++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/security/ExecSpawningFragment.java create mode 100644 src/com/android/settings/security/ExecSpawningPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index dd9938b6b5f..822b659c0bc 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -98,4 +98,8 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. "If there are no connected devices, Bluetooth will turn off after the selected timeout." + Secure app spawning + Use secure app spawning + Launch apps in a more secure way than Android which takes slightly longer and increases memory usage by app processes. + diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index bfd7e4dc3d9..ada50481305 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -24,7 +24,11 @@ android:key="app_exploit_protection_settings" android:title="@string/app_exploit_protection_category"> - + diff --git a/src/com/android/settings/security/ExecSpawningFragment.java b/src/com/android/settings/security/ExecSpawningFragment.java new file mode 100644 index 00000000000..1ab1f744617 --- /dev/null +++ b/src/com/android/settings/security/ExecSpawningFragment.java @@ -0,0 +1,34 @@ +package com.android.settings.security; + +import android.ext.settings.BoolSetting; +import android.ext.settings.ExtSettings; +import android.net.Uri; + +import com.android.settings.R; +import com.android.settings.ext.BoolSettingFragment; +import com.android.settingslib.widget.FooterPreference; + +public class ExecSpawningFragment extends BoolSettingFragment { + + @Override + protected BoolSetting getSetting() { + return ExtSettings.EXEC_SPAWNING; + } + + @Override + protected CharSequence getTitle() { + return getText(R.string.exec_spawning_title); + } + + @Override + protected CharSequence getMainSwitchTitle() { + return getText(R.string.exec_spawning_title_inner); + } + + @Override + protected FooterPreference makeFooterPref(FooterPreference.Builder builder) { + FooterPreference p = builder.setTitle(R.string.exec_spawning_footer).build(); + setFooterPrefLearnMoreUri(p, Uri.parse("https://grapheneos.org/usage#exec-spawning")); + return p; + } +} diff --git a/src/com/android/settings/security/ExecSpawningPrefController.java b/src/com/android/settings/security/ExecSpawningPrefController.java new file mode 100644 index 00000000000..cd2be5cfc71 --- /dev/null +++ b/src/com/android/settings/security/ExecSpawningPrefController.java @@ -0,0 +1,13 @@ +package com.android.settings.security; + +import android.content.Context; +import android.ext.settings.ExtSettings; + +import com.android.settings.ext.BoolSettingFragmentPrefController; + +public class ExecSpawningPrefController extends BoolSettingFragmentPrefController { + + public ExecSpawningPrefController(Context ctx, String key) { + super(ctx, key, ExtSettings.EXEC_SPAWNING); + } +} From f6976f6c865a33fec01d0c36067993ba8035b1d8 Mon Sep 17 00:00:00 2001 From: flawedworld Date: Sun, 25 Jun 2023 13:53:58 +0100 Subject: [PATCH 018/117] Mark all DSU options as unsupported --- src/com/android/settings/development/DSULoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/development/DSULoader.java b/src/com/android/settings/development/DSULoader.java index fede67a7766..957e3d79e6f 100644 --- a/src/com/android/settings/development/DSULoader.java +++ b/src/com/android/settings/development/DSULoader.java @@ -305,7 +305,7 @@ Date getDeviceSPL() { } boolean isSupported() { - boolean supported = true; + boolean supported = false; String cpu = getDeviceCpu(); if (!mCpuAbi.equals(cpu)) { Slog.i(TAG, mCpuAbi + " != " + cpu); From ba85901e3003f721864c9c1ede01a10b506fafe7 Mon Sep 17 00:00:00 2001 From: quh4gko8 <88831734+quh4gko8@users.noreply.github.com> Date: Sat, 1 Jul 2023 07:07:57 +0000 Subject: [PATCH 019/117] Remove "Add users from lock screen" setting --- .../AddUserWhenLockedPreferenceController.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java index 2dc5b2d60d6..315be794607 100644 --- a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java +++ b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java @@ -57,19 +57,7 @@ public void updateState(Preference preference) { @Override public int getAvailabilityStatus() { - if (!mUserCaps.isAdmin()) { - return DISABLED_FOR_USER; - } else if (android.multiuser.Flags.newMultiuserSettingsUx()) { - if (mUserCaps.mDisallowAddUser && !mUserCaps.mDisallowAddUserSetByAdmin) { - return DISABLED_FOR_USER; - } else { - return AVAILABLE; - } - } else if (mUserCaps.disallowAddUser() || mUserCaps.disallowAddUserSetByAdmin()) { - return DISABLED_FOR_USER; - } else { - return mUserCaps.mUserSwitcherEnabled ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; - } + return UNSUPPORTED_ON_DEVICE; } @Override From b4d0b354805a9a0044393dcade594fc6c8a780df Mon Sep 17 00:00:00 2001 From: quh4gko8 <88831734+quh4gko8@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:53:04 +0000 Subject: [PATCH 020/117] Factor out common code for reading/writing UserManager restrictions --- .../settings/users/UserDetailsSettings.java | 2 + .../settings/users/UserRestrictions.java | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/com/android/settings/users/UserRestrictions.java diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java index ec4a4ff2558..aa7b95e735d 100644 --- a/src/com/android/settings/users/UserDetailsSettings.java +++ b/src/com/android/settings/users/UserDetailsSettings.java @@ -102,6 +102,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment @VisibleForTesting /** The user being studied (not the user doing the studying). */ UserInfo mUserInfo; + private UserRestrictions userRestrictions; @Override public int getMetricsCategory() { @@ -344,6 +345,7 @@ void initialize(Context context, Bundle arguments) { boolean isNewUser = arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false); mUserInfo = mUserManager.getUserInfo(userId); + userRestrictions = new UserRestrictions(mUserManager, mUserInfo); mSwitchUserPref = findPreference(KEY_SWITCH_USER); mPhonePref = findPreference(KEY_ENABLE_TELEPHONY); diff --git a/src/com/android/settings/users/UserRestrictions.java b/src/com/android/settings/users/UserRestrictions.java new file mode 100644 index 00000000000..7db3161c201 --- /dev/null +++ b/src/com/android/settings/users/UserRestrictions.java @@ -0,0 +1,38 @@ +package com.android.settings.users; + +import android.content.pm.UserInfo; +import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; + +import java.util.List; + +final class UserRestrictions { + + final UserManager userManager; + final UserInfo userInfo; + + UserRestrictions(UserManager userManager, UserInfo userInfo) { + this.userManager = userManager; + this.userInfo = userInfo; + } + + boolean isSet(String restrictionKey) { + final boolean isSetFromUser = userManager.hasUserRestriction(restrictionKey, userInfo.getUserHandle()); + if (userInfo.isGuest()) { + return isSetFromUser || userManager.getDefaultGuestRestrictions().getBoolean(restrictionKey); + } + + return isSetFromUser; + } + + void set(String restrictionKey, boolean enableRestriction) { + if (userInfo.isGuest()) { + Bundle defaultGuestRestrictions = userManager.getDefaultGuestRestrictions(); + defaultGuestRestrictions.putBoolean(restrictionKey, enableRestriction); + userManager.setDefaultGuestRestrictions(defaultGuestRestrictions); + } else { + userManager.setUserRestriction(restrictionKey, enableRestriction, userInfo.getUserHandle()); + } + } +} From def9671518bd3d2bc1fd682fe82e93260d704be5 Mon Sep 17 00:00:00 2001 From: Pratyush Date: Sat, 3 Sep 2022 15:52:37 +0530 Subject: [PATCH 021/117] UserManager enable "install available apps" allowing adding (installed) apps from (owner) user manager ui. --- src/com/android/settings/users/UserDetailsSettings.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java index aa7b95e735d..d4317bd614b 100644 --- a/src/com/android/settings/users/UserDetailsSettings.java +++ b/src/com/android/settings/users/UserDetailsSettings.java @@ -78,7 +78,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment private static final int DIALOG_CONFIRM_GRANT_ADMIN = 7; /** Whether to enable the app_copying fragment. */ - private static final boolean SHOW_APP_COPYING_PREF = false; + private static final boolean SHOW_APP_COPYING_PREF = true; private static final int MESSAGE_PADDING = 20; private UserManager mUserManager; @@ -424,7 +424,6 @@ void initialize(Context context, Bundle arguments) { mPhonePref.setChecked(!mUserManager.hasUserRestriction( UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId))); mRemoveUserPref.setTitle(R.string.user_remove_user); - removePreference(KEY_APP_COPYING); } // Remove preference KEY_REMOVE_USER if DISALLOW_REMOVE_USER restriction is set From 3859b0173b832a0e43811658ebc456cec4aab219 Mon Sep 17 00:00:00 2001 From: quh4gko8 <88831734+quh4gko8@users.noreply.github.com> Date: Thu, 20 Jul 2023 05:07:49 +0000 Subject: [PATCH 022/117] UserManager settings for apps installs and updates --- res/values/strings_ext.xml | 11 ++ res/xml/user_details_settings.xml | 4 + .../users/UserAppsInstallSettings.java | 173 ++++++++++++++++++ .../settings/users/UserDetailsSettings.java | 11 ++ 4 files changed, 199 insertions(+) create mode 100644 src/com/android/settings/users/UserAppsInstallSettings.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 822b659c0bc..66f0fa23f23 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -102,4 +102,15 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. Use secure app spawning Launch apps in a more secure way than Android which takes slightly longer and increases memory usage by app processes. + + App installs and updates + + Enabled + Enabled for first party sources + Disabled + + Enable app installs and updates + Enable app installs and updates from first party sources only + Disable app installs and updates + diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml index 8e15d14bf5a..2cd01c1ef7d 100644 --- a/res/xml/user_details_settings.xml +++ b/res/xml/user_details_settings.xml @@ -33,6 +33,10 @@ android:key="app_and_content_access" android:icon="@drawable/ic_lock_closed" android:title="@string/user_restrictions_title" /> + getCandidates() { + Context ctx = requireContext(); + ArrayList candidates = new ArrayList<>(3); + if (!userRestrictions.userInfo.isGuest()) { + candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_enabled), + ctx.getString(R.string.user_app_install_enabled_desc), + INSTALL_ENABLED, true)); + } + candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_enabled_first_party_sources), + ctx.getString(R.string.user_app_install_enabled_first_party_sources_desc), + INSTALL_FIRST_PARTY_ENABLED, true)); + candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_disabled), + ctx.getString(R.string.user_app_install_disabled_desc), + INSTALL_DISABLED, true)); + return candidates; + } + + @Override + public void bindPreferenceExtra(SelectorWithWidgetPreference pref, String key, CandidateInfo info, + String defaultKey, String systemDefaultKey) { + pref.setSingleLineTitle(false); + + if (info instanceof CandidateInfoExtra) { + var cie = (CandidateInfoExtra) info; + pref.setSummary(cie.loadSummary()); + } + } + + @Override + protected String getDefaultKey() { + return getCurrentInstallRestriction(userRestrictions); + } + + @Override + protected boolean setDefaultKey(String key) { + if (key == null) { + return false; + } + + switch (key) { + case INSTALL_ENABLED: + if (userRestrictions.userInfo.isGuest()) { + return false; + } + userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false); + userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false); + return true; + case INSTALL_FIRST_PARTY_ENABLED: + userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false); + if (!userRestrictions.userInfo.isGuest()) { + userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true); + } + return true; + case INSTALL_DISABLED: + userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, true); + if (!userRestrictions.userInfo.isGuest()) { + userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true); + } + return true; + default: + return false; + } + } + + @Override + public int getMetricsCategory() { + return METRICS_CATEGORY_UNKNOWN; + } + + @Override + public void onResume() { + super.onResume(); + updateCandidates(); + } +} diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java index d4317bd614b..52b8e6f7aa5 100644 --- a/src/com/android/settings/users/UserDetailsSettings.java +++ b/src/com/android/settings/users/UserDetailsSettings.java @@ -66,6 +66,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access"; private static final String KEY_APP_COPYING = "app_copying"; + private static final String KEY_APP_INSTALLS = "app_installs"; + /** Integer extra containing the userId to manage */ static final String EXTRA_USER_ID = "user_id"; @@ -98,6 +100,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment Preference mRemoveUserPref; @VisibleForTesting TwoStatePreference mGrantAdminPref; + Preference mAppsInstallsPref; @VisibleForTesting /** The user being studied (not the user doing the studying). */ @@ -135,6 +138,8 @@ public void onResume() { if (mUserInfo.isGuest() && mGuestUserAutoCreated) { mRemoveUserPref.setEnabled((mUserInfo.flags & UserInfo.FLAG_INITIALIZED) != 0); } + mAppsInstallsPref.setSummary(UserAppsInstallSettings.getDescription( + requireContext(), userRestrictions)); } @Override @@ -175,6 +180,9 @@ public boolean onPreferenceClick(Preference preference) { } else if (preference == mAppCopyingPref) { openAppCopyingScreen(); return true; + } else if (preference == mAppsInstallsPref) { + UserAppsInstallSettings.launch(preference, mUserInfo.id); + return true; } return false; } @@ -355,6 +363,7 @@ void initialize(Context context, Bundle arguments) { mGrantAdminPref = findPreference(KEY_GRANT_ADMIN); mGrantAdminPref.setChecked(mUserInfo.isAdmin()); + mAppsInstallsPref = findPreference(KEY_APP_INSTALLS); mSwitchUserPref.setVisible(mUserCaps.mUserSwitchingUiEnabled); @@ -391,6 +400,7 @@ void initialize(Context context, Bundle arguments) { removePreference(KEY_REMOVE_USER); removePreference(KEY_APP_AND_CONTENT_ACCESS); removePreference(KEY_APP_COPYING); + removePreference(KEY_APP_INSTALLS); } else { if (!Utils.isVoiceCapable(context)) { // no telephony removePreference(KEY_ENABLE_TELEPHONY); @@ -435,6 +445,7 @@ void initialize(Context context, Bundle arguments) { } mRemoveUserPref.setOnPreferenceClickListener(this); + mAppsInstallsPref.setOnPreferenceClickListener(this); mPhonePref.setOnPreferenceChangeListener(this); mGrantAdminPref.setOnPreferenceChangeListener(this); mAppAndContentAccessPref.setOnPreferenceClickListener(this); From f390dd7125479f7a39c28ed5772b16c11391d1d1 Mon Sep 17 00:00:00 2001 From: quh4gko8 <88831734+quh4gko8@users.noreply.github.com> Date: Tue, 13 Jun 2023 12:19:41 +0000 Subject: [PATCH 023/117] UserManager settings for running in background --- res/values/strings_ext.xml | 2 ++ res/xml/user_details_settings.xml | 4 ++++ .../android/settings/users/UserDetailsSettings.java | 13 +++++++++++++ 3 files changed, 19 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 66f0fa23f23..14836ee79e2 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -112,5 +112,7 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. Enable app installs and updates Enable app installs and updates from first party sources only Disable app installs and updates + + Allow running in background diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml index 2cd01c1ef7d..5f6df097ec9 100644 --- a/res/xml/user_details_settings.xml +++ b/res/xml/user_details_settings.xml @@ -25,6 +25,10 @@ android:key="user_grant_admin" android:icon="@drawable/ic_admin_panel_settings" android:title="@string/user_grant_admin" /> + Date: Wed, 26 Jul 2023 09:45:29 +0000 Subject: [PATCH 024/117] Disable app copying preference when the user has DISALLOW_INSTALL_APPS restriction --- src/com/android/settings/users/UserDetailsSettings.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java index 9de016ba353..d3d4692da50 100644 --- a/src/com/android/settings/users/UserDetailsSettings.java +++ b/src/com/android/settings/users/UserDetailsSettings.java @@ -143,6 +143,7 @@ public void onResume() { } mAppsInstallsPref.setSummary(UserAppsInstallSettings.getDescription( requireContext(), userRestrictions)); + mAppCopyingPref.setEnabled(!userRestrictions.isSet(UserManager.DISALLOW_INSTALL_APPS)); } @Override From 1d5ecf9c75e3bfa360cc872734e9d82851df5b0d Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 2 Mar 2024 11:24:34 +0200 Subject: [PATCH 025/117] add support for disabling non-system apps --- .../settings/spa/app/appinfo/AppDisableButton.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt b/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt index 555e9f14c61..07d583cde30 100644 --- a/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt +++ b/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt @@ -31,6 +31,7 @@ import com.android.settingslib.spa.widget.dialog.AlertDialogButton import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager import com.android.settingslib.spaprivileged.framework.common.userManager +import com.android.settingslib.spaprivileged.model.app.installed import com.android.settingslib.spaprivileged.model.app.isDisabledUntilUsed import com.android.settingslib.Utils as SettingsLibUtils @@ -47,7 +48,7 @@ class AppDisableButton( @Composable fun getActionButton(app: ApplicationInfo): ActionButton? { - if (!app.isSystemApp) return null + if (!app.installed) return null return when { app.enabled && !app.isDisabledUntilUsed -> { @@ -62,6 +63,8 @@ class AppDisableButton( * Gets whether a package can be disabled. */ private fun ApplicationInfo.canBeDisabled(): Boolean = when { + !isSystemApp -> appButtonRepository.isAllowUninstallOrArchive(context, this) + // Try to prevent the user from bricking their phone by not allowing disabling of apps // signed with the system certificate. isSignedWithPlatformKey -> false @@ -98,7 +101,12 @@ class AppDisableButton( // Currently we apply the same device policy for both the uninstallation and disable // button. if (!appButtonRepository.isUninstallBlockedByAdmin(app)) { - dialogPresenter.open() + if (app.isSystemApp) { + dialogPresenter.open() + } else { + packageInfoPresenter.disable() + } + } } } From aa92acb6fe7adeffff84d7cbf68db4f1ee534dad Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 2 Mar 2024 12:29:45 +0200 Subject: [PATCH 026/117] don't show "More options" button in App info uninstall dialog That button opens app's App info screen. --- src/com/android/settings/spa/app/AppUtil.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/spa/app/AppUtil.kt b/src/com/android/settings/spa/app/AppUtil.kt index 64da61380f5..7b319aeddeb 100644 --- a/src/com/android/settings/spa/app/AppUtil.kt +++ b/src/com/android/settings/spa/app/AppUtil.kt @@ -37,6 +37,7 @@ fun Context.startUninstallActivity( val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply { putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers) + putExtra(Intent.EXTRA_UNINSTALL_SHOW_MORE_OPTIONS_BUTTON, false) } startActivityAsUser(intent, userHandle) -} \ No newline at end of file +} From ed7e0c8363f91891067a9f15062fcee92569496a Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 2 Mar 2024 11:19:46 +0200 Subject: [PATCH 027/117] add Storage Scopes link to the "App info" screen --- res/values/strings.xml | 2 ++ .../spa/app/appinfo/AppInfoSettings.kt | 3 +- .../app/appinfo/AppStorageScopesPreference.kt | 32 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt diff --git a/res/values/strings.xml b/res/values/strings.xml index 22c54009e3b..f8b417d9a59 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13936,4 +13936,6 @@ Sandboxed Google Play Sandboxed Google Play (work profile) + + Storage Scopes diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 78fb8df123b..46b29d7915a 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -147,6 +147,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { AppAllServicesPreference(app) AppNotificationPreference(app) AppPermissionPreference(app) + AppStorageScopesPreference(app) AppStoragePreference(app) InstantAppDomainsPreference(app) AppDataUsagePreference(app) @@ -181,4 +182,4 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { } fun isArchivingEnabled(featureFlags: PmFeatureFlags) = - featureFlags.archiving() || Flags.appArchiving() \ No newline at end of file + featureFlags.archiving() || Flags.appArchiving() diff --git a/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt b/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt new file mode 100644 index 00000000000..cbcd8944f56 --- /dev/null +++ b/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt @@ -0,0 +1,32 @@ +package com.android.settings.spa.app.appinfo + +import android.app.StorageScope +import android.content.pm.ApplicationInfo +import android.content.pm.GosPackageState +import android.content.pm.GosPackageStateFlag +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spaprivileged.model.app.userHandle +import com.android.settingslib.spaprivileged.model.app.userId + +@Composable +fun AppStorageScopesPreference(app: ApplicationInfo) { + val pkgName = app.packageName + if (!GosPackageState.get(pkgName, app.userId).hasFlag(GosPackageStateFlag.STORAGE_SCOPES_ENABLED)) { + return + } + + val context = LocalContext.current + + Preference(object : PreferenceModel { + override val title = stringResource(R.string.storage_scopes) + override val onClick = { + val intent = StorageScope.createConfigActivityIntent(pkgName) + context.startActivityAsUser(intent, app.userHandle) + } + }) +} From 19d63272ed03dc48497a9885eb74e1dfe23e1bff Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 2 Mar 2024 11:20:31 +0200 Subject: [PATCH 028/117] add Storage Scopes link to "All files access" screen --- .../spa/app/specialaccess/AllFilesAccess.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt b/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt index f6c08c0ca7c..6dba4817a2a 100644 --- a/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt +++ b/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt @@ -18,11 +18,19 @@ package com.android.settings.spa.app.specialaccess import android.Manifest import android.app.AppOpsManager +import android.app.StorageScope import android.app.settings.SettingsEnums import android.content.Context +import android.content.pm.PackageInfo +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import com.android.settings.R import com.android.settings.overlay.FeatureFactory.Companion.featureFactory +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spaprivileged.model.app.AppOps +import com.android.settingslib.spaprivileged.model.app.userHandle import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider @@ -54,4 +62,18 @@ class AllFilesAccessListModel(context: Context) : AppOpPermissionListModel(conte } featureFactory.metricsFeatureProvider.action(context, category, "") } + + @Composable + override fun extContent(record: AppOpPermissionRecord, pkgInfo: PackageInfo) { + val context = LocalContext.current + + Preference(object : PreferenceModel { + override val title = stringResource(R.string.storage_scopes) + override val onClick = { + val app = record.app + val i = StorageScope.createConfigActivityIntent(app.packageName) + context.startActivityAsUser(i, app.userHandle) + } + }) + } } From be25069de5b1b1c6457d4213d5d8d4e60668aa7f Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Fri, 8 Jul 2022 13:40:22 +0300 Subject: [PATCH 029/117] add OBB access toggle to "Install unknown apps" screen --- res/values/strings.xml | 3 ++ .../app/specialaccess/InstallUnknownApps.kt | 52 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index f8b417d9a59..cdca65e9a1e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13938,4 +13938,7 @@ Sandboxed Google Play (work profile) Storage Scopes + + Allow access to Android/obb folder + Required for installation of some large apps (mostly games) that use OBB expansion files diff --git a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt index d6fe7160dbf..0a3d5219bc9 100644 --- a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt +++ b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt @@ -22,10 +22,18 @@ import android.app.AppOpsManager import android.app.AppOpsManager.MODE_DEFAULT import android.content.Context import android.content.pm.ApplicationInfo +import android.content.pm.GosPackageState +import android.content.pm.GosPackageStateFlag +import android.content.pm.PackageInfo import android.os.UserManager import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import com.android.settings.R import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle +import com.android.settingslib.spa.widget.preference.SwitchPreference +import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import com.android.settingslib.spaprivileged.model.app.AppOps import com.android.settingslib.spaprivileged.model.app.AppOpsController import com.android.settingslib.spaprivileged.model.app.AppRecord @@ -44,7 +52,26 @@ object InstallUnknownAppsListProvider : TogglePermissionAppListProvider { data class InstallUnknownAppsRecord( override val app: ApplicationInfo, val appOpsController: AppOpsController, -) : AppRecord +) : AppRecord { + val isObbFlagSet = mutableStateOf(isObbFlagSet()) + + fun isObbFlagSet(): Boolean { + return GosPackageState.get(app.packageName, app.userId).hasFlag(GosPackageStateFlag.ALLOW_ACCESS_TO_OBB_DIRECTORY) + } + + fun setObbFlagState(state: Boolean): Boolean { + GosPackageState.edit(app.packageName, app.userId).run { + setFlagState(GosPackageStateFlag.ALLOW_ACCESS_TO_OBB_DIRECTORY, state) + killUidAfterApply() + if (apply()) { + isObbFlagSet.value = state + return true + } else { + return false + } + } + } +} class InstallUnknownAppsListModel(private val context: Context) : TogglePermissionAppListModel { @@ -84,6 +111,29 @@ class InstallUnknownAppsListModel(private val context: Context) : override fun setAllowed(record: InstallUnknownAppsRecord, newAllowed: Boolean) { record.appOpsController.setAllowed(newAllowed) + if (!newAllowed) { + record.setObbFlagState(false) + } + } + + @Composable + override fun extContent(record: InstallUnknownAppsRecord, pkgInfo: PackageInfo) { + val context = LocalContext.current + + SwitchPreference(object : SwitchPreferenceModel { + override val title = stringResource(R.string.allow_access_to_obb_directory_title) + override val summary = { + context.getString(R.string.allow_access_to_obb_directory_summary) + } + + override val checked = { + record.isObbFlagSet.value + } + override val onCheckedChange = { newChecked: Boolean -> + record.setObbFlagState(newChecked) + Unit + } + }) } companion object { From 0688fe1a5c4becdac2dcbba5963ed969c2b4dc26 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 2 Mar 2024 11:22:22 +0200 Subject: [PATCH 030/117] add Contact Scopes link to the "App info" screen --- res/values/strings_ext.xml | 2 ++ .../app/appinfo/AppContactScopesPreference.kt | 32 +++++++++++++++++++ .../spa/app/appinfo/AppInfoSettings.kt | 1 + 3 files changed, 35 insertions(+) create mode 100644 src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 14836ee79e2..bd500ec6ced 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -80,6 +80,8 @@ No query or data is sent to the server. These files contain orbits and statuses Off Will make acquiring location lock significantly slower, especially if SUPL is turned off too + Contact Scopes + GrapheneOS server Standard (Google) server Off diff --git a/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt b/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt new file mode 100644 index 00000000000..be4cf6fadbc --- /dev/null +++ b/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt @@ -0,0 +1,32 @@ +package com.android.settings.spa.app.appinfo + +import android.content.pm.ApplicationInfo +import android.content.pm.GosPackageState +import android.content.pm.GosPackageStateFlag +import android.ext.cscopes.ContactScopesApi +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spaprivileged.model.app.userHandle +import com.android.settingslib.spaprivileged.model.app.userId + +@Composable +fun AppContactScopesPreference(app: ApplicationInfo) { + val pkgName = app.packageName + if (!GosPackageState.get(pkgName, app.userId).hasFlag(GosPackageStateFlag.CONTACT_SCOPES_ENABLED)) { + return + } + + val context = LocalContext.current + + Preference(object : PreferenceModel { + override val title = stringResource(R.string.contact_scopes) + override val onClick = { + val intent = ContactScopesApi.createConfigActivityIntent(pkgName) + context.startActivityAsUser(intent, app.userHandle) + } + }) +} diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 46b29d7915a..cfe8f368bf5 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -148,6 +148,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { AppNotificationPreference(app) AppPermissionPreference(app) AppStorageScopesPreference(app) + AppContactScopesPreference(app) AppStoragePreference(app) InstantAppDomainsPreference(app) AppDataUsagePreference(app) From e339ef81febacf161254d8dc724ec4dd9017a048 Mon Sep 17 00:00:00 2001 From: empratyush Date: Mon, 20 Jun 2022 22:16:29 +0300 Subject: [PATCH 031/117] Reverse Wireless Charging UI --- Android.bp | 1 + res/values/strings.xml | 3 + res/xml/power_usage_summary.xml | 6 ++ .../BatterySharePreferenceController.java | 99 +++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 src/com/android/settings/display/BatterySharePreferenceController.java diff --git a/Android.bp b/Android.bp index 907ff12bc86..420bf5ab07c 100644 --- a/Android.bp +++ b/Android.bp @@ -93,6 +93,7 @@ android_library { // Settings dependencies "FingerprintManagerInteractor", "MediaDrmSettingsFlagsLib", + "ReverseWirelessCharging", "Settings-change-ids", "SettingsLib", "SettingsLibActivityEmbedding", diff --git a/res/values/strings.xml b/res/values/strings.xml index cdca65e9a1e..305f3e12bb9 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13941,4 +13941,7 @@ Allow access to Android/obb folder Required for installation of some large apps (mostly games) that use OBB expansion files + + Charge other devices by placing them on the back of your phone + Battery share diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml index 21a836d6d9a..c86ff0ac78f 100644 --- a/res/xml/power_usage_summary.xml +++ b/res/xml/power_usage_summary.xml @@ -70,6 +70,12 @@ android:summary="@string/battery_percentage_description" settings:controller="com.android.settings.display.BatteryPercentagePreferenceController" /> + + update()); + } + }; + + + public BatterySharePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mContext = context; + wirelessCharger = ReverseWirelessCharger.getInstance(); + } + + public boolean isPlugged(Context context) { + Intent intent = context.registerReceiver(null, + new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); + return plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + update(); + } + + @Override + public String getPreferenceKey() { + return KEY_BATTERY_SHARE; + } + + private void update() { + if (mPreference == null) return; + boolean enabled = !isPlugged(mContext) && wirelessCharger.isRtxSupported(); + mPreference.setEnabled(enabled); + ((TwoStatePreference) mPreference).setChecked(wirelessCharger.isRtxModeOn()); + } + + @Override + public int getAvailabilityStatus() { + return wirelessCharger.isRtxSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public void updateState(Preference preference) { + update(); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + wirelessCharger.setRtxMode((Boolean) newValue); + return true; + } + + @Override + public void onStart() { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + mContext.registerReceiver(mBroadcastReceiver, filter); + } + + @Override + public void onStop() { + mContext.unregisterReceiver(mBroadcastReceiver); + } +} From 9c1f06bd9513f16b8cbb693115260f2258794828 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Fri, 15 Sep 2023 10:03:16 +0300 Subject: [PATCH 032/117] hide the "Storage manager" toggle from Storage screen "Storage manager" is supposed to automatically remove backed up photos and videos. This functionality is not implemented in AOSP, i.e. this toggle doesn't actually work. --- res/values/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index 129ea31b004..9f8460ba664 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -612,7 +612,7 @@ content://com.android.providers.media.documents/root/others_root - true + false Allow running in background + "Warning: enabling this setting might cause some apps to stop working. + diff --git a/src/com/android/settings/ext/AppPrefUtils.java b/src/com/android/settings/ext/AppPrefUtils.java new file mode 100644 index 00000000000..3ae426bf36f --- /dev/null +++ b/src/com/android/settings/ext/AppPrefUtils.java @@ -0,0 +1,14 @@ +package com.android.settings.ext; + +import android.content.Context; + +import com.android.settings.R; + +import androidx.annotation.StringRes; + +public class AppPrefUtils { + + public static String getFooterForDefaultHardeningSetting(Context ctx, @StringRes int baseText) { + return ctx.getString(R.string.app_exploit_protection_default_value_warning) + "\n\n" + ctx.getString(baseText); + } +} From e438cfc8fa389c52ce35524ddfdf3dc82d23c2bd Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:44:08 +0200 Subject: [PATCH 035/117] add base class for App info single-choice fragments --- .../appinfo/RadioButtonAppInfoFragment.java | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java diff --git a/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java b/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java new file mode 100644 index 00000000000..26fa78beb4d --- /dev/null +++ b/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java @@ -0,0 +1,228 @@ +package com.android.settings.applications.appinfo; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.net.Uri; +import android.os.Bundle; +import android.util.TypedValue; + +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreferenceCompat; + +import com.android.settings.applications.AppInfoWithHeader; +import com.android.settings.applications.SpacePreference; +import com.android.settingslib.widget.FooterPreference; +import com.android.settingslib.widget.SelectorWithWidgetPreference; + +import java.util.Collections; +import java.util.List; + +public abstract class RadioButtonAppInfoFragment extends AppInfoWithHeader implements SelectorWithWidgetPreference.OnClickListener { + + public static class Entry { + public final int id; + public CharSequence title; + @Nullable + public CharSequence summary; + public boolean isChecked; + public boolean isEnabled; + + public Entry(int id, CharSequence title, @Nullable CharSequence summary, boolean isChecked, boolean isEnabled) { + this.id = id; + this.title = title; + this.summary = summary; + this.isChecked = isChecked; + this.isEnabled = isEnabled; + } + } + + public static Entry createEntry(int id, CharSequence title) { + return new Entry(id, title, null, false, true); + } + + public Entry createEntry(int id, @StringRes int title) { + return createEntry(id, getText(title)); + } + + public Entry createEntry(@StringRes int title) { + return createEntry(title, title); + } + + public abstract Entry[] getEntries(); + + public boolean hasFooter() { + return true; + } + + public abstract void updateFooter(FooterPreference fp); + + public void setLearnMoreLink(FooterPreference p, String url) { + p.setLearnMoreAction(v -> { + var i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(i); + }); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getPrefContext()); + setPreferenceScreen(screen); + requireActivity().setTitle(getTitle()); + } + + protected abstract CharSequence getTitle(); + + @Nullable + private SelectorWithWidgetPreference[] radioButtons; + @Nullable + private FooterPreference footer; + + private Preference[] extraPrefs; + + @Override + protected boolean refreshUi() { + Entry[] entries = getEntries(); + int entryCnt = entries.length; + + Context ctx = getPrefContext(); + PreferenceScreen screen = getPreferenceScreen(); + + if (radioButtons == null || radioButtons.length != entryCnt) { + if (radioButtons != null) { + for (Preference p : radioButtons) { + screen.removePreference(p); + } + } + + radioButtons = new SelectorWithWidgetPreference[entryCnt]; + + for (int i = 0; i < entryCnt; ++i) { + var p = new SelectorWithWidgetPreference(ctx); + p.setOnClickListener(this); + screen.addPreference(p); + radioButtons[i] = p; + } + } + + for (int i = 0; i < entryCnt; ++i) { + SelectorWithWidgetPreference p = radioButtons[i]; + Entry e = entries[i]; + p.setKey(Integer.toString(e.id)); + p.setTitle(e.title); + p.setSummary(e.summary); + p.setEnabled(e.isEnabled); + p.setChecked(e.isChecked); + } + + List extraPrefModels = getExtraPrefModels(); + + if (extraPrefs == null) { + if (extraPrefModels.isEmpty()) { + extraPrefs = new Preference[0]; + } else { + var spacer = new SpacePreference(ctx, null); + int h = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 48f, ctx.getResources().getDisplayMetrics()); + spacer.setHeight(h); + screen.addPreference(spacer); + + extraPrefs = new Preference[extraPrefModels.size()]; + for (int i = 0; i < extraPrefs.length; ++i) { + PrefModel pm = extraPrefModels.get(i); + Preference p; + if (pm instanceof LinkPrefModel lpm) { + p = new Preference(ctx); + p.setOnPreferenceClickListener(pref -> { + lpm.onClick.run(); + return true; + }); + } else if (pm instanceof TogglePrefModel tpm) { + p = new SwitchPreferenceCompat(ctx); + p.setOnPreferenceChangeListener(tpm.onChangeListener); + } else { + throw new IllegalArgumentException(pm.toString()); + } + p.setKey("extra_pref_" + i); + screen.addPreference(p); + extraPrefs[i] = p; + } + } + } + for (int i = 0; i < extraPrefs.length; ++i) { + PrefModel pm = extraPrefModels.get(i); + Preference p = extraPrefs[i]; + if (pm instanceof TogglePrefModel tpm) { + var sp = (SwitchPreferenceCompat) p; + sp.setChecked(tpm.isChecked); + } + p.setTitle(pm.title); + p.setSummary(pm.summary); + p.setEnabled(pm.isEnabled); + } + + if (hasFooter()) { + if (footer == null) { + footer = new FooterPreference(ctx); + screen.addPreference(footer); + } + updateFooter(footer); + } else { + if (footer != null) { + screen.removePreference(footer); + footer = null; + } + } + + return true; + } + + public static class PrefModel { + public CharSequence title; + public CharSequence summary; + public boolean isEnabled = true; + } + + public static class LinkPrefModel extends PrefModel { + public Runnable onClick; + } + + public static class TogglePrefModel extends PrefModel { + public boolean isChecked; + public Preference.OnPreferenceChangeListener onChangeListener; + } + + protected List getExtraPrefModels() { + return Collections.emptyList(); + } + + @Override + public final void onRadioButtonClicked(SelectorWithWidgetPreference emiter) { + int id = Integer.parseInt(emiter.getKey()); + onEntrySelected(id); + if (!refreshUi()) { + setIntentAndFinish(true); + } + } + + public abstract void onEntrySelected(int id); + + @Override + protected AlertDialog createDialog(int id, int errorCode) { + return null; + } + + @Override + public int getMetricsCategory() { + return METRICS_CATEGORY_UNKNOWN; + } + + protected ApplicationInfo getAppInfo() { + return mPackageInfo.applicationInfo; + } +} From 2d0afd813364d7e98694344cb51f800ba4dd540e Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:44:23 +0200 Subject: [PATCH 036/117] infrastructure for AppSwitch UIs Squashed with 28baa8dcbf5a0d285d8bf3852b723beaa290a973 by quh4gko8 <88831734+quh4gko8@users.noreply.github.com> --- res/values/strings_app_exploit_protection.xml | 37 +++ .../settings/applications/AswAdapter.kt | 88 +++++++ .../applications/AswAppInfoFragment.java | 228 ++++++++++++++++++ .../AswAppListPrefController.java | 27 +++ .../AswExploitProtectionFragment.java | 44 ++++ .../spa/app/appinfo/AppInfoSettings.kt | 3 + .../settings/spa/app/appinfo/AswAppList.kt | 101 ++++++++ .../settings/spa/app/appinfo/AswPreference.kt | 27 +++ .../spa/app/appinfo/PackageInfoPresenter.kt | 5 +- 9 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 res/values/strings_app_exploit_protection.xml create mode 100644 src/com/android/settings/applications/AswAdapter.kt create mode 100644 src/com/android/settings/applications/AswAppInfoFragment.java create mode 100644 src/com/android/settings/applications/AswAppListPrefController.java create mode 100644 src/com/android/settings/applications/AswExploitProtectionFragment.java create mode 100644 src/com/android/settings/spa/app/appinfo/AswAppList.kt create mode 100644 src/com/android/settings/spa/app/appinfo/AswPreference.kt diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml new file mode 100644 index 00000000000..5081ee0a037 --- /dev/null +++ b/res/values/strings_app_exploit_protection.xml @@ -0,0 +1,37 @@ + + + Exploit protection + + Allowed + Blocked + Default (%1$s) + Disabled + Enabled + Restricted + + Warning + This setting will weaken exploit protections for the selected app. + Proceed + + Default value can be changed in the %1$s section + + The selected app is known to be compatible with this setting + %1$s by default, because this app is known to need it. +This behavior can be disabled in the %2$s section. + + %1$s by default because this app depends on Play services + + Block for third-party apps by default + Restrict for third-party apps by default + Disable for third-party apps by default + Restricted by default + Restricted by default, except for apps that depend on Play services + Disabled by default + Blocked by default + Allowed for third-party apps by default + Enabled for third-party apps by default + + %1$s is enabled + + Exploit protection compatibility mode + diff --git a/src/com/android/settings/applications/AswAdapter.kt b/src/com/android/settings/applications/AswAdapter.kt new file mode 100644 index 00000000000..478dd02e25e --- /dev/null +++ b/src/com/android/settings/applications/AswAdapter.kt @@ -0,0 +1,88 @@ +package com.android.settings.applications + +import android.content.Context +import android.content.pm.ApplicationInfo +import android.content.pm.GosPackageState +import android.ext.settings.app.AppSwitch +import androidx.preference.Preference +import androidx.preference.PreferenceScreen +import com.android.settings.R +import com.android.settings.SettingsPreferenceFragment +import com.android.settings.applications.appinfo.AppInfoDashboardFragment +import com.android.settings.spa.SpaActivity.Companion.startSpaActivity +import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider +import com.android.settings.spa.app.appinfo.AswAppListPageProvider +import com.android.settingslib.spaprivileged.model.app.userId +import kotlin.reflect.KClass + +abstract class AswAdapter { + abstract fun getAppSwitch(): T + + enum class Category { + ExploitProtection, + } + + fun getCategory(): Category = Category.ExploitProtection + + fun getPreferenceSummary(ctx: Context, appInfo: ApplicationInfo): CharSequence { + val asw = getAppSwitch() + val si = AppSwitch.StateInfo() + val userId = appInfo.userId + val isOn = asw.get(ctx, userId, appInfo, GosPackageState.get(appInfo.packageName, userId), si) + return if (si.isUsingDefaultValue) { + getDefaultTitle(ctx, isOn) + } else { + if (isOn) getOnTitle(ctx) else getOffTitle(ctx) + } + } + + open fun getNotificationToggleTitle(ctx: Context): CharSequence? = null + open fun getNotificationToggleSummary(ctx: Context): CharSequence? = null + + abstract fun getAswTitle(ctx: Context): CharSequence + + open fun getShortAswTitle(ctx: Context) = getAswTitle(ctx) + + fun getDefaultTitle(ctx: Context, isOn: Boolean): CharSequence { + return ctx.getString(R.string.aep_default, + if (isOn) getOnTitle(ctx) else getOffTitle(ctx) + ) + } + + open fun getOnTitle(ctx: Context): CharSequence = ctx.getText(R.string.aep_enabled) + + open fun getOffTitle(ctx: Context): CharSequence = ctx.getText(R.string.aep_disabled) + + abstract fun getDetailFragmentClass(): KClass + + fun openAppPage(context: Context, app: ApplicationInfo) { + AppInfoDashboardFragment.startAppInfoFragment( + getDetailFragmentClass().java, + app, context, AppInfoSettingsProvider.METRICS_CATEGORY, + ) + } + + fun makeAppListPageProvider() = AswAppListPageProvider(this) + + fun getAppListPageProviderName() = this::class.simpleName!! + + open fun shouldIncludeInAppListPage(app: ApplicationInfo, gosPs: GosPackageState) = true + + fun openAppListPage(ctx: Context) { + ctx.startSpaActivity(getAppListPageProviderName()) + } + + @JvmOverloads + fun addAppListPageLink(screen: PreferenceScreen, + title: CharSequence = screen.context.getText(R.string.default_see_all_apps_title)) { + val ctx = screen.context + val pref = Preference(ctx).apply { + this.title = title + setOnPreferenceClickListener { p -> + p.context.startSpaActivity(getAppListPageProviderName()) + true + } + } + screen.addPreference(pref) + } +} diff --git a/src/com/android/settings/applications/AswAppInfoFragment.java b/src/com/android/settings/applications/AswAppInfoFragment.java new file mode 100644 index 00000000000..cac5229f781 --- /dev/null +++ b/src/com/android/settings/applications/AswAppInfoFragment.java @@ -0,0 +1,228 @@ +package com.android.settings.applications; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.GosPackageState; +import android.ext.settings.app.AppSwitch; +import android.os.Bundle; + +import androidx.annotation.Nullable; + +import com.android.settings.R; +import com.android.settings.applications.appinfo.RadioButtonAppInfoFragment; + +import java.util.ArrayList; +import java.util.List; + +public abstract class AswAppInfoFragment + extends RadioButtonAppInfoFragment { + + protected static final int ID_DEFAULT = 0; + protected static final int ID_ON = 1; + protected static final int ID_OFF = 2; + + public abstract AswAdapter getAswAdapter(); + + protected AswAdapter adapter; + private final ArrayList extraPrefs = new ArrayList<>(); + @Nullable + private TogglePrefModel notifTogglePref; + + @Override + public void onCreate(Bundle savedInstanceState) { + adapter = getAswAdapter(); + super.onCreate(savedInstanceState); + + if (adapter.getAppSwitch().hasNotification()) { + Context ctx = requireContext(); + var p = new TogglePrefModel(); + p.title = adapter.getNotificationToggleTitle(ctx); + p.summary = adapter.getNotificationToggleSummary(ctx); + p.onChangeListener = (pref, state) -> { + var ed = GosPackageState.edit(mPackageName, mUserId); + adapter.getAppSwitch().setNotificationEnabled(ed, (boolean) state); + return ed.apply(); + }; + extraPrefs.add(p); + notifTogglePref = p; + } + { + var p = new LinkPrefModel(); + p.title = getText(R.string.default_see_all_apps_title); + p.onClick = () -> adapter.openAppListPage(requireContext()); + extraPrefs.add(p); + } + } + + @Override + protected CharSequence getTitle() { + return adapter.getAswTitle(requireContext()); + } + + @Override + public Entry[] getEntries() { + Context ctx = requireContext(); + AppSwitch asw = adapter.getAppSwitch(); + + int userId = mUserId; + GosPackageState ps = GosPackageState.get(mPackageName, userId); + ApplicationInfo appInfo = getAppInfo(); + var si = new AppSwitch.StateInfo(); + boolean state = asw.get(ctx, userId, appInfo, ps, si); + + boolean isDefault = si.isUsingDefaultValue(); + boolean isImmutable = si.isImmutable(); + + var defaultSi = new AppSwitch.StateInfo(); + boolean defaultValue = asw.getDefaultValue(ctx, userId, appInfo, ps, defaultSi); + + var def = createEntry(ID_DEFAULT, adapter.getDefaultTitle(ctx, defaultValue)); + def.isChecked = isDefault; + def.isEnabled = !isImmutable; + if (def.isEnabled) { + int dvr = defaultSi.getDefaultValueReason(); + CharSequence summary = getSummaryForDefaultValueReason(dvr); + if (summary == null) { + summary = switch (dvr) { + case AppSwitch.DVR_DEFAULT_SETTING -> { + if (!ctx.getUser().isSystem()) { + yield null; + } + yield getString(R.string.aep_dvr_default_security_setting, + getAppDefaultSettingPathForCategory(adapter.getCategory())); + } + case AppSwitch.DVR_APP_COMPAT_CONFIG_HARDENING_OPT_IN -> + getText(R.string.aep_dvr_compat_config_hardening_opt_in); + case AppSwitch.DVR_APP_COMPAT_CONFIG_HARDENING_OPT_OUT -> { + if (!ctx.getUser().isSystem()) { + yield null; + } + var s = defaultValue ? adapter.getOnTitle(ctx) : adapter.getOffTitle(ctx); + yield getString(R.string.aep_dvr_compat_config_hardening_opt_out, + s.toString(), getSettingPath(R.string.safety_center_title, + R.string.more_security_privacy_settings)); + } + case AppSwitch.DVR_APP_IS_CLIENT_OF_GMSCORE -> { + var s = defaultValue ? adapter.getOnTitle(ctx) : adapter.getOffTitle(ctx); + yield getString(R.string.aep_dvr_app_is_client_of_gmscore, s.toString()); + } + default -> null; + }; + } + def.summary = summary; + } + + var enabled = createEntry(ID_ON, adapter.getOnTitle(ctx)); + enabled.isChecked = !isDefault && state; + enabled.isEnabled = enabled.isChecked || !isImmutable; + + var disabled = createEntry(ID_OFF, adapter.getOffTitle(ctx)); + disabled.isChecked = !isDefault && !state; + disabled.isEnabled = disabled.isChecked || !isImmutable; + + if (isImmutable) { + int immutabilityReason = si.getImmutabilityReason(); + CharSequence summary = getSummaryForImmutabilityReason(immutabilityReason); + if (summary == null) { + if (immutabilityReason == AppSwitch.IR_EXPLOIT_PROTECTION_COMPAT_MODE) { + summary = getString(R.string.aep_ir_exploit_protection_compat_mode, + getString(R.string.aep_compat_mode_title)); + } + } + if (enabled.isChecked) { + enabled.summary = summary; + } + if (disabled.isChecked) { + disabled.summary = summary; + } + } + + if (notifTogglePref != null) { + notifTogglePref.isChecked = adapter.getAppSwitch().isNotificationEnabled(ps); + notifTogglePref.isEnabled = state; + } + + return new Entry[] { def, enabled, disabled }; + } + + private String getAppDefaultSettingPathForCategory(AswAdapter.Category category) { + switch (category) { + case ExploitProtection: + return getSettingPath(R.string.safety_center_title, R.string.exploit_protection_settings); + default: + throw new IllegalArgumentException(category.toString()); + } + } + + private String getSettingPath(int... parts) { + var sb = new StringBuilder(); + for (int i = 0; i < parts.length; ++i) { + if (i != 0) { + sb.append(" > "); + } + sb.append(getString(parts[i])); + } + return sb.toString(); + } + + @Nullable + protected CharSequence getSummaryForDefaultValueReason(int dvr) { + return null; + } + + @Nullable + protected CharSequence getSummaryForImmutabilityReason(int ir) { + return null; + } + + @Override + protected List getExtraPrefModels() { + return extraPrefs; + } + + @Override + public final void onEntrySelected(int id) { + Context ctx = requireContext(); + AppSwitch asw = adapter.getAppSwitch(); + int userId = mUserId; + String pkgName = mPackageName; + GosPackageState ps = GosPackageState.get(pkgName, userId); + ApplicationInfo appInfo = getAppInfo(); + + boolean isImmutable = asw.isImmutable(ctx, userId, appInfo, ps); + + if (isImmutable) { + return; + } + + Runnable r = () -> { + GosPackageState.Editor ed = GosPackageState.edit(pkgName, userId); + + switch (id) { + case ID_DEFAULT -> asw.setUseDefaultValue(ed); + case ID_ON, ID_OFF -> asw.set(ed, id == ID_ON); + default -> throw new IllegalStateException(); + } + + ed.setKillUidAfterApply(shouldKillUidAfterChange()); + + if (!ed.apply()) { + finish(); + } + + if (!refreshUi()) { + setIntentAndFinish(true); + } + }; + + completeStateChange(id, asw.get(ctx, userId, appInfo, ps), r); + } + + protected void completeStateChange(int newEntryId, boolean curValue, Runnable stateChangeAction) { + stateChangeAction.run(); + } + + protected boolean shouldKillUidAfterChange() { + return true; + } +} diff --git a/src/com/android/settings/applications/AswAppListPrefController.java b/src/com/android/settings/applications/AswAppListPrefController.java new file mode 100644 index 00000000000..c6d9fa7260a --- /dev/null +++ b/src/com/android/settings/applications/AswAppListPrefController.java @@ -0,0 +1,27 @@ +package com.android.settings.applications; + +import android.content.Context; + +import androidx.preference.Preference; + +import com.android.settings.applications.AswAdapter; +import com.android.settings.core.BasePreferenceController; + +public abstract class AswAppListPrefController extends BasePreferenceController { + + protected final AswAdapter aswAdapter; + + public AswAppListPrefController(Context context, String preferenceKey, AswAdapter adapter) { + super(context, preferenceKey); + aswAdapter = adapter; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!getPreferenceKey().equals(preference.getKey())) { + return false; + } + aswAdapter.openAppListPage(preference.getContext()); + return true; + } +} diff --git a/src/com/android/settings/applications/AswExploitProtectionFragment.java b/src/com/android/settings/applications/AswExploitProtectionFragment.java new file mode 100644 index 00000000000..19d0a470433 --- /dev/null +++ b/src/com/android/settings/applications/AswExploitProtectionFragment.java @@ -0,0 +1,44 @@ +package com.android.settings.applications; + +import android.content.Context; +import android.content.pm.GosPackageState; +import android.ext.settings.app.AppSwitch; + +import androidx.appcompat.app.AlertDialog; + +import com.android.settings.R; + +public abstract class AswExploitProtectionFragment extends AswAppInfoFragment { + + @Override + protected void completeStateChange(int newEntryId, boolean curValue, Runnable stateChangeAction) { + Context ctx = requireContext(); + + boolean showWarning = false; + if (curValue) { + if (newEntryId == ID_OFF) { + showWarning = true; + } else if (newEntryId == ID_DEFAULT) { + AppSwitch asw = adapter.getAppSwitch(); + int userId = mUserId; + var ps = GosPackageState.get(mPackageName, userId); + showWarning = !asw.getDefaultValue(ctx, userId, getAppInfo(), ps); + } + } + if (showWarning) { + var d = getExploitProtectionWarningOnDisable(ctx, stateChangeAction); + d.show(); + } else { + stateChangeAction.run(); + } + } + + public static AlertDialog.Builder getExploitProtectionWarningOnDisable(Context ctx, Runnable action) { + var b = new AlertDialog.Builder(ctx); + b.setTitle(R.string.aep_confirm_disable_title); + b.setMessage(R.string.aep_confirm_disable_warning_msg); + b.setNegativeButton(R.string.cancel, null); + b.setPositiveButton(R.string.aep_confirm_disable_proceed_btn, (d, w) -> action.run()); + return b; + } +} diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index cfe8f368bf5..7431e928e0a 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -45,6 +45,7 @@ import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListPro import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider import com.android.settings.spa.app.specialaccess.WriteSystemPreferencesAppListProvider import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.compose.LifecycleEffect import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.ui.Category @@ -122,6 +123,8 @@ object AppInfoSettingsProvider : SettingsPageProvider { @Composable private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { + // needed to refresh AppSwitch items after returning from their fragments + LifecycleEffect(onStart = { check(packageInfoPresenter.manualRefreshFlow.tryEmit(Any())) }) val packageInfoState = packageInfoPresenter.flow.collectAsStateWithLifecycle() val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl() RegularScaffold( diff --git a/src/com/android/settings/spa/app/appinfo/AswAppList.kt b/src/com/android/settings/spa/app/appinfo/AswAppList.kt new file mode 100644 index 00000000000..c08586a7002 --- /dev/null +++ b/src/com/android/settings/spa/app/appinfo/AswAppList.kt @@ -0,0 +1,101 @@ +package com.android.settings.spa.app.appinfo + +import android.content.Context +import android.content.pm.ApplicationInfo +import android.content.pm.GosPackageState +import android.os.Bundle +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import com.android.settings.applications.AswAdapter +import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.compose.rememberContext +import com.android.settingslib.spa.framework.util.asyncFilter +import com.android.settingslib.spa.framework.util.asyncMap +import com.android.settingslib.spa.widget.ui.SpinnerOption +import com.android.settingslib.spaprivileged.model.app.AppListModel +import com.android.settingslib.spaprivileged.model.app.AppRecord +import com.android.settingslib.spaprivileged.template.app.AppListItem +import com.android.settingslib.spaprivileged.template.app.AppListItemModel +import com.android.settingslib.spaprivileged.template.app.AppListPage +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine + +open class AswAppListPageProvider(val adapter: AswAdapter<*>) : SettingsPageProvider { + override val name = adapter.getAppListPageProviderName() + + @Composable + override fun Page(arguments: Bundle?) { + AswAppListPage(adapter) + } +} + +@Composable +fun AswAppListPage(adapter: AswAdapter<*>) { + AppListPage( + title = rememberContext { ctx -> + adapter.getShortAswTitle(ctx).toString() + }, + listModel = rememberContext { ctx -> + AswAppListModel(ctx, adapter) + }, + ) +} + +class AppRecordImpl(override val app: ApplicationInfo, val gosPackageState: GosPackageState) : AppRecord + +class AswAppListModel(val ctx: Context, val adapter: AswAdapter<*>) : AppListModel { + companion object { + const val SPINNER_OPTION_OFF = 0 + const val SPINNER_OPTION_ON = 1 + } + + override fun getSpinnerOptions(recordList: List): List { + val options = ArrayList(2) + options.add(SpinnerOption(SPINNER_OPTION_OFF, adapter.getOffTitle(ctx).toString())) + options.add(SpinnerOption(SPINNER_OPTION_ON, adapter.getOnTitle(ctx).toString())) + return options + } + + override fun transform( + userIdFlow: Flow, + appListFlow: Flow> + ): Flow> { + return userIdFlow.combine(appListFlow) { userId, appList -> + appList.asyncMap { app -> + val gosPs = GosPackageState.get(app.packageName, userId) + if (adapter.shouldIncludeInAppListPage(app, gosPs)) { + AppRecordImpl(app, GosPackageState.get(app.packageName, userId)) + } else { + null + } + }.filterNotNull() + } + } + + override fun filter( + userIdFlow: Flow, + option: Int, + recordListFlow: Flow> + ): Flow> { + val appSwitch = adapter.getAppSwitch() + return userIdFlow.combine(recordListFlow) { userId, recordList -> + recordList.asyncFilter { + val value = appSwitch.get(ctx, userId, it.app, it.gosPackageState) + when (option) { + SPINNER_OPTION_OFF -> !value + SPINNER_OPTION_ON -> value + else -> throw IllegalArgumentException(option.toString()) + } + } + } + } + + @Composable + override fun AppListItemModel.AppItem() { + val context = LocalContext.current + AppListItem(onClick = { + adapter.openAppPage(context, record.app) + }) + } +} + diff --git a/src/com/android/settings/spa/app/appinfo/AswPreference.kt b/src/com/android/settings/spa/app/appinfo/AswPreference.kt new file mode 100644 index 00000000000..116fa047025 --- /dev/null +++ b/src/com/android/settings/spa/app/appinfo/AswPreference.kt @@ -0,0 +1,27 @@ +package com.android.settings.spa.app.appinfo + +import android.content.Context +import android.content.pm.ApplicationInfo +import android.ext.settings.app.AppSwitch +import androidx.compose.runtime.Composable +import com.android.settings.applications.AswAdapter +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spaprivileged.model.app.installed + +@Composable +fun AswPreference(context: Context, app: ApplicationInfo, adapter: AswAdapter) { + if (!app.installed) { + return + } + + Preference(object : PreferenceModel { + override val title = adapter.getAswTitle(context).toString() + override val summary = { + adapter.getPreferenceSummary(context, app).toString() + } + override val onClick = { + adapter.openAppPage(context, app) + } + }) +} diff --git a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt index 36fe93e2f27..dc650d78883 100644 --- a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt +++ b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt @@ -44,6 +44,7 @@ import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.PackageManagers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.filter @@ -96,7 +97,9 @@ class PackageInfoPresenter( intent.action != Intent.ACTION_PACKAGE_REMOVED || intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false) - val flow: StateFlow = merge(flowOf(null), appChangeFlow) + val manualRefreshFlow = MutableStateFlow(null) + + val flow: StateFlow = merge(flowOf(null), appChangeFlow, manualRefreshFlow) .map { getPackageInfo() } .stateIn(coroutineScope + Dispatchers.Default, SharingStarted.Eagerly, null) From add8c066cb00853ff3ec1c031f1897d34b545f6e Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 2 Mar 2024 12:09:48 +0200 Subject: [PATCH 037/117] add "Exploit protection" category to App info --- src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 7431e928e0a..0e84f1b30d7 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -178,6 +178,9 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { Enable16KbAppCompatPreference(app) } + Category(title = stringResource(R.string.exploit_protection_category_title)) { + } + Category(title = stringResource(R.string.app_install_details_group_title)) { AppInstallerInfoPreference(app) } From 01e7747eae11abed94245dad4d8a570ae115d699 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Tue, 26 Sep 2023 10:34:50 +0300 Subject: [PATCH 038/117] add per-app setting for exploit protection compatibility mode --- res/values/strings_app_exploit_protection.xml | 1 + ...oitProtectionCompatModeSwitchPreference.kt | 59 +++++++++++++++++++ .../spa/app/appinfo/AppInfoSettings.kt | 1 + 3 files changed, 61 insertions(+) create mode 100644 src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 5081ee0a037..ed4eef3ab79 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -34,4 +34,5 @@ This behavior can be disabled in the %2$s section. %1$s is enabled Exploit protection compatibility mode + Improves compatibility by disabling some of the GrapheneOS exploit protections for this app diff --git a/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt b/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt new file mode 100644 index 00000000000..daf3ace3dba --- /dev/null +++ b/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt @@ -0,0 +1,59 @@ +package com.android.settings.spa.app.appinfo + +import android.content.pm.ApplicationInfo +import android.content.pm.GosPackageState +import android.content.pm.GosPackageStateFlag +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settings.applications.AswExploitProtectionFragment +import com.android.settingslib.spa.widget.preference.SwitchPreference +import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel +import com.android.settingslib.spaprivileged.model.app.installed +import com.android.settingslib.spaprivileged.model.app.userId + +@Composable +fun AppExploitProtectionCompatModeSwitchPreference(app: ApplicationInfo, + packageInfoPresenter: PackageInfoPresenter) { + if (app.isSystemApp || !app.installed) { + return + } + + val context = LocalContext.current + val pkgName = app.packageName + val userId = app.userId + val psFlag = GosPackageStateFlag.ENABLE_EXPLOIT_PROTECTION_COMPAT_MODE + + SwitchPreference(object : SwitchPreferenceModel { + override val title = stringResource(R.string.aep_compat_mode_title) + override val summary = { + context.getString(R.string.aep_compat_mode_summary) + } + + override val checked = { + GosPackageState.get(pkgName, userId).hasFlag(psFlag) + } + + override val onCheckedChange = { newChecked: Boolean -> + val action = Runnable { + GosPackageState.edit(pkgName, userId).run { + setFlagState(psFlag, newChecked) + killUidAfterApply() + if (apply()) { + // needed to recompose other exploit protection settings + check(packageInfoPresenter.manualRefreshFlow.tryEmit(Any())) + } + } + } + + if (newChecked) { + val d = AswExploitProtectionFragment.getExploitProtectionWarningOnDisable(context, action) + d.show() + } else { + action.run() + } + Unit + } + }) +} diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 0e84f1b30d7..8f508b9f4ad 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -179,6 +179,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { } Category(title = stringResource(R.string.exploit_protection_category_title)) { + AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter) } Category(title = stringResource(R.string.app_install_details_group_title)) { From 369728ef8600d1c6496f397fba1f90fee4b8867c Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 7 Oct 2023 21:28:08 +0300 Subject: [PATCH 039/117] add toggle for automatic exploit protection compatibility mode --- res/values/strings_ext.xml | 6 ++++++ res/xml/more_security_privacy_settings.xml | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 609768d5c21..8e073138a9f 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -117,6 +117,12 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. Allow running in background + Automatic exploit protection compatibility mode + + +"Allow automatically disabling exploit protections for apps that are known to need it" + + "Warning: enabling this setting might cause some apps to stop working. diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml index c1b98843a45..99a56dd9ef1 100644 --- a/res/xml/more_security_privacy_settings.xml +++ b/res/xml/more_security_privacy_settings.xml @@ -237,6 +237,13 @@ settings:keywords="@string/keywords_app_pinning" settings:controller="com.android.settings.security.ScreenPinningPreferenceController" /> + + Date: Thu, 16 Nov 2023 17:23:47 +0200 Subject: [PATCH 040/117] add per-app setting for hardened_malloc --- AndroidManifest.xml | 18 +++++++ res/values/strings_app_exploit_protection.xml | 8 +++ res/xml/exploit_protection_settings.xml | 5 ++ src/com/android/settings/Settings.java | 2 + .../applications/AppHardenedMalloc.kt | 54 +++++++++++++++++++ .../core/gateway/SettingsGateway.java | 1 + .../settings/spa/SettingsSpaEnvironment.kt | 1 + .../spa/app/appinfo/AppInfoSettings.kt | 1 + 8 files changed, 90 insertions(+) create mode 100644 src/com/android/settings/applications/AppHardenedMalloc.kt diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 101e37fc778..18d64b27ab1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5475,5 +5475,23 @@ + + + + + + + + + + + + + diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index ed4eef3ab79..8581d72090b 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -35,4 +35,12 @@ This behavior can be disabled in the %2$s section. Exploit protection compatibility mode Improves compatibility by disabling some of the GrapheneOS exploit protections for this app + + Hardened memory allocator + + Hardened memory allocator (hardened_malloc) provides substantial defenses against the most common classes of vulnerabilities (heap memory corruption) along with reducing the lifetime of sensitive data in memory. + This app doesn’t have native code + This is a 32-bit app, hardened_malloc is 64-bit only + hardened_malloc is not allowed to be disabled for a preinstalled app + This is a debuggable app, hardened_malloc can’t be disabled diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index ada50481305..34d6ccf6cb4 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -24,6 +24,11 @@ android:key="app_exploit_protection_settings" android:title="@string/app_exploit_protection_category"> + + () { + + override fun getAppSwitch() = AswUseHardenedMalloc.I + + override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_hmalloc) + + override fun getDetailFragmentClass() = AppHardenedMallocFragment::class +} + +@Composable +fun AppHardenedMallocPreference(app: ApplicationInfo) { + val context = LocalContext.current + AswPreference(context, app, AswAdapterUseHardenedMalloc) +} + +class AppHardenedMallocFragment : AswExploitProtectionFragment() { + + override fun getAswAdapter() = AswAdapterUseHardenedMalloc + + override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? { + val id = when (ir) { + AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_hmalloc_ir_preinstalled_app + AppSwitch.IR_NO_NATIVE_CODE -> R.string.aep_hmalloc_ir_no_native_code + AppSwitch.IR_NON_64_BIT_NATIVE_CODE -> R.string.aep_hmalloc_ir_32_bit_native_code + AppSwitch.IR_IS_DEBUGGABLE_APP -> R.string.aep_hmalloc_ir_debuggable_app + else -> return null + } + return getText(id) + } + + override fun updateFooter(fp: FooterPreference) { + fp.setTitle(R.string.aep_hmalloc_footer) + setLearnMoreLink(fp, "https://grapheneos.org/features#exploit-mitigations") + } +} + + +class HardenedMallocAppListPrefController(context: Context, preferenceKey: String) : + AswAppListPrefController(context, preferenceKey, AswAdapterUseHardenedMalloc) { + + override fun getAvailabilityStatus() = AVAILABLE +} diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 4dee4dc0301..348e8b9a708 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -218,6 +218,7 @@ public class SettingsGateway { * security exception if the fragment it needs to display is not in this list. */ public static final String[] ENTRY_FRAGMENTS = { + com.android.settings.applications.AppHardenedMallocFragment.class.getName(), com.android.settings.safetycenter.ExploitProtectionFragment.class.getName(), AdvancedConnectedDeviceDashboardFragment.class.getName(), CreateShortcut.class.getName(), diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt index 7702db6bcde..1dd6f84c662 100644 --- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt +++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt @@ -102,6 +102,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) { open fun settingsPageProviders() = listOf( HomePageProvider, AppsMainPageProvider, + com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(), AllAppListPageProvider, AppInfoSettingsProvider, SpecialAppAccessPageProvider, diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 8f508b9f4ad..0415c9c0392 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -180,6 +180,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { Category(title = stringResource(R.string.exploit_protection_category_title)) { AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter) + com.android.settings.applications.AppHardenedMallocPreference(app) } Category(title = stringResource(R.string.app_install_details_group_title)) { From 7d03c42ce7e3dec7a5b3c27524f66c632a718244 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Fri, 30 Aug 2024 16:23:56 +0300 Subject: [PATCH 041/117] add dev mode per-app setting for extended virtual address space --- res/values/strings_app_exploit_protection.xml | 5 ++ res/xml/exploit_protection_settings.xml | 5 ++ .../applications/AppExtendedVaSpace.kt | 58 +++++++++++++++++++ .../settings/spa/SettingsSpaEnvironment.kt | 1 + .../spa/app/appinfo/AppInfoSettings.kt | 1 + 5 files changed, 70 insertions(+) create mode 100644 src/com/android/settings/applications/AppExtendedVaSpace.kt diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 8581d72090b..d9d94fe5484 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -43,4 +43,9 @@ This behavior can be disabled in the %2$s section. This is a 32-bit app, hardened_malloc is 64-bit only hardened_malloc is not allowed to be disabled for a preinstalled app This is a debuggable app, hardened_malloc can’t be disabled + + Extended virtual address space + Extends virtual address space from 39 to 48 bits, which significantly improves the address space layout randomization. + Incompatible with 32-bit apps + Required by hardened_malloc diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index 34d6ccf6cb4..1068040a7a6 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -29,6 +29,11 @@ android:title="@string/aep_hmalloc" settings:controller="com.android.settings.applications.HardenedMallocAppListPrefController" /> + + () { + + override fun getAppSwitch() = AswUseExtendedVaSpace.I + + override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_ext_va_space) + + override fun getDetailFragmentClass() = AppExtendedVaSpaceFragment::class +} + +@Composable +fun AppExtendedVaSpacePreference(app: ApplicationInfo) { + val context = LocalContext.current + if (ExtSettingControllerHelper.getDevModeSettingAvailability(context) != BasePreferenceController.AVAILABLE) { + return + } + + AswPreference(context, app, AswAdapterUseExtendedVaSpace) +} + +class AppExtendedVaSpaceFragment : AswExploitProtectionFragment() { + + override fun getAswAdapter() = AswAdapterUseExtendedVaSpace + + override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? { + val id = when (ir) { + AppSwitch.IR_REQUIRED_BY_HARDENED_MALLOC -> R.string.aep_ext_va_space_ir_hardened_malloc + AppSwitch.IR_NON_64_BIT_NATIVE_CODE -> R.string.aep_ext_va_space_ir_32_bit_native_code + else -> return null + } + return getText(id) + } + + override fun updateFooter(fp: FooterPreference) { + fp.setTitle(R.string.aep_ext_va_space_footer) + } +} + + +class ExtendedVaSpaceAppListPrefController(context: Context, preferenceKey: String) : + AswAppListPrefController(context, preferenceKey, AswAdapterUseExtendedVaSpace) { + + override fun getAvailabilityStatus() = ExtSettingControllerHelper + .getDevModeSettingAvailability(mContext) +} diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt index 1dd6f84c662..e001c8b152a 100644 --- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt +++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt @@ -103,6 +103,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) { HomePageProvider, AppsMainPageProvider, com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(), + com.android.settings.applications.AswAdapterUseExtendedVaSpace.makeAppListPageProvider(), AllAppListPageProvider, AppInfoSettingsProvider, SpecialAppAccessPageProvider, diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 0415c9c0392..8954d4916da 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -181,6 +181,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { Category(title = stringResource(R.string.exploit_protection_category_title)) { AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter) com.android.settings.applications.AppHardenedMallocPreference(app) + com.android.settings.applications.AppExtendedVaSpacePreference(app) } Category(title = stringResource(R.string.app_install_details_group_title)) { From bfb388b04f8ded88e049b97cee3af630a5d03d6b Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:51:07 +0200 Subject: [PATCH 042/117] add per-app setting for native debugging --- AndroidManifest.xml | 18 ++++ res/values/strings_app_exploit_protection.xml | 8 ++ res/xml/exploit_protection_settings.xml | 11 +++ src/com/android/settings/Settings.java | 2 + .../applications/AppNativeDebugging.kt | 94 +++++++++++++++++++ .../core/gateway/SettingsGateway.java | 1 + .../settings/spa/SettingsSpaEnvironment.kt | 1 + .../spa/app/appinfo/AppInfoSettings.kt | 1 + 8 files changed, 136 insertions(+) create mode 100644 src/com/android/settings/applications/AppNativeDebugging.kt diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 18d64b27ab1..a7101324453 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5476,6 +5476,24 @@ + + + + + + + + + + + + + Extends virtual address space from 39 to 48 bits, which significantly improves the address space layout randomization. Incompatible with 32-bit apps Required by hardened_malloc + + Native code debugging + Show notifications about blocked access attempts + +Native code debugging (ptrace) slightly weakens the app sandbox. Some apps (most notably banking apps) use it as a tampering detection tool. + + Native debugging is always blocked for preinstalled apps + diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index 1068040a7a6..c56c38ef64c 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -34,6 +34,17 @@ android:title="@string/aep_ext_va_space" settings:controller="com.android.settings.applications.ExtendedVaSpaceAppListPrefController" /> + + + + () { + + override fun getAppSwitch() = AswDenyNativeDebug.I + + override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_native_debug_title) + + override fun getOnTitle(ctx: Context) = ctx.getText(R.string.aep_blocked) + override fun getOffTitle(ctx: Context) = ctx.getText(R.string.aep_allowed) + + override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.aep_native_debug_notif_toggle_title) + + override fun getDetailFragmentClass() = AppNativeDebuggingFragment::class +} + +@Composable +fun AppNativeDebuggingPreference(app: ApplicationInfo) { + val context = LocalContext.current + AswPreference(context, app, AswAdapterNativeDebugging) +} + +class AppNativeDebuggingFragment : AswExploitProtectionFragment() { + + override fun getAswAdapter() = AswAdapterNativeDebugging + + override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? { + val id = when (ir) { + AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_native_debug_dvr_is_system_app + else -> return null + } + return getText(id) + } + + override fun updateFooter(fp: FooterPreference) { + fp.setTitle(R.string.aep_native_debug_footer) + } +} + +class AppDefaultNativeDebuggingPrefController(ctx: Context, key: String) : + BoolSettingFragmentPrefController(ctx, key, ExtSettings.ALLOW_NATIVE_DEBUG_BY_DEFAULT) { + + override fun getSummary(): CharSequence { + return resText(if (setting.get(mContext)) R.string.aep_default_summary_allowed_for_3p_apps else R.string.aep_default_summary_blocked) + } +} + +class AppDefaultNativeDebuggingFragment : BoolSettingFragment() { + + override fun getSetting(): BoolSetting { + invertSetting = true + return ExtSettings.ALLOW_NATIVE_DEBUG_BY_DEFAULT + } + + override fun getTitle() = getText(R.string.aep_native_debug_title) + + override fun getMainSwitchTitle() = getText(R.string.aep_default_main_switch_block_for_3p_apps) + + override fun addExtraPrefs(screen: PreferenceScreen) { + AswAdapterNativeDebugging.addAppListPageLink(screen) + } + + override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference { + val text = AppPrefUtils.getFooterForDefaultHardeningSetting( + requireContext(), + R.string.aep_native_debug_footer + ) + return builder.setTitle(text).build() + } +} + +class NativeDebuggingAppListPrefController(context: Context, preferenceKey: String) : + AswAppListPrefController(context, preferenceKey, AswAdapterNativeDebugging) { + + override fun getAvailabilityStatus() = ExtSettingControllerHelper + .getSecondaryUserOnlySettingAvailability(mContext) +} diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 348e8b9a708..c69e658103d 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -218,6 +218,7 @@ public class SettingsGateway { * security exception if the fragment it needs to display is not in this list. */ public static final String[] ENTRY_FRAGMENTS = { + com.android.settings.applications.AppNativeDebuggingFragment.class.getName(), com.android.settings.applications.AppHardenedMallocFragment.class.getName(), com.android.settings.safetycenter.ExploitProtectionFragment.class.getName(), AdvancedConnectedDeviceDashboardFragment.class.getName(), diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt index e001c8b152a..09c762f2fc5 100644 --- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt +++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt @@ -104,6 +104,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) { AppsMainPageProvider, com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(), com.android.settings.applications.AswAdapterUseExtendedVaSpace.makeAppListPageProvider(), + com.android.settings.applications.AswAdapterNativeDebugging.makeAppListPageProvider(), AllAppListPageProvider, AppInfoSettingsProvider, SpecialAppAccessPageProvider, diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 8954d4916da..cce2f233c69 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -182,6 +182,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter) com.android.settings.applications.AppHardenedMallocPreference(app) com.android.settings.applications.AppExtendedVaSpacePreference(app) + com.android.settings.applications.AppNativeDebuggingPreference(app) } Category(title = stringResource(R.string.app_install_details_group_title)) { From 11098703569d852dc837cdb3d5ff806c572d6f87 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Fri, 30 Aug 2024 16:25:59 +0300 Subject: [PATCH 043/117] add per-app setting for memory tagging --- AndroidManifest.xml | 16 +++ res/values/strings_app_exploit_protection.xml | 18 +++ res/xml/exploit_protection_settings.xml | 11 ++ src/com/android/settings/Settings.java | 2 + .../settings/applications/AppMemoryTagging.kt | 111 ++++++++++++++++++ .../core/gateway/SettingsGateway.java | 1 + .../settings/spa/SettingsSpaEnvironment.kt | 1 + .../spa/app/appinfo/AppInfoSettings.kt | 1 + 8 files changed, 161 insertions(+) create mode 100644 src/com/android/settings/applications/AppMemoryTagging.kt diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a7101324453..1e39f370ab0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5493,6 +5493,22 @@ android:value="@string/menu_key_apps"/> + + + + + + + + + + + Native debugging is always blocked for preinstalled apps + Memory tagging + Show notifications about detected errors + Memory tagging provides strong protections against exploitation of heap memory bugs (e.g. use-after-free, buffer overflow). + Memory tagging is always enabled for preinstalled apps + Memory tagging is always enabled for apps that don’t have native code + This app has opted-in to memory tagging + + Enable by default + + This setting doesn’t apply to apps that are known to be compatible with memory tagging + "Memory tagging provides strong protections against exploitation of heap memory bugs (e.g. use-after-free, buffer overflow). + +Memory tagging is always enabled for preinstalled apps and for third-party apps that are known to be +compatible with it (e.g. apps that don’t have native code), regardless of this setting." + Enabled by default + + Disabled by default, except for apps that are known to be compatible with memory tagging + diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index c56c38ef64c..d2ed9ca38c0 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -29,6 +29,17 @@ android:title="@string/aep_hmalloc" settings:controller="com.android.settings.applications.HardenedMallocAppListPrefController" /> + + + + () { + + override fun getAppSwitch() = AswUseMemoryTagging.I + + override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_memtag) + + override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.aep_memtag_notif_toggle_time) + + override fun getDetailFragmentClass() = AppMemtagFragment::class +} + +private val isMemoryTaggingSupported = Zygote.nativeSupportsMemoryTagging() + +@Composable +fun AppMemtagPreference(app: ApplicationInfo) { + if (!isMemoryTaggingSupported) { + return + } + + val context = LocalContext.current + AswPreference(context, app, AswAdapterUseMemoryTagging) +} + +class AppMemtagFragment : AswExploitProtectionFragment() { + + override fun getAswAdapter() = AswAdapterUseMemoryTagging + + override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? { + val id = when (ir) { + AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_memtag_dvr_is_system_app + AppSwitch.IR_NO_NATIVE_CODE -> R.string.aep_memtag_dvr_no_native_code + AppSwitch.IR_OPTED_IN_VIA_MANIFEST -> R.string.aep_memtag_dvr_manifest_opt_in + else -> return null + } + return getText(id) + } + + override fun updateFooter(fp: FooterPreference) { + fp.setTitle(R.string.aep_memtag_footer) + } +} + +class AppDefaultMemtagPrefController(ctx: Context, key: String) : + BoolSettingFragmentPrefController(ctx, key, ExtSettings.FORCE_APP_MEMTAG_BY_DEFAULT) { + + private val isSupported = Zygote.nativeSupportsMemoryTagging() + + override fun getAvailabilityStatus(): Int { + if (!isSupported) { + return UNSUPPORTED_ON_DEVICE + } + + return super.getAvailabilityStatus() + } + + override fun getSummaryOn() = resText(R.string.aep_default_memtag_summary_on) + override fun getSummaryOff() = resText(R.string.aep_default_memtag_summary_off) +} + +class AppDefaultMemtagFragment : BoolSettingFragment() { + + override fun getSetting() = ExtSettings.FORCE_APP_MEMTAG_BY_DEFAULT + + override fun getTitle() = resText(R.string.aep_memtag) + + override fun getMainSwitchTitle() = resText(R.string.aep_default_memtag_main_switch_title) + override fun getMainSwitchSummary() = resText(R.string.aep_default_memtag_main_switch_summary) + + override fun addExtraPrefs(screen: PreferenceScreen) { + AswAdapterUseMemoryTagging.addAppListPageLink(screen) + } + + override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference { + val text = AppPrefUtils.getFooterForDefaultHardeningSetting(requireContext(), + R.string.aep_default_memtag_footer) + return builder.setTitle(text).build() + } +} + +class MemtagAppListPrefController(context: Context, preferenceKey: String) : + AswAppListPrefController(context, preferenceKey, AswAdapterUseMemoryTagging) { + + private val isSupported = Zygote.nativeSupportsMemoryTagging() + + override fun getAvailabilityStatus(): Int { + if (!isSupported) { + return UNSUPPORTED_ON_DEVICE + } + return ExtSettingControllerHelper + .getSecondaryUserOnlySettingAvailability(mContext) + } +} diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index c69e658103d..8ea84bc6ce2 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -219,6 +219,7 @@ public class SettingsGateway { */ public static final String[] ENTRY_FRAGMENTS = { com.android.settings.applications.AppNativeDebuggingFragment.class.getName(), + com.android.settings.applications.AppMemtagFragment.class.getName(), com.android.settings.applications.AppHardenedMallocFragment.class.getName(), com.android.settings.safetycenter.ExploitProtectionFragment.class.getName(), AdvancedConnectedDeviceDashboardFragment.class.getName(), diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt index 09c762f2fc5..f7c62225702 100644 --- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt +++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt @@ -103,6 +103,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) { HomePageProvider, AppsMainPageProvider, com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(), + com.android.settings.applications.AswAdapterUseMemoryTagging.makeAppListPageProvider(), com.android.settings.applications.AswAdapterUseExtendedVaSpace.makeAppListPageProvider(), com.android.settings.applications.AswAdapterNativeDebugging.makeAppListPageProvider(), AllAppListPageProvider, diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index cce2f233c69..a83b10e87dc 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -181,6 +181,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { Category(title = stringResource(R.string.exploit_protection_category_title)) { AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter) com.android.settings.applications.AppHardenedMallocPreference(app) + com.android.settings.applications.AppMemtagPreference(app) com.android.settings.applications.AppExtendedVaSpacePreference(app) com.android.settings.applications.AppNativeDebuggingPreference(app) } From 2df9027d970addda56605a949ab5d244c37b93c6 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Mon, 27 Nov 2023 21:47:26 +0200 Subject: [PATCH 044/117] add toggle for system process crash notifications --- res/values/strings_ext.xml | 3 +++ res/xml/more_security_privacy_settings.xml | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 8e073138a9f..504fa032934 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -125,4 +125,7 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. "Warning: enabling this setting might cause some apps to stop working. + Notify about system process crashes + Such crashes may indicate exploitation attempts + diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml index 99a56dd9ef1..3da6e0d25f0 100644 --- a/res/xml/more_security_privacy_settings.xml +++ b/res/xml/more_security_privacy_settings.xml @@ -237,6 +237,14 @@ settings:keywords="@string/keywords_app_pinning" settings:controller="com.android.settings.security.ScreenPinningPreferenceController" /> + + Date: Fri, 29 Sep 2023 16:16:00 +0300 Subject: [PATCH 045/117] Widevine provisioning setting Signed-off-by: maade69 <70593890+maade69@users.noreply.github.com> --- res/values/strings_ext.xml | 5 +++ res/xml/network_provider_internet.xml | 6 +++ .../WidevineProvisioningPrefController.java | 43 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 src/com/android/settings/network/WidevineProvisioningPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 504fa032934..f46dd322b70 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -104,6 +104,11 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. Use secure app spawning Launch apps in a more secure way than Android which takes slightly longer and increases memory usage by app processes. + Widevine provisioning + GrapheneOS proxy + Google server + The provisioned certificate will be used for accessing DRM protected content. + App installs and updates diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml index b4becf7c709..594d307f83e 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -138,4 +138,10 @@ android:title="@string/remote_provisioning_title" android:order="35" settings:controller="com.android.settings.network.RemoteProvisioningPrefController" /> + + diff --git a/src/com/android/settings/network/WidevineProvisioningPrefController.java b/src/com/android/settings/network/WidevineProvisioningPrefController.java new file mode 100644 index 00000000000..09d62f012ac --- /dev/null +++ b/src/com/android/settings/network/WidevineProvisioningPrefController.java @@ -0,0 +1,43 @@ +/* + * 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.network; + +import android.content.Context; +import android.ext.settings.WidevineProvisioningSettings; + +import com.android.settings.R; +import androidx.preference.PreferenceScreen; +import com.android.settings.ext.IntSettingPrefController; +import com.android.settings.ext.RadioButtonPickerFragment2; + +public class WidevineProvisioningPrefController extends IntSettingPrefController { + + public WidevineProvisioningPrefController(Context ctx, String key) { + super(ctx, key, WidevineProvisioningSettings.SERVER_SETTING); + } + + @Override + public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) { + addFooterPreference(screen, R.string.widevine_provisioning_footer); + } + + @Override + protected void getEntries(Entries entries) { + entries.add(R.string.widevine_provisioning_enabled_grapheneos_proxy, WidevineProvisioningSettings.WV_GRAPHENEOS_PROXY); + entries.add(R.string.widevine_provisioning_enabled_google_server, WidevineProvisioningSettings.WV_STANDARD_SERVER); + } +} From 8e1ca78c4e1589a9597949340e70a03158edfbc6 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Mon, 18 Dec 2023 15:38:16 +0200 Subject: [PATCH 046/117] remove confusing mention of Android Auto from "Connected devices" screen --- .../AdvancedConnectedDeviceController.java | 10 +------- ...AdvancedConnectedDeviceControllerTest.java | 25 ------------------- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java index 2855f0ab16a..2f7dd6ff789 100644 --- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java +++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java @@ -34,7 +34,6 @@ public class AdvancedConnectedDeviceController extends BasePreferenceController private static final String DRIVING_MODE_SETTINGS_ENABLED = "gearhead:driving_mode_settings_enabled"; - private static final String GEARHEAD_PACKAGE = "com.google.android.projection.gearhead"; public AdvancedConnectedDeviceController(Context context, String preferenceKey) { super(context, preferenceKey); @@ -59,7 +58,7 @@ public static int getConnectedDevicesSummaryResourceId(Context context) { new NfcPreferenceController(context, NfcPreferenceController.KEY_TOGGLE_NFC); return getConnectedDevicesSummaryResourceId(nfcPreferenceController, - isDrivingModeAvailable(context), isAndroidAutoSettingAvailable(context)); + isDrivingModeAvailable(context), false); } @VisibleForTesting @@ -68,13 +67,6 @@ static boolean isDrivingModeAvailable(Context context) { getInt(context.getContentResolver(), DRIVING_MODE_SETTINGS_ENABLED, 0) == 1; } - @VisibleForTesting - static boolean isAndroidAutoSettingAvailable(Context context) { - final Intent intent = new Intent(IA_SETTINGS_ACTION); - intent.setPackage(GEARHEAD_PACKAGE); - return intent.resolveActivity(context.getPackageManager()) != null; - } - @VisibleForTesting static int getConnectedDevicesSummaryResourceId(NfcPreferenceController nfcPreferenceController, diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java index 6ae670dc120..2af9242dab8 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java @@ -99,31 +99,6 @@ public void isDrivingModeAvailable_returnFalse() { AdvancedConnectedDeviceController.isDrivingModeAvailable(mContext)).isFalse(); } - @Test - public void isAndroidAutoSettingAvailable_returnTrue() { - final ApplicationInfo appInfo = - ApplicationInfoBuilder.newBuilder().setPackageName(ANDROID_AUTO_PACKAGE).build(); - final ActivityInfo activityInfo = new ActivityInfo(); - activityInfo.packageName = ANDROID_AUTO_PACKAGE; - activityInfo.name = ANDROID_AUTO_PACKAGE; - activityInfo.applicationInfo = appInfo; - final ResolveInfo resolveInfo = new ResolveInfo(); - resolveInfo.activityInfo = activityInfo; - mShadowPackageManager.addResolveInfoForIntent( - buildAndroidAutoSettingsIntent(), - resolveInfo); - - assertThat( - AdvancedConnectedDeviceController.isAndroidAutoSettingAvailable(mContext)).isTrue(); - } - - @Test - public void isAndroidAutoSettingAvailable_returnFalse() { - // No ResolveInfo for Android Auto, expect false. - assertThat( - AdvancedConnectedDeviceController.isAndroidAutoSettingAvailable(mContext)).isFalse(); - } - @Test public void getConnectedDevicesSummaryResourceId_NFCAndDrivingModeAvailable() { // NFC available, driving mode available From 95cf901f4198cc4648cc500196f08965a64fb2d3 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 6 Jan 2024 19:37:47 +0200 Subject: [PATCH 047/117] add logcat viewer link to System settings --- AndroidManifest.xml | 1 + res/values/strings_ext.xml | 2 ++ res/xml/system_dashboard_fragment.xml | 7 ++++ .../system/LogcatLinkPrefController.java | 34 +++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 src/com/android/settings/system/LogcatLinkPrefController.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1e39f370ab0..373fd205ee2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -148,6 +148,7 @@ + Notify about system process crashes Such crashes may indicate exploitation attempts + View logs + diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml index 83cdf64fc00..60e4eaa220d 100644 --- a/res/xml/system_dashboard_fragment.xml +++ b/res/xml/system_dashboard_fragment.xml @@ -84,6 +84,13 @@ + + Date: Sat, 2 Mar 2024 11:25:46 +0200 Subject: [PATCH 048/117] add logcat viewer link to App info screen --- .../spa/app/appinfo/AppInfoSettings.kt | 1 + .../spa/app/appinfo/AppLogcatPreference.kt | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index a83b10e87dc..8162046c7df 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -160,6 +160,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { AppLocalePreference(app) AppOpenByDefaultPreference(app) DefaultAppShortcuts(app) + AppLogcatPreference(app) } Category(title = stringResource(R.string.unused_apps_category)) { diff --git a/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt b/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt new file mode 100644 index 00000000000..14e3c60b5e1 --- /dev/null +++ b/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt @@ -0,0 +1,29 @@ +package com.android.settings.spa.app.appinfo + +import android.content.pm.ApplicationInfo +import android.ext.LogViewerApp +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spaprivileged.model.app.installed +import com.android.settingslib.spaprivileged.model.app.userHandle + +@Composable +fun AppLogcatPreference(app: ApplicationInfo) { + if (!app.installed) { + return + } + + val context = LocalContext.current + + Preference(object : PreferenceModel { + override val title = stringResource(R.string.view_logs) + override val onClick = { + val intent = LogViewerApp.getPackageLogcatIntent(app.packageName) + context.startActivityAsUser(intent, app.userHandle) + } + }) +} From a0be10d8a661291da36d1515455089a97c8b0a82 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 21 Feb 2024 16:39:26 +0200 Subject: [PATCH 049/117] add USB-C port and pogo pins security setting --- res/values/strings_ext.xml | 32 ++++ res/xml/exploit_protection_settings.xml | 10 ++ .../UsbPortSecurityPrefController.java | 141 ++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 src/com/android/settings/security/UsbPortSecurityPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index a745a34ea95..44e90a7e01b 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -135,4 +135,36 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. View logs + USB-C port + Off + Turns off the USB-C port. + Doesn’t impact the separate charging mode, which is activated by turning off the device and plugging it in to a charger. + + Charging-only + Turns off all non-charging USB-C port functionality. + Charging-only when locked + Enables the charging-only mode when the + device is locked and disables it when the device becomes unlocked. If the port is already + plugged-in at the time when the device becomes locked, then the activation of charging-only + mode will be delayed until the port is disconnected. + Charging-only when locked, except before first unlock + This mode has the same behavior + as the “%1$s” mode, except for an additional exemption for before-first-unlock connections. + + On + Does not add any restrictions. + + USB-C port and pogo pins + USB-C port off, pogo pins used only for charging + Turns off the USB-C port and turns off all + non-charging pogo pins functionality. Doesn’t impact the separate charging mode, which is + activated by turning off the device and plugging it in to a charger. + + Turns off all non-charging USB-C port and pogo pins functionality. + Enables the charging-only mode when the + device is locked and disables it when the device becomes unlocked. If the port is already + plugged-in at the time when the device becomes locked, then the activation of charging-only + mode will be delayed until the port is disconnected. The same behavior applies to pogo pins. + + diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml index d2ed9ca38c0..530e97cd956 100644 --- a/res/xml/exploit_protection_settings.xml +++ b/res/xml/exploit_protection_settings.xml @@ -10,6 +10,16 @@ android:title="@string/auto_reboot_title" settings:controller="com.android.settings.security.AutoRebootPrefController" /> + + + + (); + usbManager.setSecurityStateForAllPorts(state, new ResultReceiver(null) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + if (resultCode != android.hardware.usb.ext.IUsbExt.NO_ERROR) { + String msg = "setPortSecurityState failed, " + + "resultCode: " + resultCode; + if (resultData != null) { + msg += ", resultData: " + resultData.toStringDeep(); + } + throw new RuntimeException(msg); + } + future.complete(null); + } + }); + try { + future.get(3, TimeUnit.SECONDS); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void setState(int prevSetting, @android.hardware.usb.ext.PortSecurityState int state) { + var usbManager = requireNonNull(mContext.getSystemService(UsbManager.class)); + if (prevSetting == UsbPortSecurity.MODE_CHARGING_ONLY && state >= UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED) { + // Turn USB ports off first to trigger reconnection of devices that were connected + // in charging-only state. Simply enabling the data path is not enough in some + // advanced scenarios, e.g. when port alt mode or port role switching are used. + setSecurityStateForAllPortsSync(usbManager, PortSecurityState.DISABLED); + } + setSecurityStateForAllPortsSync(usbManager, state); + } + + @Override + protected boolean setValue(int val) { + int prevSetting = getCurrentValue(); + boolean res = super.setValue(val); + if (!res) { + return false; + } + + int pss = switch (val) { + case UsbPortSecurity.MODE_DISABLED -> PortSecurityState.DISABLED; + case UsbPortSecurity.MODE_CHARGING_ONLY -> PortSecurityState.CHARGING_ONLY_IMMEDIATE; + case UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED -> PortSecurityState.ENABLED; + case UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED_AFU -> PortSecurityState.ENABLED; + case UsbPortSecurity.MODE_ENABLED -> PortSecurityState.ENABLED; + default -> throw new IllegalArgumentException(Integer.toString(val)); + }; + setState(prevSetting, pss); + return true; + } + + @Override + protected boolean isCredentialConfirmationRequired() { + return true; + } +} From 4132e9b5bd5d4dbe757a39ddd0c95a16512fd445 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 7 Mar 2024 12:21:53 +0200 Subject: [PATCH 050/117] enable "About phone -> Battery information" screen Squashed with: commit 50f8f1d6d2c588e8e5504f6f9f6c071c6b26938f Author: Daniel Micay Date: Sat Mar 9 10:06:21 2024 -0500 use 2021-01-01 as minimum battery date --- .../fuelgauge/BatterySettingsFeatureProviderImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java index 4b5d9526f16..acc67ecb639 100644 --- a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java @@ -32,17 +32,17 @@ public class BatterySettingsFeatureProviderImpl implements BatterySettingsFeatur @Override public boolean isManufactureDateAvailable(Context context, long manufactureDateMs) { - return false; + return manufactureDateMs > 1_609_459_200_000L; // 2021-01-01 } @Override public boolean isFirstUseDateAvailable(Context context, long firstUseDateMs) { - return false; + return firstUseDateMs > 1_609_459_200_000L; // 2021-01-01 } @Override public boolean isBatteryInfoEnabled(Context context) { - return false; + return true; } @Override From d35fe51fae547de82859042266be22088851ee85 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 17 Mar 2024 17:40:23 +0200 Subject: [PATCH 051/117] fix footer formatting issue on App pinning screen Since 20976c3a53802a8b78cab20e49154244ddaf9ddd screen_pinning_description is a formatted string, it can't be used directly from XML. --- res/xml/screen_pinning_settings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/res/xml/screen_pinning_settings.xml b/res/xml/screen_pinning_settings.xml index 2c4402da89e..f06b42ceab1 100644 --- a/res/xml/screen_pinning_settings.xml +++ b/res/xml/screen_pinning_settings.xml @@ -30,7 +30,6 @@ From 33397fdebd44fdf140685979895c39e9c1964ebf Mon Sep 17 00:00:00 2001 From: Jitesh Singh Date: Tue, 30 Jan 2024 19:48:12 +0530 Subject: [PATCH 052/117] fixes redundant horizontal margin issue on tablets --- res/values-sw600dp-v31/dimens.xml | 9 +++++++++ res/values-sw600dp/dimens.xml | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 res/values-sw600dp-v31/dimens.xml diff --git a/res/values-sw600dp-v31/dimens.xml b/res/values-sw600dp-v31/dimens.xml new file mode 100644 index 00000000000..3542f62dc08 --- /dev/null +++ b/res/values-sw600dp-v31/dimens.xml @@ -0,0 +1,9 @@ + + + 24dp + 24dp + 8dp + 20dp + 20dp + 8dp + diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml index 55735e66322..170d6998c36 100755 --- a/res/values-sw600dp/dimens.xml +++ b/res/values-sw600dp/dimens.xml @@ -29,6 +29,14 @@ 348dp + + 24dp + 24dp + 8dp + 20dp + 20dp + 8dp + 104dp 448dp From 7cbd2179c39f03680f786a7833afe62668a0cab5 Mon Sep 17 00:00:00 2001 From: Jitesh Singh Date: Wed, 31 Jan 2024 01:41:53 +0530 Subject: [PATCH 053/117] internet setup activity Co-authored-by: Dmitry Muhomor Co-authored-by: quh4gko8 <88831734+quh4gko8@users.noreply.github.com> --- AndroidManifest.xml | 13 ++ res/drawable/baseline_wifi.xml | 10 ++ res/drawable/baseline_wifi_glif.xml | 7 + res/layout/settings_main_prefs.xml | 62 ++++--- res/values/dimens.xml | 5 + res/values/themes_suw.xml | 2 + .../network/InternetSetupActivity.java | 52 ++++++ .../network/NetworkProviderSettings.java | 4 +- .../network/NetworkProviderSetup.java | 155 ++++++++++++++++++ 9 files changed, 276 insertions(+), 34 deletions(-) create mode 100644 res/drawable/baseline_wifi.xml create mode 100644 res/drawable/baseline_wifi_glif.xml create mode 100644 src/com/android/settings/network/InternetSetupActivity.java create mode 100644 src/com/android/settings/network/NetworkProviderSetup.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 373fd205ee2..5cb17f99642 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -516,6 +516,19 @@ android:value="true" /> + + + + + + + + + + + diff --git a/res/drawable/baseline_wifi_glif.xml b/res/drawable/baseline_wifi_glif.xml new file mode 100644 index 00000000000..3f12842b089 --- /dev/null +++ b/res/drawable/baseline_wifi_glif.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/res/layout/settings_main_prefs.xml b/res/layout/settings_main_prefs.xml index 48352e2efa0..5111332bfbe 100644 --- a/res/layout/settings_main_prefs.xml +++ b/res/layout/settings_main_prefs.xml @@ -34,40 +34,38 @@ android:layout_height="0dp" android:layout_weight="1"/> - - -