Loading core/java/android/hardware/hdmi/HdmiClient.java +20 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading core/java/android/hardware/hdmi/IHdmiControlService.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java +5 −0 Original line number Diff line number Diff line Loading @@ -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) { } Loading services/core/java/com/android/server/hdmi/HdmiCecKeycode.java +14 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +45 −0 Original line number Diff line number Diff line Loading @@ -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}. Loading @@ -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 Loading
core/java/android/hardware/hdmi/HdmiClient.java +20 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading
core/java/android/hardware/hdmi/IHdmiControlService.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading
core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java +5 −0 Original line number Diff line number Diff line Loading @@ -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) { } Loading
services/core/java/com/android/server/hdmi/HdmiCecKeycode.java +14 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +45 −0 Original line number Diff line number Diff line Loading @@ -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}. Loading @@ -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