Loading services/core/java/com/android/server/hdmi/HdmiControlService.java +45 −5 Original line number Diff line number Diff line Loading @@ -491,7 +491,7 @@ public class HdmiControlService extends SystemService { mIoThread.start(); mIoLooper = mIoThread.getLooper(); } mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON; mPowerStatus = getInitialPowerStatus(); mProhibitMode = false; mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true); mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true); Loading Loading @@ -538,6 +538,28 @@ public class HdmiControlService extends SystemService { mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, ENABLED); } private void bootCompleted() { // on boot, if device is interactive, set HDMI CEC state as powered on as well if (mPowerManager.isInteractive() && isPowerStandbyOrTransient()) { onWakeUp(); } } /** * Returns the initial power status used when the HdmiControlService starts. */ @VisibleForTesting int getInitialPowerStatus() { // The initial power status is POWER_STATUS_TRANSIENT_TO_STANDBY. // Once boot completes the service transitions to POWER_STATUS_ON if the device is // interactive. // Quiescent boot is a special boot mode, in which the screen stays off during boot // and the device goes to sleep after boot has finished. // We don't transition to POWER_STATUS_ON initially, as we might be booting in quiescent // mode, during which we don't want to appear powered on to avoid being made active source. return HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; } @VisibleForTesting void setCecController(HdmiCecController cecController) { mCecController = cecController; Loading @@ -553,7 +575,9 @@ public class HdmiControlService extends SystemService { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { mTvInputManager = (TvInputManager) getContext().getSystemService( Context.TV_INPUT_SERVICE); mPowerManager = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { runOnServiceThread(this::bootCompleted); } } Loading @@ -579,9 +603,7 @@ public class HdmiControlService extends SystemService { * Called when the initialization of local devices is complete. */ private void onInitializeCecComplete(int initiatedBy) { if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) { mPowerStatus = HdmiControlManager.POWER_STATUS_ON; } updatePowerStatusOnInitializeCecComplete(); mWakeUpMessageReceived = false; if (isTvDeviceEnabled()) { Loading @@ -606,6 +628,17 @@ public class HdmiControlService extends SystemService { } } /** * Updates the power status once the initialization of local devices is complete. */ private void updatePowerStatusOnInitializeCecComplete() { if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) { mPowerStatus = HdmiControlManager.POWER_STATUS_ON; } else if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY) { mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; } } private void registerContentObserver() { ContentResolver resolver = getContext().getContentResolver(); String[] settings = new String[] { Loading Loading @@ -2666,6 +2699,13 @@ public class HdmiControlService extends SystemService { return mPowerStatus; } @ServiceThreadOnly @VisibleForTesting void setPowerStatus(int powerStatus) { assertRunOnServiceThread(); mPowerStatus = powerStatus; } @ServiceThreadOnly boolean isPowerOnOrTransient() { assertRunOnServiceThread(); Loading services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +59 −8 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.hdmi; import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM; import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK; import static com.android.server.SystemService.PHASE_BOOT_COMPLETED; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; import static com.google.common.truth.Truth.assertThat; Loading @@ -25,8 +26,17 @@ import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; import android.content.ContextWrapper; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPortInfo; import android.os.IPowerManager; import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; import android.os.test.TestLooper; import androidx.test.InstrumentationRegistry; Loading @@ -36,6 +46,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; Loading Loading @@ -98,6 +110,7 @@ public class HdmiControlServiceTest { } private static final String TAG = "HdmiControlServiceTest"; private Context mContextSpy; private HdmiControlService mHdmiControlService; private HdmiCecController mHdmiCecController; private HdmiCecLocalDeviceMyDevice mMyAudioSystemDevice; Loading @@ -109,10 +122,19 @@ public class HdmiControlServiceTest { private boolean mStandbyMessageReceived; private HdmiPortInfo[] mHdmiPortInfo; @Mock private IPowerManager mIPowerManagerMock; @Before public void SetUp() { mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext()) { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock, null); when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager); when(mIPowerManagerMock.isInteractive()).thenReturn(true); mHdmiControlService = new HdmiControlService(mContextSpy) { @Override boolean isStandbyMessageReceived() { return mStandbyMessageReceived; Loading Loading @@ -198,4 +220,33 @@ public class HdmiControlServiceTest { mHdmiControlService.initPortInfo(); assertThat(mHdmiControlService.pathToPortId(0x1000)).isEqualTo(Constants.INVALID_PORT_ID); } @Test public void initialPowerStatus_normalBoot_isTransientToStandby() { assertThat(mHdmiControlService.getInitialPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); } @Test public void initialPowerStatus_quiescentBoot_isTransientToStandby() throws RemoteException { when(mIPowerManagerMock.isInteractive()).thenReturn(false); assertThat(mHdmiControlService.getInitialPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); } @Test public void powerStatusAfterBootComplete_normalBoot_isOn() { mHdmiControlService.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON); mHdmiControlService.onBootPhase(PHASE_BOOT_COMPLETED); assertThat(mHdmiControlService.getPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON); } @Test public void powerStatusAfterBootComplete_quiescentBoot_isStandby() throws RemoteException { when(mIPowerManagerMock.isInteractive()).thenReturn(false); mHdmiControlService.onBootPhase(PHASE_BOOT_COMPLETED); assertThat(mHdmiControlService.getPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_STANDBY); } } Loading
services/core/java/com/android/server/hdmi/HdmiControlService.java +45 −5 Original line number Diff line number Diff line Loading @@ -491,7 +491,7 @@ public class HdmiControlService extends SystemService { mIoThread.start(); mIoLooper = mIoThread.getLooper(); } mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON; mPowerStatus = getInitialPowerStatus(); mProhibitMode = false; mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true); mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true); Loading Loading @@ -538,6 +538,28 @@ public class HdmiControlService extends SystemService { mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, ENABLED); } private void bootCompleted() { // on boot, if device is interactive, set HDMI CEC state as powered on as well if (mPowerManager.isInteractive() && isPowerStandbyOrTransient()) { onWakeUp(); } } /** * Returns the initial power status used when the HdmiControlService starts. */ @VisibleForTesting int getInitialPowerStatus() { // The initial power status is POWER_STATUS_TRANSIENT_TO_STANDBY. // Once boot completes the service transitions to POWER_STATUS_ON if the device is // interactive. // Quiescent boot is a special boot mode, in which the screen stays off during boot // and the device goes to sleep after boot has finished. // We don't transition to POWER_STATUS_ON initially, as we might be booting in quiescent // mode, during which we don't want to appear powered on to avoid being made active source. return HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; } @VisibleForTesting void setCecController(HdmiCecController cecController) { mCecController = cecController; Loading @@ -553,7 +575,9 @@ public class HdmiControlService extends SystemService { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { mTvInputManager = (TvInputManager) getContext().getSystemService( Context.TV_INPUT_SERVICE); mPowerManager = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { runOnServiceThread(this::bootCompleted); } } Loading @@ -579,9 +603,7 @@ public class HdmiControlService extends SystemService { * Called when the initialization of local devices is complete. */ private void onInitializeCecComplete(int initiatedBy) { if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) { mPowerStatus = HdmiControlManager.POWER_STATUS_ON; } updatePowerStatusOnInitializeCecComplete(); mWakeUpMessageReceived = false; if (isTvDeviceEnabled()) { Loading @@ -606,6 +628,17 @@ public class HdmiControlService extends SystemService { } } /** * Updates the power status once the initialization of local devices is complete. */ private void updatePowerStatusOnInitializeCecComplete() { if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) { mPowerStatus = HdmiControlManager.POWER_STATUS_ON; } else if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY) { mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; } } private void registerContentObserver() { ContentResolver resolver = getContext().getContentResolver(); String[] settings = new String[] { Loading Loading @@ -2666,6 +2699,13 @@ public class HdmiControlService extends SystemService { return mPowerStatus; } @ServiceThreadOnly @VisibleForTesting void setPowerStatus(int powerStatus) { assertRunOnServiceThread(); mPowerStatus = powerStatus; } @ServiceThreadOnly boolean isPowerOnOrTransient() { assertRunOnServiceThread(); Loading
services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +59 −8 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.hdmi; import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM; import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK; import static com.android.server.SystemService.PHASE_BOOT_COMPLETED; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; import static com.google.common.truth.Truth.assertThat; Loading @@ -25,8 +26,17 @@ import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; import android.content.ContextWrapper; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPortInfo; import android.os.IPowerManager; import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; import android.os.test.TestLooper; import androidx.test.InstrumentationRegistry; Loading @@ -36,6 +46,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; Loading Loading @@ -98,6 +110,7 @@ public class HdmiControlServiceTest { } private static final String TAG = "HdmiControlServiceTest"; private Context mContextSpy; private HdmiControlService mHdmiControlService; private HdmiCecController mHdmiCecController; private HdmiCecLocalDeviceMyDevice mMyAudioSystemDevice; Loading @@ -109,10 +122,19 @@ public class HdmiControlServiceTest { private boolean mStandbyMessageReceived; private HdmiPortInfo[] mHdmiPortInfo; @Mock private IPowerManager mIPowerManagerMock; @Before public void SetUp() { mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext()) { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock, null); when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager); when(mIPowerManagerMock.isInteractive()).thenReturn(true); mHdmiControlService = new HdmiControlService(mContextSpy) { @Override boolean isStandbyMessageReceived() { return mStandbyMessageReceived; Loading Loading @@ -198,4 +220,33 @@ public class HdmiControlServiceTest { mHdmiControlService.initPortInfo(); assertThat(mHdmiControlService.pathToPortId(0x1000)).isEqualTo(Constants.INVALID_PORT_ID); } @Test public void initialPowerStatus_normalBoot_isTransientToStandby() { assertThat(mHdmiControlService.getInitialPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); } @Test public void initialPowerStatus_quiescentBoot_isTransientToStandby() throws RemoteException { when(mIPowerManagerMock.isInteractive()).thenReturn(false); assertThat(mHdmiControlService.getInitialPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); } @Test public void powerStatusAfterBootComplete_normalBoot_isOn() { mHdmiControlService.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON); mHdmiControlService.onBootPhase(PHASE_BOOT_COMPLETED); assertThat(mHdmiControlService.getPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON); } @Test public void powerStatusAfterBootComplete_quiescentBoot_isStandby() throws RemoteException { when(mIPowerManagerMock.isInteractive()).thenReturn(false); mHdmiControlService.onBootPhase(PHASE_BOOT_COMPLETED); assertThat(mHdmiControlService.getPowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_STANDBY); } }