Merge "Update mechanism for CrossProfileIntentFilters on OTA"

This commit is contained in:
Sarup Dalwani
2022-12-13 16:16:03 +00:00
committed by Android (Google) Code Review
6 changed files with 195 additions and 22 deletions

View File

@@ -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);
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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);
}
}
}
}
}

View File

@@ -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();
// 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()) {
// Save the names of pre-existing packages prior to scanning, so we can determine
// which system packages are completely new due to an upgrade.
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);
}

View File

@@ -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;
}

View File

@@ -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));
}
/**

View File

@@ -193,6 +193,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
val incrementalManager: IncrementalManager = mock()
val platformCompat: PlatformCompat = mock()
val settings: Settings = mock()
val crossProfileIntentFilterHelper: CrossProfileIntentFilterHelper = mock()
val resources: Resources = mock()
val systemConfig: SystemConfig = mock()
val apexManager: ApexManager = mock()
@@ -279,6 +280,8 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
whenever(mocks.injector.incrementalManager).thenReturn(mocks.incrementalManager)
whenever(mocks.injector.compatibility).thenReturn(mocks.platformCompat)
whenever(mocks.injector.settings).thenReturn(mocks.settings)
whenever(mocks.injector.crossProfileIntentFilterHelper)
.thenReturn(mocks.crossProfileIntentFilterHelper)
whenever(mocks.injector.dexManager).thenReturn(mocks.dexManager)
whenever(mocks.injector.systemConfig).thenReturn(mocks.systemConfig)
whenever(mocks.injector.apexManager).thenReturn(mocks.apexManager)