Merge "Add a preference panel for mouse speed." into honeycomb-mr2

This commit is contained in:
Jeff Brown
2011-06-02 17:26:05 -07:00
committed by Android (Google) Code Review
15 changed files with 232 additions and 35 deletions

View File

@ -1024,6 +1024,17 @@
visibility="public"
>
</field>
<field name="SET_POINTER_SPEED"
type="java.lang.String"
transient="false"
volatile="false"
value="&quot;android.permission.SET_POINTER_SPEED&quot;"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SET_PREFERRED_APPLICATIONS"
type="java.lang.String"
transient="false"

View File

@ -1790,6 +1790,16 @@ public final class Settings {
*/
public static final String SIP_ASK_ME_EACH_TIME = "SIP_ASK_ME_EACH_TIME";
/**
* Pointer speed setting.
* This is an integer value in a range between -7 and +7, so there are 15 possible values.
* -7 = slowest
* 0 = default speed
* +7 = fastest
* @hide
*/
public static final String POINTER_SPEED = "pointer_speed";
/**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
@ -1854,6 +1864,7 @@ public final class Settings {
USE_PTP_INTERFACE,
SIP_CALL_OPTIONS,
SIP_RECEIVE_CALLS,
POINTER_SPEED,
};
// Settings moved to Settings.Secure

View File

@ -205,4 +205,9 @@ interface IWindowManager
* Called by the status bar to notify Views of changes to System UI visiblity.
*/
void statusBarVisibilityChanged(int visibility);
/**
* Called by the settings application to temporarily set the pointer speed.
*/
void setPointerSpeed(int speed);
}

View File

@ -1071,6 +1071,13 @@
android:description="@string/permdesc_setOrientation"
android:protectionLevel="signature" />
<!-- Allows low-level access to setting the pointer speed.
Not for use by normal applications. -->
<permission android:name="android.permission.SET_POINTER_SPEED"
android:label="@string/permlab_setPointerSpeed"
android:description="@string/permdesc_setPointerSpeed"
android:protectionLevel="signature" />
<!-- Allows an application to install packages. -->
<permission android:name="android.permission.INSTALL_PACKAGES"
android:label="@string/permlab_installPackages"

View File

@ -699,6 +699,13 @@
the rotation of the screen at any time. Should never be needed for
normal applications.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
<string name="permlab_setPointerSpeed">change pointer speed</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
<string name="permdesc_setPointerSpeed">Allows an application to change
the mouse or trackpad pointer speed at any time. Should never be needed for
normal applications.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_signalPersistentProcesses">send Linux signals to applications</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->

View File

@ -125,4 +125,7 @@
<!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
<integer name="def_long_press_timeout_millis">500</integer>
<!-- Default for Settings.System.POINTER_SPEED -->
<integer name="def_pointer_speed">0</integer>
</resources>

View File

@ -1214,6 +1214,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
R.bool.def_notifications_use_ring_volume);
loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
R.integer.def_pointer_speed);
} finally {
if (stmt != null) stmt.close();
}

View File

@ -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");

View File

@ -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];

View File

@ -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");

View File

@ -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,

View File

@ -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() {
}
};

View File

@ -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) {

View File

@ -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();

View File

@ -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 },
};