Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +41 −2 Original line number Original line Diff line number Diff line Loading @@ -79,6 +79,9 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // True by default for all the ARC-enabled ports. // True by default for all the ARC-enabled ports. private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray(); private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray(); @GuardedBy("mLock") private List<byte[]> mSupportedSads = new ArrayList<>(); // Whether the System Audio Control feature is enabled or not. True by default. // Whether the System Audio Control feature is enabled or not. True by default. @GuardedBy("mLock") @GuardedBy("mLock") private boolean mSystemAudioControlFeatureEnabled; private boolean mSystemAudioControlFeatureEnabled; Loading Loading @@ -858,6 +861,13 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { new SystemAudioActionFromTv(this, avr.getLogicalAddress(), enabled, callback)); new SystemAudioActionFromTv(this, avr.getLogicalAddress(), enabled, callback)); } } void clearSads() { synchronized (mLock) { mSupportedSads.clear(); } } // # Seq 25 // # Seq 25 void setSystemAudioMode(boolean on) { void setSystemAudioMode(boolean on) { if (!isSystemAudioControlFeatureEnabled() && on) { if (!isSystemAudioControlFeatureEnabled() && on) { Loading Loading @@ -911,13 +921,41 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } } @ServiceThreadOnly @ServiceThreadOnly void enableArc(List<byte[]> supportedSads) { void enableArc() { assertRunOnServiceThread(); assertRunOnServiceThread(); HdmiLogger.debug("Set Arc Status[old:%b new:true]", mArcEstablished); HdmiLogger.debug("Set Arc Status[old:%b new:true]", mArcEstablished); enableAudioReturnChannel(true); enableAudioReturnChannel(true); notifyArcStatusToAudioService(true, supportedSads); //Ensure mSupportedSads is empty before fetching SADs synchronized (mLock) { mSupportedSads.clear(); } notifyArcStatusToAudioService(true, mSupportedSads); mArcEstablished = true; mArcEstablished = true; // Avoid triggering duplicate RequestSadAction events. // This could lead to unexpected responses from the AVR and cause the TV to receive data // out of order. The SAD report does not provide information about the order of events. if (hasAction(RequestSadAction.class)) { return; } // Send Request SAD to get real SAD instead of default empty RequestSadAction action = new RequestSadAction( this, Constants.ADDR_AUDIO_SYSTEM, new RequestSadAction.RequestSadCallback() { @Override public void onRequestSadDone(List<byte[]> supportedSadsDone) { synchronized (mLock) { mSupportedSads = supportedSadsDone; } notifyArcStatusToAudioService(false, new ArrayList<>()); synchronized (mLock) { notifyArcStatusToAudioService(true, mSupportedSads); } } }); addAndStartAction(action); } } @ServiceThreadOnly @ServiceThreadOnly Loading @@ -928,6 +966,7 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { enableAudioReturnChannel(false); enableAudioReturnChannel(false); notifyArcStatusToAudioService(false, new ArrayList<>()); notifyArcStatusToAudioService(false, new ArrayList<>()); mArcEstablished = false; mArcEstablished = false; clearSads(); } } /** /** Loading services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java +14 −29 Original line number Original line Diff line number Diff line Loading @@ -60,18 +60,6 @@ final class SetArcTransmissionStateAction extends HdmiCecFeatureAction { boolean start() { boolean start() { // Seq #37. // Seq #37. if (mEnabled) { if (mEnabled) { // Avoid triggering duplicate RequestSadAction events. // This could lead to unexpected responses from the AVR and cause the TV to receive data // out of order. The SAD report does not provide information about the order of events. if ((tv().hasAction(RequestSadAction.class))) { return true; } // Request SADs before enabling ARC RequestSadAction action = new RequestSadAction( localDevice(), Constants.ADDR_AUDIO_SYSTEM, new RequestSadAction.RequestSadCallback() { @Override public void onRequestSadDone(List<byte[]> supportedSads) { // Enable ARC status immediately before sending <Report Arc Initiated>. // Enable ARC status immediately before sending <Report Arc Initiated>. // If AVR responds with <Feature Abort>, disable ARC status again. // If AVR responds with <Feature Abort>, disable ARC status again. // This is different from spec that says that turns ARC status to // This is different from spec that says that turns ARC status to Loading @@ -80,15 +68,12 @@ final class SetArcTransmissionStateAction extends HdmiCecFeatureAction { // But implemented this way to save the time having to wait for // But implemented this way to save the time having to wait for // <Feature Abort>. // <Feature Abort>. Slog.i(TAG, "Enabling ARC"); Slog.i(TAG, "Enabling ARC"); tv().enableArc(supportedSads); tv().enableArc(); // If succeeds to send <Report ARC Initiated>, wait general timeout to // If succeeds to send <Report ARC Initiated>, wait general timeout to // check whether there is no <Feature Abort> for <Report ARC Initiated>. // check whether there is no <Feature Abort> for <Report ARC Initiated>. mState = STATE_WAITING_TIMEOUT; mState = STATE_WAITING_TIMEOUT; addTimer(mState, HdmiConfig.TIMEOUT_MS); addTimer(mState, HdmiConfig.TIMEOUT_MS); sendReportArcInitiated(); sendReportArcInitiated(); } }); addAndStartAction(action); } else { } else { disableArc(); disableArc(); finish(); finish(); Loading services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +2 −53 Original line number Original line Diff line number Diff line Loading @@ -341,18 +341,9 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); // But we need to check SADs started to be queried at this time assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mNativeWrapper.clearResultMessages(); } } Loading Loading @@ -752,17 +743,6 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); } } Loading Loading @@ -1067,16 +1047,6 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); mNativeWrapper.clearResultMessages(); mNativeWrapper.clearResultMessages(); Loading Loading @@ -1268,16 +1238,6 @@ public class HdmiCecLocalDeviceTvTest { mNativeWrapper.onCecMessage(initiateArc); mNativeWrapper.onCecMessage(initiateArc); mTestLooper.dispatchAll(); mTestLooper.dispatchAll(); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } // ARC should be established after RequestSadAction is finished assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); Loading Loading @@ -1421,17 +1381,6 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); } } Loading Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +41 −2 Original line number Original line Diff line number Diff line Loading @@ -79,6 +79,9 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // True by default for all the ARC-enabled ports. // True by default for all the ARC-enabled ports. private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray(); private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray(); @GuardedBy("mLock") private List<byte[]> mSupportedSads = new ArrayList<>(); // Whether the System Audio Control feature is enabled or not. True by default. // Whether the System Audio Control feature is enabled or not. True by default. @GuardedBy("mLock") @GuardedBy("mLock") private boolean mSystemAudioControlFeatureEnabled; private boolean mSystemAudioControlFeatureEnabled; Loading Loading @@ -858,6 +861,13 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { new SystemAudioActionFromTv(this, avr.getLogicalAddress(), enabled, callback)); new SystemAudioActionFromTv(this, avr.getLogicalAddress(), enabled, callback)); } } void clearSads() { synchronized (mLock) { mSupportedSads.clear(); } } // # Seq 25 // # Seq 25 void setSystemAudioMode(boolean on) { void setSystemAudioMode(boolean on) { if (!isSystemAudioControlFeatureEnabled() && on) { if (!isSystemAudioControlFeatureEnabled() && on) { Loading Loading @@ -911,13 +921,41 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } } @ServiceThreadOnly @ServiceThreadOnly void enableArc(List<byte[]> supportedSads) { void enableArc() { assertRunOnServiceThread(); assertRunOnServiceThread(); HdmiLogger.debug("Set Arc Status[old:%b new:true]", mArcEstablished); HdmiLogger.debug("Set Arc Status[old:%b new:true]", mArcEstablished); enableAudioReturnChannel(true); enableAudioReturnChannel(true); notifyArcStatusToAudioService(true, supportedSads); //Ensure mSupportedSads is empty before fetching SADs synchronized (mLock) { mSupportedSads.clear(); } notifyArcStatusToAudioService(true, mSupportedSads); mArcEstablished = true; mArcEstablished = true; // Avoid triggering duplicate RequestSadAction events. // This could lead to unexpected responses from the AVR and cause the TV to receive data // out of order. The SAD report does not provide information about the order of events. if (hasAction(RequestSadAction.class)) { return; } // Send Request SAD to get real SAD instead of default empty RequestSadAction action = new RequestSadAction( this, Constants.ADDR_AUDIO_SYSTEM, new RequestSadAction.RequestSadCallback() { @Override public void onRequestSadDone(List<byte[]> supportedSadsDone) { synchronized (mLock) { mSupportedSads = supportedSadsDone; } notifyArcStatusToAudioService(false, new ArrayList<>()); synchronized (mLock) { notifyArcStatusToAudioService(true, mSupportedSads); } } }); addAndStartAction(action); } } @ServiceThreadOnly @ServiceThreadOnly Loading @@ -928,6 +966,7 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { enableAudioReturnChannel(false); enableAudioReturnChannel(false); notifyArcStatusToAudioService(false, new ArrayList<>()); notifyArcStatusToAudioService(false, new ArrayList<>()); mArcEstablished = false; mArcEstablished = false; clearSads(); } } /** /** Loading
services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java +14 −29 Original line number Original line Diff line number Diff line Loading @@ -60,18 +60,6 @@ final class SetArcTransmissionStateAction extends HdmiCecFeatureAction { boolean start() { boolean start() { // Seq #37. // Seq #37. if (mEnabled) { if (mEnabled) { // Avoid triggering duplicate RequestSadAction events. // This could lead to unexpected responses from the AVR and cause the TV to receive data // out of order. The SAD report does not provide information about the order of events. if ((tv().hasAction(RequestSadAction.class))) { return true; } // Request SADs before enabling ARC RequestSadAction action = new RequestSadAction( localDevice(), Constants.ADDR_AUDIO_SYSTEM, new RequestSadAction.RequestSadCallback() { @Override public void onRequestSadDone(List<byte[]> supportedSads) { // Enable ARC status immediately before sending <Report Arc Initiated>. // Enable ARC status immediately before sending <Report Arc Initiated>. // If AVR responds with <Feature Abort>, disable ARC status again. // If AVR responds with <Feature Abort>, disable ARC status again. // This is different from spec that says that turns ARC status to // This is different from spec that says that turns ARC status to Loading @@ -80,15 +68,12 @@ final class SetArcTransmissionStateAction extends HdmiCecFeatureAction { // But implemented this way to save the time having to wait for // But implemented this way to save the time having to wait for // <Feature Abort>. // <Feature Abort>. Slog.i(TAG, "Enabling ARC"); Slog.i(TAG, "Enabling ARC"); tv().enableArc(supportedSads); tv().enableArc(); // If succeeds to send <Report ARC Initiated>, wait general timeout to // If succeeds to send <Report ARC Initiated>, wait general timeout to // check whether there is no <Feature Abort> for <Report ARC Initiated>. // check whether there is no <Feature Abort> for <Report ARC Initiated>. mState = STATE_WAITING_TIMEOUT; mState = STATE_WAITING_TIMEOUT; addTimer(mState, HdmiConfig.TIMEOUT_MS); addTimer(mState, HdmiConfig.TIMEOUT_MS); sendReportArcInitiated(); sendReportArcInitiated(); } }); addAndStartAction(action); } else { } else { disableArc(); disableArc(); finish(); finish(); Loading
services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +2 −53 Original line number Original line Diff line number Diff line Loading @@ -341,18 +341,9 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); // But we need to check SADs started to be queried at this time assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mNativeWrapper.clearResultMessages(); } } Loading Loading @@ -752,17 +743,6 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); } } Loading Loading @@ -1067,16 +1047,6 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); mNativeWrapper.clearResultMessages(); mNativeWrapper.clearResultMessages(); Loading Loading @@ -1268,16 +1238,6 @@ public class HdmiCecLocalDeviceTvTest { mNativeWrapper.onCecMessage(initiateArc); mNativeWrapper.onCecMessage(initiateArc); mTestLooper.dispatchAll(); mTestLooper.dispatchAll(); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } // ARC should be established after RequestSadAction is finished assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); Loading Loading @@ -1421,17 +1381,6 @@ public class HdmiCecLocalDeviceTvTest { HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( ADDR_TV, ADDR_TV, ADDR_AUDIO_SYSTEM); ADDR_AUDIO_SYSTEM); // <Report ARC Initiated> should only be sent after SAD querying is done assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); // Finish querying SADs for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) { assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); } assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); } } Loading