Add tests for HdmiAudioSystemClient
Bug: 110430593
Test: atest android.hardware.hdmi
Change-Id: Id988ed8180b4728e96423d5d0ca38e017b01a97f
diff --git a/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java b/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
index c1606f9d..9bebbd2 100644
--- a/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
+++ b/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
@@ -15,9 +15,13 @@
*/
package android.hardware.hdmi;
+import android.annotation.Nullable;
import android.os.Handler;
import android.os.RemoteException;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+
/**
* HdmiAudioSystemClient represents HDMI-CEC logical device of type Audio System in the Android
* system which acts as an audio system device such as sound bar.
@@ -28,12 +32,11 @@
* @hide
*/
public final class HdmiAudioSystemClient extends HdmiClient {
- // TODO(b/110430593): add tests for this class
private static final String TAG = "HdmiAudioSystemClient";
private static final int REPORT_AUDIO_STATUS_INTERVAL_MS = 500;
- private final Handler mHandler = new Handler();
+ private final Handler mHandler;
private boolean mCanSendAudioStatus = true;
private boolean mPendingReportAudioStatus;
@@ -41,9 +44,15 @@
private int mLastMaxVolume;
private boolean mLastIsMute;
+ @VisibleForTesting(visibility = Visibility.PACKAGE)
+ public HdmiAudioSystemClient(IHdmiControlService service) {
+ this(service, null);
+ }
- /* package */ HdmiAudioSystemClient(IHdmiControlService service) {
+ @VisibleForTesting(visibility = Visibility.PACKAGE)
+ public HdmiAudioSystemClient(IHdmiControlService service, @Nullable Handler handler) {
super(service);
+ mHandler = handler == null ? new Handler() : handler;
}
/** @hide */
diff --git a/core/tests/hdmitests/Android.mk b/core/tests/hdmitests/Android.mk
new file mode 100644
index 0000000..e0d2c09
--- /dev/null
+++ b/core/tests/hdmitests/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test frameworks-base-testutils
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := HdmiCecTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/hdmitests/AndroidManifest.xml b/core/tests/hdmitests/AndroidManifest.xml
new file mode 100644
index 0000000..1460b41
--- /dev/null
+++ b/core/tests/hdmitests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.hardware.hdmi"
+ android:sharedUserId="android.uid.system" >
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.hardware.hdmi"
+ android:label="HDMI CEC Tests"/>
+
+</manifest>
\ No newline at end of file
diff --git a/core/tests/hdmitests/AndroidTest.xml b/core/tests/hdmitests/AndroidTest.xml
new file mode 100644
index 0000000..7ef672d
--- /dev/null
+++ b/core/tests/hdmitests/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<configuration description="Runs HDMI CEC Tests.">
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-suite-tag" value="apct-instrumentation"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="HdmiCecTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="HdmiTests"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.hardware.hdmi" />
+ <option name="hidden-api-checks" value="false"/>
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
new file mode 100644
index 0000000..7b76a08
--- /dev/null
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import android.os.Handler;
+import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
+import android.util.Log;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link HdmiAudioSystemClient}
+ */
+@RunWith(JUnit4.class)
+@SmallTest
+public class HdmiAudioSystemClientTest {
+ private static final String TAG = "HdmiAudioSystemClientTe";
+
+ private HdmiAudioSystemClient mHdmiAudioSystemClient;
+ private TestLooper mTestLooper;
+ private int mVolume;
+ private int mMaxVolume;
+ private boolean mIsMute;
+
+ @Before
+ public void before() {
+ Log.d(TAG, "before()");
+ IHdmiControlService mService = new TestHdmiControlService();
+ mTestLooper = new TestLooper();
+ mHdmiAudioSystemClient =
+ new HdmiAudioSystemClient(mService, new Handler(mTestLooper.getLooper()));
+ resetVariables();
+ }
+
+ @Test
+ public void testSingleCommand() {
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 50, 100, false);
+ assertAudioStatus(50, 100, false);
+ }
+
+ @Test
+ public void testMultipleCommands_longTimeBetweenCalls() {
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 50, 100, false);
+ assertAudioStatus(50, 100, false);
+ mTestLooper.moveTimeForward(500);
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 60, 100, false);
+ assertAudioStatus(60, 100, false);
+ }
+
+ @Test
+ public void testMultipleCommands_shortTimeBetweenCalls() {
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+ assertAudioStatus(1, 100, false);
+
+ mTestLooper.moveTimeForward(100); // current time: 100ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 10, 100, false);
+ assertAudioStatus(1, 100, false); // command not sent, no change
+
+ mTestLooper.moveTimeForward(100); // current time: 200ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 20, 100, false);
+ assertAudioStatus(1, 100, false); // command not sent, no change
+
+ mTestLooper.moveTimeForward(300); // current time: 500ms
+ mTestLooper.dispatchAll();
+ assertAudioStatus(20, 100, false); // pending command sent, changed to 20
+
+ mTestLooper.moveTimeForward(100); // current time: 600ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 60, 100, false);
+ assertAudioStatus(20, 100, false); // command not sent, no change
+
+ mTestLooper.moveTimeForward(200); // current time: 800ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 80, 100, false);
+ assertAudioStatus(20, 100, false); // command not sent, no change
+
+ mTestLooper.moveTimeForward(200); // current time: 1000ms
+ mTestLooper.dispatchAll();
+ assertAudioStatus(80, 100, false); // command sent, changed to 80
+ }
+
+ @Test
+ public void testMultipleCommands_shortTimeAndReturn() {
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+ assertAudioStatus(1, 100, false);
+
+ mTestLooper.moveTimeForward(100); // current time: 100ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 20, 100, false);
+ assertAudioStatus(1, 100, false); // command not sent, no change
+
+ mTestLooper.moveTimeForward(100); // current time: 200ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+ assertAudioStatus(1, 100, false); // command not sent, no change
+
+ mTestLooper.moveTimeForward(300); // current time: 500ms
+ mTestLooper.dispatchAll();
+ assertAudioStatus(1, 100, false); // pending command sent
+ }
+
+ @Test
+ public void testMultipleCommands_muteAdjust() {
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+ assertAudioStatus(1, 100, false);
+
+ mTestLooper.moveTimeForward(100); // current time: 100ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(true, 10, 100, true);
+ assertAudioStatus(10, 100, true); // mute adjust, command sent, changed to 10
+
+ mTestLooper.moveTimeForward(100); // current time: 200ms
+ mTestLooper.dispatchAll();
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 20, 100, false);
+ assertAudioStatus(10, 100, true); // command not sent, no change
+
+ mTestLooper.moveTimeForward(300); // current time: 500ms
+ mTestLooper.dispatchAll();
+ assertAudioStatus(20, 100, false); // pending command sent, changed to 20, unmuted
+ }
+
+ private void assertAudioStatus(int volume, int maxVolume, boolean isMute) {
+ Assert.assertEquals(volume, mVolume);
+ Assert.assertEquals(maxVolume, mMaxVolume);
+ Assert.assertEquals(isMute, mIsMute);
+ }
+
+ private void resetVariables() {
+ mVolume = -1;
+ mMaxVolume = -1;
+ mIsMute = true;
+ }
+
+ private final class TestHdmiControlService extends IHdmiControlService.Stub {
+
+ @Override
+ public int[] getSupportedTypes() {
+ return null;
+ }
+
+ @Override
+ public HdmiDeviceInfo getActiveSource() {
+ return null;
+ }
+
+ @Override
+ public void deviceSelect(final int deviceId, final IHdmiControlCallback callback) {
+ }
+
+ @Override
+ public void portSelect(final int portId, final IHdmiControlCallback callback) {
+ }
+
+ @Override
+ public void sendKeyEvent(final int deviceType, final int keyCode, final boolean isPressed) {
+ }
+
+ @Override
+ public void oneTouchPlay(final IHdmiControlCallback callback) {
+ }
+
+ @Override
+ public void queryDisplayStatus(final IHdmiControlCallback callback) {
+ }
+
+ @Override
+ public void addHotplugEventListener(final IHdmiHotplugEventListener listener) {
+ }
+
+ @Override
+ public void removeHotplugEventListener(final IHdmiHotplugEventListener listener) {
+ }
+
+ @Override
+ public void addDeviceEventListener(final IHdmiDeviceEventListener listener) {
+ }
+
+ @Override
+ public List<HdmiPortInfo> getPortInfo() {
+ return null;
+ }
+
+ @Override
+ public boolean canChangeSystemAudioMode() {
+ return false;
+ }
+
+ @Override
+ public boolean getSystemAudioMode() {
+ return false;
+ }
+
+ @Override
+ public void setSystemAudioMode(final boolean enabled, final IHdmiControlCallback callback) {
+ }
+
+ @Override
+ public void addSystemAudioModeChangeListener(
+ final IHdmiSystemAudioModeChangeListener listener) {
+ }
+
+ @Override
+ public void removeSystemAudioModeChangeListener(
+ final IHdmiSystemAudioModeChangeListener listener) {
+ }
+
+ @Override
+ public void setInputChangeListener(final IHdmiInputChangeListener listener) {
+ }
+
+ @Override
+ public List<HdmiDeviceInfo> getInputDevices() {
+ return null;
+ }
+
+ // Returns all the CEC devices on the bus including system audio, switch,
+ // even those of reserved type.
+ @Override
+ public List<HdmiDeviceInfo> getDeviceList() {
+ return null;
+ }
+
+ @Override
+ public void setSystemAudioVolume(final int oldIndex, final int newIndex,
+ final int maxIndex) {
+ }
+
+ @Override
+ public void setSystemAudioMute(final boolean mute) {
+ }
+
+ @Override
+ public void setArcMode(final boolean enabled) {
+ }
+
+ @Override
+ public void setProhibitMode(final boolean enabled) {
+ }
+
+ @Override
+ public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
+ final int deviceType) {
+ }
+
+ @Override
+ public void sendVendorCommand(final int deviceType, final int targetAddress,
+ final byte[] params, final boolean hasVendorId) {
+ }
+
+ @Override
+ public void sendStandby(final int deviceType, final int deviceId) {
+ }
+
+ @Override
+ public void setHdmiRecordListener(IHdmiRecordListener listener) {
+ }
+
+ @Override
+ public void startOneTouchRecord(final int recorderAddress, final byte[] recordSource) {
+ }
+
+ @Override
+ public void stopOneTouchRecord(final int recorderAddress) {
+ }
+
+ @Override
+ public void startTimerRecording(final int recorderAddress, final int sourceType,
+ final byte[] recordSource) {
+ }
+
+ @Override
+ public void clearTimerRecording(final int recorderAddress, final int sourceType,
+ final byte[] recordSource) {
+ }
+
+ @Override
+ public void sendMhlVendorCommand(final int portId, final int offset, final int length,
+ final byte[] data) {
+ }
+
+ @Override
+ public void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener) {
+ }
+
+ @Override
+ public void setStandbyMode(final boolean isStandbyModeOn) {
+ }
+
+ @Override
+ public void reportAudioStatus(final int deviceType, final int volume, final int maxVolume,
+ final boolean isMute) {
+ mVolume = volume;
+ mMaxVolume = maxVolume;
+ mIsMute = isMute;
+ }
+ }
+
+}