Android系统中长按键部分:Linux驱动只是在起初按下时上报个down事件,在抬起后再报个up事件;其中,不会在有按键上报。对长按键的处理是在Android上层的InputDispatcher中,具体实现还未研究;如下是repeat的时间间隔设定地方。有空在对具体机制做分析。
Android 中 repeat 的时间间隔是由长按分发超时参数 keyRepeatTimeout 和 KeyRepeatDelay 控制的,下面结合源码来看具体实现及修改位置。
注:代码基于Android P(9.0)版本
frameworks\native\services\inputflinger\InputDispatcher.cpp
InputDispatcher构造方法,getDispatcherConfiguration
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
mPolicy(policy),
mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(NULL),
mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
mLooper = new Looper(false);
mKeyRepeatState.lastKeyEntry = NULL;
policy->getDispatcherConfiguration(&mConfig);
}
frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp
policy是NativeInputManager,在com_android_server_input_InputManagerService.cpp里面。mServiceObj是Java层的InputManagerService,getKeyRepeatTimeout和getKeyRepeatDelay已经自注释了。
void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
jint keyRepeatTimeout = env->CallIntMethod(mServiceObj,
gServiceClassInfo.getKeyRepeatTimeout);
if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
}
jint keyRepeatDelay = env->CallIntMethod(mServiceObj,
gServiceClassInfo.getKeyRepeatDelay);
if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
}
}
frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
InputManagerService中,通过ViewConfiguration去取值
// Native callback.
private int getKeyRepeatTimeout() {
return ViewConfiguration.getKeyRepeatTimeout();
}
// Native callback.
private int getKeyRepeatDelay() {
return ViewConfiguration.getKeyRepeatDelay();
}
frameworks\base\core\java\android\view\ViewConfiguration.java
KeyRepeatTimeout是在Settings数据库里面存储的值,默认的DEFAULT_LONG_PRESS_TIMEOUT是500ms。
/**
* @return the time before the first key repeat in milliseconds.
*/
public static int getKeyRepeatTimeout() {
return getLongPressTimeout();
}
/**
* @return the time between successive key repeats in milliseconds.
*/
public static int getKeyRepeatDelay() {
return KEY_REPEAT_DELAY;
}
/**
* Defines the default duration in milliseconds before a press turns into
* a long press
*/
private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500;
/**
* Defines the time between successive key repeats in milliseconds.
*/
private static final int KEY_REPEAT_DELAY = 50;
/**
* @return the duration in milliseconds before a press turns into
* a long press
*/
public static int getLongPressTimeout() {
return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT,
DEFAULT_LONG_PRESS_TIMEOUT);
}
Settings数据库可以参考Android system — settings数据库
- 在Settings数据库SettingsProvider初始化的时候DatabaseUtils的loadSecureSettings会从defaults.xml中读取默认值进行赋值。
- defaults.xml,改的越小就越快
- 原生的数据库字段可能维护有问题,目前使用的DEFAULT_LONG_PRESS_TIMEOUT和KEY_REPEAT_DELAY,修改这两个默认值可直接生效
loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
R.integer.def_long_press_timeout_millis);
<!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
<integer name="def_long_press_timeout_millis">200</integer>
<setting id="8" name="long_press_timeout" value="400" package="android" defaultValue="400" defaultSysSet="true" />