diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 5dcea2d8a2..3158624289 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -668,6 +668,20 @@ default + + android.hardware.tv.cec + + IHdmiCec + default + + + + android.hardware.tv.hdmi + + IHdmi + default + + android.hardware.tv.input 1.0 diff --git a/tv/cec/aidl/Android.bp b/tv/cec/aidl/Android.bp new file mode 100644 index 0000000000..0b0e7cf3d5 --- /dev/null +++ b/tv/cec/aidl/Android.bp @@ -0,0 +1,29 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.tv.cec", + vendor_available: true, + srcs: ["android/hardware/tv/cec/*.aidl"], + stability: "vintf", + backend: { + java: { + sdk_version: "module_current", + }, + }, +} diff --git a/tv/cec/aidl/OWNERS b/tv/cec/aidl/OWNERS new file mode 100644 index 0000000000..d9c678363b --- /dev/null +++ b/tv/cec/aidl/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 826094 +include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS \ No newline at end of file diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl new file mode 100644 index 0000000000..7377d81357 --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@Backing(type="int") @VintfStability +enum AbortReason { + UNRECOGNIZED_MODE = 0, + NOT_IN_CORRECT_MODE = 1, + CANNOT_PROVIDE_SOURCE = 2, + INVALID_OPERAND = 3, + REFUSED = 4, + UNABLE_TO_DETERMINE = 5, +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl new file mode 100644 index 0000000000..4d991cd7e9 --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@Backing(type="byte") @VintfStability +enum CecDeviceType { + INACTIVE = -1, + TV = 0, + RECORDER = 1, + TUNER = 3, + PLAYBACK = 4, + AUDIO_SYSTEM = 5, +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl new file mode 100644 index 0000000000..a36935bd30 --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@Backing(type="byte") @VintfStability +enum CecLogicalAddress { + TV = 0, + RECORDER_1 = 1, + RECORDER_2 = 2, + TUNER_1 = 3, + PLAYBACK_1 = 4, + AUDIO_SYSTEM = 5, + TUNER_2 = 6, + TUNER_3 = 7, + PLAYBACK_2 = 8, + RECORDER_3 = 9, + TUNER_4 = 10, + PLAYBACK_3 = 11, + BACKUP_1 = 12, + BACKUP_2 = 13, + FREE_USE = 14, + BROADCAST = 15, + UNREGISTERED = 15, +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl new file mode 100644 index 0000000000..5ce5ce80bb --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@VintfStability +parcelable CecMessage { + android.hardware.tv.cec.CecLogicalAddress initiator; + android.hardware.tv.cec.CecLogicalAddress destination; + byte[] body; + const int MAX_MESSAGE_BODY_LENGTH = 15; +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl new file mode 100644 index 0000000000..61ebb94c30 --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.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, +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl new file mode 100644 index 0000000000..cf8425ef2d --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@VintfStability +interface IHdmiCec { + android.hardware.tv.cec.Result addLogicalAddress(in android.hardware.tv.cec.CecLogicalAddress addr); + void clearLogicalAddress(); + void enableAudioReturnChannel(in int portId, in boolean enable); + int getCecVersion(); + int getPhysicalAddress(); + int getVendorId(); + android.hardware.tv.cec.SendMessageResult sendMessage(in android.hardware.tv.cec.CecMessage message); + void setCallback(in android.hardware.tv.cec.IHdmiCecCallback callback); + void setLanguage(in String language); + void enableWakeupByOtp(in boolean value); + void enableCec(in boolean value); + void enableSystemCecControl(in boolean value); +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl new file mode 100644 index 0000000000..1918765e49 --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@VintfStability +interface IHdmiCecCallback { + oneway void onCecMessage(in android.hardware.tv.cec.CecMessage message); +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl new file mode 100644 index 0000000000..a5ba2764a7 --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@Backing(type="byte") @VintfStability +enum Result { + SUCCESS = 0, + FAILURE_UNKNOWN = 1, + FAILURE_INVALID_ARGS = 2, + FAILURE_INVALID_STATE = 3, + FAILURE_NOT_SUPPORTED = 4, + FAILURE_BUSY = 5, +} diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl new file mode 100644 index 0000000000..58206c8c5e --- /dev/null +++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.cec; +@Backing(type="byte") @VintfStability +enum SendMessageResult { + SUCCESS = 0, + NACK = 1, + BUSY = 2, + FAIL = 3, +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl b/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl new file mode 100644 index 0000000000..3ae23ec2eb --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +/** + * Operand description [Abort Reason] + */ +@VintfStability +@Backing(type="int") +enum AbortReason { + UNRECOGNIZED_MODE = 0, + NOT_IN_CORRECT_MODE = 1, + CANNOT_PROVIDE_SOURCE = 2, + INVALID_OPERAND = 3, + REFUSED = 4, + UNABLE_TO_DETERMINE = 5, +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl new file mode 100644 index 0000000000..16dfbecdd6 --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +@VintfStability +@Backing(type="byte") +enum CecDeviceType { + INACTIVE = -1, + TV = 0, + RECORDER = 1, + TUNER = 3, + PLAYBACK = 4, + AUDIO_SYSTEM = 5, +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl new file mode 100644 index 0000000000..fbf53283a2 --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +@VintfStability +@Backing(type="byte") +enum CecLogicalAddress { + TV = 0, + RECORDER_1 = 1, + RECORDER_2 = 2, + TUNER_1 = 3, + PLAYBACK_1 = 4, + AUDIO_SYSTEM = 5, + TUNER_2 = 6, + TUNER_3 = 7, + PLAYBACK_2 = 8, + RECORDER_3 = 9, + TUNER_4 = 10, + PLAYBACK_3 = 11, + BACKUP_1 = 12, + BACKUP_2 = 13, + FREE_USE = 14, + BROADCAST = 15, + UNREGISTERED = 15, +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl new file mode 100644 index 0000000000..b126045a40 --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +import android.hardware.tv.cec.CecLogicalAddress; + +@VintfStability +parcelable CecMessage { + /** + * Maximum length of the message body + */ + const int MAX_MESSAGE_BODY_LENGTH = 15; + /** + * logical address of the initiator + */ + CecLogicalAddress initiator; + /** + * logical address of destination + */ + CecLogicalAddress destination; + /** + * The maximum size of body is 15 (MAX_MESSAGE_BODY_LENGTH) as specified in + * the section 6 of the CEC Spec 1.4b. Overflowed data must be ignored. + */ + byte[] body; +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl new file mode 100644 index 0000000000..b544a91f53 --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +@VintfStability +@Backing(type="int") +enum CecMessageType { + 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, +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl new file mode 100644 index 0000000000..dbf7139458 --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +import android.hardware.tv.cec.CecLogicalAddress; +import android.hardware.tv.cec.CecMessage; +import android.hardware.tv.cec.IHdmiCecCallback; +import android.hardware.tv.cec.Result; +import android.hardware.tv.cec.SendMessageResult; + +/** + * HDMI-CEC HAL interface definition. + */ +@VintfStability +interface IHdmiCec { + /** + * Passes the logical address that must be used in this system. + * + * HAL must use it to configure the hardware so that the CEC commands + * addressed the given logical address can be filtered in. This method must + * be able to be called as many times as necessary in order to support + * multiple logical devices. + * + * @param addr Logical address that must be used in this system. It must be + * in the range of valid logical addresses for the call to succeed. + * @return Result status of the operation. SUCCESS if successful, + * FAILURE_INVALID_ARGS if the given logical address is invalid, + * FAILURE_BUSY if device or resource is busy + */ + Result addLogicalAddress(in CecLogicalAddress addr); + + /** + * Clears all the logical addresses. + * + * It is used when the system doesn't need to process CEC command any more, + * hence to tell HAL to stop receiving commands from the CEC bus, and change + * the state back to the beginning. + */ + void clearLogicalAddress(); + + /** + * Configures ARC circuit in the hardware logic to start or stop the + * feature. + * + * @param portId Port id to be configured. + * @param enable Flag must be either true to start the feature or false to + * stop it. + */ + void enableAudioReturnChannel(in int portId, in boolean enable); + + /** + * Returns the CEC version supported by underlying hardware. + * + * @return the CEC version supported by underlying hardware. + */ + int getCecVersion(); + + /** + * Gets the CEC physical address. + * + * The physical address depends on the topology of the network formed by + * connected HDMI devices. It is therefore likely to change if the cable is + * 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. + */ + int getPhysicalAddress(); + + /** + * Gets the identifier of the vendor. + * + * @return Identifier of the vendor that is the 24-bit unique + * company ID obtained from the IEEE Registration Authority + * Committee (RAC). The upper 8 bits must be 0. + */ + int getVendorId(); + + /** + * Transmits HDMI-CEC message to other HDMI device. + * + * The method must be designed to return in a certain amount of time and not + * hanging forever which may happen if CEC signal line is pulled low for + * some reason. + * + * It must try retransmission at least once as specified in the section '7.1 + * Frame Re-transmissions' of the CEC Spec 1.4b. + * + * @param message CEC message to be sent to other HDMI device. + * @return Result status of the operation. SUCCESS if successful, + * NACK if the sent message is not acknowledged, + * BUSY if the CEC bus is busy, + * FAIL if the message could not be sent. + */ + SendMessageResult sendMessage(in CecMessage message); + + /** + * Sets a callback that HDMI-CEC HAL must later use for incoming CEC + * messages. + * + * @param callback Callback object to pass hdmi events to the system. The + * previously registered callback must be replaced with this one. + * setCallback(null) should deregister the callback. + */ + void setCallback(in IHdmiCecCallback callback); + + /** + * Passes the updated language information of Android system. Contains + * three-letter code as defined in ISO/FDIS 639-2. Must be used for HAL to + * respond to while in standby mode. + * + * @param language Three-letter code defined in ISO/FDIS 639-2. Must be + * lowercase letters. (e.g., eng for English) + */ + void setLanguage(in String language); + + /** + * Determines whether a TV panel device in standby mode should wake up when + * it receives an OTP (One Touch Play) from a source device. + * + * @param value If true, the TV device will wake up when OTP is received + * and if false, the TV device will not wake up for an OTP. + */ + void enableWakeupByOtp(in boolean value); + + /** + * Switch to enable or disable CEC on the device. + * + * @param value If true, the device will have all CEC functionalities + * and if false, the device will not perform any CEC functions. + */ + void enableCec(in boolean value); + + /** + * Determines which module processes CEC messages - the Android framework or + * the HAL. + * + * @param value If true, the Android framework will actively process CEC + * messages and if false, only the HAL will process the CEC messages. + */ + void enableSystemCecControl(in boolean value); +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl new file mode 100644 index 0000000000..4934a64503 --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +import android.hardware.tv.cec.CecMessage; + +/** + * Callbacks from the HAL implementation to notify the system of new events. + */ +@VintfStability +oneway interface IHdmiCecCallback { + /** + * The callback function that must be called by HAL implementation to notify + * the system of new CEC message arrival. + */ + void onCecMessage(in CecMessage message); +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/Result.aidl b/tv/cec/aidl/android/hardware/tv/cec/Result.aidl new file mode 100644 index 0000000000..3184c4677e --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/Result.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +@VintfStability +@Backing(type="byte") +enum Result { + SUCCESS = 0, + FAILURE_UNKNOWN = 1, + FAILURE_INVALID_ARGS = 2, + FAILURE_INVALID_STATE = 3, + FAILURE_NOT_SUPPORTED = 4, + FAILURE_BUSY = 5, +} diff --git a/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl b/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl new file mode 100644 index 0000000000..8cb98bc322 --- /dev/null +++ b/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec; + +/** + * error code used for send_message. + */ +@VintfStability +@Backing(type="byte") +enum SendMessageResult { + SUCCESS = 0, + NACK = 1, + BUSY = 2, + FAIL = 3, +} diff --git a/tv/cec/aidl/default/Android.bp b/tv/cec/aidl/default/Android.bp new file mode 100644 index 0000000000..547960112c --- /dev/null +++ b/tv/cec/aidl/default/Android.bp @@ -0,0 +1,58 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.tv.cec-service", + vintf_fragments: ["android.hardware.tv.cec-service.xml"], + relative_install_path: "hw", + vendor: true, + cflags: [ + "-Wall", + "-Wextra", + ], + init_rc: ["android.hardware.tv.cec-service.rc"], + srcs: [ + "serviceMock.cpp", + "HdmiCecMock.cpp", + ], + shared_libs: [ + "libbinder_ndk", + "liblog", + "libbase", + "libutils", + "libhardware", + "libhidlbase", + "android.hardware.tv.cec-V1-ndk", + ], +} + +cc_fuzz { + name: "android.hardware.tv.cec-service_fuzzer", + defaults: ["service_fuzzer_defaults"], + static_libs: [ + "android.hardware.tv.cec-V1-ndk", + "liblog", + ], + srcs: [ + "fuzzer.cpp", + "HdmiCecMock.cpp", + ], + fuzz_config: { + componentid: 826094, + }, +} diff --git a/tv/cec/aidl/default/HdmiCecMock.cpp b/tv/cec/aidl/default/HdmiCecMock.cpp new file mode 100644 index 0000000000..d8d655b79f --- /dev/null +++ b/tv/cec/aidl/default/HdmiCecMock.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec" +#include +#include +#include + +#include +#include +#include "HdmiCecMock.h" + +using ndk::ScopedAStatus; + +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace implementation { + +void HdmiCecMock::serviceDied(void* cookie) { + ALOGE("HdmiCecMock died"); + auto hdmiCecMock = static_cast(cookie); + hdmiCecMock->mCecThreadRun = false; +} + +ScopedAStatus HdmiCecMock::addLogicalAddress(CecLogicalAddress addr, Result* _aidl_return) { + // Have a list to maintain logical addresses + mLogicalAddresses.push_back(addr); + *_aidl_return = Result::SUCCESS; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::clearLogicalAddress() { + // Remove logical address from the list + mLogicalAddresses = {}; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::enableAudioReturnChannel(int32_t portId __unused, bool enable __unused) { + // Maintain ARC status + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::getCecVersion(int32_t* _aidl_return) { + // Maintain a cec version and return it + *_aidl_return = mCecVersion; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::getPhysicalAddress(int32_t* _aidl_return) { + // Maintain a physical address and return it + // Default 0xFFFF, update on hotplug event + *_aidl_return = mPhysicalAddress; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::getVendorId(int32_t* _aidl_return) { + *_aidl_return = mCecVendorId; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::sendMessage(const CecMessage& message, SendMessageResult* _aidl_return) { + if (message.body.size() == 0) { + *_aidl_return = SendMessageResult::NACK; + } else { + sendMessageToFifo(message); + *_aidl_return = SendMessageResult::SUCCESS; + } + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::setCallback(const std::shared_ptr& callback) { + // If callback is null, mCallback is also set to null so we do not call the old callback. + mCallback = callback; + + if (callback != nullptr) { + AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */); + + mInputFile = open(CEC_MSG_IN_FIFO, O_RDWR | O_CLOEXEC); + mOutputFile = open(CEC_MSG_OUT_FIFO, O_RDWR | O_CLOEXEC); + pthread_create(&mThreadId, NULL, __threadLoop, this); + pthread_setname_np(mThreadId, "hdmi_cec_loop"); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::setLanguage(const std::string& language) { + if (language.size() != 3) { + LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size() + << "."; + return ScopedAStatus::ok(); + } + // TODO Validate if language is a valid language code + const char* languageStr = language.c_str(); + int convertedLanguage = ((languageStr[0] & 0xFF) << 16) | ((languageStr[1] & 0xFF) << 8) | + (languageStr[2] & 0xFF); + mOptionLanguage = convertedLanguage; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::enableWakeupByOtp(bool value) { + mOptionWakeUp = value; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::enableCec(bool value) { + mOptionEnableCec = value; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiCecMock::enableSystemCecControl(bool value) { + mOptionSystemCecControl = value; + return ScopedAStatus::ok(); +} + +void* HdmiCecMock::__threadLoop(void* user) { + HdmiCecMock* const self = static_cast(user); + self->threadLoop(); + return 0; +} + +int HdmiCecMock::readMessageFromFifo(unsigned char* buf, int msgCount) { + if (msgCount <= 0 || !buf) { + return 0; + } + + int ret = -1; + // Maybe blocked at driver + ret = read(mInputFile, buf, msgCount); + if (ret < 0) { + ALOGE("[halimp_aidl] read :%s failed, ret:%d\n", CEC_MSG_IN_FIFO, ret); + return -1; + } + + return ret; +} + +int HdmiCecMock::sendMessageToFifo(const CecMessage& message) { + unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH + 1] = {0}; + int ret = -1; + + msgBuf[0] = ((static_cast(message.initiator) & 0xf) << 4) | + (static_cast(message.destination) & 0xf); + + size_t length = std::min(static_cast(message.body.size()), + static_cast(CEC_MESSAGE_BODY_MAX_LENGTH)); + for (size_t i = 0; i < length; ++i) { + msgBuf[i + 1] = static_cast(message.body[i]); + } + + // Open the output pipe for writing outgoing cec message + mOutputFile = open(CEC_MSG_OUT_FIFO, O_WRONLY | O_CLOEXEC); + if (mOutputFile < 0) { + ALOGD("[halimp_aidl] file open failed for writing"); + return -1; + } + + // Write message into the output pipe + ret = write(mOutputFile, msgBuf, length + 1); + close(mOutputFile); + if (ret < 0) { + ALOGE("[halimp_aidl] write :%s failed, ret:%d\n", CEC_MSG_OUT_FIFO, ret); + return -1; + } + return ret; +} + +void HdmiCecMock::printCecMsgBuf(const char* msg_buf, int len) { + int i, size = 0; + const int bufSize = CEC_MESSAGE_BODY_MAX_LENGTH * 3; + // Use 2 characters for each byte in the message plus 1 space + char buf[bufSize] = {0}; + + // Messages longer than max length will be truncated. + for (i = 0; i < len && size < bufSize; i++) { + size += sprintf(buf + size, " %02x", msg_buf[i]); + } + ALOGD("[halimp_aidl] %s, msg:%.*s", __FUNCTION__, size, buf); +} + +void HdmiCecMock::handleCecMessage(unsigned char* msgBuf, int msgSize) { + CecMessage message; + size_t length = std::min(static_cast(msgSize - 1), + static_cast(CEC_MESSAGE_BODY_MAX_LENGTH)); + message.body.resize(length); + + for (size_t i = 0; i < length; ++i) { + message.body[i] = static_cast(msgBuf[i + 1]); + ALOGD("[halimp_aidl] msg body %x", message.body[i]); + } + + message.initiator = static_cast((msgBuf[0] >> 4) & 0xf); + ALOGD("[halimp_aidl] msg init %hhd", message.initiator); + message.destination = static_cast((msgBuf[0] >> 0) & 0xf); + ALOGD("[halimp_aidl] msg dest %hhd", message.destination); + + if (mCallback != nullptr) { + mCallback->onCecMessage(message); + } +} + +void HdmiCecMock::threadLoop() { + ALOGD("[halimp_aidl] threadLoop start."); + unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH]; + int r = -1; + + // Open the input pipe + while (mInputFile < 0) { + usleep(1000 * 1000); + mInputFile = open(CEC_MSG_IN_FIFO, O_RDONLY | O_CLOEXEC); + } + ALOGD("[halimp_aidl] file open ok, fd = %d.", mInputFile); + + while (mCecThreadRun) { + if (!mOptionSystemCecControl) { + usleep(1000 * 1000); + continue; + } + + memset(msgBuf, 0, sizeof(msgBuf)); + // Try to get a message from dev. + // echo -n -e '\x04\x83' >> /dev/cec + r = readMessageFromFifo(msgBuf, CEC_MESSAGE_BODY_MAX_LENGTH); + if (r <= 1) { + // Ignore received ping messages + continue; + } + + printCecMsgBuf((const char*)msgBuf, r); + + if (((msgBuf[0] >> 4) & 0xf) == 0xf) { + // The message is a hotplug event, handled by HDMI HAL. + continue; + } + + handleCecMessage(msgBuf, r); + } + + ALOGD("[halimp_aidl] thread end."); +} + +HdmiCecMock::HdmiCecMock() { + ALOGE("[halimp_aidl] Opening a virtual CEC HAL for testing and virtual machine."); + mCallback = nullptr; + mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied)); +} + +} // namespace implementation +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/cec/aidl/default/HdmiCecMock.h b/tv/cec/aidl/default/HdmiCecMock.h new file mode 100644 index 0000000000..08f4d6f886 --- /dev/null +++ b/tv/cec/aidl/default/HdmiCecMock.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace implementation { + +using ::aidl::android::hardware::tv::cec::BnHdmiCec; +using ::aidl::android::hardware::tv::cec::CecLogicalAddress; +using ::aidl::android::hardware::tv::cec::CecMessage; +using ::aidl::android::hardware::tv::cec::IHdmiCec; +using ::aidl::android::hardware::tv::cec::IHdmiCecCallback; +using ::aidl::android::hardware::tv::cec::Result; +using ::aidl::android::hardware::tv::cec::SendMessageResult; + +#define CEC_MSG_IN_FIFO "/dev/cec_aidl_in_pipe" +#define CEC_MSG_OUT_FIFO "/dev/cec_aidl_out_pipe" + +struct HdmiCecMock : public BnHdmiCec { + HdmiCecMock(); + ::ndk::ScopedAStatus addLogicalAddress(CecLogicalAddress addr, Result* _aidl_return) override; + ::ndk::ScopedAStatus clearLogicalAddress() override; + ::ndk::ScopedAStatus enableAudioReturnChannel(int32_t portId, bool enable) override; + ::ndk::ScopedAStatus getCecVersion(int32_t* _aidl_return) override; + ::ndk::ScopedAStatus getPhysicalAddress(int32_t* _aidl_return) override; + ::ndk::ScopedAStatus getVendorId(int32_t* _aidl_return) override; + ::ndk::ScopedAStatus sendMessage(const CecMessage& message, + SendMessageResult* _aidl_return) override; + ::ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + ::ndk::ScopedAStatus setLanguage(const std::string& language) override; + ::ndk::ScopedAStatus enableWakeupByOtp(bool value) override; + ::ndk::ScopedAStatus enableCec(bool value) override; + ::ndk::ScopedAStatus enableSystemCecControl(bool value) override; + void printCecMsgBuf(const char* msg_buf, int len); + + private: + static void* __threadLoop(void* data); + void threadLoop(); + int readMessageFromFifo(unsigned char* buf, int msgCount); + int sendMessageToFifo(const CecMessage& message); + void handleCecMessage(unsigned char* msgBuf, int length); + + private: + static void serviceDied(void* cookie); + std::shared_ptr mCallback; + + // Variables for the virtual cec hal impl + uint16_t mPhysicalAddress = 0xFFFF; + vector mLogicalAddresses; + int32_t mCecVersion = 0x06; + uint32_t mCecVendorId = 0x01; + + // CEC Option value + bool mOptionWakeUp = 0; + bool mOptionEnableCec = 0; + bool mOptionSystemCecControl = 0; + int mOptionLanguage; + + // Testing variables + // Input file descriptor + int mInputFile; + // Output file descriptor + int mOutputFile; + bool mCecThreadRun = true; + pthread_t mThreadId = 0; + + ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; +}; +} // namespace implementation +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/cec/aidl/default/android.hardware.tv.cec-service.rc b/tv/cec/aidl/default/android.hardware.tv.cec-service.rc new file mode 100644 index 0000000000..c79520c430 --- /dev/null +++ b/tv/cec/aidl/default/android.hardware.tv.cec-service.rc @@ -0,0 +1,5 @@ +service vendor.cec-default /vendor/bin/hw/android.hardware.tv.cec-service + interface aidl android.hardware.tv.cec.IHdmiCec/default + class hal + user system + group system diff --git a/tv/cec/aidl/default/android.hardware.tv.cec-service.xml b/tv/cec/aidl/default/android.hardware.tv.cec-service.xml new file mode 100644 index 0000000000..e68450d46e --- /dev/null +++ b/tv/cec/aidl/default/android.hardware.tv.cec-service.xml @@ -0,0 +1,10 @@ + + + android.hardware.tv.cec + 1 + + IHdmiCec + default + + + diff --git a/tv/cec/aidl/default/fuzzer.cpp b/tv/cec/aidl/default/fuzzer.cpp new file mode 100644 index 0000000000..9f6a9ac0b1 --- /dev/null +++ b/tv/cec/aidl/default/fuzzer.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +using android::fuzzService; +using android::hardware::tv::cec::implementation::HdmiCecMock; +using ndk::SharedRefBase; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + auto hdmiCecAidl = SharedRefBase::make(); + + fuzzService(hdmiCecAidl->asBinder().get(), FuzzedDataProvider(data, size)); + + return 0; +} diff --git a/tv/cec/aidl/default/serviceMock.cpp b/tv/cec/aidl/default/serviceMock.cpp new file mode 100644 index 0000000000..ab86c3f642 --- /dev/null +++ b/tv/cec/aidl/default/serviceMock.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec-service-shim" + +#include +#include +#include +#include +#include +#include "HdmiCecMock.h" + +using android::hardware::tv::cec::implementation::HdmiCecMock; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + + std::shared_ptr hdmiCecAidl = ndk::SharedRefBase::make(); + const std::string instance = std::string() + HdmiCecMock::descriptor + "/default"; + binder_status_t status = + AServiceManager_addService(hdmiCecAidl->asBinder().get(), instance.c_str()); + CHECK_EQ(status, STATUS_OK); + + ABinderProcess_joinThreadPool(); + return 0; +} diff --git a/tv/cec/aidl/vts/functional/Android.bp b/tv/cec/aidl/vts/functional/Android.bp new file mode 100644 index 0000000000..37fbaf0cda --- /dev/null +++ b/tv/cec/aidl/vts/functional/Android.bp @@ -0,0 +1,38 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalTvCecAidlTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalTvCecAidlTargetTest.cpp"], + static_libs: [ + "android.hardware.tv.cec-V1-ndk", + "android.hardware.tv.hdmi-V1-ndk", + ], + shared_libs: [ + "libbinder_ndk", + ], + test_suites: [ + "general-tests", + "vts", + ], + disable_framework: true, +} diff --git a/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp b/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp new file mode 100644 index 0000000000..69c209fe2d --- /dev/null +++ b/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "HdmiCec_hal_test" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::aidl::android::hardware::tv::cec::BnHdmiCecCallback; +using ::aidl::android::hardware::tv::cec::CecDeviceType; +using ::aidl::android::hardware::tv::cec::CecLogicalAddress; +using ::aidl::android::hardware::tv::cec::CecMessage; +using ::aidl::android::hardware::tv::cec::IHdmiCec; +using ::aidl::android::hardware::tv::cec::IHdmiCecCallback; +using ::aidl::android::hardware::tv::cec::Result; +using ::aidl::android::hardware::tv::cec::SendMessageResult; +using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo; +using ::ndk::SpAIBinder; + +#define CEC_VERSION 0x05 +#define INCORRECT_VENDOR_ID 0x00 +#define TV_PHYSICAL_ADDRESS 0x0000 + +// The main test class for TV CEC HAL. +class HdmiCecTest : public ::testing::TestWithParam { + static void serviceDied(void* /* cookie */) { ALOGE("VtsHalTvCecAidlTargetTest died"); } + + public: + void SetUp() override { + hdmiCec = IHdmiCec::fromBinder( + SpAIBinder(AServiceManager_waitForService(GetParam().c_str()))); + ASSERT_NE(hdmiCec, nullptr); + ALOGI("%s: getService() for hdmiCec is %s", __func__, + hdmiCec->isRemote() ? "remote" : "local"); + + hdmiCecCallback = ::ndk::SharedRefBase::make(); + ASSERT_NE(hdmiCecCallback, nullptr); + hdmiCecDeathRecipient = + ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&serviceDied)); + ASSERT_EQ(AIBinder_linkToDeath(hdmiCec->asBinder().get(), hdmiCecDeathRecipient.get(), 0), + STATUS_OK); + } + + std::vector getDeviceTypes() { + std::vector deviceTypes; + FILE* p = popen("getprop ro.hdmi.device_type", "re"); + if (p) { + char* line = NULL; + size_t len = 0; + if (getline(&line, &len, p) > 0) { + std::istringstream stream(line); + std::string number{}; + while (std::getline(stream, number, ',')) { + deviceTypes.push_back(stoi(number)); + } + } + pclose(p); + } + return deviceTypes; + } + + bool hasDeviceType(CecDeviceType type) { + std::vector deviceTypes = getDeviceTypes(); + return std::find(deviceTypes.begin(), deviceTypes.end(), (int)type) != deviceTypes.end(); + } + + class CecCallback : public BnHdmiCecCallback { + public: + ::ndk::ScopedAStatus onCecMessage(const CecMessage& message __unused) { + return ::ndk::ScopedAStatus::ok(); + }; + }; + + std::shared_ptr hdmiCec; + std::shared_ptr hdmiCecCallback; + ::ndk::ScopedAIBinder_DeathRecipient hdmiCecDeathRecipient; +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiCecTest); +INSTANTIATE_TEST_SUITE_P(PerInstance, HdmiCecTest, + testing::ValuesIn(android::getAidlHalInstanceNames(IHdmiCec::descriptor)), + android::PrintInstanceNameToString); + +TEST_P(HdmiCecTest, ClearAddLogicalAddress) { + Result addLaResult; + ASSERT_TRUE(hdmiCec->clearLogicalAddress().isOk()); + ASSERT_TRUE(hdmiCec->addLogicalAddress(CecLogicalAddress::PLAYBACK_3, &addLaResult).isOk()); + EXPECT_EQ(addLaResult, Result::SUCCESS); +} + +TEST_P(HdmiCecTest, PhysicalAddress) { + int32_t addr; + ASSERT_TRUE(hdmiCec->getPhysicalAddress(&addr).isOk()); + if (!hasDeviceType(CecDeviceType::TV)) { + EXPECT_NE(addr, TV_PHYSICAL_ADDRESS); + } +} + +TEST_P(HdmiCecTest, SendMessage) { + CecMessage message; + message.initiator = CecLogicalAddress::PLAYBACK_1; + message.destination = CecLogicalAddress::BROADCAST; + message.body.resize(1); + message.body[0] = 131; + SendMessageResult result; + ASSERT_TRUE(hdmiCec->sendMessage(message, &result).isOk()); + EXPECT_EQ(result, SendMessageResult::SUCCESS); +} + +TEST_P(HdmiCecTest, CecVersion) { + int32_t version; + ASSERT_TRUE(hdmiCec->getCecVersion(&version).isOk()); + EXPECT_GE(version, CEC_VERSION); +} + +TEST_P(HdmiCecTest, SetCallback) { + ASSERT_TRUE(hdmiCec->setCallback(::ndk::SharedRefBase::make()).isOk()); +} + +TEST_P(HdmiCecTest, VendorId) { + int32_t vendorId; + ASSERT_TRUE(hdmiCec->getVendorId(&vendorId).isOk()); + EXPECT_NE(vendorId, INCORRECT_VENDOR_ID); +} + +TEST_P(HdmiCecTest, EnableWakeupByOtp) { + ASSERT_TRUE(hdmiCec->enableWakeupByOtp(false).isOk()); + // Restore option to its default value + ASSERT_TRUE(hdmiCec->enableWakeupByOtp(true).isOk()); +} + +TEST_P(HdmiCecTest, EnableCec) { + ASSERT_TRUE(hdmiCec->enableCec(false).isOk()); + // Restore option to its default value + ASSERT_TRUE(hdmiCec->enableCec(true).isOk()); +} + +TEST_P(HdmiCecTest, EnableSystemCecControl) { + ASSERT_TRUE(hdmiCec->enableSystemCecControl(true).isOk()); + // Restore option to its default value + ASSERT_TRUE(hdmiCec->enableSystemCecControl(false).isOk()); +} + +TEST_P(HdmiCecTest, SetLanguage) { + ASSERT_TRUE(hdmiCec->setLanguage("eng").isOk()); +} diff --git a/tv/hdmi/aidl/Android.bp b/tv/hdmi/aidl/Android.bp new file mode 100644 index 0000000000..d8c6e5f3d2 --- /dev/null +++ b/tv/hdmi/aidl/Android.bp @@ -0,0 +1,29 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.tv.hdmi", + vendor_available: true, + srcs: ["android/hardware/tv/hdmi/*.aidl"], + stability: "vintf", + backend: { + java: { + sdk_version: "module_current", + }, + }, +} diff --git a/tv/hdmi/aidl/OWNERS b/tv/hdmi/aidl/OWNERS new file mode 100644 index 0000000000..d9c678363b --- /dev/null +++ b/tv/hdmi/aidl/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 826094 +include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS \ No newline at end of file diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl new file mode 100644 index 0000000000..a5e3a2a4de --- /dev/null +++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.hdmi; +@VintfStability +parcelable HdmiPortInfo { + android.hardware.tv.hdmi.HdmiPortType type; + int portId; + boolean cecSupported; + boolean arcSupported; + int physicalAddress; +} diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl new file mode 100644 index 0000000000..af5f0f7b80 --- /dev/null +++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.hdmi; +@Backing(type="byte") @VintfStability +enum HdmiPortType { + INPUT = 0, + OUTPUT = 1, +} diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl new file mode 100644 index 0000000000..3fc7f4144a --- /dev/null +++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.hdmi; +@VintfStability +interface IHdmi { + android.hardware.tv.hdmi.HdmiPortInfo[] getPortInfo(); + boolean isConnected(in int portId); + void setCallback(in android.hardware.tv.hdmi.IHdmiCallback callback); +} diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl new file mode 100644 index 0000000000..05fe6230fe --- /dev/null +++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.hdmi; +@VintfStability +interface IHdmiCallback { + oneway void onHotplugEvent(in boolean connected, in int portId); +} diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl new file mode 100644 index 0000000000..1d6f27d1a7 --- /dev/null +++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.hdmi; + +import android.hardware.tv.hdmi.HdmiPortType; + +/** + * HDMI port descriptor + */ +@VintfStability +parcelable HdmiPortInfo { + HdmiPortType type; + int portId; // Should start from 1 which corresponds to HDMI "port 1". + boolean cecSupported; + boolean arcSupported; + // 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; +} diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl new file mode 100644 index 0000000000..59c0d42e61 --- /dev/null +++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.hdmi; + +/** + * HDMI port type. + */ +@VintfStability +@Backing(type="byte") +enum HdmiPortType { + INPUT = 0, + OUTPUT = 1, +} diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl new file mode 100644 index 0000000000..5536846cf8 --- /dev/null +++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.hdmi; + +import android.hardware.tv.hdmi.HdmiPortInfo; +import android.hardware.tv.hdmi.IHdmiCallback; + +/** + * HDMI HAL interface definition. + */ +@VintfStability +interface IHdmi { + /** + * Gets the hdmi port information of underlying hardware. + * + * @return The list of HDMI port information + */ + HdmiPortInfo[] getPortInfo(); + + /** + * Gets the connection status of the specified port. + * + * @param portId Port id to be inspected for the connection status. + * @return True if a device is connected, otherwise false. The HAL + * must watch for +5V power signal to determine the status. + */ + boolean isConnected(in int portId); + + /** + * Sets a callback that HDMI HAL must later use for internal HDMI events + * + * @param callback Callback object to pass hdmi events to the system. The + * previously registered callback must be replaced with this one. + * setCallback(null) should deregister the callback. + */ + void setCallback(in IHdmiCallback callback); +} diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl new file mode 100644 index 0000000000..51275b0034 --- /dev/null +++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.hdmi; + +/** + * Callbacks from the HDMI HAL implementation to notify the system of new events. + */ +@VintfStability +oneway interface IHdmiCallback { + /** + * The callback function that must be called by HAL implementation to notify + * the system of new hotplug event. + */ + void onHotplugEvent(in boolean connected, in int portId); +} diff --git a/tv/hdmi/aidl/default/Android.bp b/tv/hdmi/aidl/default/Android.bp new file mode 100644 index 0000000000..3e466a0a41 --- /dev/null +++ b/tv/hdmi/aidl/default/Android.bp @@ -0,0 +1,58 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.tv.hdmi-service", + vintf_fragments: ["android.hardware.tv.hdmi-service.xml"], + relative_install_path: "hw", + vendor: true, + cflags: [ + "-Wall", + "-Wextra", + ], + init_rc: ["android.hardware.tv.hdmi-service.rc"], + srcs: [ + "serviceMock.cpp", + "HdmiMock.cpp", + ], + shared_libs: [ + "libbinder_ndk", + "liblog", + "libbase", + "libutils", + "libhardware", + "libhidlbase", + "android.hardware.tv.hdmi-V1-ndk", + ], +} + +cc_fuzz { + name: "android.hardware.tv.hdmi-service_fuzzer", + defaults: ["service_fuzzer_defaults"], + static_libs: [ + "android.hardware.tv.hdmi-V1-ndk", + "liblog", + ], + srcs: [ + "fuzzer.cpp", + "HdmiMock.cpp", + ], + fuzz_config: { + componentid: 826094, + }, +} diff --git a/tv/hdmi/aidl/default/HdmiMock.cpp b/tv/hdmi/aidl/default/HdmiMock.cpp new file mode 100644 index 0000000000..0cf5118b6b --- /dev/null +++ b/tv/hdmi/aidl/default/HdmiMock.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.hdmi" +#include +#include +#include + +#include "HdmiMock.h" + +using ndk::ScopedAStatus; + +namespace android { +namespace hardware { +namespace tv { +namespace hdmi { +namespace implementation { + +void HdmiMock::serviceDied(void* cookie) { + ALOGE("HdmiMock died"); + auto hdmi = static_cast(cookie); + hdmi->mHdmiThreadRun = false; +} + +ScopedAStatus HdmiMock::getPortInfo(std::vector* _aidl_return) { + *_aidl_return = mPortInfos; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiMock::isConnected(int32_t portId, bool* _aidl_return) { + // Maintain port connection status and update on hotplug event + if (portId <= mTotalPorts && portId >= 1) { + *_aidl_return = mPortConnectionStatus[portId]; + } else { + *_aidl_return = false; + } + + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiMock::setCallback(const std::shared_ptr& callback) { + if (mCallback != nullptr) { + mCallback = nullptr; + } + + if (callback != nullptr) { + mCallback = callback; + AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */); + + mInputFile = open(HDMI_MSG_IN_FIFO, O_RDWR | O_CLOEXEC); + pthread_create(&mThreadId, NULL, __threadLoop, this); + pthread_setname_np(mThreadId, "hdmi_loop"); + } + return ScopedAStatus::ok(); +} + +void* HdmiMock::__threadLoop(void* user) { + HdmiMock* const self = static_cast(user); + self->threadLoop(); + return 0; +} + +int HdmiMock::readMessageFromFifo(unsigned char* buf, int msgCount) { + if (msgCount <= 0 || !buf) { + return 0; + } + + int ret = -1; + // Maybe blocked at driver + ret = read(mInputFile, buf, msgCount); + if (ret < 0) { + ALOGE("[halimp_aidl] read :%s failed, ret:%d\n", HDMI_MSG_IN_FIFO, ret); + return -1; + } + + return ret; +} + +void HdmiMock::printEventBuf(const char* msg_buf, int len) { + int i, size = 0; + const int bufSize = MESSAGE_BODY_MAX_LENGTH * 3; + // Use 2 characters for each byte in the message plus 1 space + char buf[bufSize] = {0}; + + // Messages longer than max length will be truncated. + for (i = 0; i < len && size < bufSize; i++) { + size += sprintf(buf + size, " %02x", msg_buf[i]); + } + ALOGD("[halimp_aidl] %s, msg:%.*s", __FUNCTION__, size, buf); +} + +void HdmiMock::handleHotplugMessage(unsigned char* msgBuf) { + bool connected = ((msgBuf[3]) & 0xf) > 0; + int32_t portId = static_cast(msgBuf[0] & 0xf); + + if (portId > static_cast(mPortInfos.size())) { + ALOGD("[halimp_aidl] ignore hot plug message, id %x does not exist", portId); + return; + } + + ALOGD("[halimp_aidl] hot plug port id %x, is connected %x", (msgBuf[0] & 0xf), + (msgBuf[3] & 0xf)); + mPortConnectionStatus[portId] = connected; + if (mPortInfos[portId].type == HdmiPortType::OUTPUT) { + mPhysicalAddress = (connected ? 0xffff : ((msgBuf[1] << 8) | (msgBuf[2]))); + mPortInfos[portId].physicalAddress = mPhysicalAddress; + ALOGD("[halimp_aidl] hot plug physical address %x", mPhysicalAddress); + } + + if (mCallback != nullptr) { + mCallback->onHotplugEvent(connected, portId); + } +} + +void HdmiMock::threadLoop() { + ALOGD("[halimp_aidl] threadLoop start."); + unsigned char msgBuf[MESSAGE_BODY_MAX_LENGTH]; + int r = -1; + + // Open the input pipe + while (mInputFile < 0) { + usleep(1000 * 1000); + mInputFile = open(HDMI_MSG_IN_FIFO, O_RDONLY | O_CLOEXEC); + } + ALOGD("[halimp_aidl] file open ok, fd = %d.", mInputFile); + + while (mHdmiThreadRun) { + memset(msgBuf, 0, sizeof(msgBuf)); + // Try to get a message from dev. + // echo -n -e '\x04\x83' >> /dev/cec + r = readMessageFromFifo(msgBuf, MESSAGE_BODY_MAX_LENGTH); + if (r <= 1) { + // Ignore received ping messages + continue; + } + + printEventBuf((const char*)msgBuf, r); + + if (((msgBuf[0] >> 4) & 0xf) == 0xf) { + handleHotplugMessage(msgBuf); + } + } + + ALOGD("[halimp_aidl] thread end."); +} + +HdmiMock::HdmiMock() { + ALOGE("[halimp_aidl] Opening a virtual HDMI HAL for testing and virtual machine."); + mCallback = nullptr; + mPortInfos.resize(mTotalPorts); + mPortConnectionStatus.resize(mTotalPorts); + mPortInfos[0] = {.type = HdmiPortType::OUTPUT, + .portId = static_cast(1), + .cecSupported = true, + .arcSupported = false, + .physicalAddress = mPhysicalAddress}; + mPortConnectionStatus[0] = false; + mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied)); +} + +} // namespace implementation +} // namespace hdmi +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/hdmi/aidl/default/HdmiMock.h b/tv/hdmi/aidl/default/HdmiMock.h new file mode 100644 index 0000000000..05795dd3aa --- /dev/null +++ b/tv/hdmi/aidl/default/HdmiMock.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace hdmi { +namespace implementation { + +using ::aidl::android::hardware::tv::hdmi::BnHdmi; +using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo; +using ::aidl::android::hardware::tv::hdmi::HdmiPortType; +using ::aidl::android::hardware::tv::hdmi::IHdmi; +using ::aidl::android::hardware::tv::hdmi::IHdmiCallback; + +#define HDMI_MSG_IN_FIFO "/dev/hdmi_in_pipe" +#define MESSAGE_BODY_MAX_LENGTH 4 + +struct HdmiMock : public BnHdmi { + HdmiMock(); + + ::ndk::ScopedAStatus getPortInfo(std::vector* _aidl_return) override; + ::ndk::ScopedAStatus isConnected(int32_t portId, bool* _aidl_return) override; + ::ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + + void printEventBuf(const char* msg_buf, int len); + + private: + static void* __threadLoop(void* data); + void threadLoop(); + int readMessageFromFifo(unsigned char* buf, int msgCount); + void handleHotplugMessage(unsigned char* msgBuf); + + private: + static void serviceDied(void* cookie); + std::shared_ptr mCallback; + + // Variables for the virtual HDMI hal impl + std::vector mPortInfos; + std::vector mPortConnectionStatus; + + // Port configuration + uint16_t mPhysicalAddress = 0xFFFF; + int mTotalPorts = 1; + + // Testing variables + // Input file descriptor + int mInputFile; + bool mHdmiThreadRun = true; + pthread_t mThreadId = 0; + + ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; +}; +} // namespace implementation +} // namespace hdmi +} // Namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc new file mode 100644 index 0000000000..c926221d12 --- /dev/null +++ b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc @@ -0,0 +1,5 @@ +service vendor.hdmi-default /vendor/bin/hw/android.hardware.tv.hdmi-service + interface aidl android.hardware.tv.hdmi.IHdmi/default + class hal + user system + group system diff --git a/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml new file mode 100644 index 0000000000..a03c1998ec --- /dev/null +++ b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml @@ -0,0 +1,10 @@ + + + android.hardware.tv.hdmi + 1 + + IHdmi + default + + + diff --git a/tv/hdmi/aidl/default/fuzzer.cpp b/tv/hdmi/aidl/default/fuzzer.cpp new file mode 100644 index 0000000000..06a2bc0f38 --- /dev/null +++ b/tv/hdmi/aidl/default/fuzzer.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +using android::fuzzService; +using android::hardware::tv::hdmi::implementation::HdmiMock; +using ndk::SharedRefBase; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + auto hdmiAidl = SharedRefBase::make(); + + fuzzService(hdmiAidl->asBinder().get(), FuzzedDataProvider(data, size)); + + return 0; +} diff --git a/tv/hdmi/aidl/default/serviceMock.cpp b/tv/hdmi/aidl/default/serviceMock.cpp new file mode 100644 index 0000000000..1d8bf51a0a --- /dev/null +++ b/tv/hdmi/aidl/default/serviceMock.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.hdmi-service-shim" + +#include +#include +#include +#include +#include +#include "HdmiMock.h" + +using android::hardware::tv::hdmi::implementation::HdmiMock; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + + std::shared_ptr hdmiAidl = ndk::SharedRefBase::make(); + const std::string instance = std::string() + HdmiMock::descriptor + "/default"; + binder_status_t status = + AServiceManager_addService(hdmiAidl->asBinder().get(), instance.c_str()); + CHECK_EQ(status, STATUS_OK); + + ABinderProcess_joinThreadPool(); + return 0; +} diff --git a/tv/hdmi/aidl/vts/functional/Android.bp b/tv/hdmi/aidl/vts/functional/Android.bp new file mode 100644 index 0000000000..f9af58d0bb --- /dev/null +++ b/tv/hdmi/aidl/vts/functional/Android.bp @@ -0,0 +1,37 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalTvHdmiAidlTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalTvHdmiAidlTargetTest.cpp"], + static_libs: [ + "android.hardware.tv.hdmi-V1-ndk", + ], + shared_libs: [ + "libbinder_ndk", + ], + test_suites: [ + "general-tests", + "vts", + ], + disable_framework: true, +} diff --git a/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp new file mode 100644 index 0000000000..78c2590a95 --- /dev/null +++ b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Hdmi_hal_test" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::aidl::android::hardware::tv::hdmi::BnHdmiCallback; +using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo; +using ::aidl::android::hardware::tv::hdmi::HdmiPortType; +using ::aidl::android::hardware::tv::hdmi::IHdmi; +using ::aidl::android::hardware::tv::hdmi::IHdmiCallback; +using ::ndk::SpAIBinder; + +#define INCORRECT_VENDOR_ID 0x00 +#define TV_PHYSICAL_ADDRESS 0x0000 + +// The main test class for TV HDMI HAL. +class HdmiTest : public ::testing::TestWithParam { + static void serviceDied(void* /* cookie */) { ALOGE("VtsHalTvCecAidlTargetTest died"); } + + public: + void SetUp() override { + hdmi = IHdmi::fromBinder(SpAIBinder(AServiceManager_waitForService(GetParam().c_str()))); + ASSERT_NE(hdmi, nullptr); + ALOGI("%s: getService() for hdmi is %s", __func__, hdmi->isRemote() ? "remote" : "local"); + + hdmiCallback = ::ndk::SharedRefBase::make(); + ASSERT_NE(hdmiCallback, nullptr); + hdmiDeathRecipient = + ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&serviceDied)); + ASSERT_EQ(AIBinder_linkToDeath(hdmi->asBinder().get(), hdmiDeathRecipient.get(), 0), + STATUS_OK); + } + + class HdmiCallback : public BnHdmiCallback { + public: + ::ndk::ScopedAStatus onHotplugEvent(bool connected __unused, int32_t portId __unused) { + return ::ndk::ScopedAStatus::ok(); + }; + }; + + std::shared_ptr hdmi; + std::shared_ptr hdmiCallback; + ::ndk::ScopedAIBinder_DeathRecipient hdmiDeathRecipient; +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiTest); +INSTANTIATE_TEST_SUITE_P(PerInstance, HdmiTest, + testing::ValuesIn(android::getAidlHalInstanceNames(IHdmi::descriptor)), + android::PrintInstanceNameToString); + +TEST_P(HdmiTest, SetCallback) { + ASSERT_TRUE(hdmi->setCallback(::ndk::SharedRefBase::make()).isOk()); +} + +TEST_P(HdmiTest, GetPortInfo) { + std::vector ports; + ASSERT_TRUE(hdmi->getPortInfo(&ports).isOk()); + + bool cecSupportedOnDevice = false; + 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__); + } + cecSupportedOnDevice = cecSupportedOnDevice | ports[i].cecSupported; + } + EXPECT_NE(cecSupportedOnDevice, false) << "At least one port should support CEC"; +} + +TEST_P(HdmiTest, IsConnected) { + std::vector ports; + ASSERT_TRUE(hdmi->getPortInfo(&ports).isOk()); + for (size_t i = 0; i < ports.size(); ++i) { + bool connected; + ASSERT_TRUE(hdmi->isConnected(ports[i].portId, &connected).isOk()); + } +}