From 46887f8e68b576ca201150c1f9e98aa0c151b362 Mon Sep 17 00:00:00 2001 From: Nathalie Le Clair Date: Wed, 11 May 2022 16:44:42 +0200 Subject: [PATCH] Return early if audio system doesn't support SAD feature Signals that the audio system doesn't support the SAD feature: - it sends a [Unrecognized Opcode] - even after 2 tries, it still doesn't respond to the messages Test: atest and manually verified that the SAD feature returns early and the ARC connection is unblocked. Bug: 232235947 Change-Id: I146fd24820537ea4957785b8eb0710ddb12b977b --- .../android/server/hdmi/RequestSadAction.java | 27 ++-- .../server/hdmi/RequestSadActionTest.java | 151 ++++++++++-------- 2 files changed, 102 insertions(+), 76 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/RequestSadAction.java b/services/core/java/com/android/server/hdmi/RequestSadAction.java index 702c0004cb91a..23aaf3260bac4 100644 --- a/services/core/java/com/android/server/hdmi/RequestSadAction.java +++ b/services/core/java/com/android/server/hdmi/RequestSadAction.java @@ -181,13 +181,20 @@ final class RequestSadAction extends HdmiCecFeatureAction { return true; } if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT - && (cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR - && (cmd.getParams()[1] & 0xFF) == Constants.ABORT_INVALID_OPERAND) { - // Queried SADs are not supported - mQueriedSadCount += MAX_SAD_PER_REQUEST; - mTimeoutRetry = 0; - querySad(); - return true; + && (cmd.getParams()[0] & 0xFF) + == Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR) { + if ((cmd.getParams()[1] & 0xFF) == Constants.ABORT_UNRECOGNIZED_OPCODE) { + // SAD feature is not supported + wrapUpAndFinish(); + return true; + } + if ((cmd.getParams()[1] & 0xFF) == Constants.ABORT_INVALID_OPERAND) { + // Queried SADs are not supported + mQueriedSadCount += MAX_SAD_PER_REQUEST; + mTimeoutRetry = 0; + querySad(); + return true; + } } return false; } @@ -211,9 +218,9 @@ final class RequestSadAction extends HdmiCecFeatureAction { querySad(); return; } - mQueriedSadCount += MAX_SAD_PER_REQUEST; - mTimeoutRetry = 0; - querySad(); + // Don't query any other SADs if one of the SAD queries ran into the maximum amount of + // retries. + wrapUpAndFinish(); } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java index f7983ca218162..3228e82b566b1 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java @@ -139,11 +139,12 @@ public class RequestSadActionTest { } @Test - public void noResponse_queryAgain_emptyResult() { + public void noResponse_queryAgainOnce_emptyResult() { RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM, mCallback); action.start(); mTestLooper.dispatchAll(); + assertThat(mSupportedSads).isNull(); HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, @@ -153,45 +154,90 @@ public class RequestSadActionTest { mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expected1); - mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); + assertThat(mSupportedSads).isNotNull(); + assertThat(mSupportedSads.size()).isEqualTo(0); + HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray()); - assertThat(mNativeWrapper.getResultMessages()).contains(expected2); - mNativeWrapper.clearResultMessages(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expected2); - mNativeWrapper.clearResultMessages(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray()); - assertThat(mNativeWrapper.getResultMessages()).contains(expected3); - mNativeWrapper.clearResultMessages(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expected3); - mNativeWrapper.clearResultMessages(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray()); - assertThat(mNativeWrapper.getResultMessages()).contains(expected4); - mNativeWrapper.clearResultMessages(); + + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expected4); mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected2); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected3); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected4); + assertThat(mSupportedSads.size()).isEqualTo(0); + } + + @Test + public void unrecognizedOpcode_dontQueryAgain_emptyResult() { + RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM, + mCallback); + action.start(); + mTestLooper.dispatchAll(); + assertThat(mSupportedSads).isNull(); + + HdmiCecMessage unrecognizedOpcode = HdmiCecMessageBuilder.buildFeatureAbortCommand( + Constants.ADDR_AUDIO_SYSTEM, mTvLogicalAddress, + Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR, + Constants.ABORT_UNRECOGNIZED_OPCODE); + + HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( + mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, + CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray()); + assertThat(mNativeWrapper.getResultMessages()).contains(expected1); + action.processCommand(unrecognizedOpcode); + mTestLooper.dispatchAll(); + + assertThat(mSupportedSads).isNotNull(); + assertThat(mSupportedSads.size()).isEqualTo(0); + + HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( + mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, + CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray()); + HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( + mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, + CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray()); + HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( + mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, + CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray()); + + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected2); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected3); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected4); assertThat(mSupportedSads.size()).isEqualTo(0); } @@ -455,11 +501,12 @@ public class RequestSadActionTest { } @Test - public void invalidMessageLength_queryAgain() { + public void invalidMessageLength_queryAgainOnce() { RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM, mCallback); action.start(); mTestLooper.dispatchAll(); + assertThat(mSupportedSads).isNull(); HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, @@ -482,63 +529,35 @@ public class RequestSadActionTest { mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); + assertThat(mSupportedSads).isNotNull(); + assertThat(mSupportedSads.size()).isEqualTo(0); + HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray()); - byte[] sadsToRespond_2 = new byte[]{ - 0x05, 0x18, 0x4A, - 0x06, 0x64, 0x5A, - 0x07, - 0x08, 0x20, 0x0A}; - HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor( - Constants.ADDR_AUDIO_SYSTEM, mTvLogicalAddress, sadsToRespond_2); - assertThat(mNativeWrapper.getResultMessages()).contains(expected2); - mNativeWrapper.clearResultMessages(); - action.processCommand(response2); - mTestLooper.dispatchAll(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expected2); - mNativeWrapper.clearResultMessages(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray()); - byte[] sadsToRespond_3 = new byte[0]; - HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor( - Constants.ADDR_AUDIO_SYSTEM, mTvLogicalAddress, sadsToRespond_3); - assertThat(mNativeWrapper.getResultMessages()).contains(expected3); - mNativeWrapper.clearResultMessages(); - action.processCommand(response3); - mTestLooper.dispatchAll(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expected3); - mNativeWrapper.clearResultMessages(); - mTestLooper.moveTimeForward(TIMEOUT_MS); - mTestLooper.dispatchAll(); - HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM, CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray()); - byte[] sadsToRespond_4 = new byte[]{ - 0x0D, 0x18, 0x4A, - 0x0E, 0x64, 0x5A, - 0x0F, 0x4B}; - HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor( - Constants.ADDR_AUDIO_SYSTEM, mTvLogicalAddress, sadsToRespond_4); - assertThat(mNativeWrapper.getResultMessages()).contains(expected4); - mNativeWrapper.clearResultMessages(); - action.processCommand(response4); + + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expected4); mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected2); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected3); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(expected4); assertThat(mSupportedSads.size()).isEqualTo(0); }