From e3cad328141f9c6806084d3685da00d2a3e4062a Mon Sep 17 00:00:00 2001 From: Marvin Ramin Date: Mon, 15 Feb 2021 14:55:30 +0100 Subject: [PATCH 1/2] Remove RECORD_TV_SCREEN handling from playback device Record TV Screen should only be supported by TV panel devices. Playback device may respond [Unrecognized Opcode]. Bug: 180103617 Test: atest com.android.server.hdmi Change-Id: I241cf0fcf7a96d603221f89d7daf58daeb732d69 --- .../android/server/hdmi/HdmiCecLocalDevice.java | 5 +---- .../server/hdmi/HdmiCecLocalDeviceTv.java | 5 ++++- .../hdmi/HdmiCecLocalDevicePlaybackTest.java | 15 +++++++++++++++ .../server/hdmi/HdmiCecLocalDeviceTvTest.java | 16 ++++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 382f0f9d6329d..aa2d6b46b7906 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -788,10 +788,7 @@ abstract class HdmiCecLocalDevice { } protected boolean handleRecordTvScreen(HdmiCecMessage message) { - // The default behavior of is replying with - // "Cannot provide source". - mService.maySendFeatureAbortCommand(message, Constants.ABORT_CANNOT_PROVIDE_SOURCE); - return true; + return false; } protected boolean handleTimerClearedStatus(HdmiCecMessage message) { diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index a3e18d1617519..8d6bcadb3e2b9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -1079,7 +1079,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { message.getSource(), HdmiControlManager.ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS); } - return super.handleRecordTvScreen(message); + // The default behavior of is replying with + // "Cannot provide source". + mService.maySendFeatureAbortCommand(message, Constants.ABORT_CANNOT_PROVIDE_SOURCE); + return true; } int recorderAddress = message.getSource(); 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 9f0d9829df014..bc06e790ff4a7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -15,6 +15,7 @@ */ package com.android.server.hdmi; +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_INVALID; @@ -1586,4 +1587,18 @@ public class HdmiCecLocalDevicePlaybackTest { assertThat(features.contains( Constants.RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU)).isFalse(); } + + @Test + public void doesNotSupportRecordTvScreen() { + HdmiCecMessage recordTvScreen = new HdmiCecMessage(ADDR_TV, mPlaybackLogicalAddress, + Constants.MESSAGE_RECORD_TV_SCREEN, HdmiCecMessage.EMPTY_PARAM); + + mNativeWrapper.onCecMessage(recordTvScreen); + mTestLooper.dispatchAll(); + + HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand( + mPlaybackLogicalAddress, ADDR_TV, Constants.MESSAGE_RECORD_TV_SCREEN, + ABORT_UNRECOGNIZED_OPCODE); + assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort); + } } 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 d5271ef869b08..4623eb5b7d4b9 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -15,9 +15,11 @@ */ package com.android.server.hdmi; +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_RECORDER_1; import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; @@ -484,4 +486,18 @@ public class HdmiCecLocalDeviceTvTest { ADDR_AUDIO_SYSTEM); assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); } + + @Test + public void supportsRecordTvScreen() { + HdmiCecMessage recordTvScreen = new HdmiCecMessage(ADDR_RECORDER_1, mTvLogicalAddress, + Constants.MESSAGE_RECORD_TV_SCREEN, HdmiCecMessage.EMPTY_PARAM); + + mNativeWrapper.onCecMessage(recordTvScreen); + mTestLooper.dispatchAll(); + + HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand( + mTvLogicalAddress, ADDR_RECORDER_1, Constants.MESSAGE_RECORD_TV_SCREEN, + ABORT_UNRECOGNIZED_OPCODE); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbort); + } } From d4a3a5ced5b483d4ad3623d25a4a30be925d20b6 Mon Sep 17 00:00:00 2001 From: Marvin Ramin Date: Mon, 15 Feb 2021 14:58:44 +0100 Subject: [PATCH 2/2] Update handling of Remote Control Passthrough messages Never respond [Unrecognized Opcode] in cases where or cannot be handled. Bug: 180103617 Test: atest com.android.server.hdmi Change-Id: I12c7de639ac31a9ae381c3706f64b53e3e92d71c --- .../server/hdmi/HdmiCecLocalDevice.java | 7 +++-- .../hdmi/HdmiCecLocalDevicePlaybackTest.java | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index aa2d6b46b7906..d8914b389191b 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -654,7 +654,9 @@ abstract class HdmiCecLocalDevice { FOLLOWER_SAFETY_TIMEOUT); return true; } - return false; + + mService.maySendFeatureAbortCommand(message, Constants.ABORT_INVALID_OPERAND); + return true; } @ServiceThreadOnly @@ -666,9 +668,8 @@ abstract class HdmiCecLocalDevice { final long upTime = SystemClock.uptimeMillis(); injectKeyEvent(upTime, KeyEvent.ACTION_UP, mLastKeycode, 0); mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE; - return true; } - return false; + return true; } static void injectKeyEvent(long time, int action, int keycode, int repeat) { 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 bc06e790ff4a7..5342486f930b4 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -50,6 +50,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.concurrent.TimeUnit; @SmallTest @Presubmit @@ -1601,4 +1602,32 @@ public class HdmiCecLocalDevicePlaybackTest { ABORT_UNRECOGNIZED_OPCODE); assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort); } + + @Test + public void shouldHandleUserControlPressedAndReleased() { + HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed( + ADDR_TV, mPlaybackLogicalAddress, + HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP); + HdmiCecMessage userControlReleased = HdmiCecMessageBuilder.buildUserControlReleased( + ADDR_TV, mPlaybackLogicalAddress); + + mNativeWrapper.onCecMessage(userControlPressed); + mTestLooper.dispatchAll(); + + // Move past the follower safety timeout + mTestLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(2)); + mTestLooper.dispatchAll(); + + mNativeWrapper.onCecMessage(userControlReleased); + mTestLooper.dispatchAll(); + + HdmiCecMessage featureAbortPressed = HdmiCecMessageBuilder.buildFeatureAbortCommand( + mPlaybackLogicalAddress, ADDR_TV, Constants.MESSAGE_USER_CONTROL_PRESSED, + ABORT_UNRECOGNIZED_OPCODE); + HdmiCecMessage featureAbortReleased = HdmiCecMessageBuilder.buildFeatureAbortCommand( + mPlaybackLogicalAddress, ADDR_TV, Constants.MESSAGE_USER_CONTROL_RELEASED, + ABORT_UNRECOGNIZED_OPCODE); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortPressed); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortReleased); + } }