Track CEC version of CEC devices

Update tracked devices CEC version based on messages received by remote
devices.
Messages that can indicate CEC version are: <CEC Version>, <Report
Features>, <Report Power Status> (broadcast).

Bug: 169121287
Test: atest HdmiCecNetworkTest

Change-Id: I944dc1cdb93b32fb28fef4b2c111a08b232543c4
This commit is contained in:
Marvin Ramin
2020-12-07 16:41:19 +01:00
parent 6f69264f75
commit 17c51c7b85
4 changed files with 167 additions and 4 deletions

View File

@@ -282,6 +282,8 @@ abstract class HdmiCecLocalDevice {
return handleGiveOsdName(message);
case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID:
return handleGiveDeviceVendorId(null);
case Constants.MESSAGE_CEC_VERSION:
return handleCecVersion();
case Constants.MESSAGE_GET_CEC_VERSION:
return handleGetCecVersion(message);
case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
@@ -405,6 +407,14 @@ abstract class HdmiCecLocalDevice {
return true;
}
@ServiceThreadOnly
private boolean handleCecVersion() {
assertRunOnServiceThread();
// Return true to avoid <Feature Abort> responses. Cec Version is tracked in HdmiCecNetwork.
return true;
}
@ServiceThreadOnly
protected boolean handleActiveSource(HdmiCecMessage message) {
return false;

View File

@@ -166,7 +166,6 @@ public class HdmiCecNetwork {
}
return false;
}
/**
* Clear all logical addresses registered in the device.
*
@@ -523,10 +522,31 @@ public class HdmiCecNetwork {
case Constants.MESSAGE_DEVICE_VENDOR_ID:
handleDeviceVendorId(message);
break;
case Constants.MESSAGE_CEC_VERSION:
handleCecVersion(message);
break;
case Constants.MESSAGE_REPORT_FEATURES:
handleReportFeatures(message);
break;
}
}
@ServiceThreadOnly
private void handleReportFeatures(HdmiCecMessage message) {
assertRunOnServiceThread();
int version = Byte.toUnsignedInt(message.getParams()[0]);
updateDeviceCecVersion(message.getSource(), version);
}
@ServiceThreadOnly
private void handleCecVersion(HdmiCecMessage message) {
assertRunOnServiceThread();
int version = Byte.toUnsignedInt(message.getParams()[0]);
updateDeviceCecVersion(message.getSource(), version);
}
@ServiceThreadOnly
private void handleReportPhysicalAddress(HdmiCecMessage message) {
assertRunOnServiceThread();
@@ -555,6 +575,31 @@ public class HdmiCecNetwork {
// Update power status of device
int newStatus = message.getParams()[0] & 0xFF;
updateDevicePowerStatus(message.getSource(), newStatus);
if (message.getDestination() == Constants.ADDR_BROADCAST) {
updateDeviceCecVersion(message.getSource(), HdmiControlManager.HDMI_CEC_VERSION_2_0);
}
}
@ServiceThreadOnly
private void updateDeviceCecVersion(int logicalAddress, int hdmiCecVersion) {
assertRunOnServiceThread();
HdmiDeviceInfo deviceInfo = getCecDeviceInfo(logicalAddress);
if (deviceInfo == null) {
Slog.w(TAG, "Can not update CEC version of non-existing device:" + logicalAddress);
return;
}
if (deviceInfo.getCecVersion() == hdmiCecVersion) {
return;
}
HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(),
deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(),
deviceInfo.getVendorId(),
deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(),
hdmiCecVersion);
updateCecDevice(updatedDeviceInfo);
}
@ServiceThreadOnly

View File

@@ -25,6 +25,8 @@ import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
import static com.android.server.hdmi.Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -264,4 +266,14 @@ public class HdmiCecLocalDeviceTest {
assertFalse(result);
}
@Test
public void handleCecVersion_isHandled() {
boolean result = mHdmiLocalDevice.onMessage(
HdmiCecMessageBuilder.buildCecVersion(ADDR_PLAYBACK_1, mHdmiLocalDevice.mAddress,
HdmiControlManager.HDMI_CEC_VERSION_1_4_b));
assertThat(result).isTrue();
}
}

View File

@@ -36,6 +36,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@@ -313,6 +314,7 @@ public class HdmiCecNetworkTest {
int powerStatus = HdmiControlManager.POWER_STATUS_ON;
String osdName = "Test Device";
int vendorId = 1234;
int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(logicalAddress,
@@ -325,6 +327,8 @@ public class HdmiCecNetworkTest {
Constants.ADDR_BROADCAST, osdName));
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildDeviceVendorIdCommand(logicalAddress, vendorId));
mHdmiCecNetwork.handleCecMessage(HdmiCecMessageBuilder.buildCecVersion(logicalAddress,
Constants.ADDR_BROADCAST, cecVersion));
assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
@@ -335,6 +339,7 @@ public class HdmiCecNetworkTest {
assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(osdName);
assertThat(cecDeviceInfo.getVendorId()).isEqualTo(vendorId);
assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
}
@Test
@@ -374,16 +379,18 @@ public class HdmiCecNetworkTest {
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress,
Constants.ADDR_BROADCAST, powerStatus));
Constants.ADDR_TV, powerStatus));
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress,
Constants.ADDR_BROADCAST, updatedPowerStatus));
Constants.ADDR_TV, updatedPowerStatus));
assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(updatedPowerStatus);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
}
@Test
@@ -428,6 +435,8 @@ public class HdmiCecNetworkTest {
assertThat(cecDeviceInfo.getVendorId()).isEqualTo(updatedVendorId);
assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
HdmiControlManager.POWER_STATUS_UNKNOWN);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
}
@Test
@@ -446,4 +455,91 @@ public class HdmiCecNetworkTest {
HdmiControlManager.DEVICE_EVENT_ADD_DEVICE,
HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
}
@Test
public void cecDevices_tracking_reportPowerStatus_broadcast_infersCec2() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
int powerStatus = HdmiControlManager.POWER_STATUS_ON;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress,
Constants.ADDR_BROADCAST, powerStatus));
assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
Constants.INVALID_PHYSICAL_ADDRESS);
assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID);
assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(
HdmiUtils.getDefaultDeviceName(logicalAddress));
assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
HdmiControlManager.HDMI_CEC_VERSION_2_0);
}
@Test
public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec14() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST,
cecVersion));
assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
}
@Test
public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec20() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST,
cecVersion));
assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
}
@Test
public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec14() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildReportFeatures(logicalAddress,
cecVersion, Collections.emptyList(),
Constants.RC_PROFILE_SOURCE, Collections.emptyList(),
Collections.emptyList()));
assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
}
@Test
public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec20() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildReportFeatures(logicalAddress,
cecVersion, Collections.emptyList(),
Constants.RC_PROFILE_SOURCE, Collections.emptyList(),
Collections.emptyList()));
assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
}
}