diff options
3 files changed, 155 insertions, 69 deletions
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index ba5ee0231753..dea9309d550b 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -295,6 +295,13 @@ final class Constants { "persist.sys.hdmi.last_system_audio_control"; /** + * Property to indicate if device supports ARC or not + * <p>Default is true. + */ + static final String PROPERTY_ARC_SUPPORT = + "persist.sys.hdmi.property_arc_support"; + + /** * Property to save the audio port to switch to when system audio control is on. * <P>Audio system should switch to this port when cec active source is not its child in the tree * or is not itself. diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 7aab75090b19..ca85249b1f87 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -189,15 +189,14 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleRequestArcInitiate(HdmiCecMessage message) { assertRunOnServiceThread(); - // TODO(b/80296911): Check if ARC supported. - - // TODO(b/80296911): Check if port is ready to accept. - - // TODO(b/80296911): if both true, activate ARC functinality and - mService.sendCecCommand( - HdmiCecMessageBuilder.buildInitiateArc(mAddress, message.getSource())); - // TODO(b/80296911): else, send <Feature Abort>["Unrecongnized opcode"] - + if (!SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) { + mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE); + } else if (!isDirectConnectToTv()) { + HdmiLogger.debug("AVR device is not directly connected with TV"); + mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); + } else { + addAndStartAction(new ArcInitiationActionFromAvr(this)); + } return true; } @@ -205,15 +204,14 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleRequestArcTermination(HdmiCecMessage message) { assertRunOnServiceThread(); - // TODO(b/80297105): Check if ARC supported. - - // TODO(b/80297105): Check is currently in arc. - - // TODO(b/80297105): If both true, deactivate ARC functionality and - mService.sendCecCommand( - HdmiCecMessageBuilder.buildTerminateArc(mAddress, message.getSource())); - // TODO(b/80297105): else, send <Feature Abort>["Unrecongnized opcode"] - + if (!SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) { + mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE); + } else if (!isArcEnabled()) { + HdmiLogger.debug("ARC is not established between TV and AVR device"); + mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); + } else { + addAndStartAction(new ArcTerminationActionFromAvr(this)); + } return true; } @@ -377,6 +375,11 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { // TODO(b/111396634): switch input according to PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT } + protected boolean isDirectConnectToTv() { + int myPhysicalAddress = mService.getPhysicalAddress(); + return (myPhysicalAddress & Constants.ROUTING_PATH_TOP_MASK) == myPhysicalAddress; + } + private void updateAudioManagerForSystemAudio(boolean on) { int device = mService.getAudioManager().setHdmiSystemAudioSupported(on); HdmiLogger.debug("[A]UpdateSystemAudio mode[on=%b] output=[%X]", on, device); @@ -435,4 +438,11 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { void setTvSystemAudioModeSupport(boolean supported) { mTvSystemAudioModeSupport = supported; } + + @VisibleForTesting + protected boolean isArcEnabled() { + synchronized (mLock) { + return mArcEstablished; + } + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java index 6845b2a9a5cc..5e7a2522f025 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java @@ -24,10 +24,13 @@ import static com.google.common.truth.Truth.assertThat; import android.media.AudioManager; import android.os.Looper; +import android.os.SystemProperties; import android.os.test.TestLooper; import android.support.test.filters.SmallTest; import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; +import java.util.List; import java.util.ArrayList; +import java.util.Collections; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -100,12 +103,19 @@ public class HdmiCecLocalDeviceAudioSystemTest { default: } } + + @Override + public void setWiredDeviceConnectionState( + int type, int state, String address, String name) { + // Do nothing. + } }; } @Override void wakeUp() {} }; + mMyLooper = mTestLooper.getLooper(); mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(mHdmiControlService); mHdmiCecLocalDeviceAudioSystem.init(); @@ -121,6 +131,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { // No TV device interacts with AVR so system audio control won't be turned on here mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); + SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "true"); } @Test @@ -135,7 +146,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessage messageGive = HdmiCecMessageBuilder.buildGiveAudioStatus(ADDR_TV, ADDR_AUDIO_SYSTEM); assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(messageGive)) - .isEqualTo(true); + .isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); } @@ -147,33 +158,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessage messageGive = HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM); assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) - .isEqualTo(true); - mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); - } - - @Test - public void handleRequestArcInitiate() { - // TODO(b/80296911): Add tests when finishing handler impl. - HdmiCecMessage expectedMessage = - HdmiCecMessageBuilder.buildInitiateArc(ADDR_AUDIO_SYSTEM, ADDR_TV); - HdmiCecMessage message = - HdmiCecMessageBuilder.buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM); - assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)) - .isEqualTo(true); - mTestLooper.dispatchAll(); - assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); - } - - @Test - public void handleRequestArcTermination() { - // TODO(b/80297105): Add tests when finishing handler impl. - HdmiCecMessage expectedMessage = - HdmiCecMessageBuilder.buildTerminateArc(ADDR_AUDIO_SYSTEM, ADDR_TV); - HdmiCecMessage messageRequestOff = - HdmiCecMessageBuilder.buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM); - assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(messageRequestOff)) - .isEqualTo(true); + .isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); } @@ -189,25 +174,25 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false); assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) - .isEqualTo(true); + .isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); // Check if correctly turned on expectedMessage = HdmiCecMessageBuilder.buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, true); assertThat(mHdmiCecLocalDeviceAudioSystem.handleSetSystemAudioMode(messageSet)) - .isEqualTo(true); + .isTrue(); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) - .isEqualTo(true); + .isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); - assertThat(mMusicMute).isEqualTo(false); + assertThat(mMusicMute).isFalse(); } @Test public void handleSystemAudioModeRequest_turnOffByTv() { - assertThat(mMusicMute).isEqualTo(false); + assertThat(mMusicMute).isFalse(); // Check if feature correctly turned off HdmiCecMessage messageGive = HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM); @@ -218,16 +203,16 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); assertThat(mHdmiCecLocalDeviceAudioSystem.handleSystemAudioModeRequest(messageRequestOff)) - .isEqualTo(true); + .isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); expectedMessage = HdmiCecMessageBuilder.buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false); assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) - .isEqualTo(true); + .isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); - assertThat(mMusicMute).isEqualTo(true); + assertThat(mMusicMute).isTrue(); } @Test @@ -241,7 +226,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); - assertThat(mMusicMute).isEqualTo(true); + assertThat(mMusicMute).isTrue(); } @Test @@ -292,37 +277,38 @@ public class HdmiCecLocalDeviceAudioSystemTest { public void handleActiveSource_updateActiveSource() { HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000); ActiveSource expectedActiveSource = new ActiveSource(ADDR_TV, 0x0000); - assertThat(mHdmiCecLocalDeviceAudioSystem.handleActiveSource(message)).isEqualTo(true); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleActiveSource(message)) + .isTrue(); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().equals(expectedActiveSource)) - .isEqualTo(true); + .isTrue(); } @Test public void terminateSystemAudioMode_systemAudioModeOff() { mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(false); - assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(false); + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse(); mMusicMute = false; HdmiCecMessage message = HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode(); - assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(false); - assertThat(mMusicMute).isEqualTo(false); + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse(); + assertThat(mMusicMute).isFalse(); assertThat(mNativeWrapper.getResultMessages()).doesNotContain(message); } @Test public void terminateSystemAudioMode_systemAudioModeOn() { mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(true); - assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(true); + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue(); mMusicMute = false; HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode(); - assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(false); - assertThat(mMusicMute).isEqualTo(true); + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse(); + assertThat(mMusicMute).isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); } @@ -332,7 +318,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { int targetPhysicalAddress = 0x1000; mNativeWrapper.setPhysicalAddress(0x1000); assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress)) - .isEqualTo(true); + .isTrue(); } @Test @@ -340,7 +326,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { int targetPhysicalAddress = 0x1100; mNativeWrapper.setPhysicalAddress(0x1000); assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress)) - .isEqualTo(true); + .isTrue(); } @Test @@ -348,21 +334,104 @@ public class HdmiCecLocalDeviceAudioSystemTest { int targetPhysicalAddress = 0x3000; mNativeWrapper.setPhysicalAddress(0x2000); assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress)) - .isEqualTo(false); + .isFalse(); targetPhysicalAddress = 0x2200; mNativeWrapper.setPhysicalAddress(0x3300); assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress)) - .isEqualTo(false); + .isFalse(); targetPhysicalAddress = 0x2213; mNativeWrapper.setPhysicalAddress(0x2212); assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress)) - .isEqualTo(false); + .isFalse(); targetPhysicalAddress = 0x2340; mNativeWrapper.setPhysicalAddress(0x2310); assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress)) - .isEqualTo(false); + .isFalse(); + } + + @Test + public void handleRequestArcInitiate_isNotDirectConnectedToTv() { + HdmiCecMessage message = HdmiCecMessageBuilder + .buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM); + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder + .buildFeatureAbortCommand( + ADDR_AUDIO_SYSTEM, ADDR_TV, + Constants.MESSAGE_REQUEST_ARC_INITIATION, + Constants.ABORT_NOT_IN_CORRECT_MODE); + mNativeWrapper.setPhysicalAddress(0x1100); + + assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)) + .isTrue(); + mTestLooper.dispatchAll(); + assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); + } + + @Test + public void handleRequestArcInitiate_startArcInitiationActionFromAvr() { + HdmiCecMessage message = HdmiCecMessageBuilder + .buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM); + mNativeWrapper.setPhysicalAddress(0x1000); + mHdmiCecLocalDeviceAudioSystem.removeAction( + ArcInitiationActionFromAvr.class); + + assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)) + .isTrue(); + mTestLooper.dispatchAll(); + assertThat(mHdmiCecLocalDeviceAudioSystem + .getActions(ArcInitiationActionFromAvr.class)).isNotEmpty(); + } + + @Test + public void handleRequestArcTerminate_arcIsOn_startTerminationActionFromAvr() { + mHdmiCecLocalDeviceAudioSystem.setArcStatus(true); + assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isTrue(); + + HdmiCecMessage message = HdmiCecMessageBuilder + .buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM); + mHdmiCecLocalDeviceAudioSystem.removeAction( + ArcTerminationActionFromAvr.class); + + assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(message)) + .isTrue(); + mTestLooper.dispatchAll(); + assertThat(mHdmiCecLocalDeviceAudioSystem + .getActions(ArcTerminationActionFromAvr.class)).isNotEmpty(); + } + + @Test + public void handleRequestArcTerminate_arcIsNotOn() { + assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse(); + HdmiCecMessage message = HdmiCecMessageBuilder + .buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM); + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder + .buildFeatureAbortCommand( + ADDR_AUDIO_SYSTEM, ADDR_TV, + Constants.MESSAGE_REQUEST_ARC_TERMINATION, + Constants.ABORT_NOT_IN_CORRECT_MODE); + + assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(message)) + .isTrue(); + mTestLooper.dispatchAll(); + assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); + } + + @Test + public void handleRequestArcInit_arcIsNotSupported() { + HdmiCecMessage message = HdmiCecMessageBuilder + .buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM); + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder + .buildFeatureAbortCommand( + ADDR_AUDIO_SYSTEM, ADDR_TV, + Constants.MESSAGE_REQUEST_ARC_INITIATION, + Constants.ABORT_UNRECOGNIZED_OPCODE); + SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "false"); + + assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)) + .isTrue(); + mTestLooper.dispatchAll(); + assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); } } |