summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Makoto Onuki <omakoto@google.com> 2020-11-06 13:43:38 -0800
committer Jin Seok Park <jinpark@google.com> 2021-01-22 21:56:16 +0900
commitdb8d2bf0a202cd57a14b6bdec46dfcc514da5c04 (patch)
treeeaa0f80e3d21c563ff3c4651a9e77997f0142b49
parent3df00e17f7ba7b2de630feaf0fe736806cd5993e (diff)
Let modules obtain target component of PendingIntent
- Media module needs to extract the component that a PendingIntent will be sent to. Currently, the code is bundled, so they're using the hidden PendingIntent.getIntent() API, but we really do not want to make it @SystemApi. So instead, adding a way to obtain the resolve information instead. - !!Media should make sure the resolved components are actually owned by the same package that called the API!! Bug: 161334442 Test: not available yet Change-Id: I09fc2e0bb23434394caadc638f48c05548376548
-rw-r--r--core/api/current.txt4
-rw-r--r--core/api/module-lib-current.txt12
-rw-r--r--core/java/android/app/IActivityManager.aidl6
-rw-r--r--core/java/android/app/PendingIntent.java52
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java42
6 files changed, 112 insertions, 9 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index b8327a9868fa..ef3db23ae5b7 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6189,7 +6189,11 @@ package android.app {
method public android.content.IntentSender getIntentSender();
method public static android.app.PendingIntent getService(android.content.Context, int, @NonNull android.content.Intent, int);
method @Deprecated public String getTargetPackage();
+ method public boolean isActivity();
+ method public boolean isBroadcast();
+ method public boolean isForegroundService();
method public boolean isImmutable();
+ method public boolean isService();
method @Nullable public static android.app.PendingIntent readPendingIntentOrNullFromParcel(@NonNull android.os.Parcel);
method public void send() throws android.app.PendingIntent.CanceledException;
method public void send(int) throws android.app.PendingIntent.CanceledException;
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 6ed09afe44a8..4b1f7ba3fbc7 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -1,4 +1,12 @@
// Signature format: 2.0
+package android {
+
+ public static final class Manifest.permission {
+ field public static final String GET_INTENT_SENDER_INTENT = "android.permission.GET_INTENT_SENDER_INTENT";
+ }
+
+}
+
package android.app {
public class ActivityManager {
@@ -26,6 +34,10 @@ package android.app {
field public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED";
}
+ public final class PendingIntent implements android.os.Parcelable {
+ method @Nullable @RequiresPermission(android.Manifest.permission.GET_INTENT_SENDER_INTENT) public java.util.List<android.content.pm.ResolveInfo> queryIntentComponents(int);
+ }
+
public class StatusBarManager {
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 0019fd1908b3..e73636fe7fd0 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -51,6 +51,7 @@ import android.content.pm.ConfigurationInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.LocusId;
@@ -704,4 +705,9 @@ interface IActivityManager {
* @throws IllegalArgumentException if the user is not a profile.
*/
boolean stopProfile(int userId);
+
+ /** Called by PendingIntent.queryIntentComponents() */
+ List<ResolveInfo> queryIntentComponentsForIntentSender(in IIntentSender sender, int matchFlags);
+
+ boolean isIntentSenderAService(in IIntentSender sender);
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 269ccb169774..3ce6488904cc 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -16,9 +16,13 @@
package android.app;
+import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemApi.Client;
import android.annotation.TestApi;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
@@ -29,6 +33,8 @@ import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.PackageManager.ResolveInfoFlags;
+import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -46,6 +52,7 @@ import com.android.internal.os.IResultReceiver;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.List;
/**
* A description of an Intent and target action to perform with it. Instances
@@ -1168,10 +1175,9 @@ public final class PendingIntent implements Parcelable {
}
/**
- * @hide
- * Check whether this PendingIntent will launch an Activity.
+ * @return TRUE if this {@link PendingIntent} was created with
+ * {@link #getActivity} or {@link #getActivities}.
*/
- @UnsupportedAppUsage
public boolean isActivity() {
try {
return ActivityManager.getService()
@@ -1182,8 +1188,7 @@ public final class PendingIntent implements Parcelable {
}
/**
- * @hide
- * Check whether this PendingIntent will launch a foreground service
+ * @return TRUE if this {@link PendingIntent} was created with {@link #getForegroundService}.
*/
public boolean isForegroundService() {
try {
@@ -1195,8 +1200,19 @@ public final class PendingIntent implements Parcelable {
}
/**
- * @hide
- * Check whether this PendingIntent will launch an Activity.
+ * @return TRUE if this {@link PendingIntent} was created with {@link #getService}.
+ */
+ public boolean isService() {
+ try {
+ return ActivityManager.getService()
+ .isIntentSenderAService(mTarget);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return TRUE if this {@link PendingIntent} was created with {@link #getBroadcast}.
*/
public boolean isBroadcast() {
try {
@@ -1236,6 +1252,28 @@ public final class PendingIntent implements Parcelable {
}
/**
+ * Resolve the intent set in this {@link PendingIntent}. Note if the pending intent is
+ * generated for another user, the resulting component may not exist on the calling user.
+ * Use {@link android.content.pm.ApplicationInfo#uid} of the resulting
+ * {@link android.content.pm.ComponentInfo} with
+ * {@link android.os.UserHandle#getUserHandleForUid(int)} to see which user will receive
+ * the intent.
+ *
+ * @param flags MATCH_* flags from {@link android.content.pm.PackageManager}.
+ * @hide
+ */
+ @RequiresPermission(permission.GET_INTENT_SENDER_INTENT)
+ @SystemApi(client = Client.MODULE_LIBRARIES)
+ public @Nullable List<ResolveInfo> queryIntentComponents(@ResolveInfoFlags int flags) {
+ try {
+ return ActivityManager.getService()
+ .queryIntentComponentsForIntentSender(mTarget, flags);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Comparison operator on two PendingIntent objects, such that true
* is returned then they both represent the same operation from the
* same package. This allows you to use {@link #getActivity},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 76acc0031b94..0a94f20d5b31 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2659,8 +2659,9 @@
<permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
android:protectionLevel="signature|privileged|development" />
- <!-- Allows use of PendingIntent.getIntent().
- @hide -->
+ <!-- Allows use of PendingIntent.getIntent(), .
+ @hide @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)
+ -->
<permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
android:protectionLevel="signature" />
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f72c9fbf1a1b..1bf3bdc450a1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4953,6 +4953,15 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public boolean isIntentSenderAService(IIntentSender pendingResult) {
+ if (pendingResult instanceof PendingIntentRecord) {
+ final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
+ return res.key.type == ActivityManager.INTENT_SENDER_SERVICE;
+ }
+ return false;
+ }
+
+ @Override
public boolean isIntentSenderABroadcast(IIntentSender pendingResult) {
if (pendingResult instanceof PendingIntentRecord) {
final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
@@ -4977,6 +4986,39 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public List<ResolveInfo> queryIntentComponentsForIntentSender(
+ IIntentSender pendingResult, int matchFlags) {
+ enforceCallingPermission(Manifest.permission.GET_INTENT_SENDER_INTENT,
+ "queryIntentComponentsForIntentSender()");
+ Preconditions.checkNotNull(pendingResult);
+ final PendingIntentRecord res;
+ try {
+ res = (PendingIntentRecord) pendingResult;
+ } catch (ClassCastException e) {
+ return null;
+ }
+ final Intent intent = res.key.requestIntent;
+ if (intent == null) {
+ return null;
+ }
+ final int userId = res.key.userId;
+ switch (res.key.type) {
+ case ActivityManager.INTENT_SENDER_ACTIVITY:
+ return mContext.getPackageManager().queryIntentActivitiesAsUser(
+ intent, matchFlags, userId);
+ case ActivityManager.INTENT_SENDER_SERVICE:
+ case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
+ return mContext.getPackageManager().queryIntentServicesAsUser(
+ intent, matchFlags, userId);
+ case ActivityManager.INTENT_SENDER_BROADCAST:
+ return mContext.getPackageManager().queryBroadcastReceiversAsUser(
+ intent, matchFlags, userId);
+ default: // ActivityManager.INTENT_SENDER_ACTIVITY_RESULT
+ throw new IllegalStateException("Unsupported intent sender type: " + res.key.type);
+ }
+ }
+
+ @Override
public String getTagForIntentSender(IIntentSender pendingResult, String prefix) {
if (!(pendingResult instanceof PendingIntentRecord)) {
return null;