Skip KeyEvent input tests for keys which are handled globally.
Bug: 197324044
Test: atest GoogleAtvReferenceRemoteControlTest
Test: atest CtsHardwareTestCases
Change-Id: I9a17c9fb238d11ad88b9da1dcfcdd96ac4dc7d22
(cherry picked from commit 28bfb73625b7f955900416305ffcef5ec2d83bf2)
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/GlobalKeyMapping.java b/tests/tests/hardware/src/android/hardware/input/cts/GlobalKeyMapping.java
new file mode 100644
index 0000000..297031a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/GlobalKeyMapping.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.cts;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.util.Log;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Loads the global keys from {@code com.android.internal.R.xml.global_keys} the same way like
+ * {@code com.android.server.policy.GlobalKeyManager} does.
+ * TODO(199182608): Make GlobalKeyManager#shouldHandleGlobalKey() a testApi and remove this class
+ */
+public class GlobalKeyMapping {
+ private static final String TAG = GlobalKeyMapping.class.getSimpleName();
+ private static final String TAG_GLOBAL_KEYS = "global_keys";
+ private static final String TAG_KEY = "key";
+ private static final String ATTR_VERSION = "version";
+ private static final String ATTR_KEY_CODE = "keyCode";
+ private static final int GLOBAL_KEY_FILE_VERSION = 1;
+ private static final Set<Integer> GLOBAL_KEYS = new HashSet<>();
+
+
+ public GlobalKeyMapping(Context context) {
+ loadGlobalKeys(context);
+ }
+
+ private void loadGlobalKeys(Context context) {
+ try (XmlResourceParser parser = context.getResources().getXml(
+ Resources.getSystem().getIdentifier("global_keys", "xml", "android"))) {
+ beginDocument(parser, TAG_GLOBAL_KEYS);
+ int version = parser.getAttributeIntValue(null, ATTR_VERSION, 0);
+ if (GLOBAL_KEY_FILE_VERSION == version) {
+ while (true) {
+ nextElement(parser);
+ String element = parser.getName();
+ if (element == null) {
+ break;
+ }
+ if (TAG_KEY.equals(element)) {
+ String keyCodeName = parser.getAttributeValue(null, ATTR_KEY_CODE);
+ int keyCode = KeyEvent.keyCodeFromString(keyCodeName);
+ if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
+ GLOBAL_KEYS.add(keyCode);
+ }
+ }
+ }
+ }
+ } catch (Resources.NotFoundException e) {
+ Log.w(TAG, "global keys file not found", e);
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "XML parser exception reading global keys file", e);
+ } catch (IOException e) {
+ Log.w(TAG, "I/O exception reading global keys file", e);
+ }
+ }
+
+ public boolean isGlobalKey(InputEvent e) {
+ if (GLOBAL_KEYS.isEmpty() || !(e instanceof KeyEvent)) {
+ return false;
+ }
+ KeyEvent keyEvent = (KeyEvent) e;
+ return GLOBAL_KEYS.contains(keyEvent.getKeyCode());
+ }
+
+ /** Ported from com.android.internal.util.XmlUtils */
+ private void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+ // skip
+ }
+ }
+
+ /** Ported from com.android.internal.util.XmlUtils */
+ private void beginDocument(XmlPullParser parser, String firstElementName)
+ throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+ // skip
+ }
+
+ if (type != parser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ if (!parser.getName().equals(firstElementName)) {
+ throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
+ + ", expected " + firstElementName);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
index d40d545..07a080a 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
@@ -31,6 +31,7 @@
import android.hardware.BatteryState;
import android.hardware.input.InputManager;
+import android.hardware.input.cts.GlobalKeyMapping;
import android.hardware.lights.Light;
import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager;
@@ -72,6 +73,8 @@
private static final long CALLBACK_TIMEOUT_MILLIS = 5000;
private HidDevice mHidDevice;
+ private final GlobalKeyMapping mGlobalKeyMapping = new GlobalKeyMapping(
+ mInstrumentation.getTargetContext());
private int mDeviceId;
private final int mRegisterResourceId;
private boolean mDelayAfterSetup = false;
@@ -214,17 +217,19 @@
@Override
protected void testInputDeviceEvents(int resourceId) {
List<HidTestData> tests = mParser.getHidTestData(resourceId);
+ // Global keys are handled by the framework and do not reach apps.
+ // The set of global keys is vendor-specific.
+ // Remove tests which contain global keys because we can't test them
+ tests.removeIf(testData -> testData.events.removeIf(mGlobalKeyMapping::isGlobalKey));
for (HidTestData testData: tests) {
mCurrentTestCase = testData.name;
-
// Send all of the HID reports
for (int i = 0; i < testData.reports.size(); i++) {
final String report = testData.reports.get(i);
mHidDevice.sendHidReport(report);
}
verifyEvents(testData.events);
-
}
}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
index df24d52..ce9746b 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
@@ -54,11 +54,11 @@
private static final float TOLERANCE = 0.005f;
private final BlockingQueue<InputEvent> mEvents;
+ protected final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
private InputListener mInputListener;
private View mDecorView;
- protected Instrumentation mInstrumentation;
protected InputJsonParser mParser;
// Stores the name of the currently running test
protected String mCurrentTestCase;
@@ -81,7 +81,6 @@
@Before
public void setUp() throws Exception {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActivityRule.getActivity().clearUnhandleKeyCode();
mDecorView = mActivityRule.getActivity().getWindow().getDecorView();
mParser = new InputJsonParser(mInstrumentation.getTargetContext());