summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Robert Horvath <robhor@google.com> 2020-01-17 11:13:53 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-01-17 11:13:53 +0000
commitc467ff4f518c16c727103896d9d64b6e401439a9 (patch)
tree975e29c4f1fb39244bf58753a446c6b91b392528
parent28d29b36a5d53954516bcb0ba7574983f657d831 (diff)
parent04848a3e17b52ebfd3ca99bed49a295fe801fa50 (diff)
Merge "Initialize HDMI PowerStatus to standby"
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java50
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java67
2 files changed, 104 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 1794df3b602e..7c2ec78c1cbc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -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);
@@ -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;
@@ -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);
}
}
@@ -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()) {
@@ -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[] {
@@ -2667,6 +2700,13 @@ public class HdmiControlService extends SystemService {
}
@ServiceThreadOnly
+ @VisibleForTesting
+ void setPowerStatus(int powerStatus) {
+ assertRunOnServiceThread();
+ mPowerStatus = powerStatus;
+ }
+
+ @ServiceThreadOnly
boolean isPowerOnOrTransient() {
assertRunOnServiceThread();
return mPowerStatus == HdmiControlManager.POWER_STATUS_ON
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 1f660742122d..9e98427db709 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -109,15 +122,24 @@ public class HdmiControlServiceTest {
private boolean mStandbyMessageReceived;
private HdmiPortInfo[] mHdmiPortInfo;
+ @Mock private IPowerManager mIPowerManagerMock;
+
@Before
- public void SetUp() {
- mHdmiControlService =
- new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
- @Override
- boolean isStandbyMessageReceived() {
- return mStandbyMessageReceived;
- }
- };
+ 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;
+ }
+ };
mMyLooper = mTestLooper.getLooper();
mMyAudioSystemDevice =
@@ -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);
+ }
}