Don't remove devices on onHotplug()
This CL affects TV panels and Audio Systems only. Before HdmiCecNetwork existed: devices were removed when HotplugDetectionAction detected a hotplug out, and TIF was informed. Before this CL: devices were removed from the CEC network onHotplug, but the listener to inform TIF wasn't invoked. This was causing multiple issues. After: on TV panels and Audio Systems, only remove devices when HotplugDetectionAction detects a hotplug out, just like before HdmiCecNetwork existed. Test: atest Bug:213417037 Change-Id: I4181b4650b70101da44fd205e4df9eb566f74496 Merged-In: I4181b4650b70101da44fd205e4df9eb566f74496
This commit is contained in:
@@ -22,6 +22,8 @@ import android.hardware.hdmi.HdmiDeviceInfo;
|
|||||||
* Callback interface definition for HDMI client to get informed of
|
* Callback interface definition for HDMI client to get informed of
|
||||||
* the CEC logical device status change event.
|
* the CEC logical device status change event.
|
||||||
*
|
*
|
||||||
|
* Only to be used on TV panel and Audio System devices (b/226317598).
|
||||||
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface IHdmiDeviceEventListener {
|
oneway interface IHdmiDeviceEventListener {
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
|
|||||||
// We'll not invalidate the active source on the hotplug event to pass CETC 11.2.2-2 ~ 3.
|
// We'll not invalidate the active source on the hotplug event to pass CETC 11.2.2-2 ~ 3.
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
getWakeLock().release();
|
getWakeLock().release();
|
||||||
|
mService.getHdmiCecNetwork().removeDevicesConnectedToPort(portId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1218,6 +1218,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
|||||||
@ServiceThreadOnly
|
@ServiceThreadOnly
|
||||||
void onHotplug(int portId, boolean connected) {
|
void onHotplug(int portId, boolean connected) {
|
||||||
assertRunOnServiceThread();
|
assertRunOnServiceThread();
|
||||||
|
|
||||||
|
if (!connected) {
|
||||||
|
mService.getHdmiCecNetwork().removeCecSwitches(portId);
|
||||||
|
}
|
||||||
|
|
||||||
// Turning System Audio Mode off when the AVR is unlugged or standby.
|
// Turning System Audio Mode off when the AVR is unlugged or standby.
|
||||||
// When the device is not unplugged but reawaken from standby, we check if the System
|
// When the device is not unplugged but reawaken from standby, we check if the System
|
||||||
// Audio Control Feature is enabled or not then decide if turning SAM on/off accordingly.
|
// Audio Control Feature is enabled or not then decide if turning SAM on/off accordingly.
|
||||||
|
|||||||
@@ -698,7 +698,7 @@ public class HdmiCecNetwork {
|
|||||||
return mCecSwitches;
|
return mCecSwitches;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeDevicesConnectedToPort(int portId) {
|
void removeCecSwitches(int portId) {
|
||||||
Iterator<Integer> it = mCecSwitches.iterator();
|
Iterator<Integer> it = mCecSwitches.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
int path = it.next();
|
int path = it.next();
|
||||||
@@ -707,6 +707,11 @@ public class HdmiCecNetwork {
|
|||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeDevicesConnectedToPort(int portId) {
|
||||||
|
removeCecSwitches(portId);
|
||||||
|
|
||||||
List<Integer> toRemove = new ArrayList<>();
|
List<Integer> toRemove = new ArrayList<>();
|
||||||
for (int i = 0; i < mDeviceInfos.size(); i++) {
|
for (int i = 0; i < mDeviceInfos.size(); i++) {
|
||||||
int key = mDeviceInfos.keyAt(i);
|
int key = mDeviceInfos.keyAt(i);
|
||||||
|
|||||||
@@ -1251,10 +1251,6 @@ public class HdmiControlService extends SystemService {
|
|||||||
device.onHotplug(portId, connected);
|
device.onHotplug(portId, connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!connected) {
|
|
||||||
mHdmiCecNetwork.removeDevicesConnectedToPort(portId);
|
|
||||||
}
|
|
||||||
|
|
||||||
announceHotplugEvent(portId, connected);
|
announceHotplugEvent(portId, connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ import java.util.List;
|
|||||||
final class HotplugDetectionAction extends HdmiCecFeatureAction {
|
final class HotplugDetectionAction extends HdmiCecFeatureAction {
|
||||||
private static final String TAG = "HotPlugDetectionAction";
|
private static final String TAG = "HotPlugDetectionAction";
|
||||||
|
|
||||||
private static final int POLLING_INTERVAL_MS = 5000;
|
public static final int POLLING_INTERVAL_MS = 5000;
|
||||||
private static final int TIMEOUT_COUNT = 3;
|
public static final int TIMEOUT_COUNT = 3;
|
||||||
private static final int AVR_COUNT_MAX = 3;
|
public static final int AVR_COUNT_MAX = 3;
|
||||||
|
|
||||||
// State in which waits for next polling
|
// State in which waits for next polling
|
||||||
private static final int STATE_WAIT_FOR_NEXT_POLLING = 1;
|
private static final int STATE_WAIT_FOR_NEXT_POLLING = 1;
|
||||||
|
|||||||
@@ -1789,4 +1789,32 @@ public class HdmiCecLocalDevicePlaybackTest {
|
|||||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortPressed);
|
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortPressed);
|
||||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortReleased);
|
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortReleased);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onHotplugClearsDevices() {
|
||||||
|
mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.isEmpty();
|
||||||
|
// Add a device to the network and assert that this device is included in the list of
|
||||||
|
// devices.
|
||||||
|
HdmiDeviceInfo infoPlayback = new HdmiDeviceInfo(
|
||||||
|
Constants.ADDR_PLAYBACK_3,
|
||||||
|
0x1000,
|
||||||
|
PORT_1,
|
||||||
|
HdmiDeviceInfo.DEVICE_PLAYBACK,
|
||||||
|
0x1000,
|
||||||
|
"Playback 3",
|
||||||
|
HdmiControlManager.POWER_STATUS_ON);
|
||||||
|
mHdmiControlService.getHdmiCecNetwork().addCecDevice(infoPlayback);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.hasSize(1);
|
||||||
|
|
||||||
|
// HAL detects a hotplug out. Assert that this device gets removed from the list of devices.
|
||||||
|
mHdmiControlService.onHotplug(PORT_1, false);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,12 +56,14 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
/** Tests for {@link HdmiCecLocalDeviceTv} class. */
|
/** Tests for {@link HdmiCecLocalDeviceTv} class. */
|
||||||
public class HdmiCecLocalDeviceTvTest {
|
public class HdmiCecLocalDeviceTvTest {
|
||||||
private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
|
private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
|
||||||
|
private static final int PORT_1 = 1;
|
||||||
|
|
||||||
private HdmiControlService mHdmiControlService;
|
private HdmiControlService mHdmiControlService;
|
||||||
private HdmiCecController mHdmiCecController;
|
private HdmiCecController mHdmiCecController;
|
||||||
@@ -73,6 +75,25 @@ public class HdmiCecLocalDeviceTvTest {
|
|||||||
private int mTvPhysicalAddress;
|
private int mTvPhysicalAddress;
|
||||||
private int mTvLogicalAddress;
|
private int mTvLogicalAddress;
|
||||||
private boolean mWokenUp;
|
private boolean mWokenUp;
|
||||||
|
private List<DeviceEventListener> mDeviceEventListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
private class DeviceEventListener {
|
||||||
|
private HdmiDeviceInfo mDevice;
|
||||||
|
private int mStatus;
|
||||||
|
|
||||||
|
DeviceEventListener(HdmiDeviceInfo device, int status) {
|
||||||
|
this.mDevice = device;
|
||||||
|
this.mStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getStatus() {
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
HdmiDeviceInfo getDeviceInfo() {
|
||||||
|
return mDevice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private IPowerManager mIPowerManagerMock;
|
private IPowerManager mIPowerManagerMock;
|
||||||
@@ -124,6 +145,11 @@ public class HdmiCecLocalDeviceTvTest {
|
|||||||
AudioManager getAudioManager() {
|
AudioManager getAudioManager() {
|
||||||
return mAudioManager;
|
return mAudioManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) {
|
||||||
|
mDeviceEventListeners.add(new DeviceEventListener(device, status));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
|
mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
|
||||||
@@ -596,4 +622,100 @@ public class HdmiCecLocalDeviceTvTest {
|
|||||||
|
|
||||||
verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt());
|
verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hotplugDetectionActionClearsDevices() {
|
||||||
|
mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.isEmpty();
|
||||||
|
// Add a device to the network and assert that this device is included in the list of
|
||||||
|
// devices.
|
||||||
|
HdmiDeviceInfo infoPlayback = new HdmiDeviceInfo(
|
||||||
|
Constants.ADDR_PLAYBACK_2,
|
||||||
|
0x1000,
|
||||||
|
PORT_1,
|
||||||
|
HdmiDeviceInfo.DEVICE_PLAYBACK,
|
||||||
|
0x1000,
|
||||||
|
"Playback 2",
|
||||||
|
HdmiControlManager.POWER_STATUS_ON);
|
||||||
|
mHdmiControlService.getHdmiCecNetwork().addCecDevice(infoPlayback);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.hasSize(1);
|
||||||
|
mDeviceEventListeners.clear();
|
||||||
|
assertThat(mDeviceEventListeners.size()).isEqualTo(0);
|
||||||
|
|
||||||
|
// HAL detects a hotplug out. Assert that this device stays in the list of devices.
|
||||||
|
mHdmiControlService.onHotplug(PORT_1, false);
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.hasSize(1);
|
||||||
|
assertThat(mDeviceEventListeners).isEmpty();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
// Make the device not acknowledge the poll message sent by the HotplugDetectionAction.
|
||||||
|
// Assert that this device is removed from the list of devices.
|
||||||
|
mNativeWrapper.setPollAddressResponse(Constants.ADDR_PLAYBACK_2, SendMessageResult.NACK);
|
||||||
|
for (int pollCount = 0; pollCount < HotplugDetectionAction.TIMEOUT_COUNT; pollCount++) {
|
||||||
|
mTestLooper.moveTimeForward(HotplugDetectionAction.POLLING_INTERVAL_MS);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.isEmpty();
|
||||||
|
assertThat(mDeviceEventListeners.size()).isEqualTo(1);
|
||||||
|
assertThat(mDeviceEventListeners.get(0).getStatus())
|
||||||
|
.isEqualTo(HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
|
||||||
|
HdmiDeviceInfo removedDeviceInfo = mDeviceEventListeners.get(0).getDeviceInfo();
|
||||||
|
assertThat(removedDeviceInfo.getPortId()).isEqualTo(PORT_1);
|
||||||
|
assertThat(removedDeviceInfo.getLogicalAddress()).isEqualTo(Constants.ADDR_PLAYBACK_2);
|
||||||
|
assertThat(removedDeviceInfo.getPhysicalAddress()).isEqualTo(0x1000);
|
||||||
|
assertThat(removedDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hotplugDetectionActionClearsDevices_AudioSystem() {
|
||||||
|
mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.isEmpty();
|
||||||
|
// Add a device to the network and assert that this device is included in the list of
|
||||||
|
// devices.
|
||||||
|
HdmiDeviceInfo infoAudioSystem = new HdmiDeviceInfo(
|
||||||
|
ADDR_AUDIO_SYSTEM,
|
||||||
|
0x1000,
|
||||||
|
PORT_1,
|
||||||
|
HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM,
|
||||||
|
0x1000,
|
||||||
|
"Audio System",
|
||||||
|
HdmiControlManager.POWER_STATUS_ON);
|
||||||
|
mHdmiControlService.getHdmiCecNetwork().addCecDevice(infoAudioSystem);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.hasSize(1);
|
||||||
|
mDeviceEventListeners.clear();
|
||||||
|
assertThat(mDeviceEventListeners.size()).isEqualTo(0);
|
||||||
|
|
||||||
|
// HAL detects a hotplug out. Assert that this device stays in the list of devices.
|
||||||
|
mHdmiControlService.onHotplug(PORT_1, false);
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.hasSize(1);
|
||||||
|
assertThat(mDeviceEventListeners).isEmpty();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
// Make the device not acknowledge the poll message sent by the HotplugDetectionAction.
|
||||||
|
// Assert that this device is removed from the list of devices.
|
||||||
|
mNativeWrapper.setPollAddressResponse(ADDR_AUDIO_SYSTEM, SendMessageResult.NACK);
|
||||||
|
for (int pollCount = 0; pollCount < HotplugDetectionAction.TIMEOUT_COUNT; pollCount++) {
|
||||||
|
mTestLooper.moveTimeForward(HotplugDetectionAction.POLLING_INTERVAL_MS);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
|
||||||
|
.isEmpty();
|
||||||
|
assertThat(mDeviceEventListeners.size()).isEqualTo(1);
|
||||||
|
assertThat(mDeviceEventListeners.get(0).getStatus())
|
||||||
|
.isEqualTo(HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
|
||||||
|
HdmiDeviceInfo removedDeviceInfo = mDeviceEventListeners.get(0).getDeviceInfo();
|
||||||
|
assertThat(removedDeviceInfo.getPortId()).isEqualTo(PORT_1);
|
||||||
|
assertThat(removedDeviceInfo.getLogicalAddress()).isEqualTo(Constants.ADDR_AUDIO_SYSTEM);
|
||||||
|
assertThat(removedDeviceInfo.getPhysicalAddress()).isEqualTo(0x1000);
|
||||||
|
assertThat(removedDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user