summaryrefslogtreecommitdiffstats
path: root/services/jni/com_android_server_InputManager.cpp
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-09-01 17:01:00 -0700
committerJeff Brown <jeffbrown@google.com>2010-09-08 11:50:55 -0700
commit85a3176704b5bfbeece9bd928369fbb76eec7dc6 (patch)
tree1a84f21c037b514c5b6717b106f5a9a2c4fd6c99 /services/jni/com_android_server_InputManager.cpp
parentc0b4f6d30d962d75125628317b5f5ea622531dfe (diff)
downloadframeworks_base-85a3176704b5bfbeece9bd928369fbb76eec7dc6.zip
frameworks_base-85a3176704b5bfbeece9bd928369fbb76eec7dc6.tar.gz
frameworks_base-85a3176704b5bfbeece9bd928369fbb76eec7dc6.tar.bz2
Add support for secure views.
Added the MotionEvent.FLAG_WINDOW_IS_OBSCURED flag which is set by the input manager whenever another visible window is partly or wholly obscured the target of a touch event so that applications can filter touches accordingly. Added a "filterTouchesWhenObscured" attribute to View which can be used to enable filtering of touches when the view's window is obscured. Change-Id: I936d9c85013fd2d77fb296a600528d30a29027d2
Diffstat (limited to 'services/jni/com_android_server_InputManager.cpp')
-rw-r--r--services/jni/com_android_server_InputManager.cpp131
1 files changed, 116 insertions, 15 deletions
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index a237ee9..4318681 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -169,6 +169,12 @@ static struct {
jfieldID dispatchingTimeoutNanos;
jfieldID frameLeft;
jfieldID frameTop;
+ jfieldID frameRight;
+ jfieldID frameBottom;
+ jfieldID visibleFrameLeft;
+ jfieldID visibleFrameTop;
+ jfieldID visibleFrameRight;
+ jfieldID visibleFrameBottom;
jfieldID touchableAreaLeft;
jfieldID touchableAreaTop;
jfieldID touchableAreaRight;
@@ -283,6 +289,12 @@ private:
nsecs_t dispatchingTimeout;
int32_t frameLeft;
int32_t frameTop;
+ int32_t frameRight;
+ int32_t frameBottom;
+ int32_t visibleFrameLeft;
+ int32_t visibleFrameTop;
+ int32_t visibleFrameRight;
+ int32_t visibleFrameBottom;
int32_t touchableAreaLeft;
int32_t touchableAreaTop;
int32_t touchableAreaRight;
@@ -294,10 +306,8 @@ private:
int32_t ownerPid;
int32_t ownerUid;
- inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
- return x >= touchableAreaLeft && x <= touchableAreaRight
- && y >= touchableAreaTop && y <= touchableAreaBottom;
- }
+ bool visibleFrameIntersects(const InputWindow* other) const;
+ bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
};
struct InputApplication {
@@ -370,9 +380,13 @@ private:
// Focus tracking for touch.
bool mTouchDown;
InputWindow* mTouchedWindow; // primary target for current down
+ bool mTouchedWindowIsObscured; // true if other windows may obscure the target
Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
-
- Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
+ struct OutsideTarget {
+ InputWindow* window;
+ bool obscured;
+ };
+ Vector<OutsideTarget> mTempTouchedOutsideTargets; // temporary outside touch targets
Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
// Focused application.
@@ -391,6 +405,7 @@ private:
int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid,
Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
+ bool isWindowObscuredLocked(const InputWindow* window);
void releaseTouchedWindowLd();
@@ -1117,6 +1132,18 @@ bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
gInputWindowClassInfo.frameLeft);
jint frameTop = env->GetIntField(windowObj,
gInputWindowClassInfo.frameTop);
+ jint frameRight = env->GetIntField(windowObj,
+ gInputWindowClassInfo.frameRight);
+ jint frameBottom = env->GetIntField(windowObj,
+ gInputWindowClassInfo.frameBottom);
+ jint visibleFrameLeft = env->GetIntField(windowObj,
+ gInputWindowClassInfo.visibleFrameLeft);
+ jint visibleFrameTop = env->GetIntField(windowObj,
+ gInputWindowClassInfo.visibleFrameTop);
+ jint visibleFrameRight = env->GetIntField(windowObj,
+ gInputWindowClassInfo.visibleFrameRight);
+ jint visibleFrameBottom = env->GetIntField(windowObj,
+ gInputWindowClassInfo.visibleFrameBottom);
jint touchableAreaLeft = env->GetIntField(windowObj,
gInputWindowClassInfo.touchableAreaLeft);
jint touchableAreaTop = env->GetIntField(windowObj,
@@ -1144,6 +1171,12 @@ bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
outWindow.frameLeft = frameLeft;
outWindow.frameTop = frameTop;
+ outWindow.frameRight = frameRight;
+ outWindow.frameBottom = frameBottom;
+ outWindow.visibleFrameLeft = visibleFrameLeft;
+ outWindow.visibleFrameTop = visibleFrameTop;
+ outWindow.visibleFrameRight = visibleFrameRight;
+ outWindow.visibleFrameBottom = visibleFrameBottom;
outWindow.touchableAreaLeft = touchableAreaLeft;
outWindow.touchableAreaTop = touchableAreaTop;
outWindow.touchableAreaRight = touchableAreaRight;
@@ -1417,11 +1450,12 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
/* Case 1: ACTION_DOWN */
InputWindow* newTouchedWindow = NULL;
- mTempTouchedOutsideWindows.clear();
+ mTempTouchedOutsideTargets.clear();
int32_t x = int32_t(motionEvent->getX(0));
int32_t y = int32_t(motionEvent->getY(0));
InputWindow* topErrorWindow = NULL;
+ bool obscured = false;
// Traverse windows from front to back to find touched window and outside targets.
size_t numWindows = mWindows.size();
@@ -1442,13 +1476,17 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
newTouchedWindow = window;
+ obscured = isWindowObscuredLocked(window);
}
break; // found touched window, exit window loop
}
}
if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
- mTempTouchedOutsideWindows.push(window);
+ OutsideTarget outsideTarget;
+ outsideTarget.window = window;
+ outsideTarget.obscured = isWindowObscuredLocked(window);
+ mTempTouchedOutsideTargets.push(outsideTarget);
}
}
}
@@ -1501,6 +1539,7 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
releaseTouchedWindowLd();
mTouchedWindow = newTouchedWindow;
+ mTouchedWindowIsObscured = obscured;
if (newTouchedWindow->hasWallpaper) {
mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
@@ -1557,21 +1596,31 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
for (size_t i = 0; i < numWallpaperWindows; i++) {
- addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
+ addTarget(mTouchedWallpaperWindows[i],
+ InputTarget::FLAG_WINDOW_IS_OBSCURED, 0, outTargets);
}
- size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
- for (size_t i = 0; i < numOutsideWindows; i++) {
- addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
+ size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
+ for (size_t i = 0; i < numOutsideTargets; i++) {
+ const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
+ int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
+ if (outsideTarget.obscured) {
+ outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+ }
+ addTarget(outsideTarget.window, outsideTargetFlags, 0, outTargets);
}
- addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
+ int32_t targetFlags = InputTarget::FLAG_SYNC;
+ if (mTouchedWindowIsObscured) {
+ targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+ }
+ addTarget(mTouchedWindow, targetFlags,
anrTimer.getTimeSpentWaitingForApplication(), outTargets);
outTouchedWindow = mTouchedWindow;
} else {
outTouchedWindow = NULL;
}
- mTempTouchedOutsideWindows.clear();
+ mTempTouchedOutsideTargets.clear();
// Check injection permission once and for all.
if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
@@ -1616,6 +1665,7 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
void NativeInputManager::releaseTouchedWindowLd() {
mTouchedWindow = NULL;
+ mTouchedWindowIsObscured = false;
mTouchedWallpaperWindows.clear();
}
@@ -1661,6 +1711,20 @@ bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
return true;
}
+bool NativeInputManager::isWindowObscuredLocked(const InputWindow* window) {
+ size_t numWindows = mWindows.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const InputWindow* other = & mWindows.itemAt(i);
+ if (other == window) {
+ break;
+ }
+ if (other->visible && window->visibleFrameIntersects(other)) {
+ return true;
+ }
+ }
+ return false;
+}
+
int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
#if DEBUG_INPUT_DISPATCHER_POLICY
@@ -1935,12 +1999,17 @@ void NativeInputManager::dumpDispatchStateLd(String8& dump) {
for (size_t i = 0; i < mWindows.size(); i++) {
dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
"visible=%d, flags=0x%08x, type=0x%08x, "
- "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
+ "frame=[%d,%d][%d,%d], "
+ "visibleFrame=[%d,%d][%d,%d], "
+ "touchableArea=[%d,%d][%d,%d], "
"ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
i, mWindows[i].inputChannel->getName().string(),
mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
mWindows[i].frameLeft, mWindows[i].frameTop,
+ mWindows[i].frameRight, mWindows[i].frameBottom,
+ mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
+ mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
mWindows[i].ownerPid, mWindows[i].ownerUid,
@@ -1955,6 +2024,20 @@ void NativeInputManager::dumpDispatchStateLd(String8& dump) {
// ----------------------------------------------------------------------------
+bool NativeInputManager::InputWindow::visibleFrameIntersects(const InputWindow* other) const {
+ return visibleFrameRight > other->visibleFrameLeft
+ && visibleFrameLeft < other->visibleFrameRight
+ && visibleFrameBottom > other->visibleFrameTop
+ && visibleFrameTop < other->visibleFrameBottom;
+}
+
+bool NativeInputManager::InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
+ return x >= touchableAreaLeft && x <= touchableAreaRight
+ && y >= touchableAreaTop && y <= touchableAreaBottom;
+}
+
+// ----------------------------------------------------------------------------
+
NativeInputManager::ANRTimer::ANRTimer() :
mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
}
@@ -2507,6 +2590,24 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
"frameTop", "I");
+ GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+ "frameRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+ "frameBottom", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
+ "visibleFrameLeft", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
+ "visibleFrameTop", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
+ "visibleFrameRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
+ "visibleFrameBottom", "I");
+
GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
"touchableAreaLeft", "I");