Snap for 12664851 from 0d585fc4ae
to 25Q1-release
Change-Id: I17f6c232afc18c5d00fe489acdcbbc612ff92c07
This commit is contained in:
@@ -10429,6 +10429,10 @@
|
|||||||
<!-- Description for setting that allows apps to send full screen intents. [CHAR LIMIT=NONE] -->
|
<!-- Description for setting that allows apps to send full screen intents. [CHAR LIMIT=NONE] -->
|
||||||
<string name="footer_description_full_screen_intent">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.</string>
|
<string name="footer_description_full_screen_intent">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.</string>
|
||||||
|
|
||||||
|
<string name="write_system_preferences_page_title">Write system preferences</string>
|
||||||
|
<string name="write_system_preferences_switch_title">Allow this app to modify system preferences on your behalf</string>
|
||||||
|
<string name="write_system_preferences_footer_description">This permission allows an app to modify core system preferences.</string>
|
||||||
|
|
||||||
<!-- Media management apps settings title [CHAR LIMIT=40] -->
|
<!-- Media management apps settings title [CHAR LIMIT=40] -->
|
||||||
<string name="media_management_apps_title">Media management apps</string>
|
<string name="media_management_apps_title">Media management apps</string>
|
||||||
<!-- Label for a setting which controls whether an app can manage media files [CHAR LIMIT=45] -->
|
<!-- Label for a setting which controls whether an app can manage media files [CHAR LIMIT=45] -->
|
||||||
|
@@ -106,6 +106,11 @@
|
|||||||
android:title="@string/full_screen_intent_title"
|
android:title="@string/full_screen_intent_title"
|
||||||
settings:controller="com.android.settings.spa.app.specialaccess.UseFullScreenIntentPreferenceController" />
|
settings:controller="com.android.settings.spa.app.specialaccess.UseFullScreenIntentPreferenceController" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="write_system_preferences"
|
||||||
|
android:title="@string/write_system_preferences_page_title"
|
||||||
|
settings:controller="com.android.settings.spa.app.specialaccess.WriteSystemPreferencesPreferenceController" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="picture_in_picture"
|
android:key="picture_in_picture"
|
||||||
android:title="@string/picture_in_picture_title"
|
android:title="@string/picture_in_picture_title"
|
||||||
|
@@ -291,23 +291,23 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
|
|||||||
// Certificates can be installed into SYSTEM_UID or WIFI_UID through CertInstaller.
|
// Certificates can be installed into SYSTEM_UID or WIFI_UID through CertInstaller.
|
||||||
final int myUserId = UserHandle.myUserId();
|
final int myUserId = UserHandle.myUserId();
|
||||||
final int systemUid = UserHandle.getUid(myUserId, Process.SYSTEM_UID);
|
final int systemUid = UserHandle.getUid(myUserId, Process.SYSTEM_UID);
|
||||||
final int wifiUid = UserHandle.getUid(myUserId, Process.WIFI_UID);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KeyStore processKeystore = KeyStore.getInstance(KEYSTORE_PROVIDER);
|
KeyStore processKeystore = KeyStore.getInstance(KEYSTORE_PROVIDER);
|
||||||
processKeystore.load(null);
|
processKeystore.load(null);
|
||||||
KeyStore wifiKeystore = null;
|
KeyStore wifiKeystore = null;
|
||||||
if (myUserId == 0) {
|
|
||||||
wifiKeystore = KeyStore.getInstance(KEYSTORE_PROVIDER);
|
|
||||||
wifiKeystore.load(new AndroidKeyStoreLoadStoreParameter(
|
|
||||||
KeyProperties.NAMESPACE_WIFI));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Credential> credentials = new ArrayList<>();
|
List<Credential> credentials = new ArrayList<>();
|
||||||
credentials.addAll(getCredentialsForUid(processKeystore, systemUid).values());
|
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;
|
return credentials;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Failed to load credentials from Keystore.", e);
|
throw new RuntimeException("Failed to load credentials from Keystore.", e);
|
||||||
|
@@ -24,6 +24,7 @@ import static com.android.settings.accessibility.AccessibilityUtil.getScreenWidt
|
|||||||
import static com.google.common.primitives.Ints.max;
|
import static com.google.common.primitives.Ints.max;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Paint.FontMetrics;
|
import android.graphics.Paint.FontMetrics;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -39,6 +40,7 @@ import androidx.preference.Preference;
|
|||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
|
||||||
import com.google.common.primitives.Floats;
|
import com.google.common.primitives.Floats;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
@@ -128,6 +130,8 @@ public final class PaletteListPreference extends Preference {
|
|||||||
final List<Integer> paletteColors = getPaletteColors(context);
|
final List<Integer> paletteColors = getPaletteColors(context);
|
||||||
final List<String> paletteData = getPaletteData(context);
|
final List<String> paletteData = getPaletteData(context);
|
||||||
|
|
||||||
|
final ColorStateList textColor =
|
||||||
|
Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary);
|
||||||
final float textPadding =
|
final float textPadding =
|
||||||
context.getResources().getDimension(R.dimen.accessibility_layout_margin_start_end);
|
context.getResources().getDimension(R.dimen.accessibility_layout_margin_start_end);
|
||||||
final String maxLengthData =
|
final String maxLengthData =
|
||||||
@@ -143,6 +147,7 @@ public final class PaletteListPreference extends Preference {
|
|||||||
for (int i = 0; i < paletteData.size(); ++i) {
|
for (int i = 0; i < paletteData.size(); ++i) {
|
||||||
final TextView textView = new TextView(context);
|
final TextView textView = new TextView(context);
|
||||||
textView.setText(paletteData.get(i));
|
textView.setText(paletteData.get(i));
|
||||||
|
textView.setTextColor(textColor);
|
||||||
textView.setHeight(paletteItemHeight);
|
textView.setHeight(paletteItemHeight);
|
||||||
textView.setPaddingRelative(Math.round(textPadding), 0, 0, 0);
|
textView.setPaddingRelative(Math.round(textPadding), 0, 0, 0);
|
||||||
textView.setGravity(Gravity.CENTER_VERTICAL);
|
textView.setGravity(Gravity.CENTER_VERTICAL);
|
||||||
|
@@ -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.
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*/
|
||||||
|
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<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||||
|
return buildPreferenceControllers(context, getSettingsLifecycle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AbstractPreferenceController> buildPreferenceControllers(
|
||||||
|
@NonNull Context context, @Nullable Lifecycle lifecycle) {
|
||||||
|
final List<AbstractPreferenceController> 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;
|
||||||
|
}
|
||||||
|
}
|
@@ -40,6 +40,11 @@ class ZenModeBlurbPreferenceController extends AbstractZenModePreferenceControll
|
|||||||
super(context, key);
|
super(context, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable(@NonNull ZenMode zenMode) {
|
||||||
|
return !zenMode.isCustomManual();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateState(Preference preference, @NonNull ZenMode zenMode) {
|
void updateState(Preference preference, @NonNull ZenMode zenMode) {
|
||||||
preference.setTitle(getModeBlurb(zenMode));
|
preference.setTitle(getModeBlurb(zenMode));
|
||||||
|
@@ -128,22 +128,12 @@ public final class CredentialStorage extends FragmentActivity {
|
|||||||
|
|
||||||
final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, KeyProperties.UID_SELF);
|
final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, KeyProperties.UID_SELF);
|
||||||
|
|
||||||
if (uid != KeyProperties.UID_SELF && !UserHandle.isSameUser(uid, Process.myUid())) {
|
if (uid != KeyProperties.UID_SELF && uid != Process.WIFI_UID) {
|
||||||
final int dstUserId = UserHandle.getUserId(uid);
|
if (!UserHandle.isSameUser(uid, Process.myUid())) {
|
||||||
|
|
||||||
// Restrict install target to the wifi uid.
|
|
||||||
if (uid != Process.WIFI_UID) {
|
|
||||||
Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs"
|
Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs"
|
||||||
+ " may only target wifi uids");
|
+ " may only target wifi uids");
|
||||||
return true;
|
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);
|
String alias = bundle.getString(Credentials.EXTRA_USER_KEY_ALIAS, null);
|
||||||
|
@@ -42,6 +42,7 @@ import com.android.settings.spa.app.specialaccess.SpecialAppAccessPageProvider
|
|||||||
import com.android.settings.spa.app.specialaccess.TurnScreenOnAppsAppListProvider
|
import com.android.settings.spa.app.specialaccess.TurnScreenOnAppsAppListProvider
|
||||||
import com.android.settings.spa.app.specialaccess.UseFullScreenIntentAppListProvider
|
import com.android.settings.spa.app.specialaccess.UseFullScreenIntentAppListProvider
|
||||||
import com.android.settings.spa.app.specialaccess.WifiControlAppListProvider
|
import com.android.settings.spa.app.specialaccess.WifiControlAppListProvider
|
||||||
|
import com.android.settings.spa.app.specialaccess.WriteSystemPreferencesAppListProvider
|
||||||
import com.android.settings.spa.app.storage.StorageAppListPageProvider
|
import com.android.settings.spa.app.storage.StorageAppListPageProvider
|
||||||
import com.android.settings.spa.core.instrumentation.SpaLogMetricsProvider
|
import com.android.settings.spa.core.instrumentation.SpaLogMetricsProvider
|
||||||
import com.android.settings.spa.core.instrumentation.SpaLogProvider
|
import com.android.settings.spa.core.instrumentation.SpaLogProvider
|
||||||
@@ -80,6 +81,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
|
|||||||
NfcTagAppsSettingsProvider,
|
NfcTagAppsSettingsProvider,
|
||||||
LongBackgroundTasksAppListProvider,
|
LongBackgroundTasksAppListProvider,
|
||||||
TurnScreenOnAppsAppListProvider,
|
TurnScreenOnAppsAppListProvider,
|
||||||
|
WriteSystemPreferencesAppListProvider,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,6 +42,7 @@ import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListPro
|
|||||||
import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
|
import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
|
||||||
import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
|
import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
|
||||||
import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
|
import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
|
||||||
|
import com.android.settings.spa.app.specialaccess.WriteSystemPreferencesAppListProvider
|
||||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||||
import com.android.settingslib.spa.framework.compose.navigator
|
import com.android.settingslib.spa.framework.compose.navigator
|
||||||
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
|
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
|
||||||
@@ -167,6 +168,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
|
|||||||
InstallUnknownAppsListProvider.InfoPageEntryItem(app)
|
InstallUnknownAppsListProvider.InfoPageEntryItem(app)
|
||||||
InteractAcrossProfilesDetailsPreference(app)
|
InteractAcrossProfilesDetailsPreference(app)
|
||||||
AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app)
|
AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app)
|
||||||
|
WriteSystemPreferencesAppListProvider.InfoPageEntryItem(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
Category(title = stringResource(R.string.app_install_details_group_title)) {
|
Category(title = stringResource(R.string.app_install_details_group_title)) {
|
||||||
|
@@ -70,6 +70,7 @@ object SpecialAppAccessPageProvider : SettingsPageProvider {
|
|||||||
WifiControlAppListProvider,
|
WifiControlAppListProvider,
|
||||||
LongBackgroundTasksAppListProvider,
|
LongBackgroundTasksAppListProvider,
|
||||||
TurnScreenOnAppsAppListProvider,
|
TurnScreenOnAppsAppListProvider,
|
||||||
|
WriteSystemPreferencesAppListProvider,
|
||||||
)
|
)
|
||||||
.map { it.buildAppListInjectEntry().setLink(fromPage = owner).build() }
|
.map { it.buildAppListInjectEntry().setLink(fromPage = owner).build() }
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.Manifest
|
||||||
|
import android.app.AppOpsManager
|
||||||
|
import android.content.Context
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settingslib.spaprivileged.model.app.AppOps
|
||||||
|
import com.android.settingslib.spaprivileged.model.app.PackageManagers
|
||||||
|
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
|
||||||
|
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
|
||||||
|
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
object WriteSystemPreferencesAppListProvider : TogglePermissionAppListProvider {
|
||||||
|
override val permissionType = "WriteSystemPreferences"
|
||||||
|
override fun createModel(context: Context) = WriteSystemPreferencesAppListModel(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
class WriteSystemPreferencesAppListModel(context: Context) : AppOpPermissionListModel(context) {
|
||||||
|
override val pageTitleResId = R.string.write_system_preferences_page_title
|
||||||
|
override val switchTitleResId = R.string.write_system_preferences_switch_title
|
||||||
|
override val footerResId = R.string.write_system_preferences_footer_description
|
||||||
|
override val appOps = AppOps(
|
||||||
|
op = AppOpsManager.OP_WRITE_SYSTEM_PREFERENCES,
|
||||||
|
setModeByUid = true,
|
||||||
|
)
|
||||||
|
override val permission = Manifest.permission.WRITE_SYSTEM_PREFERENCES
|
||||||
|
|
||||||
|
override fun filter(userIdFlow: Flow<Int>, recordListFlow: Flow<List<AppOpPermissionRecord>>):
|
||||||
|
Flow<List<AppOpPermissionRecord>> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -16,17 +16,20 @@
|
|||||||
|
|
||||||
package com.android.settings.accessibility;
|
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.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -53,12 +56,20 @@ public final class PaletteListPreferenceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void initPaletteView_success() {
|
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);
|
mPaletteListPreference.onBindViewHolder(mPreferenceViewHolder);
|
||||||
|
|
||||||
final ViewGroup viewGroup =
|
final ViewGroup viewGroup =
|
||||||
mPreferenceViewHolder.itemView.findViewById(R.id.palette_view);
|
mPreferenceViewHolder.itemView.findViewById(R.id.palette_view);
|
||||||
final int expectedCount =
|
final int childCount = viewGroup.getChildCount();
|
||||||
mContext.getResources().getStringArray(R.array.setting_palette_data).length;
|
assertThat(childCount).isEqualTo(expectedCount);
|
||||||
assertEquals(expectedCount, viewGroup.getChildCount());
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
final TextView textView = (TextView) viewGroup.getChildAt(i);
|
||||||
|
assertThat(textView.getTextColors()).isEqualTo(expectedTextColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user