diff options
author | 2024-12-05 16:49:02 -0800 | |
---|---|---|
committer | 2024-12-11 12:22:06 -0800 | |
commit | e0d6985188ceb5dc60e5ac46d66e71fb4888bb24 (patch) | |
tree | 225d9eb5dc5c254b33f42d624587054175d9d073 /PermissionController | |
parent | d63f781a4236f33f7737624005ff5e570371a4d7 (diff) |
Profile group exclusive roles setting changes
Show profile group exclusive roles in primary default app list section.
Show all users for which profile group exclusive role is available in default app screen.
LOW_COVERAGE_REASON=FLAG_NOT_ENABLED
Relnote: N/A
Flag: com.android.permission.flags.cross_user_role_enabled
Bug: 378887269
Test: atest RoleManagerTest
Test: atest RoleManagerMultiUserTest
Change-Id: Id0596f089d8cdcf13941646c547871fce679de18
Diffstat (limited to 'PermissionController')
15 files changed, 280 insertions, 48 deletions
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index 3d858a9c5..0ccd1ce1a 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -1886,6 +1886,7 @@ requestTitle="@string/role_for_testing_profile_group_exclusivity_request_title" shortLabel="@string/role_for_testing_profile_group_exclusivity_short_label" showNone="true" + uiBehavior="ReservedForTestingProfileGroupExclusivityRoleUiBehavior" visible="true"/> <!--- diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java index 91b4e1531..f02b4d90c 100644 --- a/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java +++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java @@ -18,6 +18,7 @@ package com.android.role.controller.behavior; import android.app.role.RoleManager; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.os.UserHandle; import androidx.annotation.NonNull; @@ -25,11 +26,14 @@ import androidx.annotation.Nullable; import com.android.role.controller.model.Role; import com.android.role.controller.model.RoleBehavior; +import com.android.role.controller.util.PackageUtils; import com.android.role.controller.util.RoleFlags; import com.android.role.controller.util.UserUtils; +import java.util.ArrayList; import java.util.List; +// TODO(b/383538899): make minSdk36 public class ReservedForTestingProfileGroupExclusivityRoleBehavior implements RoleBehavior { @Nullable @Override @@ -55,4 +59,31 @@ public class ReservedForTestingProfileGroupExclusivityRoleBehavior implements Ro return false; } } + + @Nullable + @Override + public List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user, + @NonNull Context context) { + if (RoleFlags.isProfileGroupExclusivityAvailable()) { + Context userContext = UserUtils.getUserContext(context, user); + RoleManager userRoleManager = userContext.getSystemService(RoleManager.class); + List<String> qualifyingPackageNames = + userRoleManager.getDefaultHoldersForTest(role.getName()); + + // When getQualifyingPackagesAsUser returns a package that isn't installed, Default App + // Settings fails to load. Only return available packages. + List<String> availableQualifyingPackageNames = new ArrayList<>(); + for (int i = 0; i < qualifyingPackageNames.size(); i++) { + String qualifyingPackage = qualifyingPackageNames.get(i); + ApplicationInfo applicationInfo = + PackageUtils.getApplicationInfoAsUser(qualifyingPackage, user, context); + if (applicationInfo != null) { + availableQualifyingPackageNames.add(qualifyingPackage); + } + } + return availableQualifyingPackageNames; + } else { + return null; + } + } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING index 46b148e68..93ad3d31b 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING +++ b/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING @@ -46,6 +46,9 @@ "postsubmit": [ { "name": "CtsRoleTestCases" + }, + { + "name": "CtsRoleMultiUserTestCases" } ], "mainline-postsubmit": [ @@ -60,6 +63,9 @@ "exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked" } ] + }, + { + "name": "CtsRoleMultiUserTestCases[com.google.android.permission.apex]" } ] } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java index 2f515f02c..400e1f162 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java @@ -69,6 +69,10 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat + ".preference.DESCRIPTION"; private static final String PREFERENCE_KEY_OTHER_NFC_SERVICES = DefaultAppChildFragment.class.getName() + ".preference.OTHER_NFC_SERVICES"; + private static final String PREFERENCE_EXTRA_PACKAGE_NAME = + DefaultAppChildFragment.class.getName() + ".extra.PACKAGE_NAME"; + private static final String PREFERENCE_EXTRA_USER = DefaultAppChildFragment.class.getName() + + ".extra.USER"; @NonNull private String mRoleName; @@ -133,7 +137,6 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat Context context = preferenceManager.getContext(); PreferenceScreen preferenceScreen = preferenceFragment.getPreferenceScreen(); - Preference oldDescriptionPreference = null; ArrayMap<String, Preference> oldPreferences = new ArrayMap<>(); if (preferenceScreen == null) { preferenceScreen = preferenceManager.createPreferenceScreen(context); @@ -162,7 +165,9 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first; boolean isHolderApplication = qualifyingApplication.second; - String key = qualifyingApplicationInfo.packageName; + int userId = + UserHandle.getUserHandleForUid(qualifyingApplicationInfo.uid).getIdentifier(); + String key = qualifyingApplicationInfo.packageName + "@" + userId; Drawable icon = Utils.getBadgedIcon(context, qualifyingApplicationInfo); String title = Utils.getFullAppLabel(qualifyingApplicationInfo, context); addPreference(key, icon, title, isHolderApplication, qualifyingApplicationInfo, @@ -205,6 +210,16 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat preference.setPersistent(false); preference.setOnPreferenceChangeListener((preference2, newValue) -> false); preference.setOnPreferenceClickListener(this); + // In the cases we need this (see #onPreferenceClick()), this should never be null. + // This method (addPreference) is used for both legitimate apps and the `NONE` item, + // the `NONE` item passes a null applicationinfo object. NFC uses a different preference + // method for adding, and a different onclick method + if (applicationInfo != null) { + Bundle extras = preference.getExtras(); + extras.putString(PREFERENCE_EXTRA_PACKAGE_NAME, applicationInfo.packageName); + extras.putParcelable(PREFERENCE_EXTRA_USER, + UserHandle.getUserHandleForUid(applicationInfo.uid)); + } } else { preference = roleApplicationPreference.asTwoStatePreference(); } @@ -243,22 +258,26 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat if (Objects.equals(key, PREFERENCE_KEY_NONE)) { mViewModel.setNoneDefaultApp(); } else { - String packageName = key; + String packageName = + preference.getExtras().getString(PREFERENCE_EXTRA_PACKAGE_NAME); + UserHandle user = + preference.getExtras().getParcelable(PREFERENCE_EXTRA_USER); CharSequence confirmationMessage = RoleUiBehaviorUtils.getConfirmationMessage(mRole, packageName, requireContext()); if (confirmationMessage != null) { - DefaultAppConfirmationDialogFragment.show(packageName, confirmationMessage, this); + DefaultAppConfirmationDialogFragment.show(packageName, user, confirmationMessage, + this); } else { - setDefaultApp(packageName); + setDefaultApp(packageName, user); } } return true; } @Override - public void setDefaultApp(@NonNull String packageName) { - mViewModel.setDefaultApp(packageName); + public void setDefaultApp(@NonNull String packageName, @NonNull UserHandle user) { + mViewModel.setDefaultApp(packageName, user); } private void addNonPaymentNfcServicesPreference(@NonNull PreferenceScreen preferenceScreen, diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java index 843854bf4..5f399a0b8 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java @@ -20,9 +20,11 @@ import android.app.AlertDialog; import android.app.Dialog; import android.content.Intent; import android.os.Bundle; +import android.os.UserHandle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.os.BundleCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; @@ -32,24 +34,27 @@ import androidx.fragment.app.Fragment; public class DefaultAppConfirmationDialogFragment extends DialogFragment { private String mPackageName; + private UserHandle mUser; private CharSequence mMessage; /** * Create a new instance of this fragment. * * @param packageName the package name of the application + * @param user the user the specified package is running in * @param message the confirmation message * * @return a new instance of this fragment * - * @see #show(String, CharSequence, Fragment) + * @see #show(String, UserHandle, CharSequence, Fragment) */ @NonNull public static DefaultAppConfirmationDialogFragment newInstance(@NonNull String packageName, - @NonNull CharSequence message) { + @NonNull UserHandle user, @NonNull CharSequence message) { DefaultAppConfirmationDialogFragment fragment = new DefaultAppConfirmationDialogFragment(); Bundle arguments = new Bundle(); arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); + arguments.putParcelable(Intent.EXTRA_USER, user); arguments.putCharSequence(Intent.EXTRA_TEXT, message); fragment.setArguments(arguments); return fragment; @@ -59,14 +64,15 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment { * Show a new instance of this fragment. * * @param packageName the package name of the application + * @param user the user the specified package is running in * @param message the confirmation message * @param fragment the parent fragment * - * @see #newInstance(String, CharSequence) + * @see #newInstance(String, UserHandle, CharSequence) */ - public static void show(@NonNull String packageName, @NonNull CharSequence message, - @NonNull Fragment fragment) { - newInstance(packageName, message).show(fragment.getChildFragmentManager(), null); + public static void show(@NonNull String packageName, @NonNull UserHandle user, + @NonNull CharSequence message, @NonNull Fragment fragment) { + newInstance(packageName, user, message).show(fragment.getChildFragmentManager(), null); } @Override @@ -75,6 +81,7 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment { Bundle arguments = getArguments(); mPackageName = arguments.getString(Intent.EXTRA_PACKAGE_NAME); + mUser = BundleCompat.getParcelable(arguments, Intent.EXTRA_USER, UserHandle.class); mMessage = arguments.getCharSequence(Intent.EXTRA_TEXT); } @@ -90,7 +97,7 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment { private void onOk() { Listener listener = (Listener) getParentFragment(); - listener.setDefaultApp(mPackageName); + listener.setDefaultApp(mPackageName, mUser); } /** @@ -103,6 +110,6 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment { * * @param packageName the package name of the application */ - void setDefaultApp(@NonNull String packageName); + void setDefaultApp(@NonNull String packageName, @NonNull UserHandle user); } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java index 5bc25df54..82253ed00 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java @@ -30,8 +30,11 @@ import androidx.lifecycle.ViewModel; import com.android.permissioncontroller.permission.utils.Utils; import com.android.permissioncontroller.role.utils.UserUtils; +import com.android.role.controller.model.Role; +import com.android.role.controller.util.RoleFlags; import java.util.List; +import java.util.function.Predicate; /** * {@link ViewModel} for the list of default apps. @@ -55,12 +58,34 @@ public class DefaultAppListViewModel extends AndroidViewModel { super(application); mUser = Process.myUserHandle(); + RoleListLiveData liveData = new RoleListLiveData(true, mUser, application); RoleListSortFunction sortFunction = new RoleListSortFunction(application); - mLiveData = Transformations.map(new RoleListLiveData(true, mUser, application), - sortFunction); mWorkProfile = UserUtils.getWorkProfile(application); - mWorkLiveData = mWorkProfile != null ? Transformations.map(new RoleListLiveData(true, - mWorkProfile, application), sortFunction) : null; + if (RoleFlags.isProfileGroupExclusivityAvailable()) { + if (mWorkProfile != null) { + // Show profile group exclusive roles from work profile in primary group. + RoleListLiveData workLiveData = + new RoleListLiveData(true, mWorkProfile, application); + Predicate<RoleItem> exclusivityPredicate = roleItem -> + roleItem.getRole().getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP; + mLiveData = Transformations.map( + new MergeRoleListLiveData(liveData, + Transformations.map(workLiveData, + new RoleListFilterFunction(exclusivityPredicate))), + sortFunction); + mWorkLiveData = Transformations.map( + Transformations.map(workLiveData, + new RoleListFilterFunction(exclusivityPredicate.negate())), + sortFunction); + } else { + mLiveData = Transformations.map(liveData, sortFunction); + mWorkLiveData = null; + } + } else { + mLiveData = Transformations.map(liveData, sortFunction); + mWorkLiveData = mWorkProfile != null ? Transformations.map( + new RoleListLiveData(true, mWorkProfile, application), sortFunction) : null; + } UserHandle privateProfile = UserUtils.getPrivateProfile(application); if (privateProfile != null && Utils.shouldShowInSettings( diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java index c89e1f71e..c982f44c6 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java @@ -30,6 +30,7 @@ import androidx.lifecycle.Transformations; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import com.android.permissioncontroller.role.utils.UserUtils; import com.android.role.controller.model.Role; import java.util.List; @@ -58,10 +59,23 @@ public class DefaultAppViewModel extends AndroidViewModel { super(application); mRole = role; - mUser = user; - - mRoleLiveData = Transformations.map(new RoleLiveData(mRole, mUser, application), - new RoleSortFunction(application)); + mUser = mRole.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP + ? UserUtils.getProfileParentOrSelf(user, application) + : user; + RoleLiveData liveData = new RoleLiveData(mRole, mUser, application); + RoleSortFunction sortFunction = new RoleSortFunction(application); + if (mRole.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP) { + UserHandle workProfile = UserUtils.getWorkProfile(application); + if (workProfile != null) { + RoleLiveData workLiveData = new RoleLiveData(role, workProfile, application); + mRoleLiveData = Transformations.map(new MergeRoleLiveData(liveData, workLiveData), + sortFunction); + } else { + mRoleLiveData = Transformations.map(liveData, sortFunction); + } + } else { + mRoleLiveData = Transformations.map(liveData, sortFunction); + } } @NonNull @@ -79,13 +93,13 @@ public class DefaultAppViewModel extends AndroidViewModel { * * @param packageName the package name of the application */ - public void setDefaultApp(@NonNull String packageName) { + public void setDefaultApp(@NonNull String packageName, @NonNull UserHandle user) { if (mManageRoleHolderStateLiveData.getValue() != ManageRoleHolderStateLiveData.STATE_IDLE) { Log.i(LOG_TAG, "Trying to set default app while another request is on-going"); return; } mManageRoleHolderStateLiveData.setRoleHolderAsUser(mRole.getName(), packageName, true, 0, - mUser, getApplication()); + user, getApplication()); } /** diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/MergeRoleListLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleListLiveData.java index 0318800f4..0c2d96b2c 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/MergeRoleListLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleListLiveData.java @@ -14,16 +14,14 @@ * limitations under the License. */ -package com.android.permissioncontroller.role.ui.specialappaccess; +package com.android.permissioncontroller.role.ui; import android.util.ArrayMap; import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; import androidx.lifecycle.MediatorLiveData; -import com.android.permissioncontroller.role.ui.RoleItem; -import com.android.permissioncontroller.role.ui.RoleListLiveData; - import java.util.ArrayList; import java.util.List; @@ -33,14 +31,14 @@ import java.util.List; public class MergeRoleListLiveData extends MediatorLiveData<List<RoleItem>> { @NonNull - private final RoleListLiveData[] mLiveDatas; + private final LiveData<List<RoleItem>>[] mLiveDatas; - public MergeRoleListLiveData(@NonNull RoleListLiveData... liveDatas) { + public MergeRoleListLiveData(@NonNull LiveData<List<RoleItem>>... liveDatas) { mLiveDatas = liveDatas; int liveDatasLength = mLiveDatas.length; for (int i = 0; i < liveDatasLength; i++) { - RoleListLiveData liveData = mLiveDatas[i]; + LiveData<List<RoleItem>> liveData = mLiveDatas[i]; addSource(liveData, roleItems -> onRoleListChanged()); } @@ -50,7 +48,7 @@ public class MergeRoleListLiveData extends MediatorLiveData<List<RoleItem>> { ArrayMap<String, RoleItem> mergedRoleItemMap = new ArrayMap<>(); int liveDatasLength = mLiveDatas.length; for (int liveDatasIndex = 0; liveDatasIndex < liveDatasLength; liveDatasIndex++) { - RoleListLiveData liveData = mLiveDatas[liveDatasIndex]; + LiveData<List<RoleItem>> liveData = mLiveDatas[liveDatasIndex]; List<RoleItem> roleItems = liveData.getValue(); if (roleItems == null) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/MergeRoleLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java index dab59a1ab..31a02729a 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/MergeRoleLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.permissioncontroller.role.ui.specialappaccess; +package com.android.permissioncontroller.role.ui; import android.content.pm.ApplicationInfo; import android.util.Pair; @@ -22,8 +22,6 @@ import android.util.Pair; import androidx.annotation.NonNull; import androidx.lifecycle.MediatorLiveData; -import com.android.permissioncontroller.role.ui.RoleLiveData; - import java.util.ArrayList; import java.util.List; diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java new file mode 100644 index 000000000..b84fa80b9 --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java @@ -0,0 +1,53 @@ +/* + * 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.permissioncontroller.role.ui; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import kotlin.jvm.functions.Function1; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +/** + * A function for {@link androidx.lifecycle#map(androidx.lifecycle.LiveData, Function1)} + * that filters a live data for role list. + */ +public class RoleListFilterFunction implements Function1<List<RoleItem>, List<RoleItem>> { + private final Predicate<RoleItem> mPredicate; + + public RoleListFilterFunction(@NonNull Predicate<RoleItem> predicate) { + mPredicate = predicate; + } + + @NonNull + @Override + public List<RoleItem> invoke(@Nullable List<RoleItem> roleItems) { + List<RoleItem> filteredRoleItems = new ArrayList<>(); + if (roleItems != null) { + int roleItemsSize = roleItems.size(); + for (int i = 0; i < roleItemsSize; i++) { + RoleItem roleItem = roleItems.get(i); + if (mPredicate.test(roleItem)) { + filteredRoleItems.add(roleItem); + } + } + } + return filteredRoleItems; + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/ReservedForTestingProfileGroupExclusivityRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/ReservedForTestingProfileGroupExclusivityRoleUiBehavior.java new file mode 100644 index 000000000..abc89edab --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/ReservedForTestingProfileGroupExclusivityRoleUiBehavior.java @@ -0,0 +1,63 @@ +/* + * 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.permissioncontroller.role.ui.behavior; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.os.UserHandle; + +import androidx.annotation.NonNull; +import androidx.preference.Preference; + +import com.android.permissioncontroller.permission.utils.Utils; +import com.android.permissioncontroller.role.ui.TwoTargetPreference; +import com.android.role.controller.model.Role; +import com.android.role.controller.util.UserUtils; + +import java.util.List; + +public class ReservedForTestingProfileGroupExclusivityRoleUiBehavior implements RoleUiBehavior { + @Override + public void preparePreferenceAsUser(@NonNull Role role, @NonNull TwoTargetPreference preference, + @NonNull List<ApplicationInfo> applicationInfos, @NonNull UserHandle user, + @NonNull Context context) { + Context userContext = UserUtils.getUserContext(context, user); + if (!applicationInfos.isEmpty()) { + preparePreferenceInternal(preference.asPreference(), applicationInfos.get(0), + false, userContext); + } + } + + @Override + public void prepareApplicationPreferenceAsUser(@NonNull Role role, + @NonNull Preference preference, @NonNull ApplicationInfo applicationInfo, + @NonNull UserHandle user, @NonNull Context context) { + Context userContext = UserUtils.getUserContext(context, user); + preparePreferenceInternal(preference, applicationInfo, true, userContext); + } + + private void preparePreferenceInternal(@NonNull Preference preference, + @NonNull ApplicationInfo applicationInfo, boolean setTitle, @NonNull Context context) { + String title = Utils.getFullAppLabel(applicationInfo, context) + "@" + + UserHandle.getUserHandleForUid(applicationInfo.uid).getIdentifier(); + if (setTitle) { + preference.setTitle(title); + } else { + preference.setSummary(title); + } + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListViewModel.java index ee5a0dbbd..e96fb0943 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListViewModel.java @@ -26,6 +26,7 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.Transformations; import androidx.lifecycle.ViewModel; +import com.android.permissioncontroller.role.ui.MergeRoleListLiveData; import com.android.permissioncontroller.role.ui.RoleItem; import com.android.permissioncontroller.role.ui.RoleListLiveData; import com.android.permissioncontroller.role.ui.RoleListSortFunction; diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java index 0cc00abc1..c12265d43 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java @@ -33,6 +33,7 @@ import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData; +import com.android.permissioncontroller.role.ui.MergeRoleLiveData; import com.android.permissioncontroller.role.ui.RoleLiveData; import com.android.permissioncontroller.role.ui.RoleSortFunction; import com.android.permissioncontroller.role.utils.UserUtils; diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt index a47719cf7..610745674 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt @@ -34,7 +34,7 @@ class WearDefaultAppHelper( val user: UserHandle, val role: Role, val viewModel: DefaultAppViewModel, - val confirmDialogViewModel: DefaultAppConfirmDialogViewModel + val confirmDialogViewModel: DefaultAppConfirmDialogViewModel, ) { fun getTitle() = context.getString(role.labelResource) @@ -46,7 +46,7 @@ class WearDefaultAppHelper( context = context, defaultLabel = context.getString(R.string.default_app_none), checked = !hasHolderApplication(qualifyingApplications), - onDefaultCheckChanged = { _ -> viewModel.setNoneDefaultApp() } + onDefaultCheckChanged = { _ -> viewModel.setNoneDefaultApp() }, ) .apply { icon = context.getDrawable(R.drawable.ic_remove_circle) } } else { @@ -67,19 +67,24 @@ class WearDefaultAppHelper( onDefaultCheckChanged = { _ -> run { val packageName = appInfo.packageName + val user = UserHandle.getUserHandleForUid(appInfo.uid) val confirmationMessage = RoleUiBehaviorUtils.getConfirmationMessage( role, packageName, - context + context, ) if (confirmationMessage != null) { - showConfirmDialog(packageName, confirmationMessage.toString()) + showConfirmDialog( + packageName, + user, + confirmationMessage.toString(), + ) } else { - setDefaultApp(packageName) + setDefaultApp(packageName, user) } } - } + }, ) .apply { icon = appInfo.loadIcon(context.packageManager) @@ -91,22 +96,22 @@ class WearDefaultAppHelper( this, appInfo, user, - context + context, ) } } .toList() } - private fun showConfirmDialog(packageName: String, message: String) { + private fun showConfirmDialog(packageName: String, userHandle: UserHandle, message: String) { confirmDialogViewModel.confirmDialogArgs = ConfirmDialogArgs( message = message, onOkButtonClick = { - setDefaultApp(packageName) + setDefaultApp(packageName, userHandle) dismissConfirmDialog() }, - onCancelButtonClick = { dismissConfirmDialog() } + onCancelButtonClick = { dismissConfirmDialog() }, ) confirmDialogViewModel.showConfirmDialogLiveData.value = true } @@ -116,8 +121,8 @@ class WearDefaultAppHelper( confirmDialogViewModel.showConfirmDialogLiveData.value = false } - private fun setDefaultApp(packageName: String) { - viewModel.setDefaultApp(packageName) + private fun setDefaultApp(packageName: String, user: UserHandle) { + viewModel.setDefaultApp(packageName, user) } fun getDescription() = context.getString(role.descriptionResource) diff --git a/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java b/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java index 339b2a12a..f3ae21578 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java +++ b/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java @@ -37,6 +37,16 @@ public class UserUtils { private UserUtils() {} /** + * Returns the parent of a given user, or user if it has no parent (e.g. it is the primary + * user) + */ + @NonNull + public static UserHandle getProfileParentOrSelf(@NonNull UserHandle user, + @NonNull Context context) { + return com.android.role.controller.util.UserUtils.getProfileParentOrSelf(user, context); + } + + /** * Get the work profile of current user, if any. * * @param context the {@code Context} to retrieve system services |