Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a01423b6 authored by Sarup Dalwani's avatar Sarup Dalwani Committed by Android (Google) Code Review
Browse files

Merge "Creating CloneProfileResolver to facilitate intent redirection for clone profile"

parents 50627b15 c077f491
Loading
Loading
Loading
Loading
+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;
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -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.
+3 −0
Original line number Diff line number Diff line
@@ -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";

    /**
+3 −1
Original line number Diff line number Diff line
@@ -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
+20 −3
Original line number Diff line number Diff line
@@ -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));