diff options
| author | 2020-11-06 13:43:38 -0800 | |
|---|---|---|
| committer | 2021-01-22 21:56:16 +0900 | |
| commit | db8d2bf0a202cd57a14b6bdec46dfcc514da5c04 (patch) | |
| tree | eaa0f80e3d21c563ff3c4651a9e77997f0142b49 | |
| parent | 3df00e17f7ba7b2de630feaf0fe736806cd5993e (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.txt | 4 | ||||
| -rw-r--r-- | core/api/module-lib-current.txt | 12 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.aidl | 6 | ||||
| -rw-r--r-- | core/java/android/app/PendingIntent.java | 52 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 5 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 42 |
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; |