From 25d8e56c538e3a5078ec575f7e3c657dda48e82d Mon Sep 17 00:00:00 2001 From: Andreea Costinas Date: Thu, 24 Oct 2024 12:48:38 +0000 Subject: [PATCH 1/5] Relax WiFi cert installation restrictions in HSUM mode The Settings app runs under the current user, which previously lacked the necessary permissions to install client certificates in HSUM mode. This change allows any admin user to install these certificates. Bug: b/370013519 Flag: EXEMPT bugfix Test: manually installed and removed client certificate for WiFi Change-Id: I57a7364c76a0adb7ed4112e48fb20070ab9d7bff --- .../settings/UserCredentialsSettings.java | 18 +++++++++--------- .../settings/security/CredentialStorage.java | 14 ++------------ 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java index 495065023e4..210543ff07f 100644 --- a/src/com/android/settings/UserCredentialsSettings.java +++ b/src/com/android/settings/UserCredentialsSettings.java @@ -291,23 +291,23 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment // Certificates can be installed into SYSTEM_UID or WIFI_UID through CertInstaller. final int myUserId = UserHandle.myUserId(); final int systemUid = UserHandle.getUid(myUserId, Process.SYSTEM_UID); - final int wifiUid = UserHandle.getUid(myUserId, Process.WIFI_UID); - try { KeyStore processKeystore = KeyStore.getInstance(KEYSTORE_PROVIDER); processKeystore.load(null); KeyStore wifiKeystore = null; - if (myUserId == 0) { - wifiKeystore = KeyStore.getInstance(KEYSTORE_PROVIDER); - wifiKeystore.load(new AndroidKeyStoreLoadStoreParameter( - KeyProperties.NAMESPACE_WIFI)); - } List credentials = new ArrayList<>(); credentials.addAll(getCredentialsForUid(processKeystore, systemUid).values()); - if (wifiKeystore != null) { - credentials.addAll(getCredentialsForUid(wifiKeystore, wifiUid).values()); + + UserManager userManager = getContext().getSystemService(UserManager.class); + if (userManager.isAdminUser()) { + wifiKeystore = KeyStore.getInstance(KEYSTORE_PROVIDER); + wifiKeystore.load( + new AndroidKeyStoreLoadStoreParameter(KeyProperties.NAMESPACE_WIFI)); + credentials.addAll( + getCredentialsForUid(wifiKeystore, Process.WIFI_UID).values()); } + return credentials; } catch (Exception e) { throw new RuntimeException("Failed to load credentials from Keystore.", e); diff --git a/src/com/android/settings/security/CredentialStorage.java b/src/com/android/settings/security/CredentialStorage.java index b62aeae9382..b1c65a7c3c0 100644 --- a/src/com/android/settings/security/CredentialStorage.java +++ b/src/com/android/settings/security/CredentialStorage.java @@ -128,22 +128,12 @@ public final class CredentialStorage extends FragmentActivity { final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, KeyProperties.UID_SELF); - if (uid != KeyProperties.UID_SELF && !UserHandle.isSameUser(uid, Process.myUid())) { - final int dstUserId = UserHandle.getUserId(uid); - - // Restrict install target to the wifi uid. - if (uid != Process.WIFI_UID) { + if (uid != KeyProperties.UID_SELF && uid != Process.WIFI_UID) { + if (!UserHandle.isSameUser(uid, Process.myUid())) { Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs" + " may only target wifi uids"); return true; } - - final Intent installIntent = new Intent(ACTION_INSTALL) - .setPackage(getPackageName()) - .setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) - .putExtras(bundle); - startActivityAsUser(installIntent, new UserHandle(dstUserId)); - return true; } String alias = bundle.getString(Credentials.EXTRA_USER_KEY_ALIAS, null); From 80f8b87e28c5f4db32e12f67999e9115d21094d1 Mon Sep 17 00:00:00 2001 From: Menghan Li Date: Thu, 14 Nov 2024 06:45:12 +0000 Subject: [PATCH 2/5] fix(ColorCorrection): Palette preview text contrast Issue Root Cause: The palette preview's text color inherits dynamic colors from the BC pattern, leading to insufficient contrast against some backgrounds. This wasn't a problem in the original design, as the BC pattern was introduced later. Solution: Set the palette preview text color to textColorPrimary to ensure the text remains legible against a wider range of background colors. Bug: 378775277 Flag: EXEMPT bugfix Test: atest PaletteListPreferenceTest Change-Id: I8efb9f9d916d618b450df169292202e499d8ac0d --- .../accessibility/PaletteListPreference.java | 5 +++++ .../PaletteListPreferenceTest.java | 19 +++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/accessibility/PaletteListPreference.java b/src/com/android/settings/accessibility/PaletteListPreference.java index eec8b5a6cde..c29113cd116 100644 --- a/src/com/android/settings/accessibility/PaletteListPreference.java +++ b/src/com/android/settings/accessibility/PaletteListPreference.java @@ -24,6 +24,7 @@ import static com.android.settings.accessibility.AccessibilityUtil.getScreenWidt import static com.google.common.primitives.Ints.max; import android.content.Context; +import android.content.res.ColorStateList; import android.graphics.Paint.FontMetrics; import android.graphics.drawable.GradientDrawable; import android.util.AttributeSet; @@ -39,6 +40,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; import com.android.settings.R; +import com.android.settingslib.Utils; import com.google.common.primitives.Floats; import com.google.common.primitives.Ints; @@ -128,6 +130,8 @@ public final class PaletteListPreference extends Preference { final List paletteColors = getPaletteColors(context); final List paletteData = getPaletteData(context); + final ColorStateList textColor = + Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary); final float textPadding = context.getResources().getDimension(R.dimen.accessibility_layout_margin_start_end); final String maxLengthData = @@ -143,6 +147,7 @@ public final class PaletteListPreference extends Preference { for (int i = 0; i < paletteData.size(); ++i) { final TextView textView = new TextView(context); textView.setText(paletteData.get(i)); + textView.setTextColor(textColor); textView.setHeight(paletteItemHeight); textView.setPaddingRelative(Math.round(textPadding), 0, 0, 0); textView.setGravity(Gravity.CENTER_VERTICAL); diff --git a/tests/robotests/src/com/android/settings/accessibility/PaletteListPreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/PaletteListPreferenceTest.java index 759b180206f..8ff3a0e6639 100644 --- a/tests/robotests/src/com/android/settings/accessibility/PaletteListPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/PaletteListPreferenceTest.java @@ -16,17 +16,20 @@ package com.android.settings.accessibility; -import static org.junit.Assert.assertEquals; +import static com.google.common.truth.Truth.assertThat; import android.content.Context; +import android.content.res.ColorStateList; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; import androidx.preference.PreferenceViewHolder; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; +import com.android.settingslib.Utils; import org.junit.Before; import org.junit.Test; @@ -53,12 +56,20 @@ public final class PaletteListPreferenceTest { @Test public void initPaletteView_success() { + final int expectedCount = + mContext.getResources().getStringArray(R.array.setting_palette_data).length; + final ColorStateList expectedTextColor = + Utils.getColorAttr(mContext, android.R.attr.textColorPrimary); + mPaletteListPreference.onBindViewHolder(mPreferenceViewHolder); final ViewGroup viewGroup = mPreferenceViewHolder.itemView.findViewById(R.id.palette_view); - final int expectedCount = - mContext.getResources().getStringArray(R.array.setting_palette_data).length; - assertEquals(expectedCount, viewGroup.getChildCount()); + final int childCount = viewGroup.getChildCount(); + assertThat(childCount).isEqualTo(expectedCount); + for (int i = 0; i < childCount; i++) { + final TextView textView = (TextView) viewGroup.getChildAt(i); + assertThat(textView.getTextColors()).isEqualTo(expectedTextColor); + } } } From 1f24f061b41b166d90244979b5628f8650679f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= Date: Thu, 14 Nov 2024 20:26:40 +0000 Subject: [PATCH 3/5] Hide the blurb for custom-manual types Fixes: 377691826 Test: manual Flag: android.app.modes_ui Change-Id: I3c959f32c7ae1cc2c95fb4e9180e2f871ed3ee91 --- .../notification/modes/ZenModeBlurbPreferenceController.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/com/android/settings/notification/modes/ZenModeBlurbPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeBlurbPreferenceController.java index 097b40db3d3..4275f221332 100644 --- a/src/com/android/settings/notification/modes/ZenModeBlurbPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeBlurbPreferenceController.java @@ -40,6 +40,11 @@ class ZenModeBlurbPreferenceController extends AbstractZenModePreferenceControll super(context, key); } + @Override + public boolean isAvailable(@NonNull ZenMode zenMode) { + return !zenMode.isCustomManual(); + } + @Override void updateState(Preference preference, @NonNull ZenMode zenMode) { preference.setTitle(getModeBlurb(zenMode)); From 22306eb982d2d0c5847f38a2d88865d3ce29300f Mon Sep 17 00:00:00 2001 From: Chris Antol Date: Thu, 14 Nov 2024 21:21:42 +0000 Subject: [PATCH 4/5] Add Special App Access page for WRITE_SYSTEM_PREFERENCES permission Bug: 374848822 Flag: com.android.settingslib.flags.write_system_preference_permission_enabled Flag: com.android.settingslib.flags.settings_catalyst Test: in-app test Change-Id: I8116e40108175d2606b0c24655d457c1f04afc35 --- res/values/strings.xml | 4 ++ res/xml/special_access.xml | 5 ++ .../settings/spa/SettingsSpaEnvironment.kt | 2 + .../spa/app/appinfo/AppInfoSettings.kt | 2 + .../spa/app/specialaccess/SpecialAppAccess.kt | 1 + .../specialaccess/WriteSystemPreferences.kt | 62 +++++++++++++++++++ ...teSystemPreferencesPreferenceController.kt | 44 +++++++++++++ 7 files changed, 120 insertions(+) create mode 100644 src/com/android/settings/spa/app/specialaccess/WriteSystemPreferences.kt create mode 100644 src/com/android/settings/spa/app/specialaccess/WriteSystemPreferencesPreferenceController.kt diff --git a/res/values/strings.xml b/res/values/strings.xml index 54b7f67b338..6c79d60a2c7 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10429,6 +10429,10 @@ Allow this app to show notifications that take up the full screen when the device is locked. Apps may use these to highlight alarms, incoming calls, or other urgent notifications. + Write system preferences + Allow this app to modify system preferences on your behalf + This permission allows an app to modify core system preferences. + Media management apps diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml index d0fe980d82b..f3a5f3216c7 100644 --- a/res/xml/special_access.xml +++ b/res/xml/special_access.xml @@ -106,6 +106,11 @@ android:title="@string/full_screen_intent_title" settings:controller="com.android.settings.spa.app.specialaccess.UseFullScreenIntentPreferenceController" /> + + , recordListFlow: Flow>): + Flow> { + return super.filter(userIdFlow, recordListFlow).map { recordList -> + recordList.filter { app -> + // Only apps that have READ_SYSTEM_PREFERENCES can utilize WRITE_SYSTEM_PREFERENCES. + // This write permission is (currently) non-functionality without the corresponding + // read permission, and the read permission can only be granted via pre-grant or + // role. As such, we don't show apps that are "requesting" this permission without + // holding the read permission, as it would create confusion and not provide them + // any functionality. + with (PackageManagers) { + app.app.hasGrantPermission(Manifest.permission.READ_SYSTEM_PREFERENCES) + } + } + } + } +} \ No newline at end of file diff --git a/src/com/android/settings/spa/app/specialaccess/WriteSystemPreferencesPreferenceController.kt b/src/com/android/settings/spa/app/specialaccess/WriteSystemPreferencesPreferenceController.kt new file mode 100644 index 00000000000..fb808fa8199 --- /dev/null +++ b/src/com/android/settings/spa/app/specialaccess/WriteSystemPreferencesPreferenceController.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 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.spa.app.specialaccess + +import android.content.Context +import androidx.preference.Preference +import com.android.settings.core.BasePreferenceController +import com.android.settings.spa.SpaActivity.Companion.startSpaActivity +import com.android.settingslib.flags.Flags + +class WriteSystemPreferencesPreferenceController( + context: Context, key: String +) : BasePreferenceController(context, key) { + override fun getAvailabilityStatus(): Int { + return if (Flags.settingsCatalyst() && Flags.writeSystemPreferencePermissionEnabled()) { + AVAILABLE + } else { + UNSUPPORTED_ON_DEVICE + } + } + + override fun handlePreferenceTreeClick(preference: Preference?): Boolean { + return if (preference?.key == mPreferenceKey) { + mContext.startSpaActivity(WriteSystemPreferencesAppListProvider.getAppListRoute()) + true + } else { + false + } + } +} \ No newline at end of file From cbc49e787d1d9da14b60298c8ee53a6153605526 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Thu, 14 Nov 2024 04:51:58 +0000 Subject: [PATCH 5/5] [Settings] Refactor: Add RegionAndNumberingSystemPickerFragmet Bug: 377664066 Flag: EXEMPT refactor Change-Id: Ib485d2763e0ce17473c8442ba4626802689c7b78 --- ...egionAndNumberingSystemPickerFragment.java | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java diff --git a/src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java b/src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java new file mode 100644 index 00000000000..171df6a3d39 --- /dev/null +++ b/src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2024 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.localepicker; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.preference.PreferenceCategory; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.internal.app.LocaleHelper; +import com.android.internal.app.LocaleStore; +import com.android.internal.app.SystemLocaleCollector; +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.widget.PreferenceCategoryController; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import com.google.android.material.appbar.AppBarLayout; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +/** + * A locale picker fragment to show region country and numbering system. + * + *

