Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af2b9207 authored by Hyundo Moon's avatar Hyundo Moon Committed by Android (Google) Code Review
Browse files

Merge "Resolve API review on getting media key session"

parents b58a4614 ece8ebbb
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -25267,12 +25267,12 @@ package android.media.session {
  public final class MediaSessionManager {
    method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName);
    method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, @Nullable android.os.Handler);
    method public void addOnMediaKeyEventSessionChangedListener(@NonNull android.content.ComponentName, @NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
    method public void addOnMediaKeyEventSessionChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
    method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
    method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener, @NonNull android.os.Handler);
    method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessions(@Nullable android.content.ComponentName);
    method @Nullable public android.media.session.MediaSession.Token getMediaKeyEventSession(@NonNull android.content.ComponentName);
    method @NonNull public String getMediaKeyEventSessionPackageName(@NonNull android.content.ComponentName);
    method @Nullable public android.media.session.MediaSession.Token getMediaKeyEventSession();
    method @NonNull public String getMediaKeyEventSessionPackageName();
    method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
    method public boolean isTrustedForMediaControl(@NonNull android.media.session.MediaSessionManager.RemoteUserInfo);
    method @Deprecated public void notifySession2Created(@NonNull android.media.Session2Token);
+0 −3
Original line number Diff line number Diff line
@@ -5588,9 +5588,6 @@ package android.media.session {
  public final class MediaSessionManager {
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventDispatchedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventSessionChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
    method @Nullable @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.media.session.MediaSession.Token getMediaKeyEventSession();
    method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public String getMediaKeyEventSessionPackageName();
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventDispatchedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
    method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
    method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
+3 −3
Original line number Diff line number Diff line
@@ -39,8 +39,8 @@ interface ISessionManager {
    ISession createSession(String packageName, in ISessionCallback sessionCb, String tag,
            in Bundle sessionInfo, int userId);
    List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
    MediaSession.Token getMediaKeyEventSession(in ComponentName compName);
    String getMediaKeyEventSessionPackageName(in ComponentName compName);
    MediaSession.Token getMediaKeyEventSession(String packageName);
    String getMediaKeyEventSessionPackageName(String packageName);
    void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
            boolean needWakeLock);
    boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
@@ -67,7 +67,7 @@ interface ISessionManager {
    void removeOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
    void addOnMediaKeyEventSessionChangedListener(
            in IOnMediaKeyEventSessionChangedListener listener,
            in ComponentName notificationListener);
            String packageName);
    void removeOnMediaKeyEventSessionChangedListener(
            in IOnMediaKeyEventSessionChangedListener listener);
    void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
+19 −80
Original line number Diff line number Diff line
@@ -194,82 +194,45 @@ public final class MediaSessionManager {
        return getActiveSessionsForUser(notificationListener, UserHandle.myUserId());
    }

    /**
     * Gets the media key event session, which would receive a media key event unless specified.
     * @return The media key event session, which would receive key events by default, unless
     *          the caller has specified the target. Can be {@code null}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    @Nullable
    public MediaSession.Token getMediaKeyEventSession() {
        try {
            return mService.getMediaKeyEventSession(null);
        } catch (RemoteException ex) {
            Log.e(TAG, "Failed to get media key event session", ex);
        }
        return null;
    }

    /**
     * Gets the media key event session, which would receive a media key event unless specified.
     * <p>
     * This requires that your app is an enabled notificationlistener using the
     * {@link NotificationListenerService} APIs, in which case you must pass
     * the {@link ComponentName} of your enabled listener.
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
     * permission be held by the calling app, or the app has an enabled notification listener
     * using the {@link NotificationListenerService} APIs. If none of them applies, it will throw
     * a {@link SecurityException}.
     *
     * @return The media key event session, which would receive key events by default, unless
     *          the caller has specified the target. Can be {@code null}.
     */
    @Nullable
    public MediaSession.Token getMediaKeyEventSession(@NonNull ComponentName notificationListener) {
        Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
    public MediaSession.Token getMediaKeyEventSession() {
        try {
            return mService.getMediaKeyEventSession(notificationListener);
            return mService.getMediaKeyEventSession(mContext.getPackageName());
        } catch (RemoteException ex) {
            Log.e(TAG, "Failed to get media key event session", ex);
        }
        return null;
    }

    /**
     * Gets the package name of the media key event session.
     * @return The package name of the media key event session or the last session's media button
     *          receiver if the media key event session is {@code null}.
     * @see #getMediaKeyEventSession()
     * @hide
     */
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    @NonNull
    public String getMediaKeyEventSessionPackageName() {
        try {
            String packageName = mService.getMediaKeyEventSessionPackageName(null);
            return (packageName != null) ? packageName : "";
        } catch (RemoteException ex) {
            Log.e(TAG, "Failed to get media key event session package name", ex);
        }
        return "";
    }

    /**
     * Gets the package name of the media key event session.
     * <p>
     * This requires that your app is an enabled notificationlistener using the
     * {@link NotificationListenerService} APIs, in which case you must pass
     * the {@link ComponentName} of your enabled listener.
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
     * permission be held by the calling app, or the app has an enabled notification listener
     * using the {@link NotificationListenerService} APIs. If none of them applies, it will throw
     * a {@link SecurityException}.
     *
     * @return The package name of the media key event session or the last session's media button
     *          receiver if the media key event session is {@code null}. Returns an empty string
     *          if neither of them exists.
     * @see #getMediaKeyEventSession(ComponentName)
     * @see #getMediaKeyEventSession()
     */
    @NonNull
    public String getMediaKeyEventSessionPackageName(@NonNull ComponentName notificationListener) {
        Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
    public String getMediaKeyEventSessionPackageName() {
        try {
            String packageName = mService.getMediaKeyEventSessionPackageName(notificationListener);
            String packageName = mService.getMediaKeyEventSessionPackageName(
                    mContext.getPackageName());
            return (packageName != null) ? packageName : "";
        } catch (RemoteException ex) {
            Log.e(TAG, "Failed to get media key event session package name", ex);
@@ -938,42 +901,18 @@ public final class MediaSessionManager {
        }
    }

    /**
     * Add a {@link OnMediaKeyEventSessionChangedListener}.
     *
     * @param executor The executor on which the listener should be invoked
     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void addOnMediaKeyEventSessionChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        addOnMediaKeyEventSessionChangedListenerInternal(null, executor, listener);
    }

    /**
     * Add a listener to be notified when the media key session is changed.
     * <p>
     * This requires that your app is an enabled notificationlistener using the
     * {@link NotificationListenerService} APIs, in which case you must pass
     * the {@link ComponentName} of your enabled listener.
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
     * permission be held by the calling app, or the app has an enabled notification listener
     * using the {@link NotificationListenerService} APIs. If none of them applies, it will throw
     * a {@link SecurityException}.
     *
     * @param notificationListener The enabled notification listener component.
     * @param executor The executor on which the listener should be invoked.
     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
     */
    public void addOnMediaKeyEventSessionChangedListener(
            @NonNull ComponentName notificationListener,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
        addOnMediaKeyEventSessionChangedListenerInternal(notificationListener, executor, listener);
    }

    private void addOnMediaKeyEventSessionChangedListenerInternal(
            @Nullable ComponentName notificationListener,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        Objects.requireNonNull(executor, "executor shouldn't be null");
@@ -982,7 +921,7 @@ public final class MediaSessionManager {
            try {
                if (mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
                    mService.addOnMediaKeyEventSessionChangedListener(
                            mOnMediaKeyEventSessionChangedListenerStub, notificationListener);
                            mOnMediaKeyEventSessionChangedListenerStub, mContext.getPackageName());
                }
                mMediaKeyEventSessionChangedCallbacks.put(listener, executor);
                executor.execute(
+30 −45
Original line number Diff line number Diff line
@@ -471,7 +471,9 @@ public class MediaSessionService extends SystemService implements Monitor {
            for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
                SessionsListenerRecord listener = mSessionsListeners.get(i);
                try {
                    enforceMediaPermissions(listener.componentName, listener.pid, listener.uid,
                    String packageName = listener.componentName == null ? null :
                            listener.componentName.getPackageName();
                    enforceMediaPermissions(packageName, listener.pid, listener.uid,
                            listener.userId);
                } catch (SecurityException e) {
                    Log.i(TAG, "ActiveSessionsListener " + listener.componentName
@@ -593,15 +595,13 @@ public class MediaSessionService extends SystemService implements Monitor {
     * for the caller's user</li>
     * </ul>
     */
    private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
    private void enforceMediaPermissions(String packageName, int pid, int uid,
            int resolvedUserId) {
        if (hasStatusBarServicePermission(pid, uid)) return;
        // TODO: Refactor to use hasMediaControlPermission and hasEnabledNotificationListener
        if (mContext
                .checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
                != PackageManager.PERMISSION_GRANTED
                && !isEnabledNotificationListener(compName,
                UserHandle.getUserHandleForUid(uid), resolvedUserId)) {
        if (hasMediaControlPermission(pid, uid)) return;

        if (packageName == null || !hasEnabledNotificationListener(
                packageName, UserHandle.getUserHandleForUid(uid), resolvedUserId)) {
            throw new SecurityException("Missing permission to control media.");
        }
    }
@@ -632,29 +632,26 @@ public class MediaSessionService extends SystemService implements Monitor {
    }

    /**
     * This checks if the component is an enabled notification listener for the
     * This checks if the given package has an enabled notification listener for the
     * specified user. Enabled components may only operate on behalf of the user
     * they're running as.
     *
     * @param compName The component that is enabled.
     * @param packageName The package name.
     * @param userHandle The user handle of the caller.
     * @param forUserId The user id they're making the request on behalf of.
     * @return True if the component is enabled, false otherwise
     * @return True if the app has an enabled notification listener for the user, false otherwise
     */
    private boolean isEnabledNotificationListener(ComponentName compName, UserHandle userHandle,
            int forUserId) {
    private boolean hasEnabledNotificationListener(String packageName,
            UserHandle userHandle, int forUserId) {
        if (userHandle.getIdentifier() != forUserId) {
            // You may not access another user's content as an enabled listener.
            return false;
        }
        if (DEBUG) {
            Log.d(TAG, "Checking if enabled notification listener " + compName);
        }
        if (compName != null) {
            return mNotificationManager.hasEnabledNotificationListener(compName.getPackageName(),
                    userHandle);
            Log.d(TAG, "Checking whether the package " + packageName + " has an"
                    + " enabled notification listener.");
        }
        return false;
        return mNotificationManager.hasEnabledNotificationListener(packageName, userHandle);
    }

    /*
@@ -1237,20 +1234,16 @@ public class MediaSessionService extends SystemService implements Monitor {
        }

        @Override
        public MediaSession.Token getMediaKeyEventSession(ComponentName notificationListener) {
        public MediaSession.Token getMediaKeyEventSession(final String packageName) {
            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
            final int userId = userHandle.getIdentifier();
            final long token = Binder.clearCallingIdentity();
            try {
                if (!hasMediaControlPermission(pid, uid)
                        && !isEnabledNotificationListener(
                                notificationListener, userHandle, userId)) {
                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
                            + " notification listener is required to"
                            + " get media key event session.");
                }
                enforcePackageName(packageName, uid);
                enforceMediaPermissions(packageName, pid, uid, userId);

                MediaSessionRecordImpl record;
                synchronized (mLock) {
                    FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1272,20 +1265,16 @@ public class MediaSessionService extends SystemService implements Monitor {
        }

        @Override
        public String getMediaKeyEventSessionPackageName(ComponentName notificationListener) {
        public String getMediaKeyEventSessionPackageName(final String packageName) {
            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
            final int userId = userHandle.getIdentifier();
            final long token = Binder.clearCallingIdentity();
            try {
                if (!hasMediaControlPermission(pid, uid)
                        && !isEnabledNotificationListener(
                        notificationListener, userHandle, userId)) {
                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
                            + " notification listener is required to"
                            + " get media key event session package name");
                }
                enforcePackageName(packageName, uid);
                enforceMediaPermissions(packageName, pid, uid, userId);

                MediaSessionRecordImpl record;
                synchronized (mLock) {
                    FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1597,7 +1586,7 @@ public class MediaSessionService extends SystemService implements Monitor {
        @Override
        public void addOnMediaKeyEventSessionChangedListener(
                final IOnMediaKeyEventSessionChangedListener listener,
                final ComponentName notificationListener) {
                final String packageName) {
            if (listener == null) {
                Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: listener is null, ignoring");
                return;
@@ -1609,13 +1598,9 @@ public class MediaSessionService extends SystemService implements Monitor {
            final int userId = userHandle.getIdentifier();
            final long token = Binder.clearCallingIdentity();
            try {
                if (!hasMediaControlPermission(pid, uid)
                        && !isEnabledNotificationListener(
                                notificationListener, userHandle, userId)) {
                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
                            + " notification listener is required to"
                            + " add MediaKeyEventSessionChangedListener.");
                }
                enforcePackageName(packageName, uid);
                enforceMediaPermissions(packageName, pid, uid, userId);

                synchronized (mLock) {
                    FullUserRecord user = getFullUserRecordLocked(userId);
                    if (user == null || user.mFullUserId != userId) {
@@ -1625,7 +1610,7 @@ public class MediaSessionService extends SystemService implements Monitor {
                    }
                    user.addOnMediaKeyEventSessionChangedListenerLocked(listener, uid);
                    Log.d(TAG, "The MediaKeyEventSessionChangedListener (" + listener.asBinder()
                            + ") is added by " + getCallingPackageName(uid));
                            + ") is added by " + packageName);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
@@ -2128,7 +2113,7 @@ public class MediaSessionService extends SystemService implements Monitor {
            int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
            // Check if they have the permissions or their component is enabled for the user
            // they're calling from.
            enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
            enforceMediaPermissions(packageName, pid, uid, resolvedUserId);
            return resolvedUserId;
        }