Merge "HDMI: More reliable DSM setting disabling"

This commit is contained in:
Paul Colța
2022-12-06 15:47:28 +00:00
committed by Android (Google) Code Review
6 changed files with 126 additions and 11 deletions

View File

@@ -15,6 +15,8 @@
*/
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
/**
@@ -33,6 +35,10 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
super(source);
}
ArcTerminationActionFromAvr(HdmiCecLocalDevice source, IHdmiControlCallback callback) {
super(source, callback);
}
@Override
boolean start() {
mState = STATE_WAITING_FOR_INITIATE_ARC_RESPONSE;
@@ -47,10 +53,19 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
return false;
}
switch (cmd.getOpcode()) {
case Constants.MESSAGE_FEATURE_ABORT:
int originalOpcode = cmd.getParams()[0] & 0xFF;
if (originalOpcode == Constants.MESSAGE_TERMINATE_ARC) {
mState = STATE_ARC_TERMINATED;
audioSystem().processArcTermination();
finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
return true;
}
return false;
case Constants.MESSAGE_REPORT_ARC_TERMINATED:
mState = STATE_ARC_TERMINATED;
audioSystem().processArcTermination();
finish();
finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
return true;
}
return false;
@@ -79,7 +94,7 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
audioSystem().setArcStatus(false);
}
HdmiLogger.debug("Terminate ARC was not successfully sent.");
finish();
finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
});
}
@@ -88,6 +103,6 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
// Disable ARC if TV didn't respond with <Report ARC Terminated> in time.
audioSystem().setArcStatus(false);
HdmiLogger.debug("handleTerminateArcTimeout");
finish();
finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
}
}

View File

@@ -458,8 +458,16 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
HdmiLogger.debug("ARC is not established between TV and AVR device");
return Constants.ABORT_NOT_IN_CORRECT_MODE;
} else {
removeAction(ArcTerminationActionFromAvr.class);
addAndStartAction(new ArcTerminationActionFromAvr(this));
if (!getActions(ArcTerminationActionFromAvr.class).isEmpty()
&& !getActions(ArcTerminationActionFromAvr.class).get(0).mCallbacks.isEmpty()) {
IHdmiControlCallback callback =
getActions(ArcTerminationActionFromAvr.class).get(0).mCallbacks.get(0);
removeAction(ArcTerminationActionFromAvr.class);
addAndStartAction(new ArcTerminationActionFromAvr(this, callback));
} else {
removeAction(ArcTerminationActionFromAvr.class);
addAndStartAction(new ArcTerminationActionFromAvr(this));
}
return Constants.HANDLED;
}
}

View File

@@ -878,16 +878,30 @@ public class HdmiControlService extends SystemService {
Slog.w(TAG, "Device type doesn't support ARC.");
return;
}
boolean isArcEnabled = false;
if (settingValue == SOUNDBAR_MODE_DISABLED && audioSystem != null) {
if (audioSystem.isArcEnabled()) {
audioSystem.addAndStartAction(new ArcTerminationActionFromAvr(audioSystem));
}
isArcEnabled = audioSystem.isArcEnabled();
if (isSystemAudioActivated()) {
audioSystem.terminateSystemAudioMode();
}
if (isArcEnabled) {
if (audioSystem.hasAction(ArcTerminationActionFromAvr.class)) {
audioSystem.removeAction(ArcTerminationActionFromAvr.class);
}
audioSystem.addAndStartAction(new ArcTerminationActionFromAvr(audioSystem,
new IHdmiControlCallback.Stub() {
@Override
public void onComplete(int result) {
mAddressAllocated = false;
initializeCecLocalDevices(INITIATED_BY_SOUNDBAR_MODE);
}
}));
}
}
if (!isArcEnabled) {
mAddressAllocated = false;
initializeCecLocalDevices(INITIATED_BY_SOUNDBAR_MODE);
}
mAddressAllocated = false;
initializeCecLocalDevices(INITIATED_BY_SOUNDBAR_MODE);
}
/**

View File

@@ -24,6 +24,8 @@ import static org.mockito.Mockito.spy;
import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.media.AudioManager;
import android.os.Looper;
@@ -52,6 +54,7 @@ public class ArcTerminationActionFromAvrTest {
private Context mContextSpy;
private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
private FakePowerManagerWrapper mPowerManager;
private TestCallback mCallback;
private ArcTerminationActionFromAvr mAction;
private FakeNativeWrapper mNativeWrapper;
@@ -112,7 +115,9 @@ public class ArcTerminationActionFromAvrTest {
}
};
mHdmiCecLocalDeviceAudioSystem.init();
mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem);
mCallback = new TestCallback();
mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem,
mCallback);
mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem);
hdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
@@ -121,6 +126,20 @@ public class ArcTerminationActionFromAvrTest {
mTestLooper.dispatchAll();
}
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 testSendMessage_sendFailed() {
mNativeWrapper.setMessageSendResult(Constants.MESSAGE_TERMINATE_ARC,
@@ -133,6 +152,7 @@ public class ArcTerminationActionFromAvrTest {
assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);
assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
@Test
@@ -149,6 +169,7 @@ public class ArcTerminationActionFromAvrTest {
mTestLooper.dispatchAll();
assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TIMEOUT);
}
@Test
@@ -167,5 +188,28 @@ public class ArcTerminationActionFromAvrTest {
mTestLooper.dispatchAll();
assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void testReportArcTerminated_featureAbort() {
mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
mTestLooper.dispatchAll();
HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_TV);
assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);
HdmiCecMessage arcTerminatedResponse = HdmiCecMessageBuilder.buildFeatureAbortCommand(
Constants.ADDR_TV,
Constants.ADDR_AUDIO_SYSTEM,
Constants.MESSAGE_TERMINATE_ARC,
Constants.ABORT_REFUSED);
mNativeWrapper.onCecMessage(arcTerminatedResponse);
mTestLooper.dispatchAll();
assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
}
}

View File

@@ -534,6 +534,25 @@ public class HdmiCecLocalDeviceAudioSystemTest {
assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
}
@Test
public void handleRequestArcTerminate_callbackIsPreserved() throws Exception {
TestCallback callback = new TestCallback();
mHdmiCecLocalDeviceAudioSystem.setArcStatus(true);
assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isTrue();
mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem, callback));
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM);
assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(message))
.isEqualTo(Constants.HANDLED);
mTestLooper.dispatchAll();
assertThat(mHdmiCecLocalDeviceAudioSystem.getActions(
ArcTerminationActionFromAvr.class).get(0).mCallbacks.get(0)).isEqualTo(callback);
}
@Test
public void handleRequestArcInit_arcIsNotSupported() throws Exception {
HdmiCecMessage message =
@@ -880,4 +899,13 @@ public class HdmiCecLocalDeviceAudioSystemTest {
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(
systemAudioModeRequest_fromAudioSystem);
}
private static class TestCallback extends IHdmiControlCallback.Stub {
private final ArrayList<Integer> mCallbackResult = new ArrayList<Integer>();
@Override
public void onComplete(int result) {
mCallbackResult.add(result);
}
}
}

View File

@@ -1036,6 +1036,7 @@ public class HdmiControlServiceTest {
@Test
public void setSoundbarMode_enabled_addAudioSystemLocalDevice() {
mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
// Initialize the local devices excluding the audio system.
mHdmiControlServiceSpy.clearCecLocalDevices();
mLocalDevices.remove(mAudioSystemDeviceSpy);
@@ -1053,6 +1054,7 @@ public class HdmiControlServiceTest {
@Test
public void setSoundbarMode_disabled_removeAudioSystemLocalDevice() {
mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
// Initialize the local devices excluding the audio system.
mHdmiControlServiceSpy.clearCecLocalDevices();
mLocalDevices.remove(mAudioSystemDeviceSpy);
@@ -1073,6 +1075,10 @@ public class HdmiControlServiceTest {
HdmiControlManager.CEC_SETTING_NAME_SOUNDBAR_MODE,
HdmiControlManager.SOUNDBAR_MODE_DISABLED);
mTestLooper.dispatchAll();
// Wait for ArcTerminationActionFromAvr timeout for the logical address allocation to start.
mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
mTestLooper.dispatchAll();
assertThat(mHdmiControlServiceSpy.audioSystem()).isNull();
}