From c077f491d22dbf1060194111053fb68d93c1efa6 Mon Sep 17 00:00:00 2001 From: Sarup Dalwani Date: Thu, 18 Aug 2022 12:07:31 +0000 Subject: [PATCH] Creating CloneProfileResolver to facilitate intent redirection for clone profile Creating CloneProfileResolver which would resolve intents for and to clone profile. As clone and owner profile are supposed to be in same userspace from end-user perspective, the resolver resolves in target profile and returns the results without much filtering Bug: 242989971 Test: Manually tested using clone profile's intent redirection test cases Change-Id: I578430465c3cc2de2365508db2c8e6722143bf28 --- .../server/pm/CloneProfileResolver.java | 99 +++++++++++++++++++ .../com/android/server/pm/ComputerEngine.java | 2 +- .../server/pm/CrossProfileIntentFilter.java | 3 + .../server/pm/CrossProfileIntentResolver.java | 4 +- .../pm/CrossProfileIntentResolverEngine.java | 23 ++++- 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 services/core/java/com/android/server/pm/CloneProfileResolver.java diff --git a/services/core/java/com/android/server/pm/CloneProfileResolver.java b/services/core/java/com/android/server/pm/CloneProfileResolver.java new file mode 100644 index 0000000000000..d3113e12abe3d --- /dev/null +++ b/services/core/java/com/android/server/pm/CloneProfileResolver.java @@ -0,0 +1,99 @@ +/* + * 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 resolveIntent(Computer computer, Intent intent, + String resolvedType, int userId, int targetUserId, long flags, + String pkgName, List matchingFilters, + boolean hasNonNegativePriorityResult, + Function pkgSettingFunction) { + List resolveInfos = mComponentResolver.queryActivities(computer, + intent, resolvedType, flags, targetUserId); + List 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 filterResolveInfoWithDomainPreferredActivity(Intent intent, + List crossProfileDomainInfos, long flags, int sourceUserId, + int targetUserId, int highestApprovalLevel) { + // no filtering for clone profile + return crossProfileDomainInfos; + } +} diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index b9967f94876a1..490ebc30e7094 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -462,7 +462,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. diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java index 0cd698a5eb0a5..798217f226cf8 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java @@ -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"; /** diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java index 9ea16d322c3c0..2581878055427 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java @@ -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; @@ -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 diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java index 7752fdffb1d78..5ae4cab8e7a6d 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java @@ -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; @@ -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; } /** @@ -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); } @@ -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));