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

Commit 8be71c0f authored by Jaewan Kim's avatar Jaewan Kim
Browse files

MediaController: Remove dispatching key event as system service APIs

This removes hidden API usages from the fwk to apex, which would be
prohibited.

With this API, the dispatching logic is changed as follows for sending
key events directly to MediaSessionRecord through MediaSessionService.

Before:
    PhoneWindow
    -> MediaController.dispatch***AsSystemService(key)
    -> MediaSessionRecord

After:
    PhoneWindow
    -> MediaSessionManager.dispatch**AsSystemService(sessionToken, key)
    -> MediaSessionService
    -> MediaSessionRecord

Bug: 123485698
Test: Build, flash and injected some key events
Change-Id: I3e0bca7565ae2f142c3389322d867700646d5038
parent 1f9995f3
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Color;
@@ -1885,7 +1884,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
                // If we have a session send it the volume command, otherwise
                // use the suggested stream.
                if (mMediaController != null) {
                    mMediaController.dispatchVolumeButtonEventAsSystemService(event);
                    getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(
                            mMediaController.getSessionToken(), event);
                } else {
                    getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(event,
                            mVolumeControlStreamType);
@@ -1906,7 +1906,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
            case KeyEvent.KEYCODE_MEDIA_RECORD:
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                if (mMediaController != null) {
                    if (mMediaController.dispatchMediaButtonEventAsSystemService(event)) {
                    if (getMediaSessionManager().dispatchMediaKeyEventAsSystemService(
                            mMediaController.getSessionToken(), event)) {
                        return true;
                    }
                }
@@ -1977,7 +1978,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
                // If we have a session send it the volume command, otherwise
                // use the suggested stream.
                if (mMediaController != null) {
                    mMediaController.dispatchVolumeButtonEventAsSystemService(event);
                    getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(
                            mMediaController.getSessionToken(), event);
                } else {
                    getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(
                            event, mVolumeControlStreamType);
@@ -2007,7 +2009,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
            case KeyEvent.KEYCODE_MEDIA_RECORD:
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                if (mMediaController != null) {
                    if (mMediaController.dispatchMediaButtonEventAsSystemService(event)) {
                    if (getMediaSessionManager().dispatchMediaKeyEventAsSystemService(
                            mMediaController.getSessionToken(), event)) {
                        return true;
                    }
                }
+18 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.ResultReceiver;
import android.view.KeyEvent;

import java.util.List;
import java.util.Objects;

/**
 * Handles incoming commands from {@link MediaController}.
@@ -603,6 +604,23 @@ public final class ControllerLink implements Parcelable {
        dest.writeStrongBinder(mISessionController.asBinder());
    }

    @Override
    public int hashCode() {
        return mISessionController.asBinder().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof ControllerLink)) {
            return false;
        }
        ControllerLink other = (ControllerLink) obj;
        return Objects.equals(getBinder(), other.getBinder());
    }

    /**
     * Class for Stub implementation
     */
+2 −74
Original line number Diff line number Diff line
@@ -123,25 +123,6 @@ public final class MediaController {
     * @return true if the event was sent to the session, false otherwise.
     */
    public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) {
        return dispatchMediaButtonEventInternal(false, keyEvent);
    }

    /**
     * Dispatches the media button event as system service to the session.
     * <p>
     * Should be only called by the {@link com.android.internal.policy.PhoneWindow} when the
     * foreground activity didn't consume the key from the hardware devices.
     *
     * @param keyEvent media key event
     * @return {@code true} if the event was sent to the session, {@code false} otherwise
     * @hide
     */
    public boolean dispatchMediaButtonEventAsSystemService(@NonNull KeyEvent keyEvent) {
        return dispatchMediaButtonEventInternal(true, keyEvent);
    }

    private boolean dispatchMediaButtonEventInternal(boolean asSystemService,
            @NonNull KeyEvent keyEvent) {
        if (keyEvent == null) {
            throw new IllegalArgumentException("KeyEvent may not be null");
        }
@@ -150,66 +131,13 @@ public final class MediaController {
        }
        try {
            return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
                    asSystemService, keyEvent);
                    false /* asSystemService */, keyEvent);
        } catch (RuntimeException e) {
            // System is dead. =(
        }
        return false;
    }

    /**
     * Dispatches the volume button event as system service to the session.
     * <p>
     * Should be only called by the {@link com.android.internal.policy.PhoneWindow} when the
     * foreground activity didn't consume the key from the hardware devices.
     *
     * @param keyEvent volume key event
     * @hide
     */
    public void dispatchVolumeButtonEventAsSystemService(@NonNull KeyEvent keyEvent) {
        switch (keyEvent.getAction()) {
            case KeyEvent.ACTION_DOWN: {
                int direction = 0;
                switch (keyEvent.getKeyCode()) {
                    case KeyEvent.KEYCODE_VOLUME_UP:
                        direction = AudioManager.ADJUST_RAISE;
                        break;
                    case KeyEvent.KEYCODE_VOLUME_DOWN:
                        direction = AudioManager.ADJUST_LOWER;
                        break;
                    case KeyEvent.KEYCODE_VOLUME_MUTE:
                        direction = AudioManager.ADJUST_TOGGLE_MUTE;
                        break;
                }
                try {
                    // Note: Need both package name and OP package name. Package name is used for
                    //       RemoteUserInfo, and OP package name is used for AudioService's internal
                    //       AppOpsManager usages.
                    mSessionBinder.adjustVolume(mContext.getPackageName(),
                            mContext.getOpPackageName(), mCbStub, true, direction,
                            AudioManager.FLAG_SHOW_UI);
                } catch (RuntimeException e) {
                    Log.wtf(TAG, "Error calling adjustVolumeBy", e);
                }
                break;
            }

            case KeyEvent.ACTION_UP: {
                final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
                        | AudioManager.FLAG_FROM_KEY;
                try {
                    // Note: Need both package name and OP package name. Package name is used for
                    //       RemoteUserInfo, and OP package name is used for AudioService's internal
                    //       AppOpsManager usages.
                    mSessionBinder.adjustVolume(mContext.getPackageName(),
                            mContext.getOpPackageName(), mCbStub, true, 0, flags);
                } catch (RuntimeException e) {
                    Log.wtf(TAG, "Error calling adjustVolumeBy", e);
                }
            }
        }
    }

    /**
     * Get the current playback state for this session.
     *
@@ -394,7 +322,7 @@ public final class MediaController {
            //       RemoteUserInfo, and OP package name is used for AudioService's internal
            //       AppOpsManager usages.
            mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
                    mCbStub, false, direction, flags);
                    mCbStub, false /* asSystemService */, direction, flags);
        } catch (RuntimeException e) {
            Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
        }