It shows suggestions at the top, then the rest of the locales. + * Allows the user to search for locales using both their native name and their name in the + * default locale.

+ */ +public class RegionAndNumberingSystemPickerFragment extends DashboardFragment { + private static final String TAG = "RegionAndNumberingSystemPickerFragment"; + + private RecyclerView mRecyclerView; + private AppBarLayout mAppBarLayout; + private Activity mActivity; + + @Override + public void onCreate(@NonNull Bundle icicle) { + super.onCreate(icicle); + mActivity = getActivity(); + if (mActivity.isFinishing()) { + return; + } + } + + @Override + public @NonNull View onCreateView(@NonNull LayoutInflater inflater, + @NonNull ViewGroup container, @NonNull Bundle savedInstanceState) { + mAppBarLayout = mActivity.findViewById(R.id.app_bar); + mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/); + return super.onCreateView(inflater, container, savedInstanceState); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mRecyclerView = view.findViewById(R.id.recycler_view); + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.system_language_picker; + } + + @Override + protected List createPreferenceControllers(Context context) { + return buildPreferenceControllers(context, getSettingsLifecycle()); + } + + private List buildPreferenceControllers( + @NonNull Context context, @Nullable Lifecycle lifecycle) { + final List controllers = new ArrayList<>(); + + // TODO: b/30358431 - Add preference of region locales. + + return controllers; + } + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.system_language_picker); + + @Override + public int getMetricsCategory() { + return 0; + } +}