Pergunta

I have implemented a window with size 1 and want to catch ACTION_OUTSIDE event.

mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(1,1,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);       

I get the trigger and I get the ACTION_OUTSIDE event, but when reading event.getRawX() and event.getRawY() they both return 0 every time. I tested the same thing with Android 2.3.6 and it worked. And I can't find anything that is deprecated.

Is it an Android problem or does anyone know a solution? Thx

Foi útil?

Solução

Tniederm, I answered a similar question here for reference, but I'll rehash it here with some minor edits:

After scouring the source code, I found the source of the issue:

https://github.com/android/platform_frameworks_base/blob/79e0206ef3203a1842949242e58fa8f3c25eb129/services/input/InputDispatcher.cpp#L1417

// 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) {
    sp<InputWindowHandle> foregroundWindowHandle =
            mTempTouchState.getFirstForegroundWindowHandle();
    const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->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) {
            sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
            if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
                mTempTouchState.addOrUpdateWindow(inputWindowHandle,
                        InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
            }
        }
    }
}

If the "outside touch" lands in a view that doesn't share its UID (read about it here) with the view that's listening for outside touches, the event dispatcher sets its coordinates to 0,0. This was definitely done for security purposes, but I'm not sure I see the full scope of the threat it's designed to mitigate. You can try to look for older versions of the InputDispatcher to find out when exactly this feature was introduced - I haven't looked myself.

I opened up a bug ticket about this if you'd like to follow it. At the very least, the documentation needs to include this information... I would also like to know if this security feature is really necessary.

Issue 72746: FLAG_WATCH_OUTSIDE_TOUCH doesn't return location for ACTION_OUTSIDE events on 4.2+

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top