HDMI: Fix broadcast vendor command handling error
HDMI CEC spec allows broadcasted <Vendor Command With ID> but it is always ignored regardless of listener registration.
Fix to allow broadcasted <Vendor Command With ID> and ignore it only when there is no listener registration.
Bug: 364774754
Test: atest com.android.server.hdmi
Merged-In: Ica6a40bf99a30179344ab51e1f1db5e2456abc82
Change-Id: Ica6a40bf99a30179344ab51e1f1db5e2456abc82
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 81204ef..a8d5696 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -927,12 +927,14 @@
protected int handleVendorCommandWithId(HdmiCecMessage message) {
byte[] params = message.getParams();
int vendorId = HdmiUtils.threeBytesToInt(params);
- if (message.getDestination() == Constants.ADDR_BROADCAST
- || message.getSource() == Constants.ADDR_UNREGISTERED) {
- Slog.v(TAG, "Wrong broadcast vendor command. Ignoring");
- } else if (!mService.invokeVendorCommandListenersOnReceived(
+ if (!mService.invokeVendorCommandListenersOnReceived(
mDeviceType, message.getSource(), message.getDestination(), params, true)) {
- return Constants.ABORT_REFUSED;
+ if (message.getDestination() == Constants.ADDR_BROADCAST
+ || message.getSource() == Constants.ADDR_UNREGISTERED) {
+ Slog.v(TAG, "Broadcast vendor command with no listeners. Ignoring");
+ } else {
+ return Constants.ABORT_REFUSED;
+ }
}
return Constants.HANDLED;
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
index 3dd8312..44fc387 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -19,6 +19,7 @@
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
@@ -520,21 +521,32 @@
public void handleVendorCommand_notHandled() {
HdmiCecMessage vendorCommand = HdmiCecMessageBuilder.buildVendorCommand(ADDR_TV,
ADDR_PLAYBACK_1, new byte[]{0});
- mNativeWrapper.onCecMessage(vendorCommand);
+ @Constants.HandleMessageResult int result =
+ mHdmiLocalDevice.handleVendorCommand(vendorCommand);
mTestLooper.dispatchAll();
- HdmiCecMessageBuilder.buildFeatureAbortCommand(ADDR_PLAYBACK_1, ADDR_TV,
- vendorCommand.getOpcode(), Constants.ABORT_REFUSED);
+ assertEquals(Constants.ABORT_REFUSED, result);
}
@Test
public void handleVendorCommandWithId_notHandled_Cec14() {
HdmiCecMessage vendorCommand = HdmiCecMessageBuilder.buildVendorCommandWithId(ADDR_TV,
ADDR_PLAYBACK_1, 0x1234, new byte[]{0});
- mNativeWrapper.onCecMessage(vendorCommand);
+ @Constants.HandleMessageResult int result =
+ mHdmiLocalDevice.handleVendorCommandWithId(vendorCommand);
mTestLooper.dispatchAll();
- HdmiCecMessageBuilder.buildFeatureAbortCommand(ADDR_PLAYBACK_1, ADDR_TV,
- vendorCommand.getOpcode(), Constants.ABORT_REFUSED);
+ assertEquals(Constants.ABORT_REFUSED, result);
+ }
+
+ @Test
+ public void handleVendorCommandWithId_broadcasted_handled() {
+ HdmiCecMessage vendorCommand = HdmiCecMessageBuilder.buildVendorCommandWithId(ADDR_TV,
+ ADDR_BROADCAST, 0x1234, new byte[]{0});
+ @Constants.HandleMessageResult int result =
+ mHdmiLocalDevice.handleVendorCommandWithId(vendorCommand);
+ mTestLooper.dispatchAll();
+
+ assertEquals(Constants.HANDLED, result);
}
}