From 53abd6e5a62b0cfe05f9c6c4bbf7b5cbcbcf5a21 Mon Sep 17 00:00:00 2001 From: flawedworld Date: Sat, 5 Feb 2022 17:42:07 +0000 Subject: [PATCH 01/85] add GrapheneOS icon --- AndroidManifest.xml | 3 ++- res/drawable/ic_launcher_foreground.xml | 30 +++++++++++++++++++++++++ res/mipmap-anydpi/ic_launcher.xml | 6 +++++ res/mipmap-anydpi/ic_launcher_round.xml | 6 +++++ res/values/ic_launcher_background.xml | 4 ++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 res/drawable/ic_launcher_foreground.xml create mode 100644 res/mipmap-anydpi/ic_launcher.xml create mode 100644 res/mipmap-anydpi/ic_launcher_round.xml create mode 100644 res/values/ic_launcher_background.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 453a71e1ad0..64f42a71bdc 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -137,7 +137,8 @@ + + + + + diff --git a/res/mipmap-anydpi/ic_launcher.xml b/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 00000000000..5c84730caa7 --- /dev/null +++ b/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/res/mipmap-anydpi/ic_launcher_round.xml b/res/mipmap-anydpi/ic_launcher_round.xml new file mode 100644 index 00000000000..5c84730caa7 --- /dev/null +++ b/res/mipmap-anydpi/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/res/values/ic_launcher_background.xml b/res/values/ic_launcher_background.xml new file mode 100644 index 00000000000..f42ada656ee --- /dev/null +++ b/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + From 6de9513be2aee4ac65e0dbc107c7d83757f7f784 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 14 Oct 2022 21:08:02 -0400 Subject: [PATCH 02/85] set styles/wallpaper picker action name --- res/values/config.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/config.xml b/res/values/config.xml index 17c33989502..5cb7b5b193d 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -47,9 +47,9 @@ - + android.intent.action.MAIN - + android.intent.action.MAIN com.android.wallpaper.LAUNCH_SOURCE From 9bf36be18d3ee4ba71fc3c3fcc53d652a781563e Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sat, 17 Apr 2021 15:15:51 +0100 Subject: [PATCH 03/85] Settings: Integrate ThemePicker and WallpaperPicker2 This uses the standalone wallpaper picker class from WallpaperPicker2 as seen in the Pixel stock ROM. --- res/values/config.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/values/config.xml b/res/values/config.xml index 5cb7b5b193d..af9984d3285 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -42,10 +42,10 @@ com.android.settings.overlay.FeatureFactoryImpl - com.android.settings - com.android.settings.Settings$WallpaperSettingsActivity + com.android.wallpaper + com.android.wallpaper.picker.CategoryPickerActivity - + com.android.customization.picker.CustomizationPickerActivity android.intent.action.MAIN From 642498301127a15d06257aadbaa117fe39e2cbba Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 16 Feb 2021 02:22:41 -0500 Subject: [PATCH 04/85] disable showing wallpaper attribution --- 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 af9984d3285..d53b69be3ab 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -460,7 +460,7 @@ true - true + false true From 9fc30d690333c63d9c7af85a586131a95afd889b Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 10 Mar 2021 00:45:12 -0500 Subject: [PATCH 05/85] add TalkBack accessibility service --- res/values/config.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/res/values/config.xml b/res/values/config.xml index d53b69be3ab..c7a84151832 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -75,6 +75,7 @@ com.example.package.first/com.example.class.FirstService com.example.package.second/com.example.class.SecondService --> + com.android.talkback/com.google.android.marvin.talkback.TalkBackService From e5f3d379d7c5ec2c2cdd0aa28716546eda9f7e7e Mon Sep 17 00:00:00 2001 From: inthewaves Date: Sun, 20 Sep 2020 17:57:30 -0700 Subject: [PATCH 06/85] get outer NFC preference to listen for changes The NFC preference in Settings -> Connected devices -> Connection preferences doesn't listen to changes from the NFC tile. (This wasn't an issue in Android 10, because there used to be a SwitchPreference that listened there.) --- .../NfcAndPaymentFragmentController.java | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java b/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java index ee0021ec951..f16dd378db5 100644 --- a/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java +++ b/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java @@ -16,21 +16,47 @@ package com.android.settings.connecteddevice; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.nfc.NfcAdapter; import android.os.UserManager; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnResume; +import com.android.settingslib.core.lifecycle.events.OnStop; /** * Controller that used to show NFC and payment features */ -public class NfcAndPaymentFragmentController extends BasePreferenceController { +public class NfcAndPaymentFragmentController extends BasePreferenceController + implements LifecycleObserver, OnResume, OnStop { private final NfcAdapter mNfcAdapter; private final PackageManager mPackageManager; private final UserManager mUserManager; + private final IntentFilter mIntentFilter; + private Preference mPreference; + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mPreference == null) { + return; + } + + final String action = intent.getAction(); + if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(action)) { + refreshSummary(mPreference); + } + } + }; public NfcAndPaymentFragmentController(Context context, String preferenceKey) { super(context, preferenceKey); @@ -38,6 +64,15 @@ public NfcAndPaymentFragmentController(Context context, String preferenceKey) { mPackageManager = context.getPackageManager(); mUserManager = context.getSystemService(UserManager.class); mNfcAdapter = NfcAdapter.getDefaultAdapter(context); + + mIntentFilter = isNfcAvailable() + ? new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED) : null; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); } @Override @@ -61,4 +96,26 @@ public CharSequence getSummary() { } return null; } + + @Override + public void onStop() { + if (!isNfcAvailable()) { + return; + } + + mContext.unregisterReceiver(mReceiver); + } + + @Override + public void onResume() { + if (!isNfcAvailable()) { + return; + } + + mContext.registerReceiver(mReceiver, mIntentFilter); + } + + private boolean isNfcAvailable() { + return mNfcAdapter != null; + } } From b735b895fd930527cae39c72711ebb572dfcae1c Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 8 Oct 2019 08:11:55 -0400 Subject: [PATCH 07/85] disable legacy suggestions --- 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 c7a84151832..70091998e15 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -234,7 +234,7 @@ Whether or not the homepage should be powered by legacy suggestion (versus contextual cards) Default to true as not all devices support contextual cards. --> - true + false false From 684ad4b9efd2a6638475360106a97af3220b6b08 Mon Sep 17 00:00:00 2001 From: Renlord Date: Sat, 11 Apr 2020 20:04:51 +1000 Subject: [PATCH 08/85] add missing android title for top_level_settings --- res/xml/top_level_settings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml index d050a1f2747..ebae388688f 100644 --- a/res/xml/top_level_settings.xml +++ b/res/xml/top_level_settings.xml @@ -18,7 +18,8 @@ + android:key="top_level_settings" + android:title="Settings"> Date: Sun, 16 May 2021 00:51:15 +0100 Subject: [PATCH 09/85] Remove misleading "Google Play system update" info field --- res/xml/firmware_version.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/res/xml/firmware_version.xml b/res/xml/firmware_version.xml index 41f7733cfb2..edc910b36cf 100644 --- a/res/xml/firmware_version.xml +++ b/res/xml/firmware_version.xml @@ -37,14 +37,6 @@ settings:enableCopying="true" settings:controller="com.android.settings.deviceinfo.firmwareversion.SecurityPatchLevelPreferenceController"/> - - - Date: Sun, 28 May 2023 18:42:41 +0300 Subject: [PATCH 10/85] do not allow disabling the bundled keyboard --- .../settings/applications/ApplicationFeatureProviderImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index 80d39475931..08a08fea03b 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -183,6 +183,10 @@ private Set getEnabledPackageAllowlist() { if (mPm.getWellbeingPackageName() != null) { keepEnabledPackages.add(mPm.getWellbeingPackageName()); } + + // Bundled keyboard, needed for text input in Direct Boot mode if the selected 3rd party + // keyboard doesn't support it + keepEnabledPackages.add("com.android.inputmethod.latin"); return keepEnabledPackages; } From 1dd9f527d7e64eae868f283aa1ac499748d30868 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 28 May 2023 18:43:14 +0300 Subject: [PATCH 11/85] do not allow disabling Vanadium WebView --- .../settings/applications/ApplicationFeatureProviderImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index 08a08fea03b..12e2b02fac6 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -187,6 +187,9 @@ private Set getEnabledPackageAllowlist() { // Bundled keyboard, needed for text input in Direct Boot mode if the selected 3rd party // keyboard doesn't support it keepEnabledPackages.add("com.android.inputmethod.latin"); + + // Replacing WebView is not supported + keepEnabledPackages.add("app.vanadium.webview"); return keepEnabledPackages; } From 0d264f24bf34c78b26173d2baea86f536ad6a551 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 28 May 2023 18:43:42 +0300 Subject: [PATCH 12/85] do not allow disabling GrapheneOS Camera --- .../settings/applications/ApplicationFeatureProviderImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index 12e2b02fac6..24b9ae1c80d 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -190,6 +190,9 @@ private Set getEnabledPackageAllowlist() { // Replacing WebView is not supported keepEnabledPackages.add("app.vanadium.webview"); + + // Only bundled camera can handle some of camera intents + keepEnabledPackages.add("app.grapheneos.camera"); return keepEnabledPackages; } From 51ae6fdd07a074f7d3904ec6591be6492b37603b Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 28 May 2023 18:44:08 +0300 Subject: [PATCH 13/85] do not allow disabling GmsCompat and GmsCompatConfig --- .../applications/ApplicationFeatureProviderImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index 24b9ae1c80d..11459fe32e1 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -193,6 +193,11 @@ private Set getEnabledPackageAllowlist() { // Only bundled camera can handle some of camera intents keepEnabledPackages.add("app.grapheneos.camera"); + + // Disabling GmsCompat app breaks the gmscompat layer + keepEnabledPackages.add(com.android.internal.gmscompat.GmsCompatApp.PKG_NAME); + // Disabling GmsCompatConfig breaks updates through Apps app + keepEnabledPackages.add(com.android.internal.gmscompat.GmsCompatApp.PKG_NAME + ".config"); return keepEnabledPackages; } From 482c4f666b240be8e59d0a4d109e89e335a3eb05 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 28 May 2023 18:44:30 +0300 Subject: [PATCH 14/85] do not allow disabling EuiccSupportPixel --- .../applications/ApplicationFeatureProviderImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index 11459fe32e1..e0bc44f3ec3 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -40,6 +40,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.telephony.SmsApplication; +import com.android.internal.util.GoogleEuicc; import com.android.settings.R; import java.util.ArrayList; @@ -198,6 +199,10 @@ private Set getEnabledPackageAllowlist() { keepEnabledPackages.add(com.android.internal.gmscompat.GmsCompatApp.PKG_NAME); // Disabling GmsCompatConfig breaks updates through Apps app keepEnabledPackages.add(com.android.internal.gmscompat.GmsCompatApp.PKG_NAME + ".config"); + + // EuiccSupportPixel handles firmware updates of embedded secure element that is used for eSIM, NFC, Felica etc + keepEnabledPackages.add(GoogleEuicc.EUICC_SUPPORT_PIXEL_PKG_NAME); + return keepEnabledPackages; } From 75b6eed699c37a825d9e4b909372234acc0239ac Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 12 Feb 2023 20:21:09 +0200 Subject: [PATCH 15/85] add a separate file for non-AOSP strings --- res/values/strings_ext.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 res/values/strings_ext.xml diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml new file mode 100644 index 00000000000..6da1fca2c7a --- /dev/null +++ b/res/values/strings_ext.xml @@ -0,0 +1,6 @@ + + + + + + From b1ee62c1c1fa6d7efdc71eacf6d0a4d4a98c5912 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 6 Apr 2023 12:06:11 +0300 Subject: [PATCH 16/85] add a set of base classes for creating Fragment-based preference UI --- res/values/strings_ext.xml | 4 +- .../settings/ext/BoolSettingFragment.java | 149 ++++++++++++++++++ .../BoolSettingFragmentPrefController.java | 26 +++ .../ext/ExtSettingFragmentPrefController.java | 42 +++++ .../settings/ext/FragmentPrefController.java | 36 +++++ 5 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/ext/BoolSettingFragment.java create mode 100644 src/com/android/settings/ext/BoolSettingFragmentPrefController.java create mode 100644 src/com/android/settings/ext/ExtSettingFragmentPrefController.java create mode 100644 src/com/android/settings/ext/FragmentPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 6da1fca2c7a..f249f7fa627 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -1,6 +1,8 @@ - + Enable + Enabled + Disabled diff --git a/src/com/android/settings/ext/BoolSettingFragment.java b/src/com/android/settings/ext/BoolSettingFragment.java new file mode 100644 index 00000000000..12aac5fc4ad --- /dev/null +++ b/src/com/android/settings/ext/BoolSettingFragment.java @@ -0,0 +1,149 @@ +package com.android.settings.ext; + +import android.content.Context; +import android.content.Intent; +import android.ext.settings.BoolSetting; +import android.net.Uri; +import android.os.Bundle; + +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.widget.FooterPreference; + +public abstract class BoolSettingFragment extends DashboardFragment implements ExtSettingPrefController { + + private static final String TAG = BoolSettingFragment.class.getSimpleName(); + + protected SwitchPreference mainSwitch; + protected boolean invertSetting; + + private ExtSettingControllerHelper helper; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + helper = new ExtSettingControllerHelper<>(requireContext(), getSetting()); + + getActivity().setTitle(getTitle()); + + Context ctx = requireContext(); + + PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(ctx); + + var mainSwitch = new SwitchPreference(ctx); + mainSwitch.setTitle(getMainSwitchTitle()); + + this.mainSwitch = mainSwitch; + refreshMainSwitch(); + + mainSwitch.setOnPreferenceChangeListener((preference, newValue) -> { + boolean state = (boolean) newValue; + + if (invertSetting) { + state = !state; + } + + if (!getSetting().put(requireContext(), state)) { + return false; + } + + onMainSwitchChanged(state); + + return true; + }); + + screen.addPreference(mainSwitch); + + addExtraPrefs(screen); + + FooterPreference footer = makeFooterPref(new FooterPreference.Builder(ctx)); + + if (footer != null) { + screen.addPreference(footer); + } + + setPreferenceScreen(screen); + } + + protected abstract BoolSetting getSetting(); + + protected abstract CharSequence getTitle(); + + protected CharSequence getMainSwitchTitle() { + return getText(R.string.bool_setting_enable); + } + + protected CharSequence getMainSwitchSummary() { + return null; + } + + protected void addExtraPrefs(PreferenceScreen screen) {} + + protected FooterPreference makeFooterPref(FooterPreference.Builder builder) { + return null; + } + + protected static void setFooterPrefLearnMoreUri(FooterPreference p, Uri uri) { + p.setLearnMoreAction(v -> { + var intent = new Intent(Intent.ACTION_VIEW, uri); + p.getContext().startActivity(intent); + }); + } + + protected void onMainSwitchChanged(boolean state) {} + + private void refreshMainSwitch() { + boolean state = getSetting().get(requireContext()); + if (invertSetting) { + state = !state; + } + mainSwitch.setChecked(state); + + CharSequence mainSwitchSummary = getMainSwitchSummary(); + if (mainSwitchSummary != null) { + mainSwitch.setSummary(mainSwitchSummary); + } + } + + @Override + public void onResume() { + super.onResume(); + helper.onResume(this); + refreshMainSwitch(); + } + + @Override + public void onPause() { + super.onPause(); + + helper.onPause(this); + } + + @Override + public void accept(BoolSetting setting) { + refreshMainSwitch(); + } + + @Override + public int getMetricsCategory() { + return METRICS_CATEGORY_UNKNOWN; + } + + @Override + protected int getPreferenceScreenResId() { + return 0; + } + + @Override + protected String getLogTag() { + return TAG; + } + + protected final CharSequence resText(int res) { + return requireContext().getText(res); + } +} diff --git a/src/com/android/settings/ext/BoolSettingFragmentPrefController.java b/src/com/android/settings/ext/BoolSettingFragmentPrefController.java new file mode 100644 index 00000000000..3f9223b800a --- /dev/null +++ b/src/com/android/settings/ext/BoolSettingFragmentPrefController.java @@ -0,0 +1,26 @@ +package com.android.settings.ext; + +import android.content.Context; +import android.ext.settings.BoolSetting; + +import com.android.settings.R; + +public abstract class BoolSettingFragmentPrefController extends ExtSettingFragmentPrefController { + + protected BoolSettingFragmentPrefController(Context ctx, String key, BoolSetting setting) { + super(ctx, key, setting); + } + + @Override + public CharSequence getSummary() { + return setting.get(mContext) ? getSummaryOn() : getSummaryOff(); + } + + protected CharSequence getSummaryOn() { + return resText(R.string.bool_setting_enabled); + } + + protected CharSequence getSummaryOff() { + return resText(R.string.bool_setting_disabled); + } +} diff --git a/src/com/android/settings/ext/ExtSettingFragmentPrefController.java b/src/com/android/settings/ext/ExtSettingFragmentPrefController.java new file mode 100644 index 00000000000..2d87635e0d2 --- /dev/null +++ b/src/com/android/settings/ext/ExtSettingFragmentPrefController.java @@ -0,0 +1,42 @@ +package com.android.settings.ext; + +import android.content.Context; +import android.ext.settings.Setting; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; + +public abstract class ExtSettingFragmentPrefController extends FragmentPrefController + implements ExtSettingPrefController { + protected final T setting; + protected final ExtSettingControllerHelper helper; + + protected ExtSettingFragmentPrefController(Context ctx, String key, T setting) { + super(ctx, key); + this.setting = setting; + helper = new ExtSettingControllerHelper(ctx, setting); + } + + @Override + public int getAvailabilityStatus() { + return helper.getAvailabilityStatus(); + } + + @Override + public void onResume(@NonNull LifecycleOwner owner) { + helper.onResume(this); + } + + @Override + public void onPause(@NonNull LifecycleOwner owner) { + helper.onPause(this); + } + + // called by the setting observer + @Override + public void accept(T setting) { + if (preference != null) { + updateState(preference); + } + } +} diff --git a/src/com/android/settings/ext/FragmentPrefController.java b/src/com/android/settings/ext/FragmentPrefController.java new file mode 100644 index 00000000000..b09ab9615c2 --- /dev/null +++ b/src/com/android/settings/ext/FragmentPrefController.java @@ -0,0 +1,36 @@ +package com.android.settings.ext; + +import android.content.Context; + +import androidx.annotation.Nullable; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; + +import com.android.settings.core.BasePreferenceController; + +public abstract class FragmentPrefController + extends BasePreferenceController { + + protected FragmentPrefController(Context ctx, String key) { + super(ctx, key); + } + + @Nullable + protected Preference preference; + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + + if (preference != this.preference) { + preference.setSingleLineTitle(false); + preference.setPersistent(false); + + this.preference = preference; + } + } + + protected final CharSequence resText(int res) { + return mContext.getText(res); + } +} From 66cf104cd40dd4f730f1afe0790326d68fe727a9 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 12 Feb 2023 19:43:44 +0200 Subject: [PATCH 17/85] add base class for ListPreference controllers --- .../ext/AbstractListPreferenceController.java | 235 ++++++++++++++++++ .../ext/RadioButtonPickerFragment2.java | 117 +++++++++ .../widget/RadioButtonPickerFragment.java | 16 +- 3 files changed, 364 insertions(+), 4 deletions(-) create mode 100644 src/com/android/settings/ext/AbstractListPreferenceController.java create mode 100644 src/com/android/settings/ext/RadioButtonPickerFragment2.java diff --git a/src/com/android/settings/ext/AbstractListPreferenceController.java b/src/com/android/settings/ext/AbstractListPreferenceController.java new file mode 100644 index 00000000000..342ffeef5df --- /dev/null +++ b/src/com/android/settings/ext/AbstractListPreferenceController.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2022 GrapheneOS + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.settings.ext; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.UserHandle; +import android.text.TextUtils; +import android.text.format.DateUtils; +import android.util.SparseIntArray; + +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.lifecycle.DefaultLifecycleObserver; +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.core.SubSettingLauncher; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.utils.CandidateInfoExtra; +import com.android.settingslib.widget.CandidateInfo; +import com.android.settingslib.widget.FooterPreference; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +public abstract class AbstractListPreferenceController extends BasePreferenceController + implements DefaultLifecycleObserver { + + private Preference preference; + private Entries entries; + + @Nullable + public RadioButtonPickerFragment2 fragment; + + protected AbstractListPreferenceController(Context ctx, String key) { + super(ctx, key); + } + + // call entries.add(entryName, entryValue) to add entries. + // entryValues can be mapped from other values or sets of values, as long as getCurrentValue() + // and setValue() methods are consistent + protected abstract void getEntries(Entries entries); + + public void getEntriesAsCandidates(ArrayList dst) { + Entries e = new Entries(mContext); + getEntries(e); + + dst.addAll(e.list); + } + + protected abstract int getCurrentValue(); + protected abstract boolean setValue(int val); + + @Override + public void updateState(Preference p) { + if (entries == null) { + entries = new Entries(mContext); + getEntries(entries); + } + + if (p != preference) { + p.setSingleLineTitle(false); + p.setPersistent(false); + this.preference = p; + } + + updatePreference(); + } + + void updatePreference() { + if (fragment != null) { + fragment.updateCandidates(); + } + + Preference p = preference; + if (p == null) { + return; + } + + int idx = entries.getIndexForValue(getCurrentValue()); + if (idx >= 0) { + p.setSummary(entries.list.get(idx).loadLabel()); + } else { + p.setSummary(null); + } + } + + public static class Entries { + private final Context context; + private final ArrayList list = new ArrayList<>(); + private final SparseIntArray valueToIndexMap = new SparseIntArray(); + + Entries(Context context) { + this.context = context; + } + + public void add(@StringRes int title, int value) { + add(context.getText(title), value); + } + + public void add(@StringRes int title, @StringRes int summary, int value) { + add(context.getText(title), context.getText(summary), value); + } + + public void add(int duration, TimeUnit timeUnit) { + long durationMillis = timeUnit.toMillis(duration); + if (durationMillis > Integer.MAX_VALUE) { + throw new IllegalArgumentException(); + } + + add(DateUtils.formatDuration(durationMillis), (int) durationMillis); + } + + public void add(CharSequence title, int value) { + add(title, null, value, true); + } + + public void add(CharSequence title, CharSequence summary, int value) { + add(title, summary, value, true); + } + + public void add(CharSequence title, @Nullable CharSequence summary, int value, boolean enabled) { + String prefKey = Integer.toString(value); + list.add(new CandidateInfoExtra(title, summary, prefKey, enabled)); + valueToIndexMap.put(value, list.size() - 1); + } + + public int getIndexForValue(int val) { + return valueToIndexMap.get(val, -1); + } + } + + @Override + public boolean isSliceable() { + return false; + } + + @Override + public int getSliceHighlightMenuRes() { + return NO_RES; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { + return super.handlePreferenceTreeClick(preference); + } + + if (this.preference instanceof ListPreference) { + return super.handlePreferenceTreeClick(preference); + } + + UserHandle workProfileUser = getWorkProfileUser(); + boolean isForWork = workProfileUser != null; + + RadioButtonPickerFragment2.fillArgs(preference, this, isForWork); + + new SubSettingLauncher(preference.getContext()) + .setDestination(RadioButtonPickerFragment2.class.getName()) + .setSourceMetricsCategory(preference.getExtras().getInt(DashboardFragment.CATEGORY, + SettingsEnums.PAGE_UNKNOWN)) + .setTitleText(preference.getTitle()) + .setArguments(preference.getExtras()) + .setUserHandle(workProfileUser) + .launch(); + return true; + } + + public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) { + + } + + public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) { + + } + + public FooterPreference addFooterPreference(PreferenceScreen screen, @StringRes int text) { + Context ctx = screen.getContext(); + return addFooterPreference(screen, ctx.getText(text), null, null); + } + + public FooterPreference addFooterPreference(PreferenceScreen screen, + @StringRes int text, String learnMoreUrl) { + return addFooterPreference(screen, text, R.string.learn_more, learnMoreUrl); + } + + public FooterPreference addFooterPreference( + PreferenceScreen screen, @StringRes int text, + @StringRes int learnMoreText, String learnMoreUrl) { + Context ctx = screen.getContext(); + Runnable learnMoreAction = () -> { + var intent = new Intent(Intent.ACTION_VIEW, Uri.parse(learnMoreUrl)); + ctx.startActivity(intent); + }; + return addFooterPreference(screen, ctx.getText(text), + ctx.getText(learnMoreText), learnMoreAction); + } + + public FooterPreference addFooterPreference( + PreferenceScreen screen, @StringRes int text, + @StringRes int learnMoreText, Runnable learnMoreAction) { + Context ctx = screen.getContext(); + return addFooterPreference(screen, ctx.getText(text), ctx.getText(learnMoreText), learnMoreAction); + } + + public FooterPreference addFooterPreference(PreferenceScreen screen, CharSequence text, + @Nullable CharSequence learnMoreText, + @Nullable Runnable learnMoreAction) { + var p = new FooterPreference(screen.getContext()); + p.setSelectable(false); + p.setSummary(text); + if (learnMoreText != null) { + p.setLearnMoreText(learnMoreText); + Objects.requireNonNull(learnMoreAction); + p.setLearnMoreAction(v -> learnMoreAction.run()); + } + p.setOrder(Preference.DEFAULT_ORDER); + screen.addPreference(p); + return p; + } + + protected final CharSequence getText(@StringRes int resId) { + return mContext.getText(resId); + } +} diff --git a/src/com/android/settings/ext/RadioButtonPickerFragment2.java b/src/com/android/settings/ext/RadioButtonPickerFragment2.java new file mode 100644 index 00000000000..f6e8b91486c --- /dev/null +++ b/src/com/android/settings/ext/RadioButtonPickerFragment2.java @@ -0,0 +1,117 @@ +package com.android.settings.ext; + +import android.content.Context; +import android.os.Bundle; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.utils.CandidateInfoExtra; +import com.android.settings.widget.RadioButtonPickerFragment; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.widget.CandidateInfo; +import com.android.settingslib.widget.SelectorWithWidgetPreference; + +import java.util.ArrayList; +import java.util.List; + +public class RadioButtonPickerFragment2 extends RadioButtonPickerFragment { + + private final ArrayList candidates = new ArrayList<>(); + + static final String KEY_PREF_CONTROLLER_CLASS = "pref_controller"; + static final String KEY_PREF_KEY = "pref_key"; + + private AbstractListPreferenceController prefController; + + public static void fillArgs(Preference pref, AbstractListPreferenceController pc, boolean isForWork) { + Bundle args = pref.getExtras(); + args.putString(KEY_PREF_CONTROLLER_CLASS, pc.getClass().getName()); + args.putString(KEY_PREF_KEY, pc.getPreferenceKey()); + args.putBoolean(EXTRA_FOR_WORK, isForWork); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + Bundle args = requireArguments(); + String prefControllerClass = args.getString(KEY_PREF_CONTROLLER_CLASS); + String prefKey = args.getString(KEY_PREF_KEY); + boolean forWork = args.getBoolean(EXTRA_FOR_WORK); + + Context ctx = requireContext(); + + prefController = (AbstractListPreferenceController) BasePreferenceController + .createInstance(ctx,prefControllerClass, prefKey, forWork); + prefController.fragment = this; + + super.onCreate(savedInstanceState); + } + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + PreferenceScreen ps = getPreferenceManager().createPreferenceScreen(requireContext()); + setPreferenceScreen(ps); + } + + @Override + protected int getPreferenceScreenResId() { + return -1; + } + + @Override + protected List getCandidates() { + candidates.clear(); + prefController.getEntriesAsCandidates(candidates); + return candidates; + } + + @Override + protected void addPrefsBeforeList(PreferenceScreen screen) { + prefController.addPrefsBeforeList(this, screen); + } + + @Override + protected void addPrefsAfterList(PreferenceScreen screen) { + prefController.addPrefsAfterList(this, screen); + } + + @Override + protected String getDefaultKey() { + return Integer.toString(prefController.getCurrentValue()); + } + + @Override + protected boolean setDefaultKey(String key) { + return prefController.setValue(Integer.parseInt(key)); + } + + @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 + public int getMetricsCategory() { + return METRICS_CATEGORY_UNKNOWN; + } + + @Override + public void onPause() { + super.onPause(); + prefController.onPause(this); + } + + @Override + public void onResume() { + super.onResume(); + prefController.onResume(this); + updateCandidates(); + } +} diff --git a/src/com/android/settings/widget/RadioButtonPickerFragment.java b/src/com/android/settings/widget/RadioButtonPickerFragment.java index 9450bb93715..2cedbdaf42c 100644 --- a/src/com/android/settings/widget/RadioButtonPickerFragment.java +++ b/src/com/android/settings/widget/RadioButtonPickerFragment.java @@ -53,7 +53,7 @@ public abstract class RadioButtonPickerFragment extends SettingsPreferenceFragme SelectorWithWidgetPreference.OnClickListener { @VisibleForTesting - static final String EXTRA_FOR_WORK = "for_work"; + protected static final String EXTRA_FOR_WORK = "for_work"; private static final String TAG = "RadioButtonPckrFrgmt"; @VisibleForTesting boolean mAppendStaticPreferences = false; @@ -157,6 +157,12 @@ public void bindPreferenceExtra(SelectorWithWidgetPreference pref, String key, CandidateInfo info, String defaultKey, String systemDefaultKey) { } + protected void addPrefsBeforeList(PreferenceScreen screen) { + if (!mAppendStaticPreferences) { + addStaticPreferences(screen); + } + } + public void updateCandidates() { mCandidates.clear(); final List candidateList = getCandidates(); @@ -172,9 +178,7 @@ public void updateCandidates() { if (mIllustrationId != 0) { addIllustration(screen); } - if (!mAppendStaticPreferences) { - addStaticPreferences(screen); - } + addPrefsBeforeList(screen); final int customLayoutResId = getRadioButtonPreferenceCustomLayoutResId(); if (shouldShowItemNone()) { @@ -202,6 +206,10 @@ public void updateCandidates() { } } mayCheckOnlyRadioButton(); + addPrefsAfterList(screen); + } + + protected void addPrefsAfterList(PreferenceScreen screen) { if (mAppendStaticPreferences) { addStaticPreferences(screen); } From 0d3b984a543b73798a7fab4e7ae24897bf64c5db Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Tue, 14 Feb 2023 08:45:56 +0200 Subject: [PATCH 18/85] add base class for toggle preference controllers --- .../ext/AbstractTogglePrefController.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/com/android/settings/ext/AbstractTogglePrefController.java diff --git a/src/com/android/settings/ext/AbstractTogglePrefController.java b/src/com/android/settings/ext/AbstractTogglePrefController.java new file mode 100644 index 00000000000..ceee6984bfd --- /dev/null +++ b/src/com/android/settings/ext/AbstractTogglePrefController.java @@ -0,0 +1,38 @@ +package com.android.settings.ext; + +import android.content.Context; + +import androidx.annotation.Nullable; +import androidx.preference.Preference; + +import com.android.settings.core.TogglePreferenceController; + +public abstract class AbstractTogglePrefController extends TogglePreferenceController { + + protected AbstractTogglePrefController(Context ctx, String key) { + super(ctx, key); + } + + @Nullable protected Preference preference; + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + + if (preference != this.preference) { + preference.setSingleLineTitle(false); + preference.setPersistent(false); + this.preference = preference; + } + } + + @Override + public boolean isSliceable() { + return false; + } + + @Override + public int getSliceHighlightMenuRes() { + return NO_RES; + } +} From 4a179a8ddd049c36a1e35a9b47ad0ac821a5026e Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 12 Feb 2023 19:44:07 +0200 Subject: [PATCH 19/85] add base classes for {Bool,Int}Setting preference controllers If no customization is needed, BoolSetting base class can be used directly from XML by adding settings:boolSettingField=" " to the preference XML definition. --- res/values/attrs.xml | 2 + .../core/PreferenceControllerListHelper.java | 3 + .../core/PreferenceXmlParserUtils.java | 12 +++ .../ext/BoolSettingPrefController.java | 90 +++++++++++++++++++ .../ext/ExtSettingControllerHelper.java | 69 ++++++++++++++ .../ext/ExtSettingPrefController.java | 12 +++ .../ext/IntSettingPrefController.java | 57 ++++++++++++ 7 files changed, 245 insertions(+) create mode 100644 src/com/android/settings/ext/BoolSettingPrefController.java create mode 100644 src/com/android/settings/ext/ExtSettingControllerHelper.java create mode 100644 src/com/android/settings/ext/ExtSettingPrefController.java create mode 100644 src/com/android/settings/ext/IntSettingPrefController.java diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 6f024a32be3..0a778da8894 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -68,6 +68,8 @@ + + diff --git a/src/com/android/settings/core/PreferenceControllerListHelper.java b/src/com/android/settings/core/PreferenceControllerListHelper.java index 6d450fe137f..18e67982583 100644 --- a/src/com/android/settings/core/PreferenceControllerListHelper.java +++ b/src/com/android/settings/core/PreferenceControllerListHelper.java @@ -28,6 +28,7 @@ import android.util.Log; import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag; +import com.android.settings.ext.BoolSettingPrefController; import com.android.settingslib.core.AbstractPreferenceController; import org.xmlpull.v1.XmlPullParserException; @@ -56,6 +57,7 @@ public static List getPreferenceControllersFromXml(Con try { preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId, MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER + | MetadataFlag.FLAG_NEED_BOOL_SETTING_FIELD | MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_FOR_WORK); } catch (IOException | XmlPullParserException e) { Log.e(TAG, "Failed to parse preference xml for getting controllers", e); @@ -65,6 +67,7 @@ public static List getPreferenceControllersFromXml(Con for (Bundle metadata : preferenceMetadata) { final String controllerName = metadata.getString(METADATA_CONTROLLER); if (TextUtils.isEmpty(controllerName)) { + BoolSettingPrefController.maybeAdd(context, metadata, controllers); continue; } BasePreferenceController controller; diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java index a1a8d6731a7..d9a1c397b64 100644 --- a/src/com/android/settings/core/PreferenceXmlParserUtils.java +++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java @@ -68,6 +68,7 @@ public class PreferenceXmlParserUtils { MetadataFlag.FLAG_NEED_KEY, MetadataFlag.FLAG_NEED_PREF_TYPE, MetadataFlag.FLAG_NEED_PREF_CONTROLLER, + MetadataFlag.FLAG_NEED_BOOL_SETTING_FIELD, MetadataFlag.FLAG_NEED_PREF_TITLE, MetadataFlag.FLAG_NEED_PREF_SUMMARY, MetadataFlag.FLAG_NEED_PREF_ICON, @@ -91,11 +92,14 @@ public class PreferenceXmlParserUtils { int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 11; int FLAG_FOR_WORK = 1 << 12; int FLAG_NEED_HIGHLIGHTABLE_MENU_KEY = 1 << 13; + + int FLAG_NEED_BOOL_SETTING_FIELD = 1 << 30; } public static final String METADATA_PREF_TYPE = "type"; public static final String METADATA_KEY = "key"; public static final String METADATA_CONTROLLER = "controller"; + public static final String METADATA_BOOL_SETTING_FIELD = "bool_setting_field"; public static final String METADATA_TITLE = "title"; public static final String METADATA_SUMMARY = "summary"; public static final String METADATA_ICON = "icon"; @@ -225,6 +229,10 @@ public static List extractMetadata(Context context, @XmlRes int xmlResId preferenceMetadata.putString(METADATA_CONTROLLER, getController(preferenceAttributes)); } + if (hasFlag(flags, MetadataFlag.FLAG_NEED_BOOL_SETTING_FIELD)) { + preferenceMetadata.putString(METADATA_BOOL_SETTING_FIELD, + getBoolSettingField(preferenceAttributes)); + } if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TITLE)) { preferenceMetadata.putString(METADATA_TITLE, getTitle(preferenceAttributes)); } @@ -321,6 +329,10 @@ private static String getController(TypedArray styledAttributes) { return styledAttributes.getString(R.styleable.Preference_controller); } + private static String getBoolSettingField(TypedArray styledAttributes) { + return styledAttributes.getString(R.styleable.Preference_boolSettingField); + } + private static String getHighlightableMenuKey(TypedArray styledAttributes) { return styledAttributes.getString(R.styleable.Preference_highlightableMenuKey); } diff --git a/src/com/android/settings/ext/BoolSettingPrefController.java b/src/com/android/settings/ext/BoolSettingPrefController.java new file mode 100644 index 00000000000..2d6d668cfc2 --- /dev/null +++ b/src/com/android/settings/ext/BoolSettingPrefController.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 GrapheneOS + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.settings.ext; + +import android.content.Context; +import android.ext.settings.BoolSetting; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; + +import com.android.settings.core.BasePreferenceController; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Objects; + +import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_BOOL_SETTING_FIELD; +import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY; + +public class BoolSettingPrefController extends AbstractTogglePrefController + implements ExtSettingPrefController { + private final BoolSetting setting; + private final ExtSettingControllerHelper helper; + + protected BoolSettingPrefController(Context ctx, String key, BoolSetting setting) { + super(ctx, key); + helper = new ExtSettingControllerHelper(ctx, setting); + this.setting = setting; + } + + @Override + public int getAvailabilityStatus() { + return helper.getAvailabilityStatus(); + } + + @Override + public final boolean isChecked() { + return setting.get(mContext); + } + + @Override + public final boolean setChecked(boolean isChecked) { + return setting.put(mContext, isChecked); + } + + @Override + public void onResume(@NonNull LifecycleOwner owner) { + helper.onResume(this); + } + + @Override + public void onPause(@NonNull LifecycleOwner owner) { + helper.onPause(this); + } + + // called by the setting observer + @Override + public void accept(BoolSetting boolSetting) { + if (preference != null) { + updateState(preference); + } + } + + // called when PreferenceScreen XML is parsed + public static void maybeAdd(Context context, Bundle metadata, + List dest) { + String boolSettingField = metadata.getString(METADATA_BOOL_SETTING_FIELD); + if (boolSettingField == null) { + return; + } + String[] split = boolSettingField.split(" "); + + BoolSetting boolSetting; + try { + Class c = Class.forName(split[0]); + Field field = c.getField(split[1]); + boolSetting = (BoolSetting) Objects.requireNonNull(field.get(null)); + } catch (Exception e) { + throw new IllegalStateException("Invalid BoolSetting field " + boolSettingField); + } + + String key = Objects.requireNonNull(metadata.getString(METADATA_KEY)); + + dest.add(new BoolSettingPrefController(context, key, boolSetting)); + } +} diff --git a/src/com/android/settings/ext/ExtSettingControllerHelper.java b/src/com/android/settings/ext/ExtSettingControllerHelper.java new file mode 100644 index 00000000000..46ad5cfeecf --- /dev/null +++ b/src/com/android/settings/ext/ExtSettingControllerHelper.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 GrapheneOS + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.settings.ext; + +import android.content.ContentResolver; +import android.content.Context; +import android.ext.settings.Setting; +import android.os.Process; +import android.provider.Settings; + +import java.util.function.Consumer; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER; + +public class ExtSettingControllerHelper { + private final Context context; + private final T setting; + + ExtSettingControllerHelper(Context context, T setting) { + this.context = context; + this.setting = setting; + } + + public static int getGlobalSettingAvailability(Context ctx) { + return Process.myUserHandle().isSystem() ? AVAILABLE : DISABLED_FOR_USER; + } + + public static int getDevModeSettingAvailability(Context ctx) { + ContentResolver cr = ctx.getContentResolver(); + String key = Settings.Global.DEVELOPMENT_SETTINGS_ENABLED; + + return (Settings.Global.getInt(cr, key, 0) == 0) ? + CONDITIONALLY_UNAVAILABLE : AVAILABLE; + } + + int getAvailabilityStatus() { + if (setting.getScope() != Setting.Scope.PER_USER) { + return getGlobalSettingAvailability(context); + } + return AVAILABLE; + } + + private Object observer; + + void onResume(ExtSettingPrefController espc) { + registerObserver(espc); + } + + void onPause(ExtSettingPrefController espc) { + unregisterObserver(); + } + + void registerObserver(Consumer settingObserver) { + if (setting.canObserveState()) { + observer = setting.registerObserver(context, settingObserver, context.getMainThreadHandler()); + } + } + + void unregisterObserver() { + if (setting.canObserveState()) { + setting.unregisterObserver(context, observer); + } + } +} diff --git a/src/com/android/settings/ext/ExtSettingPrefController.java b/src/com/android/settings/ext/ExtSettingPrefController.java new file mode 100644 index 00000000000..f641e344b50 --- /dev/null +++ b/src/com/android/settings/ext/ExtSettingPrefController.java @@ -0,0 +1,12 @@ +package com.android.settings.ext; + +import android.ext.settings.Setting; + +import androidx.annotation.NonNull; +import androidx.lifecycle.DefaultLifecycleObserver; +import androidx.lifecycle.LifecycleOwner; + +import java.util.function.Consumer; + +interface ExtSettingPrefController extends DefaultLifecycleObserver, Consumer { +} diff --git a/src/com/android/settings/ext/IntSettingPrefController.java b/src/com/android/settings/ext/IntSettingPrefController.java new file mode 100644 index 00000000000..53f3bf810b9 --- /dev/null +++ b/src/com/android/settings/ext/IntSettingPrefController.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 GrapheneOS + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.settings.ext; + +import android.content.Context; +import android.ext.settings.IntSetting; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; + +public abstract class IntSettingPrefController extends AbstractListPreferenceController + implements ExtSettingPrefController +{ + private final IntSetting setting; + + private final ExtSettingControllerHelper helper; + + protected IntSettingPrefController(Context ctx, String key, IntSetting setting) { + super(ctx, key); + this.setting = setting; + helper = new ExtSettingControllerHelper(ctx, setting); + } + + @Override + public int getAvailabilityStatus() { + return helper.getAvailabilityStatus(); + } + + @Override + protected final int getCurrentValue() { + return setting.get(mContext); + } + + @Override + protected final boolean setValue(int val) { + return setting.put(mContext, val); + } + + @Override + public void onResume(@NonNull LifecycleOwner owner) { + helper.onResume(this); + } + + @Override + public void onPause(@NonNull LifecycleOwner owner) { + helper.onPause(this); + } + + // called by the setting observer + @Override + public void accept(IntSetting intSetting) { + updatePreference(); + } +} From 7e583011b812903ddfd0366ddf1985c45b2dc7ca Mon Sep 17 00:00:00 2001 From: flawedworld <38294951+flawedworld@users.noreply.github.com> Date: Tue, 6 Apr 2021 01:13:36 +0100 Subject: [PATCH 20/85] add device info field with bootloader version --- res/values/strings.xml | 2 ++ res/xml/firmware_version.xml | 9 ++++++ ...BootloaderVersionPreferenceController.java | 28 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 src/com/android/settings/deviceinfo/firmwareversion/BootloaderVersionPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 7fe1daa5cba..2bfb0697f19 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2688,6 +2688,8 @@ Baseband version + Bootloader version + Kernel version Build number diff --git a/res/xml/firmware_version.xml b/res/xml/firmware_version.xml index edc910b36cf..cf9779a6988 100644 --- a/res/xml/firmware_version.xml +++ b/res/xml/firmware_version.xml @@ -46,6 +46,15 @@ settings:enableCopying="true" settings:controller="com.android.settings.deviceinfo.firmwareversion.BasebandVersionPreferenceController"/> + + + Date: Mon, 19 Jul 2021 01:31:27 +0200 Subject: [PATCH 21/85] hide pattern screenlock option --- .../android/settings/password/ChooseLockGenericController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/password/ChooseLockGenericController.java b/src/com/android/settings/password/ChooseLockGenericController.java index cd9eb2fd44d..48dc2094d50 100644 --- a/src/com/android/settings/password/ChooseLockGenericController.java +++ b/src/com/android/settings/password/ChooseLockGenericController.java @@ -175,8 +175,9 @@ public boolean isScreenLockVisible(ScreenLockType type) { && !managedProfile; // Swipe doesn't make sense for profiles. case MANAGED: return mManagedPasswordProvider.isManagedPasswordChoosable(); - case PIN: case PATTERN: + return false; + case PIN: case PASSWORD: // Hide the secure lock screen options if the device doesn't support the secure lock // screen feature. From 052594bc408ea70cf9b33eebc5442ddbd8a525d5 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 25 Jul 2021 14:44:48 -0400 Subject: [PATCH 22/85] drop support for showing nearby devices from Play --- 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 70091998e15..17ffc8b1a7f 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -500,7 +500,7 @@ false - content://com.google.android.gms.nearby.fastpair/device_status_list_item + From dadd0aa7dd9ad41002fe406c1e8c317842cf174b Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 18 Oct 2021 02:17:56 +0000 Subject: [PATCH 23/85] Dark mode support for app installation restriction icon --- res/drawable/ic_settings_install.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/drawable/ic_settings_install.xml b/res/drawable/ic_settings_install.xml index 5bd5e300eae..eefecc242a4 100644 --- a/res/drawable/ic_settings_install.xml +++ b/res/drawable/ic_settings_install.xml @@ -18,7 +18,8 @@ android:width="24dp" android:height="24dp" android:viewportWidth="24" - android:viewportHeight="24"> + android:viewportHeight="24" + android:tint="?android:attr/colorControlNormal"> From 2f1b4214ae572b9698e24cddd3e77f8c321cc7e3 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Wed, 7 Jul 2021 03:02:05 -0700 Subject: [PATCH 24/85] Add preference for increased touch sensitivity (glove mode) This preference controls the glove mode feature on Pixel devices for increased touch sensitivity without requiring a custom HAL or other device-side code. This is done by using the debug.touch_sensitivity_mode system property, which Settings has permission to change. The user-visible value is persisted in Settings.Secure, while the property is persisted in persist.vendor.touch_sensitivity_mode. Requires frameworks/base commit: "Add a config to state whether a device supports increased touch sensitivity." Requires device/google/* commit: "Express support for increased touch sensitivity." Closes: #1 Co-authored-by: Diab Neiroukh Change-Id: I86af721fde33226d314d8a44525f310828299a72 --- res/values/strings.xml | 4 ++ res/xml/display_settings.xml | 6 ++ .../TouchSensitivityPreferenceController.java | 61 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100755 src/com/android/settings/display/TouchSensitivityPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 2bfb0697f19..3f364841ea8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2430,6 +2430,10 @@ Camera access is required for Face Detection. Tap to manage permissions for Device Personalization Services Manage permissions + + Increase touch sensitivity + + Improves touch when using screen protectors Night Light diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml index c5e559cd8a7..514dcba967d 100644 --- a/res/xml/display_settings.xml +++ b/res/xml/display_settings.xml @@ -144,6 +144,12 @@ android:summary="@string/peak_refresh_rate_summary" settings:controller="com.android.settings.display.PeakRefreshRatePreferenceController"/> + + Date: Fri, 21 Jan 2022 22:05:44 +0200 Subject: [PATCH 25/85] add link to Sandboxed Google Play settings add Sandboxed Google Play link for the work profile The link is now dynamic and becomes hidden if GMS Core is uninstalled or disabled. --- res/values/strings.xml | 5 ++ res/xml/apps.xml | 13 ++++ .../applications/GmsCompatAppController.java | 65 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 src/com/android/settings/applications/GmsCompatAppController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 3f364841ea8..627104f09fc 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12316,4 +12316,9 @@ "This app can only be opened in 1 window" + Allow fingerprint unlocking + Allow fingerprints to unlock the screen lock. If this is disabled, fingerprints can still be used in apps. + + Sandboxed Google Play + Sandboxed Google Play (work profile) diff --git a/res/xml/apps.xml b/res/xml/apps.xml index c4313f645e4..440ad50b6ec 100644 --- a/res/xml/apps.xml +++ b/res/xml/apps.xml @@ -126,4 +126,17 @@ + + + + diff --git a/src/com/android/settings/applications/GmsCompatAppController.java b/src/com/android/settings/applications/GmsCompatAppController.java new file mode 100644 index 00000000000..ff8232d3601 --- /dev/null +++ b/src/com/android/settings/applications/GmsCompatAppController.java @@ -0,0 +1,65 @@ +/* + * 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.applications; + +import android.app.compat.gms.GmsCompat; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.UserHandle; +import android.text.TextUtils; + +import androidx.preference.Preference; + +import com.android.internal.gmscompat.GmsCompatApp; +import com.android.internal.gmscompat.GmsInfo; +import com.android.settings.core.BasePreferenceController; + +public class GmsCompatAppController extends BasePreferenceController { + private final Context context; + + public GmsCompatAppController(Context context, String key) { + super(context, key); + this.context = context; + } + + @Override + public int getAvailabilityStatus() { + UserHandle workProfile = getWorkProfileUser(); + int userId = workProfile != null ? + workProfile.getIdentifier() : + UserHandle.myUserId(); + + return GmsCompat.isGmsApp(GmsInfo.PACKAGE_GMS_CORE, userId) ? + AVAILABLE : DISABLED_FOR_USER; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { + return false; + } + Intent intent = new Intent(GmsCompatApp.PKG_NAME + ".SETTINGS_LINK"); + intent.setPackage(GmsCompatApp.PKG_NAME); + + UserHandle workProfile = getWorkProfileUser(); + if (workProfile != null) { + context.startActivityAsUser(intent, workProfile); + } else { + context.startActivity(intent); + } + return true; + } +} From 242471c6090ad76fac6e18c75d88d1ef1cd46b9f Mon Sep 17 00:00:00 2001 From: flawedworld Date: Sat, 5 Mar 2022 17:37:47 +0000 Subject: [PATCH 26/85] Show Hardware SKU in About Phone --- res/values/strings_ext.xml | 1 + res/xml/hardware_info.xml | 9 ++++ .../HardwareSkuPreferenceController.java | 48 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 src/com/android/settings/deviceinfo/hardwareinfo/HardwareSkuPreferenceController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index f249f7fa627..e46c85a4b25 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -1,5 +1,6 @@ + Hardware SKU Enable Enabled diff --git a/res/xml/hardware_info.xml b/res/xml/hardware_info.xml index e086a486ee0..8fef9371870 100644 --- a/res/xml/hardware_info.xml +++ b/res/xml/hardware_info.xml @@ -57,4 +57,13 @@ settings:controller="com.android.settings.deviceinfo.hardwareinfo.ManufacturedYearPreferenceController" settings:enableCopying="true"/> + + + diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/HardwareSkuPreferenceController.java b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareSkuPreferenceController.java new file mode 100644 index 00000000000..4be09710e8c --- /dev/null +++ b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareSkuPreferenceController.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.deviceinfo.hardwareinfo; + +import android.content.Context; +import android.os.SystemProperties; +import android.text.TextUtils; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.slices.Sliceable; + +public class HardwareSkuPreferenceController extends BasePreferenceController { + + public HardwareSkuPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return mContext.getResources().getBoolean(R.bool.config_show_device_model) && + !TextUtils.isEmpty(getSummary()) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public boolean useDynamicSliceSummary() { + return true; + } + + @Override + public CharSequence getSummary() { + return SystemProperties.get("ro.boot.hardware.sku"); + } +} From 9272a5fcf12a2fa48fcfffa165d8b428953927dd Mon Sep 17 00:00:00 2001 From: Chirayu Desai Date: Tue, 3 Mar 2020 18:45:32 +0530 Subject: [PATCH 27/85] Remove empty Security status header Change-Id: Ia09dfd67bcfb8334439bfb9dab419235b182e297 --- res/xml/security_dashboard_settings.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 0550441d3f2..211ff997d1e 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -21,12 +21,6 @@ android:key="security_dashboard_page" android:title="@string/security_settings_title"> - - - From f99288ac9bab58be4f5c971fa733d88a7db0e053 Mon Sep 17 00:00:00 2001 From: Roman Royer Date: Wed, 4 May 2016 19:04:36 -0700 Subject: [PATCH 28/85] Allow sorting Applications by size Allow sorting applications by size in Settings->Apps just like in Settings->Storage/USB->Apps Change-Id: I9e022162110e1feff20f257992086e66735e0f5e --- .../applications/manageapplications/ManageApplications.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index d734a27f033..27dbd80be73 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -850,9 +850,11 @@ void updateOptionsMenu() { } mOptionsMenu.findItem(R.id.advanced).setVisible(false); - mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE + mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible( + (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN) && mSortOrder != R.id.sort_order_alpha); - mOptionsMenu.findItem(R.id.sort_order_size).setVisible(mListType == LIST_TYPE_STORAGE + mOptionsMenu.findItem(R.id.sort_order_size).setVisible( + (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN) && mSortOrder != R.id.sort_order_size); mOptionsMenu.findItem(R.id.show_system).setVisible(!mShowSystem From 8c81124b0ddd23b60b5899b5db450922b9cf0784 Mon Sep 17 00:00:00 2001 From: empratyush Date: Wed, 4 May 2022 20:54:16 +0530 Subject: [PATCH 29/85] add missing face unlock strings for English We would need some kind of automation to do this for all languages. --- res/layout/face_enroll_introduction.xml | 4 ++-- res/values/strings.xml | 12 ++++++++++++ .../biometrics/face/FaceEnrollIntroduction.java | 12 ++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml index 8b0352928ca..ea57f4acbc9 100644 --- a/res/layout/face_enroll_introduction.xml +++ b/res/layout/face_enroll_introduction.xml @@ -64,7 +64,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/BiometricEnrollIntroTitle" - android:text="@string/security_settings_face_enroll_introduction_info_title" /> + android:text="@string/security_settings_face_enroll_introduction_info_title_en" /> + android:text="@string/security_settings_face_enroll_introduction_how_title_en" /> Use your face to unlock your phone, authorize purchases, or sign in to apps + + Keep in mind + How it works + + Glasses or lightly tinted sunglasses are OK. + Looking at the phone can unlock it even when you don’t intend to. Your phone can also be unlocked by someone who looks a lot like you, like an identical sibling, or if someone holds it up to your face. + Using a face to unlock the phone may be less secure than a strong pattern or PIN. + Face Unlock can require your eyes to be open to unlock the phone or verify it’s you. You can turn this option on at any time in Settings. + Face Unlock creates a unique model of your face to verify it’s you. To create this face model during setup, you will take images of your face from different angles.\n\nWhen you use Face Unlock, images are used to update your face model. Images used to create your face model are not stored, but the face model is stored securely on your phone and never leaves the phone. All processing occurs securely on your phone. + You’re in control + You can delete your face model or turn off Face Unlock at any time in Settings. Face models are stored on the phone until you delete them.\n\nLearn more at g.co/pixel/faceunlock. + diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java index bea0c3389ec..155d540b6cd 100644 --- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java +++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java @@ -357,32 +357,32 @@ protected boolean generateChallengeOnCreate() { @StringRes protected int getInfoMessageGlasses() { - return R.string.security_settings_face_enroll_introduction_info_glasses; + return R.string.security_settings_face_enroll_introduction_info_glasses_en; } @StringRes protected int getInfoMessageLooking() { - return R.string.security_settings_face_enroll_introduction_info_looking; + return R.string.security_settings_face_enroll_introduction_info_looking_en; } @StringRes protected int getInfoMessageRequireEyes() { - return R.string.security_settings_face_enroll_introduction_info_gaze; + return R.string.security_settings_face_enroll_introduction_info_gaze_en; } @StringRes protected int getHowMessage() { - return R.string.security_settings_face_enroll_introduction_how_message; + return R.string.security_settings_face_enroll_introduction_how_message_en; } @StringRes protected int getInControlTitle() { - return R.string.security_settings_face_enroll_introduction_control_title; + return R.string.security_settings_face_enroll_introduction_control_title_en; } @StringRes protected int getInControlMessage() { - return R.string.security_settings_face_enroll_introduction_control_message; + return R.string.security_settings_face_enroll_introduction_control_message_en; } @StringRes From fca9fecb715d028b94113b3c3c3ee8abccf3d997 Mon Sep 17 00:00:00 2001 From: June Date: Wed, 16 Mar 2022 07:09:46 +0200 Subject: [PATCH 30/85] add a per-user setting for forwarding censored notifs Signed-off-by: June Co-authored-by: inthewaves Co-authored-by: June --- res/values/strings.xml | 3 + res/xml/user_settings.xml | 6 ++ ...ionsToCurrentUserPreferenceController.java | 60 +++++++++++++++++++ .../android/settings/users/UserSettings.java | 19 ++++++ 4 files changed, 88 insertions(+) create mode 100644 src/com/android/settings/users/SendCensoredNotificationsToCurrentUserPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 9055a0e64c7..f064381b136 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12331,6 +12331,9 @@ Allow fingerprint unlocking Allow fingerprints to unlock the screen lock. If this is disabled, fingerprints can still be used in apps. + Send notifications to current user + Your lock screen notifications will be forwarded to the current user if you are active in the background. Only the user\'s name, the app\'s name, and the time received will be shown. + Sandboxed Google Play Sandboxed Google Play (work profile) diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml index 59217226592..6c7ac2c091a 100644 --- a/res/xml/user_settings.xml +++ b/res/xml/user_settings.xml @@ -100,4 +100,10 @@ android:fragment="com.android.settings.users.TimeoutToDockUserSettings" settings:controller="com.android.settings.users.TimeoutToDockUserPreferenceController"/> + + diff --git a/src/com/android/settings/users/SendCensoredNotificationsToCurrentUserPreferenceController.java b/src/com/android/settings/users/SendCensoredNotificationsToCurrentUserPreferenceController.java new file mode 100644 index 00000000000..637d7bbb782 --- /dev/null +++ b/src/com/android/settings/users/SendCensoredNotificationsToCurrentUserPreferenceController.java @@ -0,0 +1,60 @@ +package com.android.settings.users; + +import android.content.Context; +import android.provider.Settings; +import android.widget.Toast; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; + +public class SendCensoredNotificationsToCurrentUserPreferenceController + extends TogglePreferenceController { + private final UserCapabilities mUserCaps; + + public SendCensoredNotificationsToCurrentUserPreferenceController(Context context, String key) { + super(context, key); + mUserCaps = UserCapabilities.create(context); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + mUserCaps.updateAddUserCapabilities(mContext); + if (!isAvailable()) { + preference.setVisible(false); + } else { + preference.setVisible(mUserCaps.mUserSwitcherEnabled); + } + } + + @Override + public int getAvailabilityStatus() { + return mUserCaps.mUserSwitcherEnabled ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public boolean isChecked() { + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.SEND_CENSORED_NOTIFICATIONS_TO_CURRENT_USER, 0) != 0; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.SEND_CENSORED_NOTIFICATIONS_TO_CURRENT_USER, isChecked ? 1 : 0); + } + + @Override + public CharSequence getSummary() { + return mContext.getString( + R.string.user_settings_send_censored_notifications_to_current_summary); + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_system; + } +} diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java index b0816fdf4ad..018a267cdcf 100644 --- a/src/com/android/settings/users/UserSettings.java +++ b/src/com/android/settings/users/UserSettings.java @@ -137,6 +137,8 @@ public class UserSettings extends SettingsPreferenceFragment private static final String KEY_REMOVE_GUEST_ON_EXIT = "remove_guest_on_exit"; private static final String KEY_GUEST_USER_CATEGORY = "guest_user_category"; private static final String KEY_ALLOW_MULTIPLE_USERS = "allow_multiple_users"; + private static final String KEY_SEND_CENSORED_NOTIFICATIONS = + "user_settings_send_censored_notifications_to_current"; private static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in"; @@ -225,6 +227,7 @@ public class UserSettings extends SettingsPreferenceFragment private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController; private GuestTelephonyPreferenceController mGuestTelephonyPreferenceController; private RemoveGuestOnExitPreferenceController mRemoveGuestOnExitPreferenceController; + private SendCensoredNotificationsToCurrentUserPreferenceController mSendCensoredNotificationsToCurrentUserPreferenceController; private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController; private TimeoutToDockUserPreferenceController mTimeoutToDockUserPreferenceController; private UserCreatingDialog mUserCreatingDialog; @@ -322,6 +325,10 @@ public void onCreate(Bundle icicle) { mRemoveGuestOnExitPreferenceController = new RemoveGuestOnExitPreferenceController( activity, KEY_REMOVE_GUEST_ON_EXIT, this, mHandler); + mSendCensoredNotificationsToCurrentUserPreferenceController = + new SendCensoredNotificationsToCurrentUserPreferenceController(activity, + KEY_SEND_CENSORED_NOTIFICATIONS); + mMultiUserTopIntroPreferenceController = new MultiUserTopIntroPreferenceController(activity, KEY_MULTIUSER_TOP_INTRO); @@ -332,11 +339,14 @@ public void onCreate(Bundle icicle) { mAddUserWhenLockedPreferenceController.displayPreference(screen); mGuestTelephonyPreferenceController.displayPreference(screen); mRemoveGuestOnExitPreferenceController.displayPreference(screen); + mSendCensoredNotificationsToCurrentUserPreferenceController.displayPreference(screen); mMultiUserTopIntroPreferenceController.displayPreference(screen); mTimeoutToDockUserPreferenceController.displayPreference(screen); screen.findPreference(mAddUserWhenLockedPreferenceController.getPreferenceKey()) .setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController); + screen.findPreference(mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey()) + .setOnPreferenceChangeListener(mSendCensoredNotificationsToCurrentUserPreferenceController); screen.findPreference(mGuestTelephonyPreferenceController.getPreferenceKey()) .setOnPreferenceChangeListener(mGuestTelephonyPreferenceController); @@ -420,6 +430,9 @@ public void onResume() { mTimeoutToDockUserPreferenceController.getPreferenceKey())); mRemoveGuestOnExitPreferenceController.updateState(screen.findPreference( mRemoveGuestOnExitPreferenceController.getPreferenceKey())); + mSendCensoredNotificationsToCurrentUserPreferenceController.updateState(screen.findPreference( + mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey())); + if (mShouldUpdateUserList) { updateUI(); } @@ -1303,6 +1316,10 @@ void updateUserList() { mGuestTelephonyPreferenceController.getPreferenceKey()); mGuestTelephonyPreferenceController.updateState(guestCallPreference); + final Preference sendCensoredNotifs = getPreferenceScreen().findPreference( + mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey()); + mSendCensoredNotificationsToCurrentUserPreferenceController.updateState(sendCensoredNotifs); + final Preference multiUserTopIntroPreference = getPreferenceScreen().findPreference( mMultiUserTopIntroPreferenceController.getPreferenceKey()); mMultiUserTopIntroPreferenceController.updateState(multiUserTopIntroPreference); @@ -1744,6 +1761,8 @@ public List getNonIndexableKeysFromXml(Context context, int xmlResId, new AddUserWhenLockedPreferenceController( context, KEY_ADD_USER_WHEN_LOCKED); controller.updateNonIndexableKeys(niks); + new SendCensoredNotificationsToCurrentUserPreferenceController(context, + KEY_SEND_CENSORED_NOTIFICATIONS).updateNonIndexableKeys(niks); new AutoSyncDataPreferenceController(context, null /* parent */) .updateNonIndexableKeys(niks); new AutoSyncPersonalDataPreferenceController(context, null /* parent */) From d93d60ec1e89c4cb25b490710404de79fbe41965 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 17 Aug 2022 12:40:26 -0400 Subject: [PATCH 31/85] fully enable location indicators by default --- .../location/LocationIndicatorsPreferenceController.java | 2 +- .../location/RecentLocationAccessPreferenceController.java | 6 +++--- .../location/RecentLocationAccessSeeAllFragment.java | 6 +++--- .../RecentLocationAccessSeeAllPreferenceController.java | 4 ++-- .../location/RecentLocationRequestPreferenceController.java | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/location/LocationIndicatorsPreferenceController.java b/src/com/android/settings/location/LocationIndicatorsPreferenceController.java index 75ffb3a9286..1b1af8f8f73 100644 --- a/src/com/android/settings/location/LocationIndicatorsPreferenceController.java +++ b/src/com/android/settings/location/LocationIndicatorsPreferenceController.java @@ -34,7 +34,7 @@ public LocationIndicatorsPreferenceController(Context context, String preference @Override public boolean isChecked() { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - Utils.PROPERTY_LOCATION_INDICATORS_ENABLED, false); + Utils.PROPERTY_LOCATION_INDICATORS_ENABLED, true); } @Override diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java index 61682d00a8c..6b28d921efa 100644 --- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java +++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java @@ -48,7 +48,7 @@ public class RecentLocationAccessPreferenceController extends LocationBasePrefer RecentAppOpsAccess mRecentLocationApps; private PreferenceCategory mCategoryRecentLocationRequests; private int mType = ProfileSelectFragment.ProfileType.ALL; - private boolean mShowSystem = false; + private boolean mShowSystem = true; private boolean mSystemSettingChanged = false; private static class PackageEntryClickedListener implements @@ -85,9 +85,9 @@ public RecentLocationAccessPreferenceController(Context context, String key, super(context, key); mRecentLocationApps = recentLocationApps; mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; } diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java index 0ea9ffbdacb..b45bca51c4f 100644 --- a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java +++ b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java @@ -40,7 +40,7 @@ public class RecentLocationAccessSeeAllFragment extends DashboardFragment { private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 1; private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 2; - private boolean mShowSystem = false; + private boolean mShowSystem = true; private MenuItem mShowSystemMenu; private MenuItem mHideSystemMenu; private RecentLocationAccessSeeAllPreferenceController mController; @@ -61,9 +61,9 @@ public void onAttach(Context context) { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; } diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java index d6586673f89..abda482a1e5 100644 --- a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java +++ b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java @@ -51,9 +51,9 @@ public class RecentLocationAccessSeeAllPreferenceController public RecentLocationAccessSeeAllPreferenceController(Context context, String key) { super(context, key); mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; mRecentLocationAccesses = RecentAppOpsAccess.createForLocation(context); diff --git a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java index 39211ee5202..bee904efdc4 100644 --- a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java +++ b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java @@ -87,9 +87,9 @@ public void displayPreference(PreferenceScreen screen) { final List recentLocationRequests = new ArrayList<>(); final UserManager userManager = UserManager.get(mContext); final boolean showSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) + SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true) ? Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 + Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1 : false; for (RecentLocationApps.Request request : mRecentLocationApps.getAppListSorted( From 2cdf4547a7df4860631b46bdc0186459929463cb Mon Sep 17 00:00:00 2001 From: renlord Date: Fri, 15 Oct 2021 20:02:51 +0530 Subject: [PATCH 32/85] add option to always randomize MAC RANDOMIZATION_ALWAYS is set as the default option --- res/layout/wifi_network_config.xml | 2 +- res/values/arrays.xml | 7 +++++ res/xml/wifi_network_details_fragment2.xml | 2 +- .../WifiDetailPreferenceController2.java | 2 +- .../WifiPrivacyPreferenceController2.java | 28 +++++++++++++++---- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/res/layout/wifi_network_config.xml b/res/layout/wifi_network_config.xml index 6fe39bf0261..7752f70532b 100644 --- a/res/layout/wifi_network_config.xml +++ b/res/layout/wifi_network_config.xml @@ -693,7 +693,7 @@ android:layout_height="wrap_content" style="@style/wifi_item_spinner" android:prompt="@string/wifi_privacy_settings" - android:entries="@array/wifi_privacy_entries"/> + android:entries="@array/wifi_privacy_entries_extended"/> Treat as unmetered + + Use per-connection randomized MAC (default) + Use per-network randomized MAC + Use device MAC + + Use randomized MAC (default) Use device MAC @@ -1076,6 +1082,7 @@ + 100 1 0 diff --git a/res/xml/wifi_network_details_fragment2.xml b/res/xml/wifi_network_details_fragment2.xml index 00624749377..88b245adc49 100644 --- a/res/xml/wifi_network_details_fragment2.xml +++ b/res/xml/wifi_network_details_fragment2.xml @@ -94,7 +94,7 @@ android:key="privacy" android:icon="@drawable/ic_wifi_privacy_24dp" android:title="@string/wifi_privacy_settings" - android:entries="@array/wifi_privacy_entries" + android:entries="@array/wifi_privacy_entries_extended" android:entryValues="@array/wifi_privacy_values"/> Date: Fri, 19 Aug 2022 11:05:36 +0530 Subject: [PATCH 33/85] LTE Only Mode Co-authored-by: inthewaves Squashed with: Fix LTE Only mode on World Mode Co-authored-by: flawedworld --- res/values/strings.xml | 6 +++++ ...nabledNetworkModePreferenceController.java | 24 ++++++++++++++++++- ...ferredNetworkModePreferenceController.java | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index f064381b136..18d9d56c8f7 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10799,6 +10799,8 @@ Preferred network mode: CDMA/EvDo/GSM/WCDMA Preferred network mode: LTE + + Preferred network mode: LTE only Preferred network mode: GSM/WCDMA/LTE @@ -10864,8 +10866,12 @@ 4G LTE (recommended) + + LTE only 4G (recommended) + + 4G only 3G diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index 9fb80a5d412..3d7d6a85ab6 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -91,7 +91,7 @@ public int getAvailabilityStatus(int subId) { CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL) || carrierConfig.getBoolean( CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL)) { - visible = false; + visible = true; } else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) { visible = false; } else if (!isCallStateIdle()) { @@ -276,6 +276,7 @@ public void updateConfig() { } void setPreferenceEntries() { + boolean lteOnlyUnsupported = false; mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId); clearAllEntries(); @@ -291,6 +292,7 @@ void setPreferenceEntries() { .addFormat(UiOptions.PresentFormat.addGlobalEntry); break; case ENABLED_NETWORKS_CDMA_NO_LTE_CHOICES: + lteOnlyUnsupported = true; uiOptions = uiOptions .setChoices(R.array.enabled_networks_cdma_no_lte_values) .addFormat(UiOptions.PresentFormat.add3gEntry) @@ -310,6 +312,7 @@ void setPreferenceEntries() { .addFormat(UiOptions.PresentFormat.add2gEntry); break; case ENABLED_NETWORKS_EXCEPT_GSM_LTE_CHOICES: + lteOnlyUnsupported = true; uiOptions = uiOptions .setChoices(R.array.enabled_networks_except_gsm_lte_values) .addFormat(UiOptions.PresentFormat.add3gEntry); @@ -327,6 +330,7 @@ void setPreferenceEntries() { .addFormat(UiOptions.PresentFormat.add3gEntry); break; case ENABLED_NETWORKS_EXCEPT_LTE_CHOICES: + lteOnlyUnsupported = true; uiOptions = uiOptions .setChoices(R.array.enabled_networks_except_lte_values) .addFormat(UiOptions.PresentFormat.add3gEntry) @@ -375,6 +379,11 @@ void setPreferenceEntries() { throw new IllegalArgumentException( uiOptions.getType().name() + " index error."); } + + if (!lteOnlyUnsupported){ + addLteOnlyEntry(); + } + // Compose options based on given values and formats. IntStream.range(0, formatList.size()).forEach(entryIndex -> { switch (formatList.get(entryIndex)) { @@ -561,6 +570,9 @@ void setPreferenceValueAndSummary(int networkMode) { break; } case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY: + setSummary(mShow4gForLTE + ? R.string.network_4G_only : R.string.network_lte_only); + break; case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA: if (!mIsGlobalCdma) { setSelectedEntry( @@ -826,6 +838,16 @@ private void add1xEntry(int value) { mEntriesValue.add(value); } + private void addLteOnlyEntry() { + if (mShow4gForLTE) { + mEntries.add(mContext.getString(R.string.network_4G_only)); + mEntriesValue.add(TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY); + } else { + mEntries.add(mContext.getString(R.string.network_lte_only)); + mEntriesValue.add(TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY); + } + } + private void addCustomEntry(String name, int value) { mEntries.add(name); mEntriesValue.add(value); diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java index bdfeace1be6..535645a8647 100644 --- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java @@ -137,7 +137,7 @@ private int getPreferredNetworkModeSummaryResId(int NetworkMode) { case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA: return R.string.preferred_network_mode_lte_tdscdma_summary; case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY: - return R.string.preferred_network_mode_lte_summary; + return R.string.preferred_network_mode_lte_only_summary; case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM: return R.string.preferred_network_mode_lte_tdscdma_gsm_summary; case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA: From 73f4588db11811439961eb68c1486e2e114eb7ca Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 13 Nov 2022 20:24:05 +0200 Subject: [PATCH 34/85] battery usage UI: use a fallback name for unknown components --- .../settings/fuelgauge/batteryusage/BatteryEntry.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java index 86538ee8811..f0e157525e0 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java @@ -572,9 +572,10 @@ public static NameAndIcon getNameAndIconFromPowerComponent( iconId = R.drawable.ic_settings_aod; break; default: - Log.w(TAG, "unknown attribute:" + DebugUtils.constantToString( - BatteryConsumer.class, "POWER_COMPONENT_", powerComponentId)); - name = null; + String fieldName = DebugUtils.constantToString( + BatteryConsumer.class, "POWER_COMPONENT_", powerComponentId); + Log.w(TAG, "unknown attribute:" + fieldName); + name = context.getResources().getString(R.string.header_category_system) + " (" + fieldName + ")"; iconId = R.drawable.ic_power_system; break; } From 933a5d18fc50ff0a495c96fc910d5d3761862f36 Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Thu, 9 Jun 2022 11:27:32 +0200 Subject: [PATCH 35/85] 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 f4d7607c85e..37a502895ae 100644 --- a/res/xml/double_tap_power_settings.xml +++ b/res/xml/double_tap_power_settings.xml @@ -24,7 +24,7 @@ + app:lottie_rawRes="@raw/lottie_quickly_open_camera"/> Date: Tue, 14 Feb 2023 10:05:57 +0200 Subject: [PATCH 36/85] add a toggle for auto-grants of OTHER_SENSORS permission --- res/values/strings_ext.xml | 4 ++++ res/xml/privacy_dashboard_settings.xml | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index e46c85a4b25..5777e48d296 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -6,4 +6,8 @@ Enabled Disabled + 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/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml index d84dca536b8..4553010cdc9 100644 --- a/res/xml/privacy_dashboard_settings.xml +++ b/res/xml/privacy_dashboard_settings.xml @@ -85,6 +85,13 @@ android:summary="@string/mic_toggle_description" settings:controller="com.android.settings.privacy.MicToggleController"/> + + Date: Tue, 14 Feb 2023 10:27:56 +0200 Subject: [PATCH 37/85] add a toggle for camera access from the lock screen --- res/values/strings_ext.xml | 2 ++ res/xml/security_dashboard_settings.xml | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 5777e48d296..76ed86af267 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -10,4 +10,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 the device is locked + diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 211ff997d1e..dcd82af2ae5 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -49,6 +49,12 @@ android:summary="@string/summary_placeholder" settings:keywords="@string/keywords_face_settings" /> + + - \ No newline at end of file + From 8711a407ba13f9416638411b01ad38798ba8ff13 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Tue, 14 Feb 2023 11:23:29 +0200 Subject: [PATCH 38/85] add auto-reboot setting Squashed with: 20d4d3e46ba4a626d6044df499b91c1fc5e5bd96 514f0ddf2adbb7b69b0750806020476cef8ed17e Co-authored-by: Daniel Micay --- res/values/strings_ext.xml | 3 ++ res/xml/security_dashboard_settings.xml | 5 +++ .../security/AutoRebootPrefController.java | 44 +++++++++++++++++++ 3 files changed, 52 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 76ed86af267..c0fdec85619 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -12,4 +12,7 @@ Allow camera access when the device is locked + Auto reboot + Automatically reboot the device if it hasn\'t been unlocked within the selected duration of time. + diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index dcd82af2ae5..0b88f619819 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -49,6 +49,11 @@ android:summary="@string/summary_placeholder" settings:keywords="@string/keywords_face_settings" /> + + Date: Sat, 18 Feb 2023 11:09:31 -0500 Subject: [PATCH 39/85] Add toggle for screenshot timestamp EXIF metadata Signed-off-by: r3g_5z --- res/values/strings_ext.xml | 3 +++ res/xml/privacy_dashboard_settings.xml | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index c0fdec85619..29819695086 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -15,4 +15,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/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml index 4553010cdc9..ece8fab41a2 100644 --- a/res/xml/privacy_dashboard_settings.xml +++ b/res/xml/privacy_dashboard_settings.xml @@ -92,6 +92,13 @@ 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 40/85] add GNSS SUPL setting --- res/values/strings_ext.xml | 8 +++++ res/xml/location_settings.xml | 5 ++++ .../location/GnssSuplPrefController.java | 30 +++++++++++++++++++ 3 files changed, 43 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 29819695086..bd2a571bbca 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -18,4 +18,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. + + Enabled (GrapheneOS proxy) + Enabled (standard server) + Disabled + Will make acquiring location lock significantly slower, especially if PSDS is disabled too + diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml index fe87efd73d7..7f9f45378c3 100644 --- a/res/xml/location_settings.xml +++ b/res/xml/location_settings.xml @@ -66,6 +66,11 @@ android:title="@string/location_services_preference_title" settings:controller="com.android.settings.location.LocationServicesPreferenceController"/> + + Date: Sat, 18 Feb 2023 10:08:21 -0500 Subject: [PATCH 41/85] add PIN scrambling setting Signed-off-by: r3g_5z --- res/values/strings_ext.xml | 2 ++ res/xml/security_dashboard_settings.xml | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index bd2a571bbca..a05671e2577 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -26,4 +26,6 @@ Disabled Will make acquiring location lock significantly slower, especially if PSDS is disabled too + Scramble PIN input layout + diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 0b88f619819..43f880c07c5 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -54,6 +54,11 @@ android:title="@string/auto_reboot_title" settings:controller="com.android.settings.security.AutoRebootPrefController" /> + + Date: Mon, 16 Oct 2023 09:42:40 -0400 Subject: [PATCH 42/85] 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 ed155bcb10c..29988582a5e 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -976,9 +976,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 2e4ed9eb214133fe5d2b5baf282ee89184585178 Mon Sep 17 00:00:00 2001 From: r3g_5z Date: Wed, 15 Mar 2023 21:11:12 -0400 Subject: [PATCH 43/85] 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 daf1793f11f..9954efb1dca 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()); @@ -222,7 +221,6 @@ protected boolean setDefaultKey(final String key) { } setDisplayMode(width); - updateIllustrationImage(mImagePreference); return true; } From 85e6d629ff14175a5e47abe763ddad941f7bc7fc Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 19 Mar 2022 12:01:00 +0200 Subject: [PATCH 44/85] add toggle for the privileged eSIM management --- res/values/strings_ext.xml | 6 + res/xml/network_provider_internet.xml | 9 + .../network/GoogleEuiccLpaController.java | 174 ++++++++++++++++++ 3 files changed, 189 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 a05671e2577..2ce08456abf 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -28,4 +28,10 @@ Scramble PIN input layout + Enable privileged eSIM management + Requires sandboxed Google Play installation + Device restart is required to disable this setting. + Restart + Device restart is required to allow enabling this setting. + diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml index ef6ed16f73f..7cf29452cf8 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -55,6 +55,15 @@ settings:useAdminDisabledSummary="true" settings:searchable="@bool/config_show_sim_info"/> + + { + var pm = mContext.getSystemService(PowerManager.class); + pm.reboot(null); + }); + b.show(); + return false; + } + + if (!GoogleEuicc.checkLpaDependencies()) { + // this is a race condition, toggle hasn't been grayed out yet + return false; + } + + ContentResolver cr = mContext.getContentResolver(); + + if (Settings.Global.getInt(cr, Settings.Global.BOOT_COUNT, 0) == 1) { + // When BOOT_COUNT is 1, Google's LPA assumes that it was started together with Google's + // SetupWizard, and changes its behavior in unwanted ways. + // + // To avoid this, require a reboot, which will increment BOOT_COUNT + + var b = new AlertDialog.Builder(mContext); + b.setMessage(R.string.privileged_euicc_management_restart_due_to_first_boot); + b.setPositiveButton(R.string.privileged_euicc_management_restart_button, (dialogInterface, btn) -> { + var pm = mContext.getSystemService(PowerManager.class); + pm.reboot(null); + }); + b.show(); + return false; + } + + PermissionManager permissionManager = mContext.getSystemService(PermissionManager.class); + + try { + String pkg = GoogleEuicc.LPA_PKG_NAME; + + UserHandle user = mContext.getUser(); + String perm = Manifest.permission.CAMERA; + permissionManager.revokeRuntimePermission(pkg, perm, user, null); + // Previously, Camera permission was auto-granted with the FLAG_PERMISSION_SYSTEM_FIXED, + // which made it unchangeable by the user. + // Removing FLAG_PERMISSION_USER_FIXED is needed to make sure that the app is always + // able to show a permission request dialog after being enabled + int permFlagsToRemove = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED + | PackageManager.FLAG_PERMISSION_USER_FIXED; + permissionManager.updatePermissionFlags(pkg, perm, permFlagsToRemove, 0, user); + + packageManager.setApplicationEnabledSetting(pkg, COMPONENT_ENABLED_STATE_ENABLED, 0); + { + // Google's LPA expects to be enabled at boot, when ACTION_LOCKED_BOOT_COMPLETED + // is normally sent. + // Upon receiving this broadcast, it performs additional initialization that is + // skipped otherwise, see RestoreUiccSlotSettingsOnBootReceiver and CompleteBootService + var intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED); + intent.setPackage(pkg); + mContext.sendBroadcast(intent); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + private final BroadcastReceiver packageChangeListener = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (preference != null) { + updateState(preference); + } + } + }; + + @Override + public void onResume(@NonNull LifecycleOwner owner) { + var f = new IntentFilter(); + f.addAction(Intent.ACTION_PACKAGE_ADDED); + f.addAction(Intent.ACTION_PACKAGE_CHANGED); + f.addAction(Intent.ACTION_PACKAGE_REMOVED); + f.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); + + f.addDataScheme("package"); + for (String pkg : GoogleEuicc.getLpaDependencies()) { + f.addDataSchemeSpecificPart(pkg, PatternMatcher.PATTERN_LITERAL); + } + + f.addDataSchemeSpecificPart(GoogleEuicc.LPA_PKG_NAME, PatternMatcher.PATTERN_LITERAL); + + mContext.registerReceiver(packageChangeListener, f); + } + + @Override + public void onPause(@NonNull LifecycleOwner owner) { + mContext.unregisterReceiver(packageChangeListener); + } +} From 8fa7d44c27765883a3977199104d097d452f261d Mon Sep 17 00:00:00 2001 From: r3g_5z Date: Sun, 2 Apr 2023 22:23:41 -0400 Subject: [PATCH 45/85] 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 | 37 +++++++++++++++++++ 3 files changed, 48 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 2ce08456abf..ef3330acfd9 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -34,4 +34,9 @@ Restart Device restart is required to allow enabling this setting. + Attestation key provisioning + Enabled (GrapheneOS proxy) + Enabled (Google server) + Disabled + diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml index 7cf29452cf8..65e61eb71dc 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -138,4 +138,10 @@ android:summary="@string/summary_placeholder" android:order="25" settings:controller="com.android.settings.network.AdaptiveConnectivityPreferenceController"/> + + diff --git a/src/com/android/settings/network/RemoteProvisioningPrefController.java b/src/com/android/settings/network/RemoteProvisioningPrefController.java new file mode 100644 index 00000000000..64155249c91 --- /dev/null +++ b/src/com/android/settings/network/RemoteProvisioningPrefController.java @@ -0,0 +1,37 @@ +/* + * 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.ExtSettings; +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, ExtSettings.REMOTE_KEY_PROVISIONING_SERVER); + } + + @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 449384ccbe8eb399499586822a2ae1da7bdf91a9 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 6 Apr 2023 12:11:09 +0300 Subject: [PATCH 46/85] 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 ef3330acfd9..b8d5bb7cd7e 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -39,4 +39,19 @@ Enabled (Google server) Disabled + 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 b3f3f7dd5da..f890a6b7000 100644 --- a/res/xml/special_access.xml +++ b/res/xml/special_access.xml @@ -219,4 +219,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 5c95fa9a2fd6a44dbf80983a3aab8c896da6bbf5 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 3 May 2023 08:57:01 +0300 Subject: [PATCH 47/85] add GNSS PSDS setting --- res/values/strings_ext.xml | 11 ++++ res/xml/location_settings.xml | 5 ++ .../location/GnssPsdsPrefController.java | 52 +++++++++++++++++++ 3 files changed, 68 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 b8d5bb7cd7e..500217f6929 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -54,4 +54,15 @@ Examples of such apps: This setting applies to all users on the device." + Predicted Satellite Data Service (PSDS) + +"If PSDS is enabled, 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." + + Enabled (GrapheneOS server) + Enabled (Qualcomm server) + Enabled (standard server) + Disabled + Will make acquiring location lock significantly slower, especially if SUPL is disabled too + diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml index 7f9f45378c3..eff9d20af55 100644 --- a/res/xml/location_settings.xml +++ b/res/xml/location_settings.xml @@ -71,6 +71,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 48/85] add connectivity checks setting --- res/values/strings_ext.xml | 10 +++++++ res/xml/network_provider_internet.xml | 6 ++++ .../ConnectivityChecksPrefController.java | 30 +++++++++++++++++++ 3 files changed, 46 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 500217f6929..3731b82f6de 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -65,4 +65,14 @@ No query or data is sent to the server. These files contain orbits and statuses Disabled Will make acquiring location lock significantly slower, especially if SUPL is disabled too + GrapheneOS server + Standard (Google) server + Disabled + + 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 65e61eb71dc..825e0f98b80 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -139,6 +139,12 @@ android:order="25" settings:controller="com.android.settings.network.AdaptiveConnectivityPreferenceController"/> + + Date: Wed, 24 May 2023 14:57:01 +0300 Subject: [PATCH 49/85] 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 3731b82f6de..8366d62f67a 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 ba3c97dc311b55a3e91f499ba7f661165efb5fe0 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 25 May 2023 16:25:33 +0300 Subject: [PATCH 50/85] add Wi-Fi auto-off setting --- res/values/strings_ext.xml | 2 + res/xml/wifi_configure_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 8366d62f67a..fade43178e6 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -76,4 +76,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/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml index 2ab7b6a28fe..d8833ef3216 100644 --- a/res/xml/wifi_configure_settings.xml +++ b/res/xml/wifi_configure_settings.xml @@ -34,6 +34,11 @@ settings:keywords="@string/keywords_wifi_notify_open_networks" settings:controller="com.android.settings.wifi.NotifyOpenNetworksPreferenceController"/> + + Date: Wed, 24 May 2023 15:01:04 +0300 Subject: [PATCH 51/85] add Bluetooth auto-off setting --- res/values/strings_ext.xml | 6 +++ res/xml/bluetooth_screen.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 fade43178e6..b973136e3f7 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -78,4 +78,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/bluetooth_screen.xml b/res/xml/bluetooth_screen.xml index 86dc8a12c72..fa7f59e3b91 100644 --- a/res/xml/bluetooth_screen.xml +++ b/res/xml/bluetooth_screen.xml @@ -36,6 +36,11 @@ settings:searchable="false" settings:controller="com.android.settings.connecteddevice.AddDevicePreferenceController"/> + + Date: Wed, 24 May 2023 18:23:22 +0300 Subject: [PATCH 52/85] add deny_new_usb setting --- res/values/strings_ext.xml | 7 ++ res/xml/security_dashboard_settings.xml | 5 ++ .../security/DenyNewUsbPrefController.java | 77 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/com/android/settings/security/DenyNewUsbPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index b973136e3f7..38cfff9be3c 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -84,4 +84,11 @@ 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." + USB peripherals + This feature exists to reduce attack surface, especially for a locked device. + + Allow new USB peripherals + Allow new USB peripherals when unlocked + Disallow new USB peripherals + diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 43f880c07c5..208cc6d08f6 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -54,6 +54,11 @@ android:title="@string/auto_reboot_title" settings:controller="com.android.settings.security.AutoRebootPrefController" /> + + list = Arrays.asList( + DENY_NEW_USB_DISABLED, + DENY_NEW_USB_DYNAMIC, + DENY_NEW_USB_ENABLED + ); + + public DenyNewUsbPrefController(Context ctx, String key) { + super(ctx, key); + } + + @Override + public int getAvailabilityStatus() { + return getGlobalSettingAvailability(mContext); + } + + @Override + protected void getEntries(Entries entries) { + entries.add(R.string.deny_new_usb_val_enabled, list.indexOf(DENY_NEW_USB_ENABLED)); + entries.add(R.string.deny_new_usb_val_dynamic, list.indexOf(DENY_NEW_USB_DYNAMIC)); + entries.add(R.string.deny_new_usb_val_disabled, list.indexOf(DENY_NEW_USB_DISABLED)); + } + + @Override + public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) { + addFooterPreference(screen, R.string.deny_new_usb_footer, + "https://grapheneos.org/usage#usb-peripherals"); + } + + @Override + protected int getCurrentValue() { + return list.indexOf(ExtSettings.DENY_NEW_USB.get()); + } + + @Override + protected boolean setValue(int val) { + String strVal = list.get(val); + boolean res = ExtSettings.DENY_NEW_USB.put(strVal); + if (!res) { + return false; + } + if (DENY_NEW_USB_DYNAMIC.equals(strVal)) { + // when "dynamic" is written to the sysprop, the following hook is triggered in + // system/core/rootdir/init.rc : + + // on property:persist.security.deny_new_usb=dynamic + // - write /proc/sys/kernel/deny_new_usb 1 + + // But the fact that the setting was set by the user implies that the device is unlocked, + // and deny_new_usb should be disabled until the device gets locked + SystemProperties.set(ExtSettings.DENY_NEW_USB_TRANSIENT_PROP, + ExtSettings.DENY_NEW_USB_TRANSIENT_DISABLE); + } + return true; + } +} From b017c600e8fd86e951a9328daeca102fb960e1b8 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 25 May 2023 16:47:42 +0300 Subject: [PATCH 53/85] add exec spawning setting --- res/values/strings_ext.xml | 4 +++ res/xml/security_dashboard_settings.xml | 6 ++++ .../security/ExecSpawningFragment.java | 34 +++++++++++++++++++ .../security/ExecSpawningPrefController.java | 13 +++++++ 4 files changed, 57 insertions(+) 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 38cfff9be3c..5a0ece12f97 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -91,4 +91,8 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. Allow new USB peripherals when unlocked Disallow new USB peripherals + 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/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 208cc6d08f6..07dc3aa714b 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -59,6 +59,12 @@ android:title="@string/deny_new_usb_title" settings:controller="com.android.settings.security.DenyNewUsbPrefController" /> + + Date: Sun, 25 Jun 2023 13:53:58 +0100 Subject: [PATCH 54/85] 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 f8d77a5e7c1f8a71a46b2d36513f045bc88513e8 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 55/85] Remove "Add users from lock screen" setting --- .../users/AddUserWhenLockedPreferenceController.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java index ce5533e5c64..0983648d47d 100644 --- a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java +++ b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java @@ -50,13 +50,7 @@ public void updateState(Preference preference) { @Override public int getAvailabilityStatus() { - if (!mUserCaps.isAdmin()) { - return DISABLED_FOR_USER; - } else if (mUserCaps.disallowAddUser() || mUserCaps.disallowAddUserSetByAdmin()) { - return DISABLED_FOR_USER; - } else { - return mUserCaps.mUserSwitcherEnabled ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; - } + return UNSUPPORTED_ON_DEVICE; } @Override From 2c8e9f4a524c56700f67b32a4d3730acf3c6ccd4 Mon Sep 17 00:00:00 2001 From: Pratyush Date: Sat, 3 Sep 2022 15:52:37 +0530 Subject: [PATCH 56/85] 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 402d4b18dd4..fe6bd8d6e0a 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; @@ -403,7 +403,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 7c0d29e440817897df700a32ef87e834262704fa 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 57/85] Factor out common code for reading/writing UserManager restrictions --- .../settings/users/UserDetailsSettings.java | 11 +++-- .../settings/users/UserRestrictions.java | 49 +++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) 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 fe6bd8d6e0a..91d36934e93 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() { @@ -340,6 +341,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); @@ -388,6 +390,7 @@ void initialize(Context context, Bundle arguments) { removePreference(KEY_APP_AND_CONTENT_ACCESS); } + mPhonePref.setChecked(!userRestrictions.isSet(UserManager.DISALLOW_OUTGOING_CALLS)); if (mUserInfo.isGuest()) { removePreference(KEY_ENABLE_TELEPHONY); mRemoveUserPref.setTitle(mGuestUserAutoCreated @@ -400,8 +403,6 @@ void initialize(Context context, Bundle arguments) { removePreference(KEY_APP_COPYING); } } else { - mPhonePref.setChecked(!mUserManager.hasUserRestriction( - UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId))); mRemoveUserPref.setTitle(R.string.user_remove_user); } @@ -473,9 +474,9 @@ void switchUser() { private void enableCallsAndSms(boolean enabled) { mPhonePref.setChecked(enabled); - UserHandle userHandle = UserHandle.of(mUserInfo.id); - mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, !enabled, userHandle); - mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle); + userRestrictions.set(UserManager.DISALLOW_OUTGOING_CALLS, !enabled); + // SMS is always disabled for guest + userRestrictions.set(UserManager.DISALLOW_SMS, mUserInfo.isGuest() || !enabled); } /** diff --git a/src/com/android/settings/users/UserRestrictions.java b/src/com/android/settings/users/UserRestrictions.java new file mode 100644 index 00000000000..3daa2c453dc --- /dev/null +++ b/src/com/android/settings/users/UserRestrictions.java @@ -0,0 +1,49 @@ +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) { + Bundle defaultGuestRestrictions = userManager.getDefaultGuestRestrictions(); + if (userInfo.isGuest()) { + defaultGuestRestrictions.putBoolean(restrictionKey, enableRestriction); + userManager.setDefaultGuestRestrictions(defaultGuestRestrictions); + + List users = userManager.getAliveUsers(); + for (UserInfo user : users) { + if (user.isGuest()) { + UserHandle userHandle = userInfo.getUserHandle(); + for (String key : defaultGuestRestrictions.keySet()) { + userManager.setUserRestriction( + key, defaultGuestRestrictions.getBoolean(key), userHandle); + } + } + } + } else { + userManager.setUserRestriction(restrictionKey, enableRestriction, userInfo.getUserHandle()); + } + } +} From ba6f1846bc3ff84943c30503a9a88b83ad45557d 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 58/85] 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 5a0ece12f97..76525a3cd3c 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -95,4 +95,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 068039cbd04..5ce43027662 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 91d36934e93..5f9187f7182 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 SwitchPreference mGrantAdminPref; + Preference mAppsInstallsPref; @VisibleForTesting /** The user being studied (not the user doing the studying). */ @@ -131,6 +134,8 @@ public void onResume() { if (mGuestUserAutoCreated) { mRemoveUserPref.setEnabled((mUserInfo.flags & UserInfo.FLAG_INITIALIZED) != 0); } + mAppsInstallsPref.setSummary(UserAppsInstallSettings.getDescription( + requireContext(), userRestrictions)); } @Override @@ -171,6 +176,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; } @@ -351,6 +359,7 @@ void initialize(Context context, Bundle arguments) { mGrantAdminPref = findPreference(KEY_GRANT_ADMIN); mGrantAdminPref.setChecked(mUserInfo.isAdmin()); + mAppsInstallsPref = findPreference(KEY_APP_INSTALLS); mSwitchUserPref.setTitle( context.getString(com.android.settingslib.R.string.user_switch_to_user, @@ -374,6 +383,7 @@ void initialize(Context context, Bundle arguments) { removePreference(KEY_GRANT_ADMIN); 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); @@ -415,6 +425,7 @@ void initialize(Context context, Bundle arguments) { } mRemoveUserPref.setOnPreferenceClickListener(this); + mAppsInstallsPref.setOnPreferenceClickListener(this); mPhonePref.setOnPreferenceChangeListener(this); mGrantAdminPref.setOnPreferenceChangeListener(this); mAppAndContentAccessPref.setOnPreferenceClickListener(this); From 6eb72c7c180602c78f751284c7a8bd46b659b848 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 59/85] UserManager settings for running in background --- res/values/strings_ext.xml | 2 ++ res/xml/user_details_settings.xml | 4 ++++ .../android/settings/users/UserDetailsSettings.java | 12 ++++++++++++ 3 files changed, 18 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 76525a3cd3c..1108deabaa0 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -105,5 +105,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 5ce43027662..e2aa90cfdad 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 60/85] 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 4b449b01945..86685839971 100644 --- a/src/com/android/settings/users/UserDetailsSettings.java +++ b/src/com/android/settings/users/UserDetailsSettings.java @@ -138,6 +138,7 @@ public void onResume() { } mAppsInstallsPref.setSummary(UserAppsInstallSettings.getDescription( requireContext(), userRestrictions)); + mAppCopyingPref.setEnabled(!userRestrictions.isSet(UserManager.DISALLOW_INSTALL_APPS)); } @Override From 55c68909b55e81ee5d55274d014c9b874ac5383b Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Mon, 15 May 2023 15:41:39 +0300 Subject: [PATCH 61/85] add a base class for extra "App info" screen links --- .../ext/AppInfoPreferenceControllerBase2.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/com/android/settings/ext/AppInfoPreferenceControllerBase2.java diff --git a/src/com/android/settings/ext/AppInfoPreferenceControllerBase2.java b/src/com/android/settings/ext/AppInfoPreferenceControllerBase2.java new file mode 100644 index 00000000000..d0794d13925 --- /dev/null +++ b/src/com/android/settings/ext/AppInfoPreferenceControllerBase2.java @@ -0,0 +1,37 @@ +package com.android.settings.ext; + +import android.content.Context; +import android.content.pm.GosPackageState; +import android.text.TextUtils; + +import androidx.preference.Preference; + +import com.android.settings.applications.appinfo.AppInfoPreferenceControllerBase; + +public abstract class AppInfoPreferenceControllerBase2 extends AppInfoPreferenceControllerBase { + + protected AppInfoPreferenceControllerBase2(Context ctx, String key) { + super(ctx, key); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { + return false; + } + + onPreferenceClick(getPackageName()); + return true; + } + + public abstract void onPreferenceClick(String packageName); + + protected boolean hasGosPackageStateFlags(int flags) { + var ps = GosPackageState.get(getPackageName()); + return ps != null && ps.hasFlags(flags); + } + + protected String getPackageName() { + return mParent.getPackageInfo().packageName; + } +} From 1de683dc982b582270826b898e0acabc49627a6e Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 2 Jul 2022 09:41:50 +0300 Subject: [PATCH 62/85] add Storage Scopes link to the "App info" screen --- res/values/strings.xml | 2 ++ res/xml/app_info_settings.xml | 5 ++++ .../appinfo/AppInfoDashboardFragment.java | 1 + .../AppStorageScopesPreferenceController.java | 24 +++++++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppStorageScopesPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 18d9d56c8f7..50ac0755985 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12342,4 +12342,6 @@ Sandboxed Google Play Sandboxed Google Play (work profile) + + Storage Scopes diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index 73241b705f4..53d5678a323 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -59,6 +59,11 @@ settings:summaryLineCount="1" settings:controller="com.android.settings.applications.appinfo.AppPermissionPreferenceController" /> + + Date: Tue, 11 Apr 2023 17:59:17 +0300 Subject: [PATCH 63/85] add Storage Scopes link to "All files access" screen --- .../appinfo/ManageExternalStorageDetails.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/com/android/settings/applications/appinfo/ManageExternalStorageDetails.java b/src/com/android/settings/applications/appinfo/ManageExternalStorageDetails.java index 6c840d5d94d..517f75ff5c1 100644 --- a/src/com/android/settings/applications/appinfo/ManageExternalStorageDetails.java +++ b/src/com/android/settings/applications/appinfo/ManageExternalStorageDetails.java @@ -16,6 +16,7 @@ package com.android.settings.applications.appinfo; import android.app.AppOpsManager; +import android.app.StorageScope; import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; @@ -68,6 +69,8 @@ public void onCreate(Bundle savedInstanceState) { mMetricsFeatureProvider = FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider(); + + addStorageScopesLink(); } @Override @@ -176,4 +179,11 @@ private static CharSequence getSummary(Context context, PermissionState state) { ? R.string.app_permission_summary_allowed : R.string.app_permission_summary_not_allowed); } + + private void addStorageScopesLink() { + Preference p = new Preference(requireContext()); + p.setTitle(R.string.storage_scopes); + p.setIntent(StorageScope.createConfigActivityIntent(mPackageName)); + getPreferenceScreen().addPreference(p); + } } From ae18a00efe32b4f00e504c274a15a7021fda788c Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Fri, 8 Jul 2022 13:40:22 +0300 Subject: [PATCH 64/85] add OBB access toggle to "Install unknown apps" screen --- res/values/strings.xml | 3 + .../appinfo/ExternalSourcesDetails.java | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/res/values/strings.xml b/res/values/strings.xml index 50ac0755985..5ebcbf682e7 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12344,4 +12344,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/applications/appinfo/ExternalSourcesDetails.java b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java index b7232744365..f1ab2820520 100644 --- a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java +++ b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java @@ -21,6 +21,7 @@ import android.app.AppOpsManager; import android.app.settings.SettingsEnums; import android.content.Context; +import android.content.pm.GosPackageState; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; @@ -133,6 +134,9 @@ protected boolean refreshUi() { return true; } mSwitchPref.setChecked(mInstallAppsState.canInstallApps()); + + setupObbToggle(); + return true; } @@ -145,4 +149,55 @@ protected AlertDialog createDialog(int id, int errorCode) { public int getMetricsCategory() { return SettingsEnums.MANAGE_EXTERNAL_SOURCES; } + + private RestrictedSwitchPreference mObbPref; + + private void setupObbToggle() { + RestrictedSwitchPreference p = mObbPref; + if (p == null) { + if (!GosPackageState.attachableToPackage(mPackageName)) { + return; + } + p = createObbToggle(); + mSwitchPref.getParent().addPreference(p); + mObbPref = p; + } + + boolean canInstallApps = mInstallAppsState.canInstallApps(); + + if (!canInstallApps) { + p.setChecked(false); + p.callChangeListener(Boolean.FALSE); + } else { + GosPackageState ps = GosPackageState.get(mPackageName); + p.setChecked(ps != null && ps.hasFlag(GosPackageState.FLAG_ALLOW_ACCESS_TO_OBB_DIRECTORY)); + } + + p.setEnabled(canInstallApps); + } + + private RestrictedSwitchPreference createObbToggle() { + RestrictedSwitchPreference p = new RestrictedSwitchPreference(mSwitchPref.getContext()); + p.setTitle(R.string.allow_access_to_obb_directory_title); + p.setSummary(R.string.allow_access_to_obb_directory_summary); + + p.setOnPreferenceChangeListener((preference, checkedB) -> { + var ps = GosPackageState.get(mPackageName); + boolean curValue = ps != null && ps.hasFlag(GosPackageState.FLAG_ALLOW_ACCESS_TO_OBB_DIRECTORY); + + if (curValue == (boolean) checkedB) { + return true; + } + + GosPackageState.edit(mPackageName) + .setFlagsState(GosPackageState.FLAG_ALLOW_ACCESS_TO_OBB_DIRECTORY, (boolean) checkedB) + // storage mount modes can't be updated dynamically + .killUidAfterApply() + .apply(); + + return true; + }); + + return p; + } } From 3ecd86ef9f51a0d8c84d90b3eb0e17e7f82ead23 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 21 Sep 2022 19:23:25 +0300 Subject: [PATCH 65/85] show more APK details on App info screen --- res/values/strings.xml | 3 ++ .../AppVersionPreferenceController.java | 40 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 5ebcbf682e7..a722a9aca54 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12347,4 +12347,7 @@ Allow access to Android/obb folder Required for installation of some large apps (mostly games) that use OBB expansion files + + Installed: %1$s + Updated: %1$s diff --git a/src/com/android/settings/applications/appinfo/AppVersionPreferenceController.java b/src/com/android/settings/applications/appinfo/AppVersionPreferenceController.java index 23dd9602f77..734bd6ff476 100644 --- a/src/com/android/settings/applications/appinfo/AppVersionPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppVersionPreferenceController.java @@ -22,6 +22,9 @@ import com.android.settings.R; +import java.text.DateFormat; +import java.util.Date; + public class AppVersionPreferenceController extends AppInfoPreferenceControllerBase { public AppVersionPreferenceController(Context context, String key) { @@ -36,7 +39,40 @@ public CharSequence getSummary() { if (packageInfo == null) { return null; } - return mContext.getString(R.string.version_text, - BidiFormatter.getInstance().unicodeWrap(packageInfo.versionName)); + + Context ctx = mContext; + + DateFormat dateFormat = android.text.format.DateFormat.getMediumDateFormat(ctx); + DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(ctx); + + String times = null; + if (packageInfo.firstInstallTime != 0) { + String s = formatDate(packageInfo.firstInstallTime, dateFormat, timeFormat); + times = ctx.getString(R.string.app_info_install_time, s); + } + + if (packageInfo.lastUpdateTime != 0 && packageInfo.lastUpdateTime != packageInfo.firstInstallTime) { + String s = formatDate(packageInfo.lastUpdateTime, dateFormat, timeFormat); + String updateTime = ctx.getString(R.string.app_info_update_time, s); + if (times != null) { + times += '\n' + updateTime; + } else { + times = updateTime; + } + } + + return ctx.getString(R.string.version_text, + BidiFormatter.getInstance().unicodeWrap(packageInfo.versionName)) + + "\n\n" + packageInfo.packageName + + "\nversionCode " + packageInfo.getLongVersionCode() + + "\n\ntargetSdk " + packageInfo.applicationInfo.targetSdkVersion + + "\nminSdk " + packageInfo.applicationInfo.minSdkVersion + + (times != null ? ("\n\n" + times) : "") + ; + } + + private static String formatDate(long unixTs, DateFormat dateFormat, DateFormat timeFormat) { + Date d = new Date(unixTs); + return dateFormat.format(d) + "; " + timeFormat.format(d); } } From 50dce5de7549b3e5a7a4ed32284e327c5ed4b981 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Mon, 15 May 2023 15:42:11 +0300 Subject: [PATCH 66/85] add Contact Scopes link to the "App info" screen --- res/values/strings_ext.xml | 2 ++ res/xml/app_info_settings.xml | 6 +++++ .../AppContactScopesPreferenceController.java | 24 +++++++++++++++++++ .../appinfo/AppInfoDashboardFragment.java | 1 + 4 files changed, 33 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppContactScopesPreferenceController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 1108deabaa0..cdb541a627e 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -66,6 +66,8 @@ No query or data is sent to the server. These files contain orbits and statuses Disabled Will make acquiring location lock significantly slower, especially if SUPL is disabled too + Contact Scopes + GrapheneOS server Standard (Google) server Disabled diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index 53d5678a323..628f9722265 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -64,6 +64,12 @@ android:title="@string/storage_scopes" settings:controller="com.android.settings.applications.appinfo.AppStorageScopesPreferenceController" /> + + + Date: Sun, 17 Apr 2022 18:00:53 +0300 Subject: [PATCH 67/85] add an ability to disable non-system apps from the "App info" screen --- .../AppButtonsPreferenceController.java | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java index ff191ab4476..fa415d6e053 100644 --- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java @@ -205,6 +205,15 @@ public void onDestroy() { } private class UninstallAndDisableButtonListener implements View.OnClickListener { + private boolean mChangeEnabledStateOfUserApp; + + UninstallAndDisableButtonListener() { + this(false); + } + + UninstallAndDisableButtonListener(boolean changeEnabledStateOfUserApp) { + mChangeEnabledStateOfUserApp = changeEnabledStateOfUserApp; + } @Override public void onClick(View v) { @@ -236,8 +245,13 @@ public void onClick(View v) { mUserId); if (admin != null && !uninstallBlockedBySystem) { RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mActivity, admin); - } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0 || mChangeEnabledStateOfUserApp) { if (mAppEntry.info.enabled && !isDisabledUntilUsed()) { + if (mChangeEnabledStateOfUserApp) { + handleDialogClick(ButtonActionDialogFragment.DialogType.DISABLE); + return; + } + showDialogInner(ButtonActionDialogFragment.DialogType.DISABLE); } else { mMetricsFeatureProvider.action( @@ -468,6 +482,25 @@ void updateUninstallButton() { } mButtonsPref.setButton2Enabled(enabled); + + if (enabled && !isBundled) { + // "enabled" means "show uninstall button" in this context + int text; + int icon; + if (mAppEntry.info.enabled) { + text = R.string.disable_text; + icon = R.drawable.ic_settings_disable; + } else { + text = R.string.enable_text; + icon = R.drawable.ic_settings_enable; + } + mButtonsPref + .setButton4Text(text) + .setButton4Icon(icon) + .setButton4Visible(true) + .setButton4OnClickListener(new UninstallAndDisableButtonListener(true)) + ; + } } /** @@ -491,7 +524,9 @@ private void refreshAndFinishIfPossible(boolean removeTaskWhenFinishing) { @VisibleForTesting void updateForceStopButton() { - if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) { + if (!mPackageInfo.applicationInfo.enabled) { + mButtonsPref.setButton3Visible(false); + } else if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) { // User can't force stop device admin. Log.w(TAG, "User can't force stop device admin"); updateForceStopButtonInner(false /* enabled */); @@ -516,6 +551,7 @@ void updateForceStopButton() { @VisibleForTesting void updateForceStopButtonInner(boolean enabled) { + mButtonsPref.setButton3Visible(true); if (mAppsControlDisallowedBySystem) { mButtonsPref.setButton3Enabled(false); } else { @@ -530,6 +566,7 @@ void uninstallPkg(String packageName, boolean allUsers) { Uri packageUri = Uri.parse("package:" + packageName); Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri); uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, allUsers); + uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_SHOW_MORE_OPTIONS_BUTTON, false); mMetricsFeatureProvider.action(mActivity, SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP); mFragment.startActivityForResult(uninstallIntent, mRequestUninstall); From 9019f4cdd6df64dc3c85695c4089ea7f80a559a4 Mon Sep 17 00:00:00 2001 From: empratyush Date: Mon, 20 Jun 2022 22:16:29 +0300 Subject: [PATCH 68/85] 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 31895db32b1..51b4aa0d342 100644 --- a/Android.bp +++ b/Android.bp @@ -104,6 +104,7 @@ android_library { "Settings-change-ids", "androidx.room_room-runtime", "SystemUIUnfoldLib", + "ReverseWirelessCharging" ], plugins: ["androidx.room_room-compiler-plugin"], diff --git a/res/values/strings.xml b/res/values/strings.xml index a722a9aca54..a4dd51d9cf3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12350,4 +12350,7 @@ Installed: %1$s Updated: %1$s + + 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 121e1fe9628..e35c53a89e2 100644 --- a/res/xml/power_usage_summary.xml +++ b/res/xml/power_usage_summary.xml @@ -57,6 +57,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); + ((SwitchPreference) 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 898241f29d73ed95d28341bf75e8468133c5f0c3 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Fri, 15 Sep 2023 10:03:16 +0300 Subject: [PATCH 69/85] 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 17ffc8b1a7f..54b8ee7ce44 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -587,7 +587,7 @@ content://com.android.providers.media.documents/root/documents_root - true + false Allow running in background + "Warning: enabling this setting might cause some apps to stop working. + + Default value can be overridden per-app from the App info screen 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); + } +} diff --git a/src/com/android/settings/ext/DefaultOfPerAppSettingFragment.java b/src/com/android/settings/ext/DefaultOfPerAppSettingFragment.java new file mode 100644 index 00000000000..fca6febcedf --- /dev/null +++ b/src/com/android/settings/ext/DefaultOfPerAppSettingFragment.java @@ -0,0 +1,14 @@ +package com.android.settings.ext; + +import android.content.res.Resources; + +import androidx.annotation.StringRes; + +import com.android.settings.R; + +public abstract class DefaultOfPerAppSettingFragment extends BoolSettingFragment { + + protected CharSequence getMainSwitchSummary() { + return getText(R.string.summary_of_default_of_per_app_setting); + } +} From b2949bdf2db927289b1ec26eefd296243b91af0e Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:44:08 +0200 Subject: [PATCH 72/85] add base class for App info single-choice fragments --- .../appinfo/RadioButtonAppInfoFragment.java | 156 ++++++++++++++++++ 1 file changed, 156 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..4e2da7917f1 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java @@ -0,0 +1,156 @@ +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 androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.applications.AppInfoWithHeader; +import com.android.settingslib.widget.FooterPreference; +import com.android.settingslib.widget.SelectorWithWidgetPreference; + +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; + + @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); + } + + 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; + } + + @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 6645e59704341dbc0d8025ff4d9ceb8be4083102 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:44:23 +0200 Subject: [PATCH 73/85] add base classes for AppSwitch UIs --- res/values/strings_app_exploit_protection.xml | 25 +++ .../applications/appinfo/AswAdapter.kt | 38 +++++ .../appinfo/AswAppInfoFragment.java | 155 ++++++++++++++++++ .../appinfo/AswExploitProtectionFragment.java | 44 +++++ .../applications/appinfo/AswPrefController.kt | 11 ++ 5 files changed, 273 insertions(+) create mode 100644 res/values/strings_app_exploit_protection.xml create mode 100644 src/com/android/settings/applications/appinfo/AswAdapter.kt create mode 100644 src/com/android/settings/applications/appinfo/AswAppInfoFragment.java create mode 100644 src/com/android/settings/applications/appinfo/AswExploitProtectionFragment.java create mode 100644 src/com/android/settings/applications/appinfo/AswPrefController.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..6dacd66c2e2 --- /dev/null +++ b/res/values/strings_app_exploit_protection.xml @@ -0,0 +1,25 @@ + + + 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 Security 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 Security section. + + %1$s is enabled + + Exploit protection compatibility mode + diff --git a/src/com/android/settings/applications/appinfo/AswAdapter.kt b/src/com/android/settings/applications/appinfo/AswAdapter.kt new file mode 100644 index 00000000000..35b74b7091a --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AswAdapter.kt @@ -0,0 +1,38 @@ +package com.android.settings.applications.appinfo + +import android.content.Context +import android.content.pm.ApplicationInfo +import android.content.pm.GosPackageState +import android.ext.settings.app.AppSwitch +import androidx.annotation.StringRes +import com.android.settings.R + +abstract class AswAdapter(val context: Context, val userId: Int = context.userId) { + abstract fun getAppSwitch(): T + + fun getPreferenceSummary(appInfo: ApplicationInfo): CharSequence { + val asw = getAppSwitch() + val si = AppSwitch.StateInfo() + val isOn = asw.get(context, userId, appInfo, GosPackageState.get(appInfo.packageName, userId), si) + return if (si.isUsingDefaultValue) { + getDefaultTitle(isOn) + } else { + if (isOn) getOnTitle() else getOffTitle() + } + } + + abstract fun getAswTitle(): CharSequence + + fun getDefaultTitle(isOn: Boolean): CharSequence { + return context.getString(R.string.aep_default, + if (isOn) getOnTitle() else getOffTitle()) + } + + open fun getOnTitle(): CharSequence = getText(R.string.aep_enabled) + + open fun getOffTitle(): CharSequence = getText(R.string.aep_disabled) + + protected fun getText(@StringRes id: Int): CharSequence = context.getText(id) + + protected fun getString(@StringRes id: Int): String = context.getString(id) +} diff --git a/src/com/android/settings/applications/appinfo/AswAppInfoFragment.java b/src/com/android/settings/applications/appinfo/AswAppInfoFragment.java new file mode 100644 index 00000000000..d8d101eb676 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AswAppInfoFragment.java @@ -0,0 +1,155 @@ +package com.android.settings.applications.appinfo; + +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; + +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 createAswAdapter(Context ctx); + + protected AswAdapter adapter; + + @Override + public void onCreate(Bundle savedInstanceState) { + adapter = createAswAdapter(requireContext()); + super.onCreate(savedInstanceState); + } + + @Override + protected CharSequence getTitle() { + return adapter.getAswTitle(); + } + + @Override + public Entry[] getEntries() { + Context ctx = adapter.getContext(); + AppSwitch asw = adapter.getAppSwitch(); + + int userId = mUserId; + var 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(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_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 -> { + var s = defaultValue ? adapter.getOnTitle() : adapter.getOffTitle(); + yield getString(R.string.aep_dvr_compat_config_hardening_opt_out, s.toString()); + } + default -> null; + }; + } + def.summary = summary; + } + + var enabled = createEntry(ID_ON, adapter.getOnTitle()); + enabled.isChecked = !isDefault && state; + enabled.isEnabled = enabled.isChecked || !isImmutable; + + var disabled = createEntry(ID_OFF, adapter.getOffTitle()); + 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; + } + } + + return new Entry[] { def, enabled, disabled }; + } + + @Nullable + protected CharSequence getSummaryForDefaultValueReason(int dvr) { + return null; + } + + @Nullable + protected CharSequence getSummaryForImmutabilityReason(int ir) { + return null; + } + + @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/appinfo/AswExploitProtectionFragment.java b/src/com/android/settings/applications/appinfo/AswExploitProtectionFragment.java new file mode 100644 index 00000000000..6369749592f --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AswExploitProtectionFragment.java @@ -0,0 +1,44 @@ +package com.android.settings.applications.appinfo; + +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/applications/appinfo/AswPrefController.kt b/src/com/android/settings/applications/appinfo/AswPrefController.kt new file mode 100644 index 00000000000..5b0a37e82b4 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AswPrefController.kt @@ -0,0 +1,11 @@ +package com.android.settings.applications.appinfo + +import android.content.Context +import android.ext.settings.app.AppSwitch + +abstract class AswPrefController(ctx: Context, key: String, + val adapter: AswAdapter, +) : AppInfoPreferenceControllerBase(ctx, key) { + + override fun getSummary() = adapter.getPreferenceSummary(mAppEntry.info) +} From cdf19248311f9ff718fde967face5e408cb6bd77 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:44:56 +0200 Subject: [PATCH 74/85] add "Exploit protection" category to App info --- res/xml/app_info_settings.xml | 7 +++++++ ...ppExploitProtectionPrefCategoryController.java | 10 ++++++++++ .../appinfo/AppInfoDashboardFragment.java | 15 +++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppExploitProtectionPrefCategoryController.java diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index 628f9722265..faf9bc0db1c 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -210,6 +210,13 @@ + + + + AppInfoPreferenceControllerBase prepare(Class cls) { + T res = use(cls); + res.setParentFragment(this); + return res; + } + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); From 71b7b4a155dcd9d2f30c26c7ef8b9d1edc5ca7fd Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Tue, 26 Sep 2023 10:34:50 +0300 Subject: [PATCH 75/85] add per-app setting for exploit protection compatibility mode --- res/values/strings_app_exploit_protection.xml | 1 + res/xml/app_info_settings.xml | 6 ++ ...oitProtectionCompatModePrefController.java | 63 +++++++++++++++++++ .../appinfo/AppInfoDashboardFragment.java | 1 + 4 files changed, 71 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppExploitProtectionCompatModePrefController.java diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 6dacd66c2e2..88506c19306 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -22,4 +22,5 @@ This behavior can be disabled in the Security 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/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index faf9bc0db1c..f98c377de78 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -215,6 +215,12 @@ android:title="@string/exploit_protection_category_title" settings:controller="com.android.settings.applications.appinfo.AppExploitProtectionPrefCategoryController"> + + diff --git a/src/com/android/settings/applications/appinfo/AppExploitProtectionCompatModePrefController.java b/src/com/android/settings/applications/appinfo/AppExploitProtectionCompatModePrefController.java new file mode 100644 index 00000000000..02b57d87a18 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AppExploitProtectionCompatModePrefController.java @@ -0,0 +1,63 @@ +package com.android.settings.applications.appinfo; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.GosPackageState; + +import androidx.preference.Preference; +import androidx.preference.SwitchPreference; + +public class AppExploitProtectionCompatModePrefController extends AppInfoPreferenceControllerBase + implements Preference.OnPreferenceChangeListener { + + public AppExploitProtectionCompatModePrefController(Context ctx, String key) { + super(ctx, key); + } + + @Override + public int getAvailabilityStatus() { + ApplicationInfo ai = mParent.getPackageInfo().applicationInfo; + return ai.isSystemApp() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + + GosPackageState ps = GosPackageState.get(getPackageName()); + + boolean checked = ps != null && ps.hasFlags(GosPackageState.FLAG_ENABLE_EXPLOIT_PROTECTION_COMPAT_MODE); + + ((SwitchPreference) preference).setChecked(checked); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean checked = (boolean) newValue; + + Runnable r = () -> { + GosPackageState.edit(getPackageName()) + .setFlagsState(GosPackageState.FLAG_ENABLE_EXPLOIT_PROTECTION_COMPAT_MODE, checked) + .killUidAfterApply() + .apply(); + + if (!mParent.refreshUi()) { + mParent.finish(); + } + }; + + if (checked) { + var d = AswExploitProtectionFragment.getExploitProtectionWarningOnDisable(mContext, r); + d.show(); + return false; + } + + r.run(); + + return true; + } + + private String getPackageName() { + return mParent.getPackageInfo().packageName; + } +} diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index 9701f981845..c91f5b4fe6c 100644 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -233,6 +233,7 @@ public void onAttach(Context context) { aepCategory.setAppEntry(mAppEntry); AppInfoPreferenceControllerBase[] aepPrefControllers = { + prepare(AppExploitProtectionCompatModePrefController.class), }; aepCategory.setChildren(Arrays.asList(aepPrefControllers)); From 234f2d9628c5473b3e7ddbbb558d8a765cb096ff Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 7 Oct 2023 21:28:08 +0300 Subject: [PATCH 76/85] add toggle for automatic exploit protection compatibility mode --- res/values/strings_ext.xml | 6 ++++++ res/xml/security_dashboard_settings.xml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index 39d7989db05..c378a64fdc1 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -110,6 +110,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. Default value can be overridden per-app from the App info screen diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 07dc3aa714b..fb04ea2ce70 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -65,6 +65,12 @@ android:fragment="com.android.settings.security.ExecSpawningFragment" settings:controller="com.android.settings.security.ExecSpawningPrefController" /> + + Date: Thu, 16 Nov 2023 17:23:47 +0200 Subject: [PATCH 77/85] add per-app setting for hardened_malloc --- res/values/strings_app_exploit_protection.xml | 8 ++++ res/xml/app_info_settings.xml | 5 +++ .../applications/appinfo/AppHardenedMalloc.kt | 41 +++++++++++++++++++ .../appinfo/AppInfoDashboardFragment.java | 1 + 4 files changed, 55 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppHardenedMalloc.kt diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 88506c19306..451dbd345e7 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -23,4 +23,12 @@ This behavior can be disabled in the Security 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/app_info_settings.xml b/res/xml/app_info_settings.xml index f98c377de78..1d5b8d4e134 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -221,6 +221,11 @@ android:summary="@string/aep_compat_mode_summary" settings:controller="com.android.settings.applications.appinfo.AppExploitProtectionCompatModePrefController" /> + + diff --git a/src/com/android/settings/applications/appinfo/AppHardenedMalloc.kt b/src/com/android/settings/applications/appinfo/AppHardenedMalloc.kt new file mode 100644 index 00000000000..c7b169aaacd --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AppHardenedMalloc.kt @@ -0,0 +1,41 @@ +package com.android.settings.applications.appinfo + +import android.content.Context +import android.ext.settings.app.AppSwitch +import android.ext.settings.app.AswUseHardenedMalloc +import com.android.settings.R +import com.android.settingslib.widget.FooterPreference + +class AswAdapterUseHardenedMalloc(ctx: Context) : AswAdapter(ctx) { + + override fun getAppSwitch() = AswUseHardenedMalloc.I + + override fun getAswTitle() = getText(R.string.aep_hmalloc) +} + +class AppHardenedMallocPrefController(ctx: Context, key: String) : + AswPrefController(ctx, key, AswAdapterUseHardenedMalloc(ctx)) { + + override fun getDetailFragmentClass() = AppHardenedMallocFragment::class.java +} + +class AppHardenedMallocFragment : AswExploitProtectionFragment() { + + override fun createAswAdapter(ctx: Context) = AswAdapterUseHardenedMalloc(ctx) + + 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") + } +} diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index c91f5b4fe6c..667d5a962b7 100644 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -234,6 +234,7 @@ public void onAttach(Context context) { AppInfoPreferenceControllerBase[] aepPrefControllers = { prepare(AppExploitProtectionCompatModePrefController.class), + prepare(AppHardenedMallocPrefController.class), }; aepCategory.setChildren(Arrays.asList(aepPrefControllers)); From bb30059136e0492ed0f84e8d3581e9866e204b01 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Thu, 16 Nov 2023 17:23:35 +0200 Subject: [PATCH 78/85] add dev mode per-app setting for extended virtual address space --- res/values/strings_app_exploit_protection.xml | 5 +++ res/xml/app_info_settings.xml | 5 +++ .../appinfo/AppExtendedVaSpace.kt | 41 +++++++++++++++++++ .../appinfo/AppInfoDashboardFragment.java | 1 + 4 files changed, 52 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppExtendedVaSpace.kt diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 451dbd345e7..66a3528125f 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -31,4 +31,9 @@ This behavior can be disabled in the Security 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/app_info_settings.xml b/res/xml/app_info_settings.xml index 1d5b8d4e134..d942feac434 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -226,6 +226,11 @@ android:title="@string/aep_hmalloc" settings:controller="com.android.settings.applications.appinfo.AppHardenedMallocPrefController" /> + + diff --git a/src/com/android/settings/applications/appinfo/AppExtendedVaSpace.kt b/src/com/android/settings/applications/appinfo/AppExtendedVaSpace.kt new file mode 100644 index 00000000000..b1257617f43 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AppExtendedVaSpace.kt @@ -0,0 +1,41 @@ +package com.android.settings.applications.appinfo + +import android.content.Context +import android.ext.settings.app.AppSwitch +import android.ext.settings.app.AswUseExtendedVaSpace +import com.android.settings.R +import com.android.settings.ext.ExtSettingControllerHelper +import com.android.settingslib.widget.FooterPreference + +class AswAdapterUseExtendedVaSpace(ctx: Context) : AswAdapter(ctx) { + + override fun getAppSwitch() = AswUseExtendedVaSpace.I + + override fun getAswTitle() = getText(R.string.aep_ext_va_space) +} + +class AppExtendedVaSpacePrefController(ctx: Context, key: String) : + AswPrefController(ctx, key, AswAdapterUseExtendedVaSpace(ctx)) { + + override fun getDetailFragmentClass() = AppExtendedVaSpaceFragment::class.java + + override fun getAvailabilityStatus() = ExtSettingControllerHelper.getDevModeSettingAvailability(mContext) +} + +class AppExtendedVaSpaceFragment : AswExploitProtectionFragment() { + + override fun createAswAdapter(ctx: Context) = AswAdapterUseExtendedVaSpace(ctx) + + 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) + } +} diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index 667d5a962b7..fb5a86f535e 100644 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -235,6 +235,7 @@ public void onAttach(Context context) { AppInfoPreferenceControllerBase[] aepPrefControllers = { prepare(AppExploitProtectionCompatModePrefController.class), prepare(AppHardenedMallocPrefController.class), + prepare(AppExtendedVaSpacePrefController.class), }; aepCategory.setChildren(Arrays.asList(aepPrefControllers)); From f691445b6eb65f861834efd4051180118143c057 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:51:07 +0200 Subject: [PATCH 79/85] add per-app setting for native debugging --- AndroidManifest.xml | 18 +++++++ res/values/strings_app_exploit_protection.xml | 2 + res/xml/app_info_settings.xml | 5 ++ src/com/android/settings/Settings.java | 2 + .../appinfo/AppInfoDashboardFragment.java | 1 + .../appinfo/AppNativeDebugging.kt | 48 +++++++++++++++++++ .../core/gateway/SettingsGateway.java | 1 + 7 files changed, 77 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppNativeDebugging.kt diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 64f42a71bdc..8b67772accf 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -4969,5 +4969,23 @@ tools:node="remove" /> + + + + + + + + + + + + + diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 66a3528125f..8cdece1e891 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -36,4 +36,6 @@ This behavior can be disabled in the Security section. 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 debugging is always blocked for preinstalled apps diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index d942feac434..f5855f80d1d 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -231,6 +231,11 @@ android:title="@string/aep_ext_va_space" settings:controller="com.android.settings.applications.appinfo.AppExtendedVaSpacePrefController" /> + + diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 60a5b808c82..d67e0e08179 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -516,4 +516,6 @@ public static class AdaptiveBrightnessActivity extends SettingsActivity { /* emp * Activity for OneHandedSettings */ public static class OneHandedSettingsActivity extends SettingsActivity { /* empty */ } + + public static class AppNativeDebuggingActivity extends SettingsActivity {} } diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index fb5a86f535e..c158439d79a 100644 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -236,6 +236,7 @@ public void onAttach(Context context) { prepare(AppExploitProtectionCompatModePrefController.class), prepare(AppHardenedMallocPrefController.class), prepare(AppExtendedVaSpacePrefController.class), + prepare(AppNativeDebuggingPrefController.class), }; aepCategory.setChildren(Arrays.asList(aepPrefControllers)); diff --git a/src/com/android/settings/applications/appinfo/AppNativeDebugging.kt b/src/com/android/settings/applications/appinfo/AppNativeDebugging.kt new file mode 100644 index 00000000000..c99420935b2 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/AppNativeDebugging.kt @@ -0,0 +1,48 @@ +package com.android.settings.applications.appinfo + +import android.content.Context +import android.ext.settings.app.AswDenyNativeDebug +import android.ext.settings.app.AppSwitch +import com.android.settings.R +import com.android.settingslib.widget.FooterPreference + +class AswAdapterNativeDebugging(ctx: Context) : AswAdapter(ctx) { + + override fun getAppSwitch() = AswDenyNativeDebug.I + + override fun getAswTitle() = getText(R.string.native_debugging_title) + + override fun getOnTitle() = getText(R.string.aep_blocked) + override fun getOffTitle() = getText(R.string.aep_allowed) +} + +class AppNativeDebuggingPrefController(ctx: Context, key: String) : + AswPrefController(ctx, key, AswAdapterNativeDebugging(ctx)) { + + override fun getDetailFragmentClass() = AppNativeDebuggingFragment::class.java +} + +class AppNativeDebuggingFragment : AswExploitProtectionFragment() { + + override fun createAswAdapter(ctx: Context) = AswAdapterNativeDebugging(ctx) + + override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? { + val id = when (ir) { + AppSwitch.IR_IS_SYSTEM_APP -> R.string.native_debug_dvr_is_system_app + else -> return null + } + return getText(id) + } + + override fun getSummaryForDefaultValueReason(dvr: Int): CharSequence? { + val id = when (dvr) { + AppSwitch.DVR_DEFAULT_SETTING -> R.string.aep_dvr_default_security_setting + else -> return null + } + return getText(id) + } + + override fun updateFooter(fp: FooterPreference) { + fp.setTitle(R.string.native_debugging_footer) + } +} diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 7b1abaf8b24..152457c7d19 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -202,6 +202,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.appinfo.AppNativeDebuggingFragment.class.getName(), AdvancedConnectedDeviceDashboardFragment.class.getName(), CreateShortcut.class.getName(), BluetoothPairingDetail.class.getName(), From 897fdb6acf90b55f5565ad58152c98f5c6d1dd0d Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 24 May 2023 19:00:36 +0300 Subject: [PATCH 80/85] add setting for default value of per-app native debugging setting --- res/values/strings_ext.xml | 8 +++++ res/xml/security_dashboard_settings.xml | 6 ++++ .../security/NativeDebuggingFragment.java | 34 +++++++++++++++++++ .../NativeDebuggingPrefController.java | 20 +++++++++++ 4 files changed, 68 insertions(+) create mode 100644 src/com/android/settings/security/NativeDebuggingFragment.java create mode 100644 src/com/android/settings/security/NativeDebuggingPrefController.java diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index c378a64fdc1..b67820f572e 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -97,6 +97,14 @@ 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. + Native code debugging + Block for third-party apps by default + Blocked by default + Allowed for third-party apps by default + +Native code debugging (ptrace) slightly weakens the app sandbox. Some apps (most notably banking apps) use it as a tampering detection tool. + + App installs and updates diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index fb04ea2ce70..301769721bb 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -71,6 +71,12 @@ android:summary="@string/allow_automatic_per_app_epcm_summary" settings:boolSettingField="android.ext.settings.ExtSettings ALLOW_DISABLING_HARDENING_VIA_APP_COMPAT_CONFIG" /> + + Date: Wed, 15 Nov 2023 13:51:18 +0200 Subject: [PATCH 81/85] add per-app setting for memory tagging --- AndroidManifest.xml | 17 +++++++ res/values/strings_app_exploit_protection.xml | 10 ++++ res/xml/app_info_settings.xml | 5 ++ src/com/android/settings/Settings.java | 2 + .../appinfo/AppInfoDashboardFragment.java | 1 + .../applications/appinfo/AppMemoryTagging.kt | 51 +++++++++++++++++++ .../core/gateway/SettingsGateway.java | 1 + 7 files changed, 87 insertions(+) create mode 100644 src/com/android/settings/applications/appinfo/AppMemoryTagging.kt diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8b67772accf..5b8451ceed5 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -4987,5 +4987,22 @@ android:value="@string/menu_key_apps"/> + + + + + + + + + + + + diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 8cdece1e891..085bb68eb41 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -38,4 +38,14 @@ This behavior can be disabled in the Security section. Required by hardened_malloc Native debugging is always blocked for preinstalled apps + + 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 + + Memory tagging is always enabled for apps that don’t have native code + + This app has opted-in to memory tagging diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index f5855f80d1d..32d7dccc505 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -226,6 +226,11 @@ android:title="@string/aep_hmalloc" settings:controller="com.android.settings.applications.appinfo.AppHardenedMallocPrefController" /> + + (ctx) { + + override fun getAppSwitch() = AswUseMemoryTagging.I + + override fun getAswTitle() = getText(R.string.aep_memtag) +} + +class AppMemtagPrefController(ctx: Context, key: String) : + AswPrefController(ctx, key, AswAdapterUseMemoryTagging(ctx)) { + + override fun getDetailFragmentClass() = AppMemtagFragment::class.java + + private val isSupported = Zygote.nativeSupportsMemoryTagging() + override fun getAvailabilityStatus() = if (isSupported) AVAILABLE else UNSUPPORTED_ON_DEVICE +} + +class AppMemtagFragment : AswExploitProtectionFragment() { + + override fun createAswAdapter(ctx: Context) = AswAdapterUseMemoryTagging(ctx) + + 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 getSummaryForDefaultValueReason(dvr: Int): CharSequence? { + val id = when (dvr) { + AppSwitch.DVR_DEFAULT_SETTING -> R.string.aep_dvr_default_security_setting + else -> return null + } + return getText(id) + } + + override fun updateFooter(fp: FooterPreference) { + fp.setTitle(R.string.aep_memtag_footer) + } +} diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 152457c7d19..9d564305c58 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -203,6 +203,7 @@ public class SettingsGateway { */ public static final String[] ENTRY_FRAGMENTS = { com.android.settings.applications.appinfo.AppNativeDebuggingFragment.class.getName(), + com.android.settings.applications.appinfo.AppMemtagFragment.class.getName(), AdvancedConnectedDeviceDashboardFragment.class.getName(), CreateShortcut.class.getName(), BluetoothPairingDetail.class.getName(), From 88434b7a72c6045ceeeb3896e02c0f23d941cb46 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Wed, 15 Nov 2023 13:45:25 +0200 Subject: [PATCH 82/85] add setting for default value of per-app memory tagging setting --- res/values/strings_app_exploit_protection.xml | 14 ++++++ res/xml/security_dashboard_settings.xml | 6 +++ .../settings/security/ForceAppMemtag.kt | 45 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/com/android/settings/security/ForceAppMemtag.kt diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml index 085bb68eb41..a8b765d3f5f 100644 --- a/res/values/strings_app_exploit_protection.xml +++ b/res/values/strings_app_exploit_protection.xml @@ -48,4 +48,18 @@ This behavior can be disabled in the Security section. Memory tagging is always enabled for apps that don’t have native code This app has opted-in to memory tagging + + Memory tagging in third-party apps + 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/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 301769721bb..b2babcf4560 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -71,6 +71,12 @@ android:summary="@string/allow_automatic_per_app_epcm_summary" settings:boolSettingField="android.ext.settings.ExtSettings ALLOW_DISABLING_HARDENING_VIA_APP_COMPAT_CONFIG" /> + + Date: Mon, 27 Nov 2023 21:47:26 +0200 Subject: [PATCH 83/85] add toggle for system process crash notifications --- res/values/strings_ext.xml | 4 ++++ res/xml/security_dashboard_settings.xml | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml index b67820f572e..6a18389072e 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -127,4 +127,8 @@ Native code debugging (ptrace) slightly weakens the app sandbox. Some apps (most "Warning: enabling this setting might cause some apps to stop working. Default value can be overridden per-app from the App info screen + + Notify about system process crashes + Such crashes may indicate exploitation attempts + diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index b2babcf4560..ec724f0536f 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -99,6 +99,13 @@ android:title="@string/security_settings_biometric_preference_title" android:summary="@string/summary_placeholder" settings:keywords="@string/keywords_biometric_settings" /> + + Date: Fri, 29 Sep 2023 16:16:00 +0300 Subject: [PATCH 84/85] 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 | 44 +++++++++++++++++++ 3 files changed, 55 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 6a18389072e..9f4813ba8f1 100644 --- a/res/values/strings_ext.xml +++ b/res/values/strings_ext.xml @@ -105,6 +105,11 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks. Native code debugging (ptrace) slightly weakens the app sandbox. Some apps (most notably banking apps) use it as a tampering detection tool. + Widevine provisioning + Enabled (GrapheneOS proxy) + Enabled (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 825e0f98b80..bb826490104 100644 --- a/res/xml/network_provider_internet.xml +++ b/res/xml/network_provider_internet.xml @@ -150,4 +150,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..7ebc5d12bee --- /dev/null +++ b/src/com/android/settings/network/WidevineProvisioningPrefController.java @@ -0,0 +1,44 @@ +/* + * 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.ExtSettings; +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, ExtSettings.WIDEVINE_PROVISIONING_SERVER); + } + + @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); + } +} \ No newline at end of file From fd5417fdeaf5cbda017f3c56a8f472fb451137dc Mon Sep 17 00:00:00 2001 From: nycex Date: Mon, 25 Dec 2023 21:16:44 +0100 Subject: [PATCH 85/85] add toggle for screencapture on FLAG_SECURE activities --- res/values/strings.xml | 5 +++++ res/xml/privacy_dashboard_settings.xml | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/res/values/strings.xml b/res/values/strings.xml index a4dd51d9cf3..c12de8bb83a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11735,6 +11735,11 @@ Show a message when apps access text, images, or other content you\u2019ve copied + + Allow FLAG_SECURE screenshots + + Allow FLAG_SECURE activities to be screenshotted + All apps diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml index ece8fab41a2..ec1a0d37ccc 100644 --- a/res/xml/privacy_dashboard_settings.xml +++ b/res/xml/privacy_dashboard_settings.xml @@ -169,4 +169,11 @@ android:summary="@string/show_clip_access_notification_summary" settings:controller="com.android.settings.privacy.ShowClipAccessNotificationPreferenceController"/> + + +