Merge "Notify applications when input devices change."
This commit is contained in:
@@ -111,6 +111,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/database/IContentObserver.aidl \
|
||||
core/java/android/hardware/ISerialManager.aidl \
|
||||
core/java/android/hardware/input/IInputManager.aidl \
|
||||
core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
|
||||
core/java/android/hardware/usb/IUsbManager.aidl \
|
||||
core/java/android/net/IConnectivityManager.aidl \
|
||||
core/java/android/net/INetworkManagementEventObserver.aidl \
|
||||
|
||||
@@ -9822,10 +9822,20 @@ package android.hardware {
|
||||
package android.hardware.input {
|
||||
|
||||
public final class InputManager {
|
||||
method public android.view.InputDevice getInputDevice(int);
|
||||
method public int[] getInputDeviceIds();
|
||||
method public void registerInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener, android.os.Handler);
|
||||
method public void unregisterInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener);
|
||||
field public static final java.lang.String ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
|
||||
field public static final java.lang.String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
|
||||
}
|
||||
|
||||
public static abstract interface InputManager.InputDeviceListener {
|
||||
method public abstract void onInputDeviceAdded(int);
|
||||
method public abstract void onInputDeviceChanged(int);
|
||||
method public abstract void onInputDeviceRemoved(int);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.hardware.usb {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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;
|
||||
|
||||
/** @hide */
|
||||
interface IInputDevicesChangedListener {
|
||||
/* Called when input devices changed, such as a device being added,
|
||||
* removed or changing configuration.
|
||||
*
|
||||
* The parameter is an array of pairs (deviceId, generation) indicating the current
|
||||
* device id and generation of all input devices. The client can determine what
|
||||
* has happened by comparing the result to its prior observations.
|
||||
*/
|
||||
oneway void onInputDevicesChanged(in int[] deviceIdAndGeneration);
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.hardware.input;
|
||||
|
||||
import android.hardware.input.KeyboardLayout;
|
||||
import android.hardware.input.IInputDevicesChangedListener;
|
||||
import android.view.InputDevice;
|
||||
import android.view.InputEvent;
|
||||
|
||||
@@ -42,4 +43,7 @@ interface IInputManager {
|
||||
String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor);
|
||||
void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
|
||||
String keyboardLayoutDescriptor);
|
||||
|
||||
// Registers an input devices changed listener.
|
||||
void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,10 @@ package android.hardware.input;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.provider.Settings;
|
||||
@@ -29,6 +32,8 @@ import android.util.SparseArray;
|
||||
import android.view.InputDevice;
|
||||
import android.view.InputEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Provides information about input devices and available key layouts.
|
||||
* <p>
|
||||
@@ -40,11 +45,22 @@ import android.view.InputEvent;
|
||||
*/
|
||||
public final class InputManager {
|
||||
private static final String TAG = "InputManager";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final int MSG_DEVICE_ADDED = 1;
|
||||
private static final int MSG_DEVICE_REMOVED = 2;
|
||||
private static final int MSG_DEVICE_CHANGED = 3;
|
||||
|
||||
private static InputManager sInstance;
|
||||
|
||||
private final IInputManager mIm;
|
||||
private final SparseArray<InputDevice> mInputDevices = new SparseArray<InputDevice>();
|
||||
|
||||
// Guarded by mInputDevicesLock
|
||||
private final Object mInputDevicesLock = new Object();
|
||||
private SparseArray<InputDevice> mInputDevices;
|
||||
private InputDevicesChangedListener mInputDevicesChangedListener;
|
||||
private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
|
||||
new ArrayList<InputDeviceListenerDelegate>();
|
||||
|
||||
/**
|
||||
* Broadcast Action: Query available keyboard layouts.
|
||||
@@ -168,6 +184,103 @@ public final class InputManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about the input device with the specified id.
|
||||
* @param id The device id.
|
||||
* @return The input device or null if not found.
|
||||
*/
|
||||
public InputDevice getInputDevice(int id) {
|
||||
synchronized (mInputDevicesLock) {
|
||||
populateInputDevicesLocked();
|
||||
|
||||
int index = mInputDevices.indexOfKey(id);
|
||||
if (index < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
InputDevice inputDevice = mInputDevices.valueAt(index);
|
||||
if (inputDevice == null) {
|
||||
try {
|
||||
inputDevice = mIm.getInputDevice(id);
|
||||
} catch (RemoteException ex) {
|
||||
throw new RuntimeException("Could not get input device information.", ex);
|
||||
}
|
||||
}
|
||||
mInputDevices.setValueAt(index, inputDevice);
|
||||
return inputDevice;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ids of all input devices in the system.
|
||||
* @return The input device ids.
|
||||
*/
|
||||
public int[] getInputDeviceIds() {
|
||||
synchronized (mInputDevicesLock) {
|
||||
populateInputDevicesLocked();
|
||||
|
||||
final int count = mInputDevices.size();
|
||||
final int[] ids = new int[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
ids[i] = mInputDevices.keyAt(i);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an input device listener to receive notifications about when
|
||||
* input devices are added, removed or changed.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
* @param handler The handler on which the listener should be invoked, or null
|
||||
* if the listener should be invoked on the calling thread's looper.
|
||||
*
|
||||
* @see #unregisterInputDeviceListener
|
||||
*/
|
||||
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("listener must not be null");
|
||||
}
|
||||
|
||||
synchronized (mInputDevicesLock) {
|
||||
int index = findInputDeviceListenerLocked(listener);
|
||||
if (index < 0) {
|
||||
mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters an input device listener.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*
|
||||
* @see #registerInputDeviceListener
|
||||
*/
|
||||
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("listener must not be null");
|
||||
}
|
||||
|
||||
synchronized (mInputDevicesLock) {
|
||||
int index = findInputDeviceListenerLocked(listener);
|
||||
if (index >= 0) {
|
||||
mInputDeviceListeners.remove(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int findInputDeviceListenerLocked(InputDeviceListener listener) {
|
||||
final int numListeners = mInputDeviceListeners.size();
|
||||
for (int i = 0; i < numListeners; i++) {
|
||||
if (mInputDeviceListeners.get(i).mListener == listener) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about all supported keyboard layouts.
|
||||
* <p>
|
||||
@@ -326,50 +439,6 @@ public final class InputManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about the input device with the specified id.
|
||||
* @param id The device id.
|
||||
* @return The input device or null if not found.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public InputDevice getInputDevice(int id) {
|
||||
synchronized (mInputDevices) {
|
||||
InputDevice inputDevice = mInputDevices.get(id);
|
||||
if (inputDevice != null) {
|
||||
return inputDevice;
|
||||
}
|
||||
}
|
||||
final InputDevice newInputDevice;
|
||||
try {
|
||||
newInputDevice = mIm.getInputDevice(id);
|
||||
} catch (RemoteException ex) {
|
||||
throw new RuntimeException("Could not get input device information.", ex);
|
||||
}
|
||||
synchronized (mInputDevices) {
|
||||
InputDevice inputDevice = mInputDevices.get(id);
|
||||
if (inputDevice != null) {
|
||||
return inputDevice;
|
||||
}
|
||||
mInputDevices.put(id, newInputDevice);
|
||||
return newInputDevice;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ids of all input devices in the system.
|
||||
* @return The input device ids.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public int[] getInputDeviceIds() {
|
||||
try {
|
||||
return mIm.getInputDeviceIds();
|
||||
} catch (RemoteException ex) {
|
||||
throw new RuntimeException("Could not get input device ids.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the framework about whether any physical keys exist on the
|
||||
* any keyboard attached to the device that are capable of producing the given
|
||||
@@ -429,4 +498,151 @@ public final class InputManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void populateInputDevicesLocked() {
|
||||
if (mInputDevicesChangedListener == null) {
|
||||
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
|
||||
try {
|
||||
mIm.registerInputDevicesChangedListener(listener);
|
||||
} catch (RemoteException ex) {
|
||||
throw new RuntimeException(
|
||||
"Could not get register input device changed listener", ex);
|
||||
}
|
||||
mInputDevicesChangedListener = listener;
|
||||
}
|
||||
|
||||
if (mInputDevices == null) {
|
||||
final int[] ids;
|
||||
try {
|
||||
ids = mIm.getInputDeviceIds();
|
||||
} catch (RemoteException ex) {
|
||||
throw new RuntimeException("Could not get input device ids.", ex);
|
||||
}
|
||||
|
||||
mInputDevices = new SparseArray<InputDevice>();
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
mInputDevices.put(ids[i], null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Received input devices changed.");
|
||||
}
|
||||
|
||||
synchronized (mInputDevicesLock) {
|
||||
for (int i = mInputDevices.size(); --i > 0; ) {
|
||||
final int deviceId = mInputDevices.keyAt(i);
|
||||
if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Device removed: " + deviceId);
|
||||
}
|
||||
mInputDevices.removeAt(i);
|
||||
sendMessageToInputDeviceListenersLocked(MSG_DEVICE_REMOVED, deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
|
||||
final int deviceId = deviceIdAndGeneration[i];
|
||||
int index = mInputDevices.indexOfKey(deviceId);
|
||||
if (index >= 0) {
|
||||
final InputDevice device = mInputDevices.valueAt(index);
|
||||
if (device != null) {
|
||||
final int generation = deviceIdAndGeneration[i + 1];
|
||||
if (device.getGeneration() != generation) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Device changed: " + deviceId);
|
||||
}
|
||||
mInputDevices.setValueAt(index, null);
|
||||
sendMessageToInputDeviceListenersLocked(MSG_DEVICE_CHANGED, deviceId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Device added: " + deviceId);
|
||||
}
|
||||
mInputDevices.put(deviceId, null);
|
||||
sendMessageToInputDeviceListenersLocked(MSG_DEVICE_ADDED, deviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
|
||||
final int numListeners = mInputDeviceListeners.size();
|
||||
for (int i = 0; i < numListeners; i++) {
|
||||
InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
|
||||
listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
|
||||
for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
|
||||
if (deviceIdAndGeneration[i] == deviceId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for changes in input devices.
|
||||
*/
|
||||
public interface InputDeviceListener {
|
||||
/**
|
||||
* Called whenever an input device has been added to the system.
|
||||
* Use {@link InputManager#getInputDevice} to get more information about the device.
|
||||
*
|
||||
* @param deviceId The id of the input device that was added.
|
||||
*/
|
||||
void onInputDeviceAdded(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever an input device has been removed from the system.
|
||||
*
|
||||
* @param deviceId The id of the input device that was removed.
|
||||
*/
|
||||
void onInputDeviceRemoved(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever the properties of an input device have changed since they
|
||||
* were last queried. Use {@link InputManager#getInputDevice} to get
|
||||
* a fresh {@link InputDevice} object with the new properties.
|
||||
*
|
||||
* @param deviceId The id of the input device that changed.
|
||||
*/
|
||||
void onInputDeviceChanged(int deviceId);
|
||||
}
|
||||
|
||||
private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
|
||||
@Override
|
||||
public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
|
||||
InputManager.this.onInputDevicesChanged(deviceIdAndGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class InputDeviceListenerDelegate extends Handler {
|
||||
public final InputDeviceListener mListener;
|
||||
|
||||
public InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
|
||||
super(handler != null ? handler.getLooper() : Looper.myLooper());
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_DEVICE_ADDED:
|
||||
mListener.onInputDeviceAdded(msg.arg1);
|
||||
break;
|
||||
case MSG_DEVICE_REMOVED:
|
||||
mListener.onInputDeviceRemoved(msg.arg1);
|
||||
break;
|
||||
case MSG_DEVICE_CHANGED:
|
||||
mListener.onInputDeviceChanged(msg.arg1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.List;
|
||||
*/
|
||||
public final class InputDevice implements Parcelable {
|
||||
private final int mId;
|
||||
private final int mGeneration;
|
||||
private final String mName;
|
||||
private final String mDescriptor;
|
||||
private final int mSources;
|
||||
@@ -302,9 +303,10 @@ public final class InputDevice implements Parcelable {
|
||||
};
|
||||
|
||||
// Called by native code.
|
||||
private InputDevice(int id, String name, String descriptor, int sources,
|
||||
private InputDevice(int id, int generation, String name, String descriptor, int sources,
|
||||
int keyboardType, KeyCharacterMap keyCharacterMap) {
|
||||
mId = id;
|
||||
mGeneration = generation;
|
||||
mName = name;
|
||||
mDescriptor = descriptor;
|
||||
mSources = sources;
|
||||
@@ -314,6 +316,7 @@ public final class InputDevice implements Parcelable {
|
||||
|
||||
private InputDevice(Parcel in) {
|
||||
mId = in.readInt();
|
||||
mGeneration = in.readInt();
|
||||
mName = in.readString();
|
||||
mDescriptor = in.readString();
|
||||
mSources = in.readInt();
|
||||
@@ -363,6 +366,19 @@ public final class InputDevice implements Parcelable {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a generation number for this input device.
|
||||
* The generation number is incremented whenever the device is reconfigured and its
|
||||
* properties may have changed.
|
||||
*
|
||||
* @return The generation number.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public int getGeneration() {
|
||||
return mGeneration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input device descriptor, which is a stable identifier for an input device.
|
||||
* <p>
|
||||
@@ -595,6 +611,7 @@ public final class InputDevice implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(mId);
|
||||
out.writeInt(mGeneration);
|
||||
out.writeString(mName);
|
||||
out.writeString(mDescriptor);
|
||||
out.writeInt(mSources);
|
||||
@@ -624,6 +641,7 @@ public final class InputDevice implements Parcelable {
|
||||
StringBuilder description = new StringBuilder();
|
||||
description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
|
||||
description.append(" Descriptor: ").append(mDescriptor).append("\n");
|
||||
description.append(" Generation: ").append(mGeneration).append("\n");
|
||||
|
||||
description.append(" Keyboard Type: ");
|
||||
switch (mKeyboardType) {
|
||||
|
||||
@@ -22,8 +22,6 @@ import android.text.method.MetaKeyKeyListener;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.util.SparseIntArray;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InputDevice.MotionRange;
|
||||
|
||||
import java.lang.Character;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Paint.FontMetricsInt;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.hardware.input.InputManager.InputDeviceListener;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
@@ -32,7 +34,7 @@ import android.view.MotionEvent.PointerCoords;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class PointerLocationView extends View {
|
||||
public class PointerLocationView extends View implements InputDeviceListener {
|
||||
private static final String TAG = "Pointer";
|
||||
|
||||
public static class PointerState {
|
||||
@@ -82,6 +84,8 @@ public class PointerLocationView extends View {
|
||||
private final int ESTIMATE_FUTURE_POINTS = 2;
|
||||
private final float ESTIMATE_INTERVAL = 0.02f;
|
||||
|
||||
private final InputManager mIm;
|
||||
|
||||
private final ViewConfiguration mVC;
|
||||
private final Paint mTextPaint;
|
||||
private final Paint mTextBackgroundPaint;
|
||||
@@ -108,6 +112,8 @@ public class PointerLocationView extends View {
|
||||
super(c);
|
||||
setFocusableInTouchMode(true);
|
||||
|
||||
mIm = (InputManager)c.getSystemService(Context.INPUT_SERVICE);
|
||||
|
||||
mVC = ViewConfiguration.get(c);
|
||||
mTextPaint = new Paint();
|
||||
mTextPaint.setAntiAlias(true);
|
||||
@@ -139,18 +145,6 @@ public class PointerLocationView extends View {
|
||||
mActivePointerId = 0;
|
||||
|
||||
mVelocity = VelocityTracker.obtain();
|
||||
|
||||
logInputDeviceCapabilities();
|
||||
}
|
||||
|
||||
private void logInputDeviceCapabilities() {
|
||||
int[] deviceIds = InputDevice.getDeviceIds();
|
||||
for (int i = 0; i < deviceIds.length; i++) {
|
||||
InputDevice device = InputDevice.getDevice(deviceIds[i]);
|
||||
if (device != null) {
|
||||
Log.i(TAG, device.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPrintCoords(boolean state) {
|
||||
@@ -631,7 +625,53 @@ public class PointerLocationView extends View {
|
||||
logMotionEvent("Trackball", event);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
mIm.registerInputDeviceListener(this, getHandler());
|
||||
logInputDevices();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
mIm.unregisterInputDeviceListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int deviceId) {
|
||||
logInputDeviceState(deviceId, "Device Added");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
logInputDeviceState(deviceId, "Device Changed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
logInputDeviceState(deviceId, "Device Removed");
|
||||
}
|
||||
|
||||
private void logInputDevices() {
|
||||
int[] deviceIds = InputDevice.getDeviceIds();
|
||||
for (int i = 0; i < deviceIds.length; i++) {
|
||||
logInputDeviceState(deviceIds[i], "Device Enumerated");
|
||||
}
|
||||
}
|
||||
|
||||
private void logInputDeviceState(int deviceId, String state) {
|
||||
InputDevice device = mIm.getInputDevice(deviceId);
|
||||
if (device != null) {
|
||||
Log.i(TAG, state + ": " + device);
|
||||
} else {
|
||||
Log.i(TAG, state + ": " + deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
// HACK
|
||||
// A quick and dirty string builder implementation optimized for GC.
|
||||
// Using String.format causes the application grind to a halt when
|
||||
|
||||
@@ -54,8 +54,9 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
|
||||
}
|
||||
|
||||
ScopedLocalRef<jobject> inputDeviceObj(env, env->NewObject(gInputDeviceClassInfo.clazz,
|
||||
gInputDeviceClassInfo.ctor, deviceInfo.getId(), nameObj.get(),
|
||||
descriptorObj.get(), deviceInfo.getSources(), deviceInfo.getKeyboardType(),
|
||||
gInputDeviceClassInfo.ctor, deviceInfo.getId(), deviceInfo.getGeneration(),
|
||||
nameObj.get(), descriptorObj.get(),
|
||||
deviceInfo.getSources(), deviceInfo.getKeyboardType(),
|
||||
kcmObj.get()));
|
||||
|
||||
const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
|
||||
@@ -86,7 +87,7 @@ int register_android_view_InputDevice(JNIEnv* env)
|
||||
gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
|
||||
|
||||
GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz,
|
||||
"<init>", "(ILjava/lang/String;Ljava/lang/String;IILandroid/view/KeyCharacterMap;)V");
|
||||
"<init>", "(IILjava/lang/String;Ljava/lang/String;IILandroid/view/KeyCharacterMap;)V");
|
||||
|
||||
GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz,
|
||||
"addMotionRange", "(IIFFFF)V");
|
||||
|
||||
@@ -66,9 +66,11 @@ public:
|
||||
float fuzz;
|
||||
};
|
||||
|
||||
void initialize(int32_t id, const String8& name, const String8& descriptor);
|
||||
void initialize(int32_t id, int32_t generation,
|
||||
const String8& name, const String8& descriptor);
|
||||
|
||||
inline int32_t getId() const { return mId; }
|
||||
inline int32_t getGeneration() const { return mGeneration; }
|
||||
inline const String8 getName() const { return mName; }
|
||||
inline const String8 getDescriptor() const { return mDescriptor; }
|
||||
inline uint32_t getSources() const { return mSources; }
|
||||
@@ -97,6 +99,7 @@ public:
|
||||
|
||||
private:
|
||||
int32_t mId;
|
||||
int32_t mGeneration;
|
||||
String8 mName;
|
||||
String8 mDescriptor;
|
||||
uint32_t mSources;
|
||||
|
||||
@@ -127,11 +127,12 @@ String8 getInputDeviceConfigurationFilePathByName(
|
||||
// --- InputDeviceInfo ---
|
||||
|
||||
InputDeviceInfo::InputDeviceInfo() {
|
||||
initialize(-1, String8("uninitialized device info"), String8("unknown"));
|
||||
initialize(-1, -1, String8("uninitialized device info"), String8("unknown"));
|
||||
}
|
||||
|
||||
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
|
||||
mId(other.mId), mName(other.mName), mDescriptor(other.mDescriptor),
|
||||
mId(other.mId), mGeneration(other.mGeneration),
|
||||
mName(other.mName), mDescriptor(other.mDescriptor),
|
||||
mSources(other.mSources),
|
||||
mKeyboardType(other.mKeyboardType),
|
||||
mKeyCharacterMap(other.mKeyCharacterMap),
|
||||
@@ -141,8 +142,10 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
|
||||
InputDeviceInfo::~InputDeviceInfo() {
|
||||
}
|
||||
|
||||
void InputDeviceInfo::initialize(int32_t id, const String8& name, const String8& descriptor) {
|
||||
void InputDeviceInfo::initialize(int32_t id, int32_t generation,
|
||||
const String8& name, const String8& descriptor) {
|
||||
mId = id;
|
||||
mGeneration = generation;
|
||||
mName = name;
|
||||
mDescriptor = descriptor;
|
||||
mSources = 0;
|
||||
|
||||
@@ -720,6 +720,11 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (eventItem.events & EPOLLHUP) {
|
||||
ALOGI("Removing device %s due to epoll hang-up event.",
|
||||
device->identifier.name.string());
|
||||
deviceChanged = true;
|
||||
closeDeviceLocked(device);
|
||||
} else {
|
||||
ALOGW("Received unexpected epoll event 0x%08x for device %s.",
|
||||
eventItem.events, device->identifier.name.string());
|
||||
|
||||
@@ -237,7 +237,8 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub,
|
||||
const sp<InputReaderPolicyInterface>& policy,
|
||||
const sp<InputListenerInterface>& listener) :
|
||||
mContext(this), mEventHub(eventHub), mPolicy(policy),
|
||||
mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
|
||||
mGlobalMetaState(0), mGeneration(1),
|
||||
mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
|
||||
mConfigurationChangesToRefresh(0) {
|
||||
mQueuedListener = new QueuedInputListener(listener);
|
||||
|
||||
@@ -257,18 +258,24 @@ InputReader::~InputReader() {
|
||||
}
|
||||
|
||||
void InputReader::loopOnce() {
|
||||
int32_t oldGeneration;
|
||||
int32_t timeoutMillis;
|
||||
bool inputDevicesChanged = false;
|
||||
Vector<InputDeviceInfo> inputDevices;
|
||||
{ // acquire lock
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
oldGeneration = mGeneration;
|
||||
timeoutMillis = -1;
|
||||
|
||||
uint32_t changes = mConfigurationChangesToRefresh;
|
||||
if (changes) {
|
||||
mConfigurationChangesToRefresh = 0;
|
||||
timeoutMillis = 0;
|
||||
refreshConfigurationLocked(changes);
|
||||
}
|
||||
|
||||
timeoutMillis = -1;
|
||||
if (mNextTimeout != LLONG_MAX) {
|
||||
if (timeoutMillis < 0 && mNextTimeout != LLONG_MAX) {
|
||||
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
|
||||
}
|
||||
@@ -283,7 +290,8 @@ void InputReader::loopOnce() {
|
||||
if (count) {
|
||||
processEventsLocked(mEventBuffer, count);
|
||||
}
|
||||
if (!count || timeoutMillis == 0) {
|
||||
|
||||
if (mNextTimeout != LLONG_MAX) {
|
||||
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
if (now >= mNextTimeout) {
|
||||
#if DEBUG_RAW_EVENTS
|
||||
@@ -293,8 +301,18 @@ void InputReader::loopOnce() {
|
||||
timeoutExpiredLocked(now);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldGeneration != mGeneration) {
|
||||
inputDevicesChanged = true;
|
||||
getInputDevicesLocked(inputDevices);
|
||||
}
|
||||
} // release lock
|
||||
|
||||
// Send out a message that the describes the changed input devices.
|
||||
if (inputDevicesChanged) {
|
||||
mPolicy->notifyInputDevicesChanged(inputDevices);
|
||||
}
|
||||
|
||||
// Flush queued events out to the listener.
|
||||
// This must happen outside of the lock because the listener could potentially call
|
||||
// back into the InputReader's methods, such as getScanCodeState, or become blocked
|
||||
@@ -344,6 +362,12 @@ void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
|
||||
}
|
||||
|
||||
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
|
||||
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
|
||||
if (deviceIndex >= 0) {
|
||||
ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
|
||||
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
|
||||
|
||||
@@ -359,27 +383,22 @@ void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
|
||||
identifier.name.string(), device->getSources());
|
||||
}
|
||||
|
||||
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
|
||||
if (deviceIndex < 0) {
|
||||
mDevices.add(deviceId, device);
|
||||
} else {
|
||||
ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
|
||||
delete device;
|
||||
return;
|
||||
}
|
||||
mDevices.add(deviceId, device);
|
||||
bumpGenerationLocked();
|
||||
}
|
||||
|
||||
void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
|
||||
InputDevice* device = NULL;
|
||||
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
|
||||
if (deviceIndex >= 0) {
|
||||
device = mDevices.valueAt(deviceIndex);
|
||||
mDevices.removeItemsAt(deviceIndex, 1);
|
||||
} else {
|
||||
if (deviceIndex < 0) {
|
||||
ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
device = mDevices.valueAt(deviceIndex);
|
||||
mDevices.removeItemsAt(deviceIndex, 1);
|
||||
bumpGenerationLocked();
|
||||
|
||||
if (device->isIgnored()) {
|
||||
ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
|
||||
device->getId(), device->getName().string());
|
||||
@@ -394,7 +413,8 @@ void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
|
||||
|
||||
InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
|
||||
const InputDeviceIdentifier& identifier, uint32_t classes) {
|
||||
InputDevice* device = new InputDevice(&mContext, deviceId, identifier, classes);
|
||||
InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
|
||||
identifier, classes);
|
||||
|
||||
// External devices.
|
||||
if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
|
||||
@@ -577,39 +597,30 @@ void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
|
||||
}
|
||||
}
|
||||
|
||||
int32_t InputReader::bumpGenerationLocked() {
|
||||
return ++mGeneration;
|
||||
}
|
||||
|
||||
void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
*outConfiguration = mInputConfiguration;
|
||||
}
|
||||
|
||||
status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
|
||||
void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
|
||||
if (deviceIndex < 0) {
|
||||
return NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
InputDevice* device = mDevices.valueAt(deviceIndex);
|
||||
if (device->isIgnored()) {
|
||||
return NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
device->getDeviceInfo(outDeviceInfo);
|
||||
return OK;
|
||||
getInputDevicesLocked(outInputDevices);
|
||||
}
|
||||
|
||||
void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
outDeviceIds.clear();
|
||||
void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) {
|
||||
outInputDevices.clear();
|
||||
|
||||
size_t numDevices = mDevices.size();
|
||||
for (size_t i = 0; i < numDevices; i++) {
|
||||
InputDevice* device = mDevices.valueAt(i);
|
||||
if (!device->isIgnored()) {
|
||||
outDeviceIds.add(device->getId());
|
||||
outInputDevices.push();
|
||||
device->getDeviceInfo(&outInputDevices.editTop());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -824,6 +835,11 @@ void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
|
||||
mReader->requestTimeoutAtTimeLocked(when);
|
||||
}
|
||||
|
||||
int32_t InputReader::ContextImpl::bumpGeneration() {
|
||||
// lock is already held by the input loop
|
||||
return mReader->bumpGenerationLocked();
|
||||
}
|
||||
|
||||
InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
|
||||
return mReader->mPolicy.get();
|
||||
}
|
||||
@@ -854,9 +870,10 @@ bool InputReaderThread::threadLoop() {
|
||||
|
||||
// --- InputDevice ---
|
||||
|
||||
InputDevice::InputDevice(InputReaderContext* context, int32_t id,
|
||||
InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
|
||||
const InputDeviceIdentifier& identifier, uint32_t classes) :
|
||||
mContext(context), mId(id), mIdentifier(identifier), mClasses(classes),
|
||||
mContext(context), mId(id), mGeneration(generation),
|
||||
mIdentifier(identifier), mClasses(classes),
|
||||
mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
|
||||
}
|
||||
|
||||
@@ -874,6 +891,7 @@ void InputDevice::dump(String8& dump) {
|
||||
|
||||
dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
|
||||
deviceInfo.getName().string());
|
||||
dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
|
||||
dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
|
||||
dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
|
||||
dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
|
||||
@@ -983,7 +1001,7 @@ void InputDevice::timeoutExpired(nsecs_t when) {
|
||||
}
|
||||
|
||||
void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
|
||||
outDeviceInfo->initialize(mId, mIdentifier.name, mIdentifier.descriptor);
|
||||
outDeviceInfo->initialize(mId, mGeneration, mIdentifier.name, mIdentifier.descriptor);
|
||||
|
||||
size_t numMappers = mMappers.size();
|
||||
for (size_t i = 0; i < numMappers; i++) {
|
||||
@@ -1054,6 +1072,10 @@ void InputDevice::fadePointer() {
|
||||
}
|
||||
}
|
||||
|
||||
void InputDevice::bumpGeneration() {
|
||||
mGeneration = mContext->bumpGeneration();
|
||||
}
|
||||
|
||||
void InputDevice::notifyReset(nsecs_t when) {
|
||||
NotifyDeviceResetArgs args(when, mId);
|
||||
mContext->getListener()->notifyDeviceReset(&args);
|
||||
@@ -1728,6 +1750,10 @@ status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axi
|
||||
return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
|
||||
}
|
||||
|
||||
void InputMapper::bumpGeneration() {
|
||||
mDevice->bumpGeneration();
|
||||
}
|
||||
|
||||
void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
|
||||
const RawAbsoluteAxisInfo& axis, const char* name) {
|
||||
if (axis.valid) {
|
||||
@@ -2137,6 +2163,7 @@ void CursorInputMapper::configure(nsecs_t when,
|
||||
} else {
|
||||
mOrientation = DISPLAY_ORIENTATION_0;
|
||||
}
|
||||
bumpGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2998,6 +3025,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
|
||||
|
||||
// Inform the dispatcher about the changes.
|
||||
*outResetNeeded = true;
|
||||
bumpGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,11 @@ public:
|
||||
|
||||
/* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
|
||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
|
||||
|
||||
/* Notifies the input reader policy that some input devices have changed
|
||||
* and provides information about all current input devices.
|
||||
*/
|
||||
virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -240,16 +245,11 @@ public:
|
||||
*/
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
|
||||
|
||||
/* Gets information about the specified input device.
|
||||
* Returns OK if the device information was obtained or NAME_NOT_FOUND if there
|
||||
* was no such device.
|
||||
/* Gets information about all input devices.
|
||||
*
|
||||
* This method may be called on any thread (usually by the input manager).
|
||||
*/
|
||||
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
|
||||
|
||||
/* Gets the list of all registered device ids. */
|
||||
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
|
||||
virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices) = 0;
|
||||
|
||||
/* Query current input state. */
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
@@ -288,6 +288,7 @@ public:
|
||||
virtual void fadePointer() = 0;
|
||||
|
||||
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
|
||||
virtual int32_t bumpGeneration() = 0;
|
||||
|
||||
virtual InputReaderPolicyInterface* getPolicy() = 0;
|
||||
virtual InputListenerInterface* getListener() = 0;
|
||||
@@ -319,9 +320,7 @@ public:
|
||||
virtual void loopOnce();
|
||||
|
||||
virtual void getInputConfiguration(InputConfiguration* outConfiguration);
|
||||
|
||||
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
|
||||
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
|
||||
virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices);
|
||||
|
||||
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
|
||||
int32_t scanCode);
|
||||
@@ -353,6 +352,7 @@ protected:
|
||||
InputDevice* device, int32_t keyCode, int32_t scanCode);
|
||||
virtual void fadePointer();
|
||||
virtual void requestTimeoutAtTime(nsecs_t when);
|
||||
virtual int32_t bumpGeneration();
|
||||
virtual InputReaderPolicyInterface* getPolicy();
|
||||
virtual InputListenerInterface* getListener();
|
||||
virtual EventHubInterface* getEventHub();
|
||||
@@ -393,9 +393,14 @@ private:
|
||||
|
||||
void fadePointerLocked();
|
||||
|
||||
int32_t mGeneration;
|
||||
int32_t bumpGenerationLocked();
|
||||
|
||||
InputConfiguration mInputConfiguration;
|
||||
void updateInputConfigurationLocked();
|
||||
|
||||
void getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices);
|
||||
|
||||
nsecs_t mDisableVirtualKeysTimeout;
|
||||
void disableVirtualKeysUntilLocked(nsecs_t time);
|
||||
bool shouldDropVirtualKeyLocked(nsecs_t now,
|
||||
@@ -432,12 +437,13 @@ private:
|
||||
/* Represents the state of a single input device. */
|
||||
class InputDevice {
|
||||
public:
|
||||
InputDevice(InputReaderContext* context, int32_t id,
|
||||
InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
|
||||
const InputDeviceIdentifier& identifier, uint32_t classes);
|
||||
~InputDevice();
|
||||
|
||||
inline InputReaderContext* getContext() { return mContext; }
|
||||
inline int32_t getId() { return mId; }
|
||||
inline int32_t getGeneration() { return mGeneration; }
|
||||
inline const String8& getName() { return mIdentifier.name; }
|
||||
inline uint32_t getClasses() { return mClasses; }
|
||||
inline uint32_t getSources() { return mSources; }
|
||||
@@ -465,6 +471,8 @@ public:
|
||||
|
||||
void fadePointer();
|
||||
|
||||
void bumpGeneration();
|
||||
|
||||
void notifyReset(nsecs_t when);
|
||||
|
||||
inline const PropertyMap& getConfiguration() { return mConfiguration; }
|
||||
@@ -487,6 +495,7 @@ public:
|
||||
private:
|
||||
InputReaderContext* mContext;
|
||||
int32_t mId;
|
||||
int32_t mGeneration;
|
||||
InputDeviceIdentifier mIdentifier;
|
||||
uint32_t mClasses;
|
||||
|
||||
@@ -849,6 +858,7 @@ protected:
|
||||
InputReaderContext* mContext;
|
||||
|
||||
status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
|
||||
void bumpGeneration();
|
||||
|
||||
static void dumpRawAbsoluteAxisInfo(String8& dump,
|
||||
const RawAbsoluteAxisInfo& axis, const char* name);
|
||||
|
||||
@@ -127,6 +127,7 @@ private:
|
||||
class FakeInputReaderPolicy : public InputReaderPolicyInterface {
|
||||
InputReaderConfiguration mConfig;
|
||||
KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
|
||||
Vector<InputDeviceInfo> mInputDevices;
|
||||
|
||||
protected:
|
||||
virtual ~FakeInputReaderPolicy() { }
|
||||
@@ -141,10 +142,6 @@ public:
|
||||
mConfig.setDisplayInfo(displayId, true /*external*/, width, height, orientation);
|
||||
}
|
||||
|
||||
virtual nsecs_t getVirtualKeyQuietTime() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void addExcludedDeviceName(const String8& deviceName) {
|
||||
mConfig.excludedDeviceNames.push(deviceName);
|
||||
}
|
||||
@@ -157,6 +154,10 @@ public:
|
||||
return &mConfig;
|
||||
}
|
||||
|
||||
const Vector<InputDeviceInfo>& getInputDevices() const {
|
||||
return mInputDevices;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) {
|
||||
*outConfig = mConfig;
|
||||
@@ -165,6 +166,10 @@ private:
|
||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
|
||||
return mPointerControllers.valueFor(deviceId);
|
||||
}
|
||||
|
||||
virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) {
|
||||
mInputDevices = inputDevices;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -667,6 +672,7 @@ class FakeInputReaderContext : public InputReaderContext {
|
||||
sp<InputListenerInterface> mListener;
|
||||
int32_t mGlobalMetaState;
|
||||
bool mUpdateGlobalMetaStateWasCalled;
|
||||
int32_t mGeneration;
|
||||
|
||||
public:
|
||||
FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
|
||||
@@ -722,6 +728,10 @@ private:
|
||||
|
||||
virtual void requestTimeoutAtTime(nsecs_t when) {
|
||||
}
|
||||
|
||||
virtual int32_t bumpGeneration() {
|
||||
return ++mGeneration;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -887,7 +897,8 @@ public:
|
||||
InputDevice* newDevice(int32_t deviceId, const String8& name, uint32_t classes) {
|
||||
InputDeviceIdentifier identifier;
|
||||
identifier.name = name;
|
||||
return new InputDevice(&mContext, deviceId, identifier, classes);
|
||||
int32_t generation = deviceId + 1;
|
||||
return new InputDevice(&mContext, deviceId, generation, identifier, classes);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -1045,52 +1056,30 @@ TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigat
|
||||
ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
|
||||
}
|
||||
|
||||
TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsValid) {
|
||||
TEST_F(InputReaderTest, GetInputDevices) {
|
||||
ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
|
||||
INPUT_DEVICE_CLASS_KEYBOARD, NULL));
|
||||
ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("ignored"),
|
||||
0, NULL)); // no classes so device will be ignored
|
||||
|
||||
InputDeviceInfo info;
|
||||
status_t result = mReader->getInputDeviceInfo(1, &info);
|
||||
Vector<InputDeviceInfo> inputDevices;
|
||||
mReader->getInputDevices(inputDevices);
|
||||
|
||||
ASSERT_EQ(OK, result);
|
||||
ASSERT_EQ(1, info.getId());
|
||||
ASSERT_STREQ("keyboard", info.getName().string());
|
||||
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, info.getKeyboardType());
|
||||
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, info.getSources());
|
||||
ASSERT_EQ(size_t(0), info.getMotionRanges().size());
|
||||
}
|
||||
ASSERT_EQ(1U, inputDevices.size());
|
||||
ASSERT_EQ(1, inputDevices[0].getId());
|
||||
ASSERT_STREQ("keyboard", inputDevices[0].getName().string());
|
||||
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
|
||||
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
|
||||
ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
|
||||
|
||||
TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsInvalid) {
|
||||
InputDeviceInfo info;
|
||||
status_t result = mReader->getInputDeviceInfo(-1, &info);
|
||||
|
||||
ASSERT_EQ(NAME_NOT_FOUND, result);
|
||||
}
|
||||
|
||||
TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) {
|
||||
addDevice(1, String8("ignored"), 0, NULL); // no classes so device will be ignored
|
||||
|
||||
InputDeviceInfo info;
|
||||
status_t result = mReader->getInputDeviceInfo(1, &info);
|
||||
|
||||
ASSERT_EQ(NAME_NOT_FOUND, result);
|
||||
}
|
||||
|
||||
TEST_F(InputReaderTest, GetInputDeviceIds) {
|
||||
sp<FakePointerController> controller = new FakePointerController();
|
||||
mFakePolicy->setPointerController(2, controller);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
|
||||
INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY, NULL));
|
||||
ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("mouse"),
|
||||
INPUT_DEVICE_CLASS_CURSOR, NULL));
|
||||
|
||||
Vector<int32_t> ids;
|
||||
mReader->getInputDeviceIds(ids);
|
||||
|
||||
ASSERT_EQ(size_t(2), ids.size());
|
||||
ASSERT_EQ(1, ids[0]);
|
||||
ASSERT_EQ(2, ids[1]);
|
||||
// Should also have received a notification describing the new input devices.
|
||||
inputDevices = mFakePolicy->getInputDevices();
|
||||
ASSERT_EQ(1U, inputDevices.size());
|
||||
ASSERT_EQ(1, inputDevices[0].getId());
|
||||
ASSERT_STREQ("keyboard", inputDevices[0].getName().string());
|
||||
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
|
||||
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
|
||||
ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
|
||||
}
|
||||
|
||||
TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
|
||||
@@ -1243,6 +1232,7 @@ class InputDeviceTest : public testing::Test {
|
||||
protected:
|
||||
static const char* DEVICE_NAME;
|
||||
static const int32_t DEVICE_ID;
|
||||
static const int32_t DEVICE_GENERATION;
|
||||
static const uint32_t DEVICE_CLASSES;
|
||||
|
||||
sp<FakeEventHub> mFakeEventHub;
|
||||
@@ -1261,7 +1251,8 @@ protected:
|
||||
mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
|
||||
InputDeviceIdentifier identifier;
|
||||
identifier.name = DEVICE_NAME;
|
||||
mDevice = new InputDevice(mFakeContext, DEVICE_ID, identifier, DEVICE_CLASSES);
|
||||
mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
|
||||
identifier, DEVICE_CLASSES);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
@@ -1276,6 +1267,7 @@ protected:
|
||||
|
||||
const char* InputDeviceTest::DEVICE_NAME = "device";
|
||||
const int32_t InputDeviceTest::DEVICE_ID = 1;
|
||||
const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
|
||||
const uint32_t InputDeviceTest::DEVICE_CLASSES = INPUT_DEVICE_CLASS_KEYBOARD
|
||||
| INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_JOYSTICK;
|
||||
|
||||
@@ -1428,6 +1420,7 @@ class InputMapperTest : public testing::Test {
|
||||
protected:
|
||||
static const char* DEVICE_NAME;
|
||||
static const int32_t DEVICE_ID;
|
||||
static const int32_t DEVICE_GENERATION;
|
||||
static const uint32_t DEVICE_CLASSES;
|
||||
|
||||
sp<FakeEventHub> mFakeEventHub;
|
||||
@@ -1443,7 +1436,8 @@ protected:
|
||||
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
|
||||
InputDeviceIdentifier identifier;
|
||||
identifier.name = DEVICE_NAME;
|
||||
mDevice = new InputDevice(mFakeContext, DEVICE_ID, identifier, DEVICE_CLASSES);
|
||||
mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
|
||||
identifier, DEVICE_CLASSES);
|
||||
|
||||
mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
|
||||
}
|
||||
@@ -1522,6 +1516,7 @@ protected:
|
||||
|
||||
const char* InputMapperTest::DEVICE_NAME = "device";
|
||||
const int32_t InputMapperTest::DEVICE_ID = 1;
|
||||
const int32_t InputMapperTest::DEVICE_GENERATION = 2;
|
||||
const uint32_t InputMapperTest::DEVICE_CLASSES = 0; // not needed for current tests
|
||||
|
||||
|
||||
|
||||
@@ -34,18 +34,23 @@ import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.input.IInputManager;
|
||||
import android.hardware.input.IInputDevicesChangedListener;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.hardware.input.KeyboardLayout;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.MessageQueue;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.Xml;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputDevice;
|
||||
@@ -77,12 +82,33 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
|
||||
|
||||
private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
|
||||
|
||||
private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
|
||||
|
||||
// Pointer to native input manager service object.
|
||||
private final int mPtr;
|
||||
|
||||
private final Context mContext;
|
||||
private final Callbacks mCallbacks;
|
||||
private final Handler mHandler;
|
||||
private final InputManagerHandler mHandler;
|
||||
|
||||
// Used to simulate a persistent data store for keyboard layouts.
|
||||
// TODO: Replace with the real thing.
|
||||
private final HashMap<String, String> mFakeRegistry = new HashMap<String, String>();
|
||||
|
||||
// List of currently registered input devices changed listeners by process id.
|
||||
private Object mInputDevicesLock = new Object();
|
||||
private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
|
||||
private InputDevice[] mInputDevices = new InputDevice[0];
|
||||
private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
|
||||
new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
|
||||
private final ArrayList<InputDevicesChangedListenerRecord>
|
||||
mTempInputDevicesChangedListenersToNotify =
|
||||
new ArrayList<InputDevicesChangedListenerRecord>(); // handler thread only
|
||||
|
||||
// State for the currently installed input filter.
|
||||
final Object mInputFilterLock = new Object();
|
||||
InputFilter mInputFilter; // guarded by mInputFilterLock
|
||||
InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
|
||||
|
||||
private static native int nativeInit(InputManagerService service,
|
||||
Context context, MessageQueue messageQueue);
|
||||
@@ -111,9 +137,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
|
||||
private static native void nativeSetSystemUiVisibility(int ptr, int visibility);
|
||||
private static native void nativeSetFocusedApplication(int ptr,
|
||||
InputApplicationHandle application);
|
||||
private static native InputDevice nativeGetInputDevice(int ptr, int deviceId);
|
||||
private static native void nativeGetInputConfiguration(int ptr, Configuration configuration);
|
||||
private static native int[] nativeGetInputDeviceIds(int ptr);
|
||||
private static native boolean nativeTransferTouchFocus(int ptr,
|
||||
InputChannel fromChannel, InputChannel toChannel);
|
||||
private static native void nativeSetPointerSpeed(int ptr, int speed);
|
||||
@@ -145,19 +169,10 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
|
||||
/** The key is down but is a virtual key press that is being emulated by the system. */
|
||||
public static final int KEY_STATE_VIRTUAL = 2;
|
||||
|
||||
// Used to simulate a persistent data store for keyboard layouts.
|
||||
// TODO: Replace with the real thing.
|
||||
private final HashMap<String, String> mFakeRegistry = new HashMap<String, String>();
|
||||
|
||||
// State for the currently installed input filter.
|
||||
final Object mInputFilterLock = new Object();
|
||||
InputFilter mInputFilter;
|
||||
InputFilterHost mInputFilterHost;
|
||||
|
||||
public InputManagerService(Context context, Callbacks callbacks) {
|
||||
this.mContext = context;
|
||||
this.mCallbacks = callbacks;
|
||||
this.mHandler = new Handler();
|
||||
this.mHandler = new InputManagerHandler();
|
||||
|
||||
Slog.i(TAG, "Initializing input manager");
|
||||
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
|
||||
@@ -396,16 +411,98 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
|
||||
*/
|
||||
@Override // Binder call
|
||||
public InputDevice getInputDevice(int deviceId) {
|
||||
return nativeGetInputDevice(mPtr, deviceId);
|
||||
synchronized (mInputDevicesLock) {
|
||||
final int count = mInputDevices.length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
final InputDevice inputDevice = mInputDevices[i];
|
||||
if (inputDevice.getId() == deviceId) {
|
||||
return inputDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the ids of all input devices in the system.
|
||||
* @return The input device ids.
|
||||
*/
|
||||
@Override // Binder call
|
||||
public int[] getInputDeviceIds() {
|
||||
return nativeGetInputDeviceIds(mPtr);
|
||||
synchronized (mInputDevicesLock) {
|
||||
final int count = mInputDevices.length;
|
||||
int[] ids = new int[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
ids[i] = mInputDevices[i].getId();
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("listener must not be null");
|
||||
}
|
||||
|
||||
synchronized (mInputDevicesLock) {
|
||||
int callingPid = Binder.getCallingPid();
|
||||
if (mInputDevicesChangedListeners.get(callingPid) != null) {
|
||||
throw new SecurityException("The calling process has already "
|
||||
+ "registered an InputDevicesChangedListener.");
|
||||
}
|
||||
|
||||
InputDevicesChangedListenerRecord record =
|
||||
new InputDevicesChangedListenerRecord(callingPid, listener);
|
||||
try {
|
||||
IBinder binder = listener.asBinder();
|
||||
binder.linkToDeath(record, 0);
|
||||
} catch (RemoteException ex) {
|
||||
// give up
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
mInputDevicesChangedListeners.put(callingPid, record);
|
||||
}
|
||||
}
|
||||
|
||||
private void onInputDevicesChangedListenerDied(int pid) {
|
||||
synchronized (mInputDevicesLock) {
|
||||
mInputDevicesChangedListeners.remove(pid);
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called on handler.
|
||||
private void deliverInputDevicesChanged() {
|
||||
mTempInputDevicesChangedListenersToNotify.clear();
|
||||
|
||||
final int numListeners;
|
||||
final int[] deviceIdAndGeneration;
|
||||
synchronized (mInputDevicesLock) {
|
||||
if (!mInputDevicesChangedPending) {
|
||||
return;
|
||||
}
|
||||
mInputDevicesChangedPending = false;
|
||||
|
||||
numListeners = mInputDevicesChangedListeners.size();
|
||||
for (int i = 0; i < numListeners; i++) {
|
||||
mTempInputDevicesChangedListenersToNotify.add(
|
||||
mInputDevicesChangedListeners.valueAt(i));
|
||||
}
|
||||
|
||||
final int numDevices = mInputDevices.length;
|
||||
deviceIdAndGeneration = new int[numDevices * 2];
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
final InputDevice inputDevice = mInputDevices[i];
|
||||
deviceIdAndGeneration[i * 2] = inputDevice.getId();
|
||||
deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numListeners; i++) {
|
||||
mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
|
||||
deviceIdAndGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -740,6 +837,18 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
|
||||
mCallbacks.notifyConfigurationChanged();
|
||||
}
|
||||
|
||||
// Native callback.
|
||||
private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
|
||||
synchronized (mInputDevicesLock) {
|
||||
mInputDevices = inputDevices;
|
||||
|
||||
if (!mInputDevicesChangedPending) {
|
||||
mInputDevicesChangedPending = true;
|
||||
mHandler.sendEmptyMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Native callback.
|
||||
private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
|
||||
mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
|
||||
@@ -905,6 +1014,20 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
|
||||
public int getPointerLayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private handler for the input manager.
|
||||
*/
|
||||
private final class InputManagerHandler extends Handler {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_DELIVER_INPUT_DEVICES_CHANGED:
|
||||
deliverInputDevicesChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hosting interface for input filters to call back into the input manager.
|
||||
*/
|
||||
@@ -957,4 +1080,32 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private final class InputDevicesChangedListenerRecord implements DeathRecipient {
|
||||
private final int mPid;
|
||||
private final IInputDevicesChangedListener mListener;
|
||||
|
||||
public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
|
||||
mPid = pid;
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
|
||||
}
|
||||
onInputDevicesChangedListenerDied(mPid);
|
||||
}
|
||||
|
||||
public void notifyInputDevicesChanged(int[] info) {
|
||||
try {
|
||||
mListener.onInputDevicesChanged(info);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.w(TAG, "Failed to notify process "
|
||||
+ mPid + " that input devices changed, assuming it died.", ex);
|
||||
binderDied();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ static const float POINTER_SPEED_EXPONENT = 1.0f / 4;
|
||||
|
||||
static struct {
|
||||
jmethodID notifyConfigurationChanged;
|
||||
jmethodID notifyInputDevicesChanged;
|
||||
jmethodID notifyLidSwitchChanged;
|
||||
jmethodID notifyInputChannelBroken;
|
||||
jmethodID notifyANR;
|
||||
@@ -80,6 +81,10 @@ static struct {
|
||||
jmethodID getPointerIcon;
|
||||
} gServiceClassInfo;
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
} gInputDeviceClassInfo;
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
} gKeyEventClassInfo;
|
||||
@@ -179,6 +184,7 @@ public:
|
||||
|
||||
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
|
||||
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
|
||||
virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
|
||||
|
||||
/* --- InputDispatcherPolicyInterface implementation --- */
|
||||
|
||||
@@ -486,6 +492,36 @@ void NativeInputManager::ensureSpriteControllerLocked() {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
size_t count = inputDevices.size();
|
||||
jobjectArray inputDevicesObjArray = env->NewObjectArray(
|
||||
count, gInputDeviceClassInfo.clazz, NULL);
|
||||
if (inputDevicesObjArray) {
|
||||
bool error = false;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices.itemAt(i));
|
||||
if (!inputDeviceObj) {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
env->SetObjectArrayElement(inputDevicesObjArray, i, inputDeviceObj);
|
||||
env->DeleteLocalRef(inputDeviceObj);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputDevicesChanged,
|
||||
inputDevicesObjArray);
|
||||
}
|
||||
|
||||
env->DeleteLocalRef(inputDevicesObjArray);
|
||||
}
|
||||
|
||||
checkAndClearExceptionFromCallback(env, "notifyInputDevicesChanged");
|
||||
}
|
||||
|
||||
void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
|
||||
int32_t switchValue, uint32_t policyFlags) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
@@ -1147,36 +1183,6 @@ static void nativeSetSystemUiVisibility(JNIEnv* env,
|
||||
im->setSystemUiVisibility(visibility);
|
||||
}
|
||||
|
||||
static jobject nativeGetInputDevice(JNIEnv* env,
|
||||
jclass clazz, jint ptr, jint deviceId) {
|
||||
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
||||
|
||||
InputDeviceInfo deviceInfo;
|
||||
status_t status = im->getInputManager()->getReader()->getInputDeviceInfo(
|
||||
deviceId, & deviceInfo);
|
||||
if (status) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return android_view_InputDevice_create(env, deviceInfo);
|
||||
}
|
||||
|
||||
static jintArray nativeGetInputDeviceIds(JNIEnv* env,
|
||||
jclass clazz, jint ptr) {
|
||||
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
||||
|
||||
Vector<int> deviceIds;
|
||||
im->getInputManager()->getReader()->getInputDeviceIds(deviceIds);
|
||||
|
||||
jintArray deviceIdsObj = env->NewIntArray(deviceIds.size());
|
||||
if (! deviceIdsObj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
env->SetIntArrayRegion(deviceIdsObj, 0, deviceIds.size(), deviceIds.array());
|
||||
return deviceIdsObj;
|
||||
}
|
||||
|
||||
static void nativeGetInputConfiguration(JNIEnv* env,
|
||||
jclass clazz, jint ptr, jobject configObj) {
|
||||
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
||||
@@ -1273,10 +1279,6 @@ static JNINativeMethod gInputManagerMethods[] = {
|
||||
(void*) nativeSetInputDispatchMode },
|
||||
{ "nativeSetSystemUiVisibility", "(II)V",
|
||||
(void*) nativeSetSystemUiVisibility },
|
||||
{ "nativeGetInputDevice", "(II)Landroid/view/InputDevice;",
|
||||
(void*) nativeGetInputDevice },
|
||||
{ "nativeGetInputDeviceIds", "(I)[I",
|
||||
(void*) nativeGetInputDeviceIds },
|
||||
{ "nativeGetInputConfiguration", "(ILandroid/content/res/Configuration;)V",
|
||||
(void*) nativeGetInputConfiguration },
|
||||
{ "nativeTransferTouchFocus", "(ILandroid/view/InputChannel;Landroid/view/InputChannel;)Z",
|
||||
@@ -1316,6 +1318,9 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz,
|
||||
"notifyConfigurationChanged", "(J)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
|
||||
"notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyLidSwitchChanged, clazz,
|
||||
"notifyLidSwitchChanged", "(JZ)V");
|
||||
|
||||
@@ -1377,6 +1382,11 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
|
||||
"getPointerIcon", "()Landroid/view/PointerIcon;");
|
||||
|
||||
// InputDevice
|
||||
|
||||
FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
|
||||
gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
|
||||
|
||||
// KeyEvent
|
||||
|
||||
FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
|
||||
|
||||
Reference in New Issue
Block a user