diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index 16ade37aa8e63..8b6d16a171f5c 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -259,7 +259,10 @@ public class HdmiCecNetwork { // The addition of a local device should not notify listeners return; } - if (old == null) { + if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { + // Don't notify listeners of devices that haven't reported their physical address yet + return; + } else if (old == null || old.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } else if (!old.equals(info)) { @@ -286,7 +289,10 @@ public class HdmiCecNetwork { assertRunOnServiceThread(); HdmiDeviceInfo old = addDeviceInfo(info); - if (old == null) { + if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { + // Don't notify listeners of devices that haven't reported their physical address yet + return; + } else if (old == null || old.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } else if (!old.equals(info)) { @@ -379,6 +385,10 @@ public class HdmiCecNetwork { HdmiDeviceInfo info = removeDeviceInfo(HdmiDeviceInfo.idForCecDevice(address)); localDevice.mCecMessageCache.flushMessagesFrom(address); + if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { + // Don't notify listeners of devices that haven't reported their physical address yet + return; + } invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); } @@ -852,7 +862,10 @@ public class HdmiCecNetwork { public void clearDeviceList() { assertRunOnServiceThread(); for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) { - if (info.getPhysicalAddress() == getPhysicalAddress()) { + if (info.getPhysicalAddress() == getPhysicalAddress() + || info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { + // Don't notify listeners of local devices or devices that haven't reported their + // physical address yet continue; } invokeDeviceEventListener(info, 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 f1ad957eb4124..df4aa5dac9df3 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -19,6 +19,7 @@ import static com.android.server.hdmi.Constants.ABORT_UNRECOGNIZED_OPCODE; import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM; 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_RECORDER_1; import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; @@ -731,4 +732,51 @@ public class HdmiCecLocalDeviceTvTest { assertThat(removedDeviceInfo.getPhysicalAddress()).isEqualTo(0x1000); assertThat(removedDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); } + + @Test + public void listenerInvokedIfPhysicalAddressReported() { + mHdmiControlService.getHdmiCecNetwork().clearDeviceList(); + assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false)) + .isEmpty(); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_PLAYBACK_2, 0x1000, HdmiDeviceInfo.DEVICE_PLAYBACK); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false)) + .hasSize(1); + assertThat(mDeviceEventListeners.size()).isEqualTo(1); + assertThat(mDeviceEventListeners.get(0).getStatus()) + .isEqualTo(HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); + } + + @Test + public void listenerNotInvokedIfPhysicalAddressUnknown() { + mHdmiControlService.getHdmiCecNetwork().clearDeviceList(); + assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false)) + .isEmpty(); + HdmiCecMessage setOsdName = HdmiCecMessageBuilder.buildSetOsdNameCommand( + ADDR_PLAYBACK_2, ADDR_TV, "Playback 2"); + mNativeWrapper.onCecMessage(setOsdName); + mTestLooper.dispatchAll(); + + assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false)) + .hasSize(1); + assertThat(mDeviceEventListeners).isEmpty(); + + // When the device reports its physical address, the listener eventually is invoked. + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_PLAYBACK_2, 0x1000, HdmiDeviceInfo.DEVICE_PLAYBACK); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false)) + .hasSize(1); + assertThat(mDeviceEventListeners.size()).isEqualTo(1); + assertThat(mDeviceEventListeners.get(0).getStatus()) + .isEqualTo(HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); + + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java index e39e071269bac..03532ae1cb1fc 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java @@ -204,20 +204,19 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); - assertThat(mDeviceEventListenerStatuses).containsExactly( - HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test public void cecDevices_tracking_logicalAddressOnly_doesntNotifyAgain() throws Exception { int logicalAddress = Constants.ADDR_PLAYBACK_1; + int physicalAddress = 0x1000; mHdmiCecNetwork.handleCecMessage( - HdmiCecMessageBuilder.buildActiveSource(logicalAddress, 0x1000)); + HdmiCecMessageBuilder.buildActiveSource(logicalAddress, physicalAddress)); mHdmiCecNetwork.handleCecMessage( - HdmiCecMessageBuilder.buildActiveSource(logicalAddress, 0x1000)); + HdmiCecMessageBuilder.buildActiveSource(logicalAddress, physicalAddress)); - assertThat(mDeviceEventListenerStatuses).containsExactly( - HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test @@ -241,6 +240,9 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.VENDOR_ID_UNKNOWN); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + + assertThat(mDeviceEventListenerStatuses).containsExactly( + HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } @Test @@ -258,11 +260,10 @@ public class HdmiCecNetworkTest { physicalAddress, type)); - // ADD for logical address first detected - // UPDATE for updating device with physical address + // ADD for physical address first detected + // no UPDATE, since physical address didn't change assertThat(mDeviceEventListenerStatuses).containsExactly( - HdmiControlManager.DEVICE_EVENT_ADD_DEVICE, - HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); + HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } @Test @@ -284,6 +285,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getDisplayName()).isEqualTo( HdmiUtils.getDefaultDeviceName(logicalAddress)); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus); + + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test @@ -305,6 +308,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(osdName); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test @@ -326,6 +331,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getVendorId()).isEqualTo(vendorId); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test @@ -384,12 +391,10 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(updatedPhysicalAddress); assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(type); - // ADD for logical address first detected - // UPDATE for updating device with physical address + // ADD for physical address first detected // UPDATE for updating device with new physical address assertThat(mDeviceEventListenerStatuses).containsExactly( HdmiControlManager.DEVICE_EVENT_ADD_DEVICE, - HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE, HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); } @@ -473,9 +478,8 @@ public class HdmiCecNetworkTest { assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).isEmpty(); - assertThat(mDeviceEventListenerStatuses).containsExactly( - HdmiControlManager.DEVICE_EVENT_ADD_DEVICE, - HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); + // Physical address never got reported, so no listeners are triggered + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test