Merge "Fix an event injection bug when the policy is bypassed." into gingerbread
This commit is contained in:
@@ -77,6 +77,7 @@ public interface WindowManagerPolicy {
|
||||
public final static int FLAG_VIRTUAL = 0x00000100;
|
||||
|
||||
public final static int FLAG_INJECTED = 0x01000000;
|
||||
public final static int FLAG_TRUSTED = 0x02000000;
|
||||
|
||||
public final static int FLAG_WOKE_HERE = 0x10000000;
|
||||
public final static int FLAG_BRIGHT_HERE = 0x20000000;
|
||||
|
||||
@@ -95,6 +95,10 @@ enum {
|
||||
// Indicates that the input event was injected.
|
||||
POLICY_FLAG_INJECTED = 0x01000000,
|
||||
|
||||
// Indicates that the input event is from a trusted source such as a directly attached
|
||||
// input device or an application with system-wide event injection permission.
|
||||
POLICY_FLAG_TRUSTED = 0x02000000,
|
||||
|
||||
/* These flags are set by the input reader policy as it intercepts each event. */
|
||||
|
||||
// Indicates that the screen was off when the event was received and the event
|
||||
|
||||
@@ -913,7 +913,6 @@ private:
|
||||
void drainInboundQueueLocked();
|
||||
void releasePendingEventLocked();
|
||||
void releaseInboundEventLocked(EventEntry* entry);
|
||||
bool isEventFromTrustedSourceLocked(EventEntry* entry);
|
||||
|
||||
// Dispatch state.
|
||||
bool mDispatchEnabled;
|
||||
@@ -960,10 +959,10 @@ private:
|
||||
nsecs_t currentTime, ConfigurationChangedEntry* entry);
|
||||
bool dispatchKeyLocked(
|
||||
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
|
||||
bool dropEvent, nsecs_t* nextWakeupTime);
|
||||
DropReason* dropReason, nsecs_t* nextWakeupTime);
|
||||
bool dispatchMotionLocked(
|
||||
nsecs_t currentTime, MotionEntry* entry,
|
||||
bool dropEvent, nsecs_t* nextWakeupTime);
|
||||
DropReason* dropReason, nsecs_t* nextWakeupTime);
|
||||
void dispatchEventToCurrentInputTargetsLocked(
|
||||
nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
||||
}
|
||||
}
|
||||
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
|
||||
dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
|
||||
&dropReason, nextWakeupTime);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
||||
dropReason = DROP_REASON_APP_SWITCH;
|
||||
}
|
||||
done = dispatchMotionLocked(currentTime, typedEntry,
|
||||
dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
|
||||
&dropReason, nextWakeupTime);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -431,6 +431,9 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR
|
||||
const char* reason;
|
||||
switch (dropReason) {
|
||||
case DROP_REASON_POLICY:
|
||||
#if DEBUG_INBOUND_EVENT_DETAILS
|
||||
LOGD("Dropped event because policy requested that it not be delivered to the application.");
|
||||
#endif
|
||||
reason = "inbound event was dropped because the policy requested that it not be "
|
||||
"delivered to the application";
|
||||
break;
|
||||
@@ -473,7 +476,7 @@ bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
|
||||
bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
|
||||
return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
|
||||
&& isAppSwitchKeyCode(keyEntry->keyCode)
|
||||
&& isEventFromTrustedSourceLocked(keyEntry)
|
||||
&& (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
|
||||
&& (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
|
||||
}
|
||||
|
||||
@@ -541,12 +544,6 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
|
||||
mAllocator.releaseEventEntry(entry);
|
||||
}
|
||||
|
||||
bool InputDispatcher::isEventFromTrustedSourceLocked(EventEntry* entry) {
|
||||
InjectionState* injectionState = entry->injectionState;
|
||||
return ! injectionState
|
||||
|| hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid);
|
||||
}
|
||||
|
||||
void InputDispatcher::resetKeyRepeatLocked() {
|
||||
if (mKeyRepeatState.lastKeyEntry) {
|
||||
mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
|
||||
@@ -559,7 +556,8 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
|
||||
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
|
||||
|
||||
// Reuse the repeated key entry if it is otherwise unreferenced.
|
||||
uint32_t policyFlags = entry->policyFlags & (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER);
|
||||
uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
|
||||
| POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
|
||||
if (entry->refCount == 1) {
|
||||
mAllocator.recycleKeyEntry(entry);
|
||||
entry->eventTime = currentTime;
|
||||
@@ -608,19 +606,13 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(
|
||||
|
||||
bool InputDispatcher::dispatchKeyLocked(
|
||||
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
|
||||
bool dropEvent, nsecs_t* nextWakeupTime) {
|
||||
DropReason* dropReason, nsecs_t* nextWakeupTime) {
|
||||
// Give the policy a chance to intercept the key.
|
||||
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
|
||||
bool trusted;
|
||||
if (! dropEvent && mFocusedWindow) {
|
||||
trusted = checkInjectionPermission(mFocusedWindow, entry->injectionState);
|
||||
} else {
|
||||
trusted = isEventFromTrustedSourceLocked(entry);
|
||||
}
|
||||
if (trusted) {
|
||||
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
|
||||
CommandEntry* commandEntry = postCommandLocked(
|
||||
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
|
||||
if (! dropEvent && mFocusedWindow) {
|
||||
if (mFocusedWindow) {
|
||||
commandEntry->inputChannel = mFocusedWindow->inputChannel;
|
||||
}
|
||||
commandEntry->keyEntry = entry;
|
||||
@@ -630,13 +622,16 @@ bool InputDispatcher::dispatchKeyLocked(
|
||||
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
|
||||
}
|
||||
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
|
||||
if (*dropReason == DROP_REASON_NOT_DROPPED) {
|
||||
*dropReason = DROP_REASON_POLICY;
|
||||
}
|
||||
resetTargetsLocked();
|
||||
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clean up if dropping the event.
|
||||
if (dropEvent) {
|
||||
if (*dropReason != DROP_REASON_NOT_DROPPED) {
|
||||
resetTargetsLocked();
|
||||
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
|
||||
return true;
|
||||
@@ -648,7 +643,8 @@ bool InputDispatcher::dispatchKeyLocked(
|
||||
|
||||
if (entry->repeatCount == 0
|
||||
&& entry->action == AKEY_EVENT_ACTION_DOWN
|
||||
&& ! entry->isInjected()) {
|
||||
&& (entry->policyFlags & POLICY_FLAG_TRUSTED)
|
||||
&& !entry->isInjected()) {
|
||||
if (mKeyRepeatState.lastKeyEntry
|
||||
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
|
||||
// We have seen two identical key downs in a row which indicates that the device
|
||||
@@ -713,9 +709,9 @@ void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyE
|
||||
}
|
||||
|
||||
bool InputDispatcher::dispatchMotionLocked(
|
||||
nsecs_t currentTime, MotionEntry* entry, bool dropEvent, nsecs_t* nextWakeupTime) {
|
||||
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
|
||||
// Clean up if dropping the event.
|
||||
if (dropEvent) {
|
||||
if (*dropReason != DROP_REASON_NOT_DROPPED) {
|
||||
resetTargetsLocked();
|
||||
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
|
||||
return true;
|
||||
@@ -2085,6 +2081,7 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou
|
||||
return;
|
||||
}
|
||||
|
||||
policyFlags |= POLICY_FLAG_TRUSTED;
|
||||
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
||||
keyCode, scanCode, /*byref*/ policyFlags);
|
||||
|
||||
@@ -2130,6 +2127,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t
|
||||
return;
|
||||
}
|
||||
|
||||
policyFlags |= POLICY_FLAG_TRUSTED;
|
||||
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
||||
|
||||
bool needWake;
|
||||
@@ -2263,6 +2261,7 @@ void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t swi
|
||||
switchCode, switchValue, policyFlags);
|
||||
#endif
|
||||
|
||||
policyFlags |= POLICY_FLAG_TRUSTED;
|
||||
mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
|
||||
}
|
||||
|
||||
@@ -2275,7 +2274,11 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
||||
#endif
|
||||
|
||||
nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
|
||||
bool trusted = hasInjectionPermission(injectorPid, injectorUid);
|
||||
|
||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
||||
if (hasInjectionPermission(injectorPid, injectorUid)) {
|
||||
policyFlags |= POLICY_FLAG_TRUSTED;
|
||||
}
|
||||
|
||||
EventEntry* injectedEntry;
|
||||
switch (event->getType()) {
|
||||
@@ -2291,11 +2294,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
||||
int32_t flags = keyEvent->getFlags();
|
||||
int32_t keyCode = keyEvent->getKeyCode();
|
||||
int32_t scanCode = keyEvent->getScanCode();
|
||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
||||
if (trusted) {
|
||||
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
||||
keyCode, scanCode, /*byref*/ policyFlags);
|
||||
}
|
||||
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
||||
keyCode, scanCode, /*byref*/ policyFlags);
|
||||
|
||||
mLock.lock();
|
||||
injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
|
||||
@@ -2314,10 +2314,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
||||
}
|
||||
|
||||
nsecs_t eventTime = motionEvent->getEventTime();
|
||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
||||
if (trusted) {
|
||||
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
||||
}
|
||||
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
||||
|
||||
mLock.lock();
|
||||
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
|
||||
|
||||
@@ -1057,6 +1057,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
@Override
|
||||
public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
|
||||
int keyCode, int metaState, int repeatCount, int policyFlags) {
|
||||
if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean keyguardOn = keyguardOn();
|
||||
final boolean down = (action == KeyEvent.ACTION_DOWN);
|
||||
final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0);
|
||||
@@ -1083,7 +1087,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
if (!down) {
|
||||
mHomePressed = false;
|
||||
|
||||
if (! canceled) {
|
||||
if (!canceled) {
|
||||
// If an incoming call is ringing, HOME is totally disabled.
|
||||
// (The user is already on the InCallScreen at this point,
|
||||
// and his ONLY options are to answer or reject the call.)
|
||||
@@ -1735,7 +1739,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
|
||||
int policyFlags, boolean isScreenOn) {
|
||||
int result = ACTION_PASS_TO_USER;
|
||||
|
||||
if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
|
||||
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
|
||||
}
|
||||
|
||||
final boolean isWakeKey = (policyFlags
|
||||
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
|
||||
|
||||
|
||||
@@ -358,11 +358,6 @@ public class InputManager {
|
||||
private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
|
||||
private static final String CALIBRATION_DIR_PATH = "usr/idc/";
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void virtualKeyDownFeedback() {
|
||||
mWindowManagerService.mInputMonitor.virtualKeyDownFeedback();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void notifyConfigurationChanged(long whenNanos) {
|
||||
mWindowManagerService.sendNewConfiguration();
|
||||
|
||||
@@ -5243,13 +5243,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
mTempInputWindows.clear();
|
||||
}
|
||||
|
||||
/* Provides feedback for a virtual key down. */
|
||||
public void virtualKeyDownFeedback() {
|
||||
synchronized (mWindowMap) {
|
||||
mPolicy.performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notifies that the lid switch changed state. */
|
||||
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
|
||||
mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
|
||||
|
||||
@@ -50,7 +50,6 @@ static struct {
|
||||
jmethodID notifyLidSwitchChanged;
|
||||
jmethodID notifyInputChannelBroken;
|
||||
jmethodID notifyANR;
|
||||
jmethodID virtualKeyDownFeedback;
|
||||
jmethodID interceptKeyBeforeQueueing;
|
||||
jmethodID interceptKeyBeforeDispatching;
|
||||
jmethodID checkInjectEventsPermission;
|
||||
@@ -192,6 +191,8 @@ public:
|
||||
|
||||
/* --- InputDispatcherPolicyInterface implementation --- */
|
||||
|
||||
virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
||||
uint32_t policyFlags);
|
||||
virtual void notifyConfigurationChanged(nsecs_t when);
|
||||
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
|
||||
const sp<InputChannel>& inputChannel);
|
||||
@@ -205,8 +206,6 @@ public:
|
||||
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
|
||||
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
||||
const KeyEvent* keyEvent, uint32_t policyFlags);
|
||||
virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
||||
uint32_t policyFlags);
|
||||
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
|
||||
virtual bool checkInjectEventsPermissionNonReentrant(
|
||||
int32_t injectorPid, int32_t injectorUid);
|
||||
@@ -255,7 +254,6 @@ private:
|
||||
|
||||
static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
|
||||
|
||||
static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
|
||||
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
|
||||
|
||||
static inline JNIEnv* jniEnv() {
|
||||
@@ -291,37 +289,6 @@ void NativeInputManager::dump(String8& dump) {
|
||||
dump.append("\n");
|
||||
}
|
||||
|
||||
bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
|
||||
// Special keys that the WindowManagerPolicy might care about.
|
||||
switch (keyCode) {
|
||||
case AKEYCODE_VOLUME_UP:
|
||||
case AKEYCODE_VOLUME_DOWN:
|
||||
case AKEYCODE_ENDCALL:
|
||||
case AKEYCODE_POWER:
|
||||
case AKEYCODE_CALL:
|
||||
case AKEYCODE_HOME:
|
||||
case AKEYCODE_MENU:
|
||||
case AKEYCODE_SEARCH:
|
||||
// media keys
|
||||
case AKEYCODE_HEADSETHOOK:
|
||||
case AKEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case AKEYCODE_MEDIA_STOP:
|
||||
case AKEYCODE_MEDIA_NEXT:
|
||||
case AKEYCODE_MEDIA_PREVIOUS:
|
||||
case AKEYCODE_MEDIA_REWIND:
|
||||
case AKEYCODE_MEDIA_FAST_FORWARD:
|
||||
// The policy always cares about these keys.
|
||||
return true;
|
||||
default:
|
||||
// We need to pass all keys to the policy in the following cases:
|
||||
// - screen is off
|
||||
// - keyguard is visible
|
||||
// - policy is performing key chording
|
||||
//return ! isScreenOn || keyguardVisible || chording;
|
||||
return true; // XXX stubbed out for now
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
@@ -454,115 +421,6 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId,
|
||||
return result;
|
||||
}
|
||||
|
||||
bool NativeInputManager::isScreenOn() {
|
||||
return android_server_PowerManagerService_isScreenOn();
|
||||
}
|
||||
|
||||
bool NativeInputManager::isScreenBright() {
|
||||
return android_server_PowerManagerService_isScreenBright();
|
||||
}
|
||||
|
||||
void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when,
|
||||
int32_t deviceId, int32_t action, int32_t &flags,
|
||||
int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, "
|
||||
"keyCode=%d, scanCode=%d, policyFlags=0x%x",
|
||||
when, deviceId, action, flags, keyCode, scanCode, policyFlags);
|
||||
#endif
|
||||
|
||||
bool down = action == AKEY_EVENT_ACTION_DOWN;
|
||||
if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
|
||||
policyFlags |= POLICY_FLAG_VIRTUAL;
|
||||
flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
|
||||
|
||||
if (down) {
|
||||
JNIEnv* env = jniEnv();
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
|
||||
checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
|
||||
}
|
||||
}
|
||||
|
||||
const int32_t WM_ACTION_PASS_TO_USER = 1;
|
||||
const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
|
||||
const int32_t WM_ACTION_GO_TO_SLEEP = 4;
|
||||
|
||||
bool isScreenOn = this->isScreenOn();
|
||||
bool isScreenBright = this->isScreenBright();
|
||||
|
||||
jint wmActions = 0;
|
||||
if (isPolicyKey(keyCode, isScreenOn)) {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
wmActions = env->CallIntMethod(mCallbacksObj,
|
||||
gCallbacksClassInfo.interceptKeyBeforeQueueing,
|
||||
when, keyCode, down, policyFlags, isScreenOn);
|
||||
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
|
||||
wmActions = 0;
|
||||
}
|
||||
} else {
|
||||
wmActions = WM_ACTION_PASS_TO_USER;
|
||||
}
|
||||
|
||||
if (! isScreenOn) {
|
||||
// Key presses and releases wake the device.
|
||||
policyFlags |= POLICY_FLAG_WOKE_HERE;
|
||||
flags |= AKEY_EVENT_FLAG_WOKE_HERE;
|
||||
}
|
||||
|
||||
if (! isScreenBright) {
|
||||
// Key presses and releases brighten the screen if dimmed.
|
||||
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
|
||||
android_server_PowerManagerService_goToSleep(when);
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
|
||||
android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_PASS_TO_USER) {
|
||||
policyFlags |= POLICY_FLAG_PASS_TO_USER;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags);
|
||||
#endif
|
||||
|
||||
if (isScreenOn()) {
|
||||
// Only dispatch events when the device is awake.
|
||||
// Do not wake the device.
|
||||
policyFlags |= POLICY_FLAG_PASS_TO_USER;
|
||||
|
||||
if (! isScreenBright()) {
|
||||
// Brighten the screen if dimmed.
|
||||
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
|
||||
int32_t switchValue, uint32_t policyFlags) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("notifySwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
|
||||
when, switchCode, switchValue, policyFlags);
|
||||
#endif
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
switch (switchCode) {
|
||||
case SW_LID:
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
|
||||
when, switchValue == 0);
|
||||
checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeInputManager::filterTouchEvents() {
|
||||
if (mFilterTouchEvents < 0) {
|
||||
JNIEnv* env = jniEnv();
|
||||
@@ -692,6 +550,24 @@ void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDevi
|
||||
}
|
||||
}
|
||||
|
||||
void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
|
||||
int32_t switchValue, uint32_t policyFlags) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("notifySwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
|
||||
when, switchCode, switchValue, policyFlags);
|
||||
#endif
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
switch (switchCode) {
|
||||
case SW_LID:
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
|
||||
when, switchValue == 0);
|
||||
checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("notifyConfigurationChanged - when=%lld", when);
|
||||
@@ -944,13 +820,88 @@ void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
|
||||
mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
|
||||
}
|
||||
|
||||
bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
||||
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
||||
bool isScreenOn = this->isScreenOn();
|
||||
if (! isPolicyKey(keyEvent->getKeyCode(), isScreenOn)) {
|
||||
return false;
|
||||
bool NativeInputManager::isScreenOn() {
|
||||
return android_server_PowerManagerService_isScreenOn();
|
||||
}
|
||||
|
||||
bool NativeInputManager::isScreenBright() {
|
||||
return android_server_PowerManagerService_isScreenBright();
|
||||
}
|
||||
|
||||
void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when,
|
||||
int32_t deviceId, int32_t action, int32_t &flags,
|
||||
int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, "
|
||||
"keyCode=%d, scanCode=%d, policyFlags=0x%x",
|
||||
when, deviceId, action, flags, keyCode, scanCode, policyFlags);
|
||||
#endif
|
||||
|
||||
if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
|
||||
policyFlags |= POLICY_FLAG_VIRTUAL;
|
||||
flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
|
||||
}
|
||||
|
||||
const int32_t WM_ACTION_PASS_TO_USER = 1;
|
||||
const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
|
||||
const int32_t WM_ACTION_GO_TO_SLEEP = 4;
|
||||
|
||||
bool isScreenOn = this->isScreenOn();
|
||||
bool isScreenBright = this->isScreenBright();
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
jint wmActions = env->CallIntMethod(mCallbacksObj,
|
||||
gCallbacksClassInfo.interceptKeyBeforeQueueing,
|
||||
when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn);
|
||||
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
|
||||
wmActions = 0;
|
||||
}
|
||||
|
||||
if (policyFlags & POLICY_FLAG_TRUSTED) {
|
||||
if (! isScreenOn) {
|
||||
// Key presses and releases wake the device.
|
||||
policyFlags |= POLICY_FLAG_WOKE_HERE;
|
||||
flags |= AKEY_EVENT_FLAG_WOKE_HERE;
|
||||
}
|
||||
|
||||
if (! isScreenBright) {
|
||||
// Key presses and releases brighten the screen if dimmed.
|
||||
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
|
||||
android_server_PowerManagerService_goToSleep(when);
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
|
||||
android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_PASS_TO_USER) {
|
||||
policyFlags |= POLICY_FLAG_PASS_TO_USER;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags);
|
||||
#endif
|
||||
|
||||
if (isScreenOn()) {
|
||||
// Only dispatch events when the device is awake.
|
||||
// Do not wake the device.
|
||||
policyFlags |= POLICY_FLAG_PASS_TO_USER;
|
||||
|
||||
if ((policyFlags & POLICY_FLAG_TRUSTED) && !isScreenBright()) {
|
||||
// Brighten the screen if dimmed.
|
||||
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
||||
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
// Note: inputChannel may be null.
|
||||
@@ -1365,9 +1316,6 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
|
||||
"notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
|
||||
"virtualKeyDownFeedback", "()V");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
|
||||
"interceptKeyBeforeQueueing", "(JIZIZ)I");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user