Merge changes I8514bcc0,I91d20fd3,Iefc324ba,I29676ef7,I5c3d172f

* changes:
  Terminate ARC when eARC gets enabled on the RX device
  Terminate ARC before enabling eARC in the HAL
  Update ARC state based on eARC status updates
  Add callback to startArcAction
  Block new ARC connections during eARC connection
This commit is contained in:
Nathalie Le Clair
2022-12-21 20:31:38 +00:00
committed by Android (Google) Code Review
8 changed files with 991 additions and 110 deletions

View File

@@ -899,10 +899,16 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
void startArcAction(boolean enabled) {
startArcAction(enabled, null);
}
@ServiceThreadOnly
void startArcAction(boolean enabled, IHdmiControlCallback callback) {
assertRunOnServiceThread();
HdmiDeviceInfo info = getAvrDeviceInfo();
if (info == null) {
Slog.w(TAG, "Failed to start arc action; No AVR device.");
invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
return;
}
if (!canStartArcUpdateAction(info.getLogicalAddress(), enabled)) {
@@ -910,19 +916,37 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
if (enabled && !isConnectedToArcPort(info.getPhysicalAddress())) {
displayOsd(OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT);
}
invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
return;
}
if (enabled && mService.earcBlocksArcConnection()) {
Slog.i(TAG,
"ARC connection blocked because eARC connection is established or being "
+ "established.");
invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
return;
}
// Terminate opposite action and start action if not exist.
// Terminate opposite action and create an action with callback.
if (enabled) {
removeAction(RequestArcTerminationAction.class);
if (!hasAction(RequestArcInitiationAction.class)) {
addAndStartAction(new RequestArcInitiationAction(this, info.getLogicalAddress()));
if (hasAction(RequestArcInitiationAction.class)) {
RequestArcInitiationAction existingInitiationAction =
getActions(RequestArcInitiationAction.class).get(0);
existingInitiationAction.addCallback(callback);
} else {
addAndStartAction(
new RequestArcInitiationAction(this, info.getLogicalAddress(), callback));
}
} else {
removeAction(RequestArcInitiationAction.class);
if (!hasAction(RequestArcTerminationAction.class)) {
addAndStartAction(new RequestArcTerminationAction(this, info.getLogicalAddress()));
if (hasAction(RequestArcTerminationAction.class)) {
RequestArcTerminationAction existingTerminationAction =
getActions(RequestArcTerminationAction.class).get(0);
existingTerminationAction.addCallback(callback);
} else {
addAndStartAction(
new RequestArcTerminationAction(this, info.getLogicalAddress(), callback));
}
}
}
@@ -1010,6 +1034,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
protected int handleInitiateArc(HdmiCecMessage message) {
assertRunOnServiceThread();
if (mService.earcBlocksArcConnection()) {
Slog.i(TAG,
"ARC connection blocked because eARC connection is established or being "
+ "established.");
return Constants.ABORT_NOT_IN_CORRECT_MODE;
}
if (!canStartArcUpdateAction(message.getSource(), true)) {
HdmiDeviceInfo avrDeviceInfo = getAvrDeviceInfo();
if (avrDeviceInfo == null) {
@@ -1023,9 +1054,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
return Constants.ABORT_REFUSED;
}
// In case where <Initiate Arc> is started by <Request ARC Initiation>
// need to clean up RequestArcInitiationAction.
removeAction(RequestArcInitiationAction.class);
// In case where <Initiate Arc> is started by <Request ARC Initiation>, this message is
// handled in RequestArcInitiationAction as well.
SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
message.getSource(), true);
addAndStartAction(action);
@@ -1059,9 +1089,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
return Constants.HANDLED;
}
// Do not check ARC configuration since the AVR might have been already removed.
// Clean up RequestArcTerminationAction in case <Terminate Arc> was started by
// <Request ARC Termination>.
removeAction(RequestArcTerminationAction.class);
// In case where <Terminate Arc> is started by <Request ARC Termination>, this
// message is handled in RequestArcTerminationAction as well.
SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
message.getSource(), false);
addAndStartAction(action);

View File

@@ -26,6 +26,7 @@ import static android.hardware.hdmi.HdmiControlManager.SOUNDBAR_MODE_ENABLED;
import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
import static com.android.server.hdmi.Constants.DISABLED;
import static com.android.server.hdmi.Constants.ENABLED;
import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_ARC_PENDING;
import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE;
import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING;
import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE;
@@ -392,7 +393,7 @@ public class HdmiControlService extends SystemService {
// and the eARC HAL is present.
@GuardedBy("mLock")
@VisibleForTesting
protected boolean mEarcSupported;
private boolean mEarcSupported;
// Set to true while the eARC feature is enabled.
@GuardedBy("mLock")
@@ -725,7 +726,7 @@ public class HdmiControlService extends SystemService {
if (isEarcEnabled()) {
initializeEarc(INITIATED_BY_BOOT_UP);
} else {
setEarcEnabledInHal(false);
setEarcEnabledInHal(false, false);
}
}
@@ -3236,6 +3237,9 @@ public class HdmiControlService extends SystemService {
}
private void invokeCallback(IHdmiControlCallback callback, int result) {
if (callback == null) {
return;
}
try {
callback.onComplete(result);
} catch (RemoteException e) {
@@ -3518,7 +3522,7 @@ public class HdmiControlService extends SystemService {
}
initializeEarc(startReason);
} else {
setEarcEnabledInHal(false);
setEarcEnabledInHal(false, false);
}
}
// TODO: Initialize MHL local devices.
@@ -4414,8 +4418,17 @@ public class HdmiControlService extends SystemService {
private void initializeEarc(int initiatedBy) {
Slog.i(TAG, "eARC initialized, reason = " + initiatedBy);
setEarcEnabledInHal(true);
initializeEarcLocalDevice(initiatedBy);
if (initiatedBy == INITIATED_BY_ENABLE_EARC) {
// Since ARC and eARC cannot be connected simultaneously, we need to terminate ARC
// before even enabling eARC.
setEarcEnabledInHal(true, true);
} else {
// On boot, wake-up, and hotplug in, eARC will always be attempted before ARC.
// So there is no need to explicitly terminate ARC before enabling eARC.
setEarcEnabledInHal(true, false);
}
}
@ServiceThreadOnly
@@ -4464,13 +4477,14 @@ public class HdmiControlService extends SystemService {
@ServiceThreadOnly
private void onEnableEarc() {
// This will terminate ARC as well.
initializeEarc(INITIATED_BY_ENABLE_EARC);
}
@ServiceThreadOnly
private void onDisableEarc() {
disableEarcLocalDevice();
setEarcEnabledInHal(false);
setEarcEnabledInHal(false, false);
clearEarcLocalDevice();
}
@@ -4504,12 +4518,28 @@ public class HdmiControlService extends SystemService {
@ServiceThreadOnly
@VisibleForTesting
protected void setEarcEnabledInHal(boolean enabled) {
protected void setEarcEnabledInHal(boolean enabled, boolean terminateArcFirst) {
assertRunOnServiceThread();
mEarcController.setEarcEnabled(enabled);
mCecController.setHpdSignalType(
enabled ? Constants.HDMI_HPD_TYPE_STATUS_BIT : Constants.HDMI_HPD_TYPE_PHYSICAL,
mEarcPortId);
if (terminateArcFirst) {
startArcAction(false, new IHdmiControlCallback.Stub() {
@Override
public void onComplete(int result) throws RemoteException {
// Independently of the result (i.e. independently of whether the ARC RX device
// responded with <Terminate ARC> or not), we always end up terminating ARC in
// the HAL. As soon as we do that, we can enable eARC in the HAL.
mEarcController.setEarcEnabled(enabled);
mCecController.setHpdSignalType(
enabled ? Constants.HDMI_HPD_TYPE_STATUS_BIT
: Constants.HDMI_HPD_TYPE_PHYSICAL,
mEarcPortId);
}
});
} else {
mEarcController.setEarcEnabled(enabled);
mCecController.setHpdSignalType(
enabled ? Constants.HDMI_HPD_TYPE_STATUS_BIT : Constants.HDMI_HPD_TYPE_PHYSICAL,
mEarcPortId);
}
}
@ServiceThreadOnly
@@ -4540,4 +4570,21 @@ public class HdmiControlService extends SystemService {
mEarcLocalDevice.handleEarcCapabilitiesReported(rawCapabilities);
}
}
protected boolean earcBlocksArcConnection() {
if (mEarcLocalDevice == null) {
return false;
}
synchronized (mLock) {
return mEarcLocalDevice.mEarcStatus != HDMI_EARC_STATUS_ARC_PENDING;
}
}
protected void startArcAction(boolean enabled, IHdmiControlCallback callback) {
if (!isTvDeviceEnabled()) {
invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
} else {
tv().startArcAction(enabled, callback);
}
}
}

View File

@@ -18,6 +18,7 @@ package com.android.server.hdmi;
import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_ARC_PENDING;
import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_EARC_CONNECTED;
import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_EARC_PENDING;
import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_IDLE;
import android.hardware.hdmi.HdmiDeviceInfo;
@@ -69,23 +70,36 @@ public class HdmiEarcLocalDeviceTx extends HdmiEarcLocalDevice {
HdmiEarcLocalDeviceTx(HdmiControlService service) {
super(service, HdmiDeviceInfo.DEVICE_TV);
synchronized (mLock) {
mEarcStatus = HDMI_EARC_STATUS_EARC_PENDING;
}
mReportCapsHandler = new Handler(service.getServiceLooper());
mReportCapsRunnable = new ReportCapsRunnable();
}
protected void handleEarcStateChange(@Constants.EarcStatus int status) {
int oldEarcStatus;
synchronized (mLock) {
HdmiLogger.debug(TAG, "eARC state change [old:%b new %b]", mEarcStatus,
status);
oldEarcStatus = mEarcStatus;
mEarcStatus = status;
}
mReportCapsHandler.removeCallbacksAndMessages(null);
if (status == HDMI_EARC_STATUS_IDLE) {
notifyEarcStatusToAudioService(false, new ArrayList<>());
mService.startArcAction(false, null);
} else if (status == HDMI_EARC_STATUS_ARC_PENDING) {
notifyEarcStatusToAudioService(false, new ArrayList<>());
mService.startArcAction(true, null);
} else if (status == HDMI_EARC_STATUS_EARC_PENDING
&& oldEarcStatus == HDMI_EARC_STATUS_ARC_PENDING) {
mService.startArcAction(false, null);
} else if (status == HDMI_EARC_STATUS_EARC_CONNECTED) {
if (oldEarcStatus == HDMI_EARC_STATUS_ARC_PENDING) {
mService.startArcAction(false, null);
}
mReportCapsHandler.postDelayed(mReportCapsRunnable, REPORT_CAPS_MAX_DELAY_MS);
}
}

View File

@@ -16,7 +16,9 @@
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.IHdmiControlCallback;
/**
* Base feature action class for &lt;Request ARC Initiation&gt;/&lt;Request ARC Termination&gt;.
@@ -35,41 +37,19 @@ abstract class RequestArcAction extends HdmiCecFeatureAction {
*
* @param source {@link HdmiCecLocalDevice} instance
* @param avrAddress address of AV receiver. It should be AUDIO_SYSTEM type
* @param callback callback to inform about the status of the action
* @throws IllegalArgumentException if device type of sourceAddress and avrAddress
* is invalid
*/
RequestArcAction(HdmiCecLocalDevice source, int avrAddress) {
super(source);
RequestArcAction(HdmiCecLocalDevice source, int avrAddress, IHdmiControlCallback callback) {
super(source, callback);
HdmiUtils.verifyAddressType(getSourceAddress(), HdmiDeviceInfo.DEVICE_TV);
HdmiUtils.verifyAddressType(avrAddress, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mAvrAddress = avrAddress;
}
@Override
boolean processCommand(HdmiCecMessage cmd) {
if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE
|| !HdmiUtils.checkCommandSource(cmd, mAvrAddress, TAG)) {
return false;
}
int opcode = cmd.getOpcode();
switch (opcode) {
// Handles only <Feature Abort> here and, both <Initiate ARC> and <Terminate ARC>
// are handled in HdmiControlService itself because both can be
// received without <Request ARC Initiation> or <Request ARC Termination>.
case Constants.MESSAGE_FEATURE_ABORT:
int originalOpcode = cmd.getParams()[0] & 0xFF;
if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
disableArcTransmission();
finish();
return true;
} else if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION) {
tv().disableArc();
finish();
return true;
}
return false;
}
return false;
RequestArcAction(HdmiCecLocalDevice source, int avrAddress) {
this(source, avrAddress, null);
}
protected final void disableArcTransmission() {
@@ -86,6 +66,6 @@ abstract class RequestArcAction extends HdmiCecFeatureAction {
}
HdmiLogger.debug("[T] RequestArcAction.");
disableArcTransmission();
finish();
finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
}
}

View File

@@ -16,6 +16,8 @@
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
/**
@@ -35,6 +37,16 @@ final class RequestArcInitiationAction extends RequestArcAction {
super(source, avrAddress);
}
/**
* @Constructor
*
* For more details look at {@link RequestArcAction#RequestArcAction}.
*/
RequestArcInitiationAction(HdmiCecLocalDevice source, int avrAddress,
IHdmiControlCallback callback) {
super(source, avrAddress, callback);
}
@Override
boolean start() {
// Seq #38
@@ -49,10 +61,34 @@ final class RequestArcInitiationAction extends RequestArcAction {
if (error != SendMessageResult.SUCCESS) {
// Turn off ARC status if <Request ARC Initiation> fails.
tv().disableArc();
finish();
finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
}
});
return true;
}
@Override
boolean processCommand(HdmiCecMessage cmd) {
if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE
|| !HdmiUtils.checkCommandSource(cmd, mAvrAddress, TAG)) {
return false;
}
int opcode = cmd.getOpcode();
switch (opcode) {
case Constants.MESSAGE_FEATURE_ABORT:
int originalOpcode = cmd.getParams()[0] & 0xFF;
if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION) {
tv().disableArc();
finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
return true;
}
return false;
case Constants.MESSAGE_INITIATE_ARC:
finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
// This message still needs to be handled in HdmiCecLocalDeviceTv as well.
return false;
}
return false;
}
}

