summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ApplicationPackageManager.java15
-rw-r--r--core/java/android/app/role/IRoleManager.aidl6
-rw-r--r--core/java/android/app/role/RoleManager.java56
-rw-r--r--core/java/android/permission/IPermissionManager.aidl4
-rw-r--r--core/java/android/permission/PermissionManagerInternal.java31
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java57
-rw-r--r--services/core/java/com/android/server/pm/DefaultAppProvider.java187
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java53
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java279
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java162
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java181
11 files changed, 518 insertions, 513 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 34437afb614a..3642d318e820 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -30,6 +30,7 @@ import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
+import android.app.role.RoleManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -2306,20 +2307,14 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public String getDefaultBrowserPackageNameAsUser(int userId) {
- try {
- return mPermissionManager.getDefaultBrowser(userId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ RoleManager roleManager = mContext.getSystemService(RoleManager.class);
+ return roleManager.getBrowserRoleHolder(userId);
}
@Override
public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
- try {
- return mPermissionManager.setDefaultBrowser(packageName, userId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ RoleManager roleManager = mContext.getSystemService(RoleManager.class);
+ return roleManager.setBrowserRoleHolder(packageName, userId);
}
@Override
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
index 6d790b381ace..5fc25f0422e2 100644
--- a/core/java/android/app/role/IRoleManager.aidl
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -53,5 +53,9 @@ interface IRoleManager {
List<String> getHeldRolesFromController(in String packageName);
- String getDefaultSmsPackage(int userId);
+ String getBrowserRoleHolder(int userId);
+
+ boolean setBrowserRoleHolder(String packageName, int userId);
+
+ String getSmsRoleHolder(int userId);
}
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 408ce0f2ab1a..8b2e07b09701 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -613,12 +613,56 @@ public final class RoleManager {
}
/**
- * Allows getting the role holder for {@link #ROLE_SMS} without
- * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as required by
- * {@link android.provider.Telephony.Sms#getDefaultSmsPackage(Context)}
+ * Get the role holder of {@link #ROLE_BROWSER} without requiring
+ * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as in
+ * {@link android.content.pm.PackageManager#getDefaultBrowserPackageNameAsUser(int)}
+ *
+ * @param userId the user ID
+ * @return the package name of the default browser, or {@code null} if none
+ *
+ * @hide
+ */
+ @Nullable
+ //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public String getBrowserRoleHolder(@UserIdInt int userId) {
+ try {
+ return mService.getBrowserRoleHolder(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Set the role holder of {@link #ROLE_BROWSER} requiring
+ * {@link Manifest.permission.SET_PREFERRED_APPLICATIONS} instead of
+ * {@link Manifest.permission#MANAGE_ROLE_HOLDERS}, as in
+ * {@link android.content.pm.PackageManager#setDefaultBrowserPackageNameAsUser(String, int)}
+ *
+ * @param packageName the package name of the default browser, or {@code null} if none
+ * @param userId the user ID
+ * @return whether the default browser was set successfully
+ *
+ * @hide
+ */
+ @Nullable
+ @RequiresPermission(Manifest.permission.SET_PREFERRED_APPLICATIONS)
+ //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) {
+ try {
+ return mService.setBrowserRoleHolder(packageName, userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Allows getting the role holder for {@link #ROLE_SMS} without requiring
+ * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as in
+ * {@link android.provider.Telephony.Sms#getDefaultSmsPackage(Context)}.
+ *
+ * @param userId the user ID to get the default SMS package for
+ * @return the package name of the default SMS app, or {@code null} if none
*
- * @param userId The user ID to get the default SMS package for.
- * @return the package name of the default SMS app, or {@code null} if not configured.
* @hide
*/
@Nullable
@@ -626,7 +670,7 @@ public final class RoleManager {
@TestApi
public String getSmsRoleHolder(@UserIdInt int userId) {
try {
- return mService.getDefaultSmsPackage(userId);
+ return mService.getSmsRoleHolder(userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 100166814975..9855a9a98cfb 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -73,10 +73,6 @@ interface IPermissionManager {
void resetRuntimePermissions();
- boolean setDefaultBrowser(String packageName, int userId);
-
- String getDefaultBrowser(int userId);
-
void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId);
void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId);
diff --git a/core/java/android/permission/PermissionManagerInternal.java b/core/java/android/permission/PermissionManagerInternal.java
index 3134ec06fe50..71674311965c 100644
--- a/core/java/android/permission/PermissionManagerInternal.java
+++ b/core/java/android/permission/PermissionManagerInternal.java
@@ -21,10 +21,6 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.os.UserHandle;
-import com.android.internal.util.function.TriFunction;
-
-import java.util.function.BiFunction;
-
/**
* Internal interfaces to be used by other components within the system server.
*
@@ -50,33 +46,6 @@ public abstract class PermissionManagerInternal {
@UserIdInt int userId);
}
- /** Interface to override permission checks via composition */
- public interface CheckPermissionDelegate {
- /**
- * Checks whether the given package has been granted the specified permission.
- *
- * @return If the package has the permission, PERMISSION_GRANTED is
- * returned. If it does not have the permission, PERMISSION_DENIED
- * is returned.
- *
- * @see android.content.pm.PackageManager#checkPermission(String, String)
- */
- int checkPermission(String permName, String pkgName, int userId,
- TriFunction<String, String, Integer, Integer> superImpl);
-
- /**
- /**
- * Checks whether the given uid has been granted the specified permission.
- *
- * @return If the package has the permission, PERMISSION_GRANTED is
- * returned. If it does not have the permission, PERMISSION_DENIED
- * is returned.
- *
- */
- int checkUidPermission(String permName, int uid,
- BiFunction<String, Integer, Integer> superImpl);
- }
-
/**
* Get the state of the runtime permissions as xml file.
*
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 63128ced8f93..bcd122d33f7d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -265,7 +265,6 @@ import android.os.UserManager;
import android.os.WorkSource;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
-import android.permission.PermissionManagerInternal.CheckPermissionDelegate;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.server.ServerProtoEnums;
@@ -326,7 +325,6 @@ import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.QuadFunction;
-import com.android.internal.util.function.TriFunction;
import com.android.server.AlarmManagerInternal;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleInternal;
@@ -394,7 +392,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
-import java.util.function.BiFunction;
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@@ -14486,7 +14483,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mAppOpsService.setMode(AppOpsManager.OP_NO_ISOLATED_STORAGE, app.uid,
app.info.packageName, AppOpsManager.MODE_ERRORED);
mAppOpsService.setAppOpsServiceDelegate(null);
- getPermissionManagerInternalLocked().setCheckPermissionDelegate(null);
+ getPermissionManagerInternalLocked().stopShellPermissionIdentityDelegation();
mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
instr.mUiAutomationConnection).sendToTarget();
}
@@ -17201,12 +17198,6 @@ public class ActivityManagerService extends IActivityManager.Stub
// We allow delegation only to one instrumentation started from the shell
synchronized (ActivityManagerService.this) {
- // If there is a delegate it should be the same instance for app ops and permissions.
- if (mAppOpsService.getAppOpsServiceDelegate()
- != getPermissionManagerInternalLocked().getCheckPermissionDelegate()) {
- throw new IllegalStateException("Bad shell delegate state");
- }
-
// If the delegate is already set up for the target UID, nothing to do.
if (mAppOpsService.getAppOpsServiceDelegate() != null) {
if (!(mAppOpsService.getAppOpsServiceDelegate() instanceof ShellDelegate)) {
@@ -17235,10 +17226,14 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// Hook them up...
- final ShellDelegate shellDelegate = new ShellDelegate(
- instr.mTargetInfo.packageName, delegateUid, permissions);
+ final ShellDelegate shellDelegate = new ShellDelegate(delegateUid,
+ permissions);
mAppOpsService.setAppOpsServiceDelegate(shellDelegate);
- getPermissionManagerInternalLocked().setCheckPermissionDelegate(shellDelegate);
+ final String packageName = instr.mTargetInfo.packageName;
+ final List<String> permissionNames = permissions != null ?
+ Arrays.asList(permissions) : null;
+ getPermissionManagerInternalLocked().startShellPermissionIdentityDelegation(
+ delegateUid, packageName, permissionNames);
return;
}
}
@@ -17252,17 +17247,15 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized (ActivityManagerService.this) {
mAppOpsService.setAppOpsServiceDelegate(null);
- getPermissionManagerInternalLocked().setCheckPermissionDelegate(null);
+ getPermissionManagerInternalLocked().stopShellPermissionIdentityDelegation();
}
}
- private class ShellDelegate implements CheckOpsDelegate, CheckPermissionDelegate {
- private final String mTargetPackageName;
+ private class ShellDelegate implements CheckOpsDelegate {
private final int mTargetUid;
private @Nullable String[] mPermissions;
- ShellDelegate(String targetPackageName, int targetUid, @Nullable String[] permissions) {
- mTargetPackageName = targetPackageName;
+ ShellDelegate(int targetUid, @Nullable String[] permissions) {
mTargetUid = targetUid;
mPermissions = permissions;
}
@@ -17325,34 +17318,6 @@ public class ActivityManagerService extends IActivityManager.Stub
message, shouldCollectMessage);
}
- @Override
- public int checkPermission(String permName, String pkgName, int userId,
- TriFunction<String, String, Integer, Integer> superImpl) {
- if (mTargetPackageName.equals(pkgName) && isTargetPermission(permName)) {
- final long identity = Binder.clearCallingIdentity();
- try {
- return superImpl.apply(permName, "com.android.shell", userId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- return superImpl.apply(permName, pkgName, userId);
- }
-
- @Override
- public int checkUidPermission(String permName, int uid,
- BiFunction<String, Integer, Integer> superImpl) {
- if (uid == mTargetUid && isTargetPermission(permName)) {
- final long identity = Binder.clearCallingIdentity();
- try {
- return superImpl.apply(permName, Process.SHELL_UID);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- return superImpl.apply(permName, uid);
- }
-
private boolean isTargetOp(int code) {
// null permissions means all ops are targeted
if (mPermissions == null) {
diff --git a/services/core/java/com/android/server/pm/DefaultAppProvider.java b/services/core/java/com/android/server/pm/DefaultAppProvider.java
new file mode 100644
index 000000000000..cc11fb2c00bd
--- /dev/null
+++ b/services/core/java/com/android/server/pm/DefaultAppProvider.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.role.RoleManager;
+import android.os.Binder;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.util.CollectionUtils;
+import com.android.server.FgThread;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Interacts with {@link RoleManager} to provide and manage default apps.
+ */
+public class DefaultAppProvider {
+ @NonNull
+ private final Supplier<RoleManager> mRoleManagerSupplier;
+ @NonNull
+ private final PermissionManagerServiceInternal mPermissionManager;
+
+ /**
+ * Create a new instance of this class
+ *
+ * @param roleManagerSupplier the supplier for {@link RoleManager}
+ * @param permissionManager the {@link PermissionManagerServiceInternal}
+ */
+ public DefaultAppProvider(@NonNull Supplier<RoleManager> roleManagerSupplier, @NonNull
+ PermissionManagerServiceInternal permissionManager) {
+ mRoleManagerSupplier = roleManagerSupplier;
+ mPermissionManager = permissionManager;
+ }
+
+ /**
+ * Get the package name of the default browser.
+ *
+ * @param userId the user ID
+ * @return the package name of the default browser, or {@code null} if none
+ */
+ @Nullable
+ public String getDefaultBrowser(@UserIdInt int userId) {
+ return getRoleHolder(RoleManager.ROLE_BROWSER, userId);
+ }
+
+ /**
+ * Set the package name of the default browser.
+ *
+ * @param packageName package name of the default browser, or {@code null} to unset
+ * @param async whether the operation should be asynchronous
+ * @param doGrant whether to grant default permissions
+ * @param userId the user ID
+ * @return whether the default browser was successfully set.
+ */
+ public boolean setDefaultBrowser(@Nullable String packageName, boolean async, boolean doGrant,
+ @UserIdInt int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ return false;
+ }
+ final RoleManager roleManager = mRoleManagerSupplier.get();
+ if (roleManager == null) {
+ return false;
+ }
+ final UserHandle user = UserHandle.of(userId);
+ final Executor executor = FgThread.getExecutor();
+ final AndroidFuture<Void> future = new AndroidFuture<>();
+ final Consumer<Boolean> callback = successful -> {
+ if (successful) {
+ future.complete(null);
+ } else {
+ future.completeExceptionally(new RuntimeException());
+ }
+ };
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (packageName != null) {
+ roleManager.addRoleHolderAsUser(RoleManager.ROLE_BROWSER, packageName, 0, user,
+ executor, callback);
+ } else {
+ roleManager.clearRoleHoldersAsUser(RoleManager.ROLE_BROWSER, 0, user, executor,
+ callback);
+ }
+ if (!async) {
+ try {
+ future.get(5, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ Slog.e(PackageManagerService.TAG, "Exception while setting default browser: "
+ + packageName, e);
+ return false;
+ }
+ }
+ if (doGrant && packageName != null) {
+ mPermissionManager.grantDefaultPermissionsToDefaultBrowser(packageName, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return true;
+ }
+
+ /**
+ * Get the package name of the default dialer.
+ *
+ * @param userId the user ID
+ * @return the package name of the default dialer, or {@code null} if none
+ */
+ @Nullable
+ public String getDefaultDialer(@NonNull int userId) {
+ return getRoleHolder(RoleManager.ROLE_DIALER, userId);
+ }
+
+ /**
+ * Get the package name of the default home.
+ *
+ * @param userId the user ID
+ * @return the package name of the default home, or {@code null} if none
+ */
+ @Nullable
+ public String getDefaultHome(@NonNull int userId) {
+ return getRoleHolder(RoleManager.ROLE_HOME, userId);
+ }
+
+ /**
+ * Set the package name of the default home.
+ *
+ * @param packageName package name of the default home
+ * @param userId the user ID
+ * @param executor the {@link Executor} to execute callback on
+ * @param callback the callback made after the default home as been updated
+ * @return whether the default home was set
+ */
+ public boolean setDefaultHome(@NonNull String packageName, @UserIdInt int userId,
+ @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
+ final RoleManager roleManager = mRoleManagerSupplier.get();
+ if (roleManager == null) {
+ return false;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, packageName, 0,
+ UserHandle.of(userId), executor, callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return true;
+ }
+
+ @Nullable
+ private String getRoleHolder(@NonNull String roleName, @NonNull int userId) {
+ final RoleManager roleManager = mRoleManagerSupplier.get();
+ if (roleManager == null) {
+ return null;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return CollectionUtils.firstOrNull(roleManager.getRoleHoldersAsUser(roleName,
+ UserHandle.of(userId)));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9a0be06b914e..cd4fe5723a83 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -152,6 +152,7 @@ import android.app.ResourcesManager;
import android.app.admin.IDevicePolicyManager;
import android.app.admin.SecurityLog;
import android.app.backup.IBackupManager;
+import android.app.role.RoleManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
@@ -940,6 +941,7 @@ public class PackageManagerService extends IPackageManager.Stub
private final Singleton<ViewCompiler> mViewCompilerProducer;
private final Singleton<IPermissionManager> mPermissionManagerProducer;
private final Singleton<IncrementalManager> mIncrementalManagerProducer;
+ private final Singleton<DefaultAppProvider> mDefaultAppProviderProducer;
private final SystemWrapper mSystemWrapper;
private final ServiceProducer mGetLocalServiceProducer;
private final ServiceProducer mGetSystemServiceProducer;
@@ -961,6 +963,7 @@ public class PackageManagerService extends IPackageManager.Stub
Producer<IPermissionManager> permissionManagerProducer,
Producer<ViewCompiler> viewCompilerProducer,
Producer<IncrementalManager> incrementalManagerProducer,
+ Producer<DefaultAppProvider> defaultAppProviderProducer,
SystemWrapper systemWrapper,
ServiceProducer getLocalServiceProducer,
ServiceProducer getSystemServiceProducer) {
@@ -985,6 +988,7 @@ public class PackageManagerService extends IPackageManager.Stub
mPermissionManagerProducer = new Singleton<>(permissionManagerProducer);
mViewCompilerProducer = new Singleton<>(viewCompilerProducer);
mIncrementalManagerProducer = new Singleton<>(incrementalManagerProducer);
+ mDefaultAppProviderProducer = new Singleton<>(defaultAppProviderProducer);
mSystemWrapper = systemWrapper;
mGetLocalServiceProducer = getLocalServiceProducer;
mGetSystemServiceProducer = getSystemServiceProducer;
@@ -1097,6 +1101,10 @@ public class PackageManagerService extends IPackageManager.Stub
public IncrementalManager getIncrementalManager() {
return mIncrementalManagerProducer.get(this, mPackageManager);
}
+
+ public DefaultAppProvider getDefaultAppProvider() {
+ return mDefaultAppProviderProducer.get(this, mPackageManager);
+ }
}
/** Provides an abstraction to static access to system state. */
@@ -1154,6 +1162,7 @@ public class PackageManagerService extends IPackageManager.Stub
public ArtManagerService artManagerService;
public @Nullable String configuratorPackage;
public int defParseFlags;
+ public DefaultAppProvider defaultAppProvider;
public DexManager dexManager;
public List<ScanPartition> dirsToScanAsSystem;
public @Nullable String documenterPackage;
@@ -1307,6 +1316,8 @@ public class PackageManagerService extends IPackageManager.Stub
private final IncrementalManager mIncrementalManager;
+ private final DefaultAppProvider mDefaultAppProvider;
+
private final PackageProperty mPackageProperty = new PackageProperty();
private static class IFVerificationParams {
@@ -2769,6 +2780,8 @@ public class PackageManagerService extends IPackageManager.Stub
(i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
(i, pm) -> (IncrementalManager)
pm.mContext.getSystemService(Context.INCREMENTAL_SERVICE),
+ (i, pm) -> new DefaultAppProvider(() -> context.getSystemService(RoleManager.class),
+ i.getPermissionManagerServiceInternal()),
new DefaultSystemWrapper(),
LocalServices::getService,
context::getSystemService);
@@ -2944,6 +2957,7 @@ public class PackageManagerService extends IPackageManager.Stub
mArtManagerService = testParams.artManagerService;
mAvailableFeatures = testParams.availableFeatures;
mDefParseFlags = testParams.defParseFlags;
+ mDefaultAppProvider = testParams.defaultAppProvider;
mDexManager = testParams.dexManager;
mDirsToScanAsSystem = testParams.dirsToScanAsSystem;
mFactoryTest = testParams.factoryTest;
@@ -3051,6 +3065,7 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings = injector.getSettings();
mPermissionManagerService = injector.getPermissionManagerService();
mIncrementalManager = mInjector.getIncrementalManager();
+ mDefaultAppProvider = mInjector.getDefaultAppProvider();
PlatformCompat platformCompat = mInjector.getCompatibility();
mPackageParserCallback = new PackageParser2.Callback() {
@Override
@@ -7964,8 +7979,8 @@ public class PackageManagerService extends IPackageManager.Stub
} else {
// Browser/generic handling case. If there's a default browser, go straight
// to that (but only if there is no other higher-priority match).
- final String defaultBrowserPackageName =
- mPermissionManager.getDefaultBrowser(userId);
+ final String defaultBrowserPackageName = mDefaultAppProvider.getDefaultBrowser(
+ userId);
int maxMatchPrio = 0;
ResolveInfo defaultBrowserMatch = null;
final int numCandidates = matchAllList.size();
@@ -14162,8 +14177,8 @@ public class PackageManagerService extends IPackageManager.Stub
final boolean isCallerOwner = isCallerDeviceOrProfileOwner(userId);
final long callingId = Binder.clearCallingIdentity();
try {
- final String activeLauncherPackageName = mPermissionManager.getDefaultHome(userId);
- final String dialerPackageName = mPermissionManager.getDefaultDialer(userId);
+ final String activeLauncherPackageName = mDefaultAppProvider.getDefaultHome(userId);
+ final String dialerPackageName = mDefaultAppProvider.getDefaultDialer(userId);
for (int i = 0; i < packageNames.length; i++) {
canSuspend[i] = false;
final String packageName = packageNames[i];
@@ -20621,10 +20636,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
private void clearDefaultBrowserIfNeededForUser(String packageName, int userId) {
- final String defaultBrowserPackageName = mPermissionManager.getDefaultBrowser(userId);
+ final String defaultBrowserPackageName = mDefaultAppProvider.getDefaultBrowser(userId);
if (!TextUtils.isEmpty(defaultBrowserPackageName)) {
if (packageName.equals(defaultBrowserPackageName)) {
- mPermissionManager.setDefaultBrowser(null, true, true, userId);
+ mDefaultAppProvider.setDefaultBrowser(null, true, true, userId);
}
}
}
@@ -20639,7 +20654,7 @@ public class PackageManagerService extends IPackageManager.Stub
// If this browser is restored from user's backup, do not clear
// default-browser state for this user
if (installReason != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
- mPermissionManager.setDefaultBrowser(null, true, true, userId);
+ mDefaultAppProvider.setDefaultBrowser(null, true, true, userId);
}
}
@@ -20678,7 +20693,7 @@ public class PackageManagerService extends IPackageManager.Stub
// significant refactoring to keep all default apps in the package
// manager (cleaner but more work) or have the services provide
// callbacks to the package manager to request a default app reset.
- mPermissionManager.setDefaultBrowser(null, true, true, userId);
+ mDefaultAppProvider.setDefaultBrowser(null, true, true, userId);
resetNetworkPolicies(userId);
synchronized (mLock) {
scheduleWritePackageRestrictionsLocked(userId);
@@ -20912,8 +20927,8 @@ public class PackageManagerService extends IPackageManager.Stub
defaultBrowser = mSettings.removeDefaultBrowserPackageNameLPw(userId1);
}
if (defaultBrowser != null) {
- mPermissionManager
- .setDefaultBrowser(defaultBrowser, false, false, userId1);
+ mDefaultAppProvider.setDefaultBrowser(defaultBrowser, false, false,
+ userId1);
}
});
} catch (Exception e) {
@@ -21153,7 +21168,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
allHomeCandidates.addAll(resolveInfos);
- final String packageName = mPermissionManager.getDefaultHome(userId);
+ final String packageName = mDefaultAppProvider.getDefaultHome(userId);
if (packageName == null) {
return null;
}
@@ -21207,7 +21222,7 @@ public class PackageManagerService extends IPackageManager.Stub
final String packageName = preferredResolveInfo != null
&& preferredResolveInfo.activityInfo != null
? preferredResolveInfo.activityInfo.packageName : null;
- final String currentPackageName = mPermissionManager.getDefaultHome(userId);
+ final String currentPackageName = mDefaultAppProvider.getDefaultHome(userId);
if (TextUtils.equals(currentPackageName, packageName)) {
return false;
}
@@ -21222,12 +21237,12 @@ public class PackageManagerService extends IPackageManager.Stub
// Keep the default home package in RoleManager.
return false;
}
- mPermissionManager.setDefaultHome(packageName, userId, (successful) -> {
- if (successful) {
- postPreferredActivityChangedBroadcast(userId);
- }
- });
- return true;
+ return mDefaultAppProvider.setDefaultHome(packageName, userId, mContext.getMainExecutor(),
+ successful -> {
+ if (successful) {
+ postPreferredActivityChangedBroadcast(userId);
+ }
+ });
}
@Override
@@ -24977,7 +24992,7 @@ public class PackageManagerService extends IPackageManager.Stub
private String[] getKnownPackageNamesInternal(int knownPackage, int userId) {
switch (knownPackage) {
case PackageManagerInternal.PACKAGE_BROWSER:
- return new String[]{mPermissionManager.getDefaultBrowser(userId)};
+ return new String[] { mDefaultAppProvider.getDefaultBrowser(userId) };
case PackageManagerInternal.PACKAGE_INSTALLER:
return filterOnlySystemPackages(mRequiredInstallerPackage);
case PackageManagerInternal.PACKAGE_SETUP_WIZARD:
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 48e18f1b8b38..7ed887d9680a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -114,7 +114,6 @@ import android.permission.IPermissionManager;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.permission.PermissionManagerInternal;
-import android.permission.PermissionManagerInternal.CheckPermissionDelegate;
import android.permission.PermissionManagerInternal.OnRuntimePermissionStateChangedListener;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -138,6 +137,7 @@ import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IntPair;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.TriFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -151,9 +151,6 @@ import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultBrowserProvider;
-import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultDialerProvider;
-import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultHomeProvider;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.SoftRestrictedPermissionPolicy;
@@ -176,7 +173,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.function.Consumer;
+import java.util.function.BiFunction;
/**
* Manages all permissions and handles permissions related tasks.
@@ -304,15 +301,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@NonNull
private final OnPermissionChangeListeners mOnPermissionChangeListeners;
- @GuardedBy("mLock")
- private DefaultBrowserProvider mDefaultBrowserProvider;
-
- @GuardedBy("mLock")
- private DefaultDialerProvider mDefaultDialerProvider;
-
- @GuardedBy("mLock")
- private DefaultHomeProvider mDefaultHomeProvider;
-
// TODO: Take a look at the methods defined in the callback.
// The callback was initially created to support the split between permission
// manager and the package manager. However, it's started to be used for other
@@ -2018,60 +2006,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public String getDefaultBrowser(int userId) {
- final int callingUid = Binder.getCallingUid();
- if (UserHandle.getUserId(callingUid) != userId) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
- }
- if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
- return null;
- }
- DefaultBrowserProvider provider;
- synchronized (mLock) {
- provider = mDefaultBrowserProvider;
- }
- return provider != null ? provider.getDefaultBrowser(userId) : null;
- }
-
- @Override
- public boolean setDefaultBrowser(String packageName, int userId) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
- if (UserHandle.getCallingUserId() != userId) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
- }
- return setDefaultBrowserInternal(packageName, false, true, userId);
- }
-
- private boolean setDefaultBrowserInternal(String packageName, boolean async,
- boolean doGrant, int userId) {
- if (userId == UserHandle.USER_ALL) {
- return false;
- }
- DefaultBrowserProvider provider;
- synchronized (mLock) {
- provider = mDefaultBrowserProvider;
- }
- if (provider == null) {
- return false;
- }
- if (async) {
- provider.setDefaultBrowserAsync(packageName, userId);
- } else {
- if (!provider.setDefaultBrowser(packageName, userId)) {
- return false;
- }
- }
- if (doGrant && packageName != null) {
- mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(packageName,
- userId);
- }
- return true;
- }
-
- @Override
public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
final int callingUid = Binder.getCallingUid();
PackageManagerServiceUtils
@@ -2360,6 +2294,32 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
+ private void startShellPermissionIdentityDelegationInternal(int uid,
+ @NonNull String packageName, @Nullable List<String> permissionNames) {
+ synchronized (mLock) {
+ final CheckPermissionDelegate oldDelegate = mCheckPermissionDelegate;
+ if (oldDelegate != null && oldDelegate.getDelegatedUid() != uid) {
+ throw new SecurityException(
+ "Shell can delegate permissions only to one UID at a time");
+ }
+ final ShellDelegate delegate = new ShellDelegate(uid, packageName, permissionNames);
+ setCheckPermissionDelegateLocked(delegate);
+ }
+ }
+
+ private void stopShellPermissionIdentityDelegationInternal() {
+ synchronized (mLock) {
+ setCheckPermissionDelegateLocked(null);
+ }
+ }
+
+ private void setCheckPermissionDelegateLocked(@Nullable CheckPermissionDelegate delegate) {
+ if (delegate != null || mCheckPermissionDelegate != null) {
+ PackageManager.invalidatePackageInfoCache();
+ }
+ mCheckPermissionDelegate = delegate;
+ }
+
/**
* If the app is updated, and has scoped storage permissions, then it is possible that the
* app updated in an attempt to get unscoped storage. If so, revoke all storage permissions.
@@ -5233,62 +5193,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public CheckPermissionDelegate getCheckPermissionDelegate() {
- synchronized (mLock) {
- return mCheckPermissionDelegate;
- }
- }
-
- @Override
- public void setCheckPermissionDelegate(CheckPermissionDelegate delegate) {
- synchronized (mLock) {
- if (delegate != null || mCheckPermissionDelegate != null) {
- PackageManager.invalidatePackageInfoCache();
- }
- mCheckPermissionDelegate = delegate;
- }
- }
-
- @Override
- public void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider) {
- synchronized (mLock) {
- mDefaultBrowserProvider = provider;
- }
- }
-
- @Override
- public void setDefaultBrowser(String packageName, boolean async, boolean doGrant,
- int userId) {
- setDefaultBrowserInternal(packageName, async, doGrant, userId);
- }
-
- @Override
- public void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider) {
- synchronized (mLock) {
- mDefaultDialerProvider = provider;
- }
- }
-
- @Override
- public void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider) {
- synchronized (mLock) {
- mDefaultHomeProvider = provider;
- }
+ public void startShellPermissionIdentityDelegation(int uid, @NonNull String packageName,
+ @Nullable List<String> permissionNames) {
+ Objects.requireNonNull(packageName, "packageName");
+ startShellPermissionIdentityDelegationInternal(uid, packageName, permissionNames);
}
@Override
- public void setDefaultHome(String packageName, int userId, Consumer<Boolean> callback) {
- if (userId == UserHandle.USER_ALL) {
- return;
- }
- DefaultHomeProvider provider;
- synchronized (mLock) {
- provider = mDefaultHomeProvider;
- }
- if (provider == null) {
- return;
- }
- provider.setDefaultHomeAsync(packageName, userId, callback);
+ public void stopShellPermissionIdentityDelegation() {
+ stopShellPermissionIdentityDelegationInternal();
}
@Override
@@ -5332,30 +5245,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public String getDefaultBrowser(int userId) {
- DefaultBrowserProvider provider;
- synchronized (mLock) {
- provider = mDefaultBrowserProvider;
- }
- return provider != null ? provider.getDefaultBrowser(userId) : null;
- }
-
- @Override
- public String getDefaultDialer(int userId) {
- DefaultDialerProvider provider;
- synchronized (mLock) {
- provider = mDefaultDialerProvider;
- }
- return provider != null ? provider.getDefaultDialer(userId) : null;
- }
-
- @Override
- public String getDefaultHome(int userId) {
- DefaultHomeProvider provider;
- synchronized (mLock) {
- provider = mDefaultHomeProvider;
- }
- return provider != null ? provider.getDefaultHome(userId) : null;
+ public void grantDefaultPermissionsToDefaultBrowser(@NonNull String packageName,
+ @UserIdInt int userId) {
+ mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(packageName,
+ userId);
}
@Override
@@ -5545,6 +5438,102 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
/**
+ * Interface to intercept permission checks and optionally pass through to the original
+ * implementation.
+ */
+ private interface CheckPermissionDelegate {
+ /**
+ * Get the UID whose permission checks is being delegated.
+ *
+ * @return the UID
+ */
+ int getDelegatedUid();
+
+ /**
+ * Check whether the given package has been granted the specified permission.
+ *
+ * @param permissionName the name of the permission to be checked
+ * @param packageName the name of the package to be checked
+ * @param userId the user ID
+ * @param superImpl the original implementation that can be delegated to
+ * @return {@link android.content.pm.PackageManager.PERMISSION_GRANTED} if the package has
+ * the permission, or {@link android.content.pm.PackageManager.PERMISSION_DENITED} otherwise
+ *
+ * @see android.content.pm.PackageManager#checkPermission(String, String)
+ */
+ int checkPermission(@NonNull String permissionName, @NonNull String packageName,
+ @UserIdInt int userId,
+ @NonNull TriFunction<String, String, Integer, Integer> superImpl);
+
+ /**
+ * Check whether the given UID has been granted the specified permission.
+ *
+ * @param permissionName the name of the permission to be checked
+ * @param uid the UID to be checked
+ * @param superImpl the original implementation that can be delegated to
+ * @return {@link android.content.pm.PackageManager.PERMISSION_GRANTED} if the package has
+ * the permission, or {@link android.content.pm.PackageManager.PERMISSION_DENITED} otherwise
+ */
+ int checkUidPermission(@NonNull String permissionName, int uid,
+ BiFunction<String, Integer, Integer> superImpl);
+ }
+
+ private class ShellDelegate implements CheckPermissionDelegate {
+ private final int mDelegatedUid;
+ @NonNull
+ private final String mDelegatedPackageName;
+ @Nullable
+ private final List<String> mDelegatedPermissionNames;
+
+ public ShellDelegate(int delegatedUid, @NonNull String delegatedPackageName,
+ @Nullable List<String> delegatedPermissionNames) {
+ mDelegatedUid = delegatedUid;
+ mDelegatedPackageName = delegatedPackageName;
+ mDelegatedPermissionNames = delegatedPermissionNames;
+ }
+
+ @Override
+ public int getDelegatedUid() {
+ return mDelegatedUid;
+ }
+
+ @Override
+ public int checkPermission(@NonNull String permissionName, @NonNull String packageName,
+ int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl) {
+ if (mDelegatedPackageName.equals(packageName)
+ && isDelegatedPermission(permissionName)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return superImpl.apply(permissionName, "com.android.shell", userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return superImpl.apply(permissionName, packageName, userId);
+ }
+
+ @Override
+ public int checkUidPermission(@NonNull String permissionName, int uid,
+ @NonNull BiFunction<String, Integer, Integer> superImpl) {
+ if (uid == mDelegatedUid && isDelegatedPermission(permissionName)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return superImpl.apply(permissionName, Process.SHELL_UID);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return superImpl.apply(permissionName, uid);
+ }
+
+ private boolean isDelegatedPermission(@NonNull String permissionName) {
+ // null permissions means all permissions are targeted
+ return mDelegatedPermissionNames == null
+ || mDelegatedPermissionNames.contains(permissionName);
+ }
+ }
+
+ /**
* Allows injection of services and method responses to facilitate testing.
*
* <p>Test classes can create a mock of this class and pass it to the PermissionManagerService
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index f924651f1051..e006fa784cce 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -30,7 +30,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import java.util.function.Consumer;
/**
* Internal interfaces services.
@@ -66,82 +65,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
String[] getPackages(String authority, int userId);
}
- /**
- * Provider for default browser
- */
- public interface DefaultBrowserProvider {
-
- /**
- * Get the package name of the default browser.
- *
- * @param userId the user id
- *
- * @return the package name of the default browser, or {@code null} if none
- */
- @Nullable
- String getDefaultBrowser(@UserIdInt int userId);
-
- /**
- * Set the package name of the default browser.
- *
- * @param packageName package name of the default browser, or {@code null} to remove
- * @param userId the user id
- *
- * @return whether the default browser was successfully set.
- */
- boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId);
-
- /**
- * Set the package name of the default browser asynchronously.
- *
- * @param packageName package name of the default browser, or {@code null} to remove
- * @param userId the user id
- */
- void setDefaultBrowserAsync(@Nullable String packageName, @UserIdInt int userId);
- }
-
- /**
- * Provider for default dialer
- */
- public interface DefaultDialerProvider {
-
- /**
- * Get the package name of the default dialer.
- *
- * @param userId the user id
- *
- * @return the package name of the default dialer, or {@code null} if none
- */
- @Nullable
- String getDefaultDialer(@UserIdInt int userId);
- }
-
- /**
- * Provider for default home
- */
- public interface DefaultHomeProvider {
-
- /**
- * Get the package name of the default home.
- *
- * @param userId the user id
- *
- * @return the package name of the default home, or {@code null} if none
- */
- @Nullable
- String getDefaultHome(@UserIdInt int userId);
-
- /**
- * Set the package name of the default home.
- *
- * @param packageName package name of the default home, or {@code null} to remove
- * @param userId the user id
- * @param callback the callback made after the default home as been updated
- */
- void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId,
- @NonNull Consumer<Boolean> callback);
- }
-
public abstract void systemReady();
/**
@@ -257,18 +180,24 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
@PermissionInfo.ProtectionFlags int protectionFlags);
/**
- * Returns the delegate used to influence permission checking.
+ * Start delegate the permission identity of the shell UID to the given UID.
*
- * @return The delegate instance.
+ * @param uid the UID to delegate shell permission identity to
+ * @param packageName the name of the package to delegate shell permission identity to
+ * @param permissionNames the names of the permissions to delegate shell permission identity
+ * for, or {@code null} for all permissions
*/
- public abstract @Nullable CheckPermissionDelegate getCheckPermissionDelegate();
+ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ public abstract void startShellPermissionIdentityDelegation(int uid,
+ @NonNull String packageName, @Nullable List<String> permissionNames);
/**
- * Sets the delegate used to influence permission checking.
+ * Stop delegating the permission identity of the shell UID.
*
- * @param delegate A delegate instance or {@code null} to clear.
+ * @see #startShellPermissionIdentityDelegation(int, String, List)
*/
- public abstract void setCheckPermissionDelegate(@Nullable CheckPermissionDelegate delegate);
+ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ public abstract void stopShellPermissionIdentityDelegation();
/**
* Sets the dialer application packages provider.
@@ -319,69 +248,12 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider);
/**
- * Sets the default browser provider.
- *
- * @param provider the provider
- */
- public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider);
-
- /**
- * Sets the package name of the default browser provider for the given user.
- *
- * @param packageName The package name of the default browser or {@code null}
- * to clear the default browser
- * @param async If {@code true}, set the default browser asynchronously,
- * otherwise set it synchronously
- * @param doGrant If {@code true} and if {@code packageName} is not {@code null},
- * perform default permission grants on the browser, otherwise skip the
- * default permission grants.
- * @param userId The user to set the default browser for.
- */
- public abstract void setDefaultBrowser(@Nullable String packageName, boolean async,
- boolean doGrant, @UserIdInt int userId);
-
- /**
- * Sets the default dialer provider.
- *
- * @param provider the provider
- */
- public abstract void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider);
-
- /**
- * Sets the default home provider.
- *
- * @param provider the provider
- */
- public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider);
-
- /**
- * Asynchronously sets the package name of the default home provider for the given user.
- *
- * @param packageName The package name of the default home or {@code null}
- * to clear the default browser
- * @param userId The user to set the default browser for
- * @param callback Invoked after the default home has been set
- */
- public abstract void setDefaultHome(@Nullable String packageName, @UserIdInt int userId,
- @NonNull Consumer<Boolean> callback);
-
- /**
- * Returns the default browser package name for the given user.
- */
- @Nullable
- public abstract String getDefaultBrowser(@UserIdInt int userId);
-
- /**
- * Returns the default dialer package name for the given user.
- */
- @Nullable
- public abstract String getDefaultDialer(@UserIdInt int userId);
-
- /**
- * Returns the default home package name for the given user.
+ * Requests granting of the default permissions to the current default browser.
+ * @param packageName The default browser package name.
+ * @param userId The user for which to grant the permissions.
*/
- @Nullable
- public abstract String getDefaultHome(@UserIdInt int userId);
+ public abstract void grantDefaultPermissionsToDefaultBrowser(
+ @NonNull String packageName, @UserIdInt int userId);
/**
* Requests granting of the default permissions to the current default Use Open Wifi app.
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index ab6ada2f85f7..3d91a8502097 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -83,7 +83,6 @@ import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.function.Consumer;
/**
* Service for role management.
@@ -162,12 +161,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
LocalServices.addService(RoleManagerInternal.class, new Internal());
- PermissionManagerServiceInternal permissionManagerInternal =
- LocalServices.getService(PermissionManagerServiceInternal.class);
- permissionManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider());
- permissionManagerInternal.setDefaultDialerProvider(new DefaultDialerProvider());
- permissionManagerInternal.setDefaultHomeProvider(new DefaultHomeProvider());
-
registerUserRemovedReceiver();
}
@@ -657,12 +650,84 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
resultReceiver);
}
+ @Nullable
@Override
- public String getDefaultSmsPackage(int userId) {
+ public String getBrowserRoleHolder(@UserIdInt int userId) {
+ final int callingUid = Binder.getCallingUid();
+ if (UserHandle.getUserId(callingUid) != userId) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+ }
+ final PackageManagerInternal packageManager = LocalServices.getService(
+ PackageManagerInternal.class);
+ if (packageManager.getInstantAppPackageName(callingUid) != null) {
+ return null;
+ }
+
final long identity = Binder.clearCallingIdentity();
try {
- return CollectionUtils.firstOrNull(
- getRoleHoldersAsUser(RoleManager.ROLE_SMS, userId));
+ return CollectionUtils.firstOrNull(getRoleHoldersAsUser(RoleManager.ROLE_BROWSER,
+ userId));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) {
+ final Context context = getContext();
+ context.enforceCallingOrSelfPermission(
+ android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
+ if (UserHandle.getCallingUserId() != userId) {
+ context.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+ }
+
+ if (!mUserManagerInternal.exists(userId)) {
+ return false;
+ }
+
+ final AndroidFuture<Void> future = new AndroidFuture<>();
+ final RemoteCallback callback = new RemoteCallback(result -> {
+ boolean successful = result != null;
+ if (successful) {
+ future.complete(null);
+ } else {
+ future.completeExceptionally(new RuntimeException());
+ }
+ });
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (packageName != null) {
+ addRoleHolderAsUser(RoleManager.ROLE_BROWSER, packageName, 0, userId, callback);
+ } else {
+ clearRoleHoldersAsUser(RoleManager.ROLE_BROWSER, 0, userId, callback);
+ }
+ try {
+ future.get(5, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ Slog.e(LOG_TAG, "Exception while setting default browser: " + packageName, e);
+ return false;
+ }
+
+ if (packageName != null) {
+ final PermissionManagerServiceInternal permissionManager =
+ LocalServices.getService(PermissionManagerServiceInternal.class);
+ permissionManager.grantDefaultPermissionsToDefaultBrowser(packageName, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ return true;
+ }
+
+ @Override
+ public String getSmsRoleHolder(int userId) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return CollectionUtils.firstOrNull(getRoleHoldersAsUser(RoleManager.ROLE_SMS,
+ userId));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -718,100 +783,4 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
return getOrCreateUserState(userId).getRolesAndHolders();
}
}
-
- private class DefaultBrowserProvider implements
- PermissionManagerServiceInternal.DefaultBrowserProvider {
-
- @Nullable
- @Override
- public String getDefaultBrowser(@UserIdInt int userId) {
- return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders(
- RoleManager.ROLE_BROWSER));
- }
-
- @Override
- public boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) {
- AndroidFuture<Void> future = new AndroidFuture<>();
- RemoteCallback callback = new RemoteCallback(result -> {
- boolean successful = result != null;
- if (successful) {
- future.complete(null);
- } else {
- future.completeExceptionally(new RuntimeException());
- }
- });
- if (packageName != null) {
- getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
- packageName, 0, callback);
- } else {
- getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
- callback);
- }
- try {
- future.get(5, TimeUnit.SECONDS);
- return true;
- } catch (InterruptedException | ExecutionException | TimeoutException e) {
- Slog.e(LOG_TAG, "Exception while setting default browser: " + packageName, e);
- return false;
- }
- }
-
- @Override
- public void setDefaultBrowserAsync(@Nullable String packageName, @UserIdInt int userId) {
- RemoteCallback callback = new RemoteCallback(result -> {
- boolean successful = result != null;
- if (!successful) {
- Slog.e(LOG_TAG, "Failed to set default browser: " + packageName);
- }
- });
- if (packageName != null) {
- getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
- packageName, 0, callback);
- } else {
- getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
- callback);
- }
- }
- }
-
- private class DefaultDialerProvider implements
- PermissionManagerServiceInternal.DefaultDialerProvider {
-
- @Nullable
- @Override
- public String getDefaultDialer(@UserIdInt int userId) {
- return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders(
- RoleManager.ROLE_DIALER));
- }
- }
-
- private class DefaultHomeProvider implements
- PermissionManagerServiceInternal.DefaultHomeProvider {
-
- @Nullable
- @Override
- public String getDefaultHome(@UserIdInt int userId) {
- return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders(
- RoleManager.ROLE_HOME));
- }
-
- @Override
- public void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId,
- @NonNull Consumer<Boolean> callback) {
- RemoteCallback remoteCallback = new RemoteCallback(result -> {
- boolean successful = result != null;
- if (!successful) {
- Slog.e(LOG_TAG, "Failed to set default home: " + packageName);
- }
- callback.accept(successful);
- });
- if (packageName != null) {
- getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
- packageName, 0, remoteCallback);
- } else {
- getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
- remoteCallback);
- }
- }
- }
}