Merge changes I0083953e,Icc8df58d,I84e828ed,I58aff832

* changes:
  Handle out-of-bound indices
  Clarify which HAL (methods) apply to which devices
  Update HAL interface
  Add portId to HPD-related methods
This commit is contained in:
Nathalie Le Clair
2023-03-02 07:24:47 +00:00
committed by Gerrit Code Review
17 changed files with 177 additions and 122 deletions

8
tv/README.md Normal file
View File

@@ -0,0 +1,8 @@
# TV-related HIDL and AIDL HALs
This directory bundles TV-related HALs in HIDL (legacy) and AIDL.
- The 'tuner' directory contains the Tuner HIDL and AIDL HALs.
- The 'input' directory contains the TV Input HIDL and AIDL HALs.
- The 'cec' directory contains the CEC HIDL HAL.
- The 'hdmi' directory contains the HDMI-related AIDL HALs, which includes the CEC AIDL HAL.

11
tv/hdmi/README.md Normal file
View File

@@ -0,0 +1,11 @@
# HDMI-related AIDL HALs for Android devices
This directory bundles 3 HDMI-related AIDL HALs: HDMI Connection HAL, CEC HAL and eARC HAL.
The HDMI Connection HAL contains general APIs for the HDMI Connection. These methods are required by
the CEC and the eARC implementation. Therefore, devices that implement CEC need to support the HDMI
Connection HAL and the CEC HAL. Devices that implement eARC need to support the HDMI Connection HAL
and the eARC HAL.
Other Android HALs are related to HDMI as well, but not included in this directory for historical
reasons, e.g. Display HAL and TV Input HAL.

View File

