Merge "Proposal: Reduce the number of IPCs in PendingIntent" into sc-dev
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index 341393c..eb7cac07 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -17,6 +17,7 @@
package android.app;
parcelable ActivityManager.MemoryInfo;
+parcelable ActivityManager.PendingIntentInfo;
parcelable ActivityManager.ProcessErrorStateInfo;
parcelable ActivityManager.RecentTaskInfo;
parcelable ActivityManager.TaskDescription;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 220c332..07e70dc 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4776,4 +4776,71 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * A subset of immutable pending intent information suitable for caching on the client side.
+ *
+ * @hide
+ */
+ public static final class PendingIntentInfo implements Parcelable {
+
+ private final String mCreatorPackage;
+ private final int mCreatorUid;
+ private final boolean mImmutable;
+ private final int mIntentSenderType;
+
+ public PendingIntentInfo(String creatorPackage, int creatorUid, boolean immutable,
+ int intentSenderType) {
+ mCreatorPackage = creatorPackage;
+ mCreatorUid = creatorUid;
+ mImmutable = immutable;
+ mIntentSenderType = intentSenderType;
+ }
+
+ public String getCreatorPackage() {
+ return mCreatorPackage;
+ }
+
+ public int getCreatorUid() {
+ return mCreatorUid;
+ }
+
+ public boolean isImmutable() {
+ return mImmutable;
+ }
+
+ public int getIntentSenderType() {
+ return mIntentSenderType;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeString(mCreatorPackage);
+ parcel.writeInt(mCreatorUid);
+ parcel.writeBoolean(mImmutable);
+ parcel.writeInt(mIntentSenderType);
+ }
+
+ public static final @NonNull Creator<PendingIntentInfo> CREATOR =
+ new Creator<PendingIntentInfo>() {
+ @Override
+ public PendingIntentInfo createFromParcel(Parcel in) {
+ return new PendingIntentInfo(
+ /* creatorPackage= */ in.readString(),
+ /* creatorUid= */ in.readInt(),
+ /* immutable= */ in.readBoolean(),
+ /* intentSenderType= */ in.readInt());
+ }
+
+ @Override
+ public PendingIntentInfo[] newArray(int size) {
+ return new PendingIntentInfo[size];
+ }
+ };
+ }
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 4ad13e1..0bc5958 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -17,6 +17,7 @@
package android.app;
import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
import android.app.ActivityTaskManager;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
@@ -248,7 +249,7 @@
in IBinder token, in String resultWho, int requestCode, in Intent[] intents,
in String[] resolvedTypes, int flags, in Bundle options, int userId);
void cancelIntentSender(in IIntentSender sender);
- String getPackageForIntentSender(in IIntentSender sender);
+ ActivityManager.PendingIntentInfo getInfoForIntentSender(in IIntentSender sender);
void registerIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
void unregisterIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
void enterSafeMode();
@@ -293,7 +294,6 @@
int operationType);
void backupAgentCreated(in String packageName, in IBinder agent, int userId);
void unbindBackupAgent(in ApplicationInfo appInfo);
- int getUidForIntentSender(in IIntentSender sender);
int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
boolean requireFull, in String name, in String callerPackage);
void addPackageDependency(in String packageName);
@@ -345,7 +345,6 @@
@UnsupportedAppUsage
void unregisterProcessObserver(in IProcessObserver observer);
boolean isIntentSenderTargetedToPackage(in IIntentSender sender);
- boolean isIntentSenderImmutable(in IIntentSender sender);
@UnsupportedAppUsage
void updatePersistentConfiguration(in Configuration values);
void updatePersistentConfigurationWithAttribution(in Configuration values,
@@ -375,8 +374,6 @@
void unstableProviderDied(in IBinder connection);
@UnsupportedAppUsage
boolean isIntentSenderAnActivity(in IIntentSender sender);
- boolean isIntentSenderAForegroundService(in IIntentSender sender);
- boolean isIntentSenderABroadcast(in IIntentSender sender);
/** @deprecated Use {@link startActivityAsUserWithFeature} instead */
@UnsupportedAppUsage(maxTargetSdk=29, publicAlternatives="Use {@code android.content.Context#createContextAsUser(android.os.UserHandle, int)} and {@link android.content.Context#startActivity(android.content.Intent)} instead")
int startActivityAsUser(in IApplicationThread caller, in String callingPackage,
@@ -710,6 +707,4 @@
/** 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 671315f..2f06bdc 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -16,6 +16,11 @@
package android.app;
+import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
+import static android.app.ActivityManager.INTENT_SENDER_BROADCAST;
+import static android.app.ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.INTENT_SENDER_SERVICE;
+
import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -25,6 +30,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import android.annotation.TestApi;
+import android.app.ActivityManager.PendingIntentInfo;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
@@ -122,6 +128,9 @@
private IBinder mWhitelistToken;
private ArraySet<CancelListener> mCancelListeners;
+ // cached pending intent information
+ private @Nullable PendingIntentInfo mCachedInfo;
+
/**
* It is now required to specify either {@link #FLAG_IMMUTABLE}
* or {@link #FLAG_MUTABLE} when creating a PendingIntent.
@@ -463,7 +472,7 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ INTENT_SENDER_ACTIVITY, packageName,
context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, options, user.getIdentifier());
@@ -596,7 +605,7 @@
try {
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ INTENT_SENDER_ACTIVITY, packageName,
context.getAttributionTag(), null, null, requestCode, intents, resolvedTypes,
flags, options, user.getIdentifier());
return target != null ? new PendingIntent(target) : null;
@@ -650,7 +659,7 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_BROADCAST, packageName,
+ INTENT_SENDER_BROADCAST, packageName,
context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, null, userHandle.getIdentifier());
@@ -687,7 +696,7 @@
public static PendingIntent getService(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags) {
return buildServicePendingIntent(context, requestCode, intent, flags,
- ActivityManager.INTENT_SENDER_SERVICE);
+ INTENT_SENDER_SERVICE);
}
/**
@@ -717,7 +726,7 @@
public static PendingIntent getForegroundService(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags) {
return buildServicePendingIntent(context, requestCode, intent, flags,
- ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE);
+ INTENT_SENDER_FOREGROUND_SERVICE);
}
private static PendingIntent buildServicePendingIntent(Context context, int requestCode,
@@ -1001,12 +1010,7 @@
*/
@Deprecated
public String getTargetPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCreatorPackage();
}
/**
@@ -1029,12 +1033,7 @@
*/
@Nullable
public String getCreatorPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getCreatorPackage();
}
/**
@@ -1056,12 +1055,7 @@
* none associated with it.
*/
public int getCreatorUid() {
- try {
- return ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getCreatorUid();
}
/**
@@ -1154,13 +1148,8 @@
*/
@Nullable
public UserHandle getCreatorUserHandle() {
- try {
- int uid = ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ int uid = getCachedInfo().getCreatorUid();
+ return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
}
/**
@@ -1180,12 +1169,7 @@
* Check if this PendingIntent is marked with {@link #FLAG_IMMUTABLE}.
*/
public boolean isImmutable() {
- try {
- return ActivityManager.getService()
- .isIntentSenderImmutable(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().isImmutable();
}
/**
@@ -1193,48 +1177,28 @@
* {@link #getActivity} or {@link #getActivities}.
*/
public boolean isActivity() {
- try {
- return ActivityManager.getService()
- .isIntentSenderAnActivity(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getIntentSenderType() == INTENT_SENDER_ACTIVITY;
}
/**
* @return TRUE if this {@link PendingIntent} was created with {@link #getForegroundService}.
*/
public boolean isForegroundService() {
- try {
- return ActivityManager.getService()
- .isIntentSenderAForegroundService(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getIntentSenderType() == INTENT_SENDER_FOREGROUND_SERVICE;
}
/**
* @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 getCachedInfo().getIntentSenderType() == INTENT_SENDER_SERVICE;
}
/**
* @return TRUE if this {@link PendingIntent} was created with {@link #getBroadcast}.
*/
public boolean isBroadcast() {
- try {
- return ActivityManager.getService()
- .isIntentSenderABroadcast(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getIntentSenderType() == INTENT_SENDER_BROADCAST;
}
/**
@@ -1433,4 +1397,16 @@
*/
void onCancelled(PendingIntent intent);
}
+
+ private PendingIntentInfo getCachedInfo() {
+ if (mCachedInfo == null) {
+ try {
+ mCachedInfo = ActivityManager.getService().getInfoForIntentSender(mTarget);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ return mCachedInfo;
+ }
}
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 858d1e4..b1252fd 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Handler;
@@ -60,6 +61,9 @@
private final IIntentSender mTarget;
IBinder mWhitelistToken;
+ // cached pending intent information
+ private @Nullable PendingIntentInfo mCachedInfo;
+
/**
* Exception thrown when trying to send through a PendingIntent that
* has been canceled or is otherwise no longer able to execute the request.
@@ -209,13 +213,7 @@
*/
@Deprecated
public String getTargetPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- // Should never happen.
- return null;
- }
+ return getCreatorPackage();
}
/**
@@ -228,13 +226,7 @@
* none associated with it.
*/
public String getCreatorPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- // Should never happen.
- return null;
- }
+ return getCachedInfo().getCreatorPackage();
}
/**
@@ -247,13 +239,7 @@
* none associated with it.
*/
public int getCreatorUid() {
- try {
- return ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- } catch (RemoteException e) {
- // Should never happen.
- return -1;
- }
+ return getCachedInfo().getCreatorUid();
}
/**
@@ -268,14 +254,8 @@
* none associated with it.
*/
public UserHandle getCreatorUserHandle() {
- try {
- int uid = ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
- } catch (RemoteException e) {
- // Should never happen.
- return null;
- }
+ int uid = getCachedInfo().getCreatorUid();
+ return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
}
/**
@@ -384,4 +364,16 @@
public IntentSender(IBinder target) {
mTarget = IIntentSender.Stub.asInterface(target);
}
+
+ private PendingIntentInfo getCachedInfo() {
+ if (mCachedInfo == null) {
+ try {
+ mCachedInfo = ActivityManager.getService().getInfoForIntentSender(mTarget);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ return mCachedInfo;
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 29b85ac..083a963 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -142,6 +142,7 @@
import android.app.Activity;
import android.app.ActivityClient;
import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityTaskManager.RootTaskInfo;
@@ -4858,19 +4859,6 @@
}
@Override
- public String getPackageForIntentSender(IIntentSender pendingResult) {
- if (!(pendingResult instanceof PendingIntentRecord)) {
- return null;
- }
- try {
- PendingIntentRecord res = (PendingIntentRecord)pendingResult;
- return res.key.packageName;
- } catch (ClassCastException e) {
- }
- return null;
- }
-
- @Override
public void registerIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver) {
mPendingIntentController.registerIntentSenderCancelListener(sender, receiver);
}
@@ -4882,15 +4870,17 @@
}
@Override
- public int getUidForIntentSender(IIntentSender sender) {
+ public PendingIntentInfo getInfoForIntentSender(IIntentSender sender) {
if (sender instanceof PendingIntentRecord) {
- try {
- PendingIntentRecord res = (PendingIntentRecord)sender;
- return res.uid;
- } catch (ClassCastException e) {
- }
+ PendingIntentRecord res = (PendingIntentRecord) sender;
+ return new PendingIntentInfo(
+ res.key.packageName,
+ res.uid,
+ (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0,
+ res.key.type);
+ } else {
+ throw new IllegalArgumentException();
}
- return -1;
}
@Override
@@ -4916,15 +4906,6 @@
}
@Override
- public boolean isIntentSenderImmutable(IIntentSender pendingResult) {
- if (pendingResult instanceof PendingIntentRecord) {
- final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
- return (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
- }
- return false;
- }
-
- @Override
public boolean isIntentSenderAnActivity(IIntentSender pendingResult) {
if (!(pendingResult instanceof PendingIntentRecord)) {
return false;
@@ -4941,33 +4922,6 @@
}
@Override
- public boolean isIntentSenderAForegroundService(IIntentSender pendingResult) {
- if (pendingResult instanceof PendingIntentRecord) {
- final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
- return res.key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE;
- }
- return false;
- }
-
- @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;
- return res.key.type == ActivityManager.INTENT_SENDER_BROADCAST;
- }
- return false;
- }
-
- @Override
public Intent getIntentForIntentSender(IIntentSender pendingResult) {
enforceCallingPermission(Manifest.permission.GET_INTENT_SENDER_INTENT,
"getIntentForIntentSender()");