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

Commit bd8b4fa1 authored by Amy's avatar Amy Committed by Shubang Lu
Browse files

Add sendVolumeKeyEvent API to handle forwarding volume key separately.

Note that we handle volume key the same way as other keys before when
forwarding them to other cec devices. But the destination device of
volume key might be different from other function keys.

We might need to take the System Audio Control logic into this
forwarding proccess to find the proper audio receiver address.

Test: make -j44
Bug: 123369653
Change-Id: I6c9dba2b333e7eaa5137a8d2f5bfed506ae8554b
(cherry picked from commit 5db0138297836baf570f354c0b2ecb988d30936b)
parent 131cbcc3
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -55,6 +55,26 @@ public abstract class HdmiClient {
        }
    }

    /**
     * Sends a volume key event to the primary audio receiver in the system. This method should only
     * be called when the volume key is not handled by the local device. HDMI framework handles the
     * logic of finding the address of the receiver.
     *
     * @param keyCode key code to send. Defined in {@link android.view.KeyEvent}.
     * @param isPressed true if this is key press event
     *
     * @hide
     * TODO(b/110094868): unhide for Q
     */
    public void sendVolumeKeyEvent(int keyCode, boolean isPressed) {
        try {
            mService.sendVolumeKeyEvent(getDeviceType(), keyCode, isPressed);
        } catch (RemoteException e) {
            Log.e(TAG, "sendVolumeKeyEvent threw exception ", e);
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Sends vendor-specific command.
     *
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ interface IHdmiControlService {
    void deviceSelect(int deviceId, IHdmiControlCallback callback);
    void portSelect(int portId, IHdmiControlCallback callback);
    void sendKeyEvent(int deviceType, int keyCode, boolean isPressed);
    void sendVolumeKeyEvent(int deviceType, int keyCode, boolean isPressed);
    List<HdmiPortInfo> getPortInfo();
    boolean canChangeSystemAudioMode();
    boolean getSystemAudioMode();
+5 −0
Original line number Diff line number Diff line
@@ -180,6 +180,11 @@ public class HdmiAudioSystemClientTest {
        public void sendKeyEvent(final int deviceType, final int keyCode, final boolean isPressed) {
        }

        @Override
        public void sendVolumeKeyEvent(
            final int deviceType, final int keyCode, final boolean isPressed) {
        }

        @Override
        public void oneTouchPlay(final IHdmiControlCallback callback) {
        }
+14 −0
Original line number Diff line number Diff line
@@ -449,6 +449,20 @@ final class HdmiCecKeycode {
        return HdmiCecKeycode.androidKeyToCecKey(androidKeycode) != null;
    }

    /**
     * Returns {@code true} if given Android keycode is volume control related,
     * otherwise {@code false}.
     */
    static boolean isVolumeKeycode(int androidKeycode) {
        int cecKeyCode = HdmiCecKeycode.androidKeyToCecKey(androidKeycode)[0];
        return isSupportedKeycode(androidKeycode)
            && (cecKeyCode == CEC_KEYCODE_VOLUME_UP
                || cecKeyCode == CEC_KEYCODE_VOLUME_DOWN
                || cecKeyCode == CEC_KEYCODE_MUTE
                || cecKeyCode == CEC_KEYCODE_MUTE_FUNCTION
                || cecKeyCode == CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
    }

    /**
     * Returns CEC keycode to control audio mute status.
     *
+45 −0
Original line number Diff line number Diff line
@@ -1015,6 +1015,40 @@ abstract class HdmiCecLocalDevice {
        }
    }

    /**
     * Send a volume key event to other CEC device. The logical address of target device will be
     * given by {@link #findAudioReceiverAddress()}.
     *
     * @param keyCode key code defined in {@link android.view.KeyEvent}
     * @param isPressed {@code true} for key down event
     * @see #findAudioReceiverAddress()
     */
    @ServiceThreadOnly
    protected void sendVolumeKeyEvent(int keyCode, boolean isPressed) {
        assertRunOnServiceThread();
        if (!HdmiCecKeycode.isVolumeKeycode(keyCode)) {
            Slog.w(TAG, "Not a volume key: " + keyCode);
            return;
        }
        List<SendKeyAction> action = getActions(SendKeyAction.class);
        int logicalAddress = findAudioReceiverAddress();
        if (logicalAddress == Constants.ADDR_INVALID || logicalAddress == mAddress) {
            // Don't send key event to invalid device or itself.
            Slog.w(
                TAG,
                "Discard volume key event: "
                    + keyCode
                    + ", pressed:"
                    + isPressed
                    + ", receiverAddr="
                    + logicalAddress);
        } else if (!action.isEmpty()) {
            action.get(0).processKeyEvent(keyCode, isPressed);
        } else if (isPressed) {
            addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode));
        }
    }

    /**
     * Returns the logical address of the device which will receive key events via {@link
     * #sendKeyEvent}.
@@ -1026,6 +1060,17 @@ abstract class HdmiCecLocalDevice {
        return Constants.ADDR_INVALID;
    }

    /**
     * Returns the logical address of the audio receiver device which will receive volume key events
     * via {@link#sendVolumeKeyEvent}.
     *
     * @see #sendVolumeKeyEvent(int, boolean)
     */
    protected int findAudioReceiverAddress() {
        Slog.w(TAG, "findAudioReceiverAddress is not implemented");
        return Constants.ADDR_INVALID;
    }

    @ServiceThreadOnly
    void invokeCallback(IHdmiControlCallback callback, int result) {
        assertRunOnServiceThread();
Loading