Loading services/core/java/com/android/server/pm/CloneProfileResolver.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.content.Intent; import android.content.pm.ResolveInfo; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.resolution.ComponentResolverApi; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import java.util.ArrayList; import java.util.List; import java.util.function.Function; /** * Cross Profile intent resolution strategy used for and to clone profile. */ public class CloneProfileResolver extends CrossProfileResolver { public CloneProfileResolver(ComponentResolverApi componentResolver, UserManagerService userManagerService) { super(componentResolver, userManagerService); } /** * This is resolution strategy for Clone Profile. * In case of clone profile, the profile is supposed to be transparent to end user. To end user * clone and owner profile should be part of same user space. Hence, the resolution strategy * would resolve intent in both profile and return combined result without any filtering of the * results. * * @param computer ComputerEngine instance that would be needed by ComponentResolverApi * @param intent request * @param resolvedType the MIME data type of intent request * @param userId source/initiating user * @param targetUserId target user id * @param flags of intent request * @param pkgName the application package name this Intent is limited to * @param matchingFilters {@link CrossProfileIntentFilter}s configured for source user, * targeting the targetUserId * @param hasNonNegativePriorityResult if source have any non-negative(active and valid) * resolveInfo in their profile. * @param pkgSettingFunction function to find PackageStateInternal for given package * @return list of {@link CrossProfileDomainInfo} */ @Override public List<CrossProfileDomainInfo> resolveIntent(Computer computer, Intent intent, String resolvedType, int userId, int targetUserId, long flags, String pkgName, List<CrossProfileIntentFilter> matchingFilters, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction) { List<ResolveInfo> resolveInfos = mComponentResolver.queryActivities(computer, intent, resolvedType, flags, targetUserId); List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); if (resolveInfos != null) { for (int index = 0; index < resolveInfos.size(); index++) { crossProfileDomainInfos.add(new CrossProfileDomainInfo(resolveInfos.get(index), DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE, targetUserId)); } } return filterIfNotSystemUser(crossProfileDomainInfos, userId); } /** * As clone and owner profile are going to be part of the same userspace, we need no filtering * out of any clone profile's result * @param intent request * @param crossProfileDomainInfos resolved in target user * @param flags for intent resolution * @param sourceUserId source user * @param targetUserId target user * @param highestApprovalLevel highest level of domain approval * @return list of CrossProfileDomainInfo */ @Override public List<CrossProfileDomainInfo> filterResolveInfoWithDomainPreferredActivity(Intent intent, List<CrossProfileDomainInfo> crossProfileDomainInfos, long flags, int sourceUserId, int targetUserId, int highestApprovalLevel) { // no filtering for clone profile return crossProfileDomainInfos; } } services/core/java/com/android/server/pm/ComputerEngine.java +1 −1 Original line number Diff line number Diff line Loading @@ -460,7 +460,7 @@ public class ComputerEngine implements Computer { mBackgroundDexOptService = args.service.mBackgroundDexOptService; mExternalSourcesPolicy = args.service.mExternalSourcesPolicy; mCrossProfileIntentResolverEngine = new CrossProfileIntentResolverEngine( mUserManager, mDomainVerificationManager, mDefaultAppProvider); mUserManager, mDomainVerificationManager, mDefaultAppProvider, mContext); // Used to reference PMS attributes that are primitives and which are not // updated under control of the PMS lock. Loading services/core/java/com/android/server/pm/CrossProfileIntentFilter.java +3 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ class CrossProfileIntentFilter extends WatchedIntentFilter { private static final String ATTR_FILTER = "filter"; private static final String ATTR_ACCESS_CONTROL = "accessControl"; //flag to decide if intent needs to be resolved cross profile if pkgName is already defined public static final int FLAG_IS_PACKAGE_FOR_FILTER = 0x00000008; private static final String TAG = "CrossProfileIntentFilter"; /** Loading services/core/java/com/android/server/pm/CrossProfileIntentResolver.java +3 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.pm; import static com.android.server.pm.CrossProfileIntentFilter.FLAG_IS_PACKAGE_FOR_FILTER; import android.annotation.NonNull; import android.content.IntentFilter; Loading @@ -37,7 +39,7 @@ class CrossProfileIntentResolver @Override protected boolean isPackageForFilter(String packageName, CrossProfileIntentFilter filter) { return false; return (FLAG_IS_PACKAGE_FOR_FILTER & filter.mFlags) != 0; } @Override Loading services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java +20 −3 Original line number Diff line number Diff line Loading @@ -25,12 +25,14 @@ import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.Process; import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; Loading @@ -54,13 +56,15 @@ public class CrossProfileIntentResolverEngine { private final UserManagerService mUserManager; private final DomainVerificationManagerInternal mDomainVerificationManager; private final DefaultAppProvider mDefaultAppProvider; private final Context mContext; public CrossProfileIntentResolverEngine(UserManagerService userManager, DomainVerificationManagerInternal domainVerificationManager, DefaultAppProvider defaultAppProvider) { DefaultAppProvider defaultAppProvider, Context context) { mUserManager = userManager; mDomainVerificationManager = domainVerificationManager; mDefaultAppProvider = defaultAppProvider; mContext = context; } /** Loading Loading @@ -196,6 +200,21 @@ public class CrossProfileIntentResolverEngine { @SuppressWarnings("unused") private CrossProfileResolver chooseCrossProfileResolver(@NonNull Computer computer, UserInfo sourceUserInfo, UserInfo targetUserInfo) { //todo change isCloneProfile to user properties b/241532322 /** * If source or target user is clone profile, using {@link CloneProfileResolver} * We would allow CloneProfileResolver only if flag * SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE is enabled */ if (sourceUserInfo.isCloneProfile() || targetUserInfo.isCloneProfile()) { if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE)) { return new CloneProfileResolver(computer.getComponentResolver(), mUserManager); } else { return null; } } return new DefaultCrossProfileResolver(computer.getComponentResolver(), mUserManager, mDomainVerificationManager); } Loading Loading @@ -313,8 +332,6 @@ public class CrossProfileIntentResolverEngine { } if (pkgName == null && intent.hasWebURI()) { // If instant apps are not allowed and there is result only from current or cross // profile return it if (!addInstant && ((candidates.size() <= 1 && crossProfileCandidates.isEmpty()) || (candidates.isEmpty() && !crossProfileCandidates.isEmpty()))) { candidates.addAll(resolveInfoFromCrossProfileDomainInfo(crossProfileCandidates)); Loading Loading
services/core/java/com/android/server/pm/CloneProfileResolver.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.content.Intent; import android.content.pm.ResolveInfo; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.resolution.ComponentResolverApi; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import java.util.ArrayList; import java.util.List; import java.util.function.Function; /** * Cross Profile intent resolution strategy used for and to clone profile. */ public class CloneProfileResolver extends CrossProfileResolver { public CloneProfileResolver(ComponentResolverApi componentResolver, UserManagerService userManagerService) { super(componentResolver, userManagerService); } /** * This is resolution strategy for Clone Profile. * In case of clone profile, the profile is supposed to be transparent to end user. To end user * clone and owner profile should be part of same user space. Hence, the resolution strategy * would resolve intent in both profile and return combined result without any filtering of the * results. * * @param computer ComputerEngine instance that would be needed by ComponentResolverApi * @param intent request * @param resolvedType the MIME data type of intent request * @param userId source/initiating user * @param targetUserId target user id * @param flags of intent request * @param pkgName the application package name this Intent is limited to * @param matchingFilters {@link CrossProfileIntentFilter}s configured for source user, * targeting the targetUserId * @param hasNonNegativePriorityResult if source have any non-negative(active and valid) * resolveInfo in their profile. * @param pkgSettingFunction function to find PackageStateInternal for given package * @return list of {@link CrossProfileDomainInfo} */ @Override public List<CrossProfileDomainInfo> resolveIntent(Computer computer, Intent intent, String resolvedType, int userId, int targetUserId, long flags, String pkgName, List<CrossProfileIntentFilter> matchingFilters, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction) { List<ResolveInfo> resolveInfos = mComponentResolver.queryActivities(computer, intent, resolvedType, flags, targetUserId); List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); if (resolveInfos != null) { for (int index = 0; index < resolveInfos.size(); index++) { crossProfileDomainInfos.add(new CrossProfileDomainInfo(resolveInfos.get(index), DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE, targetUserId)); } } return filterIfNotSystemUser(crossProfileDomainInfos, userId); } /** * As clone and owner profile are going to be part of the same userspace, we need no filtering * out of any clone profile's result * @param intent request * @param crossProfileDomainInfos resolved in target user * @param flags for intent resolution * @param sourceUserId source user * @param targetUserId target user * @param highestApprovalLevel highest level of domain approval * @return list of CrossProfileDomainInfo */ @Override public List<CrossProfileDomainInfo> filterResolveInfoWithDomainPreferredActivity(Intent intent, List<CrossProfileDomainInfo> crossProfileDomainInfos, long flags, int sourceUserId, int targetUserId, int highestApprovalLevel) { // no filtering for clone profile return crossProfileDomainInfos; } }
services/core/java/com/android/server/pm/ComputerEngine.java +1 −1 Original line number Diff line number Diff line Loading @@ -460,7 +460,7 @@ public class ComputerEngine implements Computer { mBackgroundDexOptService = args.service.mBackgroundDexOptService; mExternalSourcesPolicy = args.service.mExternalSourcesPolicy; mCrossProfileIntentResolverEngine = new CrossProfileIntentResolverEngine( mUserManager, mDomainVerificationManager, mDefaultAppProvider); mUserManager, mDomainVerificationManager, mDefaultAppProvider, mContext); // Used to reference PMS attributes that are primitives and which are not // updated under control of the PMS lock. Loading
services/core/java/com/android/server/pm/CrossProfileIntentFilter.java +3 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ class CrossProfileIntentFilter extends WatchedIntentFilter { private static final String ATTR_FILTER = "filter"; private static final String ATTR_ACCESS_CONTROL = "accessControl"; //flag to decide if intent needs to be resolved cross profile if pkgName is already defined public static final int FLAG_IS_PACKAGE_FOR_FILTER = 0x00000008; private static final String TAG = "CrossProfileIntentFilter"; /** Loading
services/core/java/com/android/server/pm/CrossProfileIntentResolver.java +3 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.pm; import static com.android.server.pm.CrossProfileIntentFilter.FLAG_IS_PACKAGE_FOR_FILTER; import android.annotation.NonNull; import android.content.IntentFilter; Loading @@ -37,7 +39,7 @@ class CrossProfileIntentResolver @Override protected boolean isPackageForFilter(String packageName, CrossProfileIntentFilter filter) { return false; return (FLAG_IS_PACKAGE_FOR_FILTER & filter.mFlags) != 0; } @Override Loading
services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java +20 −3 Original line number Diff line number Diff line Loading @@ -25,12 +25,14 @@ import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.Process; import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; Loading @@ -54,13 +56,15 @@ public class CrossProfileIntentResolverEngine { private final UserManagerService mUserManager; private final DomainVerificationManagerInternal mDomainVerificationManager; private final DefaultAppProvider mDefaultAppProvider; private final Context mContext; public CrossProfileIntentResolverEngine(UserManagerService userManager, DomainVerificationManagerInternal domainVerificationManager, DefaultAppProvider defaultAppProvider) { DefaultAppProvider defaultAppProvider, Context context) { mUserManager = userManager; mDomainVerificationManager = domainVerificationManager; mDefaultAppProvider = defaultAppProvider; mContext = context; } /** Loading Loading @@ -196,6 +200,21 @@ public class CrossProfileIntentResolverEngine { @SuppressWarnings("unused") private CrossProfileResolver chooseCrossProfileResolver(@NonNull Computer computer, UserInfo sourceUserInfo, UserInfo targetUserInfo) { //todo change isCloneProfile to user properties b/241532322 /** * If source or target user is clone profile, using {@link CloneProfileResolver} * We would allow CloneProfileResolver only if flag * SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE is enabled */ if (sourceUserInfo.isCloneProfile() || targetUserInfo.isCloneProfile()) { if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE)) { return new CloneProfileResolver(computer.getComponentResolver(), mUserManager); } else { return null; } } return new DefaultCrossProfileResolver(computer.getComponentResolver(), mUserManager, mDomainVerificationManager); } Loading Loading @@ -313,8 +332,6 @@ public class CrossProfileIntentResolverEngine { } if (pkgName == null && intent.hasWebURI()) { // If instant apps are not allowed and there is result only from current or cross // profile return it if (!addInstant && ((candidates.size() <= 1 && crossProfileCandidates.isEmpty()) || (candidates.isEmpty() && !crossProfileCandidates.isEmpty()))) { candidates.addAll(resolveInfoFromCrossProfileDomainInfo(crossProfileCandidates)); Loading