diff options
6 files changed, 59 insertions, 72 deletions
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl index 31fb8d03c4a0..9bf126b7a875 100644 --- a/media/java/android/media/session/ISession.aidl +++ b/media/java/android/media/session/ISession.aidl @@ -35,7 +35,7 @@ interface ISession { ISessionController getController(); void setFlags(int flags); void setActive(boolean active); - void setMediaButtonReceiver(in PendingIntent mbr); + void setMediaButtonReceiver(in PendingIntent mbr, String sessionPackageName); void setMediaButtonBroadcastReceiver(in ComponentName broadcastReceiver); void setLaunchPendingIntent(in PendingIntent pi); void destroySession(); diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 24118b086c24..20fa53d3ec32 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -286,7 +286,7 @@ public final class MediaSession { @Deprecated public void setMediaButtonReceiver(@Nullable PendingIntent mbr) { try { - mBinder.setMediaButtonReceiver(mbr); + mBinder.setMediaButtonReceiver(mbr, mContext.getPackageName()); } catch (RemoteException e) { Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e); } diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java index e2e5046d98bf..70dea734f1ba 100644 --- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java +++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java @@ -58,6 +58,9 @@ final class MediaButtonReceiverHolder { private static final String TAG = "PendingIntentHolder"; private static final boolean DEBUG_KEY_EVENT = MediaSessionService.DEBUG_KEY_EVENT; private static final String COMPONENT_NAME_USER_ID_DELIM = ","; + // Filter apps regardless of the phone's locked/unlocked state. + private static final int PACKAGE_MANAGER_COMMON_FLAGS = + PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; private final int mUserId; private final PendingIntent mPendingIntent; @@ -105,40 +108,22 @@ final class MediaButtonReceiverHolder { * @return Can be {@code null} if pending intent was null. */ public static MediaButtonReceiverHolder create(Context context, int userId, - PendingIntent pendingIntent) { + PendingIntent pendingIntent, String sessionPackageName) { if (pendingIntent == null) { return null; } - ComponentName componentName = (pendingIntent != null && pendingIntent.getIntent() != null) - ? pendingIntent.getIntent().getComponent() : null; + int componentType = getComponentType(pendingIntent); + ComponentName componentName = getComponentName(pendingIntent, componentType); if (componentName != null) { - // Explicit intent, where component name is in the PendingIntent. return new MediaButtonReceiverHolder(userId, pendingIntent, componentName, - getComponentType(context, componentName)); - } - - // Implicit intent, where component name isn't in the PendingIntent. Try resolve. - PackageManager pm = context.getPackageManager(); - Intent intent = pendingIntent.getIntent(); - if ((componentName = resolveImplicitServiceIntent(pm, intent)) != null) { - return new MediaButtonReceiverHolder( - userId, pendingIntent, componentName, COMPONENT_TYPE_SERVICE); - } else if ((componentName = resolveManifestDeclaredBroadcastReceiverIntent(pm, intent)) - != null) { - return new MediaButtonReceiverHolder( - userId, pendingIntent, componentName, COMPONENT_TYPE_BROADCAST); - } else if ((componentName = resolveImplicitActivityIntent(pm, intent)) != null) { - return new MediaButtonReceiverHolder( - userId, pendingIntent, componentName, COMPONENT_TYPE_ACTIVITY); + componentType); } // Failed to resolve target component for the pending intent. It's unlikely to be usable. - // However, the pending intent would be still used, just to follow the legacy behavior. + // However, the pending intent would be still used, so setting the package name to the + // package name of the session that set this pending intent. Log.w(TAG, "Unresolvable implicit intent is set, pi=" + pendingIntent); - String packageName = (pendingIntent != null && pendingIntent.getIntent() != null) - ? pendingIntent.getIntent().getPackage() : null; - return new MediaButtonReceiverHolder(userId, pendingIntent, - packageName != null ? packageName : ""); + return new MediaButtonReceiverHolder(userId, pendingIntent, sessionPackageName); } public static MediaButtonReceiverHolder create(int userId, ComponentName broadcastReceiver) { @@ -269,6 +254,18 @@ final class MediaButtonReceiverHolder { String.valueOf(mComponentType)); } + @ComponentType + private static int getComponentType(PendingIntent pendingIntent) { + if (pendingIntent.isBroadcast()) { + return COMPONENT_TYPE_BROADCAST; + } else if (pendingIntent.isActivity()) { + return COMPONENT_TYPE_ACTIVITY; + } else if (pendingIntent.isForegroundService() || pendingIntent.isService()) { + return COMPONENT_TYPE_SERVICE; + } + return COMPONENT_TYPE_INVALID; + } + /** * Gets the type of the component * @@ -284,9 +281,7 @@ final class MediaButtonReceiverHolder { PackageManager pm = context.getPackageManager(); try { ActivityInfo activityInfo = pm.getActivityInfo(componentName, - PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.GET_ACTIVITIES); + PACKAGE_MANAGER_COMMON_FLAGS | PackageManager.GET_ACTIVITIES); if (activityInfo != null) { return COMPONENT_TYPE_ACTIVITY; } @@ -294,9 +289,7 @@ final class MediaButtonReceiverHolder { } try { ServiceInfo serviceInfo = pm.getServiceInfo(componentName, - PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.GET_SERVICES); + PACKAGE_MANAGER_COMMON_FLAGS | PackageManager.GET_SERVICES); if (serviceInfo != null) { return COMPONENT_TYPE_SERVICE; } @@ -306,40 +299,29 @@ final class MediaButtonReceiverHolder { return COMPONENT_TYPE_BROADCAST; } - private static ComponentName resolveImplicitServiceIntent(PackageManager pm, Intent intent) { - // Flag explanations. - // - MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE: - // filter apps regardless of the phone's locked/unlocked state. - // - GET_SERVICES: Return service - return createComponentName(pm.resolveService(intent, - PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.GET_SERVICES)); - } - - private static ComponentName resolveManifestDeclaredBroadcastReceiverIntent( - PackageManager pm, Intent intent) { - // Flag explanations. - // - MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE: - // filter apps regardless of the phone's locked/unlocked state. - List<ResolveInfo> resolveInfos = pm.queryBroadcastReceivers(intent, - PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); - return (resolveInfos != null && !resolveInfos.isEmpty()) - ? createComponentName(resolveInfos.get(0)) : null; - } - - private static ComponentName resolveImplicitActivityIntent(PackageManager pm, Intent intent) { - // Flag explanations. - // - MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE: - // Filter apps regardless of the phone's locked/unlocked state. - // - MATCH_DEFAULT_ONLY: - // Implicit intent receiver should be set as default. Only needed for activity. - // - GET_ACTIVITIES: Return activity - return createComponentName(pm.resolveActivity(intent, - PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.MATCH_DEFAULT_ONLY - | PackageManager.GET_ACTIVITIES)); + private static ComponentName getComponentName(PendingIntent pendingIntent, int componentType) { + List<ResolveInfo> resolveInfos = null; + switch (componentType) { + case COMPONENT_TYPE_ACTIVITY: + resolveInfos = pendingIntent.queryIntentComponents( + PACKAGE_MANAGER_COMMON_FLAGS + | PackageManager.MATCH_DEFAULT_ONLY /* Implicit intent receiver + should be set as default. Only needed for activity. */ + | PackageManager.GET_ACTIVITIES); + break; + case COMPONENT_TYPE_SERVICE: + resolveInfos = pendingIntent.queryIntentComponents( + PACKAGE_MANAGER_COMMON_FLAGS | PackageManager.GET_SERVICES); + break; + case COMPONENT_TYPE_BROADCAST: + resolveInfos = pendingIntent.queryIntentComponents( + PACKAGE_MANAGER_COMMON_FLAGS | PackageManager.GET_RECEIVERS); + break; + } + if (resolveInfos != null && !resolveInfos.isEmpty()) { + return createComponentName(resolveInfos.get(0)); + } + return null; } private static ComponentName createComponentName(ResolveInfo resolveInfo) { diff --git a/services/core/java/com/android/server/media/MediaKeyDispatcher.java b/services/core/java/com/android/server/media/MediaKeyDispatcher.java index 63618eef250a..7ef4924879bf 100644 --- a/services/core/java/com/android/server/media/MediaKeyDispatcher.java +++ b/services/core/java/com/android/server/media/MediaKeyDispatcher.java @@ -100,9 +100,12 @@ public abstract class MediaKeyDispatcher { /** * Implement this to customize the logic for which MediaButtonReceiver should consume a * dispatched key event. - * - * Note: This pending intent will have lower priority over the {@link MediaSession.Token} + * <p> + * This pending intent will have lower priority over the {@link MediaSession.Token} * returned from {@link #getMediaSession(KeyEvent, int, boolean)}. + * <p> + * Use a pending intent with an explicit intent; setting a pending intent with an implicit + * intent that cannot be resolved to a certain component name will fail. * * @return a {@link PendingIntent} instance that should receive the dispatched key event. */ diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index ae58d4c40622..74111be419b5 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -843,7 +843,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR } @Override - public void setMediaButtonReceiver(PendingIntent pi) throws RemoteException { + public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName) + throws RemoteException { final long token = Binder.clearCallingIdentity(); try { if ((mPolicies & SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER) @@ -851,7 +852,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR return; } mMediaButtonReceiverHolder = - MediaButtonReceiverHolder.create(mContext, mUserId, pi); + MediaButtonReceiverHolder.create(mContext, mUserId, pi, sessionPackageName); mService.onMediaButtonReceiverChanged(MediaSessionRecord.this); } finally { Binder.restoreCallingIdentity(token); diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index c0381e4b1715..6c1d3991c4e9 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -2124,7 +2124,8 @@ public class MediaSessionService extends SystemService implements Monitor { uid, asSystemService); if (pi != null) { mediaButtonReceiverHolder = MediaButtonReceiverHolder.create(mContext, - mCurrentFullUserRecord.mFullUserId, pi); + mCurrentFullUserRecord.mFullUserId, pi, + /* sessionPackageName= */ ""); } } } |