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

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

Merge "Creating UserProperty for deciding intent resolution strategy"

parents 59dd9491 785c3d67
Loading
Loading
Loading
Loading
+96 −3
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ public final class UserProperties implements Parcelable {
            "updateCrossProfileIntentFiltersOnOTA";
    private static final String ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL =
            "crossProfileIntentFilterAccessControl";
    private static final String ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY =
            "crossProfileIntentResolutionStrategy";

    /** Index values of each property (to indicate whether they are present in this object). */
    @IntDef(prefix = "INDEX_", value = {
@@ -59,7 +61,8 @@ public final class UserProperties implements Parcelable {
            INDEX_INHERIT_DEVICE_POLICY,
            INDEX_USE_PARENTS_CONTACTS,
            INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA,
            INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL
            INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL,
            INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY
    })
    @Retention(RetentionPolicy.SOURCE)
    private @interface PropertyIndex {
@@ -71,6 +74,7 @@ public final class UserProperties implements Parcelable {
    private static final int INDEX_USE_PARENTS_CONTACTS = 4;
    private static final int INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA = 5;
    private static final int INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL = 6;
    private static final int INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = 7;
    /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */
    private long mPropertiesPresent = 0;

@@ -218,6 +222,39 @@ public final class UserProperties implements Parcelable {
     */
    public static final int CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM_ADD_ONLY = 20;

    /**
     * Possible values for cross profile intent resolution strategy.
     *
     * @hide
     */
    @IntDef(prefix = {"CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_"}, value = {
            CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT,
            CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface CrossProfileIntentResolutionStrategy {
    }

    /**
     * Signifies to use {@link DefaultCrossProfileResolver} strategy, which
     * check if it needs to skip the initiating profile, resolves intent in target profile.
     * {@link DefaultCrossProfileResolver} also filters the {@link ResolveInfo} after intent
     * resolution based on their domain approval level
     *
     * @hide
     */
    public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT = 0;

    /**
     * Signifies that there is no need to filter {@link ResolveInfo} after cross profile intent
     * resolution across. This strategy is for profile acting transparent to end-user and resolves
     * all allowed intent without giving any profile priority.
     *
     * @hide
     */
    public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING = 1;


    /**
     * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given
     * default properties, which it uses for any property not subsequently set.
@@ -255,6 +292,7 @@ public final class UserProperties implements Parcelable {
            setUpdateCrossProfileIntentFiltersOnOTA(orig.getUpdateCrossProfileIntentFiltersOnOTA());
            setCrossProfileIntentFilterAccessControl(
                    orig.getCrossProfileIntentFilterAccessControl());
            setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy());
        }
        if (hasManagePermission) {
            // Add items that require MANAGE_USERS or stronger.
@@ -466,6 +504,36 @@ public final class UserProperties implements Parcelable {
    }
    private @CrossProfileIntentFilterAccessControlLevel int mCrossProfileIntentFilterAccessControl;

    /**
     * Returns the user's {@link CrossProfileIntentResolutionStrategy}. If not explicitly
     * configured, default value is {@link #CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT}.
     * @return user's {@link CrossProfileIntentResolutionStrategy}.
     *
     * @hide
     */
    public @CrossProfileIntentResolutionStrategy int getCrossProfileIntentResolutionStrategy() {
        if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) {
            return mCrossProfileIntentResolutionStrategy;
        }
        if (mDefaultProperties != null) {
            return mDefaultProperties.mCrossProfileIntentResolutionStrategy;
        }
        throw new SecurityException("You don't have permission to query "
                + "crossProfileIntentResolutionStrategy");
    }
    /**
     * Sets {@link CrossProfileIntentResolutionStrategy} for the user.
     * @param val resolution strategy for user
     * @hide
     */
    public void setCrossProfileIntentResolutionStrategy(
            @CrossProfileIntentResolutionStrategy int val) {
        this.mCrossProfileIntentResolutionStrategy = val;
        setPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY);
    }
    private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy;


    @Override
    public String toString() {
        // Please print in increasing order of PropertyIndex.
@@ -480,6 +548,8 @@ public final class UserProperties implements Parcelable {
                + getUpdateCrossProfileIntentFiltersOnOTA()
                + ", mCrossProfileIntentFilterAccessControl="
                + getCrossProfileIntentFilterAccessControl()
                + ", mCrossProfileIntentResolutionStrategy="
                + getCrossProfileIntentResolutionStrategy()
                + "}";
    }

@@ -500,6 +570,8 @@ public final class UserProperties implements Parcelable {
                + getUpdateCrossProfileIntentFiltersOnOTA());
        pw.println(prefix + "    mCrossProfileIntentFilterAccessControl="
                + getCrossProfileIntentFilterAccessControl());
        pw.println(prefix + "    mCrossProfileIntentResolutionStrategy="
                + getCrossProfileIntentResolutionStrategy());
    }

    /**
@@ -554,6 +626,9 @@ public final class UserProperties implements Parcelable {
                case ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL:
                    setCrossProfileIntentFilterAccessControl(parser.getAttributeInt(i));
                    break;
                case ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY:
                    setCrossProfileIntentResolutionStrategy(parser.getAttributeInt(i));
                    break;
                default:
                    Slog.w(LOG_TAG, "Skipping unknown property " + attributeName);
            }
@@ -597,6 +672,10 @@ public final class UserProperties implements Parcelable {
            serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL,
                    mCrossProfileIntentFilterAccessControl);
        }
        if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) {
            serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY,
                    mCrossProfileIntentResolutionStrategy);
        }
    }

    // For use only with an object that has already had any permission-lacking fields stripped out.
@@ -610,6 +689,7 @@ public final class UserProperties implements Parcelable {
        dest.writeBoolean(mUseParentsContacts);
        dest.writeBoolean(mUpdateCrossProfileIntentFiltersOnOTA);
        dest.writeInt(mCrossProfileIntentFilterAccessControl);
        dest.writeInt(mCrossProfileIntentResolutionStrategy);
    }

    /**
@@ -627,6 +707,7 @@ public final class UserProperties implements Parcelable {
        mUseParentsContacts = source.readBoolean();
        mUpdateCrossProfileIntentFiltersOnOTA = source.readBoolean();
        mCrossProfileIntentFilterAccessControl = source.readInt();
        mCrossProfileIntentResolutionStrategy = source.readInt();
    }

    @Override
@@ -660,6 +741,8 @@ public final class UserProperties implements Parcelable {
        private @CrossProfileIntentFilterAccessControlLevel int
                mCrossProfileIntentFilterAccessControl =
                CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL;
        private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy =
                CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT;

        public Builder setShowInLauncher(@ShowInLauncher int showInLauncher) {
            mShowInLauncher = showInLauncher;
@@ -704,6 +787,13 @@ public final class UserProperties implements Parcelable {
            return this;
        }

        /** Sets the value for {@link #mCrossProfileIntentResolutionStrategy} */
        public Builder setCrossProfileIntentResolutionStrategy(@CrossProfileIntentResolutionStrategy
                int crossProfileIntentResolutionStrategy) {
            mCrossProfileIntentResolutionStrategy = crossProfileIntentResolutionStrategy;
            return this;
        }

        /** Builds a UserProperties object with *all* values populated. */
        public UserProperties build() {
            return new UserProperties(
@@ -713,7 +803,8 @@ public final class UserProperties implements Parcelable {
                    mInheritDevicePolicy,
                    mUseParentsContacts,
                    mUpdateCrossProfileIntentFiltersOnOTA,
                    mCrossProfileIntentFilterAccessControl);
                    mCrossProfileIntentFilterAccessControl,
                    mCrossProfileIntentResolutionStrategy);
        }
    } // end Builder

@@ -724,7 +815,8 @@ public final class UserProperties implements Parcelable {
            @ShowInSettings int showInSettings,
            @InheritDevicePolicy int inheritDevicePolicy,
            boolean useParentsContacts, boolean updateCrossProfileIntentFiltersOnOTA,
            @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl) {
            @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl,
            @CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy) {

        mDefaultProperties = null;
        setShowInLauncher(showInLauncher);
@@ -734,5 +826,6 @@ public final class UserProperties implements Parcelable {
        setUseParentsContacts(useParentsContacts);
        setUpdateCrossProfileIntentFiltersOnOTA(updateCrossProfileIntentFiltersOnOTA);
        setCrossProfileIntentFilterAccessControl(crossProfileIntentFilterAccessControl);
        setCrossProfileIntentResolutionStrategy(crossProfileIntentResolutionStrategy);
    }
}
+40 −18
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.os.Process;
import android.text.TextUtils;
import android.util.Pair;
@@ -147,8 +148,6 @@ public class CrossProfileIntentResolverEngine {
            return crossProfileDomainInfos;
        }

        UserInfo userInfo = mUserManagerInternal.getUserInfo(userId);

        // Grouping the CrossProfileIntentFilters based on targerId
        SparseArray<List<CrossProfileIntentFilter>> crossProfileIntentFiltersByUser =
                new SparseArray<>();
@@ -183,11 +182,9 @@ public class CrossProfileIntentResolverEngine {
                continue;
            }

            UserInfo targetUserInfo = mUserManagerInternal.getUserInfo(targetUserId);

            // Choosing strategy based on source and target user
            CrossProfileResolver crossProfileResolver =
                    chooseCrossProfileResolver(computer, userInfo, targetUserInfo);
                    chooseCrossProfileResolver(computer, userId, targetUserId);

        /*
        If {@link CrossProfileResolver} is available for source,target pair we will call it to
@@ -234,23 +231,21 @@ public class CrossProfileIntentResolverEngine {
    /**
     * Returns {@link CrossProfileResolver} strategy based on source and target user
     * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi}
     * @param sourceUserInfo source user
     * @param targetUserInfo target user
     * @param sourceUserId source user
     * @param targetUserId target user
     * @return {@code CrossProfileResolver} which has value if source and target have
     * strategy configured otherwise null.
     */
    @SuppressWarnings("unused")
    private CrossProfileResolver chooseCrossProfileResolver(@NonNull Computer computer,
            UserInfo sourceUserInfo, UserInfo targetUserInfo) {
        //todo change isCloneProfile to user properties b/241532322
            @UserIdInt int sourceUserId, @UserIdInt int targetUserId) {
        /**
         * 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 source or target user is clone profile, using {@link NoFilteringResolver}
         * We would return NoFilteringResolver only if it is allowed(feature flag is set).
         */
        if (sourceUserInfo.isCloneProfile() || targetUserInfo.isCloneProfile()) {
            if (CloneProfileResolver.isIntentRedirectionForCloneProfileAllowed()) {
                return new CloneProfileResolver(computer.getComponentResolver(),
        if (shouldUseNoFilteringResolver(sourceUserId, targetUserId)) {
            if (NoFilteringResolver.isIntentRedirectionAllowed()) {
                return new NoFilteringResolver(computer.getComponentResolver(),
                        mUserManager);
            } else {
                return null;
@@ -624,7 +619,6 @@ public class CrossProfileIntentResolverEngine {
            categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel) {

        List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>();
        UserInfo sourceUserInfo = mUserManagerInternal.getUserInfo(sourceUserId);

        for (int index = 0; index < categorizeResolveInfoByTargetUser.size(); index++) {

@@ -634,8 +628,8 @@ public class CrossProfileIntentResolverEngine {
            } else {
                // finding cross profile strategy based on source and target user
                CrossProfileResolver crossProfileIntentResolver =
                        chooseCrossProfileResolver(computer, sourceUserInfo, mUserManagerInternal
                                .getUserInfo(categorizeResolveInfoByTargetUser.keyAt(index)));
                        chooseCrossProfileResolver(computer, sourceUserId,
                                categorizeResolveInfoByTargetUser.keyAt(index));
                // if strategy is available call it and add its filtered results
                if (crossProfileIntentResolver != null) {
                    crossProfileDomainInfos.addAll(crossProfileIntentResolver
@@ -678,4 +672,32 @@ public class CrossProfileIntentResolverEngine {
                && crossProfileDomainInfos.get(0).mResolveInfo != null
                && crossProfileDomainInfos.get(0).mResolveInfo.priority >= 0;
    }

    /**
     * Deciding if we need to user {@link NoFilteringResolver} based on source and target user
     * @param sourceUserId id of initiating user
     * @param targetUserId id of cross profile linked user
     * @return true if {@link NoFilteringResolver} is applicable in this case.
     */
    private boolean shouldUseNoFilteringResolver(@UserIdInt int sourceUserId,
            @UserIdInt int targetUserId) {
        return isNoFilteringPropertyConfiguredForUser(sourceUserId)
                || isNoFilteringPropertyConfiguredForUser(targetUserId);
    }

    /**
     * Check if configure property for cross profile intent resolution strategy for user is
     * {@link UserProperties#CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING}
     * @param userId id of user to check for property
     * @return true if user have property set to
     * {@link UserProperties#CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING}
     */
    private boolean isNoFilteringPropertyConfiguredForUser(@UserIdInt int userId) {
        if (!mUserManager.isProfile(userId)) return false;
        UserProperties userProperties = mUserManagerInternal.getUserProperties(userId);
        if (userProperties == null) return false;

        return userProperties.getCrossProfileIntentResolutionStrategy()
                == UserProperties.CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING;
    }
}
+9 −8
Original line number Diff line number Diff line
@@ -30,9 +30,10 @@ import java.util.List;
import java.util.function.Function;

/**
 * Cross Profile intent resolution strategy used for and to clone profile.
 * Intent resolution strategy used when no filtering is required. As of now, the known use-case is
 * clone profile.
 */
public class CloneProfileResolver extends CrossProfileResolver {
public class NoFilteringResolver extends CrossProfileResolver {

    /**
     * Feature flag to allow/restrict intent redirection from/to clone profile.
@@ -48,7 +49,7 @@ public class CloneProfileResolver extends CrossProfileResolver {
     * Returns true if intent redirection for clone profile feature flag is set
     * @return value of flag allow_intent_redirection_for_clone_profile
     */
    public static boolean isIntentRedirectionForCloneProfileAllowed() {
    public static boolean isIntentRedirectionAllowed() {
        final long token = Binder.clearCallingIdentity();
        try {
            return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APP_CLONING,
@@ -58,13 +59,13 @@ public class CloneProfileResolver extends CrossProfileResolver {
        }
    }

    public CloneProfileResolver(ComponentResolverApi componentResolver,
    public NoFilteringResolver(ComponentResolverApi componentResolver,
            UserManagerService userManagerService) {
        super(componentResolver, userManagerService);
    }

    /**
     * This is resolution strategy for Clone Profile.
     * This is resolution strategy for when no filtering is required.
     * 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
@@ -105,8 +106,8 @@ public class CloneProfileResolver extends CrossProfileResolver {
    }

    /**
     * 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
     * In case of Clone profile, the 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
@@ -119,7 +120,7 @@ public class CloneProfileResolver extends CrossProfileResolver {
    public List<CrossProfileDomainInfo> filterResolveInfoWithDomainPreferredActivity(Intent intent,
            List<CrossProfileDomainInfo> crossProfileDomainInfos, long flags, int sourceUserId,
            int targetUserId, int highestApprovalLevel) {
        // no filtering for clone profile
        // no filtering
        return crossProfileDomainInfos;
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -133,7 +133,9 @@ public final class UserTypeFactory {
                        .setUseParentsContacts(true)
                        .setUpdateCrossProfileIntentFiltersOnOTA(true)
                        .setCrossProfileIntentFilterAccessControl(
                                UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM));
                                UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM)
                        .setCrossProfileIntentResolutionStrategy(UserProperties
                                .CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING));
    }

    /**
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
            startWithParent='false'
            useParentsContacts='false'
            crossProfileIntentFilterAccessControl='20'
            crossProfileIntentResolutionStrategy='0'
        />
    </profile-type>
    <profile-type name='custom.test.1' max-allowed-per-parent='14' />
Loading