Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +6 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.server.hdmi.HdmiControlService.SendMessageCallback; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Locale; import java.util.Objects; /** * Represent a logical device of type Playback residing in Android system. Loading Loading @@ -171,7 +172,11 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } if (mService.isHdmiControlEnhancedBehaviorFlagEnabled()) { if (!hasAction(PowerStatusMonitorActionFromPlayback.class)) { if (mService.getHdmiCecConfig().getStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST) .equals(HdmiControlManager .POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW) && !hasAction(PowerStatusMonitorActionFromPlayback.class)) { addAndStartAction( new PowerStatusMonitorActionFromPlayback( HdmiCecLocalDevicePlayback.this)); Loading services/core/java/com/android/server/hdmi/PowerStatusMonitorActionFromPlayback.java +23 −4 Original line number Diff line number Diff line Loading @@ -34,12 +34,17 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { // State that waits for <Report Power Status> once sending <Give Device Power Status> // to the TV. private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 2; // Number of consecutive standby reports required before going to standby. private static final int REQUIRED_CONSECUTIVE_STANDBY_REPORTS = 2; // Monitoring interval (60s) @VisibleForTesting protected static final int MONITORING_INTERVAL_MS = 60000; // Timeout once sending <Give Device Power Status> // Counter for consecutive standby reports private int mConsecutiveStandbyReports = 0; PowerStatusMonitorActionFromPlayback(HdmiCecLocalDevice source) { super(source); } Loading @@ -49,6 +54,7 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { // Start after timeout since the device just finished allocation. mState = STATE_WAIT_FOR_NEXT_MONITORING; addTimer(mState, MONITORING_INTERVAL_MS); mConsecutiveStandbyReports = 0; return true; } Loading @@ -64,13 +70,21 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { private boolean handleReportPowerStatusFromTv(HdmiCecMessage cmd) { int powerStatus = cmd.getParams()[0] & 0xFF; if (powerStatus == POWER_STATUS_STANDBY) { Slog.d(TAG, "TV reported it turned off, going to sleep."); if (powerStatus != POWER_STATUS_STANDBY) { mConsecutiveStandbyReports = 0; // Reset counter if TV is not in standby. } else { mConsecutiveStandbyReports++; // Increase counter if TV reports standby. } if (mConsecutiveStandbyReports >= REQUIRED_CONSECUTIVE_STANDBY_REPORTS) { Slog.d(TAG, "TV reported standby, going to sleep."); source().getService().standby(); finish(); return true; } return false; // Schedule next monitoring. mState = STATE_WAIT_FOR_NEXT_MONITORING; addTimer(mState, MONITORING_INTERVAL_MS); return true; } @Override Loading @@ -84,6 +98,11 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { queryPowerStatus(); break; case STATE_WAIT_FOR_REPORT_POWER_STATUS: // Timer expired while waiting for <Report Power Status>. // This means we didn't receive a power status report from the TV in time. Slog.d(TAG, "Timeout waiting for <Report Power Status>." + " Resetting standby counter."); mConsecutiveStandbyReports = 0; // Reset counter on timeout mState = STATE_WAIT_FOR_NEXT_MONITORING; addTimer(mState, MONITORING_INTERVAL_MS); break; Loading services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +136 −5 Original line number Diff line number Diff line Loading @@ -2903,14 +2903,18 @@ public class HdmiCecLocalDevicePlaybackTest { } @Test public void powerStatusMonitorActionFromPlayback_TvReportPowerOff_goToSleep() { public void powerStatusMonitorActionFromPlayback_TvReportsStandbyTwice_goesToSleep() { mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW); mTestLooper.dispatchAll(); mHdmiControlService.onWakeUp(HdmiControlService.WAKE_UP_SCREEN_ON); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).hasSize(1); assertThat(mPowerManager.isInteractive()).isTrue(); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); Loading @@ -2924,23 +2928,150 @@ public class HdmiCecLocalDevicePlaybackTest { HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_STANDBY); assertThat(mNativeWrapper.getResultMessages().contains(givePowerStatus)).isTrue(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); // TV reports Standby (1st time) mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Should not go to sleep yet. mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); // TV reports Standby (2nd time) mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); // Playback device should go to sleep assertThat(mPowerManager.isInteractive()).isFalse(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).isEmpty(); } @Test public void powerStatusMonitorActionFromPlayback_StandbyThenOnThenStandbyTwice_goesToSleep() { mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW); mTestLooper.dispatchAll(); mHdmiControlService.onWakeUp(HdmiControlService.WAKE_UP_SCREEN_ON); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).hasSize(1); assertThat(mPowerManager.isInteractive()).isTrue(); HdmiCecMessage givePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(mPlaybackLogicalAddress, Constants.ADDR_TV); HdmiCecMessage reportPowerStatusTvStandby = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_STANDBY); HdmiCecMessage reportPowerStatusTvOn = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_ON); // First monitoring cycle: TV reports Standby (1st time) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Second monitoring cycle: TV reports On (resets counter) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvOn); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Third monitoring cycle: TV reports Standby (1st consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Fourth monitoring cycle: TV reports Standby (2nd consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isFalse(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).isEmpty(); } @Test public void powerStatusMonitorActionFromPlayback_StandbyTimeoutStandbyTwice_goesToSleep() { mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW); mTestLooper.dispatchAll(); mHdmiControlService.onWakeUp(HdmiControlService.WAKE_UP_SCREEN_ON); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).hasSize(1); assertThat(mPowerManager.isInteractive()).isTrue(); HdmiCecMessage givePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(mPlaybackLogicalAddress, Constants.ADDR_TV); HdmiCecMessage reportPowerStatusTvStandby = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_STANDBY); // First monitoring cycle: TV reports Standby (1st time) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Second monitoring cycle: Timeout waiting for report (resets counter) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); // Triggers <Give Power Status> mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.moveTimeForward(TIMEOUT_MS); // Timeout for <Report Power Status> mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Third monitoring cycle: TV reports Standby (1st consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); assertThat(mNativeWrapper.getResultMessages().contains(givePowerStatus)).isTrue(); // Fourth monitoring cycle: TV reports Standby (2nd consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isFalse(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).isEmpty(); } private void skipActiveSourceLostUi(long idleDuration, boolean activeSourceLostToTv, Loading Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +6 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.server.hdmi.HdmiControlService.SendMessageCallback; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Locale; import java.util.Objects; /** * Represent a logical device of type Playback residing in Android system. Loading Loading @@ -171,7 +172,11 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } if (mService.isHdmiControlEnhancedBehaviorFlagEnabled()) { if (!hasAction(PowerStatusMonitorActionFromPlayback.class)) { if (mService.getHdmiCecConfig().getStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST) .equals(HdmiControlManager .POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW) && !hasAction(PowerStatusMonitorActionFromPlayback.class)) { addAndStartAction( new PowerStatusMonitorActionFromPlayback( HdmiCecLocalDevicePlayback.this)); Loading
services/core/java/com/android/server/hdmi/PowerStatusMonitorActionFromPlayback.java +23 −4 Original line number Diff line number Diff line Loading @@ -34,12 +34,17 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { // State that waits for <Report Power Status> once sending <Give Device Power Status> // to the TV. private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 2; // Number of consecutive standby reports required before going to standby. private static final int REQUIRED_CONSECUTIVE_STANDBY_REPORTS = 2; // Monitoring interval (60s) @VisibleForTesting protected static final int MONITORING_INTERVAL_MS = 60000; // Timeout once sending <Give Device Power Status> // Counter for consecutive standby reports private int mConsecutiveStandbyReports = 0; PowerStatusMonitorActionFromPlayback(HdmiCecLocalDevice source) { super(source); } Loading @@ -49,6 +54,7 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { // Start after timeout since the device just finished allocation. mState = STATE_WAIT_FOR_NEXT_MONITORING; addTimer(mState, MONITORING_INTERVAL_MS); mConsecutiveStandbyReports = 0; return true; } Loading @@ -64,13 +70,21 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { private boolean handleReportPowerStatusFromTv(HdmiCecMessage cmd) { int powerStatus = cmd.getParams()[0] & 0xFF; if (powerStatus == POWER_STATUS_STANDBY) { Slog.d(TAG, "TV reported it turned off, going to sleep."); if (powerStatus != POWER_STATUS_STANDBY) { mConsecutiveStandbyReports = 0; // Reset counter if TV is not in standby. } else { mConsecutiveStandbyReports++; // Increase counter if TV reports standby. } if (mConsecutiveStandbyReports >= REQUIRED_CONSECUTIVE_STANDBY_REPORTS) { Slog.d(TAG, "TV reported standby, going to sleep."); source().getService().standby(); finish(); return true; } return false; // Schedule next monitoring. mState = STATE_WAIT_FOR_NEXT_MONITORING; addTimer(mState, MONITORING_INTERVAL_MS); return true; } @Override Loading @@ -84,6 +98,11 @@ public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { queryPowerStatus(); break; case STATE_WAIT_FOR_REPORT_POWER_STATUS: // Timer expired while waiting for <Report Power Status>. // This means we didn't receive a power status report from the TV in time. Slog.d(TAG, "Timeout waiting for <Report Power Status>." + " Resetting standby counter."); mConsecutiveStandbyReports = 0; // Reset counter on timeout mState = STATE_WAIT_FOR_NEXT_MONITORING; addTimer(mState, MONITORING_INTERVAL_MS); break; Loading
services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +136 −5 Original line number Diff line number Diff line Loading @@ -2903,14 +2903,18 @@ public class HdmiCecLocalDevicePlaybackTest { } @Test public void powerStatusMonitorActionFromPlayback_TvReportPowerOff_goToSleep() { public void powerStatusMonitorActionFromPlayback_TvReportsStandbyTwice_goesToSleep() { mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW); mTestLooper.dispatchAll(); mHdmiControlService.onWakeUp(HdmiControlService.WAKE_UP_SCREEN_ON); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).hasSize(1); assertThat(mPowerManager.isInteractive()).isTrue(); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); Loading @@ -2924,23 +2928,150 @@ public class HdmiCecLocalDevicePlaybackTest { HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_STANDBY); assertThat(mNativeWrapper.getResultMessages().contains(givePowerStatus)).isTrue(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); // TV reports Standby (1st time) mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Should not go to sleep yet. mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); // TV reports Standby (2nd time) mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); // Playback device should go to sleep assertThat(mPowerManager.isInteractive()).isFalse(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).isEmpty(); } @Test public void powerStatusMonitorActionFromPlayback_StandbyThenOnThenStandbyTwice_goesToSleep() { mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW); mTestLooper.dispatchAll(); mHdmiControlService.onWakeUp(HdmiControlService.WAKE_UP_SCREEN_ON); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).hasSize(1); assertThat(mPowerManager.isInteractive()).isTrue(); HdmiCecMessage givePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(mPlaybackLogicalAddress, Constants.ADDR_TV); HdmiCecMessage reportPowerStatusTvStandby = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_STANDBY); HdmiCecMessage reportPowerStatusTvOn = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_ON); // First monitoring cycle: TV reports Standby (1st time) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Second monitoring cycle: TV reports On (resets counter) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvOn); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Third monitoring cycle: TV reports Standby (1st consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Fourth monitoring cycle: TV reports Standby (2nd consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isFalse(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).isEmpty(); } @Test public void powerStatusMonitorActionFromPlayback_StandbyTimeoutStandbyTwice_goesToSleep() { mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW); mTestLooper.dispatchAll(); mHdmiControlService.onWakeUp(HdmiControlService.WAKE_UP_SCREEN_ON); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).hasSize(1); assertThat(mPowerManager.isInteractive()).isTrue(); HdmiCecMessage givePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(mPlaybackLogicalAddress, Constants.ADDR_TV); HdmiCecMessage reportPowerStatusTvStandby = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_STANDBY); // First monitoring cycle: TV reports Standby (1st time) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Second monitoring cycle: Timeout waiting for report (resets counter) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); // Triggers <Give Power Status> mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.moveTimeForward(TIMEOUT_MS); // Timeout for <Report Power Status> mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); // Third monitoring cycle: TV reports Standby (1st consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isTrue(); assertThat(mNativeWrapper.getResultMessages().contains(givePowerStatus)).isTrue(); // Fourth monitoring cycle: TV reports Standby (2nd consecutive) mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(givePowerStatus); mNativeWrapper.clearResultMessages(); mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); mTestLooper.dispatchAll(); assertThat(mPowerManager.isInteractive()).isFalse(); assertThat(mHdmiCecLocalDevicePlayback.getActions( PowerStatusMonitorActionFromPlayback.class)).isEmpty(); } private void skipActiveSourceLostUi(long idleDuration, boolean activeSourceLostToTv, Loading