+4 −0
Original line number Diff line number Diff line
@@ -42,8 +42,12 @@ interface ISessionManager {
    List<Session2Token> getSession2Tokens(int userId);
    void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
            boolean needWakeLock);
    boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
            in MediaSession.Token sessionToken, in KeyEvent keyEvent);
    void dispatchVolumeKeyEvent(String packageName, String opPackageName, boolean asSystemService,
            in KeyEvent keyEvent, int stream, boolean musicOnly);
    void dispatchVolumeKeyEventToSessionAsSystemService(String packageName, String opPackageName,
            in MediaSession.Token sessionToken, in KeyEvent keyEvent);
    void dispatchAdjustVolume(String packageName, String opPackageName, int suggestedStream,
            int delta, int flags);
    void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
+23 −10
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.os.ResultReceiver;
import android.service.media.MediaBrowserService;
import android.text.TextUtils;
@@ -43,6 +44,7 @@ import android.text.TextUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Objects;

/**
 * Allows interaction with media controllers, volume keys, media buttons, and
@@ -419,15 +421,22 @@ public final class MediaSession {
     */
    public static final class Token implements Parcelable {

        private ControllerLink mControllerLink;
        private final int mUid;
        private final ControllerLink mControllerLink;

        /**
         * @hide
         */
        public Token(ControllerLink controllerLink) {
            mUid = Process.myUid();
            mControllerLink = controllerLink;
        }

        Token(Parcel in) {
            mUid = in.readInt();
            mControllerLink = in.readParcelable(null);
        }

        @Override
        public int describeContents() {
            return 0;
@@ -435,13 +444,14 @@ public final class MediaSession {

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mUid);
            dest.writeParcelable(mControllerLink, flags);
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            int result = mUid;
            result = prime * result + ((mControllerLink == null)
                    ? 0 : mControllerLink.getBinder().hashCode());
            return result;
@@ -456,14 +466,18 @@ public final class MediaSession {
            if (getClass() != obj.getClass())
                return false;
            Token other = (Token) obj;
            if (mControllerLink == null) {
                if (other.mControllerLink != null) {
            if (mUid != other.mUid) {
                return false;
            }
            } else if (!mControllerLink.getBinder().equals(other.mControllerLink.getBinder())) {
                return false;
            return Objects.equals(mControllerLink, other.mControllerLink);
        }
            return true;

        /**
         * Gets the UID of this token.
         * @hide
         */
        public int getUid() {
            return mUid;
        }

        /**
@@ -479,8 +493,7 @@ public final class MediaSession {
                new Parcelable.Creator<Token>() {
            @Override
            public Token createFromParcel(Parcel in) {
                ControllerLink link = in.readParcelable(null);
                return new Token(link);
                return new Token(in);
            }

            @Override
Loading