diff options
5 files changed, 116 insertions, 25 deletions
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 1ba0c52ce875..3f90dfec52ba 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -68,11 +68,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { private static final String TAG = "HdmiCecLocalDeviceAudioSystem"; - // Whether System audio mode is activated or not. - // This becomes true only when all system audio sequences are finished. - @GuardedBy("mLock") - private boolean mSystemAudioActivated; - // Whether the System Audio Control feature is enabled or not. True by default. @GuardedBy("mLock") private boolean mSystemAudioControlFeatureEnabled; @@ -271,7 +266,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { synchronized (mLock) { mService.writeStringSystemProperty( Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, - mSystemAudioActivated ? "true" : "false"); + isSystemAudioActivated() ? "true" : "false"); } terminateSystemAudioMode(); } @@ -814,7 +809,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } HdmiLogger.debug( "System Audio Mode change[old:%b new:%b]", - mSystemAudioActivated, newSystemAudioMode); + isSystemAudioActivated(), newSystemAudioMode); // Wake up device if System Audio Control is turned on if (newSystemAudioMode) { mService.wakeUp(); @@ -854,8 +849,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } updateAudioManagerForSystemAudio(newSystemAudioMode); synchronized (mLock) { - if (mSystemAudioActivated != newSystemAudioMode) { - mSystemAudioActivated = newSystemAudioMode; + if (isSystemAudioActivated() != newSystemAudioMode) { + mService.setSystemAudioActivated(newSystemAudioMode); mService.announceSystemAudioModeChange(newSystemAudioMode); } } @@ -946,9 +941,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } protected boolean isSystemAudioActivated() { - synchronized (mLock) { - return mSystemAudioActivated; - } + return mService.isSystemAudioActivated(); } protected void terminateSystemAudioMode() { @@ -1215,7 +1208,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { protected void dump(IndentingPrintWriter pw) { pw.println("HdmiCecLocalDeviceAudioSystem:"); pw.increaseIndent(); - pw.println("mSystemAudioActivated: " + mSystemAudioActivated); pw.println("isRoutingFeatureEnabled " + isRoutingControlFeatureEnabled()); pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled); pw.println("mTvSystemAudioModeSupport: " + mTvSystemAudioModeSupport); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index e7c4bf7443ee..20933db803b9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -19,6 +19,7 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemProperties; @@ -30,6 +31,7 @@ import com.android.internal.app.LocalePicker; import com.android.internal.app.LocalePicker.LocaleInfo; import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; +import com.android.server.hdmi.HdmiControlService.SendMessageCallback; import java.io.UnsupportedEncodingException; import java.util.List; @@ -85,6 +87,22 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { mAddress, mService.getPhysicalAddress(), mDeviceType)); mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand( mAddress, mService.getVendorId())); + if (mService.audioSystem() == null) { + // If current device is not a functional audio system device, + // send message to potential audio system device in the system to get the system + // audio mode status. If no response, set to false. + mService.sendCecCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus( + mAddress, Constants.ADDR_AUDIO_SYSTEM), new SendMessageCallback() { + @Override + public void onSendCompleted(int error) { + if (error != SendMessageResult.SUCCESS) { + HdmiLogger.debug( + "AVR did not respond to <Give System Audio Mode Status>"); + mService.setSystemAudioActivated(false); + } + } + }); + } startQueuedActions(); } @@ -275,6 +293,37 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } @Override + protected boolean handleSetSystemAudioMode(HdmiCecMessage message) { + // System Audio Mode only turns on/off when Audio System broadcasts on/off message. + // For device with type 4 and 5, it can set system audio mode on/off + // when there is another audio system device connected into the system first. + if (message.getDestination() != Constants.ADDR_BROADCAST + || message.getSource() != Constants.ADDR_AUDIO_SYSTEM + || mService.audioSystem() != null) { + return true; + } + boolean setSystemAudioModeOn = HdmiUtils.parseCommandParamSystemAudioStatus(message); + if (mService.isSystemAudioActivated() != setSystemAudioModeOn) { + mService.setSystemAudioActivated(setSystemAudioModeOn); + } + return true; + } + + @Override + protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) { + // Only directly addressed System Audio Mode Status message can change internal + // system audio mode status. + if (message.getDestination() == mAddress + && message.getSource() == Constants.ADDR_AUDIO_SYSTEM) { + boolean setSystemAudioModeOn = HdmiUtils.parseCommandParamSystemAudioStatus(message); + if (mService.isSystemAudioActivated() != setSystemAudioModeOn) { + mService.setSystemAudioActivated(setSystemAudioModeOn); + } + } + return true; + } + + @Override protected int findKeyReceiverAddress() { return Constants.ADDR_TV; } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index a8c435086e8e..8a7051f0e736 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -77,11 +77,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // True by default for all the ARC-enabled ports. private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray(); - // Whether System audio mode is activated or not. - // This becomes true only when all system audio sequences are finished. - @GuardedBy("mLock") - private boolean mSystemAudioActivated = false; - // Whether the System Audio Control feature is enabled or not. True by default. @GuardedBy("mLock") private boolean mSystemAudioControlFeatureEnabled; @@ -829,11 +824,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { + "because the System Audio Control feature is disabled."); return; } - HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", mSystemAudioActivated, on); + HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", + mService.isSystemAudioActivated(), on); updateAudioManagerForSystemAudio(on); synchronized (mLock) { - if (mSystemAudioActivated != on) { - mSystemAudioActivated = on; + if (mService.isSystemAudioActivated() != on) { + mService.setSystemAudioActivated(on); mService.announceSystemAudioModeChange(on); } startArcAction(on); @@ -849,9 +845,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (!hasSystemAudioDevice()) { return false; } - synchronized (mLock) { - return mSystemAudioActivated; - } + return mService.isSystemAudioActivated(); } @ServiceThreadOnly @@ -1904,7 +1898,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { super.dump(pw); pw.println("mArcEstablished: " + mArcEstablished); pw.println("mArcFeatureEnabled: " + mArcFeatureEnabled); - pw.println("mSystemAudioActivated: " + mSystemAudioActivated); pw.println("mSystemAudioMute: " + mSystemAudioMute); pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled); pw.println("mAutoDeviceOff: " + mAutoDeviceOff); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index eb29c93b1ced..7376ed2b0679 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -147,6 +147,10 @@ public class HdmiControlService extends SystemService { @GuardedBy("mLock") protected final ActiveSource mActiveSource = new ActiveSource(); + // Whether System Audio Mode is activated or not. + @GuardedBy("mLock") + private boolean mSystemAudioActivated = false; + private static final boolean isHdmiCecNeverClaimPlaybackLogicAddr = SystemProperties.getBoolean( Constants.PROPERTY_HDMI_CEC_NEVER_CLAIM_PLAYBACK_LOGICAL_ADDRESS, false); @@ -2032,6 +2036,7 @@ public class HdmiControlService extends SystemService { pw.increaseIndent(); pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled); pw.println("mMhlInputChangeEnabled: " + mMhlInputChangeEnabled); + pw.println("mSystemAudioActivated: " + isSystemAudioActivated()); pw.decreaseIndent(); pw.println("mMhlController: "); @@ -2658,6 +2663,18 @@ public class HdmiControlService extends SystemService { } } + boolean isSystemAudioActivated() { + synchronized (mLock) { + return mSystemAudioActivated; + } + } + + void setSystemAudioActivated(boolean on) { + synchronized (mLock) { + mSystemAudioActivated = on; + } + } + @ServiceThreadOnly void setCecOption(int key, boolean value) { assertRunOnServiceThread(); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index feae4eed7eb1..b8799c3f16f7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -60,6 +60,11 @@ public class HdmiCecLocalDevicePlaybackTest { boolean isControlEnabled() { return true; } + + @Override + void writeStringSystemProperty(String key, String value) { + // do nothing + } }; mMyLooper = mTestLooper.getLooper(); @@ -92,4 +97,39 @@ public class HdmiCecLocalDevicePlaybackTest { // TODO(amyjojo): Move set and get LocalActivePath to Control Service. assertThat(mHdmiCecLocalDevicePlayback.getLocalActivePath()).isEqualTo(1); } + + @Test + public void handleSetSystemAudioModeOn_audioSystemBroadcast() { + mHdmiControlService.setSystemAudioActivated(false); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse(); + HdmiCecMessage message = + HdmiCecMessageBuilder.buildSetSystemAudioMode( + Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_BROADCAST, true); + assertThat(mHdmiCecLocalDevicePlayback.handleSetSystemAudioMode(message)).isTrue(); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + } + + @Test + public void handleSetSystemAudioModeOff_audioSystemToPlayback() { + mHdmiCecLocalDevicePlayback.mService.setSystemAudioActivated(true); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + // This direct message to Playback device is invalid. + // Test should ignore it and still keep the system audio mode on. + HdmiCecMessage message = + HdmiCecMessageBuilder.buildSetSystemAudioMode( + Constants.ADDR_AUDIO_SYSTEM, mHdmiCecLocalDevicePlayback.mAddress, false); + assertThat(mHdmiCecLocalDevicePlayback.handleSetSystemAudioMode(message)).isTrue(); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + } + + @Test + public void handleSystemAudioModeStatusOn_DirectltToLocalDeviceFromAudioSystem() { + mHdmiControlService.setSystemAudioActivated(false); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse(); + HdmiCecMessage message = + HdmiCecMessageBuilder.buildReportSystemAudioMode( + Constants.ADDR_AUDIO_SYSTEM, mHdmiCecLocalDevicePlayback.mAddress, true); + assertThat(mHdmiCecLocalDevicePlayback.handleSystemAudioModeStatus(message)).isTrue(); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + } } |