summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@android.com>2011-06-02 01:26:32 -0700
committerJeff Brown <jeffbrown@android.com>2011-06-02 15:39:21 -0700
commit1a84fd1fb7a51f3fe4f8865e1cdd09f3490f696c (patch)
treecf9491aedb10c8355e62ae8384db0e9f005beb1c /services
parent19c97d46fb57f87ff45d9e6ea7122b4eb21ede8c (diff)
downloadframeworks_base-1a84fd1fb7a51f3fe4f8865e1cdd09f3490f696c.zip
frameworks_base-1a84fd1fb7a51f3fe4f8865e1cdd09f3490f696c.tar.gz
frameworks_base-1a84fd1fb7a51f3fe4f8865e1cdd09f3490f696c.tar.bz2
Add a preference panel for mouse speed.
Bug: 4124987 Change-Id: I3ce175d268a1d043cf5878481261b1049a15a149
Diffstat (limited to 'services')
-rw-r--r--services/input/EventHub.cpp53
-rw-r--r--services/input/EventHub.h17
-rw-r--r--services/input/InputReader.cpp26
-rw-r--r--services/input/InputReader.h17
-rw-r--r--services/input/tests/InputReader_test.cpp7
-rw-r--r--services/java/com/android/server/wm/InputManager.java48
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java13
-rw-r--r--services/jni/com_android_server_InputManager.cpp39
8 files changed, 185 insertions, 35 deletions
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index d80abe8..f748e7c 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -33,6 +33,7 @@
#include <hardware_legacy/power.h>
+#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/Timers.h>
@@ -127,6 +128,7 @@ EventHub::EventHub(void) :
mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
mOpeningDevices(0), mClosingDevices(0),
mOpened(false), mNeedToSendFinishedDeviceScan(false),
+ mNeedToReopenDevices(0), mNeedToScanDevices(false),
mInputFdIndex(1) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
@@ -380,12 +382,10 @@ status_t EventHub::mapAxis(int32_t deviceId, int scancode, AxisInfo* outAxisInfo
return NAME_NOT_FOUND;
}
-void EventHub::addExcludedDevice(const char* deviceName)
-{
+void EventHub::setExcludedDevices(const Vector<String8>& devices) {
AutoMutex _l(mLock);
- String8 name(deviceName);
- mExcludedDevices.push_back(name);
+ mExcludedDevices = devices;
}
bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
@@ -453,9 +453,11 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
assert(bufferSize >= 1);
if (!mOpened) {
+ android_atomic_acquire_store(0, &mNeedToReopenDevices);
+
mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
mOpened = true;
- mNeedToSendFinishedDeviceScan = true;
+ mNeedToScanDevices = true;
}
struct input_event readBuffer[bufferSize];
@@ -465,6 +467,20 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ // Reopen input devices if needed.
+ if (android_atomic_acquire_load(&mNeedToReopenDevices)) {
+ android_atomic_acquire_store(0, &mNeedToReopenDevices);
+
+ LOGI("Reopening all input devices due to a configuration change.");
+
+ AutoMutex _l(mLock);
+ while (mDevices.size() > 1) {
+ closeDeviceAtIndexLocked(mDevices.size() - 1);
+ }
+ mNeedToScanDevices = true;
+ break; // return to the caller before we actually rescan
+ }
+
// Report any devices that had last been added/removed.
while (mClosingDevices) {
Device* device = mClosingDevices;
@@ -482,6 +498,12 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
}
}
+ if (mNeedToScanDevices) {
+ mNeedToScanDevices = false;
+ scanDevices();
+ mNeedToSendFinishedDeviceScan = true;
+ }
+
while (mOpeningDevices != NULL) {
Device* device = mOpeningDevices;
LOGV("Reporting device opened: id=%d, name=%s\n",
@@ -683,13 +705,14 @@ bool EventHub::openPlatformInput(void) {
pollfd.revents = 0;
mFds.push(pollfd);
mDevices.push(NULL);
+ return true;
+}
- res = scanDir(DEVICE_PATH);
+void EventHub::scanDevices() {
+ int res = scanDir(DEVICE_PATH);
if(res < 0) {
LOGE("scan dir failed for %s\n", DEVICE_PATH);
}
-
- return true;
}
// ----------------------------------------------------------------------------
@@ -742,12 +765,10 @@ int EventHub::openDevice(const char *devicePath) {
}
// Check to see if the device is on our excluded list
- List<String8>::iterator iter = mExcludedDevices.begin();
- List<String8>::iterator end = mExcludedDevices.end();
- for ( ; iter != end; iter++) {
- const char* test = *iter;
- if (identifier.name == test) {
- LOGI("ignoring event id %s driver %s\n", devicePath, test);
+ for (size_t i = 0; i < mExcludedDevices.size(); i++) {
+ const String8& item = mExcludedDevices.itemAt(i);
+ if (identifier.name == item) {
+ LOGI("ignoring event id %s driver %s\n", devicePath, item.string());
close(fd);
return -1;
}
@@ -1210,6 +1231,10 @@ int EventHub::scanDir(const char *dirname)
return 0;
}
+void EventHub::reopenDevices() {
+ android_atomic_release_store(1, &mNeedToReopenDevices);
+}
+
void EventHub::dump(String8& dump) {
dump.append("Event Hub State:\n");
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 4d26a95..853a0bd 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -178,9 +178,9 @@ public:
virtual status_t mapAxis(int32_t deviceId, int scancode,
AxisInfo* outAxisInfo) const = 0;
- // exclude a particular device from opening
- // this can be used to ignore input devices for sensors
- virtual void addExcludedDevice(const char* deviceName) = 0;
+ // Sets devices that are excluded from opening.
+ // This can be used to ignore input devices for sensors.
+ virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
/*
* Wait for events to become available and returns them.
@@ -215,6 +215,8 @@ public:
virtual void getVirtualKeyDefinitions(int32_t deviceId,
Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
+ virtual void reopenDevices() = 0;
+
virtual void dump(String8& dump) = 0;
};
@@ -242,7 +244,7 @@ public:
virtual status_t mapAxis(int32_t deviceId, int scancode,
AxisInfo* outAxisInfo) const;
- virtual void addExcludedDevice(const char* deviceName);
+ virtual void setExcludedDevices(const Vector<String8>& devices);
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
@@ -259,6 +261,8 @@ public:
virtual void getVirtualKeyDefinitions(int32_t deviceId,
Vector<VirtualKeyDefinition>& outVirtualKeys) const;
+ virtual void reopenDevices();
+
virtual void dump(String8& dump);
protected:
@@ -271,6 +275,7 @@ private:
int closeDevice(const char *devicePath);
int closeDeviceAtIndexLocked(int index);
int scanDir(const char *dirname);
+ void scanDevices();
int readNotify(int nfd);
status_t mError;
@@ -333,7 +338,9 @@ private:
bool mOpened;
bool mNeedToSendFinishedDeviceScan;
- List<String8> mExcludedDevices;
+ volatile int32_t mNeedToReopenDevices; // must be modified atomically
+ bool mNeedToScanDevices;
+ Vector<String8> mExcludedDevices;
// device ids that report particular switches.
int32_t mSwitches[SW_MAX + 1];
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 724af39..a22ec1c 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -38,6 +38,7 @@
#include "InputReader.h"
+#include <cutils/atomic.h>
#include <cutils/log.h>
#include <ui/Keyboard.h>
#include <ui/VirtualKeyMap.h>
@@ -219,10 +220,9 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputDispatcherInterface>& dispatcher) :
mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
- mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) {
- mPolicy->getReaderConfiguration(&mConfig);
-
- configureExcludedDevices();
+ mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
+ mRefreshConfiguration(0) {
+ configure(true /*firstTime*/);
updateGlobalMetaState();
updateInputConfiguration();
}
@@ -234,6 +234,11 @@ InputReader::~InputReader() {
}
void InputReader::loopOnce() {
+ if (android_atomic_acquire_load(&mRefreshConfiguration)) {
+ android_atomic_release_store(0, &mRefreshConfiguration);
+ configure(false /*firstTime*/);
+ }
+
int32_t timeoutMillis = -1;
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -454,9 +459,12 @@ void InputReader::handleConfigurationChanged(nsecs_t when) {
mDispatcher->notifyConfigurationChanged(when);
}
-void InputReader::configureExcludedDevices() {
- for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
- mEventHub->addExcludedDevice(mConfig.excludedDeviceNames[i]);
+void InputReader::configure(bool firstTime) {
+ mPolicy->getReaderConfiguration(&mConfig);
+ mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
+
+ if (!firstTime) {
+ mEventHub->reopenDevices();
}
}
@@ -677,6 +685,10 @@ bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, s
} // release device registy reader lock
}
+void InputReader::refreshConfiguration() {
+ android_atomic_release_store(1, &mRefreshConfiguration);
+}
+
void InputReader::dump(String8& dump) {
mEventHub->dump(dump);
dump.append("\n");
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index f1b89a2..5028b60 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -145,7 +145,7 @@ struct InputReaderConfiguration {
pointerGestureMultitouchMinSpeed(150.0f), // 150 pixels per second
pointerGestureSwipeTransitionAngleCosine(0.5f), // cosine of 45degrees
pointerGestureSwipeMaxWidthRatio(0.333f),
- pointerGestureMovementSpeedRatio(0.5f),
+ pointerGestureMovementSpeedRatio(0.3f),
pointerGestureZoomSpeedRatio(0.3f) { }
};
@@ -234,6 +234,9 @@ public:
/* Determine whether physical keys exist for the given framework-domain key codes. */
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
+
+ /* Reopens and reconfigures all input devices. */
+ virtual void refreshConfiguration() = 0;
};
@@ -298,6 +301,8 @@ public:
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
+ virtual void refreshConfiguration();
+
protected:
// These methods are protected virtual so they can be overridden and instrumented
// by test cases.
@@ -339,18 +344,17 @@ private:
void timeoutExpired(nsecs_t when);
void handleConfigurationChanged(nsecs_t when);
- void configureExcludedDevices();
// state management for all devices
Mutex mStateLock;
- int32_t mGlobalMetaState;
+ int32_t mGlobalMetaState; // guarded by mStateLock
virtual void updateGlobalMetaState();
virtual int32_t getGlobalMetaState();
virtual void fadePointer();
- InputConfiguration mInputConfiguration;
+ InputConfiguration mInputConfiguration; // guarded by mStateLock
void updateInputConfiguration();
nsecs_t mDisableVirtualKeysTimeout; // only accessed by reader thread
@@ -358,9 +362,12 @@ private:
virtual bool shouldDropVirtualKey(nsecs_t now,
InputDevice* device, int32_t keyCode, int32_t scanCode);
- nsecs_t mNextTimeout; // only accessed by reader thread
+ nsecs_t mNextTimeout; // only accessed by reader thread, not guarded
virtual void requestTimeoutAtTime(nsecs_t when);
+ volatile int32_t mRefreshConfiguration; // atomic
+ void configure(bool firstTime);
+
// state queries
typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index b5f603a..e85ae1f 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -617,8 +617,8 @@ private:
return NAME_NOT_FOUND;
}
- virtual void addExcludedDevice(const char* deviceName) {
- mExcludedDevices.add(String8(deviceName));
+ virtual void setExcludedDevices(const Vector<String8>& devices) {
+ mExcludedDevices = devices;
}
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
@@ -716,6 +716,9 @@ private:
virtual void dump(String8& dump) {
}
+
+ virtual void reopenDevices() {
+ }
};
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index ab781f4..4eda684 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -23,10 +23,14 @@ import org.xmlpull.v1.XmlPullParser;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.database.ContentObserver;
import android.os.Environment;
+import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.SystemProperties;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.util.Xml;
import android.view.InputChannel;
@@ -56,7 +60,7 @@ public class InputManager {
private final Callbacks mCallbacks;
private final Context mContext;
private final WindowManagerService mWindowManagerService;
-
+
private static native void nativeInit(Context context,
Callbacks callbacks, MessageQueue messageQueue);
private static native void nativeStart();
@@ -85,6 +89,7 @@ public class InputManager {
private static native int[] nativeGetInputDeviceIds();
private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
InputChannel toChannel);
+ private static native void nativeSetPointerSpeed(int speed);
private static native String nativeDump();
// Input event injection constants defined in InputDispatcher.h.
@@ -123,10 +128,13 @@ public class InputManager {
Slog.i(TAG, "Initializing input manager");
nativeInit(mContext, mCallbacks, looper.getQueue());
}
-
+
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart();
+
+ registerPointerSpeedSettingObserver();
+ updatePointerSpeedFromSettings();
}
public void setDisplaySize(int displayId, int width, int height) {
@@ -359,6 +367,42 @@ public class InputManager {
return nativeTransferTouchFocus(fromChannel, toChannel);
}
+ /**
+ * Set the pointer speed.
+ * @param speed The pointer speed as a value between -7 (slowest) and 7 (fastest)
+ * where 0 is the default speed.
+ */
+ public void setPointerSpeed(int speed) {
+ speed = Math.min(Math.max(speed, -7), 7);
+ nativeSetPointerSpeed(speed);
+ }
+
+ public void updatePointerSpeedFromSettings() {
+ int speed = getPointerSpeedSetting(0);
+ setPointerSpeed(speed);
+ }
+
+ private void registerPointerSpeedSettingObserver() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
+ new ContentObserver(mWindowManagerService.mH) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updatePointerSpeedFromSettings();
+ }
+ });
+ }
+
+ private int getPointerSpeedSetting(int defaultValue) {
+ int speed = defaultValue;
+ try {
+ speed = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.POINTER_SPEED);
+ } catch (SettingNotFoundException snfe) {
+ }
+ return speed;
+ }
+
public void dump(PrintWriter pw) {
String dumpStr = nativeDump();
if (dumpStr != null) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7760897..4ff6b06 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5947,6 +5947,19 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ /**
+ * Temporarily set the pointer speed. Does not save the new setting.
+ * Used by the settings application.
+ */
+ public void setPointerSpeed(int speed) {
+ if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
+ "setPointerSpeed()")) {
+ throw new SecurityException("Requires SET_POINTER_SPEED permission");
+ }
+
+ mInputManager.setPointerSpeed(speed);
+ }
+
private WindowState getFocusedWindow() {
synchronized (mWindowMap) {
return getFocusedWindowLocked();
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index fef41c9..2704647 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -53,6 +53,11 @@
namespace android {
+// The exponent used to calculate the pointer speed scaling factor.
+// The scaling factor is calculated as 2 ^ (speed * exponent),
+// where the speed ranges from -7 to + 7 and is supplied by the user.
+static const float POINTER_SPEED_EXPONENT = 1.0f / 3;
+
static struct {
jclass clazz;
@@ -179,6 +184,7 @@ public:
void setFocusedApplication(JNIEnv* env, jobject applicationObj);
void setInputDispatchMode(bool enabled, bool frozen);
void setSystemUiVisibility(int32_t visibility);
+ void setPointerSpeed(int32_t speed);
/* --- InputReaderPolicyInterface implementation --- */
@@ -227,6 +233,9 @@ private:
// System UI visibility.
int32_t systemUiVisibility;
+ // Pointer speed.
+ int32_t pointerSpeed;
+
// Sprite controller singleton, created on first use.
sp<SpriteController> spriteController;
@@ -266,6 +275,7 @@ NativeInputManager::NativeInputManager(jobject contextObj,
mLocked.displayOrientation = ROTATION_0;
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
+ mLocked.pointerSpeed = 0;
}
sp<EventHub> eventHub = new EventHub();
@@ -429,6 +439,13 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
if (!checkAndClearExceptionFromCallback(env, "getTouchSlop")) {
outConfig->pointerGestureTapSlop = touchSlop;
}
+
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed
+ * POINTER_SPEED_EXPONENT);
+ } // release lock
}
sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32_t deviceId) {
@@ -634,6 +651,17 @@ void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerControlle
: PointerController::INACTIVITY_TIMEOUT_NORMAL);
}
+void NativeInputManager::setPointerSpeed(int32_t speed) {
+ AutoMutex _l(mLock);
+
+ if (mLocked.pointerSpeed != speed) {
+ LOGI("Setting pointer speed to %d.", speed);
+ mLocked.pointerSpeed = speed;
+
+ mInputManager->getReader()->refreshConfiguration();
+ }
+}
+
bool NativeInputManager::isScreenOn() {
return android_server_PowerManagerService_isScreenOn();
}
@@ -1180,6 +1208,15 @@ static jboolean android_server_InputManager_nativeTransferTouchFocus(JNIEnv* env
transferTouchFocus(fromChannel, toChannel);
}
+static void android_server_InputManager_nativeSetPointerSpeed(JNIEnv* env,
+ jclass clazz, jint speed) {
+ if (checkInputManagerUnitialized(env)) {
+ return;
+ }
+
+ gNativeInputManager->setPointerSpeed(speed);
+}
+
static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
if (checkInputManagerUnitialized(env)) {
return NULL;
@@ -1234,6 +1271,8 @@ static JNINativeMethod gInputManagerMethods[] = {
(void*) android_server_InputManager_nativeGetInputConfiguration },
{ "nativeTransferTouchFocus", "(Landroid/view/InputChannel;Landroid/view/InputChannel;)Z",
(void*) android_server_InputManager_nativeTransferTouchFocus },
+ { "nativeSetPointerSpeed", "(I)V",
+ (void*) android_server_InputManager_nativeSetPointerSpeed },
{ "nativeDump", "()Ljava/lang/String;",
(void*) android_server_InputManager_nativeDump },
};