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_VIRTUAL = 0x00000100;
|
||||||
|
|
||||||
public final static int FLAG_INJECTED = 0x01000000;
|
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_WOKE_HERE = 0x10000000;
|
||||||
public final static int FLAG_BRIGHT_HERE = 0x20000000;
|
public final static int FLAG_BRIGHT_HERE = 0x20000000;
|
||||||
|
|||||||
@@ -95,6 +95,10 @@ enum {
|
|||||||
// Indicates that the input event was injected.
|
// Indicates that the input event was injected.
|
||||||
POLICY_FLAG_INJECTED = 0x01000000,
|
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. */
|
/* 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
|
// Indicates that the screen was off when the event was received and the event
|
||||||
|
|||||||
@@ -913,7 +913,6 @@ private:
|
|||||||
void drainInboundQueueLocked();
|
void drainInboundQueueLocked();
|
||||||
void releasePendingEventLocked();
|
void releasePendingEventLocked();
|
||||||
void releaseInboundEventLocked(EventEntry* entry);
|
void releaseInboundEventLocked(EventEntry* entry);
|
||||||
bool isEventFromTrustedSourceLocked(EventEntry* entry);
|
|
||||||
|
|
||||||
// Dispatch state.
|
// Dispatch state.
|
||||||
bool mDispatchEnabled;
|
bool mDispatchEnabled;
|
||||||
@@ -960,10 +959,10 @@ private:
|
|||||||
nsecs_t currentTime, ConfigurationChangedEntry* entry);
|
nsecs_t currentTime, ConfigurationChangedEntry* entry);
|
||||||
bool dispatchKeyLocked(
|
bool dispatchKeyLocked(
|
||||||
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
|
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
|
||||||
bool dropEvent, nsecs_t* nextWakeupTime);
|
DropReason* dropReason, nsecs_t* nextWakeupTime);
|
||||||
bool dispatchMotionLocked(
|
bool dispatchMotionLocked(
|
||||||
nsecs_t currentTime, MotionEntry* entry,
|
nsecs_t currentTime, MotionEntry* entry,
|
||||||
bool dropEvent, nsecs_t* nextWakeupTime);
|
DropReason* dropReason, nsecs_t* nextWakeupTime);
|
||||||
void dispatchEventToCurrentInputTargetsLocked(
|
void dispatchEventToCurrentInputTargetsLocked(
|
||||||
nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
|
nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
|
||||||
|
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
|
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
|
||||||
dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
|
&dropReason, nextWakeupTime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||||||
dropReason = DROP_REASON_APP_SWITCH;
|
dropReason = DROP_REASON_APP_SWITCH;
|
||||||
}
|
}
|
||||||
done = dispatchMotionLocked(currentTime, typedEntry,
|
done = dispatchMotionLocked(currentTime, typedEntry,
|
||||||
dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
|
&dropReason, nextWakeupTime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +431,9 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR
|
|||||||
const char* reason;
|
const char* reason;
|
||||||
switch (dropReason) {
|
switch (dropReason) {
|
||||||
case DROP_REASON_POLICY:
|
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 "
|
reason = "inbound event was dropped because the policy requested that it not be "
|
||||||
"delivered to the application";
|
"delivered to the application";
|
||||||
break;
|
break;
|
||||||
@@ -473,7 +476,7 @@ bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
|
|||||||
bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
|
bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
|
||||||
return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
|
return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
|
||||||
&& isAppSwitchKeyCode(keyEntry->keyCode)
|
&& isAppSwitchKeyCode(keyEntry->keyCode)
|
||||||
&& isEventFromTrustedSourceLocked(keyEntry)
|
&& (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
|
||||||
&& (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
|
&& (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,12 +544,6 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
|
|||||||
mAllocator.releaseEventEntry(entry);
|
mAllocator.releaseEventEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputDispatcher::isEventFromTrustedSourceLocked(EventEntry* entry) {
|
|
||||||
InjectionState* injectionState = entry->injectionState;
|
|
||||||
return ! injectionState
|
|
||||||
|| hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputDispatcher::resetKeyRepeatLocked() {
|
void InputDispatcher::resetKeyRepeatLocked() {
|
||||||
if (mKeyRepeatState.lastKeyEntry) {
|
if (mKeyRepeatState.lastKeyEntry) {
|
||||||
mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
|
mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
|
||||||
@@ -559,7 +556,8 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
|
|||||||
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
|
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
|
||||||
|
|
||||||
// Reuse the repeated key entry if it is otherwise unreferenced.
|
// 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) {
|
if (entry->refCount == 1) {
|
||||||
mAllocator.recycleKeyEntry(entry);
|
mAllocator.recycleKeyEntry(entry);
|
||||||
entry->eventTime = currentTime;
|
entry->eventTime = currentTime;
|
||||||
@@ -608,19 +606,13 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(
|
|||||||
|
|
||||||
bool InputDispatcher::dispatchKeyLocked(
|
bool InputDispatcher::dispatchKeyLocked(
|
||||||
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
|
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.
|
// Give the policy a chance to intercept the key.
|
||||||
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
|
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
|
||||||
bool trusted;
|
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
|
||||||
if (! dropEvent && mFocusedWindow) {
|
|
||||||
trusted = checkInjectionPermission(mFocusedWindow, entry->injectionState);
|
|
||||||
} else {
|
|
||||||
trusted = isEventFromTrustedSourceLocked(entry);
|
|
||||||
}
|
|
||||||
if (trusted) {
|
|
||||||
CommandEntry* commandEntry = postCommandLocked(
|
CommandEntry* commandEntry = postCommandLocked(
|
||||||
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
|
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
|
||||||
if (! dropEvent && mFocusedWindow) {
|
if (mFocusedWindow) {
|
||||||
commandEntry->inputChannel = mFocusedWindow->inputChannel;
|
commandEntry->inputChannel = mFocusedWindow->inputChannel;
|
||||||
}
|
}
|
||||||
commandEntry->keyEntry = entry;
|
commandEntry->keyEntry = entry;
|
||||||
@@ -630,13 +622,16 @@ bool InputDispatcher::dispatchKeyLocked(
|
|||||||
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
|
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
|
||||||
}
|
}
|
||||||
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
|
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
|
||||||
|
if (*dropReason == DROP_REASON_NOT_DROPPED) {
|
||||||
|
*dropReason = DROP_REASON_POLICY;
|
||||||
|
}
|
||||||
resetTargetsLocked();
|
resetTargetsLocked();
|
||||||
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
|
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up if dropping the event.
|
// Clean up if dropping the event.
|
||||||
if (dropEvent) {
|
if (*dropReason != DROP_REASON_NOT_DROPPED) {
|
||||||
resetTargetsLocked();
|
resetTargetsLocked();
|
||||||
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
|
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
|
||||||
return true;
|
return true;
|
||||||
@@ -648,7 +643,8 @@ bool InputDispatcher::dispatchKeyLocked(
|
|||||||
|
|
||||||
if (entry->repeatCount == 0
|
if (entry->repeatCount == 0
|
||||||
&& entry->action == AKEY_EVENT_ACTION_DOWN
|
&& entry->action == AKEY_EVENT_ACTION_DOWN
|
||||||
&& ! entry->isInjected()) {
|
&& (entry->policyFlags & POLICY_FLAG_TRUSTED)
|
||||||
|
&& !entry->isInjected()) {
|
||||||
if (mKeyRepeatState.lastKeyEntry
|
if (mKeyRepeatState.lastKeyEntry
|
||||||
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
|
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
|
||||||
// We have seen two identical key downs in a row which indicates that the device
|
// 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(
|
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.
|
// Clean up if dropping the event.
|
||||||
if (dropEvent) {
|
if (*dropReason != DROP_REASON_NOT_DROPPED) {
|
||||||
resetTargetsLocked();
|
resetTargetsLocked();
|
||||||
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
|
setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
|
||||||
return true;
|
return true;
|
||||||
@@ -2085,6 +2081,7 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
policyFlags |= POLICY_FLAG_TRUSTED;
|
||||||
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
||||||
keyCode, scanCode, /*byref*/ policyFlags);
|
keyCode, scanCode, /*byref*/ policyFlags);
|
||||||
|
|
||||||
@@ -2130,6 +2127,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
policyFlags |= POLICY_FLAG_TRUSTED;
|
||||||
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
||||||
|
|
||||||
bool needWake;
|
bool needWake;
|
||||||
@@ -2263,6 +2261,7 @@ void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t swi
|
|||||||
switchCode, switchValue, policyFlags);
|
switchCode, switchValue, policyFlags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
policyFlags |= POLICY_FLAG_TRUSTED;
|
||||||
mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
|
mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2275,7 +2274,11 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
|
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;
|
EventEntry* injectedEntry;
|
||||||
switch (event->getType()) {
|
switch (event->getType()) {
|
||||||
@@ -2291,11 +2294,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||||||
int32_t flags = keyEvent->getFlags();
|
int32_t flags = keyEvent->getFlags();
|
||||||
int32_t keyCode = keyEvent->getKeyCode();
|
int32_t keyCode = keyEvent->getKeyCode();
|
||||||
int32_t scanCode = keyEvent->getScanCode();
|
int32_t scanCode = keyEvent->getScanCode();
|
||||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
||||||
if (trusted) {
|
keyCode, scanCode, /*byref*/ policyFlags);
|
||||||
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
|
||||||
keyCode, scanCode, /*byref*/ policyFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
mLock.lock();
|
mLock.lock();
|
||||||
injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
|
injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
|
||||||
@@ -2314,10 +2314,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsecs_t eventTime = motionEvent->getEventTime();
|
nsecs_t eventTime = motionEvent->getEventTime();
|
||||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
||||||
if (trusted) {
|
|
||||||
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
mLock.lock();
|
mLock.lock();
|
||||||
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
|
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
|
||||||
|
|||||||
@@ -1057,6 +1057,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
@Override
|
@Override
|
||||||
public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
|
public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
|
||||||
int keyCode, int metaState, int repeatCount, int policyFlags) {
|
int keyCode, int metaState, int repeatCount, int policyFlags) {
|
||||||
|
if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final boolean keyguardOn = keyguardOn();
|
final boolean keyguardOn = keyguardOn();
|
||||||
final boolean down = (action == KeyEvent.ACTION_DOWN);
|
final boolean down = (action == KeyEvent.ACTION_DOWN);
|
||||||
final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0);
|
final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0);
|
||||||
@@ -1083,7 +1087,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
if (!down) {
|
if (!down) {
|
||||||
mHomePressed = false;
|
mHomePressed = false;
|
||||||
|
|
||||||
if (! canceled) {
|
if (!canceled) {
|
||||||
// If an incoming call is ringing, HOME is totally disabled.
|
// If an incoming call is ringing, HOME is totally disabled.
|
||||||
// (The user is already on the InCallScreen at this point,
|
// (The user is already on the InCallScreen at this point,
|
||||||
// and his ONLY options are to answer or reject the call.)
|
// 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,
|
public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
|
||||||
int policyFlags, boolean isScreenOn) {
|
int policyFlags, boolean isScreenOn) {
|
||||||
int result = ACTION_PASS_TO_USER;
|
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
|
final boolean isWakeKey = (policyFlags
|
||||||
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
|
& (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 EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
|
||||||
private static final String CALIBRATION_DIR_PATH = "usr/idc/";
|
private static final String CALIBRATION_DIR_PATH = "usr/idc/";
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public void virtualKeyDownFeedback() {
|
|
||||||
mWindowManagerService.mInputMonitor.virtualKeyDownFeedback();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void notifyConfigurationChanged(long whenNanos) {
|
public void notifyConfigurationChanged(long whenNanos) {
|
||||||
mWindowManagerService.sendNewConfiguration();
|
mWindowManagerService.sendNewConfiguration();
|
||||||
|
|||||||
@@ -5243,13 +5243,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
mTempInputWindows.clear();
|
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. */
|
/* Notifies that the lid switch changed state. */
|
||||||
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
|
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
|
||||||
mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
|
mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ static struct {
|
|||||||
jmethodID notifyLidSwitchChanged;
|
jmethodID notifyLidSwitchChanged;
|
||||||
jmethodID notifyInputChannelBroken;
|
jmethodID notifyInputChannelBroken;
|
||||||
jmethodID notifyANR;
|
jmethodID notifyANR;
|
||||||
jmethodID virtualKeyDownFeedback;
|
|
||||||
jmethodID interceptKeyBeforeQueueing;
|
jmethodID interceptKeyBeforeQueueing;
|
||||||
jmethodID interceptKeyBeforeDispatching;
|
jmethodID interceptKeyBeforeDispatching;
|
||||||
jmethodID checkInjectEventsPermission;
|
jmethodID checkInjectEventsPermission;
|
||||||
@@ -192,6 +191,8 @@ public:
|
|||||||
|
|
||||||
/* --- InputDispatcherPolicyInterface implementation --- */
|
/* --- InputDispatcherPolicyInterface implementation --- */
|
||||||
|
|
||||||
|
virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
||||||
|
uint32_t policyFlags);
|
||||||
virtual void notifyConfigurationChanged(nsecs_t when);
|
virtual void notifyConfigurationChanged(nsecs_t when);
|
||||||
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
|
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
|
||||||
const sp<InputChannel>& inputChannel);
|
const sp<InputChannel>& inputChannel);
|
||||||
@@ -205,8 +206,6 @@ public:
|
|||||||
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
|
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
|
||||||
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
||||||
const KeyEvent* keyEvent, uint32_t policyFlags);
|
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 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
|
||||||
virtual bool checkInjectEventsPermissionNonReentrant(
|
virtual bool checkInjectEventsPermissionNonReentrant(
|
||||||
int32_t injectorPid, int32_t injectorUid);
|
int32_t injectorPid, int32_t injectorUid);
|
||||||
@@ -255,7 +254,6 @@ private:
|
|||||||
|
|
||||||
static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
|
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 bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
|
||||||
|
|
||||||
static inline JNIEnv* jniEnv() {
|
static inline JNIEnv* jniEnv() {
|
||||||
@@ -291,37 +289,6 @@ void NativeInputManager::dump(String8& dump) {
|
|||||||
dump.append("\n");
|
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) {
|
bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
LOGE("An exception was thrown by callback '%s'.", methodName);
|
LOGE("An exception was thrown by callback '%s'.", methodName);
|
||||||
@@ -454,115 +421,6 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId,
|
|||||||
return result;
|
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() {
|
bool NativeInputManager::filterTouchEvents() {
|
||||||
if (mFilterTouchEvents < 0) {
|
if (mFilterTouchEvents < 0) {
|
||||||
JNIEnv* env = jniEnv();
|
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) {
|
void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
|
||||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||||
LOGD("notifyConfigurationChanged - when=%lld", when);
|
LOGD("notifyConfigurationChanged - when=%lld", when);
|
||||||
@@ -944,13 +820,88 @@ void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
|
|||||||
mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
|
mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
bool NativeInputManager::isScreenOn() {
|
||||||
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
return android_server_PowerManagerService_isScreenOn();
|
||||||
bool isScreenOn = this->isScreenOn();
|
}
|
||||||
if (! isPolicyKey(keyEvent->getKeyCode(), isScreenOn)) {
|
|
||||||
return false;
|
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();
|
JNIEnv* env = jniEnv();
|
||||||
|
|
||||||
// Note: inputChannel may be null.
|
// Note: inputChannel may be null.
|
||||||
@@ -1365,9 +1316,6 @@ int register_android_server_InputManager(JNIEnv* env) {
|
|||||||
GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
|
GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
|
||||||
"notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
|
"notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
|
||||||
|
|
||||||
GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
|
|
||||||
"virtualKeyDownFeedback", "()V");
|
|
||||||
|
|
||||||
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
|
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
|
||||||
"interceptKeyBeforeQueueing", "(JIZIZ)I");
|
"interceptKeyBeforeQueueing", "(JIZIZ)I");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user