diff --git a/services/input/InputApplication.h b/services/input/InputApplication.h index cc8006217c11f..8902f7ad0099d 100644 --- a/services/input/InputApplication.h +++ b/services/input/InputApplication.h @@ -26,26 +26,32 @@ namespace android { /* - * A handle to an application that can receive input. - * Used by the native input dispatcher to indirectly refer to the window manager objects + * Describes the properties of an application that can receive input. + * + * Used by the native input dispatcher as a handle for the window manager objects * that describe an application. */ class InputApplicationHandle : public RefBase { +public: + String8 name; + nsecs_t dispatchingTimeout; + + /** + * Requests that the state of this object be updated to reflect + * the most current available information about the application. + * + * This method should only be called from within the input dispatcher's + * critical section. + * + * Returns true on success, or false if the handle is no longer valid. + */ + virtual bool update() = 0; + protected: InputApplicationHandle() { } virtual ~InputApplicationHandle() { } }; - -/* - * An input application describes properties of an application that can receive input. - */ -struct InputApplication { - sp inputApplicationHandle; - String8 name; - nsecs_t dispatchingTimeout; -}; - } // namespace android #endif // _UI_INPUT_APPLICATION_H diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 10b9083549f22..1cac502562be9 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -211,11 +211,8 @@ InputDispatcher::InputDispatcher(const sp& polic mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX), mNextUnblockedEvent(NULL), mDispatchEnabled(true), mDispatchFrozen(false), mInputFilterEnabled(false), - mFocusedWindow(NULL), - mFocusedApplication(NULL), mCurrentInputTargetsValid(false), - mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE), - mLastHoverWindow(NULL) { + mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) { mLooper = new Looper(false); mInboundQueue.headSentinel.refCount = -1; @@ -501,16 +498,15 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY - && mInputTargetWaitApplication != NULL) { + && mInputTargetWaitApplicationHandle != NULL) { int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0]. getAxisValue(AMOTION_EVENT_AXIS_Y)); - const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y); - if (touchedWindow - && touchedWindow->inputWindowHandle != NULL - && touchedWindow->inputWindowHandle->getInputApplicationHandle() - != mInputTargetWaitApplication) { + sp touchedWindowHandle = findTouchedWindowAtLocked(x, y); + if (touchedWindowHandle != NULL + && touchedWindowHandle->inputApplicationHandle + != mInputTargetWaitApplicationHandle) { // User touched a different application than the one we are waiting on. // Flag the event, and start pruning the input queue. mNextUnblockedEvent = motionEntry; @@ -524,25 +520,25 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { return needWake; } -const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) { +sp InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) { // Traverse windows from front to back to find touched window. - size_t numWindows = mWindows.size(); + size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { - const InputWindow* window = & mWindows.editItemAt(i); - int32_t flags = window->layoutParamsFlags; + sp windowHandle = mWindowHandles.itemAt(i); + int32_t flags = windowHandle->layoutParamsFlags; - if (window->visible) { - if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) { - bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE - | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0; - if (isTouchModal || window->touchableRegionContainsPoint(x, y)) { + if (windowHandle->visible) { + if (!(flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) { + bool isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE + | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0; + if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) { // Found window. - return window; + return windowHandle; } } } - if (flags & InputWindow::FLAG_SYSTEM_ERROR) { + if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) { // Error window is on top but not visible, so touch is dropped. return NULL; } @@ -781,8 +777,8 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { CommandEntry* commandEntry = postCommandLocked( & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible); - if (mFocusedWindow) { - commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle; + if (mFocusedWindowHandle != NULL) { + commandEntry->inputWindowHandle = mFocusedWindowHandle; } commandEntry->keyEntry = entry; entry->refCount += 1; @@ -1011,7 +1007,7 @@ void InputDispatcher::resetTargetsLocked() { mCurrentInputTargetsValid = false; mCurrentInputTargets.clear(); mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE; - mInputTargetWaitApplication.clear(); + mInputTargetWaitApplicationHandle.clear(); } void InputDispatcher::commitTargetsLocked() { @@ -1019,9 +1015,11 @@ void InputDispatcher::commitTargetsLocked() { } int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, - const EventEntry* entry, const InputApplication* application, const InputWindow* window, + const EventEntry* entry, + const sp& applicationHandle, + const sp& windowHandle, nsecs_t* nextWakeupTime) { - if (application == NULL && window == NULL) { + if (applicationHandle == NULL && windowHandle == NULL) { if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) { #if DEBUG_FOCUS LOGD("Waiting for system to become ready for input."); @@ -1030,29 +1028,29 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, mInputTargetWaitStartTime = currentTime; mInputTargetWaitTimeoutTime = LONG_LONG_MAX; mInputTargetWaitTimeoutExpired = false; - mInputTargetWaitApplication.clear(); + mInputTargetWaitApplicationHandle.clear(); } } else { if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) { #if DEBUG_FOCUS LOGD("Waiting for application to become ready for input: %s", - getApplicationWindowLabelLocked(application, window).string()); + getApplicationWindowLabelLocked(applicationHandle, windowHandle).string()); #endif - nsecs_t timeout = window ? window->dispatchingTimeout : - application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT; + nsecs_t timeout = windowHandle != NULL ? windowHandle->dispatchingTimeout : + applicationHandle != NULL ? + applicationHandle->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT; mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY; mInputTargetWaitStartTime = currentTime; mInputTargetWaitTimeoutTime = currentTime + timeout; mInputTargetWaitTimeoutExpired = false; - mInputTargetWaitApplication.clear(); + mInputTargetWaitApplicationHandle.clear(); - if (window && window->inputWindowHandle != NULL) { - mInputTargetWaitApplication = - window->inputWindowHandle->getInputApplicationHandle(); + if (windowHandle != NULL) { + mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle; } - if (mInputTargetWaitApplication == NULL && application) { - mInputTargetWaitApplication = application->inputApplicationHandle; + if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) { + mInputTargetWaitApplicationHandle = applicationHandle; } } } @@ -1062,7 +1060,8 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, } if (currentTime >= mInputTargetWaitTimeoutTime) { - onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime); + onANRLocked(currentTime, applicationHandle, windowHandle, + entry->eventTime, mInputTargetWaitStartTime); // Force poll loop to wake up immediately on next iteration once we get the // ANR response back from the policy. @@ -1129,15 +1128,15 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, // If there is no currently focused window and no focused application // then drop the event. - if (! mFocusedWindow) { - if (mFocusedApplication) { + if (mFocusedWindowHandle == NULL) { + if (mFocusedApplicationHandle != NULL) { #if DEBUG_FOCUS LOGD("Waiting because there is no focused window but there is a " "focused application that may eventually add a window: %s.", - getApplicationWindowLabelLocked(mFocusedApplication, NULL).string()); + getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string()); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplication, NULL, nextWakeupTime); + mFocusedApplicationHandle, NULL, nextWakeupTime); goto Unresponsive; } @@ -1147,34 +1146,34 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, } // Check permissions. - if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) { + if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) { injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; goto Failed; } // If the currently focused window is paused then keep waiting. - if (mFocusedWindow->paused) { + if (mFocusedWindowHandle->paused) { #if DEBUG_FOCUS LOGD("Waiting because focused window is paused."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplication, mFocusedWindow, nextWakeupTime); + mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime); goto Unresponsive; } // If the currently focused window is still working on previous events then keep waiting. - if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) { + if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindowHandle)) { #if DEBUG_FOCUS LOGD("Waiting because focused window still processing previous input."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplication, mFocusedWindow, nextWakeupTime); + mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime); goto Unresponsive; } // Success! Output targets. injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED; - addWindowTargetLocked(mFocusedWindow, + addWindowTargetLocked(mFocusedWindowHandle, InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0)); // Done. @@ -1236,7 +1235,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // Update the touch state as needed based on the properties of the touch event. int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING; InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN; - const InputWindow* newHoverWindow = NULL; + sp newHoverWindowHandle; bool isSplit = mTouchState.split; bool switchedDevice = mTouchState.deviceId >= 0 @@ -1279,42 +1278,44 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(sample->pointerCoords[pointerIndex]. getAxisValue(AMOTION_EVENT_AXIS_Y)); - const InputWindow* newTouchedWindow = NULL; - const InputWindow* topErrorWindow = NULL; + sp newTouchedWindowHandle; + sp topErrorWindowHandle; bool isTouchModal = false; // Traverse windows from front to back to find touched window and outside targets. - size_t numWindows = mWindows.size(); + size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { - const InputWindow* window = & mWindows.editItemAt(i); - int32_t flags = window->layoutParamsFlags; + sp windowHandle = mWindowHandles.itemAt(i); + int32_t flags = windowHandle->layoutParamsFlags; - if (flags & InputWindow::FLAG_SYSTEM_ERROR) { - if (! topErrorWindow) { - topErrorWindow = window; + if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) { + if (topErrorWindowHandle == NULL) { + topErrorWindowHandle = windowHandle; } } - if (window->visible) { - if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) { - isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE - | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0; - if (isTouchModal || window->touchableRegionContainsPoint(x, y)) { - if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) { - newTouchedWindow = window; + if (windowHandle->visible) { + if (! (flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) { + isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE + | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0; + if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) { + if (! screenWasOff + || (flags & InputWindowHandle::FLAG_TOUCHABLE_WHEN_WAKING)) { + newTouchedWindowHandle = windowHandle; } break; // found touched window, exit window loop } } if (maskedAction == AMOTION_EVENT_ACTION_DOWN - && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) { + && (flags & InputWindowHandle::FLAG_WATCH_OUTSIDE_TOUCH)) { int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE; - if (isWindowObscuredAtPointLocked(window, x, y)) { + if (isWindowObscuredAtPointLocked(windowHandle, x, y)) { outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; } - mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0)); + mTempTouchState.addOrUpdateWindow( + windowHandle, outsideTargetFlags, BitSet32(0)); } } } @@ -1322,7 +1323,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // If there is an error window but it is not taking focus (typically because // it is invisible) then wait for it. Any other focused window may in // fact be in ANR state. - if (topErrorWindow && newTouchedWindow != topErrorWindow) { + if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) { #if DEBUG_FOCUS LOGD("Waiting because system error window is pending."); #endif @@ -1333,26 +1334,26 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } // Figure out whether splitting will be allowed for this window. - if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) { + if (newTouchedWindowHandle != NULL && newTouchedWindowHandle->supportsSplitTouch()) { // New window supports splitting. isSplit = true; } else if (isSplit) { // New window does not support splitting but we have already split events. // Assign the pointer to the first foreground window we find. // (May be NULL which is why we put this code block before the next check.) - newTouchedWindow = mTempTouchState.getFirstForegroundWindow(); + newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle(); } // If we did not find a touched window then fail. - if (! newTouchedWindow) { - if (mFocusedApplication) { + if (newTouchedWindowHandle == NULL) { + if (mFocusedApplicationHandle != NULL) { #if DEBUG_FOCUS LOGD("Waiting because there is no touched window but there is a " "focused application that may eventually add a new window: %s.", - getApplicationWindowLabelLocked(mFocusedApplication, NULL).string()); + getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string()); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - mFocusedApplication, NULL, nextWakeupTime); + mFocusedApplicationHandle, NULL, nextWakeupTime); goto Unresponsive; } @@ -1366,20 +1367,20 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, if (isSplit) { targetFlags |= InputTarget::FLAG_SPLIT; } - if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) { + if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) { targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; } // Update hover state. if (isHoverAction) { - newHoverWindow = newTouchedWindow; + newHoverWindowHandle = newTouchedWindowHandle; // Ensure all subsequent motion samples are also within the touched window. // Set *outSplitBatchAfterSample to the sample before the first one that is not // within the touched window. if (!isTouchModal) { while (sample->next) { - if (!newHoverWindow->touchableRegionContainsPoint( + if (!newHoverWindowHandle->touchableRegionContainsPoint( sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y))) { *outSplitBatchAfterSample = sample; @@ -1389,7 +1390,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } } } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) { - newHoverWindow = mLastHoverWindow; + newHoverWindowHandle = mLastHoverWindowHandle; } // Update the temporary touch state. @@ -1398,7 +1399,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, uint32_t pointerId = entry->pointerProperties[pointerIndex].id; pointerIds.markBit(pointerId); } - mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds); + mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); } else { /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */ @@ -1420,19 +1421,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, int32_t x = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); - const InputWindow* oldTouchedWindow = mTempTouchState.getFirstForegroundWindow(); - const InputWindow* newTouchedWindow = findTouchedWindowAtLocked(x, y); - if (oldTouchedWindow != newTouchedWindow && newTouchedWindow) { + sp oldTouchedWindowHandle = + mTempTouchState.getFirstForegroundWindowHandle(); + sp newTouchedWindowHandle = findTouchedWindowAtLocked(x, y); + if (oldTouchedWindowHandle != newTouchedWindowHandle + && newTouchedWindowHandle != NULL) { #if DEBUG_FOCUS LOGD("Touch is slipping out of window %s into window %s.", - oldTouchedWindow->name.string(), newTouchedWindow->name.string()); + oldTouchedWindowHandle->name.string(), + newTouchedWindowHandle->name.string()); #endif // Make a slippery exit from the old window. - mTempTouchState.addOrUpdateWindow(oldTouchedWindow, + mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0)); // Make a slippery entrance into the new window. - if (newTouchedWindow->supportsSplitTouch()) { + if (newTouchedWindowHandle->supportsSplitTouch()) { isSplit = true; } @@ -1441,7 +1445,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, if (isSplit) { targetFlags |= InputTarget::FLAG_SPLIT; } - if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) { + if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) { targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; } @@ -1449,7 +1453,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, if (isSplit) { pointerIds.markBit(entry->pointerProperties[0].id); } - mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds); + mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); // Split the batch here so we send exactly one sample. *outSplitBatchAfterSample = &entry->firstSample; @@ -1457,25 +1461,25 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } } - if (newHoverWindow != mLastHoverWindow) { + if (newHoverWindowHandle != mLastHoverWindowHandle) { // Split the batch here so we send exactly one sample as part of ENTER or EXIT. *outSplitBatchAfterSample = &entry->firstSample; // Let the previous window know that the hover sequence is over. - if (mLastHoverWindow) { + if (mLastHoverWindowHandle != NULL) { #if DEBUG_HOVER - LOGD("Sending hover exit event to window %s.", mLastHoverWindow->name.string()); + LOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->name.string()); #endif - mTempTouchState.addOrUpdateWindow(mLastHoverWindow, + mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle, InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0)); } // Let the new window know that the hover sequence is starting. - if (newHoverWindow) { + if (newHoverWindowHandle != NULL) { #if DEBUG_HOVER - LOGD("Sending hover enter event to window %s.", newHoverWindow->name.string()); + LOGD("Sending hover enter event to window %s.", newHoverWindowHandle->name.string()); #endif - mTempTouchState.addOrUpdateWindow(newHoverWindow, + mTempTouchState.addOrUpdateWindow(newHoverWindowHandle, InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0)); } } @@ -1488,7 +1492,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { haveForegroundWindow = true; - if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) { + if (! checkInjectionPermission(touchedWindow.windowHandle, + entry->injectionState)) { injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; goto Failed; @@ -1510,14 +1515,15 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // Check whether windows listening for outside touches are owned by the same UID. If it is // set the policy flag that we will not reveal coordinate information to this window. if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { - const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow(); - const int32_t foregroundWindowUid = foregroundWindow->ownerUid; + sp foregroundWindowHandle = + mTempTouchState.getFirstForegroundWindowHandle(); + const int32_t foregroundWindowUid = foregroundWindowHandle->ownerUid; for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { - const InputWindow* inputWindow = touchedWindow.window; - if (inputWindow->ownerUid != foregroundWindowUid) { - mTempTouchState.addOrUpdateWindow(inputWindow, + sp inputWindowHandle = touchedWindow.windowHandle; + if (inputWindowHandle->ownerUid != foregroundWindowUid) { + mTempTouchState.addOrUpdateWindow(inputWindowHandle, InputTarget::FLAG_ZERO_COORDS, BitSet32(0)); } } @@ -1529,22 +1535,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { // If the touched window is paused then keep waiting. - if (touchedWindow.window->paused) { + if (touchedWindow.windowHandle->paused) { #if DEBUG_FOCUS LOGD("Waiting because touched window is paused."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - NULL, touchedWindow.window, nextWakeupTime); + NULL, touchedWindow.windowHandle, nextWakeupTime); goto Unresponsive; } // If the touched window is still working on previous events then keep waiting. - if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) { + if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.windowHandle)) { #if DEBUG_FOCUS LOGD("Waiting because touched window still processing previous input."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - NULL, touchedWindow.window, nextWakeupTime); + NULL, touchedWindow.windowHandle, nextWakeupTime); goto Unresponsive; } } @@ -1557,12 +1563,13 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, // engine only supports touch events. We would need to add a mechanism similar // to View.onGenericMotionEvent to enable wallpapers to handle these events. if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { - const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow(); - if (foregroundWindow->hasWallpaper) { - for (size_t i = 0; i < mWindows.size(); i++) { - const InputWindow* window = & mWindows[i]; - if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) { - mTempTouchState.addOrUpdateWindow(window, + sp foregroundWindowHandle = + mTempTouchState.getFirstForegroundWindowHandle(); + if (foregroundWindowHandle->hasWallpaper) { + for (size_t i = 0; i < mWindowHandles.size(); i++) { + sp windowHandle = mWindowHandles.itemAt(i); + if (windowHandle->layoutParamsType == InputWindowHandle::TYPE_WALLPAPER) { + mTempTouchState.addOrUpdateWindow(windowHandle, InputTarget::FLAG_WINDOW_IS_OBSCURED | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0)); @@ -1576,7 +1583,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i); - addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags, + addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags, touchedWindow.pointerIds); } @@ -1658,7 +1665,7 @@ Failed: } // Update hover state. - mLastHoverWindow = newHoverWindow; + mLastHoverWindowHandle = newHoverWindowHandle; } } else { #if DEBUG_FOCUS @@ -1681,16 +1688,16 @@ Unresponsive: return injectionResult; } -void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags, - BitSet32 pointerIds) { +void InputDispatcher::addWindowTargetLocked(const sp& windowHandle, + int32_t targetFlags, BitSet32 pointerIds) { mCurrentInputTargets.push(); InputTarget& target = mCurrentInputTargets.editTop(); - target.inputChannel = window->inputChannel; + target.inputChannel = windowHandle->inputChannel; target.flags = targetFlags; - target.xOffset = - window->frameLeft; - target.yOffset = - window->frameTop; - target.scaleFactor = window->scaleFactor; + target.xOffset = - windowHandle->frameLeft; + target.yOffset = - windowHandle->frameTop; + target.scaleFactor = windowHandle->scaleFactor; target.pointerIds = pointerIds; } @@ -1708,17 +1715,17 @@ void InputDispatcher::addMonitoringTargetsLocked() { } } -bool InputDispatcher::checkInjectionPermission(const InputWindow* window, +bool InputDispatcher::checkInjectionPermission(const sp& windowHandle, const InjectionState* injectionState) { if (injectionState - && (window == NULL || window->ownerUid != injectionState->injectorUid) + && (windowHandle == NULL || windowHandle->ownerUid != injectionState->injectorUid) && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) { - if (window) { - LOGW("Permission denied: injecting event from pid %d uid %d to window " - "with input channel %s owned by uid %d", + if (windowHandle != NULL) { + LOGW("Permission denied: injecting event from pid %d uid %d to window %s " + "owned by uid %d", injectionState->injectorPid, injectionState->injectorUid, - window->inputChannel->getName().string(), - window->ownerUid); + windowHandle->name.string(), + windowHandle->ownerUid); } else { LOGW("Permission denied: injecting event from pid %d uid %d", injectionState->injectorPid, injectionState->injectorUid); @@ -1729,22 +1736,24 @@ bool InputDispatcher::checkInjectionPermission(const InputWindow* window, } bool InputDispatcher::isWindowObscuredAtPointLocked( - const InputWindow* window, int32_t x, int32_t y) const { - size_t numWindows = mWindows.size(); + const sp& windowHandle, int32_t x, int32_t y) const { + size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { - const InputWindow* other = & mWindows.itemAt(i); - if (other == window) { + sp otherHandle = mWindowHandles.itemAt(i); + if (otherHandle == windowHandle) { break; } - if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) { + if (otherHandle->visible && ! otherHandle->isTrustedOverlay() + && otherHandle->frameContainsPoint(x, y)) { return true; } } return false; } -bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) { - ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel); +bool InputDispatcher::isWindowFinishedWithPreviousInputLocked( + const sp& windowHandle) { + ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->inputChannel); if (connectionIndex >= 0) { sp connection = mConnectionsByReceiveFd.valueAt(connectionIndex); return connection->outboundQueue.isEmpty(); @@ -1753,19 +1762,20 @@ bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* } } -String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application, - const InputWindow* window) { - if (application) { - if (window) { - String8 label(application->name); +String8 InputDispatcher::getApplicationWindowLabelLocked( + const sp& applicationHandle, + const sp& windowHandle) { + if (applicationHandle != NULL) { + if (windowHandle != NULL) { + String8 label(applicationHandle->name); label.append(" - "); - label.append(window->name); + label.append(windowHandle->name); return label; } else { - return application->name; + return applicationHandle->name; } - } else if (window) { - return window->name; + } else if (windowHandle != NULL) { + return windowHandle->name; } else { return String8(""); } @@ -2422,11 +2432,11 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( } InputTarget target; - const InputWindow* window = getWindowLocked(connection->inputChannel); - if (window) { - target.xOffset = -window->frameLeft; - target.yOffset = -window->frameTop; - target.scaleFactor = window->scaleFactor; + sp windowHandle = getWindowHandleLocked(connection->inputChannel); + if (windowHandle != NULL) { + target.xOffset = -windowHandle->frameLeft; + target.yOffset = -windowHandle->frameTop; + target.scaleFactor = windowHandle->scaleFactor; } else { target.xOffset = 0; target.yOffset = 0; @@ -2809,7 +2819,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t } if (action == AMOTION_EVENT_ACTION_HOVER_MOVE) { - if (!mLastHoverWindow) { + if (mLastHoverWindowHandle == NULL) { #if DEBUG_BATCHING LOGD("Not streaming hover move because there is no " "last hovered window."); @@ -2817,15 +2827,16 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t goto NoBatchingOrStreaming; } - const InputWindow* hoverWindow = findTouchedWindowAtLocked( + sp hoverWindowHandle = findTouchedWindowAtLocked( pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); - if (mLastHoverWindow != hoverWindow) { + if (mLastHoverWindowHandle != hoverWindowHandle) { #if DEBUG_BATCHING LOGD("Not streaming hover move because the last hovered window " "is '%s' but the currently hovered window is '%s'.", - mLastHoverWindow->name.string(), - hoverWindow ? hoverWindow->name.string() : ""); + mLastHoverWindowHandle->name.string(), + hoverWindowHandle != NULL + ? hoverWindowHandle->name.string() : ""); #endif goto NoBatchingOrStreaming; } @@ -3125,113 +3136,109 @@ void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* ent } } -const InputWindow* InputDispatcher::getWindowLocked(const sp& inputChannel) { - for (size_t i = 0; i < mWindows.size(); i++) { - const InputWindow* window = & mWindows[i]; - if (window->inputChannel == inputChannel) { - return window; +sp InputDispatcher::getWindowHandleLocked( + const sp& inputChannel) const { + size_t numWindows = mWindowHandles.size(); + for (size_t i = 0; i < numWindows; i++) { + const sp& windowHandle = mWindowHandles.itemAt(i); + if (windowHandle->inputChannel == inputChannel) { + return windowHandle; } } return NULL; } -void InputDispatcher::setInputWindows(const Vector& inputWindows) { +bool InputDispatcher::hasWindowHandleLocked( + const sp& windowHandle) const { + size_t numWindows = mWindowHandles.size(); + for (size_t i = 0; i < numWindows; i++) { + if (mWindowHandles.itemAt(i) == windowHandle) { + return true; + } + } + return false; +} + +void InputDispatcher::setInputWindows(const Vector >& inputWindowHandles) { #if DEBUG_FOCUS LOGD("setInputWindows"); #endif { // acquire lock AutoMutex _l(mLock); - // Clear old window pointers. - sp oldFocusedWindowChannel; - if (mFocusedWindow) { - oldFocusedWindowChannel = mFocusedWindow->inputChannel; - mFocusedWindow = NULL; - } - sp oldLastHoverWindowChannel; - if (mLastHoverWindow) { - oldLastHoverWindowChannel = mLastHoverWindow->inputChannel; - mLastHoverWindow = NULL; - } + mWindowHandles = inputWindowHandles; - mWindows.clear(); - - // Loop over new windows and rebuild the necessary window pointers for - // tracking focus and touch. - mWindows.appendVector(inputWindows); - - size_t numWindows = mWindows.size(); - for (size_t i = 0; i < numWindows; i++) { - const InputWindow* window = & mWindows.itemAt(i); - if (window->hasFocus) { - mFocusedWindow = window; - break; + sp newFocusedWindowHandle; + bool foundHoveredWindow = false; + for (size_t i = 0; i < mWindowHandles.size(); i++) { + const sp& windowHandle = mWindowHandles.itemAt(i); + if (!windowHandle->update() || windowHandle->inputChannel == NULL) { + mWindowHandles.removeAt(i--); + continue; + } + if (windowHandle->hasFocus) { + newFocusedWindowHandle = windowHandle; + } + if (windowHandle == mLastHoverWindowHandle) { + foundHoveredWindow = true; } } - if (oldFocusedWindowChannel != NULL) { - if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) { + if (!foundHoveredWindow) { + mLastHoverWindowHandle = NULL; + } + + if (mFocusedWindowHandle != newFocusedWindowHandle) { + if (mFocusedWindowHandle != NULL) { #if DEBUG_FOCUS LOGD("Focus left window: %s", - oldFocusedWindowChannel->getName().string()); + mFocusedWindowHandle->name.string()); #endif CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, "focus left window"); - synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel, options); - oldFocusedWindowChannel.clear(); + synthesizeCancelationEventsForInputChannelLocked( + mFocusedWindowHandle->inputChannel, options); } - } - if (mFocusedWindow && oldFocusedWindowChannel == NULL) { + if (newFocusedWindowHandle != NULL) { #if DEBUG_FOCUS - LOGD("Focus entered window: %s", - mFocusedWindow->inputChannel->getName().string()); + LOGD("Focus entered window: %s", + newFocusedWindowHandle->name.string()); #endif + } + mFocusedWindowHandle = newFocusedWindowHandle; } - for (size_t i = 0; i < mTouchState.windows.size(); ) { + for (size_t i = 0; i < mTouchState.windows.size(); i++) { TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i); - const InputWindow* window = getWindowLocked(touchedWindow.channel); - if (window) { - touchedWindow.window = window; - i += 1; - } else { + if (!hasWindowHandleLocked(touchedWindow.windowHandle)) { #if DEBUG_FOCUS - LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string()); + LOGD("Touched window was removed: %s", touchedWindow.windowHandle->name.string()); #endif CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "touched window was removed"); - synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel, options); - mTouchState.windows.removeAt(i); + synthesizeCancelationEventsForInputChannelLocked( + touchedWindow.windowHandle->inputChannel, options); + mTouchState.windows.removeAt(i--); } } - - // Recover the last hovered window. - if (oldLastHoverWindowChannel != NULL) { - mLastHoverWindow = getWindowLocked(oldLastHoverWindowChannel); - oldLastHoverWindowChannel.clear(); - } - -#if DEBUG_FOCUS - //logDispatchStateLocked(); -#endif } // release lock // Wake up poll loop since it may need to make new input dispatching choices. mLooper->wake(); } -void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) { +void InputDispatcher::setFocusedApplication( + const sp& inputApplicationHandle) { #if DEBUG_FOCUS LOGD("setFocusedApplication"); #endif { // acquire lock AutoMutex _l(mLock); - releaseFocusedApplicationLocked(); - - if (inputApplication) { - mFocusedApplicationStorage = *inputApplication; - mFocusedApplication = & mFocusedApplicationStorage; + if (inputApplicationHandle != NULL && inputApplicationHandle->update()) { + mFocusedApplicationHandle = inputApplicationHandle; + } else { + mFocusedApplicationHandle.clear(); } #if DEBUG_FOCUS @@ -3243,13 +3250,6 @@ void InputDispatcher::setFocusedApplication(const InputApplication* inputApplica mLooper->wake(); } -void InputDispatcher::releaseFocusedApplicationLocked() { - if (mFocusedApplication) { - mFocusedApplication = NULL; - mFocusedApplicationStorage.inputApplicationHandle.clear(); - } -} - void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) { #if DEBUG_FOCUS LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen); @@ -3315,15 +3315,15 @@ bool InputDispatcher::transferTouchFocus(const sp& fromChannel, { // acquire lock AutoMutex _l(mLock); - const InputWindow* fromWindow = getWindowLocked(fromChannel); - const InputWindow* toWindow = getWindowLocked(toChannel); - if (! fromWindow || ! toWindow) { + sp fromWindowHandle = getWindowHandleLocked(fromChannel); + sp toWindowHandle = getWindowHandleLocked(toChannel); + if (fromWindowHandle == NULL || toWindowHandle == NULL) { #if DEBUG_FOCUS LOGD("Cannot transfer focus because from or to window not found."); #endif return false; } - if (fromWindow == toWindow) { + if (fromWindowHandle == toWindowHandle) { #if DEBUG_FOCUS LOGD("Trivial transfer to same window."); #endif @@ -3333,7 +3333,7 @@ bool InputDispatcher::transferTouchFocus(const sp& fromChannel, bool found = false; for (size_t i = 0; i < mTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTouchState.windows[i]; - if (touchedWindow.window == fromWindow) { + if (touchedWindow.windowHandle == fromWindowHandle) { int32_t oldTargetFlags = touchedWindow.targetFlags; BitSet32 pointerIds = touchedWindow.pointerIds; @@ -3342,7 +3342,7 @@ bool InputDispatcher::transferTouchFocus(const sp& fromChannel, int32_t newTargetFlags = oldTargetFlags & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS); - mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds); + mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); found = true; break; @@ -3392,7 +3392,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { resetTargetsLocked(); mTouchState.reset(); - mLastHoverWindow = NULL; + mLastHoverWindowHandle.clear(); } void InputDispatcher::logDispatchStateLocked() { @@ -3415,15 +3415,15 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled); dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen); - if (mFocusedApplication) { + if (mFocusedApplicationHandle != NULL) { dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n", - mFocusedApplication->name.string(), - mFocusedApplication->dispatchingTimeout / 1000000.0); + mFocusedApplicationHandle->name.string(), + mFocusedApplicationHandle->dispatchingTimeout / 1000000.0); } else { dump.append(INDENT "FocusedApplication: \n"); } dump.appendFormat(INDENT "FocusedWindow: name='%s'\n", - mFocusedWindow != NULL ? mFocusedWindow->name.string() : ""); + mFocusedWindowHandle != NULL ? mFocusedWindowHandle->name.string() : ""); dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down)); dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split)); @@ -3434,37 +3434,37 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { for (size_t i = 0; i < mTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTouchState.windows[i]; dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n", - i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value, + i, touchedWindow.windowHandle->name.string(), touchedWindow.pointerIds.value, touchedWindow.targetFlags); } } else { dump.append(INDENT "TouchedWindows: \n"); } - if (!mWindows.isEmpty()) { + if (!mWindowHandles.isEmpty()) { dump.append(INDENT "Windows:\n"); - for (size_t i = 0; i < mWindows.size(); i++) { - const InputWindow& window = mWindows[i]; + for (size_t i = 0; i < mWindowHandles.size(); i++) { + const sp& windowHandle = mWindowHandles.itemAt(i); dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, " "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, " "frame=[%d,%d][%d,%d], scale=%f, " "touchableRegion=", - i, window.name.string(), - toString(window.paused), - toString(window.hasFocus), - toString(window.hasWallpaper), - toString(window.visible), - toString(window.canReceiveKeys), - window.layoutParamsFlags, window.layoutParamsType, - window.layer, - window.frameLeft, window.frameTop, - window.frameRight, window.frameBottom, - window.scaleFactor); - dumpRegion(dump, window.touchableRegion); - dump.appendFormat(", inputFeatures=0x%08x", window.inputFeatures); + i, windowHandle->name.string(), + toString(windowHandle->paused), + toString(windowHandle->hasFocus), + toString(windowHandle->hasWallpaper), + toString(windowHandle->visible), + toString(windowHandle->canReceiveKeys), + windowHandle->layoutParamsFlags, windowHandle->layoutParamsType, + windowHandle->layer, + windowHandle->frameLeft, windowHandle->frameTop, + windowHandle->frameRight, windowHandle->frameBottom, + windowHandle->scaleFactor); + dumpRegion(dump, windowHandle->touchableRegion); + dump.appendFormat(", inputFeatures=0x%08x", windowHandle->inputFeatures); dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", - window.ownerPid, window.ownerUid, - window.dispatchingTimeout / 1000000.0); + windowHandle->ownerPid, windowHandle->ownerUid, + windowHandle->dispatchingTimeout / 1000000.0); } } else { dump.append(INDENT "Windows: \n"); @@ -3636,23 +3636,19 @@ void InputDispatcher::onDispatchCycleBrokenLocked( } void InputDispatcher::onANRLocked( - nsecs_t currentTime, const InputApplication* application, const InputWindow* window, + nsecs_t currentTime, const sp& applicationHandle, + const sp& windowHandle, nsecs_t eventTime, nsecs_t waitStartTime) { LOGI("Application is not responding: %s. " "%01.1fms since event, %01.1fms since wait started", - getApplicationWindowLabelLocked(application, window).string(), + getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(), (currentTime - eventTime) / 1000000.0, (currentTime - waitStartTime) / 1000000.0); CommandEntry* commandEntry = postCommandLocked( & InputDispatcher::doNotifyANRLockedInterruptible); - if (application) { - commandEntry->inputApplicationHandle = application->inputApplicationHandle; - } - if (window) { - commandEntry->inputWindowHandle = window->inputWindowHandle; - commandEntry->inputChannel = window->inputChannel; - } + commandEntry->inputApplicationHandle = applicationHandle; + commandEntry->inputWindowHandle = windowHandle; } void InputDispatcher::doNotifyConfigurationChangedInterruptible( @@ -3686,7 +3682,9 @@ void InputDispatcher::doNotifyANRLockedInterruptible( mLock.lock(); - resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel); + resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, + commandEntry->inputWindowHandle != NULL + ? commandEntry->inputWindowHandle->inputChannel : NULL); } void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( @@ -4560,11 +4558,10 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) { split = other.split; deviceId = other.deviceId; source = other.source; - windows.clear(); - windows.appendVector(other.windows); + windows = other.windows; } -void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window, +void InputDispatcher::TouchState::addOrUpdateWindow(const sp& windowHandle, int32_t targetFlags, BitSet32 pointerIds) { if (targetFlags & InputTarget::FLAG_SPLIT) { split = true; @@ -4572,7 +4569,7 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window, for (size_t i = 0; i < windows.size(); i++) { TouchedWindow& touchedWindow = windows.editItemAt(i); - if (touchedWindow.window == window) { + if (touchedWindow.windowHandle == windowHandle) { touchedWindow.targetFlags |= targetFlags; if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) { touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS; @@ -4585,10 +4582,9 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window, windows.push(); TouchedWindow& touchedWindow = windows.editTop(); - touchedWindow.window = window; + touchedWindow.windowHandle = windowHandle; touchedWindow.targetFlags = targetFlags; touchedWindow.pointerIds = pointerIds; - touchedWindow.channel = window->inputChannel; } void InputDispatcher::TouchState::filterNonAsIsTouchWindows() { @@ -4605,11 +4601,11 @@ void InputDispatcher::TouchState::filterNonAsIsTouchWindows() { } } -const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() const { +sp InputDispatcher::TouchState::getFirstForegroundWindowHandle() const { for (size_t i = 0; i < windows.size(); i++) { const TouchedWindow& window = windows.itemAt(i); if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { - return window.window; + return window.windowHandle; } } return NULL; @@ -4621,8 +4617,8 @@ bool InputDispatcher::TouchState::isSlippery() const { for (size_t i = 0; i < windows.size(); i++) { const TouchedWindow& window = windows.itemAt(i); if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { - if (haveSlipperyForegroundWindow - || !(window.window->layoutParamsFlags & InputWindow::FLAG_SLIPPERY)) { + if (haveSlipperyForegroundWindow || !(window.windowHandle->layoutParamsFlags + & InputWindowHandle::FLAG_SLIPPERY)) { return false; } haveSlipperyForegroundWindow = true; diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index bdd1922b9339f..15fd274f5e50f 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -321,13 +321,14 @@ public: * * This method may be called on any thread (usually by the input manager). */ - virtual void setInputWindows(const Vector& inputWindows) = 0; + virtual void setInputWindows(const Vector >& inputWindowHandles) = 0; /* Sets the focused application. * * This method may be called on any thread (usually by the input manager). */ - virtual void setFocusedApplication(const InputApplication* inputApplication) = 0; + virtual void setFocusedApplication( + const sp& inputApplicationHandle) = 0; /* Sets the input dispatching mode. * @@ -406,8 +407,8 @@ public: int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags); - virtual void setInputWindows(const Vector& inputWindows); - virtual void setFocusedApplication(const InputApplication* inputApplication); + virtual void setInputWindows(const Vector >& inputWindowHandles); + virtual void setFocusedApplication(const sp& inputApplicationHandle); virtual void setInputDispatchMode(bool enabled, bool frozen); virtual void setInputFilterEnabled(bool enabled); @@ -578,7 +579,6 @@ private: sp connection; nsecs_t eventTime; KeyEntry* keyEntry; - sp inputChannel; sp inputApplicationHandle; sp inputWindowHandle; int32_t userActivityEventType; @@ -894,7 +894,7 @@ private: // to transfer focus to a new application. EventEntry* mNextUnblockedEvent; - const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y); + sp findTouchedWindowAtLocked(int32_t x, int32_t y); // All registered connections mapped by receive pipe file descriptor. KeyedVector > mConnectionsByReceiveFd; @@ -953,19 +953,19 @@ private: bool mDispatchFrozen; bool mInputFilterEnabled; - Vector mWindows; + Vector > mWindowHandles; - const InputWindow* getWindowLocked(const sp& inputChannel); + sp getWindowHandleLocked(const sp& inputChannel) const; + bool hasWindowHandleLocked(const sp& windowHandle) const; // Focus tracking for keys, trackball, etc. - const InputWindow* mFocusedWindow; + sp mFocusedWindowHandle; // Focus tracking for touch. struct TouchedWindow { - const InputWindow* window; + sp windowHandle; int32_t targetFlags; BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set - sp channel; }; struct TouchState { bool down; @@ -978,9 +978,10 @@ private: ~TouchState(); void reset(); void copyFrom(const TouchState& other); - void addOrUpdateWindow(const InputWindow* window,int32_t targetFlags, BitSet32 pointerIds); + void addOrUpdateWindow(const sp& windowHandle, + int32_t targetFlags, BitSet32 pointerIds); void filterNonAsIsTouchWindows(); - const InputWindow* getFirstForegroundWindow() const; + sp getFirstForegroundWindowHandle() const; bool isSlippery() const; }; @@ -988,9 +989,7 @@ private: TouchState mTempTouchState; // Focused application. - InputApplication* mFocusedApplication; - InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication - void releaseFocusedApplicationLocked(); + sp mFocusedApplicationHandle; // Dispatch inbound events. bool dispatchConfigurationChangedLocked( @@ -1021,16 +1020,17 @@ private: nsecs_t mInputTargetWaitStartTime; nsecs_t mInputTargetWaitTimeoutTime; bool mInputTargetWaitTimeoutExpired; - sp mInputTargetWaitApplication; + sp mInputTargetWaitApplicationHandle; // Contains the last window which received a hover event. - const InputWindow* mLastHoverWindow; + sp mLastHoverWindowHandle; // Finding targets for input events. void resetTargetsLocked(); void commitTargetsLocked(); int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry, - const InputApplication* application, const InputWindow* window, + const sp& applicationHandle, + const sp& windowHandle, nsecs_t* nextWakeupTime); void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout, const sp& inputChannel); @@ -1043,15 +1043,17 @@ private: nsecs_t* nextWakeupTime, bool* outConflictingPointerActions, const MotionSample** outSplitBatchAfterSample); - void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags, - BitSet32 pointerIds); + void addWindowTargetLocked(const sp& windowHandle, + int32_t targetFlags, BitSet32 pointerIds); void addMonitoringTargetsLocked(); void pokeUserActivityLocked(const EventEntry* eventEntry); - bool checkInjectionPermission(const InputWindow* window, const InjectionState* injectionState); - bool isWindowObscuredAtPointLocked(const InputWindow* window, int32_t x, int32_t y) const; - bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window); - String8 getApplicationWindowLabelLocked(const InputApplication* application, - const InputWindow* window); + bool checkInjectionPermission(const sp& windowHandle, + const InjectionState* injectionState); + bool isWindowObscuredAtPointLocked(const sp& windowHandle, + int32_t x, int32_t y) const; + bool isWindowFinishedWithPreviousInputLocked(const sp& windowHandle); + String8 getApplicationWindowLabelLocked(const sp& applicationHandle, + const sp& windowHandle); // Manage the dispatch cycle for a single connection. // These methods are deliberately not Interruptible because doing all of the work @@ -1100,7 +1102,8 @@ private: void onDispatchCycleBrokenLocked( nsecs_t currentTime, const sp& connection); void onANRLocked( - nsecs_t currentTime, const InputApplication* application, const InputWindow* window, + nsecs_t currentTime, const sp& applicationHandle, + const sp& windowHandle, nsecs_t eventTime, nsecs_t waitStartTime); // Outbound policy interactions. diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp index b552f6d5b43d5..0ce8867381080 100644 --- a/services/input/InputWindow.cpp +++ b/services/input/InputWindow.cpp @@ -22,25 +22,25 @@ namespace android { -// --- InputWindow --- +// --- InputWindowHandle --- -bool InputWindow::touchableRegionContainsPoint(int32_t x, int32_t y) const { +bool InputWindowHandle::touchableRegionContainsPoint(int32_t x, int32_t y) const { return touchableRegion.contains(x, y); } -bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const { +bool InputWindowHandle::frameContainsPoint(int32_t x, int32_t y) const { return x >= frameLeft && x <= frameRight && y >= frameTop && y <= frameBottom; } -bool InputWindow::isTrustedOverlay() const { +bool InputWindowHandle::isTrustedOverlay() const { return layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY; } -bool InputWindow::supportsSplitTouch() const { - return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH; +bool InputWindowHandle::supportsSplitTouch() const { + return layoutParamsFlags & FLAG_SPLIT_TOUCH; } } // namespace android diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h index d166ad4f679ec..272081c4a04c6 100644 --- a/services/input/InputWindow.h +++ b/services/input/InputWindow.h @@ -31,29 +31,14 @@ namespace android { /* * A handle to a window that can receive input. + * * Used by the native input dispatcher to indirectly refer to the window manager objects * that describe a window. */ class InputWindowHandle : public RefBase { -protected: - InputWindowHandle(const sp& inputApplicationHandle) : - mInputApplicationHandle(inputApplicationHandle) { } - virtual ~InputWindowHandle() { } - public: - inline sp getInputApplicationHandle() { - return mInputApplicationHandle; - } + const sp inputApplicationHandle; -private: - sp mInputApplicationHandle; -}; - - -/* - * An input window describes the bounds of a window that can receive input. - */ -struct InputWindow { // Window flags from WindowManager.LayoutParams enum { FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, @@ -164,6 +149,22 @@ struct InputWindow { bool isTrustedOverlay() const; bool supportsSplitTouch() const; + + /** + * Requests that the state of this object be updated to reflect + * the most current available information about the application. + * + * This method should only be called from within the input dispatcher's + * critical section. + * + * Returns true on success, or false if the handle is no longer valid. + */ + virtual bool update() = 0; + +protected: + InputWindowHandle(const sp& inputApplicationHandle) : + inputApplicationHandle(inputApplicationHandle) { } + virtual ~InputWindowHandle() { } }; } // namespace android diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 67067de2c1ce1..131894af1b64e 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -369,11 +369,12 @@ private: return INPUT_EVENT_INJECTION_FAILED; } - virtual void setInputWindows(const Vector& inputWindows) { + virtual void setInputWindows(const Vector >& inputWindowHandles) { ADD_FAILURE() << "Should never be called by input reader."; } - virtual void setFocusedApplication(const InputApplication* inputApplication) { + virtual void setFocusedApplication( + const sp& inputApplicationHandle) { ADD_FAILURE() << "Should never be called by input reader."; } diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java index d3d9df4359d54..bfa2b3995ba81 100644 --- a/services/java/com/android/server/wm/AppWindowToken.java +++ b/services/java/com/android/server/wm/AppWindowToken.java @@ -101,7 +101,7 @@ class AppWindowToken extends WindowToken { boolean firstWindowDrawn; // Input application handle used by the input dispatcher. - InputApplicationHandle mInputApplicationHandle; + final InputApplicationHandle mInputApplicationHandle; AppWindowToken(WindowManagerService _service, IApplicationToken _token) { super(_service, _token.asBinder(), diff --git a/services/java/com/android/server/wm/InputApplication.java b/services/java/com/android/server/wm/InputApplication.java deleted file mode 100644 index e04fd31a3ffcb..0000000000000 --- a/services/java/com/android/server/wm/InputApplication.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - - -/** - * Describes input-related application properties for use by the input dispatcher. - * @hide - */ -public final class InputApplication { - // Application handle. - public InputApplicationHandle inputApplicationHandle; - - // Application name. - public String name; - - // Dispatching timeout. - public long dispatchingTimeoutNanos; - - public void recycle() { - inputApplicationHandle = null; - } -} diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/wm/InputApplicationHandle.java index 64c8e7ed73dbe..d78b1d9692cdf 100644 --- a/services/java/com/android/server/wm/InputApplicationHandle.java +++ b/services/java/com/android/server/wm/InputApplicationHandle.java @@ -32,6 +32,12 @@ public final class InputApplicationHandle { // The window manager's application window token. public final AppWindowToken appWindowToken; + // Application name. + public String name; + + // Dispatching timeout. + public long dispatchingTimeoutNanos; + private native void nativeDispose(); public InputApplicationHandle(AppWindowToken appWindowToken) { diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java index 65007f972ad52..3133a19f9c511 100644 --- a/services/java/com/android/server/wm/InputManager.java +++ b/services/java/com/android/server/wm/InputManager.java @@ -25,7 +25,6 @@ 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; @@ -83,10 +82,10 @@ public class InputManager { private static native int nativeInjectInputEvent(InputEvent event, int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int policyFlags); - private static native void nativeSetInputWindows(InputWindow[] windows); + private static native void nativeSetInputWindows(InputWindowHandle[] windowHandles); private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen); private static native void nativeSetSystemUiVisibility(int visibility); - private static native void nativeSetFocusedApplication(InputApplication application); + private static native void nativeSetFocusedApplication(InputApplicationHandle application); private static native InputDevice nativeGetInputDevice(int deviceId); private static native void nativeGetInputConfiguration(Configuration configuration); private static native int[] nativeGetInputDeviceIds(); @@ -372,11 +371,11 @@ public class InputManager { return nativeGetInputDeviceIds(); } - public void setInputWindows(InputWindow[] windows) { - nativeSetInputWindows(windows); + public void setInputWindows(InputWindowHandle[] windowHandles) { + nativeSetInputWindows(windowHandles); } - public void setFocusedApplication(InputApplication application) { + public void setFocusedApplication(InputApplicationHandle application) { nativeSetFocusedApplication(application); } diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 68066344586a5..08a3560338151 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -17,7 +17,6 @@ package com.android.server.wm; import android.graphics.Rect; -import android.os.Binder; import android.os.Process; import android.os.RemoteException; import android.util.Log; @@ -26,6 +25,7 @@ import android.view.KeyEvent; import android.view.WindowManager; import java.util.ArrayList; +import java.util.Arrays; final class InputMonitor { private final WindowManagerService mService; @@ -42,12 +42,14 @@ final class InputMonitor { // When true, need to call updateInputWindowsLw(). private boolean mUpdateInputWindowsNeeded = true; - // Temporary list of windows information to provide to the input dispatcher. - private InputWindowList mTempInputWindows = new InputWindowList(); - - // Temporary input application object to provide to the input dispatcher. - private InputApplication mTempInputApplication = new InputApplication(); - + // Fake handles for the drag surface, lazily initialized. + private InputApplicationHandle mDragApplicationHandle; + private InputWindowHandle mDragWindowHandle; + + // Array of window handles to provide to the input dispatcher. + private InputWindowHandle[] mInputWindowHandles; + private int mInputWindowHandleCount; + // Set to true when the first input device configuration change notification // is received to indicate that the input devices are ready. private final Object mInputDevicesReadyMonitor = new Object(); @@ -68,8 +70,10 @@ final class InputMonitor { synchronized (mService.mWindowMap) { WindowState windowState = (WindowState) inputWindowHandle.windowState; - Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState); - mService.removeWindowLocked(windowState.mSession, windowState); + if (windowState != null) { + Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState); + mService.removeWindowLocked(windowState.mSession, windowState); + } } } @@ -94,8 +98,11 @@ final class InputMonitor { if (appWindowToken == null && inputApplicationHandle != null) { appWindowToken = inputApplicationHandle.appWindowToken; - Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to application " - + appWindowToken.stringName); + if (appWindowToken != null) { + Slog.i(WindowManagerService.TAG, + "Input event dispatching timed out sending to application " + + appWindowToken.stringName); + } } if (appWindowToken != null && appWindowToken.appToken != null) { @@ -114,32 +121,59 @@ final class InputMonitor { return 0; // abort dispatching } - private void addDragInputWindowLw(InputWindowList windowList) { - final InputWindow inputWindow = windowList.add(); - inputWindow.inputChannel = mService.mDragState.mServerChannel; - inputWindow.name = "drag"; - inputWindow.layoutParamsFlags = 0; - inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; - inputWindow.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - inputWindow.visible = true; - inputWindow.canReceiveKeys = false; - inputWindow.hasFocus = true; - inputWindow.hasWallpaper = false; - inputWindow.paused = false; - inputWindow.layer = mService.mDragState.getDragLayerLw(); - inputWindow.ownerPid = Process.myPid(); - inputWindow.ownerUid = Process.myUid(); - inputWindow.inputFeatures = 0; - inputWindow.scaleFactor = 1.0f; + private void addDragInputWindowLw() { + if (mDragWindowHandle == null) { + mDragApplicationHandle = new InputApplicationHandle(null); + mDragApplicationHandle.name = "drag"; + mDragApplicationHandle.dispatchingTimeoutNanos = + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + + mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null); + mDragWindowHandle.name = "drag"; + mDragWindowHandle.layoutParamsFlags = 0; + mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; + mDragWindowHandle.dispatchingTimeoutNanos = + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + mDragWindowHandle.visible = true; + mDragWindowHandle.canReceiveKeys = false; + mDragWindowHandle.hasFocus = true; + mDragWindowHandle.hasWallpaper = false; + mDragWindowHandle.paused = false; + mDragWindowHandle.ownerPid = Process.myPid(); + mDragWindowHandle.ownerUid = Process.myUid(); + mDragWindowHandle.inputFeatures = 0; + mDragWindowHandle.scaleFactor = 1.0f; + + // The drag window cannot receive new touches. + mDragWindowHandle.touchableRegion.setEmpty(); + } + + mDragWindowHandle.layer = mService.mDragState.getDragLayerLw(); // The drag window covers the entire display - inputWindow.frameLeft = 0; - inputWindow.frameTop = 0; - inputWindow.frameRight = mService.mDisplay.getRealWidth(); - inputWindow.frameBottom = mService.mDisplay.getRealHeight(); + mDragWindowHandle.frameLeft = 0; + mDragWindowHandle.frameTop = 0; + mDragWindowHandle.frameRight = mService.mDisplay.getRealWidth(); + mDragWindowHandle.frameBottom = mService.mDisplay.getRealHeight(); - // The drag window cannot receive new touches. - inputWindow.touchableRegion.setEmpty(); + addInputWindowHandleLw(mDragWindowHandle); + } + + private void addInputWindowHandleLw(InputWindowHandle windowHandle) { + if (mInputWindowHandles == null) { + mInputWindowHandles = new InputWindowHandle[16]; + } + if (mInputWindowHandleCount >= mInputWindowHandles.length) { + mInputWindowHandles = Arrays.copyOf(mInputWindowHandles, + mInputWindowHandleCount * 2); + } + mInputWindowHandles[mInputWindowHandleCount++] = windowHandle; + } + + private void clearInputWindowHandlesLw() { + while (mInputWindowHandleCount != 0) { + mInputWindowHandles[--mInputWindowHandleCount] = null; + } } public void setUpdateInputWindowsNeededLw() { @@ -154,7 +188,7 @@ final class InputMonitor { mUpdateInputWindowsNeeded = false; if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED updateInputWindowsLw"); - + // Populate the input window list with information about all of the windows that // could potentially receive input. // As an optimization, we could try to prune the list of windows but this turns @@ -168,7 +202,7 @@ final class InputMonitor { if (WindowManagerService.DEBUG_DRAG) { Log.d(WindowManagerService.TAG, "Inserting drag window"); } - addDragInputWindowLw(mTempInputWindows); + addDragInputWindowLw(); } final int N = windows.size(); @@ -194,48 +228,48 @@ final class InputMonitor { } // Add a window to our list of input windows. - final InputWindow inputWindow = mTempInputWindows.add(); - inputWindow.inputWindowHandle = child.mInputWindowHandle; - inputWindow.inputChannel = child.mInputChannel; - inputWindow.name = child.toString(); - inputWindow.layoutParamsFlags = flags; - inputWindow.layoutParamsType = type; - inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); - inputWindow.visible = isVisible; - inputWindow.canReceiveKeys = child.canReceiveKeys(); - inputWindow.hasFocus = hasFocus; - inputWindow.hasWallpaper = hasWallpaper; - inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false; - inputWindow.layer = child.mLayer; - inputWindow.ownerPid = child.mSession.mPid; - inputWindow.ownerUid = child.mSession.mUid; - inputWindow.inputFeatures = child.mAttrs.inputFeatures; + final InputWindowHandle inputWindowHandle = child.mInputWindowHandle; + inputWindowHandle.inputChannel = child.mInputChannel; + inputWindowHandle.name = child.toString(); + inputWindowHandle.layoutParamsFlags = flags; + inputWindowHandle.layoutParamsType = type; + inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); + inputWindowHandle.visible = isVisible; + inputWindowHandle.canReceiveKeys = child.canReceiveKeys(); + inputWindowHandle.hasFocus = hasFocus; + inputWindowHandle.hasWallpaper = hasWallpaper; + inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false; + inputWindowHandle.layer = child.mLayer; + inputWindowHandle.ownerPid = child.mSession.mPid; + inputWindowHandle.ownerUid = child.mSession.mUid; + inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures; final Rect frame = child.mFrame; - inputWindow.frameLeft = frame.left; - inputWindow.frameTop = frame.top; - inputWindow.frameRight = frame.right; - inputWindow.frameBottom = frame.bottom; + inputWindowHandle.frameLeft = frame.left; + inputWindowHandle.frameTop = frame.top; + inputWindowHandle.frameRight = frame.right; + inputWindowHandle.frameBottom = frame.bottom; if (child.mGlobalScale != 1) { // If we are scaling the window, input coordinates need // to be inversely scaled to map from what is on screen // to what is actually being touched in the UI. - inputWindow.scaleFactor = 1.0f/child.mGlobalScale; + inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale; } else { - inputWindow.scaleFactor = 1; + inputWindowHandle.scaleFactor = 1; } - child.getTouchableRegion(inputWindow.touchableRegion); + child.getTouchableRegion(inputWindowHandle.touchableRegion); + + addInputWindowHandleLw(inputWindowHandle); } // Send windows to native code. - mService.mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray()); - + mService.mInputManager.setInputWindows(mInputWindowHandles); + // Clear the list in preparation for the next round. - // Also avoids keeping InputChannel objects referenced unnecessarily. - mTempInputWindows.clear(); - + clearInputWindowHandlesLw(); + if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw"); } @@ -329,14 +363,11 @@ final class InputMonitor { if (newApp == null) { mService.mInputManager.setFocusedApplication(null); } else { - mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle; - mTempInputApplication.name = newApp.toString(); - mTempInputApplication.dispatchingTimeoutNanos = - newApp.inputDispatchingTimeoutNanos; + final InputApplicationHandle handle = newApp.mInputApplicationHandle; + handle.name = newApp.toString(); + handle.dispatchingTimeoutNanos = newApp.inputDispatchingTimeoutNanos; - mService.mInputManager.setFocusedApplication(mTempInputApplication); - - mTempInputApplication.recycle(); + mService.mInputManager.setFocusedApplication(handle); } } diff --git a/services/java/com/android/server/wm/InputWindow.java b/services/java/com/android/server/wm/InputWindow.java deleted file mode 100644 index 655d734002933..0000000000000 --- a/services/java/com/android/server/wm/InputWindow.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import android.graphics.Region; -import android.view.InputChannel; - -/** - * Describes input-related window properties for use by the input dispatcher. - * @hide - */ -public final class InputWindow { - // The window handle. - public InputWindowHandle inputWindowHandle; - - // The input channel associated with the window. - public InputChannel inputChannel; - - // The window name. - public String name; - - // Window layout params attributes. (WindowManager.LayoutParams) - public int layoutParamsFlags; - public int layoutParamsType; - - // Dispatching timeout. - public long dispatchingTimeoutNanos; - - // Window frame. - public int frameLeft; - public int frameTop; - public int frameRight; - public int frameBottom; - - // Global scaling factor applied to touch events when they are dispatched - // to the window - public float scaleFactor; - - // Window touchable region. - public final Region touchableRegion = new Region(); - - // Window is visible. - public boolean visible; - - // Window can receive keys. - public boolean canReceiveKeys; - - // Window has focus. - public boolean hasFocus; - - // Window has wallpaper. (window is the current wallpaper target) - public boolean hasWallpaper; - - // Input event dispatching is paused. - public boolean paused; - - // Window layer. - public int layer; - - // Id of process and user that owns the window. - public int ownerPid; - public int ownerUid; - - // Window input features. - public int inputFeatures; - - public void recycle() { - inputWindowHandle = null; - inputChannel = null; - } -} diff --git a/services/java/com/android/server/wm/InputWindowHandle.java b/services/java/com/android/server/wm/InputWindowHandle.java index cc508c6f7013a..abf68d94cc5a2 100644 --- a/services/java/com/android/server/wm/InputWindowHandle.java +++ b/services/java/com/android/server/wm/InputWindowHandle.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import android.graphics.Region; +import android.view.InputChannel; import android.view.WindowManagerPolicy; /** @@ -35,6 +37,57 @@ public final class InputWindowHandle { // The window manager's window state. public final WindowManagerPolicy.WindowState windowState; + // The input channel associated with the window. + public InputChannel inputChannel; + + // The window name. + public String name; + + // Window layout params attributes. (WindowManager.LayoutParams) + public int layoutParamsFlags; + public int layoutParamsType; + + // Dispatching timeout. + public long dispatchingTimeoutNanos; + + // Window frame. + public int frameLeft; + public int frameTop; + public int frameRight; + public int frameBottom; + + // Global scaling factor applied to touch events when they are dispatched + // to the window + public float scaleFactor; + + // Window touchable region. + public final Region touchableRegion = new Region(); + + // Window is visible. + public boolean visible; + + // Window can receive keys. + public boolean canReceiveKeys; + + // Window has focus. + public boolean hasFocus; + + // Window has wallpaper. (window is the current wallpaper target) + public boolean hasWallpaper; + + // Input event dispatching is paused. + public boolean paused; + + // Window layer. + public int layer; + + // Id of process and user that owns the window. + public int ownerPid; + public int ownerUid; + + // Window input features. + public int inputFeatures; + private native void nativeDispose(); public InputWindowHandle(InputApplicationHandle inputApplicationHandle, diff --git a/services/java/com/android/server/wm/InputWindowList.java b/services/java/com/android/server/wm/InputWindowList.java deleted file mode 100644 index 6077337a8aaef..0000000000000 --- a/services/java/com/android/server/wm/InputWindowList.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - - -/** - * A specialized list of window information objects backed by an array. - * - * This class is part of an InputManager optimization to avoid allocating objects and arrays - * unnecessarily. Internally, it keeps an array full of demand-allocated objects that it - * recycles each time the list is cleared. The used portion of the array is padded with a null. - * - * The contents of the list are intended to be Z-ordered from top to bottom. - * - * @hide - */ -public final class InputWindowList { - private InputWindow[] mArray; - private int mCount; - - /** - * Creates an empty list. - */ - public InputWindowList() { - mArray = new InputWindow[8]; - } - - /** - * Clears the list. - */ - public void clear() { - if (mCount == 0) { - return; - } - - int count = mCount; - mCount = 0; - mArray[count] = mArray[0]; - while (count > 0) { - count -= 1; - mArray[count].recycle(); - } - mArray[0] = null; - } - - /** - * Adds an uninitialized input window object to the list and returns it. - */ - public InputWindow add() { - if (mCount + 1 == mArray.length) { - InputWindow[] oldArray = mArray; - mArray = new InputWindow[oldArray.length * 2]; - System.arraycopy(oldArray, 0, mArray, 0, mCount); - } - - // Grab object from tail (after used section) if available. - InputWindow item = mArray[mCount + 1]; - if (item == null) { - item = new InputWindow(); - } - - mArray[mCount] = item; - mCount += 1; - mArray[mCount] = null; - return item; - } - - /** - * Gets the input window objects as a null-terminated array. - * @return The input window array. - */ - public InputWindow[] toNullTerminatedArray() { - return mArray; - } -} \ No newline at end of file diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index b370ec9e12cd1..d298ff778d97a 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -272,7 +272,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { float mSurfaceAlpha; // Input channel and input window handle used by the input dispatcher. - InputWindowHandle mInputWindowHandle; + final InputWindowHandle mInputWindowHandle; InputChannel mInputChannel; // Used to improve performance of toString() @@ -306,6 +306,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { mIsFloatingLayer = false; mBaseLayer = 0; mSubLayer = 0; + mInputWindowHandle = null; return; } mDeathRecipient = deathRecipient; diff --git a/services/jni/Android.mk b/services/jni/Android.mk index e1c7305bb6de3..6fa5dfa969b54 100644 --- a/services/jni/Android.mk +++ b/services/jni/Android.mk @@ -4,10 +4,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ com_android_server_AlarmManagerService.cpp \ com_android_server_BatteryService.cpp \ - com_android_server_InputApplication.cpp \ com_android_server_InputApplicationHandle.cpp \ com_android_server_InputManager.cpp \ - com_android_server_InputWindow.cpp \ com_android_server_InputWindowHandle.cpp \ com_android_server_LightsService.cpp \ com_android_server_PowerManagerService.cpp \ diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp deleted file mode 100644 index 1f80242ceaccc..0000000000000 --- a/services/jni/com_android_server_InputApplication.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputApplication" - -#include "JNIHelp.h" -#include "jni.h" -#include - -#include "com_android_server_InputApplication.h" -#include "com_android_server_InputApplicationHandle.h" - -namespace android { - -static struct { - jfieldID inputApplicationHandle; - jfieldID name; - jfieldID dispatchingTimeoutNanos; -} gInputApplicationClassInfo; - - -// --- Global functions --- - -void android_server_InputApplication_toNative( - JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) { - jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj, - gInputApplicationClassInfo.inputApplicationHandle); - if (inputApplicationHandleObj) { - outInputApplication->inputApplicationHandle = - android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj); - env->DeleteLocalRef(inputApplicationHandleObj); - } else { - outInputApplication->inputApplicationHandle = NULL; - } - - jstring nameObj = jstring(env->GetObjectField(inputApplicationObj, - gInputApplicationClassInfo.name)); - if (nameObj) { - const char* nameStr = env->GetStringUTFChars(nameObj, NULL); - outInputApplication->name.setTo(nameStr); - env->ReleaseStringUTFChars(nameObj, nameStr); - env->DeleteLocalRef(nameObj); - } else { - LOGE("InputApplication.name should not be null."); - outInputApplication->name.setTo("unknown"); - } - - outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj, - gInputApplicationClassInfo.dispatchingTimeoutNanos); -} - - -// --- JNI --- - -#define FIND_CLASS(var, className) \ - var = env->FindClass(className); \ - LOG_FATAL_IF(! var, "Unable to find class " className); - -#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ - var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ - LOG_FATAL_IF(! var, "Unable to find field " fieldName); - -int register_android_server_InputApplication(JNIEnv* env) { - jclass clazz; - FIND_CLASS(clazz, "com/android/server/wm/InputApplication"); - - GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle, - clazz, - "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;"); - - GET_FIELD_ID(gInputApplicationClassInfo.name, clazz, - "name", "Ljava/lang/String;"); - - GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos, - clazz, - "dispatchingTimeoutNanos", "J"); - return 0; -} - -} /* namespace android */ diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h deleted file mode 100644 index 85fb891cfd2ba..0000000000000 --- a/services/jni/com_android_server_InputApplication.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H -#define _ANDROID_SERVER_INPUT_APPLICATION_H - -#include - -#include "JNIHelp.h" -#include "jni.h" - -namespace android { - -extern void android_server_InputApplication_toNative( - JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication); - -} // namespace android - -#endif // _ANDROID_SERVER_INPUT_APPLICATION_H diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp index 9516964302357..7de67d9fcd2b8 100644 --- a/services/jni/com_android_server_InputApplicationHandle.cpp +++ b/services/jni/com_android_server_InputApplicationHandle.cpp @@ -27,6 +27,8 @@ namespace android { static struct { jfieldID ptr; + jfieldID name; + jfieldID dispatchingTimeoutNanos; } gInputApplicationHandleClassInfo; static Mutex gHandleMutex; @@ -47,6 +49,31 @@ jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEn return env->NewLocalRef(mObjWeak); } +bool NativeInputApplicationHandle::update() { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + jobject obj = env->NewLocalRef(mObjWeak); + if (!obj) { + return false; + } + + jstring nameObj = jstring(env->GetObjectField(obj, + gInputApplicationHandleClassInfo.name)); + if (nameObj) { + const char* nameStr = env->GetStringUTFChars(nameObj, NULL); + name.setTo(nameStr); + env->ReleaseStringUTFChars(nameObj, nameStr); + env->DeleteLocalRef(nameObj); + } else { + name.setTo(""); + } + + dispatchingTimeout = env->GetLongField(obj, + gInputApplicationHandleClassInfo.dispatchingTimeoutNanos); + + env->DeleteLocalRef(obj); + return true; +} + // --- Global functions --- @@ -113,6 +140,13 @@ int register_android_server_InputApplicationHandle(JNIEnv* env) { GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz, "ptr", "I"); + GET_FIELD_ID(gInputApplicationHandleClassInfo.name, clazz, + "name", "Ljava/lang/String;"); + + GET_FIELD_ID(gInputApplicationHandleClassInfo.dispatchingTimeoutNanos, + clazz, + "dispatchingTimeoutNanos", "J"); + return 0; } diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h index 9d187219b2ec2..04cd9d60a630c 100644 --- a/services/jni/com_android_server_InputApplicationHandle.h +++ b/services/jni/com_android_server_InputApplicationHandle.h @@ -31,6 +31,8 @@ public: jobject getInputApplicationHandleObjLocalRef(JNIEnv* env); + virtual bool update(); + private: jweak mObjWeak; }; diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 14a41096bfec2..de9c9d0dbb18c 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -46,9 +46,7 @@ #include #include "com_android_server_PowerManagerService.h" -#include "com_android_server_InputApplication.h" #include "com_android_server_InputApplicationHandle.h" -#include "com_android_server_InputWindow.h" #include "com_android_server_InputWindowHandle.h" namespace android { @@ -175,8 +173,8 @@ public: const sp& inputWindowHandle, bool monitor); status_t unregisterInputChannel(JNIEnv* env, const sp& inputChannel); - void setInputWindows(JNIEnv* env, jobjectArray windowObjArray); - void setFocusedApplication(JNIEnv* env, jobject applicationObj); + void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray); + void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj); void setInputDispatchMode(bool enabled, bool frozen); void setSystemUiVisibility(int32_t visibility); void setPointerSpeed(int32_t speed); @@ -582,31 +580,38 @@ bool NativeInputManager::isKeyRepeatEnabled() { return isScreenOn(); } -void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) { - Vector windows; +void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) { + Vector > windowHandles; - bool newPointerGesturesEnabled = true; - jsize length = env->GetArrayLength(windowObjArray); - for (jsize i = 0; i < length; i++) { - jobject windowObj = env->GetObjectArrayElement(windowObjArray, i); - if (! windowObj) { - break; // found null element indicating end of used portion of the array - } - - windows.push(); - InputWindow& window = windows.editTop(); - android_server_InputWindow_toNative(env, windowObj, &window); - if (window.inputChannel == NULL) { - windows.pop(); - } else if (window.hasFocus) { - if (window.inputFeatures & InputWindow::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES) { - newPointerGesturesEnabled = false; + if (windowHandleObjArray) { + jsize length = env->GetArrayLength(windowHandleObjArray); + for (jsize i = 0; i < length; i++) { + jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i); + if (! windowHandleObj) { + break; // found null element indicating end of used portion of the array } + + sp windowHandle = + android_server_InputWindowHandle_getHandle(env, windowHandleObj); + if (windowHandle != NULL) { + windowHandles.push(windowHandle); + } + env->DeleteLocalRef(windowHandleObj); } - env->DeleteLocalRef(windowObj); } - mInputManager->getDispatcher()->setInputWindows(windows); + mInputManager->getDispatcher()->setInputWindows(windowHandles); + + // Do this after the dispatcher has updated the window handle state. + bool newPointerGesturesEnabled = true; + size_t numWindows = windowHandles.size(); + for (size_t i = 0; i < numWindows; i++) { + const sp& windowHandle = windowHandles.itemAt(i); + if (windowHandle->hasFocus && (windowHandle->inputFeatures + & InputWindowHandle::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) { + newPointerGesturesEnabled = false; + } + } uint32_t changes = 0; { // acquire lock @@ -623,16 +628,10 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArra } } -void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) { - if (applicationObj) { - InputApplication application; - android_server_InputApplication_toNative(env, applicationObj, &application); - if (application.inputApplicationHandle != NULL) { - mInputManager->getDispatcher()->setFocusedApplication(&application); - return; - } - } - mInputManager->getDispatcher()->setFocusedApplication(NULL); +void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) { + sp applicationHandle = + android_server_InputApplicationHandle_getHandle(env, applicationHandleObj); + mInputManager->getDispatcher()->setFocusedApplication(applicationHandle); } void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) { @@ -1137,21 +1136,21 @@ static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jcla } static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz, - jobjectArray windowObjArray) { + jobjectArray windowHandleObjArray) { if (checkInputManagerUnitialized(env)) { return; } - gNativeInputManager->setInputWindows(env, windowObjArray); + gNativeInputManager->setInputWindows(env, windowHandleObjArray); } static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz, - jobject applicationObj) { + jobject applicationHandleObj) { if (checkInputManagerUnitialized(env)) { return; } - gNativeInputManager->setFocusedApplication(env, applicationObj); + gNativeInputManager->setFocusedApplication(env, applicationHandleObj); } static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env, @@ -1313,9 +1312,9 @@ static JNINativeMethod gInputManagerMethods[] = { (void*) android_server_InputManager_nativeSetInputFilterEnabled }, { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIIII)I", (void*) android_server_InputManager_nativeInjectInputEvent }, - { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindow;)V", + { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindowHandle;)V", (void*) android_server_InputManager_nativeSetInputWindows }, - { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplication;)V", + { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplicationHandle;)V", (void*) android_server_InputManager_nativeSetFocusedApplication }, { "nativeSetInputDispatchMode", "(ZZ)V", (void*) android_server_InputManager_nativeSetInputDispatchMode }, diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp deleted file mode 100644 index 0426f6357248d..0000000000000 --- a/services/jni/com_android_server_InputWindow.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputWindow" - -#include "JNIHelp.h" -#include "jni.h" -#include - -#include -#include -#include "com_android_server_InputWindow.h" -#include "com_android_server_InputWindowHandle.h" - -namespace android { - -static struct { - jfieldID inputWindowHandle; - jfieldID inputChannel; - jfieldID name; - jfieldID layoutParamsFlags; - jfieldID layoutParamsType; - jfieldID dispatchingTimeoutNanos; - jfieldID frameLeft; - jfieldID frameTop; - jfieldID frameRight; - jfieldID frameBottom; - jfieldID scaleFactor; - jfieldID touchableRegion; - jfieldID visible; - jfieldID canReceiveKeys; - jfieldID hasFocus; - jfieldID hasWallpaper; - jfieldID paused; - jfieldID layer; - jfieldID ownerPid; - jfieldID ownerUid; - jfieldID inputFeatures; -} gInputWindowClassInfo; - - -// --- Global functions --- - -void android_server_InputWindow_toNative( - JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) { - jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj, - gInputWindowClassInfo.inputWindowHandle); - if (inputWindowHandleObj) { - outInputWindow->inputWindowHandle = - android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj); - env->DeleteLocalRef(inputWindowHandleObj); - } else { - outInputWindow->inputWindowHandle = NULL; - } - - jobject inputChannelObj = env->GetObjectField(inputWindowObj, - gInputWindowClassInfo.inputChannel); - if (inputChannelObj) { - outInputWindow->inputChannel = - android_view_InputChannel_getInputChannel(env, inputChannelObj); - env->DeleteLocalRef(inputChannelObj); - } else { - outInputWindow->inputChannel = NULL; - } - - jstring nameObj = jstring(env->GetObjectField(inputWindowObj, - gInputWindowClassInfo.name)); - if (nameObj) { - const char* nameStr = env->GetStringUTFChars(nameObj, NULL); - outInputWindow->name.setTo(nameStr); - env->ReleaseStringUTFChars(nameObj, nameStr); - env->DeleteLocalRef(nameObj); - } else { - LOGE("InputWindow.name should not be null."); - outInputWindow->name.setTo("unknown"); - } - - outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.layoutParamsFlags); - outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.layoutParamsType); - outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj, - gInputWindowClassInfo.dispatchingTimeoutNanos); - outInputWindow->frameLeft = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.frameLeft); - outInputWindow->frameTop = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.frameTop); - outInputWindow->frameRight = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.frameRight); - outInputWindow->frameBottom = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.frameBottom); - outInputWindow->scaleFactor = env->GetFloatField(inputWindowObj, - gInputWindowClassInfo.scaleFactor); - - jobject regionObj = env->GetObjectField(inputWindowObj, - gInputWindowClassInfo.touchableRegion); - if (regionObj) { - SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); - outInputWindow->touchableRegion.set(*region); - env->DeleteLocalRef(regionObj); - } else { - outInputWindow->touchableRegion.setEmpty(); - } - - outInputWindow->visible = env->GetBooleanField(inputWindowObj, - gInputWindowClassInfo.visible); - outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj, - gInputWindowClassInfo.canReceiveKeys); - outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj, - gInputWindowClassInfo.hasFocus); - outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj, - gInputWindowClassInfo.hasWallpaper); - outInputWindow->paused = env->GetBooleanField(inputWindowObj, - gInputWindowClassInfo.paused); - outInputWindow->layer = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.layer); - outInputWindow->ownerPid = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.ownerPid); - outInputWindow->ownerUid = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.ownerUid); - outInputWindow->inputFeatures = env->GetIntField(inputWindowObj, - gInputWindowClassInfo.inputFeatures); -} - - -// --- JNI --- - -#define FIND_CLASS(var, className) \ - var = env->FindClass(className); \ - LOG_FATAL_IF(! var, "Unable to find class " className); - -#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ - var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ - LOG_FATAL_IF(! var, "Unable to find field " fieldName); - -int register_android_server_InputWindow(JNIEnv* env) { - jclass clazz; - FIND_CLASS(clazz, "com/android/server/wm/InputWindow"); - - GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, clazz, - "inputWindowHandle", "Lcom/android/server/wm/InputWindowHandle;"); - - GET_FIELD_ID(gInputWindowClassInfo.inputChannel, clazz, - "inputChannel", "Landroid/view/InputChannel;"); - - GET_FIELD_ID(gInputWindowClassInfo.name, clazz, - "name", "Ljava/lang/String;"); - - GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, clazz, - "layoutParamsFlags", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, clazz, - "layoutParamsType", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, clazz, - "dispatchingTimeoutNanos", "J"); - - GET_FIELD_ID(gInputWindowClassInfo.frameLeft, clazz, - "frameLeft", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.frameTop, clazz, - "frameTop", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.frameRight, clazz, - "frameRight", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.frameBottom, clazz, - "frameBottom", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.scaleFactor, clazz, - "scaleFactor", "F"); - - GET_FIELD_ID(gInputWindowClassInfo.touchableRegion, clazz, - "touchableRegion", "Landroid/graphics/Region;"); - - GET_FIELD_ID(gInputWindowClassInfo.visible, clazz, - "visible", "Z"); - - GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, clazz, - "canReceiveKeys", "Z"); - - GET_FIELD_ID(gInputWindowClassInfo.hasFocus, clazz, - "hasFocus", "Z"); - - GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, clazz, - "hasWallpaper", "Z"); - - GET_FIELD_ID(gInputWindowClassInfo.paused, clazz, - "paused", "Z"); - - GET_FIELD_ID(gInputWindowClassInfo.layer, clazz, - "layer", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.ownerPid, clazz, - "ownerPid", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.ownerUid, clazz, - "ownerUid", "I"); - - GET_FIELD_ID(gInputWindowClassInfo.inputFeatures, clazz, - "inputFeatures", "I"); - return 0; -} - -} /* namespace android */ diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h deleted file mode 100644 index eaf7bdedbd7c5..0000000000000 --- a/services/jni/com_android_server_InputWindow.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ANDROID_SERVER_INPUT_WINDOW_H -#define _ANDROID_SERVER_INPUT_WINDOW_H - -#include - -#include "JNIHelp.h" -#include "jni.h" - -namespace android { - -extern void android_server_InputWindow_toNative( - JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow); - -} // namespace android - -#endif // _ANDROID_SERVER_INPUT_WINDOW_H diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp index aaf679c62c1be..09be88157df39 100644 --- a/services/jni/com_android_server_InputWindowHandle.cpp +++ b/services/jni/com_android_server_InputWindowHandle.cpp @@ -21,6 +21,9 @@ #include #include +#include +#include + #include "com_android_server_InputWindowHandle.h" #include "com_android_server_InputApplicationHandle.h" @@ -29,6 +32,26 @@ namespace android { static struct { jfieldID ptr; jfieldID inputApplicationHandle; + jfieldID inputChannel; + jfieldID name; + jfieldID layoutParamsFlags; + jfieldID layoutParamsType; + jfieldID dispatchingTimeoutNanos; + jfieldID frameLeft; + jfieldID frameTop; + jfieldID frameRight; + jfieldID frameBottom; + jfieldID scaleFactor; + jfieldID touchableRegion; + jfieldID visible; + jfieldID canReceiveKeys; + jfieldID hasFocus; + jfieldID hasWallpaper; + jfieldID paused; + jfieldID layer; + jfieldID ownerPid; + jfieldID ownerUid; + jfieldID inputFeatures; } gInputWindowHandleClassInfo; static Mutex gHandleMutex; @@ -51,6 +74,83 @@ jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) { return env->NewLocalRef(mObjWeak); } +bool NativeInputWindowHandle::update() { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + jobject obj = env->NewLocalRef(mObjWeak); + if (!obj) { + return false; + } + + jobject inputChannelObj = env->GetObjectField(obj, + gInputWindowHandleClassInfo.inputChannel); + if (inputChannelObj) { + inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj); + env->DeleteLocalRef(inputChannelObj); + } else { + inputChannel = NULL; + } + + jstring nameObj = jstring(env->GetObjectField(obj, + gInputWindowHandleClassInfo.name)); + if (nameObj) { + const char* nameStr = env->GetStringUTFChars(nameObj, NULL); + name.setTo(nameStr); + env->ReleaseStringUTFChars(nameObj, nameStr); + env->DeleteLocalRef(nameObj); + } else { + name.setTo(""); + } + + layoutParamsFlags = env->GetIntField(obj, + gInputWindowHandleClassInfo.layoutParamsFlags); + layoutParamsType = env->GetIntField(obj, + gInputWindowHandleClassInfo.layoutParamsType); + dispatchingTimeout = env->GetLongField(obj, + gInputWindowHandleClassInfo.dispatchingTimeoutNanos); + frameLeft = env->GetIntField(obj, + gInputWindowHandleClassInfo.frameLeft); + frameTop = env->GetIntField(obj, + gInputWindowHandleClassInfo.frameTop); + frameRight = env->GetIntField(obj, + gInputWindowHandleClassInfo.frameRight); + frameBottom = env->GetIntField(obj, + gInputWindowHandleClassInfo.frameBottom); + scaleFactor = env->GetFloatField(obj, + gInputWindowHandleClassInfo.scaleFactor); + + jobject regionObj = env->GetObjectField(obj, + gInputWindowHandleClassInfo.touchableRegion); + if (regionObj) { + SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); + touchableRegion.set(*region); + env->DeleteLocalRef(regionObj); + } else { + touchableRegion.setEmpty(); + } + + visible = env->GetBooleanField(obj, + gInputWindowHandleClassInfo.visible); + canReceiveKeys = env->GetBooleanField(obj, + gInputWindowHandleClassInfo.canReceiveKeys); + hasFocus = env->GetBooleanField(obj, + gInputWindowHandleClassInfo.hasFocus); + hasWallpaper = env->GetBooleanField(obj, + gInputWindowHandleClassInfo.hasWallpaper); + paused = env->GetBooleanField(obj, + gInputWindowHandleClassInfo.paused); + layer = env->GetIntField(obj, + gInputWindowHandleClassInfo.layer); + ownerPid = env->GetIntField(obj, + gInputWindowHandleClassInfo.ownerPid); + ownerUid = env->GetIntField(obj, + gInputWindowHandleClassInfo.ownerUid); + inputFeatures = env->GetIntField(obj, + gInputWindowHandleClassInfo.inputFeatures); + + env->DeleteLocalRef(obj); + return true; +} + // --- Global functions --- @@ -127,6 +227,65 @@ int register_android_server_InputWindowHandle(JNIEnv* env) { clazz, "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;"); + GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz, + "inputChannel", "Landroid/view/InputChannel;"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz, + "name", "Ljava/lang/String;"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz, + "layoutParamsFlags", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz, + "layoutParamsType", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz, + "dispatchingTimeoutNanos", "J"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.frameLeft, clazz, + "frameLeft", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.frameTop, clazz, + "frameTop", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.frameRight, clazz, + "frameRight", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz, + "frameBottom", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz, + "scaleFactor", "F"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz, + "touchableRegion", "Landroid/graphics/Region;"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz, + "visible", "Z"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz, + "canReceiveKeys", "Z"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz, + "hasFocus", "Z"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz, + "hasWallpaper", "Z"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz, + "paused", "Z"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz, + "layer", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz, + "ownerPid", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.ownerUid, clazz, + "ownerUid", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz, + "inputFeatures", "I"); return 0; } diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h index 43f2a6ba95362..913c3b10712d0 100644 --- a/services/jni/com_android_server_InputWindowHandle.h +++ b/services/jni/com_android_server_InputWindowHandle.h @@ -32,6 +32,8 @@ public: jobject getInputWindowHandleObjLocalRef(JNIEnv* env); + virtual bool update(); + private: jweak mObjWeak; }; diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp index 9dff48b170673..4178039fa55a5 100644 --- a/services/jni/onload.cpp +++ b/services/jni/onload.cpp @@ -22,9 +22,7 @@ namespace android { int register_android_server_AlarmManagerService(JNIEnv* env); int register_android_server_BatteryService(JNIEnv* env); -int register_android_server_InputApplication(JNIEnv* env); int register_android_server_InputApplicationHandle(JNIEnv* env); -int register_android_server_InputWindow(JNIEnv* env); int register_android_server_InputWindowHandle(JNIEnv* env); int register_android_server_InputManager(JNIEnv* env); int register_android_server_LightsService(JNIEnv* env); @@ -51,9 +49,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) LOG_ASSERT(env, "Could not retrieve the env!"); register_android_server_PowerManagerService(env); - register_android_server_InputApplication(env); register_android_server_InputApplicationHandle(env); - register_android_server_InputWindow(env); register_android_server_InputWindowHandle(env); register_android_server_InputManager(env); register_android_server_LightsService(env);