Loading services/core/java/com/android/server/input/ConfigurationProcessor.java +8 −8 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.input; import android.text.TextUtils; import android.util.Pair; import android.util.Slog; import android.util.Xml; Loading @@ -29,7 +28,9 @@ import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; class ConfigurationProcessor { Loading Loading @@ -86,9 +87,9 @@ class ConfigurationProcessor { * the second item in the pair is the display port. */ @VisibleForTesting static List<Pair<String, String>> processInputPortAssociations(InputStream xml) static Map<String, Integer> processInputPortAssociations(InputStream xml) throws Exception { List<Pair<String, String>> associations = new ArrayList<>(); Map<String, Integer> associations = new HashMap<String, Integer>(); try (InputStreamReader confReader = new InputStreamReader(xml)) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(confReader); Loading @@ -101,19 +102,18 @@ class ConfigurationProcessor { break; } String inputPort = parser.getAttributeValue(null, "input"); String displayPort = parser.getAttributeValue(null, "display"); if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPort)) { String displayPortStr = parser.getAttributeValue(null, "display"); if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPortStr)) { // This is likely an error by an OEM during device configuration Slog.wtf(TAG, "Ignoring incomplete entry"); continue; } try { Integer.parseUnsignedInt(displayPort); int displayPort = Integer.parseUnsignedInt(displayPortStr); associations.put(inputPort, displayPort); } catch (NumberFormatException e) { Slog.wtf(TAG, "Display port should be an integer"); continue; } associations.add(new Pair<>(inputPort, displayPort)); } } return associations; Loading services/core/java/com/android/server/input/InputManagerService.java +35 −16 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.view.Display; Loading Loading @@ -113,8 +112,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; /* * Wraps the C++ InputManager and provides its callbacks. */ Loading Loading @@ -184,6 +183,10 @@ public class InputManagerService extends IInputManager.Stub IInputFilter mInputFilter; // guarded by mInputFilterLock InputFilterHost mInputFilterHost; // guarded by mInputFilterLock // The associations of input devices to displays by port. Maps from input device port (String) // to display id (int). Currently only accessed by InputReader. private final Map<String, Integer> mStaticAssociations; private static native long nativeInit(InputManagerService service, Context context, MessageQueue messageQueue); private static native void nativeStart(long ptr); Loading Loading @@ -325,6 +328,7 @@ public class InputManagerService extends IInputManager.Stub mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null : new File(doubleTouchGestureEnablePath); mStaticAssociations = loadStaticInputPortAssociations(); LocalServices.addService(InputManagerInternal.class, new LocalService()); } Loading Loading @@ -1727,6 +1731,17 @@ public class InputManagerService extends IInputManager.Stub String dumpStr = nativeDump(mPtr); if (dumpStr != null) { pw.println(dumpStr); dumpAssociations(pw); } } private void dumpAssociations(PrintWriter pw) { if (!mStaticAssociations.isEmpty()) { pw.println("Static Associations:"); mStaticAssociations.forEach((k, v) -> { pw.print(" port: " + k); pw.println(" display: " + v); }); } } Loading Loading @@ -1910,15 +1925,16 @@ public class InputManagerService extends IInputManager.Stub } /** * Flatten a list of pairs into a list, with value positioned directly next to the key * Flatten a map into a string list, with value positioned directly next to the * key. * @return Flattened list */ private static <T> List<T> flatten(@NonNull List<Pair<T, T>> pairs) { List<T> list = new ArrayList<>(pairs.size() * 2); for (Pair<T, T> pair : pairs) { list.add(pair.first); list.add(pair.second); } private static List<String> flatten(@NonNull Map<String, Integer> map) { List<String> list = new ArrayList<>(map.size() * 2); map.forEach((k, v)-> { list.add(k); list.add(v.toString()); }); return list; } Loading @@ -1926,23 +1942,26 @@ public class InputManagerService extends IInputManager.Stub * Ports are highly platform-specific, so only allow these to be specified in the vendor * directory. */ // Native callback private static String[] getInputPortAssociations() { private static Map<String, Integer> loadStaticInputPortAssociations() { File baseDir = Environment.getVendorDirectory(); File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH); try { InputStream stream = new FileInputStream(confFile); List<Pair<String, String>> associations = ConfigurationProcessor.processInputPortAssociations(stream); List<String> associationList = flatten(associations); return associationList.toArray(new String[0]); return ConfigurationProcessor.processInputPortAssociations(stream); } catch (FileNotFoundException e) { // Most of the time, file will not exist, which is expected. } catch (Exception e) { Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e); } return new String[0]; return new HashMap<>(); } // Native callback private String[] getInputPortAssociations() { List<String> associationList = flatten(mStaticAssociations); return associationList.toArray(new String[0]); } /** Loading services/core/jni/com_android_server_input_InputManagerService.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -485,8 +485,8 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon // Received data: ['inputPort1', '1', 'inputPort2', '2'] // So we unpack accordingly here. outConfig->portAssociations.clear(); jobjectArray portAssociations = jobjectArray(env->CallStaticObjectMethod( gServiceClassInfo.clazz, gServiceClassInfo.getInputPortAssociations)); jobjectArray portAssociations = jobjectArray(env->CallObjectMethod(mServiceObj, gServiceClassInfo.getInputPortAssociations)); if (!checkAndClearExceptionFromCallback(env, "getInputPortAssociations") && portAssociations) { jsize length = env->GetArrayLength(portAssociations); for (jsize i = 0; i < length / 2; i++) { Loading Loading @@ -1920,7 +1920,7 @@ int register_android_server_InputManager(JNIEnv* env) { GET_STATIC_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz, "getExcludedDeviceNames", "()[Ljava/lang/String;"); GET_STATIC_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz, GET_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz, "getInputPortAssociations", "()[Ljava/lang/String;"); GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz, Loading services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java +5 −7 Original line number Diff line number Diff line Loading @@ -18,11 +18,9 @@ package com.android.server.input; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.content.Context; import android.util.Pair; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; Loading @@ -32,7 +30,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.InputStream; import java.util.List; import java.util.Map; /** * Build/Install/Run: Loading @@ -52,7 +50,7 @@ public class ConfigurationProcessorTest { public void testGetInputPortAssociations() { final int res = com.android.frameworks.servicestests.R.raw.input_port_associations; InputStream xml = mContext.getResources().openRawResource(res); List<Pair<String, String>> associations = null; Map<String, Integer> associations = null; try { associations = ConfigurationProcessor.processInputPortAssociations(xml); } catch (Exception e) { Loading @@ -60,8 +58,8 @@ public class ConfigurationProcessorTest { } assertNotNull(associations); assertEquals(2, associations.size()); assertTrue(associations.contains(Pair.create("USB1", "0"))); assertTrue(associations.contains(Pair.create("USB2", "1"))); assertEquals(0, associations.get("USB1").intValue()); assertEquals(1, associations.get("USB2").intValue()); } @Test Loading @@ -69,7 +67,7 @@ public class ConfigurationProcessorTest { final int res = com.android.frameworks.servicestests.R.raw.input_port_associations_bad_displayport; InputStream xml = mContext.getResources().openRawResource(res); List<Pair<String, String>> associations = null; Map<String, Integer> associations = null; try { associations = ConfigurationProcessor.processInputPortAssociations(xml); } catch (Exception e) { Loading Loading
services/core/java/com/android/server/input/ConfigurationProcessor.java +8 −8 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.input; import android.text.TextUtils; import android.util.Pair; import android.util.Slog; import android.util.Xml; Loading @@ -29,7 +28,9 @@ import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; class ConfigurationProcessor { Loading Loading @@ -86,9 +87,9 @@ class ConfigurationProcessor { * the second item in the pair is the display port. */ @VisibleForTesting static List<Pair<String, String>> processInputPortAssociations(InputStream xml) static Map<String, Integer> processInputPortAssociations(InputStream xml) throws Exception { List<Pair<String, String>> associations = new ArrayList<>(); Map<String, Integer> associations = new HashMap<String, Integer>(); try (InputStreamReader confReader = new InputStreamReader(xml)) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(confReader); Loading @@ -101,19 +102,18 @@ class ConfigurationProcessor { break; } String inputPort = parser.getAttributeValue(null, "input"); String displayPort = parser.getAttributeValue(null, "display"); if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPort)) { String displayPortStr = parser.getAttributeValue(null, "display"); if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPortStr)) { // This is likely an error by an OEM during device configuration Slog.wtf(TAG, "Ignoring incomplete entry"); continue; } try { Integer.parseUnsignedInt(displayPort); int displayPort = Integer.parseUnsignedInt(displayPortStr); associations.put(inputPort, displayPort); } catch (NumberFormatException e) { Slog.wtf(TAG, "Display port should be an integer"); continue; } associations.add(new Pair<>(inputPort, displayPort)); } } return associations; Loading
services/core/java/com/android/server/input/InputManagerService.java +35 −16 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.view.Display; Loading Loading @@ -113,8 +112,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; /* * Wraps the C++ InputManager and provides its callbacks. */ Loading Loading @@ -184,6 +183,10 @@ public class InputManagerService extends IInputManager.Stub IInputFilter mInputFilter; // guarded by mInputFilterLock InputFilterHost mInputFilterHost; // guarded by mInputFilterLock // The associations of input devices to displays by port. Maps from input device port (String) // to display id (int). Currently only accessed by InputReader. private final Map<String, Integer> mStaticAssociations; private static native long nativeInit(InputManagerService service, Context context, MessageQueue messageQueue); private static native void nativeStart(long ptr); Loading Loading @@ -325,6 +328,7 @@ public class InputManagerService extends IInputManager.Stub mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null : new File(doubleTouchGestureEnablePath); mStaticAssociations = loadStaticInputPortAssociations(); LocalServices.addService(InputManagerInternal.class, new LocalService()); } Loading Loading @@ -1727,6 +1731,17 @@ public class InputManagerService extends IInputManager.Stub String dumpStr = nativeDump(mPtr); if (dumpStr != null) { pw.println(dumpStr); dumpAssociations(pw); } } private void dumpAssociations(PrintWriter pw) { if (!mStaticAssociations.isEmpty()) { pw.println("Static Associations:"); mStaticAssociations.forEach((k, v) -> { pw.print(" port: " + k); pw.println(" display: " + v); }); } } Loading Loading @@ -1910,15 +1925,16 @@ public class InputManagerService extends IInputManager.Stub } /** * Flatten a list of pairs into a list, with value positioned directly next to the key * Flatten a map into a string list, with value positioned directly next to the * key. * @return Flattened list */ private static <T> List<T> flatten(@NonNull List<Pair<T, T>> pairs) { List<T> list = new ArrayList<>(pairs.size() * 2); for (Pair<T, T> pair : pairs) { list.add(pair.first); list.add(pair.second); } private static List<String> flatten(@NonNull Map<String, Integer> map) { List<String> list = new ArrayList<>(map.size() * 2); map.forEach((k, v)-> { list.add(k); list.add(v.toString()); }); return list; } Loading @@ -1926,23 +1942,26 @@ public class InputManagerService extends IInputManager.Stub * Ports are highly platform-specific, so only allow these to be specified in the vendor * directory. */ // Native callback private static String[] getInputPortAssociations() { private static Map<String, Integer> loadStaticInputPortAssociations() { File baseDir = Environment.getVendorDirectory(); File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH); try { InputStream stream = new FileInputStream(confFile); List<Pair<String, String>> associations = ConfigurationProcessor.processInputPortAssociations(stream); List<String> associationList = flatten(associations); return associationList.toArray(new String[0]); return ConfigurationProcessor.processInputPortAssociations(stream); } catch (FileNotFoundException e) { // Most of the time, file will not exist, which is expected. } catch (Exception e) { Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e); } return new String[0]; return new HashMap<>(); } // Native callback private String[] getInputPortAssociations() { List<String> associationList = flatten(mStaticAssociations); return associationList.toArray(new String[0]); } /** Loading
services/core/jni/com_android_server_input_InputManagerService.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -485,8 +485,8 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon // Received data: ['inputPort1', '1', 'inputPort2', '2'] // So we unpack accordingly here. outConfig->portAssociations.clear(); jobjectArray portAssociations = jobjectArray(env->CallStaticObjectMethod( gServiceClassInfo.clazz, gServiceClassInfo.getInputPortAssociations)); jobjectArray portAssociations = jobjectArray(env->CallObjectMethod(mServiceObj, gServiceClassInfo.getInputPortAssociations)); if (!checkAndClearExceptionFromCallback(env, "getInputPortAssociations") && portAssociations) { jsize length = env->GetArrayLength(portAssociations); for (jsize i = 0; i < length / 2; i++) { Loading Loading @@ -1920,7 +1920,7 @@ int register_android_server_InputManager(JNIEnv* env) { GET_STATIC_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz, "getExcludedDeviceNames", "()[Ljava/lang/String;"); GET_STATIC_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz, GET_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz, "getInputPortAssociations", "()[Ljava/lang/String;"); GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz, Loading
services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java +5 −7 Original line number Diff line number Diff line Loading @@ -18,11 +18,9 @@ package com.android.server.input; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.content.Context; import android.util.Pair; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; Loading @@ -32,7 +30,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.InputStream; import java.util.List; import java.util.Map; /** * Build/Install/Run: Loading @@ -52,7 +50,7 @@ public class ConfigurationProcessorTest { public void testGetInputPortAssociations() { final int res = com.android.frameworks.servicestests.R.raw.input_port_associations; InputStream xml = mContext.getResources().openRawResource(res); List<Pair<String, String>> associations = null; Map<String, Integer> associations = null; try { associations = ConfigurationProcessor.processInputPortAssociations(xml); } catch (Exception e) { Loading @@ -60,8 +58,8 @@ public class ConfigurationProcessorTest { } assertNotNull(associations); assertEquals(2, associations.size()); assertTrue(associations.contains(Pair.create("USB1", "0"))); assertTrue(associations.contains(Pair.create("USB2", "1"))); assertEquals(0, associations.get("USB1").intValue()); assertEquals(1, associations.get("USB2").intValue()); } @Test Loading @@ -69,7 +67,7 @@ public class ConfigurationProcessorTest { final int res = com.android.frameworks.servicestests.R.raw.input_port_associations_bad_displayport; InputStream xml = mContext.getResources().openRawResource(res); List<Pair<String, String>> associations = null; Map<String, Integer> associations = null; try { associations = ConfigurationProcessor.processInputPortAssociations(xml); } catch (Exception e) { Loading