Merge "Update mechanism for CrossProfileIntentFilters on OTA"
This commit is contained in:
committed by
Android (Google) Code Review
commit
29c944cd5a
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user