summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2020-08-05 18:33:59 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-08-05 18:33:59 +0000
commitbdfcae86ab29c4facb7d074674320e02383b385f (patch)
tree3688b8f06dbf961901b7e55c4310f54d27008eaa
parent4900a6dfee56818938b875be0e3fb76199dcac4d (diff)
parenta87e239055a3b8a33122cf2ace4949c9b2f86c91 (diff)
downloadcts-bdfcae86ab29c4facb7d074674320e02383b385f.tar.gz
Merge "Update HDMI CEC CTS tests" into stage-aosp-rvc-ts-dev
-rw-r--r--hostsidetests/hdmicec/Android.bp2
-rw-r--r--hostsidetests/hdmicec/AndroidTest.xml2
-rw-r--r--hostsidetests/hdmicec/README.md28
-rw-r--r--hostsidetests/hdmicec/app/Android.bp9
-rw-r--r--hostsidetests/hdmicec/app/AndroidManifest.xml26
-rw-r--r--hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecAudioManager.java96
-rw-r--r--hostsidetests/hdmicec/app/src/com/android/server/hdmi/SadConfigurationReaderTest.java96
-rw-r--r--hostsidetests/hdmicec/cec_adapter.md221
-rw-r--r--hostsidetests/hdmicec/setup.pngbin0 -> 20095 bytes
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java178
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/CecOperand.java81
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java249
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java7
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/LogHelper.java99
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/LogicalAddress.java92
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredFeatureRule.java57
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredPropertyRule.java104
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecAudioReturnChannelControlTest.java134
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecInvalidMessagesTest.java335
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecLogicalAddressTest.java28
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecRemoteControlPassThroughTest.java150
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecSystemAudioModeTest.java496
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecDeviceTypeTest.java57
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java50
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecLogicalAddressTest.java28
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecOneTouchPlayTest.java57
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPhysicalAddressTest.java27
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java48
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java92
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java51
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecStartupTest.java113
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java70
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java71
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemStandbyTest.java61
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecVendorCommandsTest.java40
35 files changed, 2691 insertions, 564 deletions
diff --git a/hostsidetests/hdmicec/Android.bp b/hostsidetests/hdmicec/Android.bp
index 66d0e0a3de4..4268ff190cb 100644
--- a/hostsidetests/hdmicec/Android.bp
+++ b/hostsidetests/hdmicec/Android.bp
@@ -28,6 +28,6 @@ java_test_host {
"compatibility-host-util",
],
data: [
- ":HdmiCecKeyEventCaptureApp",
+ ":HdmiCecHelperApp",
],
}
diff --git a/hostsidetests/hdmicec/AndroidTest.xml b/hostsidetests/hdmicec/AndroidTest.xml
index f4f5281efeb..a0a4350a663 100644
--- a/hostsidetests/hdmicec/AndroidTest.xml
+++ b/hostsidetests/hdmicec/AndroidTest.xml
@@ -22,7 +22,7 @@
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="HdmiCecKeyEventCaptureApp.apk" />
+ <option name="test-file-name" value="HdmiCecHelperApp.apk" />
</target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsHdmiCecHostTestCases.jar" />
diff --git a/hostsidetests/hdmicec/README.md b/hostsidetests/hdmicec/README.md
new file mode 100644
index 00000000000..3d5b003b449
--- /dev/null
+++ b/hostsidetests/hdmicec/README.md
@@ -0,0 +1,28 @@
+# CEC CTS testing for Android TV devices
+
+NOTE: CTS has two meanings here. HDMI defines a set of tests in **Compliance
+Test Specification** in HDMI 1.4b *HDMI Compliance Test Specification 1.4b and
+**Android Compatibility Test Suite**.
+
+Android Compatibility Test Suite include specific tests from HDMI Compliance
+Test Specification and other Android specific tests.
+
+## Setup
+
+### Playback devices (aka Set Top Boxes)
+
+Running these CTS tests requires a specific HDMI layout with a CEC adapter.
+
+* Android TV playback device
+* CEC adapter see [External CEC Adapter instructions](cec_adapter.md)
+* HDMI Display (aka a TV)
+
+![drawing](setup.png)
+
+### Automation
+
+Given the setup described above you can run all of these tests with the command
+
+```
+atest CtsHdmiCecHostTestCases
+```
diff --git a/hostsidetests/hdmicec/app/Android.bp b/hostsidetests/hdmicec/app/Android.bp
index 910aa306f0e..ed41e1a6b64 100644
--- a/hostsidetests/hdmicec/app/Android.bp
+++ b/hostsidetests/hdmicec/app/Android.bp
@@ -13,8 +13,13 @@
// limitations under the License.
android_test_helper_app {
- name: "HdmiCecKeyEventCaptureApp",
+ name: "HdmiCecHelperApp",
defaults: ["cts_defaults"],
srcs: ["src/**/*.java"],
- sdk_version: "current",
+ static_libs: [
+ "services.core",
+ "guava",
+ "androidx.test.runner",
+ ],
+ min_sdk_version: "28",
}
diff --git a/hostsidetests/hdmicec/app/AndroidManifest.xml b/hostsidetests/hdmicec/app/AndroidManifest.xml
index ce9fff74743..603445e6ae3 100644
--- a/hostsidetests/hdmicec/app/AndroidManifest.xml
+++ b/hostsidetests/hdmicec/app/AndroidManifest.xml
@@ -16,16 +16,30 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.hdmicec.app">
+ package="android.hdmicec.app">
<uses-feature android:name="android.software.leanback"
- android:required="false" />
- <application >
- <activity android:name=".HdmiCecKeyEventCapture" >
+ android:required="false"/>
+ <application>
+ <activity android:name=".HdmiCecKeyEventCapture"
+ android:exported="true">
<intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".HdmiCecAudioManager"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.hdmicec.app.MUTE"/>
+ <action android:name="android.hdmicec.app.UNMUTE"/>
+ <action android:name="android.hdmicec.app.REPORT_VOLUME"/>
+ <action android:name="android.hdmicec.app.SET_VOLUME"/>
+ <action android:name="android.hdmicec.app.GET_SUPPORTED_SAD_FORMATS"/>
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
</application>
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
</manifest>
diff --git a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecAudioManager.java b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecAudioManager.java
new file mode 100644
index 00000000000..f04490fc68a
--- /dev/null
+++ b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecAudioManager.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.app;
+
+import android.app.Activity;
+import android.content.Context;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.server.hdmi.SadConfigurationReaderTest;
+
+import org.junit.runner.JUnitCore;
+
+/**
+ * A simple app that can be used to mute, unmute, set volume or get the volume status of a device.
+ * The actions supported are:
+ *
+ * 1. android.hdmicec.app.MUTE: Mutes the STREAM_MUSIC of the device,
+ * irrespective of the previous state.
+ * Usage: START_COMMAND -a android.hdmicec.app.MUTE
+ * 2. android.hdmicec.app.UNMUTE: Unmutes the STREAM_MUSIC of the device,
+ * irrespective of the previous state.
+ * Usage: START_COMMAND -a android.hdmicec.app.UNMUTE
+ * 3. android.hdmicec.app.REPORT_VOLUME: Reports if the STREAM_MUSIC of the device is muted and
+ * if not muted, the current volume level in percent.
+ * Usage: START_COMMAND -a android.hdmicec.app.REPORT_VOLUME
+ * 4. android.hdmicec.app.SET_VOLUME: Sets the volume of STREAM_MUSIC to a particular level.
+ * Has to be used with --ei "volumePercent" x.
+ * Usage: START_COMMAND -a android.hdmicec.app.SET_VOLUME --ei "volumePercent" x
+ *
+ * where START_COMMAND is
+ * adb shell am start -n "android.hdmicec.app/android.hdmicec.app.HdmiCecAudioManager"
+ */
+public class HdmiCecAudioManager extends Activity {
+
+ private static final String TAG = HdmiCecAudioManager.class.getSimpleName();
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+
+ switch(getIntent().getAction()) {
+ case "android.hdmicec.app.MUTE":
+ audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
+ AudioManager.ADJUST_MUTE, 0);
+ break;
+ case "android.hdmicec.app.UNMUTE":
+ audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
+ AudioManager.ADJUST_UNMUTE, 0);
+ break;
+ case "android.hdmicec.app.REPORT_VOLUME":
+ if (audioManager.isStreamMute(AudioManager.STREAM_MUSIC)) {
+ Log.i(TAG, "Device muted.");
+ } else {
+ int minVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
+ int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ int volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+ int percentVolume = 100 * volume / (maxVolume - minVolume);
+ Log.i(TAG, "Volume at " + percentVolume + "%");
+ }
+ break;
+ case "android.hdmicec.app.SET_VOLUME":
+ int percentVolume = getIntent().getIntExtra("volumePercent", 50);
+ int minVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
+ int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ int volume = minVolume + ((maxVolume - minVolume) * percentVolume / 100);
+ audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+ Log.i(TAG, "Set volume to " + volume + " (" + percentVolume + "%)");
+ break;
+ case "android.hdmicec.app.GET_SUPPORTED_SAD_FORMATS":
+ JUnitCore junit = new JUnitCore();
+ junit.run(SadConfigurationReaderTest.class);
+ break;
+ default:
+ Log.w(TAG, "Unknown intent!");
+ }
+ finishAndRemoveTask();
+ }
+}
+
diff --git a/hostsidetests/hdmicec/app/src/com/android/server/hdmi/SadConfigurationReaderTest.java b/hostsidetests/hdmicec/app/src/com/android/server/hdmi/SadConfigurationReaderTest.java
new file mode 100644
index 00000000000..48665acfeac
--- /dev/null
+++ b/hostsidetests/hdmicec/app/src/com/android/server/hdmi/SadConfigurationReaderTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 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 com.android.server.hdmi;
+
+import android.util.Log;
+
+import com.android.server.hdmi.HdmiUtils.CodecSad;
+import com.android.server.hdmi.HdmiUtils.DeviceConfig;
+import com.google.common.hash.HashCode;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+/**
+ * Reads short audio descriptors from a configuration file and outputs to a log
+ * for use by host side tests.
+ */
+public class SadConfigurationReaderTest {
+
+ private static final String TAG = "SadConfigurationReaderTest";
+
+ // Variable should be copy of SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH in
+ // frameworks/base/services/core/java/com/android/server/hdmi/
+ // HdmiCecLocalDeviceAudioSystem.java
+ private final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml";
+
+ @Test
+ public void parseSadConfigXML() {
+ List<DeviceConfig> deviceConfigs = null;
+ File file = new File(SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH);
+ if (file.exists()) {
+ try {
+ InputStream in = new FileInputStream(file);
+ deviceConfigs = HdmiUtils.ShortAudioDescriptorXmlParser.parse(in);
+ in.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Error reading file: " + file.getAbsolutePath(), e);
+ } catch (XmlPullParserException e) {
+ Log.e(TAG, "Unable to parse file: " + file.getAbsolutePath(), e);
+ }
+ } else {
+ Log.e(TAG, "No config file present at " + file.getAbsolutePath());
+ return;
+ }
+ DeviceConfig deviceConfigToUse = null;
+ if (deviceConfigs != null && deviceConfigs.size() > 0) {
+ for (DeviceConfig deviceConfig : deviceConfigs) {
+ if (deviceConfig.name.equals("VX_AUDIO_DEVICE_IN_HDMI_ARC")) {
+ deviceConfigToUse = deviceConfig;
+ break;
+ }
+ }
+ if (deviceConfigToUse == null) {
+ Log.w(TAG, "sadConfig.xml does not have required device info for "
+ + "VX_AUDIO_DEVICE_IN_HDMI_ARC");
+ return;
+ }
+ List<Integer> audioCodecFormats = new ArrayList<>();
+ List<String> shortAudioDescriptors = new ArrayList<>();
+ for (CodecSad codecSad : deviceConfigToUse.supportedCodecs) {
+ audioCodecFormats.add(codecSad.audioCodec);
+ shortAudioDescriptors.add(HashCode.fromBytes(codecSad.sad).toString());
+ }
+ String audioCodecFormatsString = audioCodecFormats.toString();
+ String shortAudioDescriptorsString = shortAudioDescriptors.toString();
+ Log.i(TAG, "Supported Audio Formats");
+ Log.i(TAG, audioCodecFormatsString.substring(1, audioCodecFormatsString.length() - 1));
+ Log.i(TAG, shortAudioDescriptorsString
+ .substring(1, shortAudioDescriptorsString.length() - 1));
+ }
+ }
+}
diff --git a/hostsidetests/hdmicec/cec_adapter.md b/hostsidetests/hdmicec/cec_adapter.md
new file mode 100644
index 00000000000..3a325d7e325
--- /dev/null
+++ b/hostsidetests/hdmicec/cec_adapter.md
@@ -0,0 +1,221 @@
+# External CEC adapter
+
+## USB - CEC Adapter from Pulse-Eight
+
+![Picture of USB - CEC Adapter](https://www.pulse-eight.com/generated-assets/products/0000237_555.jpeg)
+
+## Get the hardware
+
+* [Order from Pulse-Eight](https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter#)
+* [Pulse-Eight USB CEC adapter on Amazon](https://www.amazon.com/s/ref=nb_sb_ss_i_1_22?url=search-alias%3Daps&field-keywords=pulse+eight+usb+cec+adapter&sprefix=usb+cec+adapter+pulse+%2Caps%2C218&crid=UK4LY390M5H2)
+
+## Get the software {#software}
+
+1. Connect "TV" port on the adapter to your TV
+2. Connect USB mini port to you computer
+3. Install the cec-client
+
+ * Linux
+
+ ```shell
+ sudo apt-get install cec-utils
+ ```
+
+ * mac (using [MacPorts](https://guide.macports.org/#installing))
+
+ ```shell
+ sudo /opt/local/bin/port install libcec
+ ```
+
+4. run the client
+
+ ```shell
+ $ cec-client
+ No device type given. Using 'recording device'
+ CEC Parser created - libCEC version 4.0.2
+ no serial port given. trying autodetect:
+ path: /dev/cu.usbmodemv1
+ com port: /dev/cu.usbmodemv1
+
+ opening a connection to the CEC adapter...
+ DEBUG: [ 1] Broadcast (F): osd name set to 'Broadcast'
+ DEBUG: [ 3] connection opened, clearing any previous input and waiting for active transmissions to end before starting
+ DEBUG: [ 10] communication thread started
+ DEBUG: [ 70] turning controlled mode on
+ NOTICE: [ 255] connection opened
+ DEBUG: [ 255] processor thread started
+ DEBUG: [ 255] << Broadcast (F) -> TV (0): POLL
+ TRAFFIC: [ 255] << f0
+ DEBUG: [ 255] setting the line timeout to 3
+ DEBUG: [ 403] >> POLL sent
+ DEBUG: [ 403] TV (0): device status changed into 'present'
+ ```
+
+## Add timestamps
+
+Use the `ts` command to add timestamps.
+
+```shell
+$ cec-client | ts
+Nov 18 16:15:46 No device type given. Using 'recording device'
+Nov 18 16:15:46 CEC Parser created - libCEC version 4.0.4
+Nov 18 16:15:46 no serial port given. trying autodetect:
+Nov 18 16:15:46 path: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-9
+Nov 18 16:15:46 com port: /dev/ttyACM0
+Nov 18 16:15:46
+Nov 18 16:15:46 opening a connection to the CEC adapter...
+Nov 18 16:15:46 DEBUG: [ 386] Broadcast (F): osd name set to 'Broadcast'
+```
+
+### ts is part of the moreutils package
+
+```shell
+sudo apt-get install moreutils
+```
+
+## cheat sheets
+
+* Show all connected devices
+
+ ```shell
+ $ echo scan | cec-client -s -d 1
+
+ ```
+
+## Available Commands
+
+[tx] \{bytes\}
+: transfer bytes over the CEC line.
+
+[txn] \{bytes\}
+: transfer bytes but don't wait for transmission ACK.
+
+[on] \{address\}
+: power on the device with the given logical address.
+
+[standby] \{address\}
+: put the device with the given address in standby mode.
+
+[la] \{logical address\}
+: change the logical address of the CEC adapter.
+
+[p] \{device\} \{port\}
+: change the HDMI port number of the CEC adapter.
+
+[pa] \{physical address\}
+: change the physical address of the CEC adapter.
+
+[as]
+: make the CEC adapter the active source.
+
+[is]
+: mark the CEC adapter as inactive source.
+
+[osd] \{addr\} \{string\}
+: set OSD message on the specified device.
+
+[ver] \{addr\}
+: get the CEC version of the specified device.
+
+[ven] \{addr\}
+: get the vendor ID of the specified device.
+
+[lang] \{addr\}
+: get the menu language of the specified device.
+
+[pow] \{addr\}
+: get the power status of the specified device.
+
+[name] \{addr\}
+: get the OSD name of the specified device.
+
+[poll] \{addr\}
+: poll the specified device.
+
+[lad]
+: lists active devices on the bus
+
+[ad] \{addr\}
+: checks whether the specified device is active.
+
+[at] \{type\}
+: checks whether the specified device type is active.
+
+[sp] \{addr\}
+: makes the specified physical address active.
+
+[spl] \{addr\}
+: makes the specified logical address active.
+
+[volup]
+: send a volume up command to the amp if present
+
+[voldown]
+: send a volume down command to the amp if present
+
+[mute]
+: send a mute/unmute command to the amp if present
+
+[self]
+: show the list of addresses controlled by libCEC
+
+[scan]
+: scan the CEC bus and display device info
+
+## Sending Remote Control Events
+
+You can send CEC remote events using the `tx` command above. The format is as
+follows:
+
+```
+tx <source id><destination id>:<command id>:<param value>
+```
+
+where all of the above parameters should be filled in with a single HEX digit
+(except `<command id>`, which requires 2 digits). Here, we want to send commands
+to the Android TV, so we will place its ID in `<destination id>`. The scan
+command above will give you the IDs for each device that the CEC adapter is
+aware of.
+
+In the examples below the DUT is a CEC player device with a logical address of
+4. Here are some useful commands to execute remote actions:
+
+* Press home
+
+ ```
+ tx 04:44:09
+ ```
+
+* Press select
+
+ ```
+ tx 04:44:00
+ ```
+
+* Press d-pad up
+
+ ```
+ tx 04:44:01
+ ```
+
+* Press d-pad down
+
+ ```
+ tx 04:44:02
+ ```
+
+* Press d-pad left
+
+ ```
+ tx 04:44:03
+ ```
+
+* Press d-pad right
+
+ ```
+ tx 04:44:04
+ ```
+
+You can check out [https://www.cec-o-matic.com/](https]://www.cec-o-matic.com/)
+for more info on formatting your request and a full list of commands and their
+respective parameters.
diff --git a/hostsidetests/hdmicec/setup.png b/hostsidetests/hdmicec/setup.png
new file mode 100644
index 00000000000..e89417e46f9
--- /dev/null
+++ b/hostsidetests/hdmicec/setup.png
Binary files differ
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java
index 8d4ece13ef0..bce34e1d461 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecMessage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -16,56 +16,36 @@
package android.hdmicec.cts;
-import java.util.HashMap;
-import java.util.Map;
-
-public enum CecMessage {
- FEATURE_ABORT(0x00),
- TEXT_VIEW_ON(0x0d),
- SET_MENU_LANGUAGE(0x32),
- STANDBY(0x36),
- USER_CONTROL_PRESSED(0x44),
- USER_CONTROL_RELEASED(0x45),
- GIVE_OSD_NAME(0x46),
- SET_OSD_NAME(0x47),
- SYSTEM_AUDIO_MODE_REQUEST(0x70),
- SET_SYSTEM_AUDIO_MODE(0x72),
- GIVE_SYSTEM_AUDIO_MODE_STATUS(0x7d),
- ACTIVE_SOURCE(0x82),
- GIVE_PHYSICAL_ADDRESS(0x83),
- REPORT_PHYSICAL_ADDRESS(0x84),
- REQUEST_ACTIVE_SOURCE(0x85),
- SET_STREAM_PATH(0x86),
- DEVICE_VENDOR_ID(0x87),
- GIVE_DEVICE_VENDOR_ID(0x8c),
- GIVE_POWER_STATUS(0x8f),
- REPORT_POWER_STATUS(0x90),
- GET_MENU_LANGUAGE(0x91),
- INACTIVE_SOURCE(0x9d),
- CEC_VERSION(0x9e),
- GET_CEC_VERSION(0x9f),
- ABORT(0xff);
-
- private final int messageId;
- private static Map messageMap = new HashMap<>();
-
- static {
- for (CecMessage message : CecMessage.values()) {
- messageMap.put(message.messageId, message);
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CecMessage {
+
+ private static final int HEXADECIMAL_RADIX = 16;
+
+ /** Gets the hexadecimal ASCII character values of a string. */
+ public static String getHexAsciiString(String string) {
+ String asciiString = "";
+ byte[] ascii = string.trim().getBytes();
+
+ for (byte b : ascii) {
+ asciiString.concat(Integer.toHexString(b));
}
- }
- public static CecMessage getMessage(int messageId) {
- return (CecMessage) messageMap.get(messageId);
+ return asciiString;
}
- @Override
- public String toString() {
- return String.format("%02x", messageId);
- }
+ public static String formatParams(String rawParams) {
+ StringBuilder params = new StringBuilder("");
+ int position = 0;
+ int endPosition = 2;
- private CecMessage(int messageId) {
- this.messageId = messageId;
+ do {
+ params.append(":" + rawParams.substring(position, endPosition));
+ position = endPosition;
+ endPosition += 2;
+ } while (endPosition <= rawParams.length());
+ return params.toString();
}
public static String formatParams(long rawParam) {
@@ -78,4 +58,110 @@ public enum CecMessage {
return params.toString();
}
+
+ /**
+ * Formats the rawParam into CEC message parameters. The parameters will be at least
+ * minimumNibbles long.
+ */
+ public static String formatParams(long rawParam, int minimumNibbles) {
+ StringBuilder params = new StringBuilder("");
+
+ do {
+ params.insert(0, ":" + String.format("%02x", rawParam % 256));
+ rawParam >>= 8;
+ minimumNibbles -= 2;
+ } while (rawParam > 0 || minimumNibbles > 0);
+
+ return params.toString();
+ }
+
+ public static int hexStringToInt(String message) {
+ return Integer.parseInt(message, HEXADECIMAL_RADIX);
+ }
+
+ public static String getAsciiString(String message) {
+ String params = getNibbles(message).substring(4);
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = 2; i <= params.length(); i += 2) {
+ builder.append((char) hexStringToInt(params.substring(i - 2, i)));
+ }
+
+ return builder.toString();
+ }
+
+ public static String getParamsAsString(String message) {
+ return getNibbles(message).substring(4);
+ }
+
+ /** Gets the params from a CEC message. */
+ public static int getParams(String message) {
+ return hexStringToInt(getNibbles(message).substring(4));
+ }
+
+ /** Gets the first 'numNibbles' number of param nibbles from a CEC message. */
+ public static int getParams(String message, int numNibbles) {
+ int paramStart = 4;
+ int end = numNibbles + paramStart;
+ return hexStringToInt(getNibbles(message).substring(paramStart, end));
+ }
+
+ /**
+ * From the params of a CEC message, gets the nibbles from position start to position end.
+ * The start and end are relative to the beginning of the params. For example, in the following
+ * message - 4F:82:10:00:04, getParamsFromMessage(message, 0, 4) will return 0x1000 and
+ * getParamsFromMessage(message, 4, 6) will return 0x04.
+ */
+ public static int getParams(String message, int start, int end) {
+ return hexStringToInt(getNibbles(message).substring(4).substring(start, end));
+ }
+
+ /**
+ * Gets the source logical address from a CEC message.
+ */
+ public static LogicalAddress getSource(String message) {
+ String param = getNibbles(message).substring(0, 1);
+ return LogicalAddress.getLogicalAddress(hexStringToInt(param));
+ }
+
+ /** Gets the destination logical address from a CEC message. */
+ public static LogicalAddress getDestination(String message) {
+ String param = getNibbles(message).substring(1, 2);
+ return LogicalAddress.getLogicalAddress(hexStringToInt(param));
+ }
+
+ /** Gets the operand from a CEC message. */
+ public static CecOperand getOperand(String message) {
+ String param = getNibbles(message).substring(2, 4);
+ return CecOperand.getOperand(hexStringToInt(param));
+ }
+
+ /**
+ * Converts ascii characters to hexadecimal numbers that can be appended to a CEC message as
+ * params. For example, "spa" will be converted to ":73:70:61"
+ */
+ public static String convertStringToHexParams(String rawParams) {
+ StringBuilder params = new StringBuilder("");
+ for (int i = 0; i < rawParams.length(); i++) {
+ params.append(String.format(":%02x", (int) rawParams.charAt(i)));
+ }
+ return params.toString();
+ }
+
+ private static String getNibbles(String message) {
+ final String tag1 = "group1";
+ final String tag2 = "group2";
+ String paramsPattern = "(?:.*[>>|<<].*?)" +
+ "(?<" + tag1 + ">[\\p{XDigit}{2}:]+)" +
+ "(?<" + tag2 + ">\\p{XDigit}{2})" +
+ "(?:.*?)";
+ String nibbles = "";
+
+ Pattern p = Pattern.compile(paramsPattern);
+ Matcher m = p.matcher(message);
+ if (m.matches()) {
+ nibbles = m.group(tag1).replace(":", "") + m.group(tag2);
+ }
+ return nibbles;
+ }
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/CecOperand.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecOperand.java
new file mode 100644
index 00000000000..5aa547ee4a1
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/CecOperand.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.cts;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum CecOperand {
+ FEATURE_ABORT(0x00),
+ TEXT_VIEW_ON(0x0d),
+ SET_MENU_LANGUAGE(0x32),
+ STANDBY(0x36),
+ USER_CONTROL_PRESSED(0x44),
+ USER_CONTROL_RELEASED(0x45),
+ GIVE_OSD_NAME(0x46),
+ SET_OSD_NAME(0x47),
+ 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),
+ 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),
+ GIVE_DEVICE_VENDOR_ID(0x8c),
+ GIVE_POWER_STATUS(0x8f),
+ REPORT_POWER_STATUS(0x90),
+ GET_MENU_LANGUAGE(0x91),
+ INACTIVE_SOURCE(0x9d),
+ CEC_VERSION(0x9e),
+ GET_CEC_VERSION(0x9f),
+ REPORT_SHORT_AUDIO_DESCRIPTOR(0xa3),
+ REQUEST_SHORT_AUDIO_DESCRIPTOR(0xa4),
+ INITIATE_ARC(0xc0),
+ ARC_INITIATED(0xc1),
+ REQUEST_ARC_INITIATION(0xc3),
+ REQUEST_ARC_TERMINATION(0xc4),
+ TERMINATE_ARC(0xc5),
+ ABORT(0xff);
+
+ private final int operandCode;
+ private static Map operandMap = new HashMap<>();
+
+ static {
+ for (CecOperand operand : CecOperand.values()) {
+ operandMap.put(operand.operandCode, operand);
+ }
+ }
+
+ public static CecOperand getOperand(int messageId) {
+ return (CecOperand) operandMap.get(messageId);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%02x", operandCode);
+ }
+
+ private CecOperand(int operandCode) {
+ this.operandCode = operandCode;
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
index f9b1899cb11..51da28007ea 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
@@ -16,10 +16,6 @@
package android.hdmicec.cts;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assume.assumeTrue;
-
-import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.RunUtil;
@@ -32,10 +28,8 @@ import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.junit.Rule;
import org.junit.rules.ExternalResource;
/** Class that helps communicate with the cec-client */
@@ -44,8 +38,6 @@ public final class HdmiCecClientWrapper extends ExternalResource {
private static final String CEC_CONSOLE_READY = "waiting for input";
private static final int MILLISECONDS_TO_READY = 10000;
private static final int DEFAULT_TIMEOUT = 20000;
- private static final String HDMI_CEC_FEATURE = "feature:android.hardware.hdmi.cec";
- private static final int HEXADECIMAL_RADIX = 16;
private static final int BUFFER_SIZE = 1024;
private Process mCecClient;
@@ -53,29 +45,16 @@ public final class HdmiCecClientWrapper extends ExternalResource {
private BufferedReader mInputConsole;
private boolean mCecClientInitialised = false;
- private CecDevice targetDevice;
- private BaseHostJUnit4Test testObject;
+ private LogicalAddress targetDevice;
private String clientParams[];
- public HdmiCecClientWrapper(CecDevice targetDevice, BaseHostJUnit4Test testObject,
- String ...clientParams) {
+ public HdmiCecClientWrapper(LogicalAddress targetDevice, String ...clientParams) {
this.targetDevice = targetDevice;
- this.testObject = testObject;
this.clientParams = clientParams;
}
@Override
protected void before() throws Throwable {
- ITestDevice testDevice;
- testDevice = testObject.getDevice();
- assertNotNull("Device not set", testDevice);
-
- assumeTrue(isHdmiCecFeatureSupported(testDevice));
-
- String deviceTypeCsv = testDevice.executeShellCommand("getprop ro.hdmi.device_type").trim();
- List<String> deviceType = Arrays.asList(deviceTypeCsv.replaceAll("\\s+", "").split(","));
- assumeTrue(deviceType.contains(CecDevice.getDeviceType(targetDevice)));
-
this.init();
};
@@ -84,24 +63,18 @@ public final class HdmiCecClientWrapper extends ExternalResource {
this.killCecProcess();
};
- /**
- * Checks if the HDMI CEC feature is running on the device. Call this function before running
- * any HDMI CEC tests.
- * This could throw a DeviceNotAvailableException.
- */
- private static boolean isHdmiCecFeatureSupported(ITestDevice device) throws Exception {
- return device.hasFeature(HDMI_CEC_FEATURE);
- }
-
/** Initialise the client */
private void init() throws Exception {
- boolean gotExpectedOut = false;
List<String> commands = new ArrayList();
- int seconds = 0;
commands.add("cec-client");
+ /* "-p 2" starts the client as if it is connected to HDMI port 2, taking the physical
+ * address 2.0.0.0 */
commands.add("-p");
commands.add("2");
+ /* "-t x" starts the client as a TV device */
+ commands.add("-t");
+ commands.add("x");
commands.addAll(Arrays.asList(clientParams));
mCecClient = RunUtil.getDefault().runCmdInBackground(commands);
@@ -133,15 +106,15 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* Sends a CEC message with source marked as broadcast to the device passed in the constructor
* through the output console of the cec-communication channel.
*/
- public void sendCecMessage(CecMessage message) throws Exception {
- sendCecMessage(CecDevice.BROADCAST, targetDevice, message, "");
+ public void sendCecMessage(CecOperand message) throws Exception {
+ sendCecMessage(LogicalAddress.BROADCAST, targetDevice, message, "");
}
/**
* Sends a CEC message from source device to the device passed in the constructor through the
* output console of the cec-communication channel.
*/
- public void sendCecMessage(CecDevice source, CecMessage message) throws Exception {
+ public void sendCecMessage(LogicalAddress source, CecOperand message) throws Exception {
sendCecMessage(source, targetDevice, message, "");
}
@@ -149,8 +122,8 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* Sends a CEC message from source device to a destination device through the output console of
* the cec-communication channel.
*/
- public void sendCecMessage(CecDevice source, CecDevice destination,
- CecMessage message) throws Exception {
+ public void sendCecMessage(LogicalAddress source, LogicalAddress destination,
+ CecOperand message) throws Exception {
sendCecMessage(source, destination, message, "");
}
@@ -158,10 +131,11 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* Sends a CEC message from source device to a destination device through the output console of
* the cec-communication channel with the appended params.
*/
- public void sendCecMessage(CecDevice source, CecDevice destination,
- CecMessage message, String params) throws Exception {
+ public void sendCecMessage(LogicalAddress source, LogicalAddress destination,
+ CecOperand message, String params) throws Exception {
checkCecClient();
mOutputConsole.write("tx " + source + destination + ":" + message + params);
+ mOutputConsole.newLine();
mOutputConsole.flush();
}
@@ -169,13 +143,13 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* Sends a <USER_CONTROL_PRESSED> and <USER_CONTROL_RELEASED> from source to destination
* through the output console of the cec-communication channel with the mentioned keycode.
*/
- public void sendUserControlPressAndRelease(CecDevice source, CecDevice destination,
+ public void sendUserControlPressAndRelease(LogicalAddress source, LogicalAddress destination,
int keycode, boolean holdKey) throws Exception {
sendUserControlPress(source, destination, keycode, holdKey);
/* Sleep less than 200ms between press and release */
TimeUnit.MILLISECONDS.sleep(100);
mOutputConsole.write("tx " + source + destination + ":" +
- CecMessage.USER_CONTROL_RELEASED);
+ CecOperand.USER_CONTROL_RELEASED);
mOutputConsole.flush();
}
@@ -184,11 +158,11 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* cec-communication channel with the mentioned keycode. If holdKey is true, the method will
* send multiple <UCP> messages to simulate a long press. No <UCR> will be sent.
*/
- public void sendUserControlPress(CecDevice source, CecDevice destination,
+ public void sendUserControlPress(LogicalAddress source, LogicalAddress destination,
int keycode, boolean holdKey) throws Exception {
String key = String.format("%02x", keycode);
String command = "tx " + source + destination + ":" +
- CecMessage.USER_CONTROL_PRESSED + ":" + key;
+ CecOperand.USER_CONTROL_PRESSED + ":" + key;
if (holdKey) {
/* Repeat once between 200ms and 450ms for at least 5 seconds. Since message will be
@@ -212,7 +186,8 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* of the cec-communication channel immediately followed by <UCP> [secondKeycode]. No <UCR>
* message is sent.
*/
- public void sendUserControlInterruptedPressAndHold(CecDevice source, CecDevice destination,
+ public void sendUserControlInterruptedPressAndHold(
+ LogicalAddress source, LogicalAddress destination,
int firstKeycode, int secondKeycode, boolean holdKey) throws Exception {
sendUserControlPress(source, destination, firstKeycode, holdKey);
/* Sleep less than 200ms between press and release */
@@ -253,13 +228,40 @@ public final class HdmiCecClientWrapper extends ExternalResource {
return false;
}
+ /** Gets all the messages received from the given source device during a period of duration
+ * seconds.
+ */
+ public List<CecOperand> getAllMessages(LogicalAddress source, int duration) throws Exception {
+ List<CecOperand> receivedOperands = new ArrayList<>();
+ long startTime = System.currentTimeMillis();
+ long endTime = startTime;
+ Pattern pattern = Pattern.compile("(.*>>)(.*?)" +
+ "(" + source + "\\p{XDigit}):(.*)",
+ Pattern.CASE_INSENSITIVE);
+
+ while ((endTime - startTime <= duration)) {
+ if (mInputConsole.ready()) {
+ String line = mInputConsole.readLine();
+ if (pattern.matcher(line).matches()) {
+ CecOperand operand = CecMessage.getOperand(line);
+ if (!receivedOperands.contains(operand)) {
+ receivedOperands.add(operand);
+ }
+ }
+ }
+ endTime = System.currentTimeMillis();
+ }
+ return receivedOperands;
+ }
+
+
/**
* Looks for the CEC expectedMessage broadcast on the cec-client communication channel and
* returns the first line that contains that message within default timeout. If the CEC message
* is not found within the timeout, an exception is thrown.
*/
- public String checkExpectedOutput(CecMessage expectedMessage) throws Exception {
- return checkExpectedOutput(CecDevice.BROADCAST, expectedMessage, DEFAULT_TIMEOUT);
+ public String checkExpectedOutput(CecOperand expectedMessage) throws Exception {
+ return checkExpectedOutput(LogicalAddress.BROADCAST, expectedMessage, DEFAULT_TIMEOUT);
}
/**
@@ -267,8 +269,8 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* communication channel and returns the first line that contains that message within
* default timeout. If the CEC message is not found within the timeout, an exception is thrown.
*/
- public String checkExpectedOutput(CecDevice toDevice,
- CecMessage expectedMessage) throws Exception {
+ public String checkExpectedOutput(LogicalAddress toDevice,
+ CecOperand expectedMessage) throws Exception {
return checkExpectedOutput(toDevice, expectedMessage, DEFAULT_TIMEOUT);
}
@@ -277,9 +279,9 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* returns the first line that contains that message within timeoutMillis. If the CEC message
* is not found within the timeout, an exception is thrown.
*/
- public String checkExpectedOutput(CecMessage expectedMessage,
+ public String checkExpectedOutput(CecOperand expectedMessage,
long timeoutMillis) throws Exception {
- return checkExpectedOutput(CecDevice.BROADCAST, expectedMessage, timeoutMillis);
+ return checkExpectedOutput(LogicalAddress.BROADCAST, expectedMessage, timeoutMillis);
}
/**
@@ -287,7 +289,7 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* communication channel and returns the first line that contains that message within
* timeoutMillis. If the CEC message is not found within the timeout, an exception is thrown.
*/
- public String checkExpectedOutput(CecDevice toDevice, CecMessage expectedMessage,
+ public String checkExpectedOutput(LogicalAddress toDevice, CecOperand expectedMessage,
long timeoutMillis) throws Exception {
checkCecClient();
long startTime = System.currentTimeMillis();
@@ -316,8 +318,8 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* within the default timeout. If the CEC message is not found within the timeout, function
* returns without error.
*/
- public void checkOutputDoesNotContainMessage(CecDevice toDevice,
- CecMessage incorrectMessage) throws Exception {
+ public void checkOutputDoesNotContainMessage(LogicalAddress toDevice,
+ CecOperand incorrectMessage) throws Exception {
checkOutputDoesNotContainMessage(toDevice, incorrectMessage, DEFAULT_TIMEOUT);
}
@@ -327,7 +329,7 @@ public final class HdmiCecClientWrapper extends ExternalResource {
* within timeoutMillis. If the CEC message is not found within the timeout, function returns
* without error.
*/
- public void checkOutputDoesNotContainMessage(CecDevice toDevice, CecMessage incorrectMessage,
+ public void checkOutputDoesNotContainMessage(LogicalAddress toDevice, CecOperand incorrectMessage,
long timeoutMillis) throws Exception {
checkCecClient();
@@ -344,146 +346,13 @@ public final class HdmiCecClientWrapper extends ExternalResource {
if (pattern.matcher(line).matches()) {
CLog.v("Found " + incorrectMessage.name() + " in " + line);
throw new Exception("Found " + incorrectMessage.name() + " to " + toDevice +
- " with params " + getParamsFromMessage(line));
+ " with params " + CecMessage.getParamsAsString(line));
}
}
endTime = System.currentTimeMillis();
}
}
- /** Gets the hexadecimal ASCII character values of a string. */
- public String getHexAsciiString(String string) {
- String asciiString = "";
- byte[] ascii = string.trim().getBytes();
-
- for (byte b : ascii) {
- asciiString.concat(Integer.toHexString(b));
- }
-
- return asciiString;
- }
-
- public String formatParams(String rawParams) {
- StringBuilder params = new StringBuilder("");
- int position = 0;
- int endPosition = 2;
-
- do {
- params.append(":" + rawParams.substring(position, endPosition));
- position = endPosition;
- endPosition += 2;
- } while (endPosition <= rawParams.length());
- return params.toString();
- }
-
- public String formatParams(long rawParam) {
- StringBuilder params = new StringBuilder("");
-
- do {
- params.insert(0, ":" + String.format("%02x", rawParam % 256));
- rawParam >>= 8;
- } while (rawParam > 0);
-
- return params.toString();
- }
-
- /** Formats a CEC message in the hex colon format (sd:op:xx:xx). */
- public String formatMessage(CecDevice source, CecDevice destination, CecMessage message,
- int params) {
- StringBuilder cecMessage = new StringBuilder("" + source + destination + ":" + message);
-
- cecMessage.append(formatParams(params));
-
- return cecMessage.toString();
- }
-
- public static int hexStringToInt(String message) {
- return Integer.parseInt(message, HEXADECIMAL_RADIX);
- }
-
- public String getAsciiStringFromMessage(String message) {
- String params = getNibbles(message).substring(4);
- StringBuilder builder = new StringBuilder();
-
- for (int i = 2; i <= params.length(); i += 2) {
- builder.append((char) hexStringToInt(params.substring(i - 2, i)));
- }
-
- return builder.toString();
- }
-
- /**
- * Gets the params from a CEC message.
- */
- public int getParamsFromMessage(String message) {
- return hexStringToInt(getNibbles(message).substring(4));
- }
-
- /**
- * Gets the first 'numNibbles' number of param nibbles from a CEC message.
- */
- public int getParamsFromMessage(String message, int numNibbles) {
- int paramStart = 4;
- int end = numNibbles + paramStart;
- return hexStringToInt(getNibbles(message).substring(paramStart, end));
- }
-
- /**
- * From the params of a CEC message, gets the nibbles from position start to position end.
- * The start and end are relative to the beginning of the params. For example, in the following
- * message - 4F:82:10:00:04, getParamsFromMessage(message, 0, 4) will return 0x1000 and
- * getParamsFromMessage(message, 4, 6) will return 0x04.
- */
- public int getParamsFromMessage(String message, int start, int end) {
- return hexStringToInt(getNibbles(message).substring(4).substring(start, end));
- }
-
- /**
- * Gets the source logical address from a CEC message.
- */
- public CecDevice getSourceFromMessage(String message) {
- String param = getNibbles(message).substring(0, 1);
- return CecDevice.getDevice(hexStringToInt(param));
- }
-
- /**
- * Converts ascii characters to hexadecimal numbers that can be appended to a CEC message as
- * params. For example, "spa" will be converted to ":73:70:61"
- */
- public static String convertStringToHexParams(String rawParams) {
- StringBuilder params = new StringBuilder("");
- for (int i = 0; i < rawParams.length(); i++) {
- params.append(String.format(":%02x", (int) rawParams.charAt(i)));
- }
- return params.toString();
- }
-
-
- /**
- * Gets the destination logical address from a CEC message.
- */
- public CecDevice getDestinationFromMessage(String message) {
- String param = getNibbles(message).substring(1, 2);
- return CecDevice.getDevice(hexStringToInt(param));
- }
-
- private String getNibbles(String message) {
- final String tag1 = "group1";
- final String tag2 = "group2";
- String paramsPattern = "(?:.*[>>|<<].*?)" +
- "(?<" + tag1 + ">[\\p{XDigit}{2}:]+)" +
- "(?<" + tag2 + ">\\p{XDigit}{2})" +
- "(?:.*?)";
- String nibbles = "";
-
- Pattern p = Pattern.compile(paramsPattern);
- Matcher m = p.matcher(message);
- if (m.matches()) {
- nibbles = m.group(tag1).replace(":", "") + m.group(tag2);
- }
- return nibbles;
- }
-
/**
* Kills the cec-client process that was created in init().
*/
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
index 0565eaefbfb..8af4a8b5c0d 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
@@ -47,4 +47,11 @@ public final class HdmiCecConstants {
public static final int CEC_DEVICE_TYPE_PLAYBACK_DEVICE = 4;
public static final int CEC_DEVICE_TYPE_AUDIO_SYSTEM = 5;
+ /** Feature Abort Reasons */
+ public static final int ABORT_UNRECOGNIZED_MODE = 0;
+ public static final int ABORT_NOT_IN_CORRECT_MODE = 1;
+ public static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
+ public static final int ABORT_INVALID_OPERAND = 3;
+ public static final int ABORT_REFUSED = 4;
+ public static final int ABORT_UNABLE_TO_DETERMINE = 5;
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/LogHelper.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/LogHelper.java
new file mode 100644
index 00000000000..a7692f38104
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/LogHelper.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 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.hdmicec.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tradefed.device.ITestDevice;
+
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+
+/** Helper class to get for device logcat. */
+public final class LogHelper {
+
+ private static final int WAIT_TIME = 10;
+
+ /**
+ * The tag of the SadConfigurationReaderTest launched by the APK.
+ */
+ private static final String SAD_READER = "SadConfigurationReaderTest";
+
+ private static final String SAD_CONFIGURATION_MARKER = "Supported Audio Formats";
+
+ private static String getLog(ITestDevice device, String tag) throws Exception {
+ TimeUnit.SECONDS.sleep(WAIT_TIME);
+ String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", tag + ":I", "*:S");
+ // Search for string.
+ String testString = "";
+ Scanner in = new Scanner(logs);
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if (line.startsWith("I/" + tag)) {
+ testString = line.split(":")[1].trim();
+ }
+ }
+ device.executeAdbCommand("logcat", "-c");
+ return testString;
+ }
+
+ public static void assertLog(ITestDevice device, String tag, String ...expectedOutput)
+ throws Exception {
+ String testString = getLog(device, tag);
+ List<String> expectedOutputs = new ArrayList<>(Arrays.asList(expectedOutput));
+ assertThat(testString).isIn(expectedOutputs);
+ }
+
+ public static void assertLogDoesNotContain(ITestDevice device, String tag,
+ String expectedOutput) throws Exception {
+ String testString = getLog(device, tag);
+ assertThat(testString).doesNotContain(expectedOutput);
+ }
+
+ public static List<Integer> getSupportedAudioFormats(ITestDevice device) throws Exception {
+ TimeUnit.SECONDS.sleep(WAIT_TIME);
+ String logs =
+ device.executeAdbCommand("logcat", "-v", "brief", "-d", SAD_READER + ":I", "*:S");
+ // Search for string.
+ String testString = "";
+ Scanner in = new Scanner(logs);
+ List<Integer> mSupportedAudioFormats = null;
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if (line.startsWith("I/" + SAD_READER)) {
+ testString = line.split(":")[1].trim();
+ if (testString.equals(SAD_CONFIGURATION_MARKER)) {
+ List<String> mFormatsLine =
+ Arrays.asList(in.nextLine().split(":")[1].trim().split(", "));
+ List<String> mCodecSADsLine =
+ Arrays.asList(in.nextLine().split(":")[1].trim().split(", "));
+ mSupportedAudioFormats =
+ Lists.transform(mFormatsLine, fl -> Integer.parseInt(fl));
+ }
+ }
+ }
+ device.executeAdbCommand("logcat", "-c");
+ assumeTrue(testString.equals(SAD_CONFIGURATION_MARKER));
+ return mSupportedAudioFormats;
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/LogicalAddress.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/LogicalAddress.java
new file mode 100644
index 00000000000..5bcf5d1c92f
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/LogicalAddress.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.hdmicec.cts;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum LogicalAddress {
+ TV(0x0),
+ RECORDER_1(0x1),
+ RECORDER_2(0x2),
+ TUNER_1(0x3),
+ PLAYBACK_1(0x4),
+ AUDIO_SYSTEM(0x5),
+ TUNER_2(0x6),
+ TUNER_3(0x7),
+ PLAYBACK_2(0x8),
+ RECORDER_3(0x9),
+ TUNER_4(0xa),
+ PLAYBACK_3(0xb),
+ RESERVED_1(0xc),
+ RESERVED_2(0xd),
+ SPECIFIC_USE(0xe),
+ BROADCAST(0xf);
+
+ private final int address;
+ private static Map deviceMap = new HashMap<>();
+
+ // CEC Device feature list
+ public static final String HDMI_CEC_FEATURE = "feature:android.hardware.hdmi.cec";
+ public static final String LEANBACK_FEATURE = "feature:android.software.leanback";
+
+ // CEC Device property list
+ public static final String HDMI_DEVICE_TYPE_PROPERTY = "ro.hdmi.device_type";
+
+ @Override
+ public String toString() {
+ return Integer.toHexString(this.address);
+ }
+
+ static {
+ for (LogicalAddress device : LogicalAddress.values()) {
+ deviceMap.put(device.address, device);
+ }
+ }
+
+ public String getDeviceType() {
+ switch (this) {
+ case PLAYBACK_1:
+ case PLAYBACK_2:
+ case PLAYBACK_3:
+ return Integer.toString(HdmiCecConstants.CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+ case TV:
+ return Integer.toString(HdmiCecConstants.CEC_DEVICE_TYPE_TV);
+ case AUDIO_SYSTEM:
+ return Integer.toString(HdmiCecConstants.CEC_DEVICE_TYPE_AUDIO_SYSTEM);
+ case RECORDER_1:
+ case RECORDER_2:
+ case RECORDER_3:
+ return Integer.toString(HdmiCecConstants.CEC_DEVICE_TYPE_RECORDER);
+ case TUNER_1:
+ case TUNER_2:
+ case TUNER_3:
+ case TUNER_4:
+ return Integer.toString(HdmiCecConstants.CEC_DEVICE_TYPE_TUNER);
+ default:
+ return Integer.toString(HdmiCecConstants.CEC_DEVICE_TYPE_RESERVED);
+ }
+ }
+
+ public static LogicalAddress getLogicalAddress(int address) {
+ return (LogicalAddress) deviceMap.get(address);
+ }
+
+ private LogicalAddress(int address) {
+ this.address = address;
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredFeatureRule.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredFeatureRule.java
new file mode 100644
index 00000000000..8fb70ec025e
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredFeatureRule.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.cts;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Rule to check if the required device feature is available on device.
+ */
+public class RequiredFeatureRule implements TestRule {
+
+ private final BaseHostJUnit4Test mTest;
+ private final String mFeature;
+
+ public RequiredFeatureRule(BaseHostJUnit4Test test, String feature) {
+ mTest = test;
+ mFeature = feature;
+ }
+
+ @Override
+ public Statement apply(final Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ ITestDevice testDevice = mTest.getDevice();
+ // Checks if the device is available.
+ assumeTrue("Test device is not available", testDevice != null);
+ // Checks if the requested feature is available on the device.
+ assumeTrue(mFeature + " not present in DUT " + testDevice.getSerialNumber(),
+ testDevice.hasFeature(mFeature));
+ base.evaluate();
+ }
+ };
+ }
+}
+
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredPropertyRule.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredPropertyRule.java
new file mode 100644
index 00000000000..f3998adbe08
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/RequiredPropertyRule.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.cts;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Rule class that allows for checking device property value against required values.
+ * Static functions in this class can be used to check properties as a list or single value.
+ */
+public class RequiredPropertyRule implements TestRule {
+
+ // Do not allow instantiation.
+ private RequiredPropertyRule(){}
+
+ @Override
+ public Statement apply(final Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ base.evaluate();
+ }
+ };
+ }
+
+ private static String getDevicePropertyValue(BaseHostJUnit4Test test, String propertyName)
+ throws Throwable {
+ ITestDevice testDevice = test.getDevice();
+ // Checks if the device is available.
+ assumeTrue("Test device is not available", testDevice != null);
+ return testDevice.executeShellCommand("getprop " + propertyName).trim();
+
+ }
+
+ public static RequiredPropertyRule isEqualTo(final BaseHostJUnit4Test test,
+ final String propertyName, final String propertyValue) {
+ return new RequiredPropertyRule() {
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ String deviceProperty = getDevicePropertyValue(test, propertyName);
+ assumeTrue("Required property " + propertyName + " = " + propertyValue
+ + " is not present in " + deviceProperty
+ + " of device " + test.getDevice().getSerialNumber(),
+ deviceProperty.equals(propertyValue));
+ base.evaluate();
+ }
+ };
+ }
+ };
+ }
+
+ public static RequiredPropertyRule asCsvContainsValue(final BaseHostJUnit4Test test,
+ final String propertyName, final String propertyValue) {
+ return new RequiredPropertyRule() {
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ List<String> deviceProperties =
+ Arrays.asList(getDevicePropertyValue(test, propertyName)
+ .replaceAll("\\s+", "")
+ .split(","));
+ assumeTrue(
+ "Required property " + propertyName + " = " + propertyValue
+ + " is not present in " + deviceProperties.toString()
+ + " of device " + test.getDevice().getSerialNumber(),
+ deviceProperties.contains(propertyValue));
+ base.evaluate();
+ }
+ };
+ }
+ };
+ }
+}
+
+
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecAudioReturnChannelControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecAudioReturnChannelControlTest.java
new file mode 100644
index 00000000000..897a35e4adf
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecAudioReturnChannelControlTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2020 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.hdmicec.cts.audio;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
+import android.hdmicec.cts.HdmiCecClientWrapper;
+import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Rule;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+/** HDMI CEC test to test audio return channel control (Section 11.2.17) */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecAudioReturnChannelControlTest extends BaseHostJUnit4Test {
+
+ private static final LogicalAddress AUDIO_DEVICE = LogicalAddress.AUDIO_SYSTEM;
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(AUDIO_DEVICE);
+
+ @Rule
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ AUDIO_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
+
+ private void checkArcIsInitiated(){
+ try {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.REQUEST_ARC_INITIATION);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.INITIATE_ARC);
+ } catch(Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ /**
+ * Test 11.2.17-1
+ * Tests that the device sends a directly addressed <Initiate ARC> message
+ * when it wants to initiate ARC.
+ */
+ @Test
+ public void cect_11_2_17_1_InitiateArc() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.REPORT_PHYSICAL_ADDRESS,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ getDevice().executeShellCommand("reboot");
+ getDevice().waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.INITIATE_ARC);
+ }
+
+ /**
+ * Test 11.2.17-2
+ * Tests that the device sends a directly addressed <Terminate ARC> message
+ * when it wants to terminate ARC.
+ */
+ @Test
+ public void cect_11_2_17_2_TerminateArc() throws Exception {
+ checkArcIsInitiated();
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.REPORT_PHYSICAL_ADDRESS,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ getDevice().executeShellCommand("input keyevent KEYCODE_SLEEP");
+ try {
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.TERMINATE_ARC);
+ } finally {
+ getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ }
+ }
+
+ /**
+ * Test 11.2.17-3
+ * Tests that the device sends a directly addressed <Initiate ARC>
+ * message when it is requested to initiate ARC.
+ */
+ @Test
+ public void cect_11_2_17_3_RequestToInitiateArc() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.REPORT_PHYSICAL_ADDRESS,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.REQUEST_ARC_INITIATION);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.INITIATE_ARC);
+ }
+
+ /**
+ * Test 11.2.17-4
+ * Tests that the device sends a directly addressed <Terminate ARC> message
+ * when it is requested to terminate ARC.
+ */
+ @Test
+ public void cect_11_2_17_4_RequestToTerminateArc() throws Exception {
+ checkArcIsInitiated();
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.REPORT_PHYSICAL_ADDRESS,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.REQUEST_ARC_TERMINATION);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.TERMINATE_ARC);
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecInvalidMessagesTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecInvalidMessagesTest.java
new file mode 100644
index 00000000000..a77573ebcd7
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecInvalidMessagesTest.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.cts.audio;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
+import android.hdmicec.cts.HdmiCecClientWrapper;
+import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogHelper;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+/** HDMI CEC test to verify that device ignores invalid messages (Section 12) */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecInvalidMessagesTest extends BaseHostJUnit4Test {
+
+ private static final LogicalAddress AUDIO_DEVICE = LogicalAddress.AUDIO_SYSTEM;
+ private static final String PROPERTY_LOCALE = "persist.sys.locale";
+
+ /** The package name of the APK. */
+ private static final String PACKAGE = "android.hdmicec.app";
+
+ /** The class name of the main activity in the APK. */
+ private static final String CLASS = "HdmiCecKeyEventCapture";
+
+ /** The command to launch the main activity. */
+ private static final String START_COMMAND = String.format(
+ "am start -W -a android.intent.action.MAIN -n %s/%s.%s", PACKAGE, PACKAGE, CLASS);
+
+ /** The command to clear the main activity. */
+ private static final String CLEAR_COMMAND = String.format("pm clear %s", PACKAGE);
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(AUDIO_DEVICE);
+
+ @Rule
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ AUDIO_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
+
+ private String getSystemLocale() throws Exception {
+ ITestDevice device = getDevice();
+ return device.executeShellCommand("getprop " + PROPERTY_LOCALE).trim();
+ }
+
+ private void setSystemLocale(String locale) throws Exception {
+ ITestDevice device = getDevice();
+ device.executeShellCommand("setprop " + PROPERTY_LOCALE + " " + locale);
+ }
+
+ private boolean isLanguageEditable() throws Exception {
+ String val = getDevice().executeShellCommand("getprop ro.hdmi.set_menu_language");
+ return val.trim().equals("true") ? true : false;
+ }
+
+ private static String extractLanguage(String locale) {
+ return locale.split("[^a-zA-Z]")[0];
+ }
+
+ private void checkArcIsInitiated(){
+ try {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.REQUEST_ARC_INITIATION);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.INITIATE_ARC);
+ } catch(Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ /**
+ * Test 12-1
+ * Tests that the device ignores every broadcast only message that is received as
+ * directly addressed.
+ */
+ @Test
+ public void cect_12_1_BroadcastReceivedAsDirectlyAddressed() throws Exception {
+ /* <Set Menu Language> */
+ assumeTrue(isLanguageEditable());
+ final String locale = getSystemLocale();
+ final String originalLanguage = extractLanguage(locale);
+ final String language = originalLanguage.equals("spa") ? "eng" : "spa";
+ try {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ AUDIO_DEVICE,
+ CecOperand.SET_MENU_LANGUAGE,
+ CecMessage.convertStringToHexParams(language));
+ assertThat(originalLanguage).isEqualTo(extractLanguage(getSystemLocale()));
+ } finally {
+ // If the language was incorrectly changed during the test, restore it.
+ setSystemLocale(locale);
+ }
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <GET_CEC_VERSION> if received as
+ * a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_getCecVersion() throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.GET_CEC_VERSION);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.TV,
+ CecOperand.CEC_VERSION);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <GIVE_PHYSICAL_ADDRESS> if received
+ * as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_givePhysicalAddress()
+ throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.GIVE_PHYSICAL_ADDRESS);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.BROADCAST,
+ CecOperand.REPORT_PHYSICAL_ADDRESS);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <GIVE_AUDIO_STATUS> if received as
+ * a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_giveAudioStatus() throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.GIVE_AUDIO_STATUS);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.TV,
+ CecOperand.REPORT_AUDIO_STATUS);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <GIVE_POWER_STATUS> if received as
+ * a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_givePowerStatus() throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.GIVE_POWER_STATUS);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.TV,
+ CecOperand.REPORT_POWER_STATUS);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <GIVE_DEVICE_VENDOR_ID> if received
+ * as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_giveDeviceVendorId()
+ throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.GIVE_DEVICE_VENDOR_ID);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.BROADCAST,
+ CecOperand.DEVICE_VENDOR_ID);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <GIVE_OSD_NAME> if received as
+ * a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_giveOsdName() throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.GIVE_OSD_NAME);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.TV,
+ CecOperand.SET_OSD_NAME);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <GIVE_SYSTEM_AUDIO_MODE_STATUS> if
+ * received as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_giveSystemAudioModeStatus()
+ throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.TV,
+ CecOperand.SYSTEM_AUDIO_MODE_STATUS);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <REQUEST_SHORT_AUDIO_DESCRIPTOR> if
+ * received as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_requestShortAudioDescriptor()
+ throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.REQUEST_SHORT_AUDIO_DESCRIPTOR,
+ CecMessage.formatParams("01020304"));
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.TV,
+ CecOperand.REPORT_SHORT_AUDIO_DESCRIPTOR);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <SYSTEM_AUDIO_MODE_REQUEST> if
+ * received as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_systemAudioModeRequest()
+ throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.BROADCAST,
+ CecOperand.SET_SYSTEM_AUDIO_MODE);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <REQUEST_ARC_INITIATION> if
+ * received as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_requestArcInitiation()
+ throws Exception {
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.REQUEST_ARC_INITIATION);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.BROADCAST,
+ CecOperand.INITIATE_ARC);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <REQUEST_ARC_TERMINATION> if
+ * received as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_requestArcTermination()
+ throws Exception {
+ checkArcIsInitiated();
+ hdmiCecClient.sendCecMessage(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ CecOperand.REQUEST_ARC_TERMINATION);
+ hdmiCecClient.checkOutputDoesNotContainMessage(
+ LogicalAddress.BROADCAST,
+ CecOperand.TERMINATE_ARC);
+ }
+
+ /**
+ * Test 12-2
+ * Tests that the device ignores directly addressed message <USER_CONTROL_PRESSED> if received
+ * as a broadcast message
+ */
+ @Test
+ public void cect_12_2_DirectlyAddressedReceivedAsBroadcast_userControlPressed()
+ throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Clear logcat.
+ device.executeAdbCommand("logcat", "-c");
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND);
+ hdmiCecClient.sendUserControlPressAndRelease(
+ LogicalAddress.TV,
+ LogicalAddress.BROADCAST,
+ HdmiCecConstants.CEC_CONTROL_UP,
+ false);
+ LogHelper.assertLogDoesNotContain(getDevice(), CLASS, "Short press KEYCODE_DPAD_UP");
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecLogicalAddressTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecLogicalAddressTest.java
index 1305a2b50b8..d0f052d6d6a 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecLogicalAddressTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecLogicalAddressTest.java
@@ -16,29 +16,43 @@
package android.hdmicec.cts.audio;
-import static org.junit.Assert.assertThat;
-import static org.hamcrest.CoreMatchers.is;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
/** HDMI CEC test to verify logical address after device reboot (Section 10.2.5) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecLogicalAddressTest extends BaseHostJUnit4Test {
- private static final CecDevice AUDIO_DEVICE = CecDevice.AUDIO_SYSTEM;
+
+ private static final LogicalAddress AUDIO_DEVICE = LogicalAddress.AUDIO_SYSTEM;
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(AUDIO_DEVICE);
@Rule
- public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(AUDIO_DEVICE, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ AUDIO_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 10.2.5-1
@@ -50,7 +64,7 @@ public final class HdmiCecLogicalAddressTest extends BaseHostJUnit4Test {
ITestDevice device = getDevice();
device.executeShellCommand("reboot");
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.REPORT_PHYSICAL_ADDRESS);
- assertThat(hdmiCecClient.getSourceFromMessage(message), is(AUDIO_DEVICE));
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_PHYSICAL_ADDRESS);
+ assertThat(CecMessage.getSource(message)).isEqualTo(AUDIO_DEVICE);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecRemoteControlPassThroughTest.java
index 9931e263dc1..d01b5063546 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecRemoteControlPassThroughTest.java
@@ -16,23 +16,22 @@
package android.hdmicec.cts.audio;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogHelper;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
-import java.util.Scanner;
-import java.util.concurrent.TimeUnit;
-
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Test {
@@ -49,29 +48,18 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
/** The command to clear the main activity. */
private static final String CLEAR_COMMAND = String.format("pm clear %s", PACKAGE);
- private static final int WAIT_TIME = 10;
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.AUDIO_SYSTEM);
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.AUDIO_SYSTEM, this);
-
- private void lookForLog(String expectedOut) throws Exception {
- ITestDevice device = getDevice();
- TimeUnit.SECONDS.sleep(WAIT_TIME);
- String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
- // Search for string.
- String testString = "";
- Scanner in = new Scanner(logs);
- while (in.hasNextLine()) {
- String line = in.nextLine();
- if(line.startsWith("I/" + CLASS)) {
- testString = line.split(":")[1].trim();
- break;
- }
- }
- device.executeAdbCommand("logcat", "-c");
- assertThat(testString).isEqualTo(expectedOut);
- }
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.AUDIO_SYSTEM.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.13-1
@@ -87,24 +75,24 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
device.executeAdbCommand("logcat", "-c");
// Start the APK and wait for it to complete.
device.executeShellCommand(START_COMMAND);
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_UP, false);
- lookForLog("Short press KEYCODE_DPAD_UP");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_DOWN, false);
- lookForLog("Short press KEYCODE_DPAD_DOWN");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_LEFT, false);
- lookForLog("Short press KEYCODE_DPAD_LEFT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_RIGHT, false);
- lookForLog("Short press KEYCODE_DPAD_RIGHT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_SELECT, false);
- lookForLog("Short press KEYCODE_DPAD_CENTER");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_CENTER");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_BACK, false);
- lookForLog("Short press KEYCODE_BACK");
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_BACK");
}
/**
@@ -121,24 +109,24 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
device.executeAdbCommand("logcat", "-c");
// Start the APK and wait for it to complete.
device.executeShellCommand(START_COMMAND);
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_UP, true);
- lookForLog("Long press KEYCODE_DPAD_UP");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_DOWN, true);
- lookForLog("Long press KEYCODE_DPAD_DOWN");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_LEFT, true);
- lookForLog("Long press KEYCODE_DPAD_LEFT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_RIGHT, true);
- lookForLog("Long press KEYCODE_DPAD_RIGHT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_SELECT, true);
- lookForLog("Long press KEYCODE_DPAD_CENTER");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_CENTER");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_BACK, true);
- lookForLog("Long press KEYCODE_BACK");
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_BACK");
}
/**
@@ -155,24 +143,24 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
device.executeAdbCommand("logcat", "-c");
// Start the APK and wait for it to complete.
device.executeShellCommand(START_COMMAND);
- hdmiCecClient.sendUserControlPress(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ hdmiCecClient.sendUserControlPress(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_UP, true);
- lookForLog("Long press KEYCODE_DPAD_UP");
- hdmiCecClient.sendUserControlPress(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlPress(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_DOWN, true);
- lookForLog("Long press KEYCODE_DPAD_DOWN");
- hdmiCecClient.sendUserControlPress(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlPress(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_LEFT, true);
- lookForLog("Long press KEYCODE_DPAD_LEFT");
- hdmiCecClient.sendUserControlPress(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlPress(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_RIGHT, true);
- lookForLog("Long press KEYCODE_DPAD_RIGHT");
- hdmiCecClient.sendUserControlPress(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlPress(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_SELECT, true);
- lookForLog("Long press KEYCODE_DPAD_CENTER");
- hdmiCecClient.sendUserControlPress(CecDevice.TV, CecDevice.AUDIO_SYSTEM,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_CENTER");
+ hdmiCecClient.sendUserControlPress(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
HdmiCecConstants.CEC_CONTROL_BACK, true);
- lookForLog("Long press KEYCODE_BACK");
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_BACK");
}
/**
@@ -190,29 +178,29 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
device.executeAdbCommand("logcat", "-c");
// Start the APK and wait for it to complete.
device.executeShellCommand(START_COMMAND);
- hdmiCecClient.sendUserControlInterruptedPressAndHold(CecDevice.TV,
- CecDevice.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_UP,
+ hdmiCecClient.sendUserControlInterruptedPressAndHold(LogicalAddress.TV,
+ LogicalAddress.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_UP,
HdmiCecConstants.CEC_CONTROL_BACK, true);
- lookForLog("Long press KEYCODE_DPAD_UP");
- hdmiCecClient.sendUserControlInterruptedPressAndHold(CecDevice.TV,
- CecDevice.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_DOWN,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlInterruptedPressAndHold(LogicalAddress.TV,
+ LogicalAddress.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_DOWN,
HdmiCecConstants.CEC_CONTROL_UP, true);
- lookForLog("Long press KEYCODE_DPAD_DOWN");
- hdmiCecClient.sendUserControlInterruptedPressAndHold(CecDevice.TV,
- CecDevice.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_LEFT,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlInterruptedPressAndHold(LogicalAddress.TV,
+ LogicalAddress.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_LEFT,
HdmiCecConstants.CEC_CONTROL_DOWN, true);
- lookForLog("Long press KEYCODE_DPAD_LEFT");
- hdmiCecClient.sendUserControlInterruptedPressAndHold(CecDevice.TV,
- CecDevice.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_RIGHT,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlInterruptedPressAndHold(LogicalAddress.TV,
+ LogicalAddress.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_RIGHT,
HdmiCecConstants.CEC_CONTROL_LEFT, true);
- lookForLog("Long press KEYCODE_DPAD_RIGHT");
- hdmiCecClient.sendUserControlInterruptedPressAndHold(CecDevice.TV,
- CecDevice.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_SELECT,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlInterruptedPressAndHold(LogicalAddress.TV,
+ LogicalAddress.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_SELECT,
HdmiCecConstants.CEC_CONTROL_RIGHT, true);
- lookForLog("Long press KEYCODE_DPAD_CENTER");
- hdmiCecClient.sendUserControlInterruptedPressAndHold(CecDevice.TV,
- CecDevice.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_BACK,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_CENTER");
+ hdmiCecClient.sendUserControlInterruptedPressAndHold(LogicalAddress.TV,
+ LogicalAddress.AUDIO_SYSTEM, HdmiCecConstants.CEC_CONTROL_BACK,
HdmiCecConstants.CEC_CONTROL_SELECT, true);
- lookForLog("Long press KEYCODE_BACK");
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_BACK");
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecSystemAudioModeTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecSystemAudioModeTest.java
index 6f6e4dc11c6..ac21a0fa8ba 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecSystemAudioModeTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/audio/HdmiCecSystemAudioModeTest.java
@@ -16,29 +16,206 @@
package android.hdmicec.cts.audio;
-import static org.junit.Assert.assertThat;
-import static org.hamcrest.CoreMatchers.is;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.common.collect.Range;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogHelper;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.After;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
/** HDMI CEC test to test system audio mode (Section 11.2.15) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecSystemAudioModeTest extends BaseHostJUnit4Test {
- private static final CecDevice AUDIO_DEVICE = CecDevice.AUDIO_SYSTEM;
+
+ /** The package name of the APK. */
+ private static final String PACKAGE = "android.hdmicec.app";
+
+ /** The class name of the main activity in the APK. */
+ private static final String CLASS = "HdmiCecAudioManager";
+
+ /** The command to launch the main activity. */
+ private static final String START_COMMAND = String.format(
+ "am start -n %s/%s.%s -a ", PACKAGE, PACKAGE, CLASS);
+
+ /** The command to clear the main activity. */
+ private static final String CLEAR_COMMAND = String.format("pm clear %s", PACKAGE);
+
+ private static final LogicalAddress AUDIO_DEVICE = LogicalAddress.AUDIO_SYSTEM;
private static final int ON = 0x1;
+ private static final int OFF = 0x0;
+ private static final int MAX_AUDIO_FORMATS = 4;
+ private static final int MAX_VALID_AUDIO_FORMATS = 2;
+
+ private List<Integer> mSupportedAudioFormats = null;
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(AUDIO_DEVICE, "-t", "t");
@Rule
- public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(AUDIO_DEVICE, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ AUDIO_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
+
+ private String getRequestSadFormatsParams(boolean sendValidFormats) throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Clear logcat.
+ device.executeAdbCommand("logcat", "-c");
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND + "android.hdmicec.app.GET_SUPPORTED_SAD_FORMATS");
+ mSupportedAudioFormats = LogHelper.getSupportedAudioFormats(getDevice());
+
+ // Create a list of all the audio format codes according to CEA-861-D. Remove the supported
+ // audio format codes from it, to get the unsupported audio format codes.
+ List<Integer> mAllCodecFormats =
+ IntStream.range(1, 15).boxed().collect(Collectors.toList());
+ List<Integer> unsupportedAudioFormats = new ArrayList<>();
+ unsupportedAudioFormats.addAll(mAllCodecFormats);
+ unsupportedAudioFormats.removeAll(mSupportedAudioFormats);
+ // Create params message for REQUEST_SHORT_AUDIO_DESCRIPTOR
+ String messageParams = "";
+ int i = 0;
+ int listIndex = 0;
+ if (sendValidFormats) {
+ while (i < Math.min(MAX_VALID_AUDIO_FORMATS, mSupportedAudioFormats.size())) {
+ messageParams +=
+ CecMessage.formatParams(mSupportedAudioFormats.get(listIndex), 2);
+ i++;
+ listIndex++;
+ }
+ listIndex = 0;
+ }
+ while (i < Math.min(MAX_AUDIO_FORMATS, unsupportedAudioFormats.size())) {
+ messageParams += CecMessage.formatParams(unsupportedAudioFormats.get(listIndex), 2);
+ i++;
+ listIndex++;
+ }
+ return messageParams;
+ }
+
+ private void muteDevice() throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Clear logcat.
+ device.executeAdbCommand("logcat", "-c");
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND + "android.hdmicec.app.MUTE");
+ }
+
+ private void unmuteDevice() throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND + "android.hdmicec.app.UNMUTE");
+ }
+
+ public boolean isDeviceMuted() throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Clear logcat.
+ device.executeAdbCommand("logcat", "-c");
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND + "android.hdmicec.app.REPORT_VOLUME");
+ try {
+ LogHelper.assertLog(getDevice(), CLASS, "Device muted.");
+ return true;
+ } catch(Exception e) {
+ return false;
+ }
+ }
+
+ public void setDeviceVolume(int percentVolume) throws Exception {
+ ITestDevice device = getDevice();
+ // Clear activity
+ device.executeShellCommand(CLEAR_COMMAND);
+ // Start the APK and wait for it to complete.
+ device.executeShellCommand(START_COMMAND + "android.hdmicec.app.SET_VOLUME --ei " +
+ "\"volumePercent\" " + percentVolume);
+ }
+
+ public void sendSystemAudioModeTermination() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST);
+ }
+
+ public void sendSystemAudioModeInitiation() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ }
+
+ private int getDutAudioStatus() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE, CecOperand.GIVE_AUDIO_STATUS);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.REPORT_AUDIO_STATUS);
+ return CecMessage.getParams(message);
+ }
+
+ private void initateSystemAudioModeFromTuner() throws Exception {
+ getDevice().reboot();
+ hdmiCecClient.sendCecMessage(LogicalAddress.TUNER_1, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ handleSetSystemAudioModeOnToTv();
+ }
+
+ private void handleSetSystemAudioModeOnToTv() throws Exception {
+ hdmiCecClient.checkExpectedOutput(CecOperand.REQUEST_ACTIVE_SOURCE);
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST, CecOperand.ACTIVE_SOURCE,
+ CecMessage.formatParams("2000"));
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ }
+
+ private void initiateSystemAudioModeFromDut() throws Exception {
+ getDevice().reboot();
+ hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_PHYSICAL_ADDRESS);
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
+ CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.INITIATE_ARC);
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.AUDIO_SYSTEM,
+ CecOperand.ARC_INITIATED);
+ handleSetSystemAudioModeOnToTv();
+ }
+
+ @After
+ public void resetVolume() throws Exception {
+ setDeviceVolume(20);
+ }
/**
* Test 11.2.15-1
@@ -47,17 +224,306 @@ public final class HdmiCecSystemAudioModeTest extends BaseHostJUnit4Test {
*/
@Test
public void cect_11_2_15_1_SystemAudioModeRequestAsFollower() throws Exception {
- hdmiCecClient.sendCecMessage(CecDevice.TV, AUDIO_DEVICE,
- CecMessage.SYSTEM_AUDIO_MODE_REQUEST,
- hdmiCecClient.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS));
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.SET_SYSTEM_AUDIO_MODE);
- assertThat(hdmiCecClient.getParamsFromMessage(message), is(ON));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
/* Repeat test for device 0x3 (TUNER_1) */
- hdmiCecClient.sendCecMessage(CecDevice.TUNER_1, AUDIO_DEVICE,
- CecMessage.SYSTEM_AUDIO_MODE_REQUEST,
- hdmiCecClient.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS));
- message = hdmiCecClient.checkExpectedOutput(CecMessage.SET_SYSTEM_AUDIO_MODE);
- assertThat(hdmiCecClient.getParamsFromMessage(message), is(ON));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TUNER_1, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ }
+
+ /**
+ * Test 11.2.15-2
+ * Tests that the device issues <Set System Audio Mode>
+ * message when the feature is initiated in the device .
+ */
+ @Test
+ public void cect_11_2_15_2_SystemAudioModeWithFeatureInitiation() throws Exception {
+ initiateSystemAudioModeFromDut();
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ }
+
+ /**
+ * Test 11.2.15-3
+ * Tests that the device doesn't broadcast any <Set System Audio Mode>
+ * messages when TV responds with a <Feature Abort> to a directly addressed
+ * <Set System Audio Mode> message.
+ */
+ @Test
+ public void cect_11_2_15_3_SystemAudioModeWithFeatureAbort() throws Exception {
+ initiateSystemAudioModeFromDut();
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE, CecOperand.FEATURE_ABORT,
+ CecMessage.formatParams(CecOperand.SET_SYSTEM_AUDIO_MODE + "04"));
+ hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.BROADCAST,
+ CecOperand.SET_SYSTEM_AUDIO_MODE);
+ //The DUT will need a reboot here so it'll forget the feature abort from the previous
+ // message. Else it may not respond correctly with a SET_SYSTEM_AUDIO_MODE message
+ // in future tests.
+ getDevice().reboot();
+ }
+
+ /**
+ * Test 11.2.15-4
+ * Tests that the device responds correctly to a <Give System Audio Status>
+ * message when System Audio Mode is "On".
+ */
+ @Test
+ public void cect_11_2_15_4_SystemAudioModeStatusOn() throws Exception {
+ sendSystemAudioModeInitiation();
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
+ message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.SYSTEM_AUDIO_MODE_STATUS);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ }
+
+ /**
+ * Test 11.2.15-5
+ * Tests that the device sends a <Set System Audio Mode> ["Off"]
+ * message when a <System Audio Mode Request> is received with no operands
+ */
+ @Test
+ public void cect_11_2_15_5_SetSystemAudioModeOff() throws Exception {
+ sendSystemAudioModeInitiation();
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ sendSystemAudioModeTermination();
+ message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(OFF);
+ }
+
+ /**
+ * Test 11.2.15-6
+ * Tests that the device sends a <Set System Audio Mode> ["Off"]
+ * message before going into standby when System Audio Mode is on.
+ */
+ @Test
+ public void cect_11_2_15_6_SystemAudioModeOffBeforeStandby() throws Exception {
+ try {
+ getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ sendSystemAudioModeInitiation();
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ getDevice().executeShellCommand("input keyevent KEYCODE_SLEEP");
+ message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(OFF);
+ } finally {
+ getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ }
+ }
+
+ /**
+ * Test 11.2.15-7
+ * Tests that the device responds correctly to a <Give System Audio Mode Status>
+ * message when the System Audio Mode is "Off".
+ */
+ @Test
+ public void cect_11_2_15_7_SystemAudioModeStatusOff() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.SET_SYSTEM_AUDIO_MODE, CecMessage.formatParams(OFF));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.SYSTEM_AUDIO_MODE_STATUS);
+ assertThat(CecMessage.getParams(message)).isEqualTo(OFF);
+ }
+
+ /**
+ * Test 11.2.15-8
+ * Tests that the device handles <User Controlled Pressed> ["Mute"]
+ * correctly when System Audio Mode is "On".
+ */
+ @Test
+ public void cect_11_2_15_8_HandleUcpMute() throws Exception {
+ unmuteDevice();
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, AUDIO_DEVICE,
+ HdmiCecConstants.CEC_CONTROL_MUTE, false);
+ assertWithMessage("Device is not muted").that(isDeviceMuted()).isTrue();
+ }
+
+ /**
+ * Test 11.2.15-9
+ * Tests that the DUT responds with a <Report Audio Status> message with correct parameters
+ * to a <Give Audio Status> message when volume is set to 0% and not muted.
+ */
+ @Test
+ public void cect_11_2_15_9_ReportAudioStatus_0_unmuted() throws Exception {
+ sendSystemAudioModeInitiation();
+ unmuteDevice();
+ setDeviceVolume(0);
+ int reportedVolume = getDutAudioStatus();
+ assertThat(reportedVolume).isEqualTo(0);
+ }
+
+ /**
+ * Test 11.2.15-9
+ * Tests that the DUT responds with a <Report Audio Status> message with correct parameters
+ * to a <Give Audio Status> message when volume is set to 50% and not muted.
+ */
+ @Test
+ public void cect_11_2_15_9_ReportAudioStatus_50_unmuted() throws Exception {
+ sendSystemAudioModeInitiation();
+ unmuteDevice();
+ setDeviceVolume(50);
+ int reportedVolume = getDutAudioStatus();
+ /* Allow for a range of volume, since the actual volume set will depend on the device's
+ volume resolution. */
+ assertThat(reportedVolume).isIn(Range.closed(46, 54));
+ }
+
+ /**
+ * Test 11.2.15-9
+ * Tests that the DUT responds with a <Report Audio Status> message with correct parameters
+ * to a <Give Audio Status> message when volume is set to 100% and not muted.
+ */
+ @Test
+ public void cect_11_2_15_9_ReportAudioStatus_100_unmuted() throws Exception {
+ sendSystemAudioModeInitiation();
+ unmuteDevice();
+ setDeviceVolume(100);
+ int reportedVolume = getDutAudioStatus();
+ assertThat(reportedVolume).isEqualTo(100);
+ }
+
+ /**
+ * Test 11.2.15-9
+ * Tests that the DUT responds with a <Report Audio Status> message with correct parameters
+ * to a <Give Audio Status> message when volume is muted.
+ */
+ @Test
+ public void cect_11_2_15_9_ReportAudioStatusMuted() throws Exception {
+ sendSystemAudioModeInitiation();
+ muteDevice();
+ int reportedVolume = getDutAudioStatus();
+ /* If device is muted, the 8th bit of CEC message parameters is set and the volume will
+ be greater than 127. */
+ assertWithMessage("Device not muted").that(reportedVolume).isGreaterThan(127);
+ }
+
+ /**
+ * Test 11.2.15-13
+ * Tests that the device responds to a <Request Short Audio Descriptor> message with a
+ * <Report Short Audio Descriptor> message with only those audio descriptors that are supported.
+ */
+ @Test
+ public void cect_11_2_15_13_ValidShortAudioDescriptor() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.REQUEST_SHORT_AUDIO_DESCRIPTOR, getRequestSadFormatsParams(true));
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.REPORT_SHORT_AUDIO_DESCRIPTOR);
+ /* Each Short Audio Descriptor is 3 bytes long. In the first byte of the params, bits 3-6
+ * will have the audio format. Bit 7 will always 0 for audio format defined in CEA-861-D.
+ * Bits 0-2 represent (Max number of channels - 1). Discard bits 0-2 and check for the
+ * format.
+ * Iterate the params by 3 bytes(6 nibbles) and extract only the first byte(2 nibbles).
+ */
+ for (int i = 0; i < Math.min(mSupportedAudioFormats.size(), MAX_VALID_AUDIO_FORMATS); i++) {
+ int audioFormat =
+ CecMessage.getParams(message, 6 * i, 6 * i + 2) >>> 3;
+ assertWithMessage("Could not find audio format " + audioFormat)
+ .that(mSupportedAudioFormats).contains(audioFormat);
+ }
+ }
+
+ /**
+ * Test 11.2.15-14
+ * Tests that the device responds to a <Request Short Audio Descriptor> message with a
+ * <Feature Abort> [“Invalid Operand”] when a <Request Short Audio Descriptor> message is
+ * received with a single [Audio Format ID][Audio Format Code] pair that is not supported.
+ */
+ @Test
+ public void cect_11_2_15_14_InvalidShortAudioDescriptor() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.REQUEST_SHORT_AUDIO_DESCRIPTOR, getRequestSadFormatsParams(false));
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.FEATURE_ABORT);
+ assertThat(CecOperand.getOperand(CecMessage.getParams(message, 2)))
+ .isEqualTo(CecOperand.REQUEST_SHORT_AUDIO_DESCRIPTOR);
+ assertThat(CecMessage.getParams(message, 2, 4))
+ .isEqualTo(HdmiCecConstants.ABORT_INVALID_OPERAND);
+ }
+
+ /**
+ * Test 11.2.15-16
+ * Tests that the device unmute its volume when it broadcasts a
+ * <Set System Audio Mode> ["On"] message
+ */
+ @Test
+ public void cect_11_2_15_16_UnmuteForSystemAudioRequestOn() throws Exception {
+ muteDevice();
+ sendSystemAudioModeTermination();
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(OFF);
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ assertWithMessage("Device muted").that(isDeviceMuted()).isFalse();
+ }
+
+ /**
+ * Test 11.2.15-17
+ * Tests that the device mute its volume when it broadcasts a
+ * <Set System Audio Mode> ["Off"] message
+ */
+ @Test
+ public void cect_11_2_15_17_MuteForSystemAudioRequestOff() throws Exception {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE,
+ CecOperand.SYSTEM_AUDIO_MODE_REQUEST,
+ CecMessage.formatParams(HdmiCecConstants.TV_PHYSICAL_ADDRESS,
+ HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
+ sendSystemAudioModeTermination();
+ message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_SYSTEM_AUDIO_MODE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(OFF);
+ assertWithMessage("Device not muted").that(isDeviceMuted()).isTrue();
+ }
+
+ /**
+ * Test 11.2.15-18
+ * Tests that the device doesn't broadcast <Set System Audio Mode>
+ * messages if TV responds with a <Feature Abort> message to directly addressed
+ * <Set System Audio Mode> message within the required maximum response time of 1 second.
+ */
+ @Test
+ public void cect_11_2_15_18_SystemAudioModeWithFeatureAbortWithinTime() throws Exception {
+ initiateSystemAudioModeFromDut();
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE, CecOperand.FEATURE_ABORT,
+ CecMessage.formatParams(CecOperand.SET_SYSTEM_AUDIO_MODE + "04"));
+ hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.BROADCAST,
+ CecOperand.SET_SYSTEM_AUDIO_MODE);
+ }
+
+ /**
+ * Test 11.2.15-19
+ * Tests that the device doesn't broadcast <Set System Audio Mode>
+ * messages if TV responds with a <Feature Abort> message to directly addressed
+ * <Set System Audio Mode> message within the required maximum response time of 1 second.
+ * The <Set System Audio Mode> message should be initiated from logical address 3.
+ */
+ @Test
+ public void cect_11_2_15_19_SystemAudioModeWithFeatureAbortWithinTime() throws Exception {
+ initateSystemAudioModeFromTuner();
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, AUDIO_DEVICE, CecOperand.FEATURE_ABORT,
+ CecMessage.formatParams(CecOperand.SET_SYSTEM_AUDIO_MODE + "04"));
+ hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.BROADCAST,
+ CecOperand.SET_SYSTEM_AUDIO_MODE);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecDeviceTypeTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecDeviceTypeTest.java
new file mode 100644
index 00000000000..4c716cceb4b
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecDeviceTypeTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020 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.hdmicec.cts.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+
+/** Tests to see that a valid HDMI CEC device type is declared by the device. */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecDeviceTypeTest extends BaseHostJUnit4Test {
+
+ private static List<String> validTypes = new ArrayList<>(
+ Arrays.asList("", "0", "4", "4,5", "5,4"));
+ /**
+ * Tests that the device declares a valid HDMI CEC device type.
+ */
+ @Test
+ public void checkHdmiCecDeviceType() throws Exception {
+ ITestDevice device = getDevice();
+ String logs = device.executeShellCommand("cmd package list features");
+ Scanner in = new Scanner(logs);
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if (line.equals("feature:android.software.leanback")) {
+ // Remove "" as valid device type if android.software.leanback feature is supported
+ validTypes.remove("");
+ }
+ }
+ String deviceType = device.executeShellCommand("getprop ro.hdmi.device_type");
+ assertThat(deviceType.trim()).isIn(validTypes);
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java
index cda29512f7f..ef1042596df 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java
@@ -16,28 +16,42 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
/** HDMI CEC tests related to the device reporting the device OSD name (Section 11.2.11) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecDeviceOsdNameTest extends BaseHostJUnit4Test {
- private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
+
+ private static final LogicalAddress PLAYBACK_DEVICE = LogicalAddress.PLAYBACK_1;
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.11-1a
@@ -53,9 +67,9 @@ public final class HdmiCecDeviceOsdNameTest extends BaseHostJUnit4Test {
if (deviceName.length() > nameLength) {
deviceName = deviceName.substring(0, nameLength).trim();
}
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GIVE_OSD_NAME);
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV, CecMessage.SET_OSD_NAME);
- assertEquals(deviceName, hdmiCecClient.getAsciiStringFromMessage(message));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, CecOperand.GIVE_OSD_NAME);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.SET_OSD_NAME);
+ assertThat(CecMessage.getAsciiString(message)).isEqualTo(deviceName);
}
/**
@@ -70,10 +84,10 @@ public final class HdmiCecDeviceOsdNameTest extends BaseHostJUnit4Test {
String originalName = device.executeShellCommand("settings get global device_name").trim();
try {
device.executeShellCommand("settings put global device_name '" + testName + "'");
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GIVE_OSD_NAME);
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV,
- CecMessage.SET_OSD_NAME);
- assertEquals(testName, hdmiCecClient.getAsciiStringFromMessage(message));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, CecOperand.GIVE_OSD_NAME);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.SET_OSD_NAME);
+ assertThat(CecMessage.getAsciiString(message)).isEqualTo(testName);
} finally {
device.executeShellCommand("settings put global device_name '" + originalName + "'");
}
@@ -85,11 +99,11 @@ public final class HdmiCecDeviceOsdNameTest extends BaseHostJUnit4Test {
*/
@Test
public void cect_11_2_11_2_UnregisteredDeviceGiveOsdNameTest() throws Exception {
- hdmiCecClient.sendCecMessage(CecDevice.PLAYBACK_1, CecMessage.GIVE_OSD_NAME);
- hdmiCecClient.checkOutputDoesNotContainMessage(CecDevice.PLAYBACK_1,
- CecMessage.SET_OSD_NAME);
- hdmiCecClient.sendCecMessage(CecDevice.BROADCAST, CecMessage.GIVE_OSD_NAME);
- hdmiCecClient.checkOutputDoesNotContainMessage(CecDevice.BROADCAST,
- CecMessage.SET_OSD_NAME);
+ hdmiCecClient.sendCecMessage(LogicalAddress.PLAYBACK_1, CecOperand.GIVE_OSD_NAME);
+ hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.PLAYBACK_1,
+ CecOperand.SET_OSD_NAME);
+ hdmiCecClient.sendCecMessage(LogicalAddress.BROADCAST, CecOperand.GIVE_OSD_NAME);
+ hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.BROADCAST,
+ CecOperand.SET_OSD_NAME);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecLogicalAddressTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecLogicalAddressTest.java
index 83c9120d0ac..d48a6cd8b56 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecLogicalAddressTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecLogicalAddressTest.java
@@ -16,29 +16,43 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
/** HDMI CEC test to verify physical address after device reboot (Section 10.2.3) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecLogicalAddressTest extends BaseHostJUnit4Test {
- private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
+
+ private static final LogicalAddress PLAYBACK_DEVICE = LogicalAddress.PLAYBACK_1;
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 10.2.3-1
@@ -50,7 +64,7 @@ public final class HdmiCecLogicalAddressTest extends BaseHostJUnit4Test {
ITestDevice device = getDevice();
device.executeShellCommand("reboot");
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.REPORT_PHYSICAL_ADDRESS);
- assertEquals(PLAYBACK_DEVICE, hdmiCecClient.getSourceFromMessage(message));
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_PHYSICAL_ADDRESS);
+ assertThat(CecMessage.getSource(message)).isEqualTo(PLAYBACK_DEVICE);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecOneTouchPlayTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecOneTouchPlayTest.java
index a4ca3d246f6..56a7df25381 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecOneTouchPlayTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecOneTouchPlayTest.java
@@ -16,17 +16,21 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -36,9 +40,32 @@ public final class HdmiCecOneTouchPlayTest extends BaseHostJUnit4Test {
private static final int PHYSICAL_ADDRESS = 0x1000;
+ /** Intent to launch the remote pairing activity */
+ private static final String ACTION_CONNECT_INPUT_NORMAL =
+ "com.google.android.intent.action.CONNECT_INPUT";
+
+ /** Package name of the Settings app */
+ private static final String SETTINGS_PACKAGE =
+ "com.android.tv.settings";
+
+ /** The command to broadcast an intent. */
+ private static final String START_COMMAND = "am start -a ";
+
+ /** The command to stop an app. */
+ private static final String FORCE_STOP_COMMAND = "am force-stop ";
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
+
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.1-1
@@ -48,9 +75,25 @@ public final class HdmiCecOneTouchPlayTest extends BaseHostJUnit4Test {
@Test
public void cect_11_2_1_1_OneTouchPlay() throws Exception {
ITestDevice device = getDevice();
+ device.reboot();
device.executeShellCommand("input keyevent KEYCODE_HOME");
- hdmiCecClient.checkExpectedOutput(CecDevice.TV, CecMessage.TEXT_VIEW_ON);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.ACTIVE_SOURCE);
- assertEquals(PHYSICAL_ADDRESS, hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.TEXT_VIEW_ON);
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.ACTIVE_SOURCE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(PHYSICAL_ADDRESS);
+ }
+
+ /**
+ * Tests that the device sends a <TEXT_VIEW_ON> when the pairing activity is started on
+ * device, followed by a <ACTIVE_SOURCE> message.
+ */
+ @Test
+ public void cect_PairingActivity_OneTouchPlay() throws Exception {
+ ITestDevice device = getDevice();
+ device.reboot();
+ device.executeShellCommand(START_COMMAND + ACTION_CONNECT_INPUT_NORMAL);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.TEXT_VIEW_ON);
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.ACTIVE_SOURCE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(PHYSICAL_ADDRESS);
+ device.executeShellCommand(FORCE_STOP_COMMAND + SETTINGS_PACKAGE);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPhysicalAddressTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPhysicalAddressTest.java
index 91280e7204b..bae84906ef0 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPhysicalAddressTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPhysicalAddressTest.java
@@ -16,18 +16,22 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -35,9 +39,18 @@ import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecPhysicalAddressTest extends BaseHostJUnit4Test {
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
+
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 10.1.2-1
@@ -49,9 +62,9 @@ public final class HdmiCecPhysicalAddressTest extends BaseHostJUnit4Test {
ITestDevice device = getDevice();
device.executeShellCommand("reboot");
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.REPORT_PHYSICAL_ADDRESS);
- int physicalAddress = hdmiCecClient.getParamsFromMessage(message,
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_PHYSICAL_ADDRESS);
+ int physicalAddress = CecMessage.getParams(message,
HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH);
- assertEquals(HdmiCecConstants.PHYSICAL_ADDRESS, physicalAddress);
+ assertThat(HdmiCecConstants.PHYSICAL_ADDRESS).isEqualTo(physicalAddress);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java
index 911d2335846..2d8d3ac7313 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java
@@ -16,18 +16,22 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -39,12 +43,24 @@ public final class HdmiCecPowerStatusTest extends BaseHostJUnit4Test {
private static final int ON = 0x0;
private static final int OFF = 0x1;
+ private static final int IN_TRANSITION_TO_STANDBY = 0x3;
+ private static final int SLEEP_TIMESTEP_SECONDS = 1;
private static final int WAIT_TIME = 5;
+ private static final int MAX_SLEEP_TIME = 8;
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.14-1
@@ -56,10 +72,10 @@ public final class HdmiCecPowerStatusTest extends BaseHostJUnit4Test {
ITestDevice device = getDevice();
/* Make sure the device is not booting up/in standby */
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GIVE_POWER_STATUS);
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV,
- CecMessage.REPORT_POWER_STATUS);
- assertEquals(ON, hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.REPORT_POWER_STATUS);
+ assertThat(CecMessage.getParams(message)).isEqualTo(ON);
}
/**
@@ -73,12 +89,20 @@ public final class HdmiCecPowerStatusTest extends BaseHostJUnit4Test {
try {
/* Make sure the device is not booting up/in standby */
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
+ /* Home Key to prevent device from going to deep suspend state */
+ device.executeShellCommand("input keyevent KEYCODE_HOME");
device.executeShellCommand("input keyevent KEYCODE_SLEEP");
TimeUnit.SECONDS.sleep(WAIT_TIME);
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GIVE_POWER_STATUS);
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV,
- CecMessage.REPORT_POWER_STATUS);
- assertEquals(OFF, hdmiCecClient.getParamsFromMessage(message));
+ int waitTimeSeconds = WAIT_TIME;
+ int powerStatus;
+ do {
+ TimeUnit.SECONDS.sleep(SLEEP_TIMESTEP_SECONDS);
+ waitTimeSeconds += SLEEP_TIMESTEP_SECONDS;
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
+ powerStatus = CecMessage.getParams(hdmiCecClient.checkExpectedOutput(
+ LogicalAddress.TV, CecOperand.REPORT_POWER_STATUS));
+ } while (powerStatus == IN_TRANSITION_TO_STANDBY && waitTimeSeconds <= MAX_SLEEP_TIME);
+ assertThat(powerStatus).isEqualTo(OFF);
} finally {
/* Wake up the device */
device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
index 9ac7eaba6ba..b0d927dcb7b 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
@@ -16,23 +16,22 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
-
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogHelper;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
-import java.util.Scanner;
-import java.util.concurrent.TimeUnit;
-
/** HDMI CEC test to check if the device reports power status correctly (Section 11.2.13) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Test {
@@ -55,29 +54,18 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
*/
private static final String CLEAR_COMMAND = String.format("pm clear %s", PACKAGE);
- private static final int WAIT_TIME = 10;
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
-
- private void lookForLog(String expectedOut) throws Exception {
- ITestDevice device = getDevice();
- TimeUnit.SECONDS.sleep(WAIT_TIME);
- String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
- // Search for string.
- String testString = "";
- Scanner in = new Scanner(logs);
- while (in.hasNextLine()) {
- String line = in.nextLine();
- if(line.startsWith("I/" + CLASS)) {
- testString = line.split(":")[1].trim();
- break;
- }
- }
- device.executeAdbCommand("logcat", "-c");
- assertEquals(expectedOut, testString);
- }
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.13-1
@@ -93,24 +81,25 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
device.executeAdbCommand("logcat", "-c");
// Start the APK and wait for it to complete.
device.executeShellCommand(START_COMMAND);
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_UP, false);
- lookForLog("Short press KEYCODE_DPAD_UP");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_DOWN, false);
- lookForLog("Short press KEYCODE_DPAD_DOWN");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_LEFT, false);
- lookForLog("Short press KEYCODE_DPAD_LEFT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_RIGHT, false);
- lookForLog("Short press KEYCODE_DPAD_RIGHT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_SELECT, false);
- lookForLog("Short press KEYCODE_DPAD_CENTER");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS,
+ "Short press KEYCODE_DPAD_CENTER", "Short press KEYCODE_ENTER");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_BACK, false);
- lookForLog("Short press KEYCODE_BACK");
+ LogHelper.assertLog(getDevice(), CLASS, "Short press KEYCODE_BACK");
}
/**
@@ -127,23 +116,24 @@ public final class HdmiCecRemoteControlPassThroughTest extends BaseHostJUnit4Tes
device.executeAdbCommand("logcat", "-c");
// Start the APK and wait for it to complete.
device.executeShellCommand(START_COMMAND);
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_UP, true);
- lookForLog("Long press KEYCODE_DPAD_UP");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_UP");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_DOWN, true);
- lookForLog("Long press KEYCODE_DPAD_DOWN");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_DOWN");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_LEFT, true);
- lookForLog("Long press KEYCODE_DPAD_LEFT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_LEFT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_RIGHT, true);
- lookForLog("Long press KEYCODE_DPAD_RIGHT");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_DPAD_RIGHT");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_SELECT, true);
- lookForLog("Long press KEYCODE_DPAD_CENTER");
- hdmiCecClient.sendUserControlPressAndRelease(CecDevice.TV, CecDevice.PLAYBACK_1,
+ LogHelper.assertLog(getDevice(), CLASS,
+ "Long press KEYCODE_DPAD_CENTER", "Long press KEYCODE_ENTER");
+ hdmiCecClient.sendUserControlPressAndRelease(LogicalAddress.TV, LogicalAddress.PLAYBACK_1,
HdmiCecConstants.CEC_CONTROL_BACK, true);
- lookForLog("Long press KEYCODE_BACK");
+ LogHelper.assertLog(getDevice(), CLASS, "Long press KEYCODE_BACK");
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
index 4fd2a8968ce..8bec365451a 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
@@ -16,18 +16,22 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -39,9 +43,18 @@ public final class HdmiCecRoutingControlTest extends BaseHostJUnit4Test {
private static final int PHYSICAL_ADDRESS = 0x1000;
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
+
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.2-1
@@ -52,15 +65,14 @@ public final class HdmiCecRoutingControlTest extends BaseHostJUnit4Test {
public void cect_11_2_2_1_SetStreamPathToDut() throws Exception {
final long hdmi2Address = 0x2000;
/* Switch to HDMI2. Setup assumes DUT is connected to HDMI1. */
- hdmiCecClient.sendCecMessage(CecDevice.PLAYBACK_2, CecDevice.BROADCAST,
- CecMessage.ACTIVE_SOURCE, hdmiCecClient.formatParams(hdmi2Address));
+ hdmiCecClient.sendCecMessage(LogicalAddress.PLAYBACK_2, LogicalAddress.BROADCAST,
+ CecOperand.ACTIVE_SOURCE, CecMessage.formatParams(hdmi2Address));
TimeUnit.SECONDS.sleep(3);
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecDevice.BROADCAST,
- CecMessage.SET_STREAM_PATH,
- hdmiCecClient.formatParams(HdmiCecConstants.PHYSICAL_ADDRESS));
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.ACTIVE_SOURCE);
- assertEquals(HdmiCecConstants.PHYSICAL_ADDRESS,
- hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.SET_STREAM_PATH,
+ CecMessage.formatParams(HdmiCecConstants.PHYSICAL_ADDRESS));
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.ACTIVE_SOURCE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(PHYSICAL_ADDRESS);
}
/**
@@ -72,10 +84,10 @@ public final class HdmiCecRoutingControlTest extends BaseHostJUnit4Test {
public void cect_11_2_2_2_RequestActiveSource() throws Exception {
ITestDevice device = getDevice();
device.executeShellCommand("input keyevent KEYCODE_HOME");
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecDevice.BROADCAST,
- CecMessage.REQUEST_ACTIVE_SOURCE);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.ACTIVE_SOURCE);
- assertEquals(PHYSICAL_ADDRESS, hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.REQUEST_ACTIVE_SOURCE);
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.ACTIVE_SOURCE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(PHYSICAL_ADDRESS);
}
/**
@@ -89,10 +101,9 @@ public final class HdmiCecRoutingControlTest extends BaseHostJUnit4Test {
try {
device.executeShellCommand("input keyevent KEYCODE_HOME");
device.executeShellCommand("input keyevent KEYCODE_SLEEP");
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV,
- CecMessage.INACTIVE_SOURCE);
- assertEquals(HdmiCecConstants.PHYSICAL_ADDRESS,
- hdmiCecClient.getParamsFromMessage(message));
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.INACTIVE_SOURCE);
+ assertThat(CecMessage.getParams(message)).isEqualTo(PHYSICAL_ADDRESS);
} finally {
/* Wake up the device */
device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecStartupTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecStartupTest.java
new file mode 100644
index 00000000000..06b62f93b3a
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecStartupTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.cts.playback;
+
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assume.assumeTrue;
+
+import android.hdmicec.cts.CecOperand;
+import android.hdmicec.cts.HdmiCecClientWrapper;
+import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * HDMI CEC test to verify physical address after device reboot (Section 10.2.3)
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecStartupTest extends BaseHostJUnit4Test {
+
+ private static final LogicalAddress PLAYBACK_DEVICE = LogicalAddress.PLAYBACK_1;
+ private static final ImmutableList<CecOperand> necessaryMessages =
+ new ImmutableList.Builder<CecOperand>()
+ .add(CecOperand.REPORT_PHYSICAL_ADDRESS, CecOperand.CEC_VERSION,
+ CecOperand.DEVICE_VENDOR_ID, CecOperand.GIVE_POWER_STATUS).build();
+ private static final ImmutableList<CecOperand> permissibleMessages =
+ new ImmutableList.Builder<CecOperand>()
+ .add(CecOperand.VENDOR_COMMAND, CecOperand.GIVE_DEVICE_VENDOR_ID,
+ CecOperand.SET_OSD_NAME, CecOperand.GIVE_OSD_NAME).build();
+
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
+
+ @Rule
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ PLAYBACK_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
+
+ /**
+ * Tests that the device sends all the messages that should be sent on startup. It also ensures
+ * that only the device only sends messages which are allowed by the spec.
+ */
+ @Test
+ public void cectVerifyStartupMessages() throws Exception {
+ ITestDevice device = getDevice();
+
+ /* Make sure device is playback only. Not applicable to playback/audio combinations */
+ String deviceTypeCsv = device.executeShellCommand("getprop ro.hdmi.device_type").trim();
+ assumeTrue(deviceTypeCsv.equals(LogicalAddress.PLAYBACK_1.getDeviceType()));
+
+ device.executeShellCommand("reboot");
+ device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
+ /* Monitor CEC messages for 20s after reboot */
+ final List<CecOperand> messagesReceived =
+ hdmiCecClient.getAllMessages(LogicalAddress.PLAYBACK_1, 20);
+
+ /* Predicate to apply on necessaryMessages to ensure that all necessaryMessages are received. */
+ final Predicate<CecOperand> notReceived = new Predicate<CecOperand>() {
+ @Override
+ public boolean apply(@Nullable CecOperand cecOperand) {
+ return !messagesReceived.contains(cecOperand);
+ }
+ };
+
+ /* Predicate to apply on messagesReceived to ensure all messages received are permissible. */
+ final Predicate<CecOperand> notAllowed = new Predicate<CecOperand>() {
+ @Override
+ public boolean apply(@Nullable CecOperand cecOperand) {
+ return !(permissibleMessages.contains(cecOperand) || necessaryMessages.contains(cecOperand));
+ }
+ };
+
+ assertWithMessage("Some necessary messages are missing").
+ that(filter(necessaryMessages, notReceived)).isEmpty();
+
+ assertWithMessage("Some non-permissible messages received").
+ that(filter(messagesReceived, notAllowed)).isEmpty();
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
index 5162a271490..229e807671c 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
@@ -16,31 +16,44 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
-import java.util.concurrent.TimeUnit;
-
/** HDMI CEC test to verify system audio control commands (Section 11.2.15) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecSystemAudioControlTest extends BaseHostJUnit4Test {
- private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
- @Rule
+ private static final LogicalAddress PLAYBACK_DEVICE = LogicalAddress.PLAYBACK_1;
+
public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this, "-t", "a");
+ new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1, "-t", "a");
+
+ @Rule
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ PLAYBACK_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.15-10
@@ -49,10 +62,12 @@ public final class HdmiCecSystemAudioControlTest extends BaseHostJUnit4Test {
@Test
public void cect_11_2_15_10_GiveSystemAudioModeStatus() throws Exception {
ITestDevice device = getDevice();
+ /* Home Key to prevent device from going to deep suspend state */
+ device.executeShellCommand("input keyevent KEYCODE_HOME");
device.executeShellCommand("input keyevent KEYCODE_SLEEP");
device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
- hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
- CecMessage.GIVE_SYSTEM_AUDIO_MODE_STATUS);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.AUDIO_SYSTEM,
+ CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
}
/**
@@ -64,22 +79,22 @@ public final class HdmiCecSystemAudioControlTest extends BaseHostJUnit4Test {
@Test
public void cect_11_2_15_11_VolumeUpDownUserControlPressed() throws Exception {
ITestDevice device = getDevice();
- hdmiCecClient.sendCecMessage(CecDevice.AUDIO_SYSTEM, CecDevice.BROADCAST,
- CecMessage.SET_SYSTEM_AUDIO_MODE, CecMessage.formatParams(1));
+ hdmiCecClient.sendCecMessage(LogicalAddress.AUDIO_SYSTEM, LogicalAddress.BROADCAST,
+ CecOperand.SET_SYSTEM_AUDIO_MODE, CecMessage.formatParams(1));
device.executeShellCommand("input keyevent KEYCODE_VOLUME_UP");
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
- CecMessage.USER_CONTROL_PRESSED);
- assertEquals(HdmiCecConstants.CEC_CONTROL_VOLUME_UP,
- hdmiCecClient.getParamsFromMessage(message));
- hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM, CecMessage.USER_CONTROL_RELEASED);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.AUDIO_SYSTEM,
+ CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(message))
+ .isEqualTo(HdmiCecConstants.CEC_CONTROL_VOLUME_UP);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.AUDIO_SYSTEM, CecOperand.USER_CONTROL_RELEASED);
device.executeShellCommand("input keyevent KEYCODE_VOLUME_DOWN");
- message = hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
- CecMessage.USER_CONTROL_PRESSED);
- assertEquals(HdmiCecConstants.CEC_CONTROL_VOLUME_DOWN,
- hdmiCecClient.getParamsFromMessage(message));
- hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM, CecMessage.USER_CONTROL_RELEASED);
+ message = hdmiCecClient.checkExpectedOutput(LogicalAddress.AUDIO_SYSTEM,
+ CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(message))
+ .isEqualTo(HdmiCecConstants.CEC_CONTROL_VOLUME_DOWN);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.AUDIO_SYSTEM, CecOperand.USER_CONTROL_RELEASED);
}
/**
@@ -91,13 +106,12 @@ public final class HdmiCecSystemAudioControlTest extends BaseHostJUnit4Test {
@Test
public void cect_11_2_15_12_MuteUserControlPressed() throws Exception {
ITestDevice device = getDevice();
- hdmiCecClient.sendCecMessage(CecDevice.AUDIO_SYSTEM, CecDevice.BROADCAST,
- CecMessage.SET_SYSTEM_AUDIO_MODE, CecMessage.formatParams(1));
+ hdmiCecClient.sendCecMessage(LogicalAddress.AUDIO_SYSTEM, LogicalAddress.BROADCAST,
+ CecOperand.SET_SYSTEM_AUDIO_MODE, CecMessage.formatParams(1));
device.executeShellCommand("input keyevent KEYCODE_VOLUME_MUTE");
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM,
- CecMessage.USER_CONTROL_PRESSED);
- assertEquals(HdmiCecConstants.CEC_CONTROL_MUTE,
- hdmiCecClient.getParamsFromMessage(message));
- hdmiCecClient.checkExpectedOutput(CecDevice.AUDIO_SYSTEM, CecMessage.USER_CONTROL_RELEASED);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.AUDIO_SYSTEM,
+ CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(message)).isEqualTo(HdmiCecConstants.CEC_CONTROL_MUTE);
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.AUDIO_SYSTEM, CecOperand.USER_CONTROL_RELEASED);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java
index c6df9f7f0ca..5e59a8f4870 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java
@@ -16,20 +16,25 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assume.assumeTrue;
import android.hdmicec.cts.CecClientMessage;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -42,9 +47,18 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
private static final String PROPERTY_LOCALE = "persist.sys.locale";
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
+
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ LogicalAddress.PLAYBACK_1.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.6-1
@@ -52,7 +66,7 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
*/
@Test
public void cect_11_2_6_1_Ack() throws Exception {
- String command = CecClientMessage.POLL + " " + CecDevice.PLAYBACK_1;
+ String command = CecClientMessage.POLL + " " + LogicalAddress.PLAYBACK_1;
String expectedOutput = "POLL sent";
hdmiCecClient.sendConsoleMessage(command);
if (!hdmiCecClient.checkConsoleOutput(expectedOutput)) {
@@ -67,13 +81,13 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
*/
@Test
public void cect_11_2_6_2_GivePhysicalAddress() throws Exception {
- hdmiCecClient.sendCecMessage(CecMessage.GIVE_PHYSICAL_ADDRESS);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.REPORT_PHYSICAL_ADDRESS);
+ hdmiCecClient.sendCecMessage(CecOperand.GIVE_PHYSICAL_ADDRESS);
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_PHYSICAL_ADDRESS);
/* The checkExpectedOutput has already verified the first 4 nibbles of the message. We
* have to verify the last 6 nibbles */
- int receivedParams = hdmiCecClient.getParamsFromMessage(message);
- assertEquals(HdmiCecConstants.PHYSICAL_ADDRESS, receivedParams >> 8);
- assertEquals(HdmiCecConstants.PLAYBACK_DEVICE_TYPE, receivedParams & 0xFF);
+ int receivedParams = CecMessage.getParams(message);
+ assertThat(HdmiCecConstants.PHYSICAL_ADDRESS).isEqualTo(receivedParams >> 8);
+ assertThat(HdmiCecConstants.PLAYBACK_DEVICE_TYPE).isEqualTo(receivedParams & 0xFF);
}
/**
@@ -82,11 +96,10 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
*/
@Test
public void cect_11_2_6_6_GiveCecVersion() throws Exception {
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GET_CEC_VERSION);
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV,
- CecMessage.CEC_VERSION);
-
- assertEquals(CEC_VERSION_NUMBER, hdmiCecClient.getParamsFromMessage(message));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, CecOperand.GET_CEC_VERSION);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
+ CecOperand.CEC_VERSION);
+ assertThat(CecMessage.getParams(message)).isEqualTo(CEC_VERSION_NUMBER);
}
/**
@@ -95,11 +108,11 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
*/
@Test
public void cect_11_2_6_7_GetMenuLanguage() throws Exception {
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecMessage.GET_MENU_LANGUAGE);
- String message = hdmiCecClient.checkExpectedOutput(CecDevice.TV, CecMessage.FEATURE_ABORT);
- int abortedOpcode = hdmiCecClient.getParamsFromMessage(message,
- CecMessage.GET_MENU_LANGUAGE.toString().length());
- assertEquals(CecMessage.getMessage(abortedOpcode), CecMessage.GET_MENU_LANGUAGE);
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, CecOperand.GET_MENU_LANGUAGE);
+ String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.FEATURE_ABORT);
+ int abortedOpcode = CecMessage.getParams(message,
+ CecOperand.GET_MENU_LANGUAGE.toString().length());
+ assertThat(CecOperand.getOperand(abortedOpcode)).isEqualTo(CecOperand.GET_MENU_LANGUAGE);
}
private String getSystemLocale() throws Exception {
@@ -133,9 +146,9 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
final String language = originalLanguage.equals("spa") ? "eng" : "spa";
final String newLanguage = originalLanguage.equals("spa") ? "en" : "es";
try {
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecDevice.BROADCAST,
- CecMessage.SET_MENU_LANGUAGE, hdmiCecClient.convertStringToHexParams(language));
- assertEquals(newLanguage, extractLanguage(getSystemLocale()));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.SET_MENU_LANGUAGE, CecMessage.convertStringToHexParams(language));
+ assertThat(extractLanguage(getSystemLocale())).isEqualTo(newLanguage);
} finally {
setSystemLocale(locale);
}
@@ -152,9 +165,9 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
final String originalLanguage = extractLanguage(locale);
final String language = "spb";
try {
- hdmiCecClient.sendCecMessage(CecDevice.TV, CecDevice.BROADCAST,
- CecMessage.SET_MENU_LANGUAGE, hdmiCecClient.convertStringToHexParams(language));
- assertEquals(originalLanguage, extractLanguage(getSystemLocale()));
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.SET_MENU_LANGUAGE, CecMessage.convertStringToHexParams(language));
+ assertThat(extractLanguage(getSystemLocale())).isEqualTo(originalLanguage);
} finally {
setSystemLocale(locale);
}
@@ -172,9 +185,9 @@ public final class HdmiCecSystemInformationTest extends BaseHostJUnit4Test {
final String originalLanguage = extractLanguage(locale);
final String language = originalLanguage.equals("spa") ? "eng" : "spa";
try {
- hdmiCecClient.sendCecMessage(CecDevice.RECORDER_1, CecDevice.BROADCAST,
- CecMessage.SET_MENU_LANGUAGE, hdmiCecClient.convertStringToHexParams(language));
- assertEquals(originalLanguage, extractLanguage(getSystemLocale()));
+ hdmiCecClient.sendCecMessage(LogicalAddress.RECORDER_1, LogicalAddress.BROADCAST,
+ CecOperand.SET_MENU_LANGUAGE, CecMessage.convertStringToHexParams(language));
+ assertThat(extractLanguage(getSystemLocale())).isEqualTo(originalLanguage);
} finally {
setSystemLocale(locale);
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemStandbyTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemStandbyTest.java
index 1aa8fe47f2d..369542e3138 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemStandbyTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemStandbyTest.java
@@ -16,20 +16,21 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
-import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.device.TestDeviceState;
-import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -38,14 +39,24 @@ import java.util.concurrent.TimeUnit;
/** HDMI CEC test to verify the device handles standby correctly (Section 11.2.3) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecSystemStandbyTest extends BaseHostJUnit4Test {
- private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
+
+ private static final LogicalAddress PLAYBACK_DEVICE = LogicalAddress.PLAYBACK_1;
private static final String HDMI_CONTROL_DEVICE_AUTO_OFF =
"hdmi_control_auto_device_off_enabled";
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
+
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ PLAYBACK_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
private boolean setHdmiControlDeviceAutoOff(boolean turnOn) throws Exception {
ITestDevice device = getDevice();
@@ -58,16 +69,16 @@ public final class HdmiCecSystemStandbyTest extends BaseHostJUnit4Test {
return val.equals("1") ? true : false;
}
- private void checkDeviceAsleepAfterStandbySent(CecDevice source, CecDevice destination)
+ private void checkDeviceAsleepAfterStandbySent(LogicalAddress source, LogicalAddress destination)
throws Exception {
ITestDevice device = getDevice();
try {
device.executeShellCommand("input keyevent KEYCODE_HOME");
TimeUnit.SECONDS.sleep(5);
- hdmiCecClient.sendCecMessage(source, destination, CecMessage.STANDBY);
+ hdmiCecClient.sendCecMessage(source, destination, CecOperand.STANDBY);
TimeUnit.SECONDS.sleep(5);
String wakeState = device.executeShellCommand("dumpsys power | grep mWakefulness=");
- assertEquals("mWakefulness=Asleep", wakeState.trim());
+ assertThat(wakeState.trim()).isEqualTo("mWakefulness=Asleep");
} finally {
/* Wake up the device */
device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
@@ -84,19 +95,19 @@ public final class HdmiCecSystemStandbyTest extends BaseHostJUnit4Test {
getDevice().waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
try {
TimeUnit.SECONDS.sleep(5);
- checkDeviceAsleepAfterStandbySent(CecDevice.TV, CecDevice.BROADCAST);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.TV, LogicalAddress.BROADCAST);
/* Wake up the TV */
- hdmiCecClient.sendConsoleMessage("on " + CecDevice.TV);
- checkDeviceAsleepAfterStandbySent(CecDevice.RECORDER_1, CecDevice.BROADCAST);
+ hdmiCecClient.sendConsoleMessage("on " + LogicalAddress.TV);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.RECORDER_1, LogicalAddress.BROADCAST);
/* Wake up the TV */
- hdmiCecClient.sendConsoleMessage("on " + CecDevice.TV);
- checkDeviceAsleepAfterStandbySent(CecDevice.AUDIO_SYSTEM, CecDevice.BROADCAST);
+ hdmiCecClient.sendConsoleMessage("on " + LogicalAddress.TV);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.AUDIO_SYSTEM, LogicalAddress.BROADCAST);
/* Wake up the TV */
- hdmiCecClient.sendConsoleMessage("on " + CecDevice.TV);
- checkDeviceAsleepAfterStandbySent(CecDevice.PLAYBACK_2, CecDevice.BROADCAST);
+ hdmiCecClient.sendConsoleMessage("on " + LogicalAddress.TV);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.PLAYBACK_2, LogicalAddress.BROADCAST);
} finally {
/* Wake up the TV */
- hdmiCecClient.sendConsoleMessage("on " + CecDevice.TV);
+ hdmiCecClient.sendConsoleMessage("on " + LogicalAddress.TV);
}
}
@@ -108,11 +119,11 @@ public final class HdmiCecSystemStandbyTest extends BaseHostJUnit4Test {
public void cect_11_2_3_3_HandleAddressedStandby() throws Exception {
getDevice().executeShellCommand("reboot");
getDevice().waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
- checkDeviceAsleepAfterStandbySent(CecDevice.TV, CecDevice.PLAYBACK_1);
- checkDeviceAsleepAfterStandbySent(CecDevice.RECORDER_1, CecDevice.PLAYBACK_1);
- checkDeviceAsleepAfterStandbySent(CecDevice.AUDIO_SYSTEM, CecDevice.PLAYBACK_1);
- checkDeviceAsleepAfterStandbySent(CecDevice.PLAYBACK_2, CecDevice.PLAYBACK_1);
- checkDeviceAsleepAfterStandbySent(CecDevice.BROADCAST, CecDevice.PLAYBACK_1);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.TV, LogicalAddress.PLAYBACK_1);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.RECORDER_1, LogicalAddress.PLAYBACK_1);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.AUDIO_SYSTEM, LogicalAddress.PLAYBACK_1);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.PLAYBACK_2, LogicalAddress.PLAYBACK_1);
+ checkDeviceAsleepAfterStandbySent(LogicalAddress.BROADCAST, LogicalAddress.PLAYBACK_1);
}
/**
@@ -125,7 +136,7 @@ public final class HdmiCecSystemStandbyTest extends BaseHostJUnit4Test {
boolean wasOn = setHdmiControlDeviceAutoOff(false);
try {
device.executeShellCommand("input keyevent KEYCODE_SLEEP");
- hdmiCecClient.checkOutputDoesNotContainMessage(CecDevice.BROADCAST, CecMessage.STANDBY);
+ hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.BROADCAST, CecOperand.STANDBY);
device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
} finally {
setHdmiControlDeviceAutoOff(wasOn);
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecVendorCommandsTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecVendorCommandsTest.java
index df9bc5ae4e8..edff394ba38 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecVendorCommandsTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecVendorCommandsTest.java
@@ -16,30 +16,44 @@
package android.hdmicec.cts.playback;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
-import android.hdmicec.cts.CecDevice;
import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecClientWrapper;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+import android.hdmicec.cts.RequiredPropertyRule;
+import android.hdmicec.cts.RequiredFeatureRule;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.junit.Test;
/** HDMI CEC test to verify device vendor specific commands (Section 11.2.9) */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecVendorCommandsTest extends BaseHostJUnit4Test {
- private static final CecDevice PLAYBACK_DEVICE = CecDevice.PLAYBACK_1;
+
+ private static final LogicalAddress PLAYBACK_DEVICE = LogicalAddress.PLAYBACK_1;
private static final int INCORRECT_VENDOR_ID = 0x0;
+ public HdmiCecClientWrapper hdmiCecClient = new HdmiCecClientWrapper(LogicalAddress.PLAYBACK_1);
+
@Rule
- public HdmiCecClientWrapper hdmiCecClient =
- new HdmiCecClientWrapper(CecDevice.PLAYBACK_1, this);
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(new RequiredFeatureRule(this, LogicalAddress.HDMI_CEC_FEATURE))
+ .around(new RequiredFeatureRule(this, LogicalAddress.LEANBACK_FEATURE))
+ .around(RequiredPropertyRule.asCsvContainsValue(
+ this,
+ LogicalAddress.HDMI_DEVICE_TYPE_PROPERTY,
+ PLAYBACK_DEVICE.getDeviceType()))
+ .around(hdmiCecClient);
/**
* Test 11.2.9-1
@@ -48,10 +62,14 @@ public final class HdmiCecVendorCommandsTest extends BaseHostJUnit4Test {
*/
@Test
public void cect_11_2_9_1_GiveDeviceVendorId() throws Exception {
- for (CecDevice cecDevice : CecDevice.values()) {
- hdmiCecClient.sendCecMessage(cecDevice, CecMessage.GIVE_DEVICE_VENDOR_ID);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.DEVICE_VENDOR_ID);
- assertNotEquals(INCORRECT_VENDOR_ID, hdmiCecClient.getParamsFromMessage(message));
+ for (LogicalAddress logicalAddress : LogicalAddress.values()) {
+ // Skip the logical address of this device
+ if (logicalAddress == PLAYBACK_DEVICE) {
+ continue;
+ }
+ hdmiCecClient.sendCecMessage(logicalAddress, CecOperand.GIVE_DEVICE_VENDOR_ID);
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.DEVICE_VENDOR_ID);
+ assertThat(CecMessage.getParams(message)).isNotEqualTo(INCORRECT_VENDOR_ID);
}
}
@@ -65,7 +83,7 @@ public final class HdmiCecVendorCommandsTest extends BaseHostJUnit4Test {
ITestDevice device = getDevice();
device.executeShellCommand("reboot");
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
- String message = hdmiCecClient.checkExpectedOutput(CecMessage.DEVICE_VENDOR_ID);
- assertNotEquals(INCORRECT_VENDOR_ID, hdmiCecClient.getParamsFromMessage(message));
+ String message = hdmiCecClient.checkExpectedOutput(CecOperand.DEVICE_VENDOR_ID);
+ assertThat(CecMessage.getParams(message)).isNotEqualTo(INCORRECT_VENDOR_ID);
}
}