Merge "Support dynamic input mapping"
This commit is contained in:
committed by
Android (Google) Code Review
commit
56d6f15acd
@@ -90,4 +90,11 @@ interface IInputManager {
|
||||
|
||||
/** Create an input monitor for gestures. */
|
||||
InputMonitor monitorGestureInput(String name, int displayId);
|
||||
|
||||
// Add a runtime association between the input port and the display port. This overrides any
|
||||
// static associations.
|
||||
void addPortAssociation(in String inputPort, int displayPort);
|
||||
// Remove the runtime association between the input port and the display port. Any existing
|
||||
// static association for the cleared input port will be restored.
|
||||
void removePortAssociation(in String inputPort);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.hardware.input;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.annotation.SystemService;
|
||||
@@ -963,6 +964,41 @@ public final class InputManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a runtime association between the input port and the display port. This overrides any
|
||||
* static associations.
|
||||
* @param inputPort The port of the input device.
|
||||
* @param displayPort The physical port of the associated display.
|
||||
* <p>
|
||||
* Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT}.
|
||||
* </p>
|
||||
* @hide
|
||||
*/
|
||||
public void addPortAssociation(@NonNull String inputPort, int displayPort) {
|
||||
try {
|
||||
mIm.addPortAssociation(inputPort, displayPort);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the runtime association between the input port and the display port. Any existing
|
||||
* static association for the cleared input port will be restored.
|
||||
* @param inputPort The port of the input device to be cleared.
|
||||
* <p>
|
||||
* Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT}.
|
||||
* </p>
|
||||
* @hide
|
||||
*/
|
||||
public void removePortAssociation(@NonNull String inputPort) {
|
||||
try {
|
||||
mIm.removePortAssociation(inputPort);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private void populateInputDevicesLocked() {
|
||||
if (mInputDevicesChangedListener == null) {
|
||||
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
|
||||
|
||||
@@ -4756,6 +4756,10 @@
|
||||
<!-- Allows input events to be monitored. Very dangerous! @hide -->
|
||||
<permission android:name="android.permission.MONITOR_INPUT"
|
||||
android:protectionLevel="signature" />
|
||||
<!-- Allows the caller to change the associations between input devices and displays.
|
||||
Very dangerous! @hide -->
|
||||
<permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- Allows query of any normal app on the device, regardless of manifest declarations. -->
|
||||
<permission android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
|
||||
@@ -83,11 +83,11 @@ import android.view.ViewConfiguration;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
|
||||
import com.android.internal.notification.SystemNotificationChannels;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.DisplayThread;
|
||||
import com.android.server.LocalServices;
|
||||
@@ -186,6 +186,9 @@ public class InputManagerService extends IInputManager.Stub
|
||||
// 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 final Object mAssociationsLock = new Object();
|
||||
@GuardedBy("mAssociationLock")
|
||||
private final Map<String, Integer> mRuntimeAssociations = new HashMap<String, Integer>();
|
||||
|
||||
private static native long nativeInit(InputManagerService service,
|
||||
Context context, MessageQueue messageQueue);
|
||||
@@ -240,6 +243,7 @@ public class InputManagerService extends IInputManager.Stub
|
||||
private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
|
||||
private static native void nativeSetPointerCapture(long ptr, boolean detached);
|
||||
private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId);
|
||||
private static native void nativeNotifyPortAssociationsChanged(long ptr);
|
||||
|
||||
// Input event injection constants defined in InputDispatcher.h.
|
||||
private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
|
||||
@@ -1723,6 +1727,49 @@ public class InputManagerService extends IInputManager.Stub
|
||||
nativeSetCustomPointerIcon(mPtr, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a runtime association between the input port and the display port. This overrides any
|
||||
* static associations.
|
||||
* @param inputPort The port of the input device.
|
||||
* @param displayPort The physical port of the associated display.
|
||||
*/
|
||||
@Override // Binder call
|
||||
public void addPortAssociation(@NonNull String inputPort, int displayPort) {
|
||||
if (!checkCallingPermission(
|
||||
android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT,
|
||||
"addPortAssociation()")) {
|
||||
throw new SecurityException(
|
||||
"Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT permission");
|
||||
}
|
||||
|
||||
Objects.requireNonNull(inputPort);
|
||||
synchronized (mAssociationsLock) {
|
||||
mRuntimeAssociations.put(inputPort, displayPort);
|
||||
}
|
||||
nativeNotifyPortAssociationsChanged(mPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the runtime association between the input port and the display port. Any existing
|
||||
* static association for the cleared input port will be restored.
|
||||
* @param inputPort The port of the input device to be cleared.
|
||||
*/
|
||||
@Override // Binder call
|
||||
public void removePortAssociation(@NonNull String inputPort) {
|
||||
if (!checkCallingPermission(
|
||||
android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT,
|
||||
"clearPortAssociations()")) {
|
||||
throw new SecurityException(
|
||||
"Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT permission");
|
||||
}
|
||||
|
||||
Objects.requireNonNull(inputPort);
|
||||
synchronized (mAssociationsLock) {
|
||||
mRuntimeAssociations.remove(inputPort);
|
||||
}
|
||||
nativeNotifyPortAssociationsChanged(mPtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
|
||||
@@ -1743,6 +1790,16 @@ public class InputManagerService extends IInputManager.Stub
|
||||
pw.println(" display: " + v);
|
||||
});
|
||||
}
|
||||
|
||||
synchronized (mAssociationsLock) {
|
||||
if (!mRuntimeAssociations.isEmpty()) {
|
||||
pw.println("Runtime Associations:");
|
||||
mRuntimeAssociations.forEach((k, v) -> {
|
||||
pw.print(" port: " + k);
|
||||
pw.println(" display: " + v);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkCallingPermission(String permission, String func) {
|
||||
@@ -1766,6 +1823,7 @@ public class InputManagerService extends IInputManager.Stub
|
||||
@Override
|
||||
public void monitor() {
|
||||
synchronized (mInputFilterLock) { }
|
||||
synchronized (mAssociationsLock) { /* Test if blocked by associations lock. */}
|
||||
nativeMonitor(mPtr);
|
||||
}
|
||||
|
||||
@@ -1930,7 +1988,7 @@ public class InputManagerService extends IInputManager.Stub
|
||||
* @return Flattened list
|
||||
*/
|
||||
private static List<String> flatten(@NonNull Map<String, Integer> map) {
|
||||
List<String> list = new ArrayList<>(map.size() * 2);
|
||||
final List<String> list = new ArrayList<>(map.size() * 2);
|
||||
map.forEach((k, v)-> {
|
||||
list.add(k);
|
||||
list.add(v.toString());
|
||||
@@ -1943,11 +2001,11 @@ public class InputManagerService extends IInputManager.Stub
|
||||
* directory.
|
||||
*/
|
||||
private static Map<String, Integer> loadStaticInputPortAssociations() {
|
||||
File baseDir = Environment.getVendorDirectory();
|
||||
File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
|
||||
final File baseDir = Environment.getVendorDirectory();
|
||||
final File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
|
||||
|
||||
try {
|
||||
InputStream stream = new FileInputStream(confFile);
|
||||
final InputStream stream = new FileInputStream(confFile);
|
||||
return ConfigurationProcessor.processInputPortAssociations(stream);
|
||||
} catch (FileNotFoundException e) {
|
||||
// Most of the time, file will not exist, which is expected.
|
||||
@@ -1960,7 +2018,14 @@ public class InputManagerService extends IInputManager.Stub
|
||||
|
||||
// Native callback
|
||||
private String[] getInputPortAssociations() {
|
||||
List<String> associationList = flatten(mStaticAssociations);
|
||||
final Map<String, Integer> associations = new HashMap<>(mStaticAssociations);
|
||||
|
||||
// merge the runtime associations.
|
||||
synchronized (mAssociationsLock) {
|
||||
associations.putAll(mRuntimeAssociations);
|
||||
}
|
||||
|
||||
final List<String> associationList = flatten(associations);
|
||||
return associationList.toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1757,6 +1757,12 @@ static jboolean nativeCanDispatchToDisplay(JNIEnv* env, jclass /* clazz */, jlon
|
||||
return im->getInputManager()->getReader()->canDispatchToDisplay(deviceId, displayId);
|
||||
}
|
||||
|
||||
static void nativeNotifyPortAssociationsChanged(JNIEnv* env, jclass /* clazz */, jlong ptr) {
|
||||
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
||||
im->getInputManager()->getReader()->requestRefreshConfiguration(
|
||||
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static const JNINativeMethod gInputManagerMethods[] = {
|
||||
@@ -1842,6 +1848,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
|
||||
(void*) nativeSetCustomPointerIcon },
|
||||
{ "nativeCanDispatchToDisplay", "(JII)Z",
|
||||
(void*) nativeCanDispatchToDisplay },
|
||||
{ "nativeNotifyPortAssociationsChanged", "(J)V",
|
||||
(void*) nativeNotifyPortAssociationsChanged },
|
||||
};
|
||||
|
||||
#define FIND_CLASS(var, className) \
|
||||
|
||||
Reference in New Issue
Block a user