blob: a3d02d4fe26f00ecdd5a4691cc44b7b403165b95 [file] [log] [blame]
/*
* Copyright (C) 2021 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 static android.hardware.hdmi.DeviceFeatures.FEATURE_NOT_SUPPORTED;
import static android.hardware.hdmi.DeviceFeatures.FEATURE_SUPPORTED;
import static android.hardware.hdmi.DeviceFeatures.FEATURE_SUPPORT_UNKNOWN;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.hdmi.DeviceFeatures;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.os.Looper;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.server.SystemService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.ArrayList;
import java.util.Collections;
@SmallTest
@Presubmit
@RunWith(JUnit4.class)
public class SetAudioVolumeLevelDiscoveryActionTest {
private HdmiControlService mHdmiControlServiceSpy;
private HdmiCecController mHdmiCecController;
private HdmiCecLocalDevicePlayback mPlaybackDevice;
private FakeNativeWrapper mNativeWrapper;
private FakePowerManagerWrapper mPowerManager;
private Looper mLooper;
private Context mContextSpy;
private TestLooper mTestLooper = new TestLooper();
private int mPhysicalAddress = 0x1100;
private int mPlaybackLogicalAddress;
private TestCallback mTestCallback;
private SetAudioVolumeLevelDiscoveryAction mAction;
/**
* Setup: Local Playback device attempts to determine whether a connected TV supports
* <Set Audio Volume Level>.
*/
@Before
public void setUp() throws RemoteException {
mContextSpy = spy(new ContextWrapper(
InstrumentationRegistry.getInstrumentation().getTargetContext()));
mHdmiControlServiceSpy = spy(new HdmiControlService(mContextSpy,
Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK),
new FakeAudioDeviceVolumeManagerWrapper()));
doNothing().when(mHdmiControlServiceSpy)
.writeStringSystemProperty(anyString(), anyString());
mLooper = mTestLooper.getLooper();
mHdmiControlServiceSpy.setIoLooper(mLooper);
mHdmiControlServiceSpy.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy));
mHdmiControlServiceSpy.setDeviceConfig(new FakeDeviceConfigWrapper());
mNativeWrapper = new FakeNativeWrapper();
mNativeWrapper.setPhysicalAddress(mPhysicalAddress);
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
mHdmiControlServiceSpy, mNativeWrapper, mHdmiControlServiceSpy.getAtomWriter());
mHdmiControlServiceSpy.setCecController(mHdmiCecController);
mHdmiControlServiceSpy.setHdmiMhlController(
HdmiMhlControllerStub.create(mHdmiControlServiceSpy));
mHdmiControlServiceSpy.initService();
mHdmiControlServiceSpy.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
mPowerManager = new FakePowerManagerWrapper(mContextSpy);
mHdmiControlServiceSpy.setPowerManager(mPowerManager);
mHdmiControlServiceSpy.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
mTestLooper.dispatchAll();
mPlaybackDevice = mHdmiControlServiceSpy.playback();
mPlaybackLogicalAddress = mPlaybackDevice.getDeviceInfo().getLogicalAddress();
// Setup specific to these tests
mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
Constants.ADDR_TV, 0x0000, HdmiDeviceInfo.DEVICE_TV));
mTestLooper.dispatchAll();
mTestCallback = new TestCallback();
mAction = new SetAudioVolumeLevelDiscoveryAction(mPlaybackDevice,
Constants.ADDR_TV, mTestCallback);
}
@Test
public void sendsSetAudioVolumeLevel() {
mPlaybackDevice.addAndStartAction(mAction);
mTestLooper.dispatchAll();
HdmiCecMessage setAudioVolumeLevel = SetAudioVolumeLevelMessage.build(
mPlaybackLogicalAddress, Constants.ADDR_TV,
Constants.AUDIO_VOLUME_STATUS_UNKNOWN);
assertThat(mNativeWrapper.getResultMessages()).contains(setAudioVolumeLevel);
}
@Test
public void noMatchingFeatureAbortReceived_actionSucceedsAndSetsFeatureSupported() {
mPlaybackDevice.addAndStartAction(mAction);
mTestLooper.dispatchAll();
// Wrong opcode
mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildFeatureAbortCommand(
Constants.ADDR_TV,
mPlaybackLogicalAddress,
Constants.MESSAGE_GIVE_DECK_STATUS,
Constants.ABORT_UNRECOGNIZED_OPCODE));
// Wrong source
mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildFeatureAbortCommand(
Constants.ADDR_AUDIO_SYSTEM,
mPlaybackLogicalAddress,
Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
Constants.ABORT_UNRECOGNIZED_OPCODE));
mTestLooper.dispatchAll();
mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
mTestLooper.dispatchAll();
@DeviceFeatures.FeatureSupportStatus int savlSupport =
mHdmiControlServiceSpy.getHdmiCecNetwork().getCecDeviceInfo(Constants.ADDR_TV)
.getDeviceFeatures().getSetAudioVolumeLevelSupport();
assertThat(savlSupport).isEqualTo(FEATURE_SUPPORTED);
assertThat(mTestCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void matchingFeatureAbortReceived_actionSucceedsAndSetsFeatureNotSupported() {
mPlaybackDevice.addAndStartAction(mAction);
mTestLooper.dispatchAll();
mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildFeatureAbortCommand(
Constants.ADDR_TV,
mPlaybackLogicalAddress,
Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
Constants.ABORT_UNRECOGNIZED_OPCODE));
mTestLooper.dispatchAll();
@DeviceFeatures.FeatureSupportStatus int savlSupport =
mHdmiControlServiceSpy.getHdmiCecNetwork().getCecDeviceInfo(Constants.ADDR_TV)
.getDeviceFeatures().getSetAudioVolumeLevelSupport();
assertThat(savlSupport).isEqualTo(FEATURE_NOT_SUPPORTED);
assertThat(mTestCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void messageFailedToSend_actionFailsAndDoesNotUpdateFeatureSupport() {
mNativeWrapper.setMessageSendResult(Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
SendMessageResult.FAIL);
mTestLooper.dispatchAll();
mPlaybackDevice.addAndStartAction(mAction);
mTestLooper.dispatchAll();
@DeviceFeatures.FeatureSupportStatus int savlSupport =
mHdmiControlServiceSpy.getHdmiCecNetwork().getCecDeviceInfo(Constants.ADDR_TV)
.getDeviceFeatures().getSetAudioVolumeLevelSupport();
assertThat(savlSupport).isEqualTo(FEATURE_SUPPORT_UNKNOWN);
assertThat(mTestCallback.getResult()).isEqualTo(
HdmiControlManager.RESULT_COMMUNICATION_FAILED);
}
private static class TestCallback extends IHdmiControlCallback.Stub {
private final ArrayList<Integer> mCallbackResult = new ArrayList<Integer>();
@Override
public void onComplete(int result) {
mCallbackResult.add(result);
}
private int getResult() {
assertThat(mCallbackResult.size()).isEqualTo(1);
return mCallbackResult.get(0);
}
}
}