@@ -34,7 +34,7 @@
package android.hardware.tv.hdmi.cec;
@Backing(type="byte") @VintfStability
enum CecDeviceType {
INACTIVE = -1,
INACTIVE = (-1) /* -1 */,
TV = 0,
RECORDER = 1,
TUNER = 3,

View File

@@ -34,78 +34,78 @@
package android.hardware.tv.hdmi.cec;
@Backing(type="int") @VintfStability
enum CecMessageType {
FEATURE_ABORT = 0,
IMAGE_VIEW_ON = 4,
TUNER_STEP_INCREMENT = 5,
TUNER_STEP_DECREMENT = 6,
TUNER_DEVICE_STATUS = 7,
GIVE_TUNER_DEVICE_STATUS = 8,
RECORD_ON = 9,
RECORD_STATUS = 10,
RECORD_OFF = 11,
TEXT_VIEW_ON = 13,
RECORD_TV_SCREEN = 15,
GIVE_DECK_STATUS = 26,
DECK_STATUS = 27,
SET_MENU_LANGUAGE = 50,
CLEAR_ANALOG_TIMER = 51,
SET_ANALOG_TIMER = 52,
TIMER_STATUS = 53,
STANDBY = 54,
PLAY = 65,
DECK_CONTROL = 66,
TIMER_CLEARED_STATUS = 67,
USER_CONTROL_PRESSED = 68,
USER_CONTROL_RELEASED = 69,
GIVE_OSD_NAME = 70,
SET_OSD_NAME = 71,
SET_OSD_STRING = 100,
SET_TIMER_PROGRAM_TITLE = 103,
SYSTEM_AUDIO_MODE_REQUEST = 112,
GIVE_AUDIO_STATUS = 113,
SET_SYSTEM_AUDIO_MODE = 114,
REPORT_AUDIO_STATUS = 122,
GIVE_SYSTEM_AUDIO_MODE_STATUS = 125,
SYSTEM_AUDIO_MODE_STATUS = 126,
ROUTING_CHANGE = 128,
ROUTING_INFORMATION = 129,
ACTIVE_SOURCE = 130,
GIVE_PHYSICAL_ADDRESS = 131,
REPORT_PHYSICAL_ADDRESS = 132,
REQUEST_ACTIVE_SOURCE = 133,
SET_STREAM_PATH = 134,
DEVICE_VENDOR_ID = 135,
VENDOR_COMMAND = 137,
VENDOR_REMOTE_BUTTON_DOWN = 138,
VENDOR_REMOTE_BUTTON_UP = 139,
GIVE_DEVICE_VENDOR_ID = 140,
MENU_REQUEST = 141,
MENU_STATUS = 142,
GIVE_DEVICE_POWER_STATUS = 143,
REPORT_POWER_STATUS = 144,
GET_MENU_LANGUAGE = 145,
SELECT_ANALOG_SERVICE = 146,
SELECT_DIGITAL_SERVICE = 147,
SET_DIGITAL_TIMER = 151,
CLEAR_DIGITAL_TIMER = 153,
SET_AUDIO_RATE = 154,
INACTIVE_SOURCE = 157,
CEC_VERSION = 158,
GET_CEC_VERSION = 159,
VENDOR_COMMAND_WITH_ID = 160,
CLEAR_EXTERNAL_TIMER = 161,
SET_EXTERNAL_TIMER = 162,
REPORT_SHORT_AUDIO_DESCRIPTOR = 163,
REQUEST_SHORT_AUDIO_DESCRIPTOR = 164,
INITIATE_ARC = 192,
REPORT_ARC_INITIATED = 193,
REPORT_ARC_TERMINATED = 194,
REQUEST_ARC_INITIATION = 195,
REQUEST_ARC_TERMINATION = 196,
TERMINATE_ARC = 197,
ABORT = 255,
GIVE_FEATURES = 165,
REPORT_FEATURES = 166,
REQUEST_CURRENT_LATENCY = 167,
REPORT_CURRENT_LATENCY = 168,
FEATURE_ABORT = 0x00,
IMAGE_VIEW_ON = 0x04,
TUNER_STEP_INCREMENT = 0x05,
TUNER_STEP_DECREMENT = 0x06,
TUNER_DEVICE_STATUS = 0x07,
GIVE_TUNER_DEVICE_STATUS = 0x08,
RECORD_ON = 0x09,
RECORD_STATUS = 0x0A,
RECORD_OFF = 0x0B,
TEXT_VIEW_ON = 0x0D,
RECORD_TV_SCREEN = 0x0F,
GIVE_DECK_STATUS = 0x1A,
DECK_STATUS = 0x1B,
SET_MENU_LANGUAGE = 0x32,
CLEAR_ANALOG_TIMER = 0x33,
SET_ANALOG_TIMER = 0x34,
TIMER_STATUS = 0x35,
STANDBY = 0x36,
PLAY = 0x41,
DECK_CONTROL = 0x42,
TIMER_CLEARED_STATUS = 0x43,
USER_CONTROL_PRESSED = 0x44,
USER_CONTROL_RELEASED = 0x45,
GIVE_OSD_NAME = 0x46,
SET_OSD_NAME = 0x47,
SET_OSD_STRING = 0x64,
SET_TIMER_PROGRAM_TITLE = 0x67,
SYSTEM_AUDIO_MODE_REQUEST = 0x70,
GIVE_AUDIO_STATUS = 0x71,
SET_SYSTEM_AUDIO_MODE = 0x72,
REPORT_AUDIO_STATUS = 0x7A,
GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
SYSTEM_AUDIO_MODE_STATUS = 0x7E,
ROUTING_CHANGE = 0x80,
ROUTING_INFORMATION = 0x81,
ACTIVE_SOURCE = 0x82,
GIVE_PHYSICAL_ADDRESS = 0x83,
REPORT_PHYSICAL_ADDRESS = 0x84,
REQUEST_ACTIVE_SOURCE = 0x85,
SET_STREAM_PATH = 0x86,
DEVICE_VENDOR_ID = 0x87,
VENDOR_COMMAND = 0x89,
VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
VENDOR_REMOTE_BUTTON_UP = 0x8B,
GIVE_DEVICE_VENDOR_ID = 0x8C,
MENU_REQUEST = 0x8D,
MENU_STATUS = 0x8E,
GIVE_DEVICE_POWER_STATUS = 0x8F,
REPORT_POWER_STATUS = 0x90,
GET_MENU_LANGUAGE = 0x91,
SELECT_ANALOG_SERVICE = 0x92,
SELECT_DIGITAL_SERVICE = 0x93,
SET_DIGITAL_TIMER = 0x97,
CLEAR_DIGITAL_TIMER = 0x99,
SET_AUDIO_RATE = 0x9A,
INACTIVE_SOURCE = 0x9D,
CEC_VERSION = 0x9E,
GET_CEC_VERSION = 0x9F,
VENDOR_COMMAND_WITH_ID = 0xA0,
CLEAR_EXTERNAL_TIMER = 0xA1,
SET_EXTERNAL_TIMER = 0xA2,
REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3,
REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4,
INITIATE_ARC = 0xC0,
REPORT_ARC_INITIATED = 0xC1,
REPORT_ARC_TERMINATED = 0xC2,
REQUEST_ARC_INITIATION = 0xC3,
REQUEST_ARC_TERMINATION = 0xC4,
TERMINATE_ARC = 0xC5,
ABORT = 0xFF,
GIVE_FEATURES = 0xA5,
REPORT_FEATURES = 0xA6,
REQUEST_CURRENT_LATENCY = 0xA7,
REPORT_CURRENT_LATENCY = 0xA8,
}

View File

@@ -41,7 +41,7 @@ interface IHdmiCec {
int getPhysicalAddress();
int getVendorId();
android.hardware.tv.hdmi.cec.SendMessageResult sendMessage(in android.hardware.tv.hdmi.cec.CecMessage message);
void setCallback(in android.hardware.tv.hdmi.cec.IHdmiCecCallback callback);
void setCallback(in @nullable android.hardware.tv.hdmi.cec.IHdmiCecCallback callback);
void setLanguage(in String language);
void enableWakeupByOtp(in boolean value);
void enableCec(in boolean value);

View File

@@ -77,7 +77,7 @@ interface IHdmiCec {
* plugged off and on again. It is advised to call getPhysicalAddress to get
* the updated address when hot plug event takes place.
*
* @param out addr Physical address of this device.
* @return Physical address of this device.
*/
int getPhysicalAddress();
@@ -116,7 +116,7 @@ interface IHdmiCec {
* previously registered callback must be replaced with this one.
* setCallback(null) should deregister the callback.
*/
void setCallback(in IHdmiCecCallback callback);
void setCallback(in @nullable IHdmiCecCallback callback);
/**
* Passes the updated language information of Android system. Contains

View File

@@ -37,6 +37,6 @@ interface IHdmiConnection {
android.hardware.tv.hdmi.connection.HdmiPortInfo[] getPortInfo();
boolean isConnected(in int portId);
void setCallback(in android.hardware.tv.hdmi.connection.IHdmiConnectionCallback callback);
void setHpdSignal(android.hardware.tv.hdmi.connection.HpdSignal signal);
android.hardware.tv.hdmi.connection.HpdSignal getHpdSignal();
void setHpdSignal(android.hardware.tv.hdmi.connection.HpdSignal signal, in int portId);
android.hardware.tv.hdmi.connection.HpdSignal getHpdSignal(in int portId);
}

View File

@@ -24,10 +24,16 @@ import android.hardware.tv.hdmi.connection.HdmiPortType;
@VintfStability
parcelable HdmiPortInfo {
HdmiPortType type;
int portId; // Output ports should start from 1 which corresponds to HDMI "port 1".
int portId; // For devices with input ports (e.g. TV Panels), input ports should start from 1
// which corresponds to HDMI "port 1".
// In the following, 'supported' refers to having the necessary hardware and firmware on the
// device to support CEC/ARC/eARC on this port.
boolean cecSupported;
boolean arcSupported;
boolean arcSupported; // If true, cecSupported has to be true as well. ARC cannot be supported
// without CEC support.
boolean eArcSupported;
// The physical address of the device connected to this port, valid range is 0x0000 to 0xFFFF
// (ref Sec 8.7.2 of HDMI 1.4b).
int physicalAddress;

View File

@@ -55,16 +55,33 @@ interface IHdmiConnection {
* signaling EDID updates). By default, the HAL will use {@code HDMI_HPD_PHYSICAL} (the physical
* hotplug signal). When set to {@code HDMI_HPD_STATUS_BIT} the HAL should use the HDP status
* bit.
*
* This is only relevant to TV Panel devices that support eARC TX. While eARC TX is connected,
* the framework calls this method to set the HPD signal to {@code HDMI_HPD_STATUS_BIT}.
*
* For all other device types, this method can be stubbed.
*
* @param signal The HPD signal type to use.
* @param portId id of the port on which the HPD signal should be set.
*
* @throws ServiceSpecificException with error code set to
* {@code Result::FAILURE_NOT_SUPPORTED} if the signal type is not supported.
* {@code Result::FAILURE_INVALID_ARGS} if the signal type is invalid.
* {@code Result::FAILURE_UNKNOWN} if the signal type could not be set because of an
* unknown failure.
*/
void setHpdSignal(HpdSignal signal);
void setHpdSignal(HpdSignal signal, in int portId);
/**
* Get the current signal the HAL is using for HPD
*
* This is only relevant to TV Panel devices that support eARC TX. While eARC TX is connected,
* this method returns {@code HDMI_HPD_STATUS_BIT}.
*
* For all other device types, this method can be stubbed by always returning
* {@code HDMI_HPD_PHYSICAL}.
*
* @param portId id of the port of which the current HPD signal is queried.
*/
HpdSignal getHpdSignal();
HpdSignal getHpdSignal(in int portId);
}

View File

@@ -69,18 +69,23 @@ ScopedAStatus HdmiConnectionMock::setCallback(
return ScopedAStatus::ok();
}
ScopedAStatus HdmiConnectionMock::setHpdSignal(HpdSignal signal) {
if (mHdmiThreadRun) {
mHpdSignal = signal;
return ScopedAStatus::ok();
} else {
ScopedAStatus HdmiConnectionMock::setHpdSignal(HpdSignal signal, int32_t portId) {
if (portId > mTotalPorts || portId < 1) {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
if (!mHdmiThreadRun) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::FAILURE_INVALID_STATE));
}
mHpdSignal.at(portId - 1) = signal;
return ScopedAStatus::ok();
}
ScopedAStatus HdmiConnectionMock::getHpdSignal(HpdSignal* _aidl_return) {
*_aidl_return = mHpdSignal;
ScopedAStatus HdmiConnectionMock::getHpdSignal(int32_t portId, HpdSignal* _aidl_return) {
if (portId > mTotalPorts || portId < 1) {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
*_aidl_return = mHpdSignal.at(portId - 1);
return ScopedAStatus::ok();
}
@@ -123,7 +128,7 @@ void HdmiConnectionMock::handleHotplugMessage(unsigned char* msgBuf) {
bool connected = ((msgBuf[3]) & 0xf) > 0;
int32_t portId = static_cast<uint32_t>(msgBuf[0] & 0xf);
if (portId > static_cast<int32_t>(mPortInfos.size())) {
if (portId > static_cast<int32_t>(mPortInfos.size()) || portId < 1) {
ALOGD("[halimp_aidl] ignore hot plug message, id %x does not exist", portId);
return;
}
@@ -179,6 +184,7 @@ HdmiConnectionMock::HdmiConnectionMock() {
mCallback = nullptr;
mPortInfos.resize(mTotalPorts);
mPortConnectionStatus.resize(mTotalPorts);
mHpdSignal.resize(mTotalPorts);
mPortInfos[0] = {.type = HdmiPortType::OUTPUT,
.portId = static_cast<uint32_t>(1),
.cecSupported = true,
@@ -186,6 +192,7 @@ HdmiConnectionMock::HdmiConnectionMock() {
.eArcSupported = false,
.physicalAddress = mPhysicalAddress};
mPortConnectionStatus[0] = false;
mHpdSignal[0] = HpdSignal::HDMI_HPD_PHYSICAL;
mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
}

View File

@@ -46,8 +46,8 @@ struct HdmiConnectionMock : public BnHdmiConnection {
::ndk::ScopedAStatus isConnected(int32_t portId, bool* _aidl_return) override;
::ndk::ScopedAStatus setCallback(
const std::shared_ptr<IHdmiConnectionCallback>& callback) override;
::ndk::ScopedAStatus setHpdSignal(HpdSignal signal) override;
::ndk::ScopedAStatus getHpdSignal(HpdSignal* _aidl_return) override;
::ndk::ScopedAStatus setHpdSignal(HpdSignal signal, int32_t portId) override;
::ndk::ScopedAStatus getHpdSignal(int32_t portId, HpdSignal* _aidl_return) override;
void printEventBuf(const char* msg_buf, int len);
@@ -70,7 +70,7 @@ struct HdmiConnectionMock : public BnHdmiConnection {
int mTotalPorts = 1;
// HPD Signal being used
HpdSignal mHpdSignal = HpdSignal::HDMI_HPD_PHYSICAL;
std::vector<HpdSignal> mHpdSignal;
// Testing variables
// Input file descriptor

View File

@@ -93,8 +93,8 @@ TEST_P(HdmiConnectionTest, GetPortInfo) {
for (size_t i = 0; i < ports.size(); ++i) {
EXPECT_TRUE((ports[i].type == HdmiPortType::OUTPUT) ||
(ports[i].type == HdmiPortType::INPUT));
if (ports[i].portId == 0) {
ALOGW("%s: Port id should start from 1", __func__);
if (ports[i].type == HdmiPortType::OUTPUT && ports[i].portId <= 0) {
ALOGW("%s: Port id for output ports should start from 1", __func__);
}
cecSupportedOnDevice = cecSupportedOnDevice | ports[i].cecSupported;
}
@@ -111,16 +111,21 @@ TEST_P(HdmiConnectionTest, IsConnected) {
}
TEST_P(HdmiConnectionTest, HdpSignal) {
std::vector<HdmiPortInfo> ports;
ASSERT_TRUE(hdmiConnection->getPortInfo(&ports).isOk());
HpdSignal originalSignal;
HpdSignal signal = HpdSignal::HDMI_HPD_STATUS_BIT;
HpdSignal readSignal;
ASSERT_TRUE(hdmiConnection->getHpdSignal(&originalSignal).isOk());
ASSERT_TRUE(hdmiConnection->setHpdSignal(signal).isOk());
ASSERT_TRUE(hdmiConnection->getHpdSignal(&readSignal).isOk());
EXPECT_EQ(readSignal, signal);
signal = HpdSignal::HDMI_HPD_PHYSICAL;
ASSERT_TRUE(hdmiConnection->setHpdSignal(signal).isOk());
ASSERT_TRUE(hdmiConnection->getHpdSignal(&readSignal).isOk());
EXPECT_EQ(readSignal, signal);
ASSERT_TRUE(hdmiConnection->setHpdSignal(originalSignal).isOk());
for (size_t i = 0; i < ports.size(); ++i) {
int32_t portId = ports[i].portId;
HpdSignal readSignal;
ASSERT_TRUE(hdmiConnection->getHpdSignal(portId, &originalSignal).isOk());
ASSERT_TRUE(hdmiConnection->setHpdSignal(signal, portId).isOk());
ASSERT_TRUE(hdmiConnection->getHpdSignal(portId, &readSignal).isOk());
EXPECT_EQ(readSignal, signal);
signal = HpdSignal::HDMI_HPD_PHYSICAL;
ASSERT_TRUE(hdmiConnection->setHpdSignal(signal, portId).isOk());
ASSERT_TRUE(hdmiConnection->getHpdSignal(portId, &readSignal).isOk());
EXPECT_EQ(readSignal, signal);
ASSERT_TRUE(hdmiConnection->setHpdSignal(originalSignal, portId).isOk());
}
}

View File

@@ -34,8 +34,8 @@
package android.hardware.tv.hdmi.earc;
@Backing(type="byte") @VintfStability
enum IEArcStatus {
STATUS_IDLE = 0,
STATUS_EARC_PENDING = 1,
STATUS_ARC_PENDING = 2,
STATUS_EARC_CONNECTED = 3,
IDLE = 0,
EARC_PENDING = 1,
ARC_PENDING = 2,
EARC_CONNECTED = 3,
}

View File

@@ -20,7 +20,7 @@ import android.hardware.tv.hdmi.earc.IEArcCallback;
import android.hardware.tv.hdmi.earc.IEArcStatus;
/**
* eARC HAL interface definition
* eARC HAL interface definition. This is only relevant to TV Panels that implement eARC TX.
*/
@VintfStability
interface IEArc {
@@ -64,10 +64,11 @@ interface IEArc {
IEArcStatus getState(in int portId);
/**
* Getter for the most recent capabilities reported by the device connected to port.
* Getter for the most recent audio capabilities reported by the device connected to port.
*
* @param portId The port ID on which the device is connected.
* @return The raw, unparsed audio capabilities
* @return a byte array containing the raw, unparsed audio capabilities (Ref "Section 9.5.3.6 -
* eARC RX Capabilities Data Structure" in HDMI 2.1 specification).
*/
byte[] getLastReportedAudioCapabilities(in int portId);
}

View File

@@ -34,9 +34,9 @@ oneway interface IEArcCallback {
/**
* The callback function that must be called by the eARC driver and HAL implementation to
* notify the Android framework of the audio capabilities reported by the connected device. On
* every state change to {@code STATUS_EARC_CONNECTED}, the driver shall read the capabilities
* reported by the eARC RX. The onStateChange callback shall always be invoked first and the
* onCapabilitiesReported callback shall be invoked second.
* every state change to {@code IEArcStatus::EARC_CONNECTED}, the driver shall read the
* capabilities reported by the eARC RX. The onStateChange callback shall always be invoked
* first and the onCapabilitiesReported callback shall be invoked second.
* @param rawCapabilities The raw unparsed audio capabilities (Ref "Section 9.5.3.6 - eARC RX
* Capabilities Data Structure" in HDMI 2.1 specification).
* @param portId The port ID for which the audio capabilities are being reported

View File

@@ -22,8 +22,8 @@ package android.hardware.tv.hdmi.earc;
@VintfStability
@Backing(type="byte")
enum IEArcStatus {
STATUS_IDLE = 0,
STATUS_EARC_PENDING = 1,
STATUS_ARC_PENDING = 2,
STATUS_EARC_CONNECTED = 3,
IDLE = 0,
EARC_PENDING = 1,
ARC_PENDING = 2,
EARC_CONNECTED = 3,
}

View File

@@ -109,7 +109,7 @@ EArcMock::EArcMock() {
mCallback = nullptr;
mCapabilities.resize(mTotalPorts);
mPortStatus.resize(mTotalPorts);
mPortStatus[0] = IEArcStatus::STATUS_IDLE;
mPortStatus[0] = IEArcStatus::IDLE;
mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
}