1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.input; 18 19 import android.text.TextUtils; 20 import android.util.Slog; 21 import android.util.Xml; 22 23 import com.android.internal.annotations.VisibleForTesting; 24 import com.android.internal.util.XmlUtils; 25 import com.android.modules.utils.TypedXmlPullParser; 26 27 import java.io.InputStream; 28 import java.util.ArrayList; 29 import java.util.HashMap; 30 import java.util.List; 31 import java.util.Map; 32 33 34 class ConfigurationProcessor { 35 private static final String TAG = "ConfigurationProcessor"; 36 processExcludedDeviceNames(InputStream xml)37 static List<String> processExcludedDeviceNames(InputStream xml) throws Exception { 38 List<String> names = new ArrayList<>(); 39 { 40 TypedXmlPullParser parser = Xml.resolvePullParser(xml); 41 XmlUtils.beginDocument(parser, "devices"); 42 while (true) { 43 XmlUtils.nextElement(parser); 44 if (!"device".equals(parser.getName())) { 45 break; 46 } 47 String name = parser.getAttributeValue(null, "name"); 48 if (name != null) { 49 names.add(name); 50 } 51 } 52 } 53 return names; 54 } 55 56 /** 57 * Parse the configuration for input port associations. 58 * 59 * Configuration format: 60 * <code> 61 * <ports> 62 * <port display="0" input="usb-xhci-hcd.0.auto-1.4.3/input0" /> 63 * <port display="1" input="usb-xhci-hcd.0.auto-1.4.2/input0" /> 64 * </ports> 65 * </code> 66 * 67 * In this example, any input device that has physical port of 68 * "usb-xhci-hcd.0.auto-1.4.3/input0" will be associated with a display 69 * that has the physical port "0". If such a display does not exist, the input device 70 * will be disabled and no input events will be dispatched from that input device until a 71 * matching display appears. Likewise, an input device that has port "..1.4.2.." will have 72 * its input events forwarded to a display that has physical port of "1". 73 * 74 * Note: display port must be a numeric value, and this is checked at runtime for validity. 75 * At the same time, it is specified as a string for simplicity. 76 * 77 * Note: do not confuse "display id" with "display port". 78 * The "display port" is the physical port on which the display is connected. This could 79 * be something like HDMI0, HDMI1, etc. For virtual displays, "display port" will be null. 80 * The "display id" is a way to identify a particular display, and is not a stable API. 81 * All displays, including virtual ones, will have a display id. 82 * 83 * Return the pairs of associations. The first item in the pair is the input port, 84 * the second item in the pair is the display port. 85 */ 86 @VisibleForTesting processInputPortAssociations(InputStream xml)87 static Map<String, Integer> processInputPortAssociations(InputStream xml) 88 throws Exception { 89 Map<String, Integer> associations = new HashMap<String, Integer>(); 90 { 91 TypedXmlPullParser parser = Xml.resolvePullParser(xml); 92 XmlUtils.beginDocument(parser, "ports"); 93 94 while (true) { 95 XmlUtils.nextElement(parser); 96 String entryName = parser.getName(); 97 if (!"port".equals(entryName)) { 98 break; 99 } 100 String inputPort = parser.getAttributeValue(null, "input"); 101 String displayPortStr = parser.getAttributeValue(null, "display"); 102 if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPortStr)) { 103 // This is likely an error by an OEM during device configuration 104 Slog.wtf(TAG, "Ignoring incomplete entry"); 105 continue; 106 } 107 try { 108 int displayPort = Integer.parseUnsignedInt(displayPortStr); 109 associations.put(inputPort, displayPort); 110 } catch (NumberFormatException e) { 111 Slog.wtf(TAG, "Display port should be an integer"); 112 } 113 } 114 } 115 return associations; 116 } 117 } 118