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

Commit 12eec889 authored by Sarup Dalwani's avatar Sarup Dalwani
Browse files

Update mechanism for CrossProfileIntentFilters on OTA

Mechanism would be triggered on OTA, identified in PackageManager.
The update task is triggered in different thread. Update task clears all
the CrossProfileIntentFitlers between user and parent, then it applies
the new default filters. Onlt the users who have user property
updateCrossProfileIntentFiltersOnOTA set would be eligible for the
update.

Bug: 258376391
Test: Manually tested the flow
Change-Id: I0223466c07006daa195a318e105e7aca338aa3c8
parent c5deccb2
Loading
Loading
Loading
Loading
+59 −2
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ public final class UserProperties implements Parcelable {
    private static final String ATTR_SHOW_IN_SETTINGS = "showInSettings";
    private static final String ATTR_INHERIT_DEVICE_POLICY = "inheritDevicePolicy";
    private static final String ATTR_USE_PARENTS_CONTACTS = "useParentsContacts";
    private static final String ATTR_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA =
            "updateCrossProfileIntentFiltersOnOTA";

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

@@ -199,6 +203,7 @@ public final class UserProperties implements Parcelable {
            // Add items that require exposeAllFields to be true (strictest permission level).
            setStartWithParent(orig.getStartWithParent());
            setInheritDevicePolicy(orig.getInheritDevicePolicy());
            setUpdateCrossProfileIntentFiltersOnOTA(orig.getUpdateCrossProfileIntentFiltersOnOTA());
        }
        if (hasManagePermission) {
            // Add items that require MANAGE_USERS or stronger.
@@ -354,6 +359,34 @@ public final class UserProperties implements Parcelable {
     */
    private boolean mUseParentsContacts;

    /**
     * Returns true if user needs to update default
     * {@link com.android.server.pm.CrossProfileIntentFilter} with its parents during an OTA update
     * @hide
     */
    public boolean getUpdateCrossProfileIntentFiltersOnOTA() {
        if (isPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA)) {
            return mUpdateCrossProfileIntentFiltersOnOTA;
        }
        if (mDefaultProperties != null) {
            return mDefaultProperties.mUpdateCrossProfileIntentFiltersOnOTA;
        }
        throw new SecurityException("You don't have permission to query "
                + "updateCrossProfileIntentFiltersOnOTA");
    }

    /** @hide */
    public void setUpdateCrossProfileIntentFiltersOnOTA(boolean val) {
        this.mUpdateCrossProfileIntentFiltersOnOTA = val;
        setPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA);
    }

    /*
     Indicate if {@link com.android.server.pm.CrossProfileIntentFilter}s need to be updated during
     OTA update between user-parent
     */
    private boolean mUpdateCrossProfileIntentFiltersOnOTA;

    @Override
    public String toString() {
        // Please print in increasing order of PropertyIndex.
@@ -364,6 +397,8 @@ public final class UserProperties implements Parcelable {
                + ", mShowInSettings=" + getShowInSettings()
                + ", mInheritDevicePolicy=" + getInheritDevicePolicy()
                + ", mUseParentsContacts=" + getUseParentsContacts()
                + ", mUpdateCrossProfileIntentFiltersOnOTA="
                + getUpdateCrossProfileIntentFiltersOnOTA()
                + "}";
    }

@@ -380,6 +415,8 @@ public final class UserProperties implements Parcelable {
        pw.println(prefix + "    mShowInSettings=" + getShowInSettings());
        pw.println(prefix + "    mInheritDevicePolicy=" + getInheritDevicePolicy());
        pw.println(prefix + "    mUseParentsContacts=" + getUseParentsContacts());
        pw.println(prefix + "    mUpdateCrossProfileIntentFiltersOnOTA="
                + getUpdateCrossProfileIntentFiltersOnOTA());
    }

    /**
@@ -428,6 +465,9 @@ public final class UserProperties implements Parcelable {
                case ATTR_USE_PARENTS_CONTACTS:
                    setUseParentsContacts(parser.getAttributeBoolean(i));
                    break;
                case ATTR_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA:
                    setUpdateCrossProfileIntentFiltersOnOTA(parser.getAttributeBoolean(i));
                    break;
                default:
                    Slog.w(LOG_TAG, "Skipping unknown property " + attributeName);
            }
@@ -462,6 +502,11 @@ public final class UserProperties implements Parcelable {
            serializer.attributeBoolean(null, ATTR_USE_PARENTS_CONTACTS,
                    mUseParentsContacts);
        }
        if (isPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA)) {
            serializer.attributeBoolean(null,
                    ATTR_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA,
                    mUpdateCrossProfileIntentFiltersOnOTA);
        }
    }

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

    /**
@@ -488,6 +534,7 @@ public final class UserProperties implements Parcelable {
        mShowInSettings = source.readInt();
        mInheritDevicePolicy = source.readInt();
        mUseParentsContacts = source.readBoolean();
        mUpdateCrossProfileIntentFiltersOnOTA = source.readBoolean();
    }

    @Override
@@ -517,6 +564,7 @@ public final class UserProperties implements Parcelable {
        private @ShowInSettings int mShowInSettings = SHOW_IN_SETTINGS_WITH_PARENT;
        private @InheritDevicePolicy int mInheritDevicePolicy = INHERIT_DEVICE_POLICY_NO;
        private boolean mUseParentsContacts = false;
        private boolean mUpdateCrossProfileIntentFiltersOnOTA = false;

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

        /** Sets the value for {@link #mUpdateCrossProfileIntentFiltersOnOTA} */
        public Builder setUpdateCrossProfileIntentFiltersOnOTA(boolean
                updateCrossProfileIntentFiltersOnOTA) {
            mUpdateCrossProfileIntentFiltersOnOTA = updateCrossProfileIntentFiltersOnOTA;
            return this;
        }

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

@@ -563,7 +619,7 @@ public final class UserProperties implements Parcelable {
            boolean startWithParent,
            @ShowInSettings int showInSettings,
            @InheritDevicePolicy int inheritDevicePolicy,
            boolean useParentsContacts) {
            boolean useParentsContacts, boolean updateCrossProfileIntentFiltersOnOTA) {

        mDefaultProperties = null;
        setShowInLauncher(showInLauncher);
@@ -571,5 +627,6 @@ public final class UserProperties implements Parcelable {
        setShowInSettings(showInSettings);
        setInheritDevicePolicy(inheritDevicePolicy);
        setUseParentsContacts(useParentsContacts);
        setUpdateCrossProfileIntentFiltersOnOTA(updateCrossProfileIntentFiltersOnOTA);
    }
}
+100 −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.Context;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.util.ArraySet;

/**
 * Helper class to manage {@link com.android.server.pm.CrossProfileIntentFilter}s.
 */
public class CrossProfileIntentFilterHelper {
    private Context mContext;
    private UserManagerInternal mUserManagerInternal;
    private Settings mSettings;
    private UserManagerService mUserManagerService;
    private PackageManagerTracedLock mLock;

    public CrossProfileIntentFilterHelper(Settings settings, UserManagerService userManagerService,
            PackageManagerTracedLock lock, UserManagerInternal userManagerInternal,
            Context context) {
        mSettings = settings;
        mUserManagerService = userManagerService;
        mLock = lock;
        mContext = context;
        mUserManagerInternal = userManagerInternal;
    }

    /**
     * For users that have
     * {@link android.content.pm.UserProperties#getUpdateCrossProfileIntentFiltersOnOTA} set, this
     * task will update default {@link com.android.server.pm.CrossProfileIntentFilter} between that
     * user and its parent. This will only update CrossProfileIntentFilters set by system package.
     * The new default are configured in {@link UserTypeDetails}.
     */
    public void updateDefaultCrossProfileIntentFilter() {
        for (UserInfo userInfo : mUserManagerInternal.getUsers(false)) {

            UserProperties currentUserProperties = mUserManagerInternal
                    .getUserProperties(userInfo.id);

            if (currentUserProperties.getUpdateCrossProfileIntentFiltersOnOTA()) {
                int parentUserId = mUserManagerInternal.getProfileParentId(userInfo.id);
                if (parentUserId != userInfo.id) {
                    clearCrossProfileIntentFilters(userInfo.id,
                            mContext.getOpPackageName(), parentUserId);
                    clearCrossProfileIntentFilters(parentUserId,
                            mContext.getOpPackageName(),  userInfo.id);

                    mUserManagerInternal.setDefaultCrossProfileIntentFilters(parentUserId,
                            userInfo.id);
                }
            }
        }
    }

    /**
     * Clear {@link CrossProfileIntentFilter}s configured on source user by ownerPackage
     * targeting the targetUserId. If targetUserId is null then it will clear
     * {@link CrossProfileIntentFilter} for any target user.
     * @param sourceUserId source user for whom CrossProfileIntentFilter would be configured
     * @param ownerPackage package who would have configured CrossProfileIntentFilter
     * @param targetUserId user id for which CrossProfileIntentFilter will be removed.
     *                     This can be null in which case it will clear for any target user.
     */
    public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage,
            Integer targetUserId) {
        synchronized (mLock) {
            CrossProfileIntentResolver resolver = mSettings
                    .editCrossProfileIntentResolverLPw(sourceUserId);
            ArraySet<CrossProfileIntentFilter> set =
                    new ArraySet<>(resolver.filterSet());
            for (CrossProfileIntentFilter filter : set) {
                //Only remove if calling user is allowed based on access control of
                // {@link CrossProfileIntentFilter}
                if (filter.getOwnerPackage().equals(ownerPackage)
                        && (targetUserId == null || filter.mTargetUserId == targetUserId)
                        && mUserManagerService.isCrossProfileIntentFilterAccessible(sourceUserId,
                        filter.mTargetUserId, /* addCrossProfileIntentFilter */ false)) {
                    resolver.removeFilter(filter);
                }
            }
        }
    }
}
+18 −18
Original line number Diff line number Diff line
@@ -1537,7 +1537,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                (i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager(), pm),
                (i, pm) -> IBackupManager.Stub.asInterface(ServiceManager.getService(
                        Context.BACKUP_SERVICE)),
                (i, pm) -> new SharedLibrariesImpl(pm, i));
                (i, pm) -> new SharedLibrariesImpl(pm, i),
                (i, pm) -> new CrossProfileIntentFilterHelper(i.getSettings(),
                        i.getUserManagerService(), i.getLock(), i.getUserManagerInternal(),
                        context));

        if (Build.VERSION.SDK_INT <= 0) {
            Slog.w(TAG, "**** ro.build.version.sdk not set!");
@@ -2029,13 +2032,21 @@ public class PackageManagerService implements PackageSender, TestUtilityService
            final WatchedArrayMap<String, PackageSetting> packageSettings =
                mSettings.getPackagesLocked();

            if (isDeviceUpgrading()) {
                // Save the names of pre-existing packages prior to scanning, so we can determine
                // which system packages are completely new due to an upgrade.
            if (isDeviceUpgrading()) {
                mExistingPackages = new ArraySet<>(packageSettings.size());
                for (PackageSetting ps : packageSettings.values()) {
                    mExistingPackages.add(ps.getPackageName());
                }

                // Triggering {@link com.android.server.pm.crossprofile.
                // CrossProfileIntentFilterHelper.updateDefaultCrossProfileIntentFilter} to update
                // {@link  CrossProfileIntentFilter}s between eligible users and their parent
                t.traceBegin("cross profile intent filter update");
                mInjector.getCrossProfileIntentFilterHelper()
                        .updateDefaultCrossProfileIntentFilter();
                t.traceEnd();
            }

            mCacheDir = PackageManagerServiceUtils.preparePackageParserCache(
@@ -3448,6 +3459,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
        scheduleWritePackageRestrictions(sourceUserId);
    }


    // Enforcing that callingUid is owning pkg on userId
    private void enforceOwnerRights(@NonNull Computer snapshot, String pkg, int callingUid) {
        // The system owns everything.
@@ -4638,21 +4650,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService
            enforceOwnerRights(snapshot, ownerPackage, callingUid);
            PackageManagerServiceUtils.enforceShellRestriction(mInjector.getUserManagerInternal(),
                    UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
            synchronized (mLock) {
                CrossProfileIntentResolver resolver =
                        mSettings.editCrossProfileIntentResolverLPw(sourceUserId);
                ArraySet<CrossProfileIntentFilter> set =
                        new ArraySet<>(resolver.filterSet());
                for (CrossProfileIntentFilter filter : set) {
                    //Only remove if calling user is allowed based on access control of
                    // {@link CrossProfileIntentFilter}
                    if (filter.getOwnerPackage().equals(ownerPackage)
                            && mUserManager.isCrossProfileIntentFilterAccessible(sourceUserId,
                            filter.mTargetUserId, /* addCrossProfileIntentFilter */ false)) {
                        resolver.removeFilter(filter);
                    }
                }
            }
            PackageManagerService.this.mInjector.getCrossProfileIntentFilterHelper()
                            .clearCrossProfileIntentFilters(sourceUserId, ownerPackage,
                                    null);
            scheduleWritePackageRestrictions(sourceUserId);
        }

+13 −1
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ public class PackageManagerServiceInjector {
    private final Singleton<BackgroundDexOptService> mBackgroundDexOptService;
    private final Singleton<IBackupManager> mIBackupManager;
    private final Singleton<SharedLibrariesImpl> mSharedLibrariesProducer;
    private final Singleton<CrossProfileIntentFilterHelper> mCrossProfileIntentFilterHelperProducer;

    PackageManagerServiceInjector(Context context, PackageManagerTracedLock lock,
            Installer installer, Object installLock, PackageAbiHelper abiHelper,
@@ -176,7 +177,8 @@ public class PackageManagerServiceInjector {
            ServiceProducer getSystemServiceProducer,
            Producer<BackgroundDexOptService> backgroundDexOptService,
            Producer<IBackupManager> iBackupManager,
            Producer<SharedLibrariesImpl> sharedLibrariesProducer) {
            Producer<SharedLibrariesImpl> sharedLibrariesProducer,
            Producer<CrossProfileIntentFilterHelper> crossProfileIntentFilterHelperProducer) {
        mContext = context;
        mLock = lock;
        mInstaller = installer;
@@ -228,6 +230,8 @@ public class PackageManagerServiceInjector {
        mBackgroundDexOptService = new Singleton<>(backgroundDexOptService);
        mIBackupManager = new Singleton<>(iBackupManager);
        mSharedLibrariesProducer = new Singleton<>(sharedLibrariesProducer);
        mCrossProfileIntentFilterHelperProducer = new Singleton<>(
                crossProfileIntentFilterHelperProducer);
    }

    /**
@@ -262,6 +266,14 @@ public class PackageManagerServiceInjector {
        return mLock;
    }

    /**
     * {@link CrossProfileIntentFilterHelper} which manages {@link CrossProfileIntentFilter}
     * @return CrossProfileIntentFilterHelper
     */
    public CrossProfileIntentFilterHelper getCrossProfileIntentFilterHelper() {
        return mCrossProfileIntentFilterHelperProducer.get(this, mPackageManager);
    }

    public Installer getInstaller() {
        return mInstaller;
    }
+2 −1
Original line number Diff line number Diff line
@@ -132,7 +132,8 @@ public final class UserTypeFactory {
                        .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_WITH_PARENT)
                        .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_WITH_PARENT)
                        .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT)
                        .setUseParentsContacts(true));
                        .setUseParentsContacts(true)
                        .setUpdateCrossProfileIntentFiltersOnOTA(true));
    }

    /**
Loading