Merge "Prevent power state queries for 2.0 devices" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d0c396e66f
@@ -17,6 +17,7 @@ package com.android.server.hdmi;
|
||||
|
||||
import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_UNKNOWN;
|
||||
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.hardware.hdmi.HdmiDeviceInfo;
|
||||
import android.hardware.tv.cec.V1_0.SendMessageResult;
|
||||
import android.util.SparseIntArray;
|
||||
@@ -108,7 +109,10 @@ public class PowerStatusMonitorAction extends HdmiCecFeatureAction {
|
||||
private void resetPowerStatus(List<HdmiDeviceInfo> deviceInfos) {
|
||||
mPowerStatus.clear();
|
||||
for (HdmiDeviceInfo info : deviceInfos) {
|
||||
mPowerStatus.append(info.getLogicalAddress(), info.getDevicePowerStatus());
|
||||
if (localDevice().mService.getCecVersion() < HdmiControlManager.HDMI_CEC_VERSION_2_0
|
||||
|| info.getCecVersion() < HdmiControlManager.HDMI_CEC_VERSION_2_0) {
|
||||
mPowerStatus.append(info.getLogicalAddress(), info.getDevicePowerStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,19 +121,22 @@ public class PowerStatusMonitorAction extends HdmiCecFeatureAction {
|
||||
localDevice().mService.getHdmiCecNetwork().getDeviceInfoList(false);
|
||||
resetPowerStatus(deviceInfos);
|
||||
for (HdmiDeviceInfo info : deviceInfos) {
|
||||
final int logicalAddress = info.getLogicalAddress();
|
||||
sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
|
||||
logicalAddress),
|
||||
new SendMessageCallback() {
|
||||
@Override
|
||||
public void onSendCompleted(int error) {
|
||||
// If fails to send <Give Device Power Status>,
|
||||
// update power status into UNKNOWN.
|
||||
if (error != SendMessageResult.SUCCESS) {
|
||||
updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, true);
|
||||
if (localDevice().mService.getCecVersion() < HdmiControlManager.HDMI_CEC_VERSION_2_0
|
||||
|| info.getCecVersion() < HdmiControlManager.HDMI_CEC_VERSION_2_0) {
|
||||
final int logicalAddress = info.getLogicalAddress();
|
||||
sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
|
||||
logicalAddress),
|
||||
new SendMessageCallback() {
|
||||
@Override
|
||||
public void onSendCompleted(int error) {
|
||||
// If fails to send <Give Device Power Status>,
|
||||
// update power status into UNKNOWN.
|
||||
if (error != SendMessageResult.SUCCESS) {
|
||||
updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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;
|
||||
|
||||
import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
|
||||
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
|
||||
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
|
||||
import static com.android.server.hdmi.Constants.ADDR_TV;
|
||||
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
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.HdmiDeviceInfo;
|
||||
import android.hardware.hdmi.HdmiPortInfo;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Handler;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.IThermalService;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.test.TestLooper;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
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;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** Tests for {@link ActiveSourceAction} */
|
||||
@SmallTest
|
||||
@RunWith(JUnit4.class)
|
||||
public class PowerStatusMonitorActionTest {
|
||||
|
||||
private Context mContextSpy;
|
||||
private HdmiControlService mHdmiControlService;
|
||||
private FakeNativeWrapper mNativeWrapper;
|
||||
|
||||
private TestLooper mTestLooper = new TestLooper();
|
||||
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
|
||||
private int mPhysicalAddress;
|
||||
private HdmiCecLocalDeviceTv mTvDevice;
|
||||
|
||||
@Mock
|
||||
private IPowerManager mIPowerManagerMock;
|
||||
@Mock
|
||||
private IThermalService mIThermalServiceMock;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
|
||||
|
||||
PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock,
|
||||
mIThermalServiceMock, new Handler(mTestLooper.getLooper()));
|
||||
when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
|
||||
when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
|
||||
when(mIPowerManagerMock.isInteractive()).thenReturn(true);
|
||||
|
||||
HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
|
||||
|
||||
mHdmiControlService = new HdmiControlService(mContextSpy) {
|
||||
@Override
|
||||
AudioManager getAudioManager() {
|
||||
return new AudioManager() {
|
||||
@Override
|
||||
public void setWiredDeviceConnectionState(
|
||||
int type, int state, String address, String name) {
|
||||
// Do nothing.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
void wakeUp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isPowerStandby() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowerManager getPowerManager() {
|
||||
return powerManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeStringSystemProperty(String key, String value) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HdmiCecConfig getHdmiCecConfig() {
|
||||
return hdmiCecConfig;
|
||||
}
|
||||
};
|
||||
|
||||
Looper looper = mTestLooper.getLooper();
|
||||
mHdmiControlService.setIoLooper(looper);
|
||||
mNativeWrapper = new FakeNativeWrapper();
|
||||
HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
|
||||
this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
|
||||
mHdmiControlService.setCecController(hdmiCecController);
|
||||
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
|
||||
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
|
||||
mTvDevice = new HdmiCecLocalDeviceTv(mHdmiControlService);
|
||||
mTvDevice.init();
|
||||
mLocalDevices.add(mTvDevice);
|
||||
mTestLooper.dispatchAll();
|
||||
HdmiPortInfo[] hdmiPortInfo = new HdmiPortInfo[2];
|
||||
hdmiPortInfo[0] =
|
||||
new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x1000, true, false, false);
|
||||
hdmiPortInfo[1] =
|
||||
new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, 0x2000, true, false, false);
|
||||
mNativeWrapper.setPortInfo(hdmiPortInfo);
|
||||
mHdmiControlService.initService();
|
||||
mPhysicalAddress = 0x0000;
|
||||
mNativeWrapper.setPhysicalAddress(mPhysicalAddress);
|
||||
mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
|
||||
mTestLooper.dispatchAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sourceDevice_1_4_updatesPowerState() {
|
||||
sendMessageFromPlaybackDevice(ADDR_PLAYBACK_1, 0x1000);
|
||||
|
||||
PowerStatusMonitorAction action = new PowerStatusMonitorAction(mTvDevice);
|
||||
action.start();
|
||||
assertPowerStatus(ADDR_PLAYBACK_1, HdmiControlManager.POWER_STATUS_UNKNOWN);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
|
||||
ADDR_TV,
|
||||
ADDR_PLAYBACK_1);
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus);
|
||||
|
||||
reportPowerStatus(ADDR_PLAYBACK_1, false, HdmiControlManager.POWER_STATUS_ON);
|
||||
assertPowerStatus(ADDR_PLAYBACK_1, HdmiControlManager.POWER_STATUS_ON);
|
||||
|
||||
mTestLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(60));
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus);
|
||||
|
||||
reportPowerStatus(ADDR_PLAYBACK_1, false, HdmiControlManager.POWER_STATUS_STANDBY);
|
||||
assertPowerStatus(ADDR_PLAYBACK_1, HdmiControlManager.POWER_STATUS_STANDBY);
|
||||
}
|
||||
|
||||
private void assertPowerStatus(int logicalAddress, int powerStatus) {
|
||||
HdmiDeviceInfo deviceInfo = mHdmiControlService.getHdmiCecNetwork().getCecDeviceInfo(
|
||||
logicalAddress);
|
||||
assertThat(deviceInfo).isNotNull();
|
||||
assertThat(deviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sourceDevice_2_0_doesNotUpdatePowerState() {
|
||||
mHdmiControlService.getHdmiCecConfig().setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
|
||||
HdmiControlManager.HDMI_CEC_VERSION_2_0);
|
||||
sendMessageFromPlaybackDevice(ADDR_PLAYBACK_1, 0x1000);
|
||||
reportPowerStatus(ADDR_PLAYBACK_1, true, HdmiControlManager.POWER_STATUS_ON);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
PowerStatusMonitorAction action = new PowerStatusMonitorAction(mTvDevice);
|
||||
action.start();
|
||||
|
||||
assertPowerStatus(ADDR_PLAYBACK_1, HdmiControlManager.POWER_STATUS_ON);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
|
||||
ADDR_TV,
|
||||
ADDR_PLAYBACK_1);
|
||||
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus);
|
||||
|
||||
mTestLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(60));
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
assertPowerStatus(ADDR_PLAYBACK_1, HdmiControlManager.POWER_STATUS_ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedSourceDevices_localDevice_1_4_updatesAll() {
|
||||
mHdmiControlService.getHdmiCecConfig().setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
|
||||
HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
|
||||
mTestLooper.dispatchAll();
|
||||
sendMessageFromPlaybackDevice(ADDR_PLAYBACK_1, 0x1000);
|
||||
sendMessageFromPlaybackDevice(ADDR_PLAYBACK_2, 0x2000);
|
||||
reportPowerStatus(ADDR_PLAYBACK_2, true, HdmiControlManager.POWER_STATUS_ON);
|
||||
|
||||
assertPowerStatus(ADDR_PLAYBACK_1, HdmiControlManager.POWER_STATUS_UNKNOWN);
|
||||
assertPowerStatus(ADDR_PLAYBACK_2, HdmiControlManager.POWER_STATUS_ON);
|
||||
|
||||
PowerStatusMonitorAction action = new PowerStatusMonitorAction(mTvDevice);
|
||||
action.start();
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
|
||||
ADDR_TV,
|
||||
ADDR_PLAYBACK_1);
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus);
|
||||
|
||||
HdmiCecMessage giveDevicePowerStatus2 = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
|
||||
ADDR_TV,
|
||||
ADDR_PLAYBACK_2);
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedSourceDevices_localDevice_2_0_onlyUpdates_1_4() {
|
||||
mHdmiControlService.getHdmiCecConfig().setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
|
||||
HdmiControlManager.HDMI_CEC_VERSION_2_0);
|
||||
mTestLooper.dispatchAll();
|
||||
sendMessageFromPlaybackDevice(ADDR_PLAYBACK_1, 0x1000);
|
||||
sendMessageFromPlaybackDevice(ADDR_PLAYBACK_2, 0x2000);
|
||||
reportPowerStatus(ADDR_PLAYBACK_2, true, HdmiControlManager.POWER_STATUS_ON);
|
||||
|
||||
PowerStatusMonitorAction action = new PowerStatusMonitorAction(mTvDevice);
|
||||
action.start();
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
|
||||
ADDR_TV,
|
||||
ADDR_PLAYBACK_1);
|
||||
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus);
|
||||
|
||||
HdmiCecMessage giveDevicePowerStatus2 = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
|
||||
ADDR_TV,
|
||||
ADDR_PLAYBACK_2);
|
||||
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus2);
|
||||
}
|
||||
|
||||
private void sendMessageFromPlaybackDevice(int logicalAddress, int physicalAddress) {
|
||||
HdmiCecMessage playbackDevice = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
|
||||
logicalAddress, physicalAddress, HdmiDeviceInfo.DEVICE_PLAYBACK);
|
||||
mNativeWrapper.onCecMessage(playbackDevice);
|
||||
mTestLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private void reportPowerStatus(int logicalAddress, boolean broadcast, int powerStatus) {
|
||||
int destination = broadcast ? ADDR_BROADCAST : ADDR_TV;
|
||||
HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
|
||||
logicalAddress, destination,
|
||||
powerStatus);
|
||||
mNativeWrapper.onCecMessage(reportPowerStatus);
|
||||
mTestLooper.dispatchAll();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user