Merge "Explicitly allow access to share targets by package" into tm-dev am: 09f39ec2fd am: e96155bd5a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17669233
Change-Id: I24c58dd416f0729d9c8471d89adf8e045095e9c0
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 056f255..9627c43 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -105,6 +105,7 @@
import android.util.Xml;
import android.view.IWindowManager;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -455,6 +456,8 @@
private final boolean mIsAppSearchEnabled;
+ private ComponentName mChooserActivity;
+
static class InvalidFileFormatException extends Exception {
public InvalidFileFormatException(String message, Throwable cause) {
super(message, cause);
@@ -1646,6 +1649,26 @@
return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
}
+ @VisibleForTesting
+ ComponentName injectChooserActivity() {
+ if (mChooserActivity == null) {
+ mChooserActivity = ComponentName.unflattenFromString(
+ mContext.getResources().getString(R.string.config_chooserActivity));
+ }
+ return mChooserActivity;
+ }
+
+ private boolean isCallerChooserActivity() {
+ // TODO(b/228975502): Migrate this check to a proper permission or role check
+ final int callingUid = injectBinderCallingUid();
+ ComponentName systemChooser = injectChooserActivity();
+ if (systemChooser == null) {
+ return false;
+ }
+ int uid = injectGetPackageUid(systemChooser.getPackageName(), UserHandle.USER_SYSTEM);
+ return uid == callingUid;
+ }
+
private void enforceSystemOrShell() {
if (!(isCallerSystem() || isCallerShell())) {
throw new SecurityException("Caller must be system or shell");
@@ -2525,7 +2548,9 @@
IntentFilter filter, @UserIdInt int userId) {
Preconditions.checkStringNotEmpty(packageName, "packageName");
Objects.requireNonNull(filter, "intentFilter");
- verifyCaller(packageName, userId);
+ if (!isCallerChooserActivity()) {
+ verifyCaller(packageName, userId);
+ }
enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS,
"getShareTargets");
synchronized (mLock) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index a79a52c..e4ee4d06 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -538,6 +538,11 @@
}
@Override
+ ComponentName injectChooserActivity() {
+ return mInjectedChooserActivity;
+ }
+
+ @Override
void wtf(String message, Throwable th) {
// During tests, WTF is fatal.
fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
@@ -678,6 +683,7 @@
protected int mInjectedCallingUid;
protected String mInjectedClientPackage;
+ protected ComponentName mInjectedChooserActivity;
protected Map<String, PackageInfo> mInjectedPackages;
@@ -723,6 +729,9 @@
protected static final String LAUNCHER_4 = "com.android.launcher.4";
protected static final int LAUNCHER_UID_4 = 10014;
+ protected static final String CHOOSER_ACTIVITY_PACKAGE = "com.android.intentresolver";
+ protected static final int CHOOSER_ACTIVITY_UID = 10015;
+
protected static final int USER_0 = UserHandle.USER_SYSTEM;
protected static final int USER_10 = 10;
protected static final int USER_11 = 11;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index a350dfb..867890f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -6901,6 +6901,9 @@
}
public void testGetShareTargets_permission() {
+ addPackage(CHOOSER_ACTIVITY_PACKAGE, CHOOSER_ACTIVITY_UID, 10, "sig1");
+ mInjectedChooserActivity =
+ ComponentName.createRelative(CHOOSER_ACTIVITY_PACKAGE, ".ChooserActivity");
IntentFilter filter = new IntentFilter();
assertExpectException(SecurityException.class, "Missing permission", () ->
@@ -6909,6 +6912,11 @@
// Has permission, now it should pass.
mCallerPermissions.add(permission.MANAGE_APP_PREDICTIONS);
mManager.getShareTargets(filter);
+
+ runWithCaller(CHOOSER_ACTIVITY_PACKAGE, USER_0, () -> {
+ // Access is allowed when called from the configured system ChooserActivity
+ mManager.getShareTargets(filter);
+ });
}
public void testHasShareTargets_permission() {