Enable and disable eARC in the HAL

Depending on the settings value, enable or disable on boot and wakeup.
Enable when the setting gets enabled.
Disable when the setting gets disabled.

Test: atest
Bug: 240388084

Change-Id: I74a90d26e8cde0f9acfd5eb1b33c845a6a995b18
This commit is contained in:
Nathalie Le Clair
2022-08-09 09:18:03 +02:00
parent ad77ca9fb0
commit 40355178f2
5 changed files with 203 additions and 26 deletions

View File

@@ -54,7 +54,7 @@ import java.util.concurrent.ArrayBlockingQueue;
* Class that models a logical CEC device hosted in this system. Handles initialization, CEC
* commands that call for actions customized per device type.
*/
abstract class HdmiCecLocalDevice {
abstract class HdmiCecLocalDevice extends HdmiLocalDevice {
private static final String TAG = "HdmiCecLocalDevice";
private static final int MAX_HDMI_ACTIVE_SOURCE_HISTORY = 10;

View File

@@ -713,8 +713,12 @@ public class HdmiControlService extends SystemService {
mEarcSupported &= (mEarcController != null);
}
if (isEarcSupportedAndEnabled()) {
initializeEarc(INITIATED_BY_BOOT_UP);
if (isEarcSupported()) {
if (isEarcEnabled()) {
initializeEarc(INITIATED_BY_BOOT_UP);
} else {
setEarcEnabledInHal(false);
}
}
mHdmiCecConfig.registerChangeListener(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
@@ -3386,9 +3390,15 @@ public class HdmiControlService extends SystemService {
}
}
private boolean isEarcSupportedAndEnabled() {
private boolean isEarcEnabled() {
synchronized (mLock) {
return mEarcSupported && mEarcEnabled;
return mEarcEnabled;
}
}
private boolean isEarcSupported() {
synchronized (mLock) {
return mEarcSupported;
}
}
@@ -3485,21 +3495,24 @@ public class HdmiControlService extends SystemService {
} else {
Slog.i(TAG, "Device does not support HDMI-CEC.");
}
if (isEarcSupportedAndEnabled()) {
int startReason = -1;
switch (wakeUpAction) {
case WAKE_UP_SCREEN_ON:
startReason = INITIATED_BY_SCREEN_ON;
break;
case WAKE_UP_BOOT_UP:
startReason = INITIATED_BY_BOOT_UP;
break;
default:
Slog.e(TAG, "wakeUpAction " + wakeUpAction + " not defined.");
return;
if (isEarcSupported()) {
if (isEarcEnabled()) {
int startReason = -1;
switch (wakeUpAction) {
case WAKE_UP_SCREEN_ON:
startReason = INITIATED_BY_SCREEN_ON;
break;
case WAKE_UP_BOOT_UP:
startReason = INITIATED_BY_BOOT_UP;
break;
default:
Slog.e(TAG, "wakeUpAction " + wakeUpAction + " not defined.");
return;
}
initializeEarc(startReason);
} else {
setEarcEnabledInHal(false);
}
initializeEarc(startReason);
}
// TODO: Initialize MHL local devices.
}
@@ -4394,6 +4407,7 @@ public class HdmiControlService extends SystemService {
private void initializeEarc(int initiatedBy) {
Slog.i(TAG, "eARC initialized, reason = " + initiatedBy);
setEarcEnabledInHal(true);
initializeEarcLocalDevice(initiatedBy);
}
@@ -4415,8 +4429,8 @@ public class HdmiControlService extends SystemService {
synchronized (mLock) {
mEarcEnabled = (enabled == EARC_FEATURE_ENABLED);
if (!mEarcSupported) {
Slog.i(TAG, "Enabled/disabled eARC setting, but the hardware doesn´t support eARC."
if (!isEarcSupported()) {
Slog.i(TAG, "Enabled/disabled eARC setting, but the hardware doesn´t support eARC. "
+ "This settings change doesn´t have an effect.");
return;
}
@@ -4448,6 +4462,8 @@ public class HdmiControlService extends SystemService {
@ServiceThreadOnly
private void onDisableEarc() {
disableEarcLocalDevice();
setEarcEnabledInHal(false);
clearEarcLocalDevice();
}
@@ -4471,5 +4487,17 @@ public class HdmiControlService extends SystemService {
assertRunOnServiceThread();
return mEarcLocalDevice;
}
private void disableEarcLocalDevice() {
if (mEarcLocalDevice == null) {
return;
}
mEarcLocalDevice.disableDevice();
}
@ServiceThreadOnly
@VisibleForTesting
protected void setEarcEnabledInHal(boolean enabled) {
assertRunOnServiceThread();
mEarcController.setEarcEnabled(enabled);
}
}

View File

@@ -22,9 +22,12 @@ import android.util.IndentingPrintWriter;
* Class that models a local eARC device hosted in this system.
* The class contains methods that are common between eARC TX and eARC RX devices.
*/
public class HdmiEarcLocalDevice {
public class HdmiEarcLocalDevice extends HdmiLocalDevice {
private static final String TAG = "HdmiEarcLocalDevice";
protected void disableDevice() {
}
/** Dump internal status of HdmiEarcLocalDevice object */
protected void dump(final IndentingPrintWriter pw) {
// Should be overridden in the more specific classes

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.hdmi;
/**
* Class that models an HDMI device hosted in this system.
* Can be used to share methods between CEC and eARC local devices.
* Currently just a placeholder.
*/
abstract class HdmiLocalDevice {
private static final String TAG = "HdmiLocalDevice";
}

View File

@@ -22,6 +22,7 @@ import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON;
import static com.google.common.truth.Truth.assertThat;
@@ -29,6 +30,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
@@ -128,13 +130,13 @@ public class HdmiControlServiceTest {
mLocalDevices.add(mPlaybackDeviceSpy);
mHdmiPortInfo = new HdmiPortInfo[4];
mHdmiPortInfo[0] =
new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x2100, true, false, false);
new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x2100, true, false, false, false);
mHdmiPortInfo[1] =
new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, 0x2200, true, false, false);
new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, 0x2200, true, false, false, false);
mHdmiPortInfo[2] =
new HdmiPortInfo(3, HdmiPortInfo.PORT_INPUT, 0x2000, true, false, false);
new HdmiPortInfo(3, HdmiPortInfo.PORT_INPUT, 0x2000, true, false, true, true);
mHdmiPortInfo[3] =
new HdmiPortInfo(4, HdmiPortInfo.PORT_INPUT, 0x3000, true, false, false);
new HdmiPortInfo(4, HdmiPortInfo.PORT_INPUT, 0x3000, true, false, false, false);
mNativeWrapper.setPortInfo(mHdmiPortInfo);
mHdmiControlServiceSpy.initService();
mPowerManager = new FakePowerManagerWrapper(mContextSpy);
@@ -1131,6 +1133,124 @@ public class HdmiControlServiceTest {
verify(mHdmiControlServiceSpy, times(1)).initializeEarcLocalDevice(anyInt());
}
@Test
public void disableCec_DoNotInformHalAboutEarc() {
mHdmiControlServiceSpy.setEarcSupported(true);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean());
}
@Test
public void disableEarc_informHalAboutEarc() {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(true);
}
@Test
public void enableCec_DoNotInformHalAboutEarc() {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean());
}
@Test
public void enableEarc_informHalAboutEarc() {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(false);
}
@Test
public void bootWithEarcEnabled_informHalAboutEarc() {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.initService();
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(false);
}
@Test
public void bootWithEarcDisabled_informHalAboutEarc() {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.initService();
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(true);
}
@Test
public void wakeUpWithEarcEnabled_informHalAboutEarc() {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_ENABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.onWakeUp(WAKE_UP_SCREEN_ON);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(false);
}
@Test
public void wakeUpWithEarcDisabled_informHalAboutEarc() {
mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED,
HdmiControlManager.EARC_FEATURE_DISABLED);
mHdmiControlServiceSpy.setEarcSupported(true);
mTestLooper.dispatchAll();
Mockito.clearInvocations(mHdmiControlServiceSpy);
mHdmiControlServiceSpy.onWakeUp(WAKE_UP_SCREEN_ON);
mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false);
verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(true);
}
protected static class MockPlaybackDevice extends HdmiCecLocalDevicePlayback {
private boolean mCanGoToStandby;