From ae47689bcada3919559b2deda188fdfe7dc5f738 Mon Sep 17 00:00:00 2001
From: flawedworld <38294951+flawedworld@users.noreply.github.com>
Date: Sun, 16 May 2021 00:51:15 +0100
Subject: [PATCH 001/162] 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 002/162] extend list of system apps that are not allowed to be
disabled
---
.../ApplicationFeatureProviderImpl.java | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index 62c5910904a..c078f951269 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -22,12 +22,14 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
+import android.ext.PackageId;
import android.location.LocationManager;
import android.os.RemoteException;
import android.os.SystemConfigManager;
@@ -201,6 +203,42 @@ private Set getEnabledPackageAllowlist() {
if (mPm.getWellbeingPackageName() != null) {
keepEnabledPackages.add(mPm.getWellbeingPackageName());
}
+
+ ArraySet systemPkgs = new ArraySet<>(new String[] {
+ // Bundled keyboard, needed for text input in Direct Boot mode if the selected 3rd
+ // party keyboard doesn't support it
+ "com.android.inputmethod.latin",
+
+ // Replacing WebView is not supported
+ "app.vanadium.webview",
+
+ // Only bundled camera can handle some of camera intents
+ "app.grapheneos.camera",
+
+ // Disabling GmsCompat app breaks the GmsCompat layer
+ com.android.internal.gmscompat.GmsCompatApp.PKG_NAME,
+
+ // EuiccSupportPixel handles firmware updates of embedded secure element that is
+ // used for eSIM, NFC, Felica etc
+ PackageId.EUICC_SUPPORT_PIXEL_NAME,
+
+ // CameraX extensions break when it's disabled, which breaks apps that use the
+ // CameraX library
+ PackageId.PIXEL_CAMERA_SERVICES_NAME,
+
+ // Emergency calls break when it's disabled, system dialer app is required for it.
+ "com.android.dialer",
+ });
+
+ PackageManager pm = mContext.getPackageManager();
+
+ for (ApplicationInfo ai : pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY)) {
+ String pkgName = ai.packageName;
+ if (systemPkgs.contains(pkgName)) {
+ keepEnabledPackages.add(pkgName);
+ }
+ }
+
return keepEnabledPackages;
}
From 39129314f189d50ef64c3033ebe1bf2a02b2e025 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sun, 12 Feb 2023 20:21:09 +0200
Subject: [PATCH 003/162] 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 e4e83960e90073a81a9219364e175bdf4e0538ff Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Thu, 6 Apr 2023 12:06:11 +0300
Subject: [PATCH 004/162] add a set of base classes for creating Fragment-based
preference UI
---
res/values/strings_ext.xml | 4 +-
.../settings/ext/BoolSettingFragment.java | 157 ++++++++++++++++++
.../BoolSettingFragmentPrefController.java | 26 +++
.../ext/ExtSettingFragmentPrefController.java | 42 +++++
.../settings/ext/FragmentPrefController.java | 36 ++++
5 files changed, 264 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..e342faa688d
--- /dev/null
+++ b/src/com/android/settings/ext/BoolSettingFragment.java
@@ -0,0 +1,157 @@
+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.SwitchPreferenceCompat;
+
+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 SwitchPreferenceCompat 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 SwitchPreferenceCompat(ctx);
+ mainSwitch.setTitle(getMainSwitchTitle());
+
+ this.mainSwitch = mainSwitch;
+ refreshMainSwitch();
+
+ mainSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
+ boolean state = (boolean) newValue;
+
+ if (invertSetting) {
+ state = !state;
+ }
+
+ if (interceptMainSwitchChange(state)) {
+ return false;
+ }
+
+ 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 boolean interceptMainSwitchChange(boolean newValue) {
+ return false;
+ }
+
+ protected void onMainSwitchChanged(boolean state) {}
+
+ protected 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 bc85bb0bcd28cf681886751b44449de009588e5a Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sun, 12 Feb 2023 19:43:44 +0200
Subject: [PATCH 005/162] add base class for ListPreference controllers
---
.../ext/AbstractListPreferenceController.java | 242 ++++++++++++++++++
.../ext/RadioButtonPickerFragment2.java | 208 +++++++++++++++
.../widget/RadioButtonPickerFragment.java | 17 +-
3 files changed, 462 insertions(+), 5 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..a5686e370ee
--- /dev/null
+++ b/src/com/android/settings/ext/AbstractListPreferenceController.java
@@ -0,0 +1,242 @@
+/*
+ * 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);
+ }
+
+ /**
+ * Returns whether to require user credential confirmation before changing this preference.
+ */
+ protected boolean isCredentialConfirmationRequired() {
+ return false;
+ }
+}
diff --git a/src/com/android/settings/ext/RadioButtonPickerFragment2.java b/src/com/android/settings/ext/RadioButtonPickerFragment2.java
new file mode 100644
index 00000000000..a44c9280af7
--- /dev/null
+++ b/src/com/android/settings/ext/RadioButtonPickerFragment2.java
@@ -0,0 +1,208 @@
+package com.android.settings.ext;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.utils.CandidateInfoExtra;
+import com.android.settings.widget.RadioButtonPickerFragment;
+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);
+ }
+
+ private static final String KEY_USER_CREDENTIAL_CONFIRMED = "user_credential_confirmed";
+ private boolean userCredentialConfirmed;
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ PreferenceScreen ps = getPreferenceManager().createPreferenceScreen(requireContext());
+ setPreferenceScreen(ps);
+
+ if (savedInstanceState != null) {
+ userCredentialConfirmed = savedInstanceState.getBoolean(
+ KEY_USER_CREDENTIAL_CONFIRMED, false);
+ }
+
+ updateCandidates();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_USER_CREDENTIAL_CONFIRMED, userCredentialConfirmed);
+ }
+
+ private Runnable onAfterCredentialConfirmed;
+
+ private void runAfterCredentialConfirmation(Runnable runnable) {
+ if (userCredentialConfirmed) {
+ throw new IllegalStateException();
+ }
+
+ if (onAfterCredentialConfirmed != null) {
+ throw new IllegalStateException();
+ }
+
+ onAfterCredentialConfirmed = runnable;
+
+ var b = new ChooseLockSettingsHelper.Builder(requireActivity());
+ b.setActivityResultLauncher(credentialConfirmationLauncher);
+ b.setForegroundOnly(true);
+ b.show();
+ }
+
+ private final ActivityResultLauncher credentialConfirmationLauncher =
+ registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
+ this::onCredentialConfirmationResult);
+
+ private void onCredentialConfirmationResult(@Nullable ActivityResult result) {
+ Runnable r = onAfterCredentialConfirmed;
+ onAfterCredentialConfirmed = null;
+
+ if (result != null && result.getResultCode() == Activity.RESULT_OK) {
+ userCredentialConfirmed = true;
+ if (r != null) {
+ r.run();
+ }
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (!requireActivity().isChangingConfigurations()) {
+ userCredentialConfirmed = false;
+ }
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return -1;
+ }
+
+ @Override
+ protected List extends CandidateInfo> 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) {
+ if (key.equals(getDefaultKey())) {
+ return true;
+ }
+
+ if (!userCredentialConfirmed && prefController.isCredentialConfirmationRequired()) {
+ Context ctx = requireContext();
+ LockPatternUtils lpu = FeatureFactory.getFeatureFactory()
+ .getSecurityFeatureProvider()
+ .getLockPatternUtils(ctx);
+
+ if (lpu.isSecure(ctx.getUserId())) {
+ runAfterCredentialConfirmation(() -> prefController.setValue(Integer.parseInt(key)));
+ return false;
+ }
+ }
+
+ 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);
+ }
+
+ private boolean updateCandidatesOnResume;
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ prefController.onResume(this);
+
+ if (updateCandidatesOnResume) {
+ updateCandidates();
+ } else {
+ // updateCandidates() is called from onCreatePrefences() right before the first onResume()
+ updateCandidatesOnResume = true;
+ }
+ }
+}
diff --git a/src/com/android/settings/widget/RadioButtonPickerFragment.java b/src/com/android/settings/widget/RadioButtonPickerFragment.java
index 9578efbb55d..4927e221609 100644
--- a/src/com/android/settings/widget/RadioButtonPickerFragment.java
+++ b/src/com/android/settings/widget/RadioButtonPickerFragment.java
@@ -62,8 +62,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";
private static final String KEY_CATEGORY_PREFERENCE = "radio_button_picker_category";
@VisibleForTesting
@@ -182,6 +181,12 @@ protected SelectorWithWidgetPreference createPreference() {
return new RestrictedSelectorWithWidgetPreference(getPrefContext());
}
+ protected void addPrefsBeforeList(PreferenceScreen screen) {
+ if (!mAppendStaticPreferences) {
+ addStaticPreferences(screen);
+ }
+ }
+
public void updateCandidates() {
mCandidates.clear();
final List extends CandidateInfo> candidateList = getCandidates();
@@ -197,9 +202,7 @@ public void updateCandidates() {
if (mIllustrationId != 0) {
addIllustration(screen);
}
- if (!mAppendStaticPreferences) {
- addStaticPreferences(screen);
- }
+ addPrefsBeforeList(screen);
PreferenceGroup radioButtonsGroup = screen;
if (mCategoryTitleId != 0) {
Context context = getPrefContext();
@@ -235,6 +238,10 @@ public void updateCandidates() {
}
}
mayCheckOnlyRadioButton();
+ addPrefsAfterList(screen);
+ }
+
+ protected void addPrefsAfterList(PreferenceScreen screen) {
if (mAppendStaticPreferences) {
addStaticPreferences(screen);
}
From 0924b565ae30222863ed037f6dfb2c97914c9a4b Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Tue, 14 Feb 2023 08:45:56 +0200
Subject: [PATCH 006/162] 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 f6bcec2506a3b13c0faa442b10a0b1a5b5f8e9c3 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sun, 12 Feb 2023 19:44:07 +0200
Subject: [PATCH 007/162] 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 | 96 +++++++++++++++++++
.../ext/ExtSettingControllerHelper.java | 72 ++++++++++++++
.../ext/ExtSettingPrefController.java | 12 +++
.../ext/IntSettingPrefController.java | 62 ++++++++++++
7 files changed, 259 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 c5cb82de15f..589d7a3d303 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -66,6 +66,8 @@
+
+
diff --git a/src/com/android/settings/core/PreferenceControllerListHelper.java b/src/com/android/settings/core/PreferenceControllerListHelper.java
index 9dc0a9fa108..30d41d88c3e 100644
--- a/src/com/android/settings/core/PreferenceControllerListHelper.java
+++ b/src/com/android/settings/core/PreferenceControllerListHelper.java
@@ -31,6 +31,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
+import com.android.settings.ext.BoolSettingPrefController;
import com.android.settingslib.core.AbstractPreferenceController;
import org.xmlpull.v1.XmlPullParserException;
@@ -59,6 +60,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);
@@ -68,6 +70,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 cf2f9ca179b..5d4758deeff 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -65,6 +65,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,
@@ -92,11 +93,14 @@ public class PreferenceXmlParserUtils {
int FLAG_FOR_WORK = 1 << 12;
int FLAG_NEED_HIGHLIGHTABLE_MENU_KEY = 1 << 13;
int FLAG_NEED_USER_RESTRICTION = 1 << 14;
+
+ 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";
@@ -163,6 +167,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));
}
@@ -231,6 +239,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..659585dc5dd
--- /dev/null
+++ b/src/com/android/settings/ext/BoolSettingPrefController.java
@@ -0,0 +1,96 @@
+/*
+ * 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 android.os.UserHandle;
+
+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;
+
+ public BoolSettingPrefController(Context ctx, String key, BoolSetting setting) {
+ this(ctx, key, setting, ctx.getUser());
+ }
+
+ public BoolSettingPrefController(Context ctx, String key, BoolSetting setting, UserHandle user) {
+ super(ctx, key);
+ this.setting = setting;
+ Context userContext = ctx.getUser().equals(user) ? ctx : ctx.createContextAsUser(user, 0);
+ helper = new ExtSettingControllerHelper<>(userContext, setting);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return helper.getAvailabilityStatus();
+ }
+
+ @Override
+ public final boolean isChecked() {
+ return setting.get(helper.context);
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return setting.put(helper.context, 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..1c8e70d4cdb
--- /dev/null
+++ b/src/com/android/settings/ext/ExtSettingControllerHelper.java
@@ -0,0 +1,72 @@
+/*
+ * 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.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 {
+ public 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 ctx.getUser().isSystem() ? AVAILABLE : DISABLED_FOR_USER;
+ }
+
+ public static int getSecondaryUserOnlySettingAvailability(Context ctx) {
+ return ctx.getUser().isSystem() ? DISABLED_FOR_USER : AVAILABLE;
+ }
+
+ 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, context.getMainThreadHandler(), settingObserver);
+ }
+ }
+
+ 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..38ecc9a89b3
--- /dev/null
+++ b/src/com/android/settings/ext/IntSettingPrefController.java
@@ -0,0 +1,62 @@
+/*
+ * 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 android.os.UserHandle;
+
+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) {
+ this(ctx, key, setting, ctx.getUser());
+ }
+
+ protected IntSettingPrefController(Context ctx, String key, IntSetting setting, UserHandle user) {
+ super(ctx, key);
+ this.setting = setting;
+ Context userContext = ctx.getUser().equals(user) ? ctx : ctx.createContextAsUser(user, 0);
+ helper = new ExtSettingControllerHelper<>(userContext, setting);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return helper.getAvailabilityStatus();
+ }
+
+ @Override
+ protected final int getCurrentValue() {
+ return setting.get(helper.context);
+ }
+
+ @Override
+ protected boolean setValue(int val) {
+ return setting.put(helper.context, 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 eb443dbb92526a82261f46781e265c92b1250349 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Tue, 30 Jul 2024 15:20:39 +0300
Subject: [PATCH 008/162] add Exploit protection screen
---
AndroidManifest.xml | 17 +++++++++++
res/values/strings_ext.xml | 5 ++++
res/xml/exploit_protection_settings.xml | 16 ++++++++++
src/com/android/settings/Settings.java | 3 ++
.../core/gateway/SettingsGateway.java | 1 +
.../dashboard/DashboardFragmentRegistry.java | 3 ++
.../ExploitProtectionFragment.java | 29 +++++++++++++++++++
7 files changed, 74 insertions(+)
create mode 100644 res/xml/exploit_protection_settings.xml
create mode 100644 src/com/android/settings/safetycenter/ExploitProtectionFragment.java
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 585c2125164..49d0b5905bc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2407,6 +2407,23 @@
android:value="@string/menu_key_safety_center"/>
+
+
+
+
+
+
+
+
+
+
+
Enabled
Disabled
+ Exploit protection
+
+ App exploit protection
+
+
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
new file mode 100644
index 00000000000..54da29f1394
--- /dev/null
+++ b/res/xml/exploit_protection_settings.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 76d8f1667d9..15db565117d 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -629,6 +629,9 @@ public static class ContactsStorageSettingsActivity extends SettingsActivity { /
public static class ContentProtectionSettingsActivity extends SettingsActivity { /* empty */ }
public static class MagnificationActivity extends SettingsActivity { /* empty */ }
public static class FlashNotificationsActivity extends SettingsActivity { /* empty */ }
+
+ public static class ExploitProtectionActivity extends SettingsActivity {}
+
public static class NotificationBundlesActivity extends SettingsActivity { /* empty */ }
public static class NotificationSummarizationActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 4b86248264a..2d3f63e9a5e 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -229,6 +229,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.safetycenter.ExploitProtectionFragment.class.getName(),
AdvancedConnectedDeviceDashboardFragment.class.getName(),
CreateShortcut.class.getName(),
BluetoothPairingDetail.class.getName(),
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 26a1f7ff63f..f93c417c89a 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -42,6 +42,7 @@
import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.SoundSettings;
import com.android.settings.privacy.PrivacyDashboardFragment;
+import com.android.settings.safetycenter.ExploitProtectionFragment;
import com.android.settings.safetycenter.MoreSecurityPrivacyFragment;
import com.android.settings.safetycenter.ui.PrivacyControlsFragment;
import com.android.settings.security.LockscreenDashboardFragment;
@@ -73,6 +74,8 @@ public class DashboardFragmentRegistry {
static {
PARENT_TO_CATEGORY_KEY_MAP = new ArrayMap<>();
+ PARENT_TO_CATEGORY_KEY_MAP.put(ExploitProtectionFragment.class.getName(),
+ CategoryKey.CATEGORY_EXPLOIT_PROTECTION_SETTINGS);
PARENT_TO_CATEGORY_KEY_MAP.put(TopLevelSettings.class.getName(),
CategoryKey.CATEGORY_HOMEPAGE);
PARENT_TO_CATEGORY_KEY_MAP.put(
diff --git a/src/com/android/settings/safetycenter/ExploitProtectionFragment.java b/src/com/android/settings/safetycenter/ExploitProtectionFragment.java
new file mode 100644
index 00000000000..2542012590b
--- /dev/null
+++ b/src/com/android/settings/safetycenter/ExploitProtectionFragment.java
@@ -0,0 +1,29 @@
+package com.android.settings.safetycenter;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+@SearchIndexable
+public class ExploitProtectionFragment extends DashboardFragment {
+ private static final String TAG = "ExploitProtFragment";
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.exploit_protection_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return METRICS_CATEGORY_UNKNOWN;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.exploit_protection_settings);
+}
From 8df8abf0241fd618d9dcc59ad744290414ea8839 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 009/162] 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 ea5dbdff62b..d438f13354e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3624,6 +3624,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 010/162] 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 6284e7c908cdedd9d25e474fd2483d0021553996 Mon Sep 17 00:00:00 2001
From: Daniel Micay
Date: Sun, 25 Jul 2021 14:44:48 -0400
Subject: [PATCH 011/162] 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 76a9050bdd0..8c21fe4ed73 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -524,7 +524,7 @@
false
- content://com.google.android.gms.nearby.fastpair/device_status_list_item
+
From bfdf3e21eb2e3328475fa8e5461fad0fde91945f Mon Sep 17 00:00:00 2001
From: Your Name
Date: Mon, 18 Oct 2021 02:17:56 +0000
Subject: [PATCH 012/162] 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 96c9256c23fceb5b7b2b18b7333bf2506d9ccc4d Mon Sep 17 00:00:00 2001
From: Danny Lin
Date: Wed, 7 Jul 2021 03:02:05 -0700
Subject: [PATCH 013/162] 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.
Co-authored-by: Diab Neiroukh
Squashed with e7264c6b8e2a5b6c234d188467b4ad0fda744530
Change-Id: I86af721fde33226d314d8a44525f310828299a72
---
res/values/config_google.xml | 4 ++
res/values/strings.xml | 4 ++
res/values/strings_google.xml | 6 ++
res/xml/display_settings.xml | 6 ++
.../TouchSensitivityPreferenceController.java | 61 +++++++++++++++++++
5 files changed, 81 insertions(+)
create mode 100644 res/values/config_google.xml
create mode 100644 res/values/strings_google.xml
create mode 100755 src/com/android/settings/display/TouchSensitivityPreferenceController.java
diff --git a/res/values/config_google.xml b/res/values/config_google.xml
new file mode 100644
index 00000000000..075926c5209
--- /dev/null
+++ b/res/values/config_google.xml
@@ -0,0 +1,4 @@
+
+
+ false
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d438f13354e..fc10f765f88 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3292,6 +3292,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/values/strings_google.xml b/res/values/strings_google.xml
new file mode 100644
index 00000000000..6f981f03170
--- /dev/null
+++ b/res/values/strings_google.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 33f328fc819..283077fc949 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -182,6 +182,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 014/162] add dynamic link to sandboxed Google Play settings
---
res/values/strings_ext.xml | 3 +-
res/xml/apps.xml | 13 +++++
.../applications/GmsCompatAppController.java | 48 +++++++++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 src/com/android/settings/applications/GmsCompatAppController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 3bda9789896..d57deb8a427 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -9,5 +9,6 @@
App exploit protection
-
+ Sandboxed Google Play
+ Sandboxed Google Play (work profile)
diff --git a/res/xml/apps.xml b/res/xml/apps.xml
index b6874973b22..8233a1f8a72 100644
--- a/res/xml/apps.xml
+++ b/res/xml/apps.xml
@@ -134,4 +134,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..32fe7d05e60
--- /dev/null
+++ b/src/com/android/settings/applications/GmsCompatAppController.java
@@ -0,0 +1,48 @@
+package com.android.settings.applications;
+
+import android.app.compat.gms.GmsCompat;
+import android.content.Context;
+import android.content.Intent;
+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 {
+
+ public GmsCompatAppController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ UserHandle workProfile = getWorkProfileUser();
+ int userId = workProfile != null ?
+ workProfile.getIdentifier() :
+ UserHandle.myUserId();
+
+ return GmsCompat.isEnabledFor(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) {
+ mContext.startActivityAsUser(intent, workProfile);
+ } else {
+ mContext.startActivity(intent);
+ }
+ return true;
+ }
+}
From 1cf885e2b4a76bd1626f89649ddfcb53248656b8 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Mon, 12 Aug 2024 17:45:43 +0300
Subject: [PATCH 015/162] add Private Space sandboxed Google Play link
It's added to Private Space screen instead of the Apps screen (where regular and work profile links
are) to avoid revealing whether the Private Space is present when the "Hide when locked" Private
Space option is enabled.
---
res/xml/private_space_settings.xml | 5 +++
.../applications/GmsCompatAppController.java | 41 +++++++++++++------
2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/res/xml/private_space_settings.xml b/res/xml/private_space_settings.xml
index e444c80dad3..80a8658df50 100644
--- a/res/xml/private_space_settings.xml
+++ b/res/xml/private_space_settings.xml
@@ -56,6 +56,11 @@
settings:controller="com.android.settings.privatespace.HidePrivateSpaceSummaryController"
settings:searchable="false" />
+
+
Date: Sat, 5 Mar 2022 17:37:47 +0000
Subject: [PATCH 016/162] 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 d57deb8a427..8f1e44c30d6 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 4617efe1bfe5828293598beead168a9ff2a73a03 Mon Sep 17 00:00:00 2001
From: Roman Royer
Date: Wed, 4 May 2016 19:04:36 -0700
Subject: [PATCH 017/162] 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 9e1cb8d067c..c5f3cd9dd58 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -880,9 +880,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 e8cbc6fa7259bfb917c34756e2ae3c0a00e263dd Mon Sep 17 00:00:00 2001
From: June
Date: Wed, 16 Mar 2022 07:09:46 +0200
Subject: [PATCH 018/162] add a per-user setting for forwarding censored notifs
Signed-off-by: June
Co-authored-by: inthewaves
Co-authored-by: June
---
res/values/strings_ext.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_ext.xml b/res/values/strings_ext.xml
index 8f1e44c30d6..34df22b18f1 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -12,4 +12,7 @@
Sandboxed Google Play
Sandboxed Google Play (work profile)
+
+ 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.
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index ec0e72818b1..413091d5cab 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -112,4 +112,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 d1186a52244..07053db27f2 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -149,6 +149,8 @@ public class UserSettings extends SettingsPreferenceFragment
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_USER_SETTINGS_SCREEN = "user_settings_screen";
+ private static final String KEY_SEND_CENSORED_NOTIFICATIONS =
+ "user_settings_send_censored_notifications_to_current";
private static final String KEY_USER_SWITCH_TOGGLE = "multiple_users_main_switch";
private static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in";
@@ -249,6 +251,7 @@ public class UserSettings extends SettingsPreferenceFragment
private AddUserFromSignInPreferenceController mAddUserFromSignInPreferenceController;
private GuestTelephonyPreferenceController mGuestTelephonyPreferenceController;
private RemoveGuestOnExitPreferenceController mRemoveGuestOnExitPreferenceController;
+ private SendCensoredNotificationsToCurrentUserPreferenceController mSendCensoredNotificationsToCurrentUserPreferenceController;
private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController;
private TimeoutToDockUserPreferenceController mTimeoutToDockUserPreferenceController;
private UserCreatingDialog mUserCreatingDialog;
@@ -341,6 +344,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);
@@ -355,6 +362,7 @@ public void onCreate(Bundle icicle) {
mAddUserFromSignInPreferenceController.displayPreference(screen);
mGuestTelephonyPreferenceController.displayPreference(screen);
mRemoveGuestOnExitPreferenceController.displayPreference(screen);
+ mSendCensoredNotificationsToCurrentUserPreferenceController.displayPreference(screen);
mMultiUserTopIntroPreferenceController.displayPreference(screen);
mTimeoutToDockUserPreferenceController.displayPreference(screen);
mMainSwitchController.displayPreference(screen);
@@ -362,6 +370,8 @@ public void onCreate(Bundle icicle) {
screen.findPreference(mAddUserWhenLockedPreferenceController.getPreferenceKey())
.setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController);
+ screen.findPreference(mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey())
+ .setOnPreferenceChangeListener(mSendCensoredNotificationsToCurrentUserPreferenceController);
screen.findPreference(mAddUserFromSignInPreferenceController.getPreferenceKey())
.setOnPreferenceChangeListener(mAddUserFromSignInPreferenceController);
@@ -453,6 +463,9 @@ public void onResume() {
mRemoveGuestOnExitPreferenceController.updateState(screen.findPreference(
mRemoveGuestOnExitPreferenceController.getPreferenceKey()));
mMainSwitchController.updateState();
+ mSendCensoredNotificationsToCurrentUserPreferenceController.updateState(screen.findPreference(
+ mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey()));
+
if (mShouldUpdateUserList) {
updateUI();
}
@@ -1425,6 +1438,10 @@ && getPrefContext()
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);
@@ -1995,6 +2012,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 1850f7c857b803c9c4af18c46483919d6092563e Mon Sep 17 00:00:00 2001
From: Daniel Micay
Date: Wed, 17 Aug 2022 12:40:26 -0400
Subject: [PATCH 019/162] fully enable location indicators by default
---
.../location/RecentLocationAccessPreferenceController.java | 6 +++---
.../location/RecentLocationAccessSeeAllFragment.java | 6 +++---
.../RecentLocationAccessSeeAllPreferenceController.java | 4 ++--
.../location/RecentLocationRequestPreferenceController.java | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
index c93b450ba01..7cfcbe55c9d 100644
--- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
@@ -53,7 +53,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;
@VisibleForTesting
@@ -108,9 +108,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 50c105b44c5..6eb1402b413 100644
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
@@ -57,11 +57,11 @@ public RecentLocationAccessSeeAllPreferenceController(Context context, String ke
DeviceConfig.NAMESPACE_PRIVACY,
SystemUiDeviceConfigFlags
.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED,
- false)
+ true)
? Settings.Secure.getInt(
mContext.getContentResolver(),
Settings.Secure.LOCATION_SHOW_SYSTEM_OPS,
- 0)
+ 1)
== 1
: false;
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 f2c7aa6920584dbe25cccf7994821dc1d5bec5e5 Mon Sep 17 00:00:00 2001
From: Pratyush
Date: Fri, 19 Aug 2022 11:05:36 +0530
Subject: [PATCH 020/162] 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 fc10f765f88..046f7762bcb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -12890,6 +12890,8 @@
Preferred network mode: CDMA/EvDo/GSM/WCDMA
Preferred network mode: LTE
+
+ Preferred network mode: LTE only
Preferred network mode: GSM/WCDMA/LTE
@@ -12955,8 +12957,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 932897ec20d..c3b7f3b780c 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -144,7 +144,7 @@ public EnabledNetworkModePreferenceController(Context context, String key) {
@Override
public int getAvailabilityStatus() {
return getNetworkModePreferenceType(mContext, mSubId)
- == NetworkModePreferenceType.EnabledNetworkMode
+ != NetworkModePreferenceType.PreferredNetworkMode
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@@ -385,6 +385,7 @@ private boolean isDisabledByAdmin() {
}
void setPreferenceEntries() {
+ boolean lteOnlyUnsupported = false;
mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
clearAllEntries();
@@ -400,6 +401,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)
@@ -419,6 +421,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);
@@ -436,6 +439,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)
@@ -484,6 +488,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)) {
@@ -667,6 +676,9 @@ void setPreferenceValueAndSummary(int networkMode) {
break;
}
case TelephonyManager.NETWORK_MODE_LTE_ONLY:
+ setSummary(mShow4gForLTE
+ ? R.string.network_4G_only : R.string.network_lte_only);
+ break;
case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
if (!mIsGlobalCdma) {
setSelectedEntry(TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA);
@@ -858,6 +870,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(TelephonyManager.NETWORK_MODE_LTE_ONLY);
+ } else {
+ mEntries.add(mContext.getString(R.string.network_lte_only));
+ mEntriesValue.add(TelephonyManager.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 1ee1b31e4dd..d70b1ed8b7e 100644
--- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
@@ -220,7 +220,7 @@ private int getPreferredNetworkModeSummaryResId(int networkMode) {
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
return R.string.preferred_network_mode_lte_tdscdma_summary;
case TelephonyManager.NETWORK_MODE_LTE_ONLY:
- return R.string.preferred_network_mode_lte_summary;
+ return R.string.preferred_network_mode_lte_only_summary;
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
return R.string.preferred_network_mode_lte_tdscdma_gsm_summary;
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
From cd316ca0578ef74836feb904b9ab6497b7b875c9 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sun, 13 Nov 2022 20:24:05 +0200
Subject: [PATCH 021/162] battery usage UI: use a fallback name for unknown
components
---
.../fuelgauge/batteryusage/BatteryEntry.java | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
index fef30563fe2..6b057484c9f 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
@@ -616,14 +616,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 7a3b6ded29286caa8bac48dc676b625d00ecc21d Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Tue, 14 Feb 2023 10:05:57 +0200
Subject: [PATCH 022/162] add a toggle for auto-grants of OTHER_SENSORS
permission
---
res/values/strings_ext.xml | 5 +++++
res/xml/more_security_privacy_settings.xml | 7 +++++++
2 files changed, 12 insertions(+)
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 34df22b18f1..f8173a12a79 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -15,4 +15,9 @@
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.
+
+ Allow Sensors permission to apps by default
+ Sensors is a non-standard permission, apps may malfunction if it’s denied.
+ A permission prompt will be shown when an app tries to access sensors. Note that some apps may need to be manually restarted after allowing the Sensors permission.
+
diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml
index 0068872ef31..3f95584f381 100644
--- a/res/xml/more_security_privacy_settings.xml
+++ b/res/xml/more_security_privacy_settings.xml
@@ -97,6 +97,13 @@
settings:controller=
"com.android.settings.sound.MediaControlsLockScreenPreferenceController" />
+
+
Date: Tue, 14 Feb 2023 10:27:56 +0200
Subject: [PATCH 023/162] add a toggle for camera access from the lock screen
---
res/values/strings_ext.xml | 2 ++
res/xml/security_settings_picker.xml | 4 ++++
src/com/android/settings/password/ChooseLockGeneric.java | 4 ++++
3 files changed, 10 insertions(+)
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index f8173a12a79..60aa5c3db17 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -20,4 +20,6 @@
Sensors is a non-standard permission, apps may malfunction if it’s denied.
A permission prompt will be shown when an app tries to access sensors. Note that some apps may need to be manually restarted after allowing the Sensors permission.
+ Allow camera access when locked
+
diff --git a/res/xml/security_settings_picker.xml b/res/xml/security_settings_picker.xml
index f3f3ba42b1b..fac3712e189 100644
--- a/res/xml/security_settings_picker.xml
+++ b/res/xml/security_settings_picker.xml
@@ -88,6 +88,10 @@
android:title="@string/lockpattern_settings_enhanced_pin_privacy_title"
android:summary="@string/lockpattern_settings_enhanced_pin_privacy_summary" />
+
Date: Tue, 14 Feb 2023 11:23:29 +0200
Subject: [PATCH 024/162] add auto-reboot setting
Squashed with:
20d4d3e46ba4a626d6044df499b91c1fc5e5bd96
514f0ddf2adbb7b69b0750806020476cef8ed17e
Co-authored-by: Daniel Micay
---
res/values/strings_ext.xml | 3 ++
res/xml/exploit_protection_settings.xml | 5 ++
.../security/AutoRebootPrefController.java | 49 +++++++++++++++++++
3 files changed, 57 insertions(+)
create mode 100644 src/com/android/settings/security/AutoRebootPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 60aa5c3db17..26a5d59a775 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -22,4 +22,7 @@
Allow camera access when locked
+ Auto reboot
+ Automatically reboot the device if it hasn\'t been unlocked within the selected duration of time.
+
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index 54da29f1394..faaf3b59180 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -5,6 +5,11 @@
android:key="exploit_protection_settings"
android:title="@string/exploit_protection_settings">
+
+
diff --git a/src/com/android/settings/security/AutoRebootPrefController.java b/src/com/android/settings/security/AutoRebootPrefController.java
new file mode 100644
index 00000000000..9c00e954e96
--- /dev/null
+++ b/src/com/android/settings/security/AutoRebootPrefController.java
@@ -0,0 +1,49 @@
+package com.android.settings.security;
+
+import android.content.Context;
+import android.ext.settings.ExtSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+import static java.util.concurrent.TimeUnit.DAYS;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+
+public class AutoRebootPrefController extends IntSettingPrefController {
+
+ public AutoRebootPrefController(Context ctx, String key) {
+ super(ctx, key, ExtSettings.AUTO_REBOOT_TIMEOUT);
+ }
+
+ @Override
+ public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+ addFooterPreference(screen, R.string.auto_reboot_footer,
+ "https://grapheneos.org/features#auto-reboot");
+ }
+
+ @Override
+ protected void getEntries(Entries entries) {
+ entries.add(R.string.switch_off_text, 0);
+ entries.add(3, DAYS);
+ entries.add(2, DAYS);
+ entries.add(36, HOURS);
+ entries.add(1, DAYS);
+ entries.add(18, HOURS);
+ entries.add(12, HOURS);
+ entries.add(8, HOURS);
+ entries.add(4, HOURS);
+ entries.add(2, HOURS);
+ entries.add(1, HOURS);
+ entries.add(30, MINUTES);
+ entries.add(10, MINUTES);
+ }
+
+ @Override
+ protected boolean isCredentialConfirmationRequired() {
+ return true;
+ }
+}
From 9f225b3028c2604898d91de51b7bc7df9882e45f Mon Sep 17 00:00:00 2001
From: r3g_5z
Date: Sat, 18 Feb 2023 11:09:31 -0500
Subject: [PATCH 025/162] Add toggle for screenshot timestamp EXIF metadata
Signed-off-by: r3g_5z
---
res/values/strings_ext.xml | 3 +++
res/xml/more_security_privacy_settings.xml | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 26a5d59a775..0c351a59378 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -25,4 +25,7 @@
Auto reboot
Automatically reboot the device if it hasn\'t been unlocked within the selected duration of time.
+ Save screenshot timestamp to EXIF
+ Enables adding a timestamp to screenshot EXIF metadata
+
diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml
index 3f95584f381..adf0d09c604 100644
--- a/res/xml/more_security_privacy_settings.xml
+++ b/res/xml/more_security_privacy_settings.xml
@@ -104,6 +104,12 @@
android:summaryOff="@string/auto_grant_OTHER_SENSORS_permission_summary_off"
settings:boolSettingField="android.ext.settings.ExtSettings AUTO_GRANT_OTHER_SENSORS_PERMISSION"/>
+
+
Date: Fri, 3 Mar 2023 09:53:21 +0200
Subject: [PATCH 026/162] add GNSS SUPL setting
---
res/values/strings_ext.xml | 8 ++++
res/xml/location_settings.xml | 5 +++
.../location/GnssSuplPrefController.java | 40 +++++++++++++++++++
3 files changed, 53 insertions(+)
create mode 100644 src/com/android/settings/location/GnssSuplPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 0c351a59378..e9ed237eec9 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -28,4 +28,12 @@
Save screenshot timestamp to EXIF
Enables adding a timestamp to screenshot EXIF metadata
+ Secure User Plane Location (SUPL)
+ A-GNSS (assisted satellite geolocation) based on nearby cell towers.
+
+ GrapheneOS proxy
+ Standard server
+ Off
+ Will make acquiring location lock significantly slower, especially if PSDS is turned off too
+
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 5d5c6b6cd38..c22c22c09a9 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -77,6 +77,11 @@
android:title="@string/location_services_preference_title"
settings:controller="com.android.settings.location.LocationServicesPreferenceController"/>
+
+
Date: Mon, 16 Oct 2023 09:42:40 -0400
Subject: [PATCH 027/162] 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 b3d42275fae..184e228d127 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -1096,9 +1096,6 @@ && isAutoPinConfirmPossible(length)
&& !isSupervisingProfile()) {
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 91432a0ded4248388b2802b71b45a6445db38360 Mon Sep 17 00:00:00 2001
From: r3g_5z
Date: Wed, 15 Mar 2023 21:11:12 -0400
Subject: [PATCH 028/162] 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 224a6f3b391..9550a7cb2cd 100644
--- a/src/com/android/settings/display/ScreenResolutionFragment.java
+++ b/src/com/android/settings/display/ScreenResolutionFragment.java
@@ -107,7 +107,6 @@ protected int getPreferenceScreenResId() {
@Override
protected void addStaticPreferences(PreferenceScreen screen) {
- updateIllustrationImage(mImagePreference);
screen.addPreference(mImagePreference);
final FooterPreference footerPreference = new FooterPreference(screen.getContext());
@@ -229,7 +228,6 @@ protected boolean setDefaultKey(final String key) {
}
setDisplayMode(width);
- updateIllustrationImage(mImagePreference);
return true;
}
From f222fb0ad75a5803a20aa68b5fbc0eddc8ef5a52 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Wed, 24 Jan 2024 19:13:22 +0200
Subject: [PATCH 029/162] add toggle for eSIM support via Google's eSIM LPA
package
---
res/values/strings_ext.xml | 18 +++
res/xml/network_provider_internet.xml | 8 ++
.../network/GoogleEuiccLpaController.java | 108 ++++++++++++++++++
3 files changed, 134 insertions(+)
create mode 100644 src/com/android/settings/network/GoogleEuiccLpaController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index e9ed237eec9..e04ab4c886b 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -36,4 +36,22 @@
Off
Will make acquiring location lock significantly slower, especially if PSDS is turned off too
+ eSIM support
+
+A device restart is required to enable this setting.
+
+ Warning
+
+"Turning off eSIM support will break the following functionality:
+
+• adding new eSIMs
+• turning existing eSIMs on or off
+• removing eSIMs, including from the lock screen (e.g. when eSIM is locked with a forgotten PIN)
+• wiping eSIMs during factory reset
+
+Device will be automatically restarted."
+
+ Restart
+ Proceed
+
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index 7a333672317..d1acf902104 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -56,6 +56,14 @@
settings:useAdminDisabledSummary="true"
settings:controller="com.android.settings.network.MobileNetworkSummaryController" />
+
+
setEnabled(isChecked));
+ b.show();
+
+ return false;
+ }
+}
From 83715685aaba1859155dc0da6a76b8bb0f186a68 Mon Sep 17 00:00:00 2001
From: r3g_5z
Date: Sun, 2 Apr 2023 22:23:41 -0400
Subject: [PATCH 030/162] remote key provisioning server setting
Co-authored-by: flawedworld
Signed-off-by: r3g_5z
---
res/values/strings_ext.xml | 5 +++
res/xml/network_provider_internet.xml | 6 ++++
.../RemoteProvisioningPrefController.java | 36 +++++++++++++++++++
3 files changed, 47 insertions(+)
create mode 100644 src/com/android/settings/network/RemoteProvisioningPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index e04ab4c886b..fc367bb5726 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -54,4 +54,9 @@ Device will be automatically restarted."
Restart
Proceed
+ Attestation key provisioning
+ GrapheneOS proxy
+ Google server
+ Off
+
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index d1acf902104..d04f6999b1c 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -126,4 +126,10 @@
android:summary="@string/cellular_security_summary"
android:order="30"
settings:controller="com.android.settings.network.CellularSecurityPreferenceController"/>
+
+
diff --git a/src/com/android/settings/network/RemoteProvisioningPrefController.java b/src/com/android/settings/network/RemoteProvisioningPrefController.java
new file mode 100644
index 00000000000..8617d6bd98c
--- /dev/null
+++ b/src/com/android/settings/network/RemoteProvisioningPrefController.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import android.content.Context;
+import android.ext.settings.RemoteKeyProvisioningSettings;
+
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+
+public class RemoteProvisioningPrefController extends IntSettingPrefController {
+
+ public RemoteProvisioningPrefController(Context ctx, String key) {
+ super(ctx, key, RemoteKeyProvisioningSettings.SERVER_SETTING);
+ }
+
+ @Override
+ protected void getEntries(Entries entries) {
+ entries.add(R.string.remote_provisioning_enabled_grapheneos_proxy, RemoteKeyProvisioningSettings.GRAPHENEOS_PROXY);
+ entries.add(R.string.remote_provisioning_enabled_google_server, RemoteKeyProvisioningSettings.STANDARD_SERVER);
+ }
+}
From 62200e2b1bcae517e7f275cb3a03975064f67a98 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Thu, 6 Apr 2023 12:11:09 +0300
Subject: [PATCH 031/162] 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 fc367bb5726..a7d5ff6d9f9 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -59,4 +59,19 @@ Device will be automatically restarted."
Google server
Off
+ Special access to hardware accelerators for Google apps
+ Access granted
+ Access not granted
+ Grant special access to hardware accelerators to Google apps
+
+"Some Google apps expect to be able to access hardware accelerators in a special, more capable way than regular apps do.
+
+Examples of such apps:
+• Pixel Camera
+• Google Photos
+• Google Recorder
+
+This setting applies to all users on the device."
+
+
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index f3a5f3216c7..32867ea63f7 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -231,4 +231,10 @@
android:name="classname"
android:value="com.android.settings.Settings$ChangeNfcTagAppsActivity" />
+
+
diff --git a/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java
new file mode 100644
index 00000000000..d681703f4cd
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java
@@ -0,0 +1,46 @@
+package com.android.settings.applications.specialaccess;
+
+import android.app.ActivityThread;
+import android.ext.settings.BoolSetting;
+import android.ext.settings.ExtSettings;
+import android.os.RemoteException;
+
+import com.android.internal.util.GoogleCameraUtils;
+import com.android.settings.R;
+import com.android.settings.ext.BoolSettingFragment;
+import com.android.settingslib.widget.FooterPreference;
+
+public class GoogleSpecialAcceleratorAccessFragment extends BoolSettingFragment {
+ private static final String TAG = GoogleSpecialAcceleratorAccessFragment.class.getSimpleName();
+
+ @Override
+ protected BoolSetting getSetting() {
+ return ExtSettings.ALLOW_GOOGLE_APPS_SPECIAL_ACCESS_TO_ACCELERATORS;
+ }
+
+ @Override
+ protected CharSequence getTitle() {
+ return resText(R.string.Google_apps_special_accelerator_access_title);
+ }
+
+ @Override
+ protected CharSequence getMainSwitchTitle() {
+ return resText(R.string.Google_apps_special_accelerator_access_main_switch);
+ }
+
+ @Override
+ protected void onMainSwitchChanged(boolean state) {
+ if (GoogleCameraUtils.isCustomSeInfoNeededForAccessToAccelerators(requireContext())) {
+ try {
+ ActivityThread.getPackageManager().updateSeInfo(GoogleCameraUtils.PACKAGE_NAME);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ @Override
+ protected FooterPreference makeFooterPref(FooterPreference.Builder builder) {
+ return builder.setTitle(R.string.Google_apps_special_accelerator_access_footer).build();
+ }
+}
diff --git a/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java
new file mode 100644
index 00000000000..ac7d84fcbb0
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java
@@ -0,0 +1,34 @@
+package com.android.settings.applications.specialaccess;
+
+import android.content.Context;
+import android.ext.settings.ExtSettings;
+
+import com.android.settings.R;
+import com.android.settings.ext.BoolSettingFragmentPrefController;
+
+public class GoogleSpecialAcceleratorAccessPrefController extends BoolSettingFragmentPrefController {
+
+ public GoogleSpecialAcceleratorAccessPrefController(Context ctx, String key) {
+ super(ctx, key, ExtSettings.ALLOW_GOOGLE_APPS_SPECIAL_ACCESS_TO_ACCELERATORS);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_Google_apps_can_have_special_access_to_accelerators)) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+
+ return super.getAvailabilityStatus();
+ }
+
+ @Override
+ protected CharSequence getSummaryOn() {
+ return resText(R.string.Google_apps_special_accelerator_access_summary_granted);
+ }
+
+ @Override
+ protected CharSequence getSummaryOff() {
+ return resText(R.string.Google_apps_special_accelerator_access_summary_not_granted);
+ }
+}
From 4e37451784815caae19da021683548dec7612c1c Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Wed, 3 May 2023 08:57:01 +0300
Subject: [PATCH 032/162] add GNSS PSDS setting
---
res/values/strings_ext.xml | 10 ++++
res/xml/location_settings.xml | 5 ++
.../location/GnssPsdsPrefController.java | 49 +++++++++++++++++++
3 files changed, 64 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 a7d5ff6d9f9..cbe556d6b7d 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -74,4 +74,14 @@ Examples of such apps:
This setting applies to all users on the device."
+ Predicted Satellite Data Service (PSDS)
+
+"If PSDS is turned on, static PSDS information files will be downloaded periodically to improve location resolution speed and accuracy.
+No query or data is sent to the server. These files contain orbits and statuses of satellites, Earth environmental data and time adjustment information."
+
+ GrapheneOS server
+ Standard server
+ Off
+ Will make acquiring location lock significantly slower, especially if SUPL is turned off too
+
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index c22c22c09a9..c115ccf6486 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -82,6 +82,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 033/162] add connectivity checks setting
---
res/values/strings_ext.xml | 10 +++++++
res/xml/network_provider_internet.xml | 6 ++++
.../ConnectivityChecksPrefController.java | 29 +++++++++++++++++++
3 files changed, 45 insertions(+)
create mode 100644 src/com/android/settings/network/ConnectivityChecksPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index cbe556d6b7d..73019e6f41e 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -84,4 +84,14 @@ No query or data is sent to the server. These files contain orbits and statuses
Off
Will make acquiring location lock significantly slower, especially if SUPL is turned off too
+ GrapheneOS server
+ Standard (Google) server
+ Off
+
+ Internet connectivity checks
+
+"Connectivity check is a special empty server request that is made to find out whether the current network has internet connection.
+There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
+
+
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index d04f6999b1c..b4becf7c709 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -127,6 +127,12 @@
android:order="30"
settings:controller="com.android.settings.network.CellularSecurityPreferenceController"/>
+
+
Date: Wed, 24 May 2023 14:57:01 +0300
Subject: [PATCH 034/162] 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 73019e6f41e..dc5f42758b2 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 d510fe61e75d64d56a1628724fe18a423ec73d28 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Thu, 25 May 2023 16:25:33 +0300
Subject: [PATCH 035/162] add Wi-Fi auto-off setting
---
res/values/strings_ext.xml | 2 +
res/xml/exploit_protection_settings.xml | 5 +++
.../wifi/WifiAutoOffPrefController.java | 39 +++++++++++++++++++
3 files changed, 46 insertions(+)
create mode 100644 src/com/android/settings/wifi/WifiAutoOffPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index dc5f42758b2..770ec6e7ddb 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -95,4 +95,6 @@ No query or data is sent to the server. These files contain orbits and statuses
There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
+ Turn off Wi-Fi automatically
+ If Wi-Fi is disconnected, it will be turned off after the selected timeout.
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index faaf3b59180..b5f3a0e1dde 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -10,6 +10,11 @@
android:title="@string/auto_reboot_title"
settings:controller="com.android.settings.security.AutoRebootPrefController" />
+
+
diff --git a/src/com/android/settings/wifi/WifiAutoOffPrefController.java b/src/com/android/settings/wifi/WifiAutoOffPrefController.java
new file mode 100644
index 00000000000..b8ec16bd69a
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiAutoOffPrefController.java
@@ -0,0 +1,39 @@
+package com.android.settings.wifi;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.ext.settings.ExtSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.AutoOffSetting;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class WifiAutoOffPrefController extends IntSettingPrefController {
+
+ public WifiAutoOffPrefController(Context ctx, String key) {
+ super(ctx, key, ExtSettings.WIFI_AUTO_OFF);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ int r = super.getAvailabilityStatus();
+ if (r == AVAILABLE) {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI) ?
+ AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+ return r;
+ }
+
+ @Override
+ public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+ addFooterPreference(screen, R.string.wifi_auto_off_footer);
+ }
+
+ @Override
+ protected void getEntries(Entries entries) {
+ AutoOffSetting.getEntries(entries);
+ }
+}
From 28b2d90da8836ab8b310c35f8012b95e7a2871aa Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Wed, 24 May 2023 15:01:04 +0300
Subject: [PATCH 036/162] add Bluetooth auto-off setting
---
res/values/strings_ext.xml | 6 +++
res/xml/exploit_protection_settings.xml | 5 +++
.../BluetoothAutoOffPrefController.java | 39 +++++++++++++++++++
3 files changed, 50 insertions(+)
create mode 100644 src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 770ec6e7ddb..44ce80d094d 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -97,4 +97,10 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Turn off Wi-Fi automatically
If Wi-Fi is disconnected, it will be turned off after the selected timeout.
+
+ Turn off Bluetooth automatically
+
+"If there are no connected devices, Bluetooth will turn off after the selected timeout."
+
+
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index b5f3a0e1dde..bfd7e4dc3d9 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -15,6 +15,11 @@
android:title="@string/wifi_auto_off_title"
settings:controller="com.android.settings.wifi.WifiAutoOffPrefController"/>
+
+
diff --git a/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java b/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java
new file mode 100644
index 00000000000..14791951802
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java
@@ -0,0 +1,39 @@
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.ext.settings.ExtSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.AutoOffSetting;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class BluetoothAutoOffPrefController extends IntSettingPrefController {
+
+ public BluetoothAutoOffPrefController(Context ctx, String key) {
+ super(ctx, key, ExtSettings.BLUETOOTH_AUTO_OFF);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ int r = super.getAvailabilityStatus();
+ if (r == AVAILABLE) {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH) ?
+ AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+ return r;
+ }
+
+ @Override
+ public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+ addFooterPreference(screen, R.string.bluetooth_auto_off_footer);
+ }
+
+ @Override
+ protected void getEntries(Entries entries) {
+ AutoOffSetting.getEntries(entries);
+ }
+}
From d57a3732f30b0d8af6ba529e812a1c4fd34d21bc Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Thu, 25 May 2023 16:47:42 +0300
Subject: [PATCH 037/162] add exec spawning setting
---
res/values/strings_ext.xml | 4 +++
res/xml/exploit_protection_settings.xml | 6 +++-
.../security/ExecSpawningFragment.java | 34 +++++++++++++++++++
.../security/ExecSpawningPrefController.java | 13 +++++++
4 files changed, 56 insertions(+), 1 deletion(-)
create mode 100644 src/com/android/settings/security/ExecSpawningFragment.java
create mode 100644 src/com/android/settings/security/ExecSpawningPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 44ce80d094d..37b4eb73129 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -103,4 +103,8 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
"If there are no connected devices, Bluetooth will turn off after the selected timeout."
+ Secure app spawning
+ Use secure app spawning
+ Launch apps in a more secure way than Android which takes slightly longer and increases memory usage by app processes.
+
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index bfd7e4dc3d9..ada50481305 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -24,7 +24,11 @@
android:key="app_exploit_protection_settings"
android:title="@string/app_exploit_protection_category">
-
+
diff --git a/src/com/android/settings/security/ExecSpawningFragment.java b/src/com/android/settings/security/ExecSpawningFragment.java
new file mode 100644
index 00000000000..1ab1f744617
--- /dev/null
+++ b/src/com/android/settings/security/ExecSpawningFragment.java
@@ -0,0 +1,34 @@
+package com.android.settings.security;
+
+import android.ext.settings.BoolSetting;
+import android.ext.settings.ExtSettings;
+import android.net.Uri;
+
+import com.android.settings.R;
+import com.android.settings.ext.BoolSettingFragment;
+import com.android.settingslib.widget.FooterPreference;
+
+public class ExecSpawningFragment extends BoolSettingFragment {
+
+ @Override
+ protected BoolSetting getSetting() {
+ return ExtSettings.EXEC_SPAWNING;
+ }
+
+ @Override
+ protected CharSequence getTitle() {
+ return getText(R.string.exec_spawning_title);
+ }
+
+ @Override
+ protected CharSequence getMainSwitchTitle() {
+ return getText(R.string.exec_spawning_title_inner);
+ }
+
+ @Override
+ protected FooterPreference makeFooterPref(FooterPreference.Builder builder) {
+ FooterPreference p = builder.setTitle(R.string.exec_spawning_footer).build();
+ setFooterPrefLearnMoreUri(p, Uri.parse("https://grapheneos.org/usage#exec-spawning"));
+ return p;
+ }
+}
diff --git a/src/com/android/settings/security/ExecSpawningPrefController.java b/src/com/android/settings/security/ExecSpawningPrefController.java
new file mode 100644
index 00000000000..cd2be5cfc71
--- /dev/null
+++ b/src/com/android/settings/security/ExecSpawningPrefController.java
@@ -0,0 +1,13 @@
+package com.android.settings.security;
+
+import android.content.Context;
+import android.ext.settings.ExtSettings;
+
+import com.android.settings.ext.BoolSettingFragmentPrefController;
+
+public class ExecSpawningPrefController extends BoolSettingFragmentPrefController {
+
+ public ExecSpawningPrefController(Context ctx, String key) {
+ super(ctx, key, ExtSettings.EXEC_SPAWNING);
+ }
+}
From b198d3c05df1f7fadbdc9e6530d61a239b432081 Mon Sep 17 00:00:00 2001
From: flawedworld
Date: Sun, 25 Jun 2023 13:53:58 +0100
Subject: [PATCH 038/162] 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 90aead8c50d85dcbc77844b27dbf1eb54509eca1 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 039/162] Remove "Add users from lock screen" setting
---
.../users/AddUserWhenLockedPreferenceController.java | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
index 38aef0f217b..7618f73e4b0 100644
--- a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
+++ b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
@@ -51,17 +51,7 @@ public void updateState(Preference preference) {
@Override
public int getAvailabilityStatus() {
- if (mContext.getResources()
- .getBoolean(
- com.android.internal.R.bool.config_userSwitchingMustGoThroughLoginScreen)) {
- return UNSUPPORTED_ON_DEVICE;
- } else if (!mUserCaps.isAdmin()) {
- return DISABLED_FOR_USER;
- } else if (mUserCaps.mDisallowAddUser && !mUserCaps.mDisallowAddUserSetByAdmin) {
- return DISABLED_FOR_USER;
- } else {
- return AVAILABLE;
- }
+ return UNSUPPORTED_ON_DEVICE;
}
@Override
From 59dd7c1cc6ed148ed015db23248c4a85d8302691 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 040/162] Factor out common code for reading/writing
UserManager restrictions
---
.../settings/users/UserDetailsSettings.java | 2 +
.../settings/users/UserRestrictions.java | 66 +++++++++++++++++++
2 files changed, 68 insertions(+)
create mode 100644 src/com/android/settings/users/UserRestrictions.java
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 14fb6f353d0..e085b6fb793 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -118,6 +118,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() {
@@ -365,6 +366,7 @@ void initialize(Context context, Bundle arguments) {
boolean isNewUser =
arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false);
mUserInfo = mUserManager.getUserInfo(userId);
+ userRestrictions = UserRestrictions.createInstance(mUserManager, mUserInfo);
mSwitchUserPref = findPreference(KEY_SWITCH_USER);
mPhonePref = findPreference(KEY_ENABLE_TELEPHONY_CALLING);
diff --git a/src/com/android/settings/users/UserRestrictions.java b/src/com/android/settings/users/UserRestrictions.java
new file mode 100644
index 00000000000..6ab1b301118
--- /dev/null
+++ b/src/com/android/settings/users/UserRestrictions.java
@@ -0,0 +1,66 @@
+package com.android.settings.users;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public final class UserRestrictions {
+
+ @NonNull
+ private final UserManager userManager;
+ @NonNull
+ public final UserInfo userInfo;
+
+ @Nullable
+ public static UserRestrictions createInstance(@NonNull Context ctx, int userId) {
+ UserManager userManager = ctx.getSystemService(UserManager.class);
+ if (userManager == null) {
+ return null;
+ }
+
+ return createInstance(userManager, userId);
+ }
+
+ @Nullable
+ public static UserRestrictions createInstance(@NonNull UserManager userManager, int userId) {
+ UserInfo userInfo = userManager.getUserInfo(userId);
+ if (userInfo == null) {
+ return null;
+ }
+
+ return new UserRestrictions(userManager, userInfo);
+ }
+
+ @NonNull
+ public static UserRestrictions createInstance(@NonNull UserManager userManager, @NonNull UserInfo userInfo) {
+ return new UserRestrictions(userManager, userInfo);
+ }
+
+ private UserRestrictions(@NonNull UserManager userManager, @NonNull UserInfo userInfo) {
+ this.userManager = userManager;
+ this.userInfo = userInfo;
+ }
+
+ public boolean isSet(String restrictionKey) {
+ final boolean isSetFromUser = userManager.hasUserRestriction(restrictionKey, userInfo.getUserHandle());
+ if (userInfo.isGuest()) {
+ return isSetFromUser || userManager.getDefaultGuestRestrictions().getBoolean(restrictionKey);
+ }
+
+ return isSetFromUser;
+ }
+
+ public void set(String restrictionKey, boolean enableRestriction) {
+ if (userInfo.isGuest()) {
+ Bundle defaultGuestRestrictions = userManager.getDefaultGuestRestrictions();
+ defaultGuestRestrictions.putBoolean(restrictionKey, enableRestriction);
+ userManager.setDefaultGuestRestrictions(defaultGuestRestrictions);
+ } else {
+ userManager.setUserRestriction(restrictionKey, enableRestriction, userInfo.getUserHandle());
+ }
+ }
+}
From 6e9fe6c758d0345887d60898699ccaf9cf7e1061 Mon Sep 17 00:00:00 2001
From: Pratyush
Date: Sat, 3 Sep 2022 15:52:37 +0530
Subject: [PATCH 041/162] 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 e085b6fb793..42594c2f7d4 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -91,7 +91,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;
@VisibleForTesting
static final int REQUEST_CONFIRM_REMOVE = 1;
@@ -458,7 +458,6 @@ void initialize(Context context, Bundle arguments) {
} else {
mPhonePref.setChecked(!mUserManager.hasUserRestriction(
UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
- removePreference(KEY_APP_COPYING);
}
// Remove preference KEY_REMOVE_USER if DISALLOW_REMOVE_USER restriction is set
From 5d3b9132d9e175003441b2eedf84d3f96ecf1016 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 042/162] UserManager settings for apps installs and updates
---
res/values/strings_ext.xml | 11 ++
res/xml/user_details_settings.xml | 4 +
.../users/UserAppsInstallSettings.java | 177 ++++++++++++++++++
.../settings/users/UserDetailsSettings.java | 11 ++
4 files changed, 203 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 37b4eb73129..a01ad75d9ed 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -107,4 +107,15 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Use secure app spawning
Launch apps in a more secure way than Android which takes slightly longer and increases memory usage by app processes.
+
+ App installs and updates
+
+ Enabled
+ Enabled for first party sources
+ Disabled
+
+ Enable app installs and updates
+ Enable app installs and updates from first party sources only
+ Disable app installs and updates
+
diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml
index 8e15d14bf5a..2cd01c1ef7d 100644
--- a/res/xml/user_details_settings.xml
+++ b/res/xml/user_details_settings.xml
@@ -33,6 +33,10 @@
android:key="app_and_content_access"
android:icon="@drawable/ic_lock_closed"
android:title="@string/user_restrictions_title" />
+
getCandidates() {
+ Context ctx = requireContext();
+ ArrayList candidates = new ArrayList<>(3);
+ if (!userRestrictions.userInfo.isGuest()) {
+ candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_enabled),
+ ctx.getString(R.string.user_app_install_enabled_desc),
+ INSTALL_ENABLED, true));
+ }
+ candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_enabled_first_party_sources),
+ ctx.getString(R.string.user_app_install_enabled_first_party_sources_desc),
+ INSTALL_FIRST_PARTY_ENABLED, true));
+ candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_disabled),
+ ctx.getString(R.string.user_app_install_disabled_desc),
+ INSTALL_DISABLED, true));
+ return candidates;
+ }
+
+ @Override
+ public void bindPreferenceExtra(SelectorWithWidgetPreference pref, String key, CandidateInfo info,
+ String defaultKey, String systemDefaultKey) {
+ pref.setSingleLineTitle(false);
+
+ if (info instanceof CandidateInfoExtra) {
+ var cie = (CandidateInfoExtra) info;
+ pref.setSummary(cie.loadSummary());
+ }
+ }
+
+ @Override
+ protected String getDefaultKey() {
+ return getCurrentInstallRestriction(userRestrictions);
+ }
+
+ @Override
+ protected boolean setDefaultKey(String key) {
+ if (key == null) {
+ return false;
+ }
+
+ switch (key) {
+ case INSTALL_ENABLED:
+ if (userRestrictions.userInfo.isGuest()) {
+ return false;
+ }
+ userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false);
+ userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
+ return true;
+ case INSTALL_FIRST_PARTY_ENABLED:
+ userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false);
+ if (!userRestrictions.userInfo.isGuest()) {
+ userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+ }
+ return true;
+ case INSTALL_DISABLED:
+ userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, true);
+ if (!userRestrictions.userInfo.isGuest()) {
+ userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+ }
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return METRICS_CATEGORY_UNKNOWN;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateCandidates();
+ }
+}
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 42594c2f7d4..7555279f01c 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -79,6 +79,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";
@@ -114,6 +116,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
Preference mRemoveUserPref;
@VisibleForTesting
TwoStatePreference mGrantAdminPref;
+ Preference mAppsInstallsPref;
@VisibleForTesting
/** The user being studied (not the user doing the studying). */
@@ -150,6 +153,8 @@ public void onResume() {
if (mUserInfo.isGuest() && mGuestUserAutoCreated) {
mRemoveUserPref.setEnabled((mUserInfo.flags & UserInfo.FLAG_INITIALIZED) != 0);
}
+ mAppsInstallsPref.setSummary(UserAppsInstallSettings.getDescription(
+ requireContext(), userRestrictions));
}
@Override
@@ -190,6 +195,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;
}
@@ -376,6 +384,7 @@ void initialize(Context context, Bundle arguments) {
mGrantAdminPref = findPreference(KEY_GRANT_ADMIN);
mGrantAdminPref.setChecked(mUserInfo.isAdmin());
+ mAppsInstallsPref = findPreference(KEY_APP_INSTALLS);
mSwitchUserPref.setVisible(mUserCaps.mUserSwitchingUiEnabled
&& UserHandle.myUserId() != mUserInfo.id);
@@ -432,6 +441,7 @@ void initialize(Context context, Bundle arguments) {
removePreference(KEY_ENABLE_TELEPHONY_CALLING);
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_CALLING);
@@ -466,6 +476,7 @@ void initialize(Context context, Bundle arguments) {
removePreference(KEY_REMOVE_USER);
}
+ mAppsInstallsPref.setOnPreferenceClickListener(this);
mPhonePref.setOnPreferenceChangeListener(this);
mGrantAdminPref.setOnPreferenceChangeListener(this);
mAppAndContentAccessPref.setOnPreferenceClickListener(this);
From 12cfaa0e41cf89e18f988fae5d9b9b3644be02ef 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 043/162] UserManager settings for running in background
---
res/values/strings_ext.xml | 2 ++
res/xml/user_details_settings.xml | 4 ++++
.../android/settings/users/UserDetailsSettings.java | 13 +++++++++++++
3 files changed, 19 insertions(+)
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index a01ad75d9ed..79c2ccd45d6 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -117,5 +117,7 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Enable app installs and updates
Enable app installs and updates from first party sources only
Disable app installs and updates
+
+ Allow running in background
diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml
index 2cd01c1ef7d..5f6df097ec9 100644
--- a/res/xml/user_details_settings.xml
+++ b/res/xml/user_details_settings.xml
@@ -25,6 +25,10 @@
android:key="user_grant_admin"
android:icon="@drawable/ic_admin_panel_settings"
android:title="@string/user_grant_admin" />
+
Date: Wed, 26 Jul 2023 09:45:29 +0000
Subject: [PATCH 044/162] 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 f9cad65daeb..c3484111183 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -158,6 +158,7 @@ public void onResume() {
}
mAppsInstallsPref.setSummary(UserAppsInstallSettings.getDescription(
requireContext(), userRestrictions));
+ mAppCopyingPref.setEnabled(!userRestrictions.isSet(UserManager.DISALLOW_INSTALL_APPS));
}
@Override
From e893e7f9fc0e20f74d936b347072df623a341c51 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 2 Mar 2024 11:24:34 +0200
Subject: [PATCH 045/162] add support for disabling non-system apps
---
.../settings/spa/app/appinfo/AppDisableButton.kt | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt b/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt
index 555e9f14c61..07d583cde30 100644
--- a/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt
@@ -31,6 +31,7 @@ import com.android.settingslib.spa.widget.dialog.AlertDialogButton
import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.android.settingslib.spaprivileged.model.app.installed
import com.android.settingslib.spaprivileged.model.app.isDisabledUntilUsed
import com.android.settingslib.Utils as SettingsLibUtils
@@ -47,7 +48,7 @@ class AppDisableButton(
@Composable
fun getActionButton(app: ApplicationInfo): ActionButton? {
- if (!app.isSystemApp) return null
+ if (!app.installed) return null
return when {
app.enabled && !app.isDisabledUntilUsed -> {
@@ -62,6 +63,8 @@ class AppDisableButton(
* Gets whether a package can be disabled.
*/
private fun ApplicationInfo.canBeDisabled(): Boolean = when {
+ !isSystemApp -> appButtonRepository.isAllowUninstallOrArchive(context, this)
+
// Try to prevent the user from bricking their phone by not allowing disabling of apps
// signed with the system certificate.
isSignedWithPlatformKey -> false
@@ -98,7 +101,12 @@ class AppDisableButton(
// Currently we apply the same device policy for both the uninstallation and disable
// button.
if (!appButtonRepository.isUninstallBlockedByAdmin(app)) {
- dialogPresenter.open()
+ if (app.isSystemApp) {
+ dialogPresenter.open()
+ } else {
+ packageInfoPresenter.disable()
+ }
+
}
}
}
From 0cb09d32eb51c18e53d7e73a9edaa5464c004ac3 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 2 Mar 2024 12:29:45 +0200
Subject: [PATCH 046/162] don't show "More options" button in App info
uninstall dialog
That button opens app's App info screen.
---
src/com/android/settings/spa/app/AppUtil.kt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/com/android/settings/spa/app/AppUtil.kt b/src/com/android/settings/spa/app/AppUtil.kt
index 64da61380f5..7b319aeddeb 100644
--- a/src/com/android/settings/spa/app/AppUtil.kt
+++ b/src/com/android/settings/spa/app/AppUtil.kt
@@ -37,6 +37,7 @@ fun Context.startUninstallActivity(
val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers)
+ putExtra(Intent.EXTRA_UNINSTALL_SHOW_MORE_OPTIONS_BUTTON, false)
}
startActivityAsUser(intent, userHandle)
-}
\ No newline at end of file
+}
From c2e1378babb0f4ea1718d73d2a1854cb18839756 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 2 Mar 2024 11:19:46 +0200
Subject: [PATCH 047/162] add Storage Scopes link to the "App info" screen
---
res/values/strings_ext.xml | 3 +-
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
.../app/appinfo/AppStorageScopesPreference.kt | 32 +++++++++++++++++++
3 files changed, 35 insertions(+), 1 deletion(-)
create mode 100644 src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 79c2ccd45d6..cf015c0d004 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -85,6 +85,8 @@ No query or data is sent to the server. These files contain orbits and statuses
Off
Will make acquiring location lock significantly slower, especially if SUPL is turned off too
+ Storage Scopes
+
GrapheneOS server
Standard (Google) server
Off
@@ -119,5 +121,4 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Disable app installs and updates
Allow running in background
-
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 2004757ed03..4e6796d4ced 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -149,6 +149,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
AppPermissionPreference(app)
ManageTargetAppFunctionAccessPreference(app)
ManageAgentAppFunctionAccessPreference(app)
+ AppStorageScopesPreference(app)
AppStoragePreference(app)
InstantAppDomainsPreference(app)
AppDataUsagePreference(app)
diff --git a/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt b/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt
new file mode 100644
index 00000000000..cbcd8944f56
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt
@@ -0,0 +1,32 @@
+package com.android.settings.spa.app.appinfo
+
+import android.app.StorageScope
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.content.pm.GosPackageStateFlag
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.userHandle
+import com.android.settingslib.spaprivileged.model.app.userId
+
+@Composable
+fun AppStorageScopesPreference(app: ApplicationInfo) {
+ val pkgName = app.packageName
+ if (!GosPackageState.get(pkgName, app.userId).hasFlag(GosPackageStateFlag.STORAGE_SCOPES_ENABLED)) {
+ return
+ }
+
+ val context = LocalContext.current
+
+ Preference(object : PreferenceModel {
+ override val title = stringResource(R.string.storage_scopes)
+ override val onClick = {
+ val intent = StorageScope.createConfigActivityIntent(pkgName)
+ context.startActivityAsUser(intent, app.userHandle)
+ }
+ })
+}
From 4b4c1636472903506df851e6628d4ac9f2588f1d Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 2 Mar 2024 11:20:31 +0200
Subject: [PATCH 048/162] add Storage Scopes link to "All files access" screen
---
.../spa/app/specialaccess/AllFilesAccess.kt | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt b/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt
index f6c08c0ca7c..6dba4817a2a 100644
--- a/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt
+++ b/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt
@@ -18,11 +18,19 @@ package com.android.settings.spa.app.specialaccess
import android.Manifest
import android.app.AppOpsManager
+import android.app.StorageScope
import android.app.settings.SettingsEnums
import android.content.Context
+import android.content.pm.PackageInfo
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.model.app.AppOps
+import com.android.settingslib.spaprivileged.model.app.userHandle
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
@@ -54,4 +62,18 @@ class AllFilesAccessListModel(context: Context) : AppOpPermissionListModel(conte
}
featureFactory.metricsFeatureProvider.action(context, category, "")
}
+
+ @Composable
+ override fun extContent(record: AppOpPermissionRecord, pkgInfo: PackageInfo) {
+ val context = LocalContext.current
+
+ Preference(object : PreferenceModel {
+ override val title = stringResource(R.string.storage_scopes)
+ override val onClick = {
+ val app = record.app
+ val i = StorageScope.createConfigActivityIntent(app.packageName)
+ context.startActivityAsUser(i, app.userHandle)
+ }
+ })
+ }
}
From 1925ca8b46152b91953f3047707259c67eb91ad5 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Fri, 8 Jul 2022 13:40:22 +0300
Subject: [PATCH 049/162] add OBB access toggle to "Install unknown apps"
screen
---
res/values/strings_ext.xml | 3 ++
.../app/specialaccess/InstallUnknownApps.kt | 52 ++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index cf015c0d004..7afa35c78d4 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -121,4 +121,7 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Disable app installs and updates
Allow running in background
+
+ Allow access to Android/obb folder
+ Required for installation of some large apps (mostly games) that use OBB expansion files
diff --git a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
index d6fe7160dbf..0a3d5219bc9 100644
--- a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
+++ b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
@@ -22,10 +22,18 @@ import android.app.AppOpsManager
import android.app.AppOpsManager.MODE_DEFAULT
import android.content.Context
import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.content.pm.GosPackageStateFlag
+import android.content.pm.PackageInfo
import android.os.UserManager
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spaprivileged.model.app.AppOps
import com.android.settingslib.spaprivileged.model.app.AppOpsController
import com.android.settingslib.spaprivileged.model.app.AppRecord
@@ -44,7 +52,26 @@ object InstallUnknownAppsListProvider : TogglePermissionAppListProvider {
data class InstallUnknownAppsRecord(
override val app: ApplicationInfo,
val appOpsController: AppOpsController,
-) : AppRecord
+) : AppRecord {
+ val isObbFlagSet = mutableStateOf(isObbFlagSet())
+
+ fun isObbFlagSet(): Boolean {
+ return GosPackageState.get(app.packageName, app.userId).hasFlag(GosPackageStateFlag.ALLOW_ACCESS_TO_OBB_DIRECTORY)
+ }
+
+ fun setObbFlagState(state: Boolean): Boolean {
+ GosPackageState.edit(app.packageName, app.userId).run {
+ setFlagState(GosPackageStateFlag.ALLOW_ACCESS_TO_OBB_DIRECTORY, state)
+ killUidAfterApply()
+ if (apply()) {
+ isObbFlagSet.value = state
+ return true
+ } else {
+ return false
+ }
+ }
+ }
+}
class InstallUnknownAppsListModel(private val context: Context) :
TogglePermissionAppListModel {
@@ -84,6 +111,29 @@ class InstallUnknownAppsListModel(private val context: Context) :
override fun setAllowed(record: InstallUnknownAppsRecord, newAllowed: Boolean) {
record.appOpsController.setAllowed(newAllowed)
+ if (!newAllowed) {
+ record.setObbFlagState(false)
+ }
+ }
+
+ @Composable
+ override fun extContent(record: InstallUnknownAppsRecord, pkgInfo: PackageInfo) {
+ val context = LocalContext.current
+
+ SwitchPreference(object : SwitchPreferenceModel {
+ override val title = stringResource(R.string.allow_access_to_obb_directory_title)
+ override val summary = {
+ context.getString(R.string.allow_access_to_obb_directory_summary)
+ }
+
+ override val checked = {
+ record.isObbFlagSet.value
+ }
+ override val onCheckedChange = { newChecked: Boolean ->
+ record.setObbFlagState(newChecked)
+ Unit
+ }
+ })
}
companion object {
From 8b14197a99f83a7ff4d025ec73f7c94f6c4a8f0e Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 2 Mar 2024 11:22:22 +0200
Subject: [PATCH 050/162] add Contact Scopes link to the "App info" screen
---
res/values/strings_ext.xml | 2 ++
.../app/appinfo/AppContactScopesPreference.kt | 32 +++++++++++++++++++
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
3 files changed, 35 insertions(+)
create mode 100644 src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 7afa35c78d4..94a22b60f8a 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -85,6 +85,8 @@ No query or data is sent to the server. These files contain orbits and statuses
Off
Will make acquiring location lock significantly slower, especially if SUPL is turned off too
+ Contact Scopes
+
Storage Scopes
GrapheneOS server
diff --git a/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt b/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt
new file mode 100644
index 00000000000..be4cf6fadbc
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt
@@ -0,0 +1,32 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.content.pm.GosPackageStateFlag
+import android.ext.cscopes.ContactScopesApi
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.userHandle
+import com.android.settingslib.spaprivileged.model.app.userId
+
+@Composable
+fun AppContactScopesPreference(app: ApplicationInfo) {
+ val pkgName = app.packageName
+ if (!GosPackageState.get(pkgName, app.userId).hasFlag(GosPackageStateFlag.CONTACT_SCOPES_ENABLED)) {
+ return
+ }
+
+ val context = LocalContext.current
+
+ Preference(object : PreferenceModel {
+ override val title = stringResource(R.string.contact_scopes)
+ override val onClick = {
+ val intent = ContactScopesApi.createConfigActivityIntent(pkgName)
+ context.startActivityAsUser(intent, app.userHandle)
+ }
+ })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 4e6796d4ced..391a21273d8 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -150,6 +150,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
ManageTargetAppFunctionAccessPreference(app)
ManageAgentAppFunctionAccessPreference(app)
AppStorageScopesPreference(app)
+ AppContactScopesPreference(app)
AppStoragePreference(app)
InstantAppDomainsPreference(app)
AppDataUsagePreference(app)
From d0c9018b5de3bc9ad3690942b31e51a23e290260 Mon Sep 17 00:00:00 2001
From: empratyush
Date: Mon, 20 Jun 2022 22:16:29 +0300
Subject: [PATCH 051/162] add Battery share toggle
---
Android.bp | 1 +
res/values/strings_ext.xml | 3 +
res/xml/power_usage_summary.xml | 9 ++
.../BatterySharePreferenceController.java | 99 +++++++++++++++++++
4 files changed, 112 insertions(+)
create mode 100644 src/com/android/settings/display/BatterySharePreferenceController.java
diff --git a/Android.bp b/Android.bp
index 47244771a25..32cb853e568 100644
--- a/Android.bp
+++ b/Android.bp
@@ -100,6 +100,7 @@ android_library {
// Settings dependencies
"FingerprintManagerInteractor",
"MediaDrmSettingsFlagsLib",
+ "ReverseWirelessCharging",
"Settings-change-ids",
"SettingsLib",
"SettingsLibActivityEmbedding",
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 94a22b60f8a..775f9cc184a 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -126,4 +126,7 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Allow access to Android/obb folder
Required for installation of some large apps (mostly games) that use OBB expansion files
+
+ Charge other devices by placing them on the back of your phone
+ Battery share
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 4890560e3f7..9b1ba7b83f4 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -77,6 +77,15 @@
settings:controller="com.android.settings.display.BatteryPercentagePreferenceController" />
+
+
+
+
update());
+ }
+ };
+
+
+ public BatterySharePreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ mContext = context;
+ wirelessCharger = ReverseWirelessCharger.getInstance();
+ }
+
+ public boolean isPlugged(Context context) {
+ Intent intent = context.registerReceiver(null,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ return plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ update();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_BATTERY_SHARE;
+ }
+
+ private void update() {
+ if (mPreference == null) return;
+ boolean enabled = !isPlugged(mContext) && wirelessCharger.isRtxSupported();
+ mPreference.setEnabled(enabled);
+ ((TwoStatePreference) mPreference).setChecked(wirelessCharger.isRtxModeOn());
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return wirelessCharger.isRtxSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ update();
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ wirelessCharger.setRtxMode((Boolean) newValue);
+ return true;
+ }
+
+ @Override
+ public void onStart() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ mContext.registerReceiver(mBroadcastReceiver, filter);
+ }
+
+ @Override
+ public void onStop() {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ }
+}
From 86e671c3e41e66881701380947ed570caee7d283 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Fri, 15 Sep 2023 10:03:16 +0300
Subject: [PATCH 052/162] 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 8c21fe4ed73..28d7036e7a3 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -618,7 +618,7 @@
content://com.android.providers.media.documents/root/others_root
- true
+ false
Allow running in background
+ "Warning: enabling this setting might cause some apps to stop working.
+
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/ext/AppPrefUtils.java b/src/com/android/settings/ext/AppPrefUtils.java
new file mode 100644
index 00000000000..3ae426bf36f
--- /dev/null
+++ b/src/com/android/settings/ext/AppPrefUtils.java
@@ -0,0 +1,14 @@
+package com.android.settings.ext;
+
+import android.content.Context;
+
+import com.android.settings.R;
+
+import androidx.annotation.StringRes;
+
+public class AppPrefUtils {
+
+ public static String getFooterForDefaultHardeningSetting(Context ctx, @StringRes int baseText) {
+ return ctx.getString(R.string.app_exploit_protection_default_value_warning) + "\n\n" + ctx.getString(baseText);
+ }
+}
From d84628825243ad88df70b579113339d55e94e37f Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Wed, 15 Nov 2023 13:44:08 +0200
Subject: [PATCH 054/162] add base class for App info single-choice fragments
---
.../appinfo/RadioButtonAppInfoFragment.java | 228 ++++++++++++++++++
1 file changed, 228 insertions(+)
create mode 100644 src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java
diff --git a/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java b/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java
new file mode 100644
index 00000000000..26fa78beb4d
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java
@@ -0,0 +1,228 @@
+package com.android.settings.applications.appinfo;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.TypedValue;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreferenceCompat;
+
+import com.android.settings.applications.AppInfoWithHeader;
+import com.android.settings.applications.SpacePreference;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.Collections;
+import java.util.List;
+
+public abstract class RadioButtonAppInfoFragment extends AppInfoWithHeader implements SelectorWithWidgetPreference.OnClickListener {
+
+ public static class Entry {
+ public final int id;
+ public CharSequence title;
+ @Nullable
+ public CharSequence summary;
+ public boolean isChecked;
+ public boolean isEnabled;
+
+ public Entry(int id, CharSequence title, @Nullable CharSequence summary, boolean isChecked, boolean isEnabled) {
+ this.id = id;
+ this.title = title;
+ this.summary = summary;
+ this.isChecked = isChecked;
+ this.isEnabled = isEnabled;
+ }
+ }
+
+ public static Entry createEntry(int id, CharSequence title) {
+ return new Entry(id, title, null, false, true);
+ }
+
+ public Entry createEntry(int id, @StringRes int title) {
+ return createEntry(id, getText(title));
+ }
+
+ public Entry createEntry(@StringRes int title) {
+ return createEntry(title, title);
+ }
+
+ public abstract Entry[] getEntries();
+
+ public boolean hasFooter() {
+ return true;
+ }
+
+ public abstract void updateFooter(FooterPreference fp);
+
+ public void setLearnMoreLink(FooterPreference p, String url) {
+ p.setLearnMoreAction(v -> {
+ var i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ startActivity(i);
+ });
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getPrefContext());
+ setPreferenceScreen(screen);
+ requireActivity().setTitle(getTitle());
+ }
+
+ protected abstract CharSequence getTitle();
+
+ @Nullable
+ private SelectorWithWidgetPreference[] radioButtons;
+ @Nullable
+ private FooterPreference footer;
+
+ private Preference[] extraPrefs;
+
+ @Override
+ protected boolean refreshUi() {
+ Entry[] entries = getEntries();
+ int entryCnt = entries.length;
+
+ Context ctx = getPrefContext();
+ PreferenceScreen screen = getPreferenceScreen();
+
+ if (radioButtons == null || radioButtons.length != entryCnt) {
+ if (radioButtons != null) {
+ for (Preference p : radioButtons) {
+ screen.removePreference(p);
+ }
+ }
+
+ radioButtons = new SelectorWithWidgetPreference[entryCnt];
+
+ for (int i = 0; i < entryCnt; ++i) {
+ var p = new SelectorWithWidgetPreference(ctx);
+ p.setOnClickListener(this);
+ screen.addPreference(p);
+ radioButtons[i] = p;
+ }
+ }
+
+ for (int i = 0; i < entryCnt; ++i) {
+ SelectorWithWidgetPreference p = radioButtons[i];
+ Entry e = entries[i];
+ p.setKey(Integer.toString(e.id));
+ p.setTitle(e.title);
+ p.setSummary(e.summary);
+ p.setEnabled(e.isEnabled);
+ p.setChecked(e.isChecked);
+ }
+
+ List extraPrefModels = getExtraPrefModels();
+
+ if (extraPrefs == null) {
+ if (extraPrefModels.isEmpty()) {
+ extraPrefs = new Preference[0];
+ } else {
+ var spacer = new SpacePreference(ctx, null);
+ int h = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 48f, ctx.getResources().getDisplayMetrics());
+ spacer.setHeight(h);
+ screen.addPreference(spacer);
+
+ extraPrefs = new Preference[extraPrefModels.size()];
+ for (int i = 0; i < extraPrefs.length; ++i) {
+ PrefModel pm = extraPrefModels.get(i);
+ Preference p;
+ if (pm instanceof LinkPrefModel lpm) {
+ p = new Preference(ctx);
+ p.setOnPreferenceClickListener(pref -> {
+ lpm.onClick.run();
+ return true;
+ });
+ } else if (pm instanceof TogglePrefModel tpm) {
+ p = new SwitchPreferenceCompat(ctx);
+ p.setOnPreferenceChangeListener(tpm.onChangeListener);
+ } else {
+ throw new IllegalArgumentException(pm.toString());
+ }
+ p.setKey("extra_pref_" + i);
+ screen.addPreference(p);
+ extraPrefs[i] = p;
+ }
+ }
+ }
+ for (int i = 0; i < extraPrefs.length; ++i) {
+ PrefModel pm = extraPrefModels.get(i);
+ Preference p = extraPrefs[i];
+ if (pm instanceof TogglePrefModel tpm) {
+ var sp = (SwitchPreferenceCompat) p;
+ sp.setChecked(tpm.isChecked);
+ }
+ p.setTitle(pm.title);
+ p.setSummary(pm.summary);
+ p.setEnabled(pm.isEnabled);
+ }
+
+ if (hasFooter()) {
+ if (footer == null) {
+ footer = new FooterPreference(ctx);
+ screen.addPreference(footer);
+ }
+ updateFooter(footer);
+ } else {
+ if (footer != null) {
+ screen.removePreference(footer);
+ footer = null;
+ }
+ }
+
+ return true;
+ }
+
+ public static class PrefModel {
+ public CharSequence title;
+ public CharSequence summary;
+ public boolean isEnabled = true;
+ }
+
+ public static class LinkPrefModel extends PrefModel {
+ public Runnable onClick;
+ }
+
+ public static class TogglePrefModel extends PrefModel {
+ public boolean isChecked;
+ public Preference.OnPreferenceChangeListener onChangeListener;
+ }
+
+ protected List getExtraPrefModels() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public final void onRadioButtonClicked(SelectorWithWidgetPreference emiter) {
+ int id = Integer.parseInt(emiter.getKey());
+ onEntrySelected(id);
+ if (!refreshUi()) {
+ setIntentAndFinish(true);
+ }
+ }
+
+ public abstract void onEntrySelected(int id);
+
+ @Override
+ protected AlertDialog createDialog(int id, int errorCode) {
+ return null;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return METRICS_CATEGORY_UNKNOWN;
+ }
+
+ protected ApplicationInfo getAppInfo() {
+ return mPackageInfo.applicationInfo;
+ }
+}
From 52593632ba95c5b73642b46d41140f464ad05fec Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Wed, 15 Nov 2023 13:44:23 +0200
Subject: [PATCH 055/162] infrastructure for AppSwitch UIs
Squashed with 28baa8dcbf5a0d285d8bf3852b723beaa290a973 by quh4gko8 <88831734+quh4gko8@users.noreply.github.com>
---
res/values/strings_app_exploit_protection.xml | 37 +++
.../settings/applications/AswAdapter.kt | 88 +++++++
.../applications/AswAppInfoFragment.java | 228 ++++++++++++++++++
.../AswAppListPrefController.java | 27 +++
.../AswExploitProtectionFragment.java | 44 ++++
.../spa/app/appinfo/AppInfoSettings.kt | 3 +
.../settings/spa/app/appinfo/AswAppList.kt | 101 ++++++++
.../settings/spa/app/appinfo/AswPreference.kt | 27 +++
.../spa/app/appinfo/PackageInfoPresenter.kt | 5 +-
9 files changed, 559 insertions(+), 1 deletion(-)
create mode 100644 res/values/strings_app_exploit_protection.xml
create mode 100644 src/com/android/settings/applications/AswAdapter.kt
create mode 100644 src/com/android/settings/applications/AswAppInfoFragment.java
create mode 100644 src/com/android/settings/applications/AswAppListPrefController.java
create mode 100644 src/com/android/settings/applications/AswExploitProtectionFragment.java
create mode 100644 src/com/android/settings/spa/app/appinfo/AswAppList.kt
create mode 100644 src/com/android/settings/spa/app/appinfo/AswPreference.kt
diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml
new file mode 100644
index 00000000000..5081ee0a037
--- /dev/null
+++ b/res/values/strings_app_exploit_protection.xml
@@ -0,0 +1,37 @@
+
+
+ Exploit protection
+
+ Allowed
+ Blocked
+ Default (%1$s)
+ Disabled
+ Enabled
+ Restricted
+
+ Warning
+ This setting will weaken exploit protections for the selected app.
+ Proceed
+
+ Default value can be changed in the %1$s section
+
+ The selected app is known to be compatible with this setting
+ %1$s by default, because this app is known to need it.
+This behavior can be disabled in the %2$s section.
+
+ %1$s by default because this app depends on Play services
+
+ Block for third-party apps by default
+ Restrict for third-party apps by default
+ Disable for third-party apps by default
+ Restricted by default
+ Restricted by default, except for apps that depend on Play services
+ Disabled by default
+ Blocked by default
+ Allowed for third-party apps by default
+ Enabled for third-party apps by default
+
+ %1$s is enabled
+
+ Exploit protection compatibility mode
+
diff --git a/src/com/android/settings/applications/AswAdapter.kt b/src/com/android/settings/applications/AswAdapter.kt
new file mode 100644
index 00000000000..478dd02e25e
--- /dev/null
+++ b/src/com/android/settings/applications/AswAdapter.kt
@@ -0,0 +1,88 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.ext.settings.app.AppSwitch
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.SettingsPreferenceFragment
+import com.android.settings.applications.appinfo.AppInfoDashboardFragment
+import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
+import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
+import com.android.settings.spa.app.appinfo.AswAppListPageProvider
+import com.android.settingslib.spaprivileged.model.app.userId
+import kotlin.reflect.KClass
+
+abstract class AswAdapter {
+ abstract fun getAppSwitch(): T
+
+ enum class Category {
+ ExploitProtection,
+ }
+
+ fun getCategory(): Category = Category.ExploitProtection
+
+ fun getPreferenceSummary(ctx: Context, appInfo: ApplicationInfo): CharSequence {
+ val asw = getAppSwitch()
+ val si = AppSwitch.StateInfo()
+ val userId = appInfo.userId
+ val isOn = asw.get(ctx, userId, appInfo, GosPackageState.get(appInfo.packageName, userId), si)
+ return if (si.isUsingDefaultValue) {
+ getDefaultTitle(ctx, isOn)
+ } else {
+ if (isOn) getOnTitle(ctx) else getOffTitle(ctx)
+ }
+ }
+
+ open fun getNotificationToggleTitle(ctx: Context): CharSequence? = null
+ open fun getNotificationToggleSummary(ctx: Context): CharSequence? = null
+
+ abstract fun getAswTitle(ctx: Context): CharSequence
+
+ open fun getShortAswTitle(ctx: Context) = getAswTitle(ctx)
+
+ fun getDefaultTitle(ctx: Context, isOn: Boolean): CharSequence {
+ return ctx.getString(R.string.aep_default,
+ if (isOn) getOnTitle(ctx) else getOffTitle(ctx)
+ )
+ }
+
+ open fun getOnTitle(ctx: Context): CharSequence = ctx.getText(R.string.aep_enabled)
+
+ open fun getOffTitle(ctx: Context): CharSequence = ctx.getText(R.string.aep_disabled)
+
+ abstract fun getDetailFragmentClass(): KClass
+
+ fun openAppPage(context: Context, app: ApplicationInfo) {
+ AppInfoDashboardFragment.startAppInfoFragment(
+ getDetailFragmentClass().java,
+ app, context, AppInfoSettingsProvider.METRICS_CATEGORY,
+ )
+ }
+
+ fun makeAppListPageProvider() = AswAppListPageProvider(this)
+
+ fun getAppListPageProviderName() = this::class.simpleName!!
+
+ open fun shouldIncludeInAppListPage(app: ApplicationInfo, gosPs: GosPackageState) = true
+
+ fun openAppListPage(ctx: Context) {
+ ctx.startSpaActivity(getAppListPageProviderName())
+ }
+
+ @JvmOverloads
+ fun addAppListPageLink(screen: PreferenceScreen,
+ title: CharSequence = screen.context.getText(R.string.default_see_all_apps_title)) {
+ val ctx = screen.context
+ val pref = Preference(ctx).apply {
+ this.title = title
+ setOnPreferenceClickListener { p ->
+ p.context.startSpaActivity(getAppListPageProviderName())
+ true
+ }
+ }
+ screen.addPreference(pref)
+ }
+}
diff --git a/src/com/android/settings/applications/AswAppInfoFragment.java b/src/com/android/settings/applications/AswAppInfoFragment.java
new file mode 100644
index 00000000000..cac5229f781
--- /dev/null
+++ b/src/com/android/settings/applications/AswAppInfoFragment.java
@@ -0,0 +1,228 @@
+package com.android.settings.applications;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.GosPackageState;
+import android.ext.settings.app.AppSwitch;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+import com.android.settings.R;
+import com.android.settings.applications.appinfo.RadioButtonAppInfoFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AswAppInfoFragment
+ extends RadioButtonAppInfoFragment {
+
+ protected static final int ID_DEFAULT = 0;
+ protected static final int ID_ON = 1;
+ protected static final int ID_OFF = 2;
+
+ public abstract AswAdapter getAswAdapter();
+
+ protected AswAdapter adapter;
+ private final ArrayList extraPrefs = new ArrayList<>();
+ @Nullable
+ private TogglePrefModel notifTogglePref;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ adapter = getAswAdapter();
+ super.onCreate(savedInstanceState);
+
+ if (adapter.getAppSwitch().hasNotification()) {
+ Context ctx = requireContext();
+ var p = new TogglePrefModel();
+ p.title = adapter.getNotificationToggleTitle(ctx);
+ p.summary = adapter.getNotificationToggleSummary(ctx);
+ p.onChangeListener = (pref, state) -> {
+ var ed = GosPackageState.edit(mPackageName, mUserId);
+ adapter.getAppSwitch().setNotificationEnabled(ed, (boolean) state);
+ return ed.apply();
+ };
+ extraPrefs.add(p);
+ notifTogglePref = p;
+ }
+ {
+ var p = new LinkPrefModel();
+ p.title = getText(R.string.default_see_all_apps_title);
+ p.onClick = () -> adapter.openAppListPage(requireContext());
+ extraPrefs.add(p);
+ }
+ }
+
+ @Override
+ protected CharSequence getTitle() {
+ return adapter.getAswTitle(requireContext());
+ }
+
+ @Override
+ public Entry[] getEntries() {
+ Context ctx = requireContext();
+ AppSwitch asw = adapter.getAppSwitch();
+
+ int userId = mUserId;
+ GosPackageState ps = GosPackageState.get(mPackageName, userId);
+ ApplicationInfo appInfo = getAppInfo();
+ var si = new AppSwitch.StateInfo();
+ boolean state = asw.get(ctx, userId, appInfo, ps, si);
+
+ boolean isDefault = si.isUsingDefaultValue();
+ boolean isImmutable = si.isImmutable();
+
+ var defaultSi = new AppSwitch.StateInfo();
+ boolean defaultValue = asw.getDefaultValue(ctx, userId, appInfo, ps, defaultSi);
+
+ var def = createEntry(ID_DEFAULT, adapter.getDefaultTitle(ctx, defaultValue));
+ def.isChecked = isDefault;
+ def.isEnabled = !isImmutable;
+ if (def.isEnabled) {
+ int dvr = defaultSi.getDefaultValueReason();
+ CharSequence summary = getSummaryForDefaultValueReason(dvr);
+ if (summary == null) {
+ summary = switch (dvr) {
+ case AppSwitch.DVR_DEFAULT_SETTING -> {
+ if (!ctx.getUser().isSystem()) {
+ yield null;
+ }
+ yield getString(R.string.aep_dvr_default_security_setting,
+ getAppDefaultSettingPathForCategory(adapter.getCategory()));
+ }
+ case AppSwitch.DVR_APP_COMPAT_CONFIG_HARDENING_OPT_IN ->
+ getText(R.string.aep_dvr_compat_config_hardening_opt_in);
+ case AppSwitch.DVR_APP_COMPAT_CONFIG_HARDENING_OPT_OUT -> {
+ if (!ctx.getUser().isSystem()) {
+ yield null;
+ }
+ var s = defaultValue ? adapter.getOnTitle(ctx) : adapter.getOffTitle(ctx);
+ yield getString(R.string.aep_dvr_compat_config_hardening_opt_out,
+ s.toString(), getSettingPath(R.string.safety_center_title,
+ R.string.more_security_privacy_settings));
+ }
+ case AppSwitch.DVR_APP_IS_CLIENT_OF_GMSCORE -> {
+ var s = defaultValue ? adapter.getOnTitle(ctx) : adapter.getOffTitle(ctx);
+ yield getString(R.string.aep_dvr_app_is_client_of_gmscore, s.toString());
+ }
+ default -> null;
+ };
+ }
+ def.summary = summary;
+ }
+
+ var enabled = createEntry(ID_ON, adapter.getOnTitle(ctx));
+ enabled.isChecked = !isDefault && state;
+ enabled.isEnabled = enabled.isChecked || !isImmutable;
+
+ var disabled = createEntry(ID_OFF, adapter.getOffTitle(ctx));
+ disabled.isChecked = !isDefault && !state;
+ disabled.isEnabled = disabled.isChecked || !isImmutable;
+
+ if (isImmutable) {
+ int immutabilityReason = si.getImmutabilityReason();
+ CharSequence summary = getSummaryForImmutabilityReason(immutabilityReason);
+ if (summary == null) {
+ if (immutabilityReason == AppSwitch.IR_EXPLOIT_PROTECTION_COMPAT_MODE) {
+ summary = getString(R.string.aep_ir_exploit_protection_compat_mode,
+ getString(R.string.aep_compat_mode_title));
+ }
+ }
+ if (enabled.isChecked) {
+ enabled.summary = summary;
+ }
+ if (disabled.isChecked) {
+ disabled.summary = summary;
+ }
+ }
+
+ if (notifTogglePref != null) {
+ notifTogglePref.isChecked = adapter.getAppSwitch().isNotificationEnabled(ps);
+ notifTogglePref.isEnabled = state;
+ }
+
+ return new Entry[] { def, enabled, disabled };
+ }
+
+ private String getAppDefaultSettingPathForCategory(AswAdapter.Category category) {
+ switch (category) {
+ case ExploitProtection:
+ return getSettingPath(R.string.safety_center_title, R.string.exploit_protection_settings);
+ default:
+ throw new IllegalArgumentException(category.toString());
+ }
+ }
+
+ private String getSettingPath(int... parts) {
+ var sb = new StringBuilder();
+ for (int i = 0; i < parts.length; ++i) {
+ if (i != 0) {
+ sb.append(" > ");
+ }
+ sb.append(getString(parts[i]));
+ }
+ return sb.toString();
+ }
+
+ @Nullable
+ protected CharSequence getSummaryForDefaultValueReason(int dvr) {
+ return null;
+ }
+
+ @Nullable
+ protected CharSequence getSummaryForImmutabilityReason(int ir) {
+ return null;
+ }
+
+ @Override
+ protected List getExtraPrefModels() {
+ return extraPrefs;
+ }
+
+ @Override
+ public final void onEntrySelected(int id) {
+ Context ctx = requireContext();
+ AppSwitch asw = adapter.getAppSwitch();
+ int userId = mUserId;
+ String pkgName = mPackageName;
+ GosPackageState ps = GosPackageState.get(pkgName, userId);
+ ApplicationInfo appInfo = getAppInfo();
+
+ boolean isImmutable = asw.isImmutable(ctx, userId, appInfo, ps);
+
+ if (isImmutable) {
+ return;
+ }
+
+ Runnable r = () -> {
+ GosPackageState.Editor ed = GosPackageState.edit(pkgName, userId);
+
+ switch (id) {
+ case ID_DEFAULT -> asw.setUseDefaultValue(ed);
+ case ID_ON, ID_OFF -> asw.set(ed, id == ID_ON);
+ default -> throw new IllegalStateException();
+ }
+
+ ed.setKillUidAfterApply(shouldKillUidAfterChange());
+
+ if (!ed.apply()) {
+ finish();
+ }
+
+ if (!refreshUi()) {
+ setIntentAndFinish(true);
+ }
+ };
+
+ completeStateChange(id, asw.get(ctx, userId, appInfo, ps), r);
+ }
+
+ protected void completeStateChange(int newEntryId, boolean curValue, Runnable stateChangeAction) {
+ stateChangeAction.run();
+ }
+
+ protected boolean shouldKillUidAfterChange() {
+ return true;
+ }
+}
diff --git a/src/com/android/settings/applications/AswAppListPrefController.java b/src/com/android/settings/applications/AswAppListPrefController.java
new file mode 100644
index 00000000000..c6d9fa7260a
--- /dev/null
+++ b/src/com/android/settings/applications/AswAppListPrefController.java
@@ -0,0 +1,27 @@
+package com.android.settings.applications;
+
+import android.content.Context;
+
+import androidx.preference.Preference;
+
+import com.android.settings.applications.AswAdapter;
+import com.android.settings.core.BasePreferenceController;
+
+public abstract class AswAppListPrefController extends BasePreferenceController {
+
+ protected final AswAdapter aswAdapter;
+
+ public AswAppListPrefController(Context context, String preferenceKey, AswAdapter adapter) {
+ super(context, preferenceKey);
+ aswAdapter = adapter;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!getPreferenceKey().equals(preference.getKey())) {
+ return false;
+ }
+ aswAdapter.openAppListPage(preference.getContext());
+ return true;
+ }
+}
diff --git a/src/com/android/settings/applications/AswExploitProtectionFragment.java b/src/com/android/settings/applications/AswExploitProtectionFragment.java
new file mode 100644
index 00000000000..19d0a470433
--- /dev/null
+++ b/src/com/android/settings/applications/AswExploitProtectionFragment.java
@@ -0,0 +1,44 @@
+package com.android.settings.applications;
+
+import android.content.Context;
+import android.content.pm.GosPackageState;
+import android.ext.settings.app.AppSwitch;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+
+public abstract class AswExploitProtectionFragment extends AswAppInfoFragment {
+
+ @Override
+ protected void completeStateChange(int newEntryId, boolean curValue, Runnable stateChangeAction) {
+ Context ctx = requireContext();
+
+ boolean showWarning = false;
+ if (curValue) {
+ if (newEntryId == ID_OFF) {
+ showWarning = true;
+ } else if (newEntryId == ID_DEFAULT) {
+ AppSwitch asw = adapter.getAppSwitch();
+ int userId = mUserId;
+ var ps = GosPackageState.get(mPackageName, userId);
+ showWarning = !asw.getDefaultValue(ctx, userId, getAppInfo(), ps);
+ }
+ }
+ if (showWarning) {
+ var d = getExploitProtectionWarningOnDisable(ctx, stateChangeAction);
+ d.show();
+ } else {
+ stateChangeAction.run();
+ }
+ }
+
+ public static AlertDialog.Builder getExploitProtectionWarningOnDisable(Context ctx, Runnable action) {
+ var b = new AlertDialog.Builder(ctx);
+ b.setTitle(R.string.aep_confirm_disable_title);
+ b.setMessage(R.string.aep_confirm_disable_warning_msg);
+ b.setNegativeButton(R.string.cancel, null);
+ b.setPositiveButton(R.string.aep_confirm_disable_proceed_btn, (d, w) -> action.run());
+ return b;
+ }
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 391a21273d8..3dbf7caf66e 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -46,6 +46,7 @@ import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
import com.android.settings.spa.app.specialaccess.UsageDataAppListProvider
import com.android.settings.spa.app.specialaccess.WriteSystemPreferencesAppListProvider
import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.LifecycleEffect
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category
@@ -121,6 +122,8 @@ object AppInfoSettingsProvider : SettingsPageProvider {
@Composable
private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
+ // needed to refresh AppSwitch items after returning from their fragments
+ LifecycleEffect(onStart = { check(packageInfoPresenter.manualRefreshFlow.tryEmit(Any())) })
val packageInfoState = packageInfoPresenter.flow.collectAsStateWithLifecycle()
val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl()
RegularScaffold(
diff --git a/src/com/android/settings/spa/app/appinfo/AswAppList.kt b/src/com/android/settings/spa/app/appinfo/AswAppList.kt
new file mode 100644
index 00000000000..c08586a7002
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AswAppList.kt
@@ -0,0 +1,101 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import com.android.settings.applications.AswAdapter
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.rememberContext
+import com.android.settingslib.spa.framework.util.asyncFilter
+import com.android.settingslib.spa.framework.util.asyncMap
+import com.android.settingslib.spa.widget.ui.SpinnerOption
+import com.android.settingslib.spaprivileged.model.app.AppListModel
+import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.template.app.AppListItem
+import com.android.settingslib.spaprivileged.template.app.AppListItemModel
+import com.android.settingslib.spaprivileged.template.app.AppListPage
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+
+open class AswAppListPageProvider(val adapter: AswAdapter<*>) : SettingsPageProvider {
+ override val name = adapter.getAppListPageProviderName()
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ AswAppListPage(adapter)
+ }
+}
+
+@Composable
+fun AswAppListPage(adapter: AswAdapter<*>) {
+ AppListPage(
+ title = rememberContext { ctx ->
+ adapter.getShortAswTitle(ctx).toString()
+ },
+ listModel = rememberContext { ctx ->
+ AswAppListModel(ctx, adapter)
+ },
+ )
+}
+
+class AppRecordImpl(override val app: ApplicationInfo, val gosPackageState: GosPackageState) : AppRecord
+
+class AswAppListModel(val ctx: Context, val adapter: AswAdapter<*>) : AppListModel {
+ companion object {
+ const val SPINNER_OPTION_OFF = 0
+ const val SPINNER_OPTION_ON = 1
+ }
+
+ override fun getSpinnerOptions(recordList: List): List {
+ val options = ArrayList(2)
+ options.add(SpinnerOption(SPINNER_OPTION_OFF, adapter.getOffTitle(ctx).toString()))
+ options.add(SpinnerOption(SPINNER_OPTION_ON, adapter.getOnTitle(ctx).toString()))
+ return options
+ }
+
+ override fun transform(
+ userIdFlow: Flow,
+ appListFlow: Flow>
+ ): Flow> {
+ return userIdFlow.combine(appListFlow) { userId, appList ->
+ appList.asyncMap { app ->
+ val gosPs = GosPackageState.get(app.packageName, userId)
+ if (adapter.shouldIncludeInAppListPage(app, gosPs)) {
+ AppRecordImpl(app, GosPackageState.get(app.packageName, userId))
+ } else {
+ null
+ }
+ }.filterNotNull()
+ }
+ }
+
+ override fun filter(
+ userIdFlow: Flow,
+ option: Int,
+ recordListFlow: Flow>
+ ): Flow> {
+ val appSwitch = adapter.getAppSwitch()
+ return userIdFlow.combine(recordListFlow) { userId, recordList ->
+ recordList.asyncFilter {
+ val value = appSwitch.get(ctx, userId, it.app, it.gosPackageState)
+ when (option) {
+ SPINNER_OPTION_OFF -> !value
+ SPINNER_OPTION_ON -> value
+ else -> throw IllegalArgumentException(option.toString())
+ }
+ }
+ }
+ }
+
+ @Composable
+ override fun AppListItemModel.AppItem() {
+ val context = LocalContext.current
+ AppListItem(onClick = {
+ adapter.openAppPage(context, record.app)
+ })
+ }
+}
+
diff --git a/src/com/android/settings/spa/app/appinfo/AswPreference.kt b/src/com/android/settings/spa/app/appinfo/AswPreference.kt
new file mode 100644
index 00000000000..116fa047025
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AswPreference.kt
@@ -0,0 +1,27 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.app.AppSwitch
+import androidx.compose.runtime.Composable
+import com.android.settings.applications.AswAdapter
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.installed
+
+@Composable
+fun AswPreference(context: Context, app: ApplicationInfo, adapter: AswAdapter) {
+ if (!app.installed) {
+ return
+ }
+
+ Preference(object : PreferenceModel {
+ override val title = adapter.getAswTitle(context).toString()
+ override val summary = {
+ adapter.getPreferenceSummary(context, app).toString()
+ }
+ override val onClick = {
+ adapter.openAppPage(context, app)
+ }
+ })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
index 8785fe821af..a08e6b6e740 100644
--- a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
+++ b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
@@ -44,6 +44,7 @@ import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.model.app.PackageManagers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filter
@@ -96,7 +97,9 @@ class PackageInfoPresenter(
intent.action != Intent.ACTION_PACKAGE_REMOVED ||
intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false)
- val flow: StateFlow = merge(flowOf(null), appChangeFlow)
+ val manualRefreshFlow = MutableStateFlow(null)
+
+ val flow: StateFlow = merge(flowOf(null), appChangeFlow, manualRefreshFlow)
.map { getPackageInfo() }
.stateIn(coroutineScope + Dispatchers.Default, SharingStarted.Eagerly, null)
From f9c66473fdf5498111caa4d2528d3dcd0c6e1e23 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 2 Mar 2024 12:09:48 +0200
Subject: [PATCH 056/162] add "Exploit protection" category to App info
---
src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 3dbf7caf66e..6ccdeabfc77 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -181,6 +181,9 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
UsageDataAppListProvider.InfoPageEntryItem(app)
}
+ Category(title = stringResource(R.string.exploit_protection_category_title)) {
+ }
+
Category(title = stringResource(R.string.app_install_details_group_title)) {
AppInstallerInfoPreference(app)
}
From 0bc856dd4dd56e1e688e143c4bb6cdcae70e4c87 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Tue, 26 Sep 2023 10:34:50 +0300
Subject: [PATCH 057/162] add per-app setting for exploit protection
compatibility mode
---
res/values/strings_app_exploit_protection.xml | 1 +
...oitProtectionCompatModeSwitchPreference.kt | 59 +++++++++++++++++++
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
3 files changed, 61 insertions(+)
create mode 100644 src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt
diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml
index 5081ee0a037..ed4eef3ab79 100644
--- a/res/values/strings_app_exploit_protection.xml
+++ b/res/values/strings_app_exploit_protection.xml
@@ -34,4 +34,5 @@ This behavior can be disabled in the %2$s section.
%1$s is enabled
Exploit protection compatibility mode
+ Improves compatibility by disabling some of the GrapheneOS exploit protections for this app
diff --git a/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt b/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt
new file mode 100644
index 00000000000..daf3ace3dba
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt
@@ -0,0 +1,59 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.content.pm.GosPackageStateFlag
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settings.applications.AswExploitProtectionFragment
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import com.android.settingslib.spaprivileged.model.app.installed
+import com.android.settingslib.spaprivileged.model.app.userId
+
+@Composable
+fun AppExploitProtectionCompatModeSwitchPreference(app: ApplicationInfo,
+ packageInfoPresenter: PackageInfoPresenter) {
+ if (app.isSystemApp || !app.installed) {
+ return
+ }
+
+ val context = LocalContext.current
+ val pkgName = app.packageName
+ val userId = app.userId
+ val psFlag = GosPackageStateFlag.ENABLE_EXPLOIT_PROTECTION_COMPAT_MODE
+
+ SwitchPreference(object : SwitchPreferenceModel {
+ override val title = stringResource(R.string.aep_compat_mode_title)
+ override val summary = {
+ context.getString(R.string.aep_compat_mode_summary)
+ }
+
+ override val checked = {
+ GosPackageState.get(pkgName, userId).hasFlag(psFlag)
+ }
+
+ override val onCheckedChange = { newChecked: Boolean ->
+ val action = Runnable {
+ GosPackageState.edit(pkgName, userId).run {
+ setFlagState(psFlag, newChecked)
+ killUidAfterApply()
+ if (apply()) {
+ // needed to recompose other exploit protection settings
+ check(packageInfoPresenter.manualRefreshFlow.tryEmit(Any()))
+ }
+ }
+ }
+
+ if (newChecked) {
+ val d = AswExploitProtectionFragment.getExploitProtectionWarningOnDisable(context, action)
+ d.show()
+ } else {
+ action.run()
+ }
+ Unit
+ }
+ })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 6ccdeabfc77..0d6ce0a7dd6 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -182,6 +182,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
}
Category(title = stringResource(R.string.exploit_protection_category_title)) {
+ AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter)
}
Category(title = stringResource(R.string.app_install_details_group_title)) {
From a75ecbd1942992e9d43dcd7d277a22a24bd1ba8a Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 7 Oct 2023 21:28:08 +0300
Subject: [PATCH 058/162] add toggle for automatic exploit protection
compatibility mode
---
res/values/strings_ext.xml | 6 ++++++
res/xml/more_security_privacy_settings.xml | 7 +++++++
2 files changed, 13 insertions(+)
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index e2ef48368dd..219e9dfd244 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -124,6 +124,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.
Allow access to Android/obb folder
diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml
index adf0d09c604..025f1c20755 100644
--- a/res/xml/more_security_privacy_settings.xml
+++ b/res/xml/more_security_privacy_settings.xml
@@ -235,6 +235,13 @@
settings:keywords="@string/keywords_app_pinning"
settings:controller="com.android.settings.security.ScreenPinningPreferenceController" />
+
+
Date: Thu, 16 Nov 2023 17:23:47 +0200
Subject: [PATCH 059/162] add per-app setting for hardened_malloc
---
AndroidManifest.xml | 18 +++++++
res/values/strings_app_exploit_protection.xml | 8 +++
res/xml/exploit_protection_settings.xml | 5 ++
src/com/android/settings/Settings.java | 2 +
.../applications/AppHardenedMalloc.kt | 54 +++++++++++++++++++
.../core/gateway/SettingsGateway.java | 1 +
.../settings/spa/SettingsSpaEnvironment.kt | 1 +
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
8 files changed, 90 insertions(+)
create mode 100644 src/com/android/settings/applications/AppHardenedMalloc.kt
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 49d0b5905bc..811db2d6a54 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -6040,5 +6040,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml
index ed4eef3ab79..8581d72090b 100644
--- a/res/values/strings_app_exploit_protection.xml
+++ b/res/values/strings_app_exploit_protection.xml
@@ -35,4 +35,12 @@ This behavior can be disabled in the %2$s section.
Exploit protection compatibility mode
Improves compatibility by disabling some of the GrapheneOS exploit protections for this app
+
+ Hardened memory allocator
+
+ Hardened memory allocator (hardened_malloc) provides substantial defenses against the most common classes of vulnerabilities (heap memory corruption) along with reducing the lifetime of sensitive data in memory.
+ This app doesn’t have native code
+ This is a 32-bit app, hardened_malloc is 64-bit only
+ hardened_malloc is not allowed to be disabled for a preinstalled app
+ This is a debuggable app, hardened_malloc can’t be disabled
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index ada50481305..34d6ccf6cb4 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -24,6 +24,11 @@
android:key="app_exploit_protection_settings"
android:title="@string/app_exploit_protection_category">
+
+
() {
+
+ override fun getAppSwitch() = AswUseHardenedMalloc.I
+
+ override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_hmalloc)
+
+ override fun getDetailFragmentClass() = AppHardenedMallocFragment::class
+}
+
+@Composable
+fun AppHardenedMallocPreference(app: ApplicationInfo) {
+ val context = LocalContext.current
+ AswPreference(context, app, AswAdapterUseHardenedMalloc)
+}
+
+class AppHardenedMallocFragment : AswExploitProtectionFragment() {
+
+ override fun getAswAdapter() = AswAdapterUseHardenedMalloc
+
+ override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+ val id = when (ir) {
+ AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_hmalloc_ir_preinstalled_app
+ AppSwitch.IR_NO_NATIVE_CODE -> R.string.aep_hmalloc_ir_no_native_code
+ AppSwitch.IR_NON_64_BIT_NATIVE_CODE -> R.string.aep_hmalloc_ir_32_bit_native_code
+ AppSwitch.IR_IS_DEBUGGABLE_APP -> R.string.aep_hmalloc_ir_debuggable_app
+ else -> return null
+ }
+ return getText(id)
+ }
+
+ override fun updateFooter(fp: FooterPreference) {
+ fp.setTitle(R.string.aep_hmalloc_footer)
+ setLearnMoreLink(fp, "https://grapheneos.org/features#exploit-mitigations")
+ }
+}
+
+
+class HardenedMallocAppListPrefController(context: Context, preferenceKey: String) :
+ AswAppListPrefController(context, preferenceKey, AswAdapterUseHardenedMalloc) {
+
+ override fun getAvailabilityStatus() = AVAILABLE
+}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 2d3f63e9a5e..fc5421a9ef7 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -229,6 +229,7 @@ public class SettingsGateway {
* security exception if the fragment it needs to display is not in this list.
*/
public static final String[] ENTRY_FRAGMENTS = {
+ com.android.settings.applications.AppHardenedMallocFragment.class.getName(),
com.android.settings.safetycenter.ExploitProtectionFragment.class.getName(),
AdvancedConnectedDeviceDashboardFragment.class.getName(),
CreateShortcut.class.getName(),
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index ce95004f34d..2c85f69e8ce 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -101,6 +101,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
listOf(
HomePageProvider,
AppsMainPageProvider,
+ com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(),
AllAppListPageProvider,
AppInfoSettingsProvider,
SpecialAppAccessPageProvider,
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 0d6ce0a7dd6..fbbf7d39300 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -183,6 +183,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
Category(title = stringResource(R.string.exploit_protection_category_title)) {
AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter)
+ com.android.settings.applications.AppHardenedMallocPreference(app)
}
Category(title = stringResource(R.string.app_install_details_group_title)) {
From bfa68f17fdcf52358f65256531c5a80c995ac066 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Fri, 30 Aug 2024 16:23:56 +0300
Subject: [PATCH 060/162] add dev mode per-app setting for extended virtual
address space
---
res/values/strings_app_exploit_protection.xml | 5 ++
res/xml/exploit_protection_settings.xml | 5 ++
.../applications/AppExtendedVaSpace.kt | 58 +++++++++++++++++++
.../settings/spa/SettingsSpaEnvironment.kt | 1 +
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
5 files changed, 70 insertions(+)
create mode 100644 src/com/android/settings/applications/AppExtendedVaSpace.kt
diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml
index 8581d72090b..d9d94fe5484 100644
--- a/res/values/strings_app_exploit_protection.xml
+++ b/res/values/strings_app_exploit_protection.xml
@@ -43,4 +43,9 @@ This behavior can be disabled in the %2$s section.
This is a 32-bit app, hardened_malloc is 64-bit only
hardened_malloc is not allowed to be disabled for a preinstalled app
This is a debuggable app, hardened_malloc can’t be disabled
+
+ Extended virtual address space
+ Extends virtual address space from 39 to 48 bits, which significantly improves the address space layout randomization.
+ Incompatible with 32-bit apps
+ Required by hardened_malloc
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index 34d6ccf6cb4..1068040a7a6 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -29,6 +29,11 @@
android:title="@string/aep_hmalloc"
settings:controller="com.android.settings.applications.HardenedMallocAppListPrefController" />
+
+
() {
+
+ override fun getAppSwitch() = AswUseExtendedVaSpace.I
+
+ override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_ext_va_space)
+
+ override fun getDetailFragmentClass() = AppExtendedVaSpaceFragment::class
+}
+
+@Composable
+fun AppExtendedVaSpacePreference(app: ApplicationInfo) {
+ val context = LocalContext.current
+ if (ExtSettingControllerHelper.getDevModeSettingAvailability(context) != BasePreferenceController.AVAILABLE) {
+ return
+ }
+
+ AswPreference(context, app, AswAdapterUseExtendedVaSpace)
+}
+
+class AppExtendedVaSpaceFragment : AswExploitProtectionFragment() {
+
+ override fun getAswAdapter() = AswAdapterUseExtendedVaSpace
+
+ override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+ val id = when (ir) {
+ AppSwitch.IR_REQUIRED_BY_HARDENED_MALLOC -> R.string.aep_ext_va_space_ir_hardened_malloc
+ AppSwitch.IR_NON_64_BIT_NATIVE_CODE -> R.string.aep_ext_va_space_ir_32_bit_native_code
+ else -> return null
+ }
+ return getText(id)
+ }
+
+ override fun updateFooter(fp: FooterPreference) {
+ fp.setTitle(R.string.aep_ext_va_space_footer)
+ }
+}
+
+
+class ExtendedVaSpaceAppListPrefController(context: Context, preferenceKey: String) :
+ AswAppListPrefController(context, preferenceKey, AswAdapterUseExtendedVaSpace) {
+
+ override fun getAvailabilityStatus() = ExtSettingControllerHelper
+ .getDevModeSettingAvailability(mContext)
+}
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index 2c85f69e8ce..7d3e08323c9 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -102,6 +102,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
HomePageProvider,
AppsMainPageProvider,
com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(),
+ com.android.settings.applications.AswAdapterUseExtendedVaSpace.makeAppListPageProvider(),
AllAppListPageProvider,
AppInfoSettingsProvider,
SpecialAppAccessPageProvider,
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index fbbf7d39300..1cf0ce258d1 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -184,6 +184,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
Category(title = stringResource(R.string.exploit_protection_category_title)) {
AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter)
com.android.settings.applications.AppHardenedMallocPreference(app)
+ com.android.settings.applications.AppExtendedVaSpacePreference(app)
}
Category(title = stringResource(R.string.app_install_details_group_title)) {
From 4fdf019774166d708c23436fac69180c9a17c3f1 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Wed, 15 Nov 2023 13:51:07 +0200
Subject: [PATCH 061/162] add per-app setting for native debugging
---
AndroidManifest.xml | 18 ++++
res/values/strings_app_exploit_protection.xml | 8 ++
res/xml/exploit_protection_settings.xml | 11 +++
src/com/android/settings/Settings.java | 2 +
.../applications/AppNativeDebugging.kt | 94 +++++++++++++++++++
.../core/gateway/SettingsGateway.java | 1 +
.../settings/spa/SettingsSpaEnvironment.kt | 1 +
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
8 files changed, 136 insertions(+)
create mode 100644 src/com/android/settings/applications/AppNativeDebugging.kt
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 811db2d6a54..369ce4b1002 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -6041,6 +6041,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Extends virtual address space from 39 to 48 bits, which significantly improves the address space layout randomization.
Incompatible with 32-bit apps
Required by hardened_malloc
+
+ Native code debugging
+ Show notifications about blocked access attempts
+
+Native code debugging (ptrace) slightly weakens the app sandbox. Some apps (most notably banking apps) use it as a tampering detection tool.
+
+ Native debugging is always blocked for preinstalled apps
+
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index 1068040a7a6..c56c38ef64c 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -34,6 +34,17 @@
android:title="@string/aep_ext_va_space"
settings:controller="com.android.settings.applications.ExtendedVaSpaceAppListPrefController" />
+
+
+
+
() {
+
+ override fun getAppSwitch() = AswDenyNativeDebug.I
+
+ override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_native_debug_title)
+
+ override fun getOnTitle(ctx: Context) = ctx.getText(R.string.aep_blocked)
+ override fun getOffTitle(ctx: Context) = ctx.getText(R.string.aep_allowed)
+
+ override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.aep_native_debug_notif_toggle_title)
+
+ override fun getDetailFragmentClass() = AppNativeDebuggingFragment::class
+}
+
+@Composable
+fun AppNativeDebuggingPreference(app: ApplicationInfo) {
+ val context = LocalContext.current
+ AswPreference(context, app, AswAdapterNativeDebugging)
+}
+
+class AppNativeDebuggingFragment : AswExploitProtectionFragment() {
+
+ override fun getAswAdapter() = AswAdapterNativeDebugging
+
+ override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+ val id = when (ir) {
+ AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_native_debug_dvr_is_system_app
+ else -> return null
+ }
+ return getText(id)
+ }
+
+ override fun updateFooter(fp: FooterPreference) {
+ fp.setTitle(R.string.aep_native_debug_footer)
+ }
+}
+
+class AppDefaultNativeDebuggingPrefController(ctx: Context, key: String) :
+ BoolSettingFragmentPrefController(ctx, key, ExtSettings.ALLOW_NATIVE_DEBUG_BY_DEFAULT) {
+
+ override fun getSummary(): CharSequence {
+ return resText(if (setting.get(mContext)) R.string.aep_default_summary_allowed_for_3p_apps else R.string.aep_default_summary_blocked)
+ }
+}
+
+class AppDefaultNativeDebuggingFragment : BoolSettingFragment() {
+
+ override fun getSetting(): BoolSetting {
+ invertSetting = true
+ return ExtSettings.ALLOW_NATIVE_DEBUG_BY_DEFAULT
+ }
+
+ override fun getTitle() = getText(R.string.aep_native_debug_title)
+
+ override fun getMainSwitchTitle() = getText(R.string.aep_default_main_switch_block_for_3p_apps)
+
+ override fun addExtraPrefs(screen: PreferenceScreen) {
+ AswAdapterNativeDebugging.addAppListPageLink(screen)
+ }
+
+ override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference {
+ val text = AppPrefUtils.getFooterForDefaultHardeningSetting(
+ requireContext(),
+ R.string.aep_native_debug_footer
+ )
+ return builder.setTitle(text).build()
+ }
+}
+
+class NativeDebuggingAppListPrefController(context: Context, preferenceKey: String) :
+ AswAppListPrefController(context, preferenceKey, AswAdapterNativeDebugging) {
+
+ override fun getAvailabilityStatus() = ExtSettingControllerHelper
+ .getSecondaryUserOnlySettingAvailability(mContext)
+}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index fc5421a9ef7..b3c1ec08472 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -229,6 +229,7 @@ public class SettingsGateway {
* security exception if the fragment it needs to display is not in this list.
*/
public static final String[] ENTRY_FRAGMENTS = {
+ com.android.settings.applications.AppNativeDebuggingFragment.class.getName(),
com.android.settings.applications.AppHardenedMallocFragment.class.getName(),
com.android.settings.safetycenter.ExploitProtectionFragment.class.getName(),
AdvancedConnectedDeviceDashboardFragment.class.getName(),
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index 7d3e08323c9..9ca0a5c46c9 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -103,6 +103,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
AppsMainPageProvider,
com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(),
com.android.settings.applications.AswAdapterUseExtendedVaSpace.makeAppListPageProvider(),
+ com.android.settings.applications.AswAdapterNativeDebugging.makeAppListPageProvider(),
AllAppListPageProvider,
AppInfoSettingsProvider,
SpecialAppAccessPageProvider,
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 1cf0ce258d1..10df60fcf93 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -185,6 +185,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter)
com.android.settings.applications.AppHardenedMallocPreference(app)
com.android.settings.applications.AppExtendedVaSpacePreference(app)
+ com.android.settings.applications.AppNativeDebuggingPreference(app)
}
Category(title = stringResource(R.string.app_install_details_group_title)) {
From bb89e6aec911a0601af6773b452e497a56049093 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Fri, 30 Aug 2024 16:25:59 +0300
Subject: [PATCH 062/162] add per-app setting for memory tagging
---
AndroidManifest.xml | 16 +++
res/values/strings_app_exploit_protection.xml | 18 +++
res/xml/exploit_protection_settings.xml | 11 ++
src/com/android/settings/Settings.java | 2 +
.../settings/applications/AppMemoryTagging.kt | 111 ++++++++++++++++++
.../core/gateway/SettingsGateway.java | 1 +
.../settings/spa/SettingsSpaEnvironment.kt | 1 +
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
8 files changed, 161 insertions(+)
create mode 100644 src/com/android/settings/applications/AppMemoryTagging.kt
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 369ce4b1002..99b51175c30 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -6058,6 +6058,22 @@
android:value="@string/menu_key_apps"/>
+
+
+
+
+
+
+
+
+
+
+
Native debugging is always blocked for preinstalled apps
+ Memory tagging
+ Show notifications about detected errors
+ Memory tagging provides strong protections against exploitation of heap memory bugs (e.g. use-after-free, buffer overflow).
+ Memory tagging is always enabled for preinstalled apps
+ Memory tagging is always enabled for apps that don’t have native code
+ This app has opted-in to memory tagging
+
+ Enable by default
+
+ This setting doesn’t apply to apps that are known to be compatible with memory tagging
+ "Memory tagging provides strong protections against exploitation of heap memory bugs (e.g. use-after-free, buffer overflow).
+
+Memory tagging is always enabled for preinstalled apps and for third-party apps that are known to be
+compatible with it (e.g. apps that don’t have native code), regardless of this setting."
+ Enabled by default
+
+ Disabled by default, except for apps that are known to be compatible with memory tagging
+
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index c56c38ef64c..d2ed9ca38c0 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -29,6 +29,17 @@
android:title="@string/aep_hmalloc"
settings:controller="com.android.settings.applications.HardenedMallocAppListPrefController" />
+
+
+
+
() {
+
+ override fun getAppSwitch() = AswUseMemoryTagging.I
+
+ override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_memtag)
+
+ override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.aep_memtag_notif_toggle_time)
+
+ override fun getDetailFragmentClass() = AppMemtagFragment::class
+}
+
+private val isMemoryTaggingSupported = Zygote.nativeSupportsMemoryTagging()
+
+@Composable
+fun AppMemtagPreference(app: ApplicationInfo) {
+ if (!isMemoryTaggingSupported) {
+ return
+ }
+
+ val context = LocalContext.current
+ AswPreference(context, app, AswAdapterUseMemoryTagging)
+}
+
+class AppMemtagFragment : AswExploitProtectionFragment() {
+
+ override fun getAswAdapter() = AswAdapterUseMemoryTagging
+
+ override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+ val id = when (ir) {
+ AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_memtag_dvr_is_system_app
+ AppSwitch.IR_NO_NATIVE_CODE -> R.string.aep_memtag_dvr_no_native_code
+ AppSwitch.IR_OPTED_IN_VIA_MANIFEST -> R.string.aep_memtag_dvr_manifest_opt_in
+ else -> return null
+ }
+ return getText(id)
+ }
+
+ override fun updateFooter(fp: FooterPreference) {
+ fp.setTitle(R.string.aep_memtag_footer)
+ }
+}
+
+class AppDefaultMemtagPrefController(ctx: Context, key: String) :
+ BoolSettingFragmentPrefController(ctx, key, ExtSettings.FORCE_APP_MEMTAG_BY_DEFAULT) {
+
+ private val isSupported = Zygote.nativeSupportsMemoryTagging()
+
+ override fun getAvailabilityStatus(): Int {
+ if (!isSupported) {
+ return UNSUPPORTED_ON_DEVICE
+ }
+
+ return super.getAvailabilityStatus()
+ }
+
+ override fun getSummaryOn() = resText(R.string.aep_default_memtag_summary_on)
+ override fun getSummaryOff() = resText(R.string.aep_default_memtag_summary_off)
+}
+
+class AppDefaultMemtagFragment : BoolSettingFragment() {
+
+ override fun getSetting() = ExtSettings.FORCE_APP_MEMTAG_BY_DEFAULT
+
+ override fun getTitle() = resText(R.string.aep_memtag)
+
+ override fun getMainSwitchTitle() = resText(R.string.aep_default_memtag_main_switch_title)
+ override fun getMainSwitchSummary() = resText(R.string.aep_default_memtag_main_switch_summary)
+
+ override fun addExtraPrefs(screen: PreferenceScreen) {
+ AswAdapterUseMemoryTagging.addAppListPageLink(screen)
+ }
+
+ override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference {
+ val text = AppPrefUtils.getFooterForDefaultHardeningSetting(requireContext(),
+ R.string.aep_default_memtag_footer)
+ return builder.setTitle(text).build()
+ }
+}
+
+class MemtagAppListPrefController(context: Context, preferenceKey: String) :
+ AswAppListPrefController(context, preferenceKey, AswAdapterUseMemoryTagging) {
+
+ private val isSupported = Zygote.nativeSupportsMemoryTagging()
+
+ override fun getAvailabilityStatus(): Int {
+ if (!isSupported) {
+ return UNSUPPORTED_ON_DEVICE
+ }
+ return ExtSettingControllerHelper
+ .getSecondaryUserOnlySettingAvailability(mContext)
+ }
+}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index b3c1ec08472..4a44ed3ce49 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -230,6 +230,7 @@ public class SettingsGateway {
*/
public static final String[] ENTRY_FRAGMENTS = {
com.android.settings.applications.AppNativeDebuggingFragment.class.getName(),
+ com.android.settings.applications.AppMemtagFragment.class.getName(),
com.android.settings.applications.AppHardenedMallocFragment.class.getName(),
com.android.settings.safetycenter.ExploitProtectionFragment.class.getName(),
AdvancedConnectedDeviceDashboardFragment.class.getName(),
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index 9ca0a5c46c9..4337c1f3725 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -102,6 +102,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
HomePageProvider,
AppsMainPageProvider,
com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(),
+ com.android.settings.applications.AswAdapterUseMemoryTagging.makeAppListPageProvider(),
com.android.settings.applications.AswAdapterUseExtendedVaSpace.makeAppListPageProvider(),
com.android.settings.applications.AswAdapterNativeDebugging.makeAppListPageProvider(),
AllAppListPageProvider,
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 10df60fcf93..398a6de5b08 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -184,6 +184,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
Category(title = stringResource(R.string.exploit_protection_category_title)) {
AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter)
com.android.settings.applications.AppHardenedMallocPreference(app)
+ com.android.settings.applications.AppMemtagPreference(app)
com.android.settings.applications.AppExtendedVaSpacePreference(app)
com.android.settings.applications.AppNativeDebuggingPreference(app)
}
From f4470ecc52871cf7e3edd9f12bbcfe920ef715a1 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Mon, 27 Nov 2023 21:47:26 +0200
Subject: [PATCH 063/162] add toggle for system process crash notifications
---
res/values/strings_ext.xml | 3 +++
res/xml/more_security_privacy_settings.xml | 8 ++++++++
2 files changed, 11 insertions(+)
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 219e9dfd244..cecf804a5ce 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -137,4 +137,7 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Charge other devices by placing them on the back of your phone
Battery share
+
+ Notify about system process crashes
+ Such crashes may indicate exploitation attempts
diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml
index 025f1c20755..69b209fa4a6 100644
--- a/res/xml/more_security_privacy_settings.xml
+++ b/res/xml/more_security_privacy_settings.xml
@@ -235,6 +235,14 @@
settings:keywords="@string/keywords_app_pinning"
settings:controller="com.android.settings.security.ScreenPinningPreferenceController" />
+
+
Date: Fri, 29 Sep 2023 16:16:00 +0300
Subject: [PATCH 064/162] Widevine provisioning setting
Signed-off-by: maade69 <70593890+maade69@users.noreply.github.com>
---
res/values/strings_ext.xml | 5 +++
res/xml/network_provider_internet.xml | 6 +++
.../WidevineProvisioningPrefController.java | 43 +++++++++++++++++++
3 files changed, 54 insertions(+)
create mode 100644 src/com/android/settings/network/WidevineProvisioningPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index cecf804a5ce..c0ac38edb83 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -111,6 +111,11 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
Use secure app spawning
Launch apps in a more secure way than Android which takes slightly longer and increases memory usage by app processes.
+ Widevine provisioning
+ GrapheneOS proxy
+ Google server
+ The provisioned certificate will be used for accessing DRM protected content.
+
App installs and updates
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index b4becf7c709..594d307f83e 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -138,4 +138,10 @@
android:title="@string/remote_provisioning_title"
android:order="35"
settings:controller="com.android.settings.network.RemoteProvisioningPrefController" />
+
+
diff --git a/src/com/android/settings/network/WidevineProvisioningPrefController.java b/src/com/android/settings/network/WidevineProvisioningPrefController.java
new file mode 100644
index 00000000000..09d62f012ac
--- /dev/null
+++ b/src/com/android/settings/network/WidevineProvisioningPrefController.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import android.content.Context;
+import android.ext.settings.WidevineProvisioningSettings;
+
+import com.android.settings.R;
+import androidx.preference.PreferenceScreen;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class WidevineProvisioningPrefController extends IntSettingPrefController {
+
+ public WidevineProvisioningPrefController(Context ctx, String key) {
+ super(ctx, key, WidevineProvisioningSettings.SERVER_SETTING);
+ }
+
+ @Override
+ public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+ addFooterPreference(screen, R.string.widevine_provisioning_footer);
+ }
+
+ @Override
+ protected void getEntries(Entries entries) {
+ entries.add(R.string.widevine_provisioning_enabled_grapheneos_proxy, WidevineProvisioningSettings.WV_GRAPHENEOS_PROXY);
+ entries.add(R.string.widevine_provisioning_enabled_google_server, WidevineProvisioningSettings.WV_STANDARD_SERVER);
+ }
+}
From 723df5723893f84f65ac4c3be9a04289118b7a48 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Mon, 18 Dec 2023 15:38:16 +0200
Subject: [PATCH 065/162] remove confusing mention of Android Auto from
"Connected devices" screen
---
.../AdvancedConnectedDeviceController.java | 10 +-------
...AdvancedConnectedDeviceControllerTest.java | 25 -------------------
2 files changed, 1 insertion(+), 34 deletions(-)
diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
index 2b86a2ad048..57215f11486 100644
--- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
+++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
@@ -35,7 +35,6 @@ public class AdvancedConnectedDeviceController extends BasePreferenceController
private static final String DRIVING_MODE_SETTINGS_ENABLED =
"gearhead:driving_mode_settings_enabled";
- private static final String GEARHEAD_PACKAGE = "com.google.android.projection.gearhead";
public AdvancedConnectedDeviceController(Context context, String preferenceKey) {
super(context, preferenceKey);
@@ -60,7 +59,7 @@ public static int getConnectedDevicesSummaryResourceId(Context context) {
new NfcPreferenceController(context, NfcPreferenceController.KEY_TOGGLE_NFC);
return getConnectedDevicesSummaryResourceId(nfcPreferenceController,
- isDrivingModeAvailable(context), isAndroidAutoSettingAvailable(context));
+ isDrivingModeAvailable(context), false);
}
@VisibleForTesting
@@ -69,13 +68,6 @@ static boolean isDrivingModeAvailable(Context context) {
getInt(context.getContentResolver(), DRIVING_MODE_SETTINGS_ENABLED, 0) == 1;
}
- @VisibleForTesting
- static boolean isAndroidAutoSettingAvailable(Context context) {
- final Intent intent = new Intent(IA_SETTINGS_ACTION);
- intent.setPackage(GEARHEAD_PACKAGE);
- return intent.resolveActivity(context.getPackageManager()) != null;
- }
-
@VisibleForTesting
static int getConnectedDevicesSummaryResourceId(NfcPreferenceController
nfcPreferenceController,
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
index 6ae670dc120..2af9242dab8 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
@@ -99,31 +99,6 @@ public void isDrivingModeAvailable_returnFalse() {
AdvancedConnectedDeviceController.isDrivingModeAvailable(mContext)).isFalse();
}
- @Test
- public void isAndroidAutoSettingAvailable_returnTrue() {
- final ApplicationInfo appInfo =
- ApplicationInfoBuilder.newBuilder().setPackageName(ANDROID_AUTO_PACKAGE).build();
- final ActivityInfo activityInfo = new ActivityInfo();
- activityInfo.packageName = ANDROID_AUTO_PACKAGE;
- activityInfo.name = ANDROID_AUTO_PACKAGE;
- activityInfo.applicationInfo = appInfo;
- final ResolveInfo resolveInfo = new ResolveInfo();
- resolveInfo.activityInfo = activityInfo;
- mShadowPackageManager.addResolveInfoForIntent(
- buildAndroidAutoSettingsIntent(),
- resolveInfo);
-
- assertThat(
- AdvancedConnectedDeviceController.isAndroidAutoSettingAvailable(mContext)).isTrue();
- }
-
- @Test
- public void isAndroidAutoSettingAvailable_returnFalse() {
- // No ResolveInfo for Android Auto, expect false.
- assertThat(
- AdvancedConnectedDeviceController.isAndroidAutoSettingAvailable(mContext)).isFalse();
- }
-
@Test
public void getConnectedDevicesSummaryResourceId_NFCAndDrivingModeAvailable() {
// NFC available, driving mode available
From a2cb5c35dc1be859bf895f47312ab4a851a88760 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sat, 6 Jan 2024 19:37:47 +0200
Subject: [PATCH 066/162] add logcat viewer link to System settings
---
AndroidManifest.xml | 1 +
res/values/strings_ext.xml | 3 ++
res/xml/system_dashboard_fragment.xml | 7 ++++
.../system/LogcatLinkPrefController.java | 34 +++++++++++++++++++
4 files changed, 45 insertions(+)
create mode 100644 src/com/android/settings/system/LogcatLinkPrefController.java
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 99b51175c30..c1fa945db61 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -150,6 +150,7 @@
+
Notify about system process crashes
Such crashes may indicate exploitation attempts
+
+ View logs
+
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index 2bef02855dc..704dac9f385 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -113,6 +113,13 @@
+
+
Date: Sat, 2 Mar 2024 11:25:46 +0200
Subject: [PATCH 067/162] add logcat viewer link to App info screen
---
.../spa/app/appinfo/AppInfoSettings.kt | 1 +
.../spa/app/appinfo/AppLogcatPreference.kt | 29 +++++++++++++++++++
2 files changed, 30 insertions(+)
create mode 100644 src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 398a6de5b08..83979d639f5 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -162,6 +162,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
AppLocalePreference(app)
AppOpenByDefaultPreference(app)
DefaultAppShortcuts(app)
+ AppLogcatPreference(app)
}
Category(title = stringResource(R.string.unused_apps_category)) {
diff --git a/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt b/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt
new file mode 100644
index 00000000000..14e3c60b5e1
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt
@@ -0,0 +1,29 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.pm.ApplicationInfo
+import android.ext.LogViewerApp
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.installed
+import com.android.settingslib.spaprivileged.model.app.userHandle
+
+@Composable
+fun AppLogcatPreference(app: ApplicationInfo) {
+ if (!app.installed) {
+ return
+ }
+
+ val context = LocalContext.current
+
+ Preference(object : PreferenceModel {
+ override val title = stringResource(R.string.view_logs)
+ override val onClick = {
+ val intent = LogViewerApp.getPackageLogcatIntent(app.packageName)
+ context.startActivityAsUser(intent, app.userHandle)
+ }
+ })
+}
From 5efbc38ef7e6186909391d811ebd232ff53e65bb Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Wed, 21 Feb 2024 16:39:26 +0200
Subject: [PATCH 068/162] add USB-C port and pogo pins security setting
---
res/values/strings_ext.xml | 32 +++++++
res/xml/exploit_protection_settings.xml | 10 +++
.../UsbPortSecurityPrefController.java | 85 +++++++++++++++++++
3 files changed, 127 insertions(+)
create mode 100644 src/com/android/settings/security/UsbPortSecurityPrefController.java
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
index 2f3c8d88604..4847d62aa03 100644
--- a/res/values/strings_ext.xml
+++ b/res/values/strings_ext.xml
@@ -148,4 +148,36 @@ There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
View logs
+ USB-C port
+ Off
+ Turns off the USB-C port.
+ Doesn’t impact the separate charging mode, which is activated by turning off the device and plugging it in to a charger.
+
+ Charging-only
+ Turns off all non-charging USB-C port functionality.
+ Charging-only when locked
+ Enables the charging-only mode when the
+ device is locked and disables it when the device becomes unlocked. If the port is already
+ plugged-in at the time when the device becomes locked, then the activation of charging-only
+ mode will be delayed until the port is disconnected.
+ Charging-only when locked, except before first unlock
+ This mode has the same behavior
+ as the “%1$s” mode, except for an additional exemption for before-first-unlock connections.
+
+ On
+ Does not add any restrictions.
+
+ USB-C port and pogo pins
+ USB-C port off, pogo pins used only for charging
+ Turns off the USB-C port and turns off all
+ non-charging pogo pins functionality. Doesn’t impact the separate charging mode, which is
+ activated by turning off the device and plugging it in to a charger.
+
+ Turns off all non-charging USB-C port and pogo pins functionality.
+ Enables the charging-only mode when the
+ device is locked and disables it when the device becomes unlocked. If the port is already
+ plugged-in at the time when the device becomes locked, then the activation of charging-only
+ mode will be delayed until the port is disconnected. The same behavior applies to pogo pins.
+
+
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
index d2ed9ca38c0..530e97cd956 100644
--- a/res/xml/exploit_protection_settings.xml
+++ b/res/xml/exploit_protection_settings.xml
@@ -10,6 +10,16 @@
android:title="@string/auto_reboot_title"
settings:controller="com.android.settings.security.AutoRebootPrefController" />
+
+
+
+
Date: Thu, 7 Mar 2024 12:21:53 +0200
Subject: [PATCH 069/162] enable "About phone -> Battery information" screen
Squashed with:
commit 50f8f1d6d2c588e8e5504f6f9f6c071c6b26938f
Author: Daniel Micay
Date: Sat Mar 9 10:06:21 2024 -0500
use 2021-01-01 as minimum battery date
---
.../fuelgauge/BatterySettingsFeatureProviderImpl.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java
index 19c10d78306..d2b9c0cebb1 100644
--- a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java
@@ -32,17 +32,17 @@ public class BatterySettingsFeatureProviderImpl implements BatterySettingsFeatur
@Override
public boolean isManufactureDateAvailable(Context context, long manufactureDateMs) {
- return false;
+ return manufactureDateMs > 1_609_459_200_000L; // 2021-01-01
}
@Override
public boolean isFirstUseDateAvailable(Context context, long firstUseDateMs) {
- return false;
+ return firstUseDateMs > 1_609_459_200_000L; // 2021-01-01
}
@Override
public boolean isBatteryInfoEnabled(Context context) {
- return false;
+ return true;
}
@Override
From 52d5942ea7e98cebae52038a930595822babafe4 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor
Date: Sun, 17 Mar 2024 17:40:23 +0200
Subject: [PATCH 070/162] fix footer formatting issue on App pinning screen
Since 20976c3a53802a8b78cab20e49154244ddaf9ddd screen_pinning_description is a formatted string,
it can't be used directly from XML.
---
res/xml/screen_pinning_settings.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/res/xml/screen_pinning_settings.xml b/res/xml/screen_pinning_settings.xml
index 2c4402da89e..f06b42ceab1 100644
--- a/res/xml/screen_pinning_settings.xml
+++ b/res/xml/screen_pinning_settings.xml
@@ -30,7 +30,6 @@
From 95ec88d7c2f8dc42b9f7d80226c63ffc5d559961 Mon Sep 17 00:00:00 2001
From: Jitesh Singh
Date: Tue, 30 Jan 2024 19:48:12 +0530
Subject: [PATCH 071/162] fixes redundant horizontal margin issue on tablets
---
res/values-sw600dp-v31/dimens.xml | 9 +++++++++
res/values-sw600dp/dimens.xml | 8 ++++++++
2 files changed, 17 insertions(+)
create mode 100644 res/values-sw600dp-v31/dimens.xml
diff --git a/res/values-sw600dp-v31/dimens.xml b/res/values-sw600dp-v31/dimens.xml
new file mode 100644
index 00000000000..3542f62dc08
--- /dev/null
+++ b/res/values-sw600dp-v31/dimens.xml
@@ -0,0 +1,9 @@
+
+
+ 24dp
+ 24dp
+ 8dp
+ 20dp
+ 20dp
+ 8dp
+
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index f5615bfbe67..255df2876d9 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -29,6 +29,14 @@
348dp
+
+ 24dp
+ 24dp
+ 8dp
+ 20dp
+ 20dp
+ 8dp
+
104dp
448dp
From 456c7563708379c2839a9455e44cff571b04cdce Mon Sep 17 00:00:00 2001
From: Jitesh Singh
Date: Wed, 31 Jan 2024 01:41:53 +0530
Subject: [PATCH 072/162] internet setup activity
Co-authored-by: Dmitry Muhomor
Co-authored-by: quh4gko8 <88831734+quh4gko8@users.noreply.github.com>
---
AndroidManifest.xml | 13 ++
res/drawable/baseline_wifi.xml | 10 ++
res/drawable/baseline_wifi_glif.xml | 7 +
res/layout/settings_main_prefs.xml | 62 ++++---
res/values/dimens.xml | 5 +
res/values/themes_suw.xml | 2 +
.../network/InternetSetupActivity.java | 52 ++++++
.../network/NetworkProviderSettings.java | 4 +-
.../network/NetworkProviderSetup.java | 155 ++++++++++++++++++
9 files changed, 276 insertions(+), 34 deletions(-)
create mode 100644 res/drawable/baseline_wifi.xml
create mode 100644 res/drawable/baseline_wifi_glif.xml
create mode 100644 src/com/android/settings/network/InternetSetupActivity.java
create mode 100644 src/com/android/settings/network/NetworkProviderSetup.java
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c1fa945db61..6cce54f67f3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -520,6 +520,19 @@
android:value="true" />
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/drawable/baseline_wifi_glif.xml b/res/drawable/baseline_wifi_glif.xml
new file mode 100644
index 00000000000..3f12842b089
--- /dev/null
+++ b/res/drawable/baseline_wifi_glif.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/settings_main_prefs.xml b/res/layout/settings_main_prefs.xml
index 48352e2efa0..5111332bfbe 100644
--- a/res/layout/settings_main_prefs.xml
+++ b/res/layout/settings_main_prefs.xml
@@ -34,40 +34,38 @@
android:layout_height="0dp"
android:layout_weight="1"/>
-
-
-
-
-
-
-
+
+
-
+
-
+
+
-
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b4575a9d168..fbd3d44c698 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -523,6 +523,11 @@
16dp
24dp
+
+
+ @dimen/sud_progress_bar_margin_top_material_you
+
+
136dp
64dp
diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml
index 0ba60474da2..b254fe7b36b 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -150,6 +150,7 @@
- @style/LockPatternStyle
+ - true
+
+