summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Paul Colta <donpaul@google.com> 2024-08-05 17:35:04 +0000
committer Paul Colta <donpaul@google.com> 2024-08-05 22:34:27 +0000
commit87fb35963d579cb646e4f7b628ceb9ba9cd99eb9 (patch)
treef55f18bcd211a47c181936f81834b6b8c0f0133a
parenta1c4fab3a3b246bbb0c3e611719ff3364213cb8f (diff)
HDMI: Process buffered <Active Source> faster on TVs
On OTP the <Active Source> message handled by the TV would be buffered until the connected OTT device would send a <Report PA> message. If the device wouldn't send <Report PA> by itself, the TV will send a <Give PA> message only when DeviceDiscoveryAction polling has been finished and the Physical Address Stage has started. In this patch, a device info with the known information from <Active Source> message is added. This helps the buffered message to be processed sooner by TvInputCallback#onInputAdded call. Flag: EXEMPT bugfix Bug: 354848887 Test: atest com.android.server.hdmi (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bae98b3de36aacbfdee3eba5318f9b429b36aedc) Merged-In: Ibe8f066542b97e4424c02770f238f2026dac192b Change-Id: Ibe8f066542b97e4424c02770f238f2026dac192b
-rw-r--r--services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java12
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java28
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java29
3 files changed, 68 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
index 46b4f48165f9..44907457f649 100644
--- a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
+++ b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
@@ -17,8 +17,10 @@
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiDeviceInfo;
+
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
/**
* Buffer storage to keep incoming messages for later processing. Used to
@@ -83,6 +85,16 @@ final class DelayedMessageBuffer {
return false;
}
+ List<HdmiCecMessage> getBufferedMessagesWithOpcode(int opcode) {
+ List<HdmiCecMessage> messages = new ArrayList<>();
+ for (HdmiCecMessage message : mBuffer) {
+ if (message.getOpcode() == opcode) {
+ messages.add(message);
+ }
+ }
+ return messages;
+ }
+
void processAllMessages() {
// Use the copied buffer.
ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<>(mBuffer);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 54490899ab5f..6bc55886936e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -205,7 +205,9 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
resetSelectRequestBuffer();
launchDeviceDiscovery();
startQueuedActions();
- if (!mDelayedMessageBuffer.isBuffered(Constants.MESSAGE_ACTIVE_SOURCE)) {
+ List<HdmiCecMessage> bufferedActiveSource = mDelayedMessageBuffer
+ .getBufferedMessagesWithOpcode(Constants.MESSAGE_ACTIVE_SOURCE);
+ if (bufferedActiveSource.isEmpty()) {
addAndStartAction(new RequestActiveSourceAction(this, new IHdmiControlCallback.Stub() {
@Override
public void onComplete(int result) {
@@ -220,7 +222,31 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
}
}));
+ } else {
+ addCecDeviceForBufferedActiveSource(bufferedActiveSource.get(0));
+ }
+ }
+
+ // Add a new CEC device with known information from the buffered <Active Source> message. This
+ // helps TvInputCallback#onInputAdded to be called such that the message can be processed and
+ // the TV to switch to the new active input.
+ @ServiceThreadOnly
+ private void addCecDeviceForBufferedActiveSource(HdmiCecMessage bufferedActiveSource) {
+ assertRunOnServiceThread();
+ if (bufferedActiveSource == null) {
+ return;
}
+ int source = bufferedActiveSource.getSource();
+ int physicalAddress = HdmiUtils.twoBytesToInt(bufferedActiveSource.getParams());
+ List<Integer> deviceTypes = HdmiUtils.getTypeFromAddress(source);
+ HdmiDeviceInfo newDevice = HdmiDeviceInfo.cecDeviceBuilder()
+ .setLogicalAddress(source)
+ .setPhysicalAddress(physicalAddress)
+ .setDisplayName(HdmiUtils.getDefaultDeviceName(source))
+ .setDeviceType(deviceTypes.get(0))
+ .setVendorId(Constants.VENDOR_ID_UNKNOWN)
+ .build();
+ mService.getHdmiCecNetwork().addCecDevice(newDevice);
}
@ServiceThreadOnly
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 01c4d1fa6b5c..a4e636c01d65 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -26,6 +26,7 @@ import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE;
+import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON;
import static com.google.common.truth.Truth.assertThat;
@@ -1907,4 +1908,32 @@ public class HdmiCecLocalDeviceTvTest {
// NewDeviceAction did not start and <Give OSD Name> was not sent.
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveOsdName);
}
+
+ @Test
+ public void onOneTouchPlay_wakeUp_addCecDevice() {
+ assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+ .isEmpty();
+ mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
+ HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED);
+ mPowerManager.setInteractive(false);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(ADDR_PLAYBACK_1,
+ mTvLogicalAddress);
+ HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ 0x1000);
+ assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(textViewOn)).isEqualTo(Constants.HANDLED);
+ assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(activeSource)).isEqualTo(
+ Constants.HANDLED);
+ mTestLooper.dispatchAll();
+ assertThat(mPowerManager.isInteractive()).isTrue();
+
+ // FakePowerManagerWrapper#wakeUp() doesn't broadcast Intent.ACTION_SCREEN_ON so we have to
+ // manually call this method.
+ mHdmiControlService.onWakeUp(WAKE_UP_SCREEN_ON);
+ mTestLooper.dispatchAll();
+ assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+ .hasSize(1);
+ }
}