From b25f034ab782e6bae168b1f8ee276206ef9fbdf8 Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Sat, 1 Feb 2025 18:59:07 -0800 Subject: Refactor default app implementation So that it can better accommodate new features. Default holders logic is extracted into SignedPackage(Utils) for reuse, a RoleApplicationItem is added to replace the previous Pair, the LiveData transformation functions are made generic, and DefaultAppChildFragment preference code is also refactored to be more reusable. Bug: 388234667 Relnote: N/A Flag: EXEMPT bugfix Test: presubmit Change-Id: I3285e868c6d7457dfd42bbe12c741e5cae2f78f5 --- .../role/ui/DefaultAppChildFragment.java | 109 ++++++++++++--------- .../role/ui/DefaultAppListChildFragment.java | 27 +++-- .../role/ui/DefaultAppListViewModel.java | 6 +- .../role/ui/DefaultAppViewModel.java | 20 ++-- .../role/ui/ListLiveDataFilterFunction.java | 57 +++++++++++ .../role/ui/ListLiveDataSortFunction.java | 49 +++++++++ .../role/ui/MergeRoleLiveData.java | 17 ++-- .../role/ui/RequestRoleFragment.java | 92 ++++++++--------- .../role/ui/RoleApplicationItem.java | 53 ++++++++++ .../role/ui/RoleListFilterFunction.java | 53 ---------- .../role/ui/RoleListSortFunction.java | 25 ++--- .../permissioncontroller/role/ui/RoleLiveData.java | 12 +-- .../role/ui/RoleSortFunction.java | 34 +++---- .../SpecialAppAccessChildFragment.java | 37 ++++--- .../SpecialAppAccessViewModel.java | 13 ++- .../role/ui/wear/WearDefaultAppHelper.kt | 22 ++--- .../role/ui/wear/WearDefaultAppScreen.kt | 11 +-- .../role/ui/wear/WearRequestRoleFragment.kt | 20 ++-- .../role/ui/wear/WearRequestRoleHelper.kt | 37 ++++--- .../role/ui/wear/WearRequestRoleScreen.kt | 11 +-- 20 files changed, 393 insertions(+), 312 deletions(-) create mode 100644 PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataFilterFunction.java create mode 100644 PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataSortFunction.java create mode 100644 PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationItem.java delete mode 100644 PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java (limited to 'PermissionController/src') diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java index 61e33d10b..5f870b1e3 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java @@ -25,7 +25,6 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; import android.util.ArrayMap; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -34,6 +33,7 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.preference.TwoStatePreference; @@ -125,13 +125,17 @@ public class DefaultAppChildFragment onApplicationListChanged()); mViewModel.getManageRoleHolderStateLiveData().observe(this, this::onManageRoleHolderStateChanged); } - private void onRoleChanged( - @NonNull List> qualifyingApplications) { + private void onApplicationListChanged() { + List applicationItems = mViewModel.getLiveData().getValue(); + if (applicationItems == null) { + return; + } + PF preferenceFragment = requirePreferenceFragment(); PreferenceManager preferenceManager = preferenceFragment.getPreferenceManager(); Context context = preferenceManager.getContext(); @@ -142,37 +146,12 @@ public class DefaultAppChildFragment= 0; --i) { - Preference preference = preferenceScreen.getPreference(i); - - preferenceScreen.removePreference(preference); - preference.setOrder(Preference.DEFAULT_ORDER); - oldPreferences.put(preference.getKey(), preference); - } + clearPreferences(preferenceScreen, oldPreferences); } - if (mRole.shouldShowNone()) { - Drawable icon = AppCompatResources.getDrawable(context, R.drawable.ic_remove_circle); - String title = getString(R.string.default_app_none); - boolean noHolderApplication = !hasHolderApplication(qualifyingApplications); - addPreference(PREFERENCE_KEY_NONE, icon, title, noHolderApplication, null, - oldPreferences, preferenceScreen, context); - } - - int qualifyingApplicationsSize = qualifyingApplications.size(); - for (int i = 0; i < qualifyingApplicationsSize; i++) { - Pair qualifyingApplication = qualifyingApplications.get(i); - ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first; - boolean isHolderApplication = qualifyingApplication.second; - - 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, - oldPreferences, preferenceScreen, context); - } + boolean noneChecked = !hasHolderApplication(applicationItems); + addNonePreferenceIfNeeded(preferenceScreen, noneChecked, oldPreferences, context); + addApplicationPreferences(preferenceScreen, applicationItems, oldPreferences, context); addNonPaymentNfcServicesPreference(preferenceScreen, oldPreferences, context); addDescriptionPreference(preferenceScreen, oldPreferences); @@ -180,24 +159,64 @@ public class DefaultAppChildFragment> qualifyingApplications) { - int qualifyingApplicationsSize = qualifyingApplications.size(); - for (int i = 0; i < qualifyingApplicationsSize; i++) { - Pair qualifyingApplication = qualifyingApplications.get(i); - boolean isHolderApplication = qualifyingApplication.second; + private static void clearPreferences(@NonNull PreferenceGroup preferenceGroup, + @NonNull ArrayMap oldPreferences) { + for (int i = preferenceGroup.getPreferenceCount() - 1; i >= 0; --i) { + Preference preference = preferenceGroup.getPreference(i); + + preferenceGroup.removePreference(preference); + preference.setOrder(Preference.DEFAULT_ORDER); + oldPreferences.put(preference.getKey(), preference); + } + } - if (isHolderApplication) { + private static boolean hasHolderApplication( + @NonNull List applicationItems) { + int applicationItemsSize = applicationItems.size(); + for (int i = 0; i < applicationItemsSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + if (applicationItem.isHolderApplication()) { return true; } } return false; } - private void addPreference(@NonNull String key, @NonNull Drawable icon, - @NonNull CharSequence title, boolean checked, @Nullable ApplicationInfo applicationInfo, - @NonNull ArrayMap oldPreferences, - @NonNull PreferenceScreen preferenceScreen, @NonNull Context context) { + private void addNonePreferenceIfNeeded(@NonNull PreferenceGroup preferenceGroup, + boolean checked, @NonNull ArrayMap oldPreferences, + @NonNull Context context) { + if (!mRole.shouldShowNone()) { + return; + } + + Drawable icon = AppCompatResources.getDrawable(context, R.drawable.ic_remove_circle); + String title = getString(R.string.default_app_none); + addApplicationPreference(preferenceGroup, PREFERENCE_KEY_NONE, icon, title, checked, null, + oldPreferences, context); + } + + private void addApplicationPreferences(@NonNull PreferenceGroup preferenceGroup, + @NonNull List applicationItems, + @NonNull ArrayMap oldPreferences, @NonNull Context context) { + int applicationItemsSize = applicationItems.size(); + for (int i = 0; i < applicationItemsSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); + int userId = UserHandle.getUserHandleForUid(applicationInfo.uid).getIdentifier(); + String key = applicationInfo.packageName + "@" + userId; + Drawable icon = Utils.getBadgedIcon(context, applicationInfo); + String title = Utils.getFullAppLabel(applicationInfo, context); + boolean isHolderApplication = applicationItem.isHolderApplication(); + + addApplicationPreference(preferenceGroup, key, icon, title, isHolderApplication, + applicationInfo, oldPreferences, context); + } + } + + private void addApplicationPreference(@NonNull PreferenceGroup preferenceGroup, + @NonNull String key, @NonNull Drawable icon, @NonNull CharSequence title, + boolean checked, @Nullable ApplicationInfo applicationInfo, + @NonNull ArrayMap oldPreferences, @NonNull Context context) { RoleApplicationPreference roleApplicationPreference = (RoleApplicationPreference) oldPreferences.get(key); TwoStatePreference preference; @@ -233,7 +252,7 @@ public class DefaultAppChildFragment oldPreferences) { if (preferenceCategory == null) { return; } clearPreferences(preferenceCategory, oldPreferences); - preferenceScreen.removePreference(preferenceCategory); + preferenceCategory.getParent().removePreference(preferenceCategory); preferenceCategory.setOrder(Preference.DEFAULT_ORDER); } @@ -197,7 +195,7 @@ public class DefaultAppListChildFragment roleItems, @NonNull ArrayMap oldPreferences, @@ -210,11 +208,10 @@ public class DefaultAppListChildFragment roleItems, @NonNull ArrayMap oldPreferences, @NonNull Preference.OnPreferenceClickListener listener, @NonNull UserHandle user, @NonNull Context context) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java index 718af090e..4a280bd58 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java @@ -78,11 +78,11 @@ public class DefaultAppListViewModel extends AndroidViewModel { mLiveData = Transformations.map( new MergeRoleListLiveData(liveData, Transformations.map(workLiveData, - new RoleListFilterFunction(exclusivityPredicate))), + new ListLiveDataFilterFunction<>(exclusivityPredicate))), sortFunction); mWorkLiveData = Transformations.map( Transformations.map(workLiveData, - new RoleListFilterFunction(exclusivityPredicate.negate())), + new ListLiveDataFilterFunction<>(exclusivityPredicate.negate())), sortFunction); } else if (Flags.crossUserRoleUxBugfixEnabled() && isWorkProfile) { // Show profile group exclusive roles from the profile parent (full user) in primary @@ -92,7 +92,7 @@ public class DefaultAppListViewModel extends AndroidViewModel { mLiveData = Transformations.map( new MergeRoleListLiveData(liveData, Transformations.map(profileParentLiveData, - new RoleListFilterFunction(exclusivityPredicate))), + new ListLiveDataFilterFunction<>(exclusivityPredicate))), sortFunction); mWorkLiveData = null; } else { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java index cdee94b13..790c55d84 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java @@ -18,10 +18,8 @@ package com.android.permissioncontroller.role.ui; import android.app.Application; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.os.UserHandle; import android.util.Log; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; @@ -48,7 +46,7 @@ public class DefaultAppViewModel extends AndroidViewModel { private final UserHandle mUser; @NonNull - private final LiveData>> mRoleLiveData; + private final LiveData> mLiveData; @NonNull private final ManageRoleHolderStateLiveData mManageRoleHolderStateLiveData = @@ -60,30 +58,30 @@ public class DefaultAppViewModel extends AndroidViewModel { mRole = role; // If EXCLUSIVITY_PROFILE_GROUP this user should be profile parent - mUser = mRole.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP + mUser = role.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP ? UserUtils.getProfileParentOrSelf(user, application) : user; - RoleLiveData liveData = new RoleLiveData(mRole, mUser, application); + RoleLiveData liveData = new RoleLiveData(role, mUser, application); RoleSortFunction sortFunction = new RoleSortFunction(application); - if (mRole.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP) { + if (role.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP) { // Context user might be work profile, ensure we get a non-null UserHandle if work // profile exists. getWorkProfile returns null if context user is work profile. UserHandle workProfile = UserUtils.getWorkProfileOrSelf(application); if (workProfile != null) { RoleLiveData workLiveData = new RoleLiveData(role, workProfile, application); - mRoleLiveData = Transformations.map(new MergeRoleLiveData(liveData, workLiveData), + mLiveData = Transformations.map(new MergeRoleLiveData(liveData, workLiveData), sortFunction); } else { - mRoleLiveData = Transformations.map(liveData, sortFunction); + mLiveData = Transformations.map(liveData, sortFunction); } } else { - mRoleLiveData = Transformations.map(liveData, sortFunction); + mLiveData = Transformations.map(liveData, sortFunction); } } @NonNull - public LiveData>> getRoleLiveData() { - return mRoleLiveData; + public LiveData> getLiveData() { + return mLiveData; } @NonNull diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataFilterFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataFilterFunction.java new file mode 100644 index 000000000..8657db0ab --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataFilterFunction.java @@ -0,0 +1,57 @@ +/* + * 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.Transformations#map(androidx.lifecycle.LiveData, Function1)} + * that filters a live data for a list. + * + * @param the type of the list elements + */ +public class ListLiveDataFilterFunction implements Function1, List> { + private final Predicate mPredicate; + + public ListLiveDataFilterFunction(@NonNull Predicate predicate) { + mPredicate = predicate; + } + + @NonNull + @Override + public List invoke(@Nullable List items) { + List filteredItems = new ArrayList<>(); + if (items != null) { + int itemsSize = items.size(); + for (int i = 0; i < itemsSize; i++) { + T item = items.get(i); + if (mPredicate.test(item)) { + filteredItems.add(item); + } + } + } + return filteredItems; + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataSortFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataSortFunction.java new file mode 100644 index 000000000..36e7afcc8 --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataSortFunction.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2025 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 kotlin.jvm.functions.Function1; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * A function for + * {@link androidx.lifecycle.Transformations#map(androidx.lifecycle.LiveData, Function1)} + * that sorts a live data for a list. + * + * @param the type of the list elements + */ +public class ListLiveDataSortFunction implements Function1, List> { + + @NonNull + private final Comparator mComparator; + + public ListLiveDataSortFunction(@NonNull Comparator comparator) { + mComparator = comparator; + } + + @Override + public List invoke(List items) { + List sortedItems = new ArrayList<>(items); + sortedItems.sort(mComparator); + return sortedItems; + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java index 31a02729a..72c2264ce 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java @@ -16,9 +16,6 @@ package com.android.permissioncontroller.role.ui; -import android.content.pm.ApplicationInfo; -import android.util.Pair; - import androidx.annotation.NonNull; import androidx.lifecycle.MediatorLiveData; @@ -28,7 +25,7 @@ import java.util.List; /** * {@link MediatorLiveData} that merges multiple {@link RoleLiveData} instances. */ -public class MergeRoleLiveData extends MediatorLiveData>> { +public class MergeRoleLiveData extends MediatorLiveData> { @NonNull private final RoleLiveData[] mLiveDatas; @@ -40,23 +37,23 @@ public class MergeRoleLiveData extends MediatorLiveData onRoleChanged()); + addSource(liveData, items -> onRoleChanged()); } } private void onRoleChanged() { - List> mergedQualifyingApplications = new ArrayList<>(); + List mergedItems = new ArrayList<>(); int liveDatasLength = mLiveDatas.length; for (int i = 0; i < liveDatasLength; i++) { RoleLiveData liveData = mLiveDatas[i]; - List> qualifyingApplications = liveData.getValue(); - if (qualifyingApplications == null) { + List items = liveData.getValue(); + if (items == null) { return; } - mergedQualifyingApplications.addAll(qualifyingApplications); + mergedItems.addAll(items); } - setValue(mergedQualifyingApplications); + setValue(mergedItems); } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java index 60139f0c8..f411b0cd0 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java @@ -30,7 +30,6 @@ import android.os.Process; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; -import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -236,7 +235,7 @@ public class RequestRoleFragment extends DialogFragment { ViewModelProvider.Factory viewModelFactory = new RequestRoleViewModel.Factory(mRole, requireActivity().getApplication()); mViewModel = new ViewModelProvider(this, viewModelFactory).get(RequestRoleViewModel.class); - mViewModel.getRoleLiveData().observe(this, this::onRoleDataChanged); + mViewModel.getLiveData().observe(this, this::onApplicationListChanged); mViewModel.getManageRoleHolderStateLiveData().observe(this, this::onManageRoleHolderStateChanged); } @@ -272,9 +271,9 @@ public class RequestRoleFragment extends DialogFragment { setDeniedOnceAndFinish(); } - private void onRoleDataChanged( - @NonNull List> qualifyingApplications) { - mAdapter.replace(qualifyingApplications); + private void onApplicationListChanged( + @NonNull List applicationItems) { + mAdapter.replace(applicationItems); updateUi(); } @@ -364,8 +363,8 @@ public class RequestRoleFragment extends DialogFragment { boolean dontAskAgain = mDontAskAgainCheck != null && mDontAskAgainCheck.isChecked(); mAdapter.setDontAskAgain(dontAskAgain); AlertDialog dialog = getDialog(); - boolean hasRoleData = mViewModel.getRoleLiveData().getValue() != null; - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled && hasRoleData + boolean hasApplicationList = mViewModel.getLiveData().getValue() != null; + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled && hasApplicationList && (dontAskAgain || !mAdapter.isHolderApplicationChecked())); dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(enabled); } @@ -420,12 +419,12 @@ public class RequestRoleFragment extends DialogFragment { } int count = mAdapter.getCount(); for (int i = 0; i < count; i++) { - Pair qualifyingApplication = mAdapter.getItem(i); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = mAdapter.getItem(i); + if (applicationItem == null) { // Skip the "None" item. continue; } - ApplicationInfo applicationInfo = qualifyingApplication.first; + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); if (Objects.equals(UserPackage.from(applicationInfo), userPackage)) { return applicationInfo.uid; } @@ -493,8 +492,7 @@ public class RequestRoleFragment extends DialogFragment { // We'll use a null to represent the "None" item. @NonNull - private final List> mQualifyingApplications = - new ArrayList<>(); + private final List mApplicationItems = new ArrayList<>(); @Nullable private UserPackage mHolderUserPackage; @@ -546,12 +544,12 @@ public class RequestRoleFragment extends DialogFragment { } public void onItemClicked(int position) { - Pair qualifyingApplication = getItem(position); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = getItem(position); + if (applicationItem == null) { mUserChecked = true; mCheckedUserPackage = null; } else { - ApplicationInfo applicationInfo = qualifyingApplication.first; + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); UserHandle user = UserHandle.getUserHandleForUid(applicationInfo.uid); Intent restrictionIntent = mRole.getApplicationRestrictionIntentAsUser( applicationInfo, user, mListView.getContext()); @@ -566,24 +564,24 @@ public class RequestRoleFragment extends DialogFragment { notifyDataSetChanged(); } - public void replace(@NonNull List> qualifyingApplications) { - mQualifyingApplications.clear(); + public void replace(@NonNull List applicationItems) { + mApplicationItems.clear(); if (mRole.shouldShowNone()) { - mQualifyingApplications.add(0, null); + mApplicationItems.add(0, null); } - mQualifyingApplications.addAll(qualifyingApplications); - mHolderUserPackage = getHolderUserPackage(qualifyingApplications); + mApplicationItems.addAll(applicationItems); + mHolderUserPackage = getHolderUserPackage(applicationItems); if (mUserChecked && mCheckedUserPackage != null) { boolean isCheckedPackageNameFound = false; int count = getCount(); for (int i = 0; i < count; i++) { - Pair qualifyingApplication = getItem(i); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = getItem(i); + if (applicationItem == null) { continue; } - ApplicationInfo applicationInfo = qualifyingApplication.first; - UserPackage userPackage = UserPackage.from(applicationInfo); + UserPackage userPackage = + UserPackage.from(applicationItem.getApplicationInfo()); if (Objects.equals(userPackage, mCheckedUserPackage)) { mUserChecked = true; @@ -606,19 +604,15 @@ public class RequestRoleFragment extends DialogFragment { @Nullable private static UserPackage getHolderUserPackage( - @NonNull List> qualifyingApplications) { - int qualifyingApplicationSize = qualifyingApplications.size(); - for (int i = 0; i < qualifyingApplicationSize; i++) { - Pair qualifyingApplication = qualifyingApplications.get( - i); - if (qualifyingApplication == null) { + @NonNull List applicationItems) { + int applicationItemSize = applicationItems.size(); + for (int i = 0; i < applicationItemSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + if (applicationItem == null) { continue; } - ApplicationInfo applicationInfo = qualifyingApplication.first; - boolean isHolderApplication = qualifyingApplication.second; - - if (isHolderApplication) { - return UserPackage.from(applicationInfo); + if (applicationItem.isHolderApplication()) { + return UserPackage.from(applicationItem.getApplicationInfo()); } } return null; @@ -645,13 +639,13 @@ public class RequestRoleFragment extends DialogFragment { @Override public int getCount() { - return mQualifyingApplications.size(); + return mApplicationItems.size(); } @Nullable @Override - public Pair getItem(int position) { - return mQualifyingApplications.get(position); + public RoleApplicationItem getItem(int position) { + return mApplicationItems.get(position); } @Override @@ -660,9 +654,9 @@ public class RequestRoleFragment extends DialogFragment { // Work around AbsListView.confirmCheckedPositionsById() not respecting our count. return ListView.INVALID_ROW_ID; } - Pair qualifyingApplication = getItem(position); - return qualifyingApplication == null ? 0 - : qualifyingApplication.first.packageName.hashCode(); + RoleApplicationItem applicationItem = getItem(position); + return applicationItem == null ? 0 + : applicationItem.getApplicationInfo().packageName.hashCode(); } @Override @@ -670,12 +664,11 @@ public class RequestRoleFragment extends DialogFragment { if (!mDontAskAgain) { return true; } - Pair qualifyingApplication = getItem(position); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = getItem(position); + if (applicationItem == null) { return mHolderUserPackage == null; } else { - boolean isHolderApplication = qualifyingApplication.second; - return isHolderApplication; + return applicationItem.isHolderApplication(); } } @@ -697,14 +690,14 @@ public class RequestRoleFragment extends DialogFragment { LAYOUT_TRANSITION_DURATION_MILLIS); } - Pair qualifyingApplication = getItem(position); + RoleApplicationItem applicationItem = getItem(position); ApplicationInfo applicationInfo; boolean restricted; boolean checked; Drawable icon; String title; String subtitle; - if (qualifyingApplication == null) { + if (applicationItem == null) { applicationInfo = null; restricted = false; checked = mCheckedUserPackage == null; @@ -713,15 +706,14 @@ public class RequestRoleFragment extends DialogFragment { subtitle = mHolderUserPackage == null ? context.getString( R.string.request_role_current_default) : null; } else { - applicationInfo = qualifyingApplication.first; + applicationInfo = applicationItem.getApplicationInfo(); UserPackage userPackage = UserPackage.from(applicationInfo); restricted = mRole.getApplicationRestrictionIntentAsUser(applicationInfo, userPackage.user, context) != null; checked = Objects.equals(userPackage, mCheckedUserPackage); icon = Utils.getBadgedIcon(context, applicationInfo); title = Utils.getAppLabel(applicationInfo, context); - boolean isHolderApplication = qualifyingApplication.second; - subtitle = isHolderApplication + subtitle = applicationItem.isHolderApplication() ? context.getString(R.string.request_role_current_default) : checked ? context.getString(mRole.getRequestDescriptionResource()) : null; } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationItem.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationItem.java new file mode 100644 index 000000000..b6c489ea1 --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationItem.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2025 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 android.content.pm.ApplicationInfo; + +import androidx.annotation.NonNull; + +/** + * Information about an application to be displayed in a list of applications qualifying for a role. + */ +public class RoleApplicationItem { + + /** + * The {@link ApplicationInfo} for this application. + */ + @NonNull + private final ApplicationInfo mApplicationInfo; + + /** + * Whether this application is holding the role. + */ + private final boolean mIsHolderApplication; + + public RoleApplicationItem(@NonNull ApplicationInfo applicationInfo, + boolean isHolderApplication) { + mApplicationInfo = applicationInfo; + mIsHolderApplication = isHolderApplication; + } + + @NonNull + public ApplicationInfo getApplicationInfo() { + return mApplicationInfo; + } + + public boolean isHolderApplication() { + return mIsHolderApplication; + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java deleted file mode 100644 index b84fa80b9..000000000 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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> { - private final Predicate mPredicate; - - public RoleListFilterFunction(@NonNull Predicate predicate) { - mPredicate = predicate; - } - - @NonNull - @Override - public List invoke(@Nullable List roleItems) { - List 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/RoleListSortFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListSortFunction.java index ca059aa32..07b4db1f4 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListSortFunction.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListSortFunction.java @@ -23,30 +23,23 @@ import androidx.annotation.NonNull; import kotlin.jvm.functions.Function1; -import java.util.ArrayList; import java.util.Comparator; -import java.util.List; /** - * A function for {@link androidx.lifecycle#map(androidx.lifecycle.LiveData, Function1)} + * A function for + * {@link androidx.lifecycle.Transformations#map(androidx.lifecycle.LiveData, Function1)} * that sorts a live data for role list. */ -public class RoleListSortFunction implements Function1, List> { - - @NonNull - private final Comparator mComparator; +public class RoleListSortFunction extends ListLiveDataSortFunction { public RoleListSortFunction(@NonNull Context context) { - Collator collator = Collator.getInstance(context.getResources().getConfiguration() - .getLocales().get(0)); - mComparator = Comparator.comparing(roleItem -> context.getString( - roleItem.getRole().getShortLabelResource()), collator); + super(createComparator(context)); } - @Override - public List invoke(List p1) { - List sorted = new ArrayList<>(p1); - sorted.sort(mComparator); - return sorted; + private static Comparator createComparator(@NonNull Context context) { + Collator collator = Collator.getInstance(context.getResources().getConfiguration() + .getLocales().get(0)); + return Comparator.comparing(item -> context.getString( + item.getRole().getShortLabelResource()), collator); } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java index bb492f76d..1b6d42934 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java @@ -22,7 +22,6 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.os.UserHandle; import android.util.Log; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; @@ -38,7 +37,7 @@ import java.util.List; /** * {@link LiveData} for a role. */ -public class RoleLiveData extends AsyncTaskLiveData>> +public class RoleLiveData extends AsyncTaskLiveData> implements OnRoleHoldersChangedListener { private static final String LOG_TAG = RoleLiveData.class.getSimpleName(); @@ -77,12 +76,12 @@ public class RoleLiveData extends AsyncTaskLiveData> loadValueInBackground() { + protected List loadValueInBackground() { RoleManager roleManager = mContext.getSystemService(RoleManager.class); List holderPackageNames = roleManager.getRoleHoldersAsUser(mRole.getName(), mUser); List qualifyingPackageNames = mRole.getQualifyingPackagesAsUser(mUser, mContext); - List> qualifyingApplications = new ArrayList<>(); + List applicationItems = new ArrayList<>(); int qualifyingPackageNamesSize = qualifyingPackageNames.size(); for (int i = 0; i < qualifyingPackageNamesSize; i++) { String qualifyingPackageName = qualifyingPackageNames.get(i); @@ -98,9 +97,10 @@ public class RoleLiveData extends AsyncTaskLiveData(qualifyingApplicationInfo, isHolderApplication)); + applicationItems.add( + new RoleApplicationItem(qualifyingApplicationInfo, isHolderApplication)); } - return qualifyingApplications; + return applicationItems; } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java index 10db9dbcd..9a06a6b01 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java @@ -17,10 +17,8 @@ package com.android.permissioncontroller.role.ui; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.icu.text.Collator; import android.os.UserHandle; -import android.util.Pair; import androidx.annotation.NonNull; @@ -28,34 +26,26 @@ import com.android.permissioncontroller.permission.utils.Utils; import kotlin.jvm.functions.Function1; -import java.util.ArrayList; import java.util.Comparator; -import java.util.List; /** - * A function for {@link androidx.lifecycle#map(androidx.lifecycle.LiveData, Function1)} + * A function for + * {@link androidx.lifecycle.Transformations#map(androidx.lifecycle.LiveData, Function1)} * that sorts a live data for role. */ -public class RoleSortFunction implements Function1>, - List>> { - - @NonNull - private final Comparator> mComparator; +public class RoleSortFunction extends ListLiveDataSortFunction { public RoleSortFunction(@NonNull Context context) { - Collator collator = Collator.getInstance(context.getResources().getConfiguration() - .getLocales().get(0)); - Comparator> labelComparator = Comparator.comparing(role -> - Utils.getAppLabel(role.first, context), collator); - Comparator> userIdComparator = Comparator.comparingInt(role - -> UserHandle.getUserHandleForUid(role.first.uid).getIdentifier()); - mComparator = labelComparator.thenComparing(userIdComparator); + super(createComparator(context)); } - @Override - public List> invoke(List> p1) { - List> sorted = new ArrayList<>(p1); - sorted.sort(mComparator); - return sorted; + private static Comparator createComparator(@NonNull Context context) { + Collator collator = Collator.getInstance(context.getResources().getConfiguration() + .getLocales().get(0)); + Comparator labelComparator = Comparator.comparing(item -> + Utils.getAppLabel(item.getApplicationInfo(), context), collator); + Comparator userIdComparator = Comparator.comparingInt(item + -> UserHandle.getUserHandleForUid(item.getApplicationInfo().uid).getIdentifier()); + return labelComparator.thenComparing(userIdComparator); } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java index 0963635e7..7a13eb2b5 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java @@ -23,7 +23,6 @@ import android.content.pm.ApplicationInfo; import android.os.Bundle; import android.os.UserHandle; import android.util.ArrayMap; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -37,6 +36,7 @@ import androidx.preference.TwoStatePreference; import com.android.permissioncontroller.permission.utils.Utils; import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData; +import com.android.permissioncontroller.role.ui.RoleApplicationItem; import com.android.permissioncontroller.role.ui.RoleApplicationPreference; import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; @@ -107,12 +107,12 @@ public class SpecialAppAccessChildFragment> qualifyingApplications) { + private void onApplicationListChanged( + @NonNull List applicationItems) { PF preferenceFragment = requirePreferenceFragment(); PreferenceManager preferenceManager = preferenceFragment.getPreferenceManager(); Context context = preferenceManager.getContext(); @@ -138,14 +138,12 @@ public class SpecialAppAccessChildFragment qualifyingApplication = qualifyingApplications.get(i); - ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first; - boolean isHolderPackage = qualifyingApplication.second; - - String key = qualifyingApplicationInfo.packageName + '_' - + qualifyingApplicationInfo.uid; + int applicationItemsSize = applicationItems.size(); + for (int i = 0; i < applicationItemsSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); + String key = applicationInfo.packageName + '_' + + applicationInfo.uid; RoleApplicationPreference roleApplicationPreference = (RoleApplicationPreference) oldPreferences.get(key); TwoStatePreference preference; @@ -153,24 +151,23 @@ public class SpecialAppAccessChildFragment false); preference.setOnPreferenceClickListener(this); preference.getExtras().putParcelable(PREFERENCE_EXTRA_APPLICATION_INFO, - qualifyingApplicationInfo); + applicationInfo); } else { preference = roleApplicationPreference.asTwoStatePreference(); } - preference.setChecked(isHolderPackage); - UserHandle user = UserHandle.getUserHandleForUid(qualifyingApplicationInfo.uid); + preference.setChecked(applicationItem.isHolderApplication()); + UserHandle user = UserHandle.getUserHandleForUid(applicationInfo.uid); roleApplicationPreference.setRestrictionIntent( - mRole.getApplicationRestrictionIntentAsUser(qualifyingApplicationInfo, user, - context)); + mRole.getApplicationRestrictionIntentAsUser(applicationInfo, user, context)); RoleUiBehaviorUtils.prepareApplicationPreferenceAsUser(mRole, roleApplicationPreference, - qualifyingApplicationInfo, user, context); + applicationInfo, user, context); preferenceScreen.addPreference(preference); } 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 c12265d43..f4abc0db1 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java @@ -17,12 +17,10 @@ package com.android.permissioncontroller.role.ui.specialappaccess; import android.app.Application; -import android.content.pm.ApplicationInfo; import android.os.Process; import android.os.UserHandle; import android.util.ArrayMap; import android.util.Log; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; @@ -34,6 +32,7 @@ import androidx.lifecycle.ViewModelProvider; import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData; import com.android.permissioncontroller.role.ui.MergeRoleLiveData; +import com.android.permissioncontroller.role.ui.RoleApplicationItem; import com.android.permissioncontroller.role.ui.RoleLiveData; import com.android.permissioncontroller.role.ui.RoleSortFunction; import com.android.permissioncontroller.role.utils.UserUtils; @@ -52,7 +51,7 @@ public class SpecialAppAccessViewModel extends AndroidViewModel { private final Role mRole; @NonNull - private final LiveData>> mRoleLiveData; + private final LiveData> mLiveData; @NonNull private final ArrayMap mManageRoleHolderStateLiveDatas = @@ -68,17 +67,17 @@ public class SpecialAppAccessViewModel extends AndroidViewModel { UserHandle workProfile = UserUtils.getWorkProfile(application); RoleSortFunction sortFunction = new RoleSortFunction(application); if (workProfile == null) { - mRoleLiveData = Transformations.map(roleLiveData, sortFunction); + mLiveData = Transformations.map(roleLiveData, sortFunction); } else { RoleLiveData workRoleLiveData = new RoleLiveData(role, workProfile, application); - mRoleLiveData = Transformations.map(new MergeRoleLiveData(roleLiveData, + mLiveData = Transformations.map(new MergeRoleLiveData(roleLiveData, workRoleLiveData), sortFunction); } } @NonNull - public LiveData>> getRoleLiveData() { - return mRoleLiveData; + public LiveData> getLiveData() { + return mLiveData; } /** 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 9e93f33c7..65548d9a1 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt @@ -17,12 +17,11 @@ package com.android.permissioncontroller.role.ui.wear import android.content.Context -import android.content.pm.ApplicationInfo import android.os.UserHandle -import android.util.Pair import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.utils.Utils import com.android.permissioncontroller.role.ui.DefaultAppViewModel +import com.android.permissioncontroller.role.ui.RoleApplicationItem import com.android.permissioncontroller.role.ui.wear.model.ConfirmDialogArgs import com.android.permissioncontroller.role.ui.wear.model.DefaultAppConfirmDialogViewModel import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils @@ -39,13 +38,13 @@ class WearDefaultAppHelper( fun getTitle() = context.getString(role.labelResource) fun getNonePreference( - qualifyingApplications: List> + applicationItems: List ): WearRoleApplicationPreference? = if (role.shouldShowNone()) { WearRoleApplicationPreference( context = context, defaultLabel = context.getString(R.string.default_app_none), - checked = !hasHolderApplication(qualifyingApplications), + checked = !hasHolderApplication(applicationItems), onDefaultCheckChanged = { _ -> viewModel.setNoneDefaultApp() }, ) .apply { icon = context.getDrawable(R.drawable.ic_remove_circle) } @@ -54,12 +53,12 @@ class WearDefaultAppHelper( } fun getPreferences( - qualifyingApplications: List> + applicationItems: List ): List { - return qualifyingApplications - .map { pair -> - val appInfo = pair.first - val selected = pair.second + return applicationItems + .map { applicationItem -> + val appInfo = applicationItem.applicationInfo + val selected = applicationItem.isHolderApplication val user = UserHandle.getUserHandleForUid(appInfo.uid) WearRoleApplicationPreference( context = context, @@ -127,7 +126,6 @@ class WearDefaultAppHelper( fun getDescription() = context.getString(role.descriptionResource) - private fun hasHolderApplication( - qualifyingApplications: List> - ): Boolean = qualifyingApplications.map { it.second }.contains(true) + private fun hasHolderApplication(applicationItems: List): Boolean = + applicationItems.map { it.isHolderApplication }.contains(true) } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt index 067c5b1be..c3cbe4670 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt @@ -16,8 +16,6 @@ package com.android.permissioncontroller.role.ui.wear -import android.content.pm.ApplicationInfo -import android.util.Pair import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -25,6 +23,7 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import com.android.permissioncontroller.role.ui.RoleApplicationItem import com.android.permissioncontroller.role.ui.wear.model.ConfirmDialogArgs import com.android.permissioncontroller.wear.permission.components.ScrollableScreen import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent @@ -39,7 +38,7 @@ import com.android.permissioncontroller.wear.permission.components.theme.WearPer @Composable fun WearDefaultAppScreen(helper: WearDefaultAppHelper) { - val roleLiveData = helper.viewModel.roleLiveData.observeAsState(emptyList()) + val roleLiveData = helper.viewModel.liveData.observeAsState(emptyList()) val showConfirmDialog = helper.confirmDialogViewModel.showConfirmDialogLiveData.observeAsState(false) var isLoading by remember { mutableStateOf(true) } @@ -60,11 +59,11 @@ fun WearDefaultAppScreen(helper: WearDefaultAppHelper) { @Composable private fun WearDefaultAppContent( isLoading: Boolean, - qualifyingApplications: List>, + applicationItems: List, helper: WearDefaultAppHelper, ) { ScrollableScreen(title = helper.getTitle(), isLoading = isLoading) { - helper.getNonePreference(qualifyingApplications)?.let { + helper.getNonePreference(applicationItems)?.let { item { WearPermissionToggleControl( label = it.title.toString(), @@ -76,7 +75,7 @@ private fun WearDefaultAppContent( ) } } - for (pref in helper.getPreferences(qualifyingApplications)) { + for (pref in helper.getPreferences(applicationItems)) { item { WearPermissionToggleControl( label = pref.title.toString(), diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt index af8dc5e92..99f2fe36f 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt @@ -231,11 +231,11 @@ class WearRequestRoleFragment : Fragment() { if (userPackage == null) { return -1 } - viewModel.roleLiveData.value?.let { qualifyingApplications -> - for (qualifyingApplication in qualifyingApplications) { - val qualifyingApplicationInfo = qualifyingApplication.first - val qualifyingAppUserPackage = UserPackage.from(qualifyingApplicationInfo) - if (Objects.equals(qualifyingAppUserPackage, userPackage)) { + viewModel.liveData.value?.let { applicationItems -> + for (applicationItem in applicationItems) { + val qualifyingApplicationInfo = applicationItem.applicationInfo + val qualifyingUserPackage = UserPackage.from(qualifyingApplicationInfo) + if (Objects.equals(qualifyingUserPackage, userPackage)) { return qualifyingApplicationInfo.uid } } @@ -244,12 +244,10 @@ class WearRequestRoleFragment : Fragment() { } private fun getHolderUserPackage(): UserPackage? { - viewModel.roleLiveData.value?.let { qualifyingApplications -> + viewModel.liveData.value?.let { qualifyingApplications -> for (qualifyingApplication in qualifyingApplications) { - val isHolderApplication = qualifyingApplication.second - if (isHolderApplication) { - val applicationInfo = qualifyingApplication.first - return UserPackage.from(applicationInfo) + if (qualifyingApplication.isHolderApplication) { + return UserPackage.from(qualifyingApplication.applicationInfo) } } } @@ -257,7 +255,7 @@ class WearRequestRoleFragment : Fragment() { } private fun getQualifyingApplicationCount(): Int { - return viewModel.roleLiveData.value?.size ?: -1 + return viewModel.liveData.value?.size ?: -1 } private fun setDeniedAlwaysAndFinish() { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt index f8a1b1ee8..f95f1ee90 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt @@ -20,12 +20,12 @@ import android.content.Context import android.content.pm.ApplicationInfo import android.graphics.drawable.Drawable import android.os.Process -import android.util.Pair import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.utils.Utils import com.android.permissioncontroller.role.UserPackage import com.android.permissioncontroller.role.model.UserDeniedManager import com.android.permissioncontroller.role.ui.RequestRoleViewModel +import com.android.permissioncontroller.role.ui.RoleApplicationItem import com.android.permissioncontroller.role.ui.wear.model.WearRequestRoleViewModel import com.android.role.controller.model.Role import java.util.Objects @@ -50,11 +50,11 @@ class WearRequestRoleHelper( UserDeniedManager.getInstance(context).isDeniedOnce(roleName, packageName) fun getNonePreference( - qualifyingApplications: List>, + applicationItems: List, selectedPackage: UserPackage?, ): RequestRolePreference? = if (role.shouldShowNone()) { - val hasHolderApplication = hasHolderApplication(qualifyingApplications) + val hasHolderApplication = hasHolderApplication(applicationItems) RequestRolePreference( userPackage = null, label = context.getString(R.string.default_app_none), @@ -79,48 +79,47 @@ class WearRequestRoleHelper( } fun getPreferences( - qualifyingApplications: List>, + applicationItems: List, selectedPackage: UserPackage?, ): List { - return qualifyingApplications - .map { qualifyingApplication -> - val userPackage = UserPackage.from(qualifyingApplication.first) + return applicationItems + .map { applicationItem -> + val userPackage = UserPackage.from(applicationItem.applicationInfo) RequestRolePreference( userPackage = userPackage, - label = Utils.getAppLabel(qualifyingApplication.first, context), + label = Utils.getAppLabel(applicationItem.applicationInfo, context), subTitle = - if (qualifyingApplication.second) { + if (applicationItem.isHolderApplication) { context.getString(R.string.request_role_current_default) } else { context.getString(role.requestDescriptionResource) }, - icon = Utils.getBadgedIcon(context, qualifyingApplication.first), + icon = Utils.getBadgedIcon(context, applicationItem.applicationInfo), checked = Objects.equals(userPackage, selectedPackage), enabled = if (!wearViewModel.dontAskAgain()) { true } else { - qualifyingApplication.second + applicationItem.isHolderApplication }, - isHolder = qualifyingApplication.second, + isHolder = applicationItem.isHolderApplication, ) } .toList() } - private fun hasHolderApplication( - qualifyingApplications: List> - ): Boolean = qualifyingApplications.map { it.second }.contains(true) + private fun hasHolderApplication(applicationItems: List): Boolean = + applicationItems.map { it.isHolderApplication }.contains(true) fun shouldSetAsDefaultEnabled(enabled: Boolean): Boolean { return enabled && (wearViewModel.dontAskAgain() || !wearViewModel.isHolderChecked) } - fun initializeHolderPackage(qualifyingApplications: List>) { + fun initializeHolderPackage(applicationItems: List) { wearViewModel.holderPackage = - qualifyingApplications - .find { it.second } - ?.first + applicationItems + .find { it.isHolderApplication } + ?.applicationInfo ?.let { appInfo -> UserPackage.from(appInfo) } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt index 5244e1a63..1367f4c3c 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt @@ -16,8 +16,6 @@ package com.android.permissioncontroller.role.ui.wear -import android.content.pm.ApplicationInfo -import android.util.Pair import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable @@ -33,6 +31,7 @@ import androidx.compose.ui.unit.dp import com.android.permissioncontroller.R import com.android.permissioncontroller.role.UserPackage import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData +import com.android.permissioncontroller.role.ui.RoleApplicationItem import com.android.permissioncontroller.wear.permission.components.ScrollableScreen import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle @@ -50,7 +49,7 @@ fun WearRequestRoleScreen( onSetAsDefault: (Boolean, UserPackage?) -> Unit, onCanceled: () -> Unit, ) { - val roleLiveData = helper.viewModel.roleLiveData.observeAsState(emptyList()) + val roleLiveData = helper.viewModel.liveData.observeAsState(emptyList()) val manageRoleHolderState = helper.viewModel.manageRoleHolderStateLiveData.observeAsState( ManageRoleHolderStateLiveData.STATE_WORKING @@ -102,7 +101,7 @@ internal fun WearRequestRoleContent( materialUIVersion: WearPermissionMaterialUIVersion, isLoading: Boolean, helper: WearRequestRoleHelper, - qualifyingApplications: List>, + applicationItems: List, enabled: Boolean, dontAskAgain: Boolean, selectedPackage: UserPackage?, @@ -118,7 +117,7 @@ internal fun WearRequestRoleContent( showTimeText = false, isLoading = isLoading, ) { - helper.getNonePreference(qualifyingApplications, selectedPackage)?.let { pref -> + helper.getNonePreference(applicationItems, selectedPackage)?.let { pref -> item { WearPermissionToggleControl( materialUIVersion = materialUIVersion, @@ -143,7 +142,7 @@ internal fun WearRequestRoleContent( } } - for (pref in helper.getPreferences(qualifyingApplications, selectedPackage)) { + for (pref in helper.getPreferences(applicationItems, selectedPackage)) { item { WearPermissionToggleControl( materialUIVersion = materialUIVersion, -- cgit v1.2.3-59-g8ed1b