View File

@@ -16,6 +16,8 @@
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
/**
@@ -35,6 +37,16 @@ final class RequestArcTerminationAction extends RequestArcAction {
super(source, avrAddress);
}
/**
* @Constructor
*
* @see RequestArcAction#RequestArcAction
*/
RequestArcTerminationAction(HdmiCecLocalDevice source, int avrAddress,
IHdmiControlCallback callback) {
super(source, avrAddress, callback);
}
@Override
boolean start() {
mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
@@ -49,10 +61,34 @@ final class RequestArcTerminationAction extends RequestArcAction {
// If failed to send <Request ARC Termination>, start "Disabled" ARC
// transmission action.
disableArcTransmission();
finish();
finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
}
});
return true;
}
@Override
boolean processCommand(HdmiCecMessage cmd) {
if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE
|| !HdmiUtils.checkCommandSource(cmd, mAvrAddress, TAG)) {
return false;
}
int opcode = cmd.getOpcode();
switch (opcode) {
case Constants.MESSAGE_FEATURE_ABORT:
int originalOpcode = cmd.getParams()[0] & 0xFF;
if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
disableArcTransmission();
finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
return true;
}
return false;
case Constants.MESSAGE_TERMINATE_ARC:
finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
// This message still needs to be handled in HdmiCecLocalDeviceTv as well.
return false;
}
return false;
}
}

