From fed495078e23f69c87c93e3a3a8d79ec4d74fff5 Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Mon, 5 Mar 2018 17:51:12 +0900 Subject: [PATCH] MediaSession2: Ask server whether a controller is trusted Bug: 73150040 Test: Run all MediaComponents tests once Change-Id: Ic003a40654a45e6fd367d7389216fddf320a8edc --- .../media/session/ISessionManager.aidl | 1 + .../media/session/MediaSessionManager.java | 19 ++++++ .../server/media/MediaSessionService.java | 59 ++++++++++++++++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl index 50b4acbfc77ee..963457bedb602 100644 --- a/media/java/android/media/session/ISessionManager.aidl +++ b/media/java/android/media/session/ISessionManager.aidl @@ -52,6 +52,7 @@ interface ISessionManager { void setOnMediaKeyListener(in IOnMediaKeyListener listener); // MediaSession2 + boolean isTrusted(int uid, String packageName); boolean createSession2(in Bundle sessionToken); void destroySession2(in Bundle sessionToken); List getSessionTokens(boolean activeSessionOnly, boolean sessionServiceOnly); diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index d079b7a9e6126..6b130cc1c4023 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -339,6 +339,25 @@ public final class MediaSessionManager { } } + /** + * Returns whether the api + * + * @param uid uid of the app + * @param packageName packageName + * @hide + */ + public boolean isTrusted(int uid, @NonNull String packageName) { + if (packageName == null) { + return false; + } + try { + return mService.isTrusted(uid, packageName); + } catch (RemoteException e) { + Log.wtf(TAG, "Cannot communicate with the service.", e); + } + return false; + } + /** * Called when a {@link MediaSession2} is created. * @hide diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 6411ae1ea69dc..693953788a5b5 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -19,6 +19,7 @@ package com.android.server.media; import static android.media.SessionToken2.TYPE_SESSION; import android.app.ActivityManager; +import android.app.AppGlobals; import android.app.INotificationManager; import android.app.KeyguardManager; import android.app.PendingIntent; @@ -30,6 +31,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; @@ -117,12 +119,13 @@ public class MediaSessionService extends SystemService implements Monitor { private final MessageHandler mHandler = new MessageHandler(); private final PowerManager.WakeLock mMediaEventWakeLock; private final int mLongPressTimeout; + private final INotificationManager mNotificationManager; + private final IPackageManager mPackageManager; private KeyguardManager mKeyguardManager; private IAudioService mAudioService; private ContentResolver mContentResolver; private SettingsObserver mSettingsObserver; - private INotificationManager mNotificationManager; private boolean mHasFeatureLeanback; // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile) @@ -150,6 +153,7 @@ public class MediaSessionService extends SystemService implements Monitor { mLongPressTimeout = ViewConfiguration.getLongPressTimeout(); mNotificationManager = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + mPackageManager = AppGlobals.getPackageManager(); } @Override @@ -1493,6 +1497,59 @@ public class MediaSessionService extends SystemService implements Monitor { } } + /** + * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL + * permission or an enabled notification listener) + * + * @param uid uid of the controller app + * @param packageName package name of the controller app + */ + @Override + public boolean isTrusted(int uid, String packageName) throws RemoteException { + final long token = Binder.clearCallingIdentity(); + try { + int userId = UserHandle.getUserId(uid); + // Sanity check whether uid and packageName matches + if (uid != mPackageManager.getPackageUid(packageName, 0, userId)) { + throw new IllegalArgumentException("uid=" + uid + " and packageName=" + + packageName + " doesn't match"); + } + + // Check if it's system server or has MEDIA_CONTENT_CONTROL. + // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra + // check here. + if (uid == Process.SYSTEM_UID || mPackageManager.checkPermission( + android.Manifest.permission.MEDIA_CONTENT_CONTROL, packageName, uid) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + if (DEBUG) { + Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted" + + " MEDIA_CONTENT_CONTROL"); + } + + // TODO(jaewan): Add hasEnabledNotificationListener(String pkgName) for + // optimization (Post-P) + final List enabledNotificationListeners = + mNotificationManager.getEnabledNotificationListeners(userId); + if (enabledNotificationListeners != null) { + for (int i = 0; i < enabledNotificationListeners.size(); i++) { + if (TextUtils.equals(packageName, + enabledNotificationListeners.get(i).getPackageName())) { + return true; + } + } + } + } finally { + Binder.restoreCallingIdentity(token); + } + if (DEBUG) { + Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled notification" + + " listener"); + } + return false; + } + /** * Called when a {@link android.media.MediaSession2} instance is created. *