diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index 04a7259a2b2df..72b79f401a99d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -269,7 +269,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)) { @@ -296,7 +299,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)) { @@ -389,6 +395,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); } @@ -823,7 +833,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 06cd0bce659e6..0afd27c48ee60 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; @@ -718,4 +719,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 017039053222d..c617d217ec94e 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java @@ -202,20 +202,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 @@ -239,6 +238,9 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + + assertThat(mDeviceEventListenerStatuses).containsExactly( + HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } @Test @@ -256,11 +258,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 @@ -282,6 +283,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getDisplayName()).isEqualTo( HdmiUtils.getDefaultDeviceName(logicalAddress)); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus); + + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test @@ -303,6 +306,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(osdName); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test @@ -324,6 +329,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getVendorId()).isEqualTo(vendorId); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + + assertThat(mDeviceEventListenerStatuses).isEmpty(); } @Test @@ -382,12 +389,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); } @@ -471,9 +476,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