View File

@@ -39,6 +39,7 @@ import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.media.AudioManager;
import android.os.Looper;
@@ -96,6 +97,7 @@ public class HdmiCecLocalDeviceTvTest {
private int mTvPhysicalAddress;
private int mTvLogicalAddress;
private boolean mWokenUp;
private boolean mEarcBlocksArc;
private List<DeviceEventListener> mDeviceEventListeners = new ArrayList<>();
private class DeviceEventListener {
@@ -155,6 +157,11 @@ public class HdmiCecLocalDeviceTvTest {
return false;
}
@Override
boolean isPowerStandbyOrTransient() {
return false;
}
@Override
AudioManager getAudioManager() {
return mAudioManager;
@@ -164,6 +171,11 @@ public class HdmiCecLocalDeviceTvTest {
void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) {
mDeviceEventListeners.add(new DeviceEventListener(device, status));
}
@Override
protected boolean earcBlocksArcConnection() {
return mEarcBlocksArc;
}
};
mHdmiControlService.setIoLooper(mMyLooper);
@@ -175,16 +187,18 @@ public class HdmiCecLocalDeviceTvTest {
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[2];
hdmiPortInfos[0] =
new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x1000, true, false, false);
new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x1000, true, false, false, false);
hdmiPortInfos[1] =
new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, 0x2000, true, false, true);
new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, 0x2000, true, false, true, true);
mNativeWrapper.setPortInfo(hdmiPortInfos);
mHdmiControlService.initService();
mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
mPowerManager = new FakePowerManagerWrapper(context);
mHdmiControlService.setPowerManager(mPowerManager);
mTvPhysicalAddress = 0x0000;
mEarcBlocksArc = false;
mNativeWrapper.setPhysicalAddress(mTvPhysicalAddress);
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_DISABLED);
mTestLooper.dispatchAll();
mHdmiCecLocalDeviceTv = mHdmiControlService.tv();
mTvLogicalAddress = mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress();
@@ -196,6 +210,20 @@ public class HdmiCecLocalDeviceTvTest {
mNativeWrapper.clearResultMessages();
}
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);
}
}
@Test
public void initialPowerStateIsStandby() {
assertThat(mHdmiCecLocalDeviceTv.getPowerStatus()).isEqualTo(
@@ -426,9 +454,10 @@ public class HdmiCecLocalDeviceTvTest {
public void startArcAction_enable_portDoesNotSupportArc() {
// Emulate Audio device on port 0x1000 (does not support ARC)
mNativeWrapper.setPortConnectionStatus(1, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mHdmiCecLocalDeviceTv.startArcAction(true);
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
@@ -445,9 +474,10 @@ public class HdmiCecLocalDeviceTvTest {
public void startArcAction_disable_portDoesNotSupportArc() {
// Emulate Audio device on port 0x1000 (does not support ARC)
mNativeWrapper.setPortConnectionStatus(1, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mHdmiCecLocalDeviceTv.startArcAction(false);
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
@@ -464,9 +494,10 @@ public class HdmiCecLocalDeviceTvTest {
public void startArcAction_enable_portSupportsArc() {
// Emulate Audio device on port 0x2000 (supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mHdmiCecLocalDeviceTv.startArcAction(true);
@@ -485,9 +516,10 @@ public class HdmiCecLocalDeviceTvTest {
public void startArcAction_disable_portSupportsArc() {
// Emulate Audio device on port 0x2000 (supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mHdmiCecLocalDeviceTv.startArcAction(false);
@@ -522,9 +554,10 @@ public class HdmiCecLocalDeviceTvTest {
public void handleInitiateArc_portDoesNotSupportArc() {
// Emulate Audio device on port 0x1000 (does not support ARC)
mNativeWrapper.setPortConnectionStatus(1, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc(
ADDR_AUDIO_SYSTEM,
@@ -544,9 +577,10 @@ public class HdmiCecLocalDeviceTvTest {
public void handleInitiateArc_portSupportsArc() {
// Emulate Audio device on port 0x2000 (supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc(
@@ -574,6 +608,66 @@ public class HdmiCecLocalDeviceTvTest {
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
}
@Test
public void handleTerminateArc_noAudioDevice() {
HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(terminateArc);
mTestLooper.dispatchAll();
HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated);
}
@Test
public void handleTerminateArc_portDoesNotSupportArc() {
// Emulate Audio device on port 0x1000 (does not support ARC)
mNativeWrapper.setPortConnectionStatus(1, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(terminateArc);
mTestLooper.dispatchAll();
HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated);
}
@Test
public void handleTerminateArc_portSupportsArc() {
// Emulate Audio device on port 0x2000 (supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(terminateArc);
mTestLooper.dispatchAll();
HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated);
}
@Test
public void supportsRecordTvScreen() {
HdmiCecMessage recordTvScreen = HdmiCecMessage.build(ADDR_RECORDER_1, mTvLogicalAddress,
@@ -595,9 +689,10 @@ public class HdmiCecLocalDeviceTvTest {
HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED);
// Emulate Audio device on port 0x1000 (does not support ARC)
mNativeWrapper.setPortConnectionStatus(1, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
HdmiCecFeatureAction systemAudioAutoInitiationAction =
@@ -636,9 +731,9 @@ public class HdmiCecLocalDeviceTvTest {
public void hotplugDetectionAction_discoversDeviceAfterMessageReceived() {
// Playback 1 sends a message before ACKing a poll
mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.NACK);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildActiveSource(
HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(
ADDR_PLAYBACK_1, ADDR_TV);
mNativeWrapper.onCecMessage(hdmiCecMessage);
mNativeWrapper.onCecMessage(activeSource);
mTestLooper.dispatchAll();
// Playback 1 begins ACKing polls, allowing detection by HotplugDetectionAction
@@ -812,12 +907,12 @@ public class HdmiCecLocalDeviceTvTest {
mTestLooper.dispatchAll();
// <Feature Abort>[Not in correct mode] not sent
HdmiCecMessage featureAbortMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand(
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
ADDR_TV,
ADDR_PLAYBACK_1,
Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
Constants.ABORT_NOT_IN_CORRECT_MODE);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortMessage);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbort);
// <Set Audio Volume Level> uses volume range [0, 100]; STREAM_MUSIC uses range [0, 25]
verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(5), anyInt());
@@ -838,12 +933,12 @@ public class HdmiCecLocalDeviceTvTest {
mTestLooper.dispatchAll();
// <Feature Abort>[Not in correct mode] sent
HdmiCecMessage featureAbortMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand(
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
ADDR_TV,
ADDR_PLAYBACK_1,
Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
Constants.ABORT_NOT_IN_CORRECT_MODE);
assertThat(mNativeWrapper.getResultMessages()).contains(featureAbortMessage);
assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort);
// AudioManager not notified of volume change
verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), anyInt(),
@@ -853,11 +948,11 @@ public class HdmiCecLocalDeviceTvTest {
@Test
public void tvSendRequestArcTerminationOnSleep() {
// Emulate Audio device on port 0x2000 (supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(hdmiCecMessage);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mHdmiCecLocalDeviceTv.startArcAction(true);
@@ -898,4 +993,560 @@ public class HdmiCecLocalDeviceTvTest {
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
}
@Test
public void startArcAction_enable_earcBlocksArc() {
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
mEarcBlocksArc = true;
// Emulate Audio device on port 0x2000 (supports ARC and eARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mHdmiCecLocalDeviceTv.startArcAction(true);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcInitiation);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcTermination);
}
@Test
public void startArcAction_enable_earcDoesNotBlockArc() {
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
mEarcBlocksArc = false;
// Emulate Audio device on port 0x2000 (supports ARC and eARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mHdmiCecLocalDeviceTv.startArcAction(true);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcInitiation);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcTermination);
}
@Test
public void startArcAction_disable_earcBlocksArc() {
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
mEarcBlocksArc = true;
// Emulate Audio device on port 0x2000 (supports ARC and eARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mHdmiCecLocalDeviceTv.startArcAction(false);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcInitiation);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
}
@Test
public void handleInitiateArc_earcBlocksArc() {
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
mEarcBlocksArc = true;
// Emulate Audio device on port 0x2000 (supports ARC and eARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(requestArcInitiation);
mTestLooper.dispatchAll();
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
ADDR_TV,
ADDR_AUDIO_SYSTEM,
Constants.MESSAGE_INITIATE_ARC,
Constants.ABORT_NOT_IN_CORRECT_MODE);
assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort);
}
@Test
public void handleInitiateArc_earcDoesNotBlockArc() {
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
mEarcBlocksArc = false;
// Emulate Audio device on port 0x2000 (supports ARC and eARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(requestArcInitiation);
mTestLooper.dispatchAll();
HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
// <Report ARC Initiated> should only be sent after SAD querying is done
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
// Finish querying SADs
assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
mNativeWrapper.clearResultMessages();
mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
}
@Test
public void handleTerminateArc_earcBlocksArc() {
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
mEarcBlocksArc = true;
// Emulate Audio device on port 0x2000 (supports ARC and eARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(terminateArc);
mTestLooper.dispatchAll();
HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated);
}
@Test
public void startArcAction_initiation_noAvr() {
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
@Test
public void startArcAction_initiation_portNotConnected() {
// Emulate Audio device on port 0x2000 (supports ARC)
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
// Emulate port disconnect
mNativeWrapper.setPortConnectionStatus(2, false);
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_INCORRECT_MODE);
}
@Test
public void startArcAction_initiation_portDoesNotSupportArc() {
// Emulate Audio device on port 0x1000 (Doesn´t support ARC)
mNativeWrapper.setPortConnectionStatus(1, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_INCORRECT_MODE);
}
@Test
public void startArcAction_initiation_indirectPhysicalAddress() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2320, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_INCORRECT_MODE);
}
@Test
public void startArcAction_initiation_earcBlocksArc() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mEarcBlocksArc = true;
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_INCORRECT_MODE);
}
@Test
public void startArcAction_initiation_messageNotAcked() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mNativeWrapper.setMessageSendResult(
Constants.MESSAGE_REQUEST_ARC_INITIATION, SendMessageResult.NACK);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcInitiation);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
@Test
public void startArcAction_initiation_timeout() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcInitiation);
mTestLooper.moveTimeForward(TIMEOUT_MS);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TIMEOUT);
}
@Test
public void startArcAction_initiation_featureAbort() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcInitiation);
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
ADDR_AUDIO_SYSTEM,
ADDR_TV,
Constants.MESSAGE_REQUEST_ARC_INITIATION,
Constants.ABORT_NOT_IN_CORRECT_MODE);
mNativeWrapper.onCecMessage(featureAbort);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
@Test
public void startArcAction_initiation_success() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(true, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcInitiation);
HdmiCecMessage initiateArc = HdmiCecMessageBuilder.buildInitiateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(initiateArc);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void startArcAction_termination_noAvr() {
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(false, callback);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
@Test
public void startArcAction_termination_portDoesNotSupportArc() {
// Emulate Audio device on port 0x1000 (Doesn´t support ARC)
mNativeWrapper.setPortConnectionStatus(1, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(false, callback);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_INCORRECT_MODE);
}
@Test
public void startArcAction_termination_messageNotAcked() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
mNativeWrapper.setMessageSendResult(
Constants.MESSAGE_REQUEST_ARC_TERMINATION, SendMessageResult.NACK);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(false, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
@Test
public void startArcAction_termination_timeout() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(false, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
mTestLooper.moveTimeForward(TIMEOUT_MS);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TIMEOUT);
}
@Test
public void startArcAction_termination_featureAbort() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(false, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
ADDR_AUDIO_SYSTEM,
ADDR_TV,
Constants.MESSAGE_REQUEST_ARC_TERMINATION,
Constants.ABORT_NOT_IN_CORRECT_MODE);
mNativeWrapper.onCecMessage(featureAbort);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
@Test
public void startArcAction_termination_success() {
// Emulate Audio device on port 0x2000 (Supports ARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceTv.startArcAction(false, callback);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(terminateArc);
mTestLooper.dispatchAll();
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void enableEarc_terminateArc() {
// Emulate Audio device on port 0x2000 (supports ARC and eARC)
mNativeWrapper.setPortConnectionStatus(2, true);
HdmiCecMessage reportPhysicalAddress =
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
HdmiCecMessage initiateArc = HdmiCecMessageBuilder.buildInitiateArc(
ADDR_AUDIO_SYSTEM,
ADDR_TV);
mNativeWrapper.onCecMessage(initiateArc);
mTestLooper.dispatchAll();
HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
// <Report ARC Initiated> should only be sent after SAD querying is done
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
// Finish querying SADs
assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
mNativeWrapper.clearResultMessages();
mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
mNativeWrapper.clearResultMessages();
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
}
}

View File

@@ -30,9 +30,11 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -143,6 +145,7 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.setPowerManager(mPowerManager);
mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
mHdmiControlServiceSpy.setAudioManager(mAudioManager);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
}
@@ -1087,7 +1090,6 @@ public class HdmiControlServiceTest {
@Test
public void disableEarc_clearEarcLocalDevice() {
mHdmiControlServiceSpy.setEarcSupported(true);
mHdmiControlServiceSpy.clearEarcLocalDevice();
mHdmiControlServiceSpy.addEarcLocalDevice(
new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy));
@@ -1100,7 +1102,6 @@ public class HdmiControlServiceTest {
@Test
public void disableCec_doNotClearEarcLocalDevice() {
mHdmiControlServiceSpy.setEarcSupported(true);
mHdmiControlServiceSpy.clearEarcLocalDevice();
mHdmiControlServiceSpy.addEarcLocalDevice(
new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy));
@@ -1113,7 +1114,6 @@ public class HdmiControlServiceTest {
@Test
public void enableCec_initializeCecLocalDevices() {
mHdmiControlServiceSpy.setEarcSupported(true);
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
mTestLooper.dispatchAll();
@@ -1125,7 +1125,6 @@ public class HdmiControlServiceTest {
@Test
public void enableEarc_initializeEarcLocalDevices() {
mHdmiControlServiceSpy.setEarcSupported(true);
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.setEarcEnabled(HdmiControlManager.EARC_FEATURE_DISABLED);
mTestLooper.dispatchAll();
@@ -1137,7 +1136,6 @@ public class HdmiControlServiceTest {
@Test
public void disableCec_DoNotInformHalAboutEarc() {
mHdmiControlServiceSpy.setEarcSupported(true);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
@@ -1147,7 +1145,7 @@ public class HdmiControlServiceTest {
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean());
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean(), anyBoolean());
}
@Test
@@ -1155,15 +1153,14 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false, false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(true), anyBoolean());
}
@Test
@@ -1171,14 +1168,13 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean());
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean(), anyBoolean());
}
@Test
@@ -1186,15 +1182,14 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true, true);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(false), anyBoolean());
}
@Test
@@ -1202,13 +1197,15 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.initService();
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true, false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(false), anyBoolean());
}
@Test
@@ -1216,13 +1213,12 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.initService();
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false, false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(true), anyBoolean());
}
@Test
@@ -1230,13 +1226,12 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.onWakeUp(WAKE_UP_SCREEN_ON);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true, false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(false), anyBoolean());
}
@Test
@@ -1244,13 +1239,106 @@ public class HdmiControlServiceTest {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.onWakeUp(WAKE_UP_SCREEN_ON);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false, false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(true), anyBoolean());
}
@Test
public void earcIdle_blocksArcConnection() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_IDLE);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue();
}
@Test
public void earcPending_blocksArcConnection() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue();
}
@Test
public void earcEnabled_blocksArcConnection() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue();
}
@Test
public void arcPending_doesNotBlockArcConnection() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isFalse();
}
@Test
public void earcStatusBecomesIdle_terminateArc() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_IDLE);
verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(false), any());
}
@Test
public void earcStatusBecomesEnabled_doNothing() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED);
verify(mHdmiControlServiceSpy, times(0)).startArcAction(anyBoolean(), any());
}
@Test
public void earcStatusBecomesPending_doNothing() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING);
verify(mHdmiControlServiceSpy, times(0)).startArcAction(anyBoolean(), any());
}
@Test
public void earcStatusBecomesNotEnabled_initiateArc() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING);
verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(true), any());
}
@Test
public void earcStateWasArcPending_becomesEarcPending_terminateArc() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING);
mTestLooper.dispatchAll();
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING);
verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(false), any());
}
@Test
public void earcStateWasArcPending_becomesEarcEnabled_terminateArc() {
mHdmiControlServiceSpy.clearEarcLocalDevice();
HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx);
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING);
mTestLooper.dispatchAll();
localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED);
verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(false), any());
}
protected static class MockPlaybackDevice extends HdmiCecLocalDevicePlayback {