diff options
| author | 2022-04-04 16:13:43 +0000 | |
|---|---|---|
| committer | 2022-04-04 16:13:43 +0000 | |
| commit | d27da8101bb1878833e66dc0b874958731152593 (patch) | |
| tree | 5178229b1791e5a5df93e0dc1bcf52ca0576c801 | |
| parent | cc03484e9d5bf6dad4f8196fc914bdffcc0f99ce (diff) | |
| parent | c188a5688898bc801b80d2dfee03e1bb5bf6b035 (diff) | |
Don't remove devices on onHotplug() am: c188a56888
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2039064
Change-Id: I222cf5c44dfc9059f3e503cd2d6b0a10b3d76e46
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
8 files changed, 167 insertions, 8 deletions
diff --git a/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl b/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl index 69f29111635c..b2ddef9c29a6 100644 --- a/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl +++ b/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl @@ -22,6 +22,8 @@ import android.hardware.hdmi.HdmiDeviceInfo; * Callback interface definition for HDMI client to get informed of * the CEC logical device status change event. * + * Only to be used on TV panel and Audio System devices (b/226317598). + * * @hide */ oneway interface IHdmiDeviceEventListener { diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 40718585c484..1be8d327c405 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -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. if (!connected) { getWakeLock().release(); + mService.getHdmiCecNetwork().removeDevicesConnectedToPort(portId); } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 3d218cffc5df..b1ffbda8d773 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -1218,6 +1218,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @ServiceThreadOnly void onHotplug(int portId, boolean connected) { assertRunOnServiceThread(); + + if (!connected) { + mService.getHdmiCecNetwork().removeCecSwitches(portId); + } + // 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 // Audio Control Feature is enabled or not then decide if turning SAM on/off accordingly. diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index 1234d7fa0832..04a7259a2b2d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -698,7 +698,7 @@ public class HdmiCecNetwork { return mCecSwitches; } - void removeDevicesConnectedToPort(int portId) { + void removeCecSwitches(int portId) { Iterator<Integer> it = mCecSwitches.iterator(); while (it.hasNext()) { int path = it.next(); @@ -707,6 +707,11 @@ public class HdmiCecNetwork { it.remove(); } } + } + + void removeDevicesConnectedToPort(int portId) { + removeCecSwitches(portId); + List<Integer> toRemove = new ArrayList<>(); for (int i = 0; i < mDeviceInfos.size(); i++) { int key = mDeviceInfos.keyAt(i); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 8dadf5a8d20d..a16bd3b5e6ba 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1251,10 +1251,6 @@ public class HdmiControlService extends SystemService { device.onHotplug(portId, connected); } - if (!connected) { - mHdmiCecNetwork.removeDevicesConnectedToPort(portId); - } - announceHotplugEvent(portId, connected); } diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java index 4c4c9783fab0..3d771646df6a 100644 --- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java +++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java @@ -36,9 +36,9 @@ import java.util.List; final class HotplugDetectionAction extends HdmiCecFeatureAction { private static final String TAG = "HotPlugDetectionAction"; - private static final int POLLING_INTERVAL_MS = 5000; - private static final int TIMEOUT_COUNT = 3; - private static final int AVR_COUNT_MAX = 3; + public static final int POLLING_INTERVAL_MS = 5000; + public static final int TIMEOUT_COUNT = 3; + public static final int AVR_COUNT_MAX = 3; // State in which waits for next polling private static final int STATE_WAIT_FOR_NEXT_POLLING = 1; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index 524ad6282397..77af22598c43 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -1789,4 +1789,32 @@ public class HdmiCecLocalDevicePlaybackTest { assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortPressed); 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(); + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java index 59711a62f3f3..06cd0bce659e 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -56,12 +56,14 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.List; @SmallTest @RunWith(JUnit4.class) /** Tests for {@link HdmiCecLocalDeviceTv} class. */ public class HdmiCecLocalDeviceTvTest { private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1; + private static final int PORT_1 = 1; private HdmiControlService mHdmiControlService; private HdmiCecController mHdmiCecController; @@ -73,6 +75,25 @@ public class HdmiCecLocalDeviceTvTest { private int mTvPhysicalAddress; private int mTvLogicalAddress; 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 private IPowerManager mIPowerManagerMock; @@ -124,6 +145,11 @@ public class HdmiCecLocalDeviceTvTest { AudioManager getAudioManager() { return mAudioManager; } + + @Override + void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) { + mDeviceEventListeners.add(new DeviceEventListener(device, status)); + } }; mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService); @@ -596,4 +622,100 @@ public class HdmiCecLocalDeviceTvTest { 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); + } } |