Android 7.1 触摸事件代码跟踪

平台

rk3288 + Android 7.1

Framework-service

|-- frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

    public InputManagerService(Context context) {        this.mContext = context;        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());        mUseDevInputEventForAudioJack =                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="                + mUseDevInputEventForAudioJack);        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());        String doubleTouchGestureEnablePath = context.getResources().getString(                R.string.config_doubleTouchGestureEnableFile);        mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :            new File(doubleTouchGestureEnablePath);        LocalServices.addService(InputManagerInternal.class, new LocalService());    }    public void start() {        Slog.i(TAG, "Starting input manager");        nativeStart(mPtr);        // Add ourself to the Watchdog monitors.        Watchdog.getInstance().addMonitor(this);        registerPointerSpeedSettingObserver();        registerShowTouchesSettingObserver();        registerAccessibilityLargePointerSettingObserver();        mContext.registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                updatePointerSpeedFromSettings();                updateShowTouchesFromSettings();                updateAccessibilityLargePointerFromSettings();            }        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);        updatePointerSpeedFromSettings();        updateShowTouchesFromSettings();        updateAccessibilityLargePointerFromSettings();    }

Framework-jni

|-- frameworks/base/services/core/jni/Android.mk

LOCAL_SHARED_LIBRARIES += \    libandroid_runtime \    libandroidfw \    libbinder \    libcutils \    liblog \    libhardware \    libhardware_legacy \    libkeystore_binder \    libnativehelper \    libutils \    libui \    libinput \    libinputflinger \    libinputservice \    libsensorservice \    libskia \    libgui \    libusbhost \    libsuspend \    libEGL \    libGLESv2 \    libnetutils \    libdrm \    libsync \

|-- frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

#include static jlong nativeInit(JNIEnv* env, jclass /* clazz */,        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);    if (messageQueue == NULL) {        jniThrowRuntimeException(env, "MessageQueue is not initialized.");        return 0;    }    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,            messageQueue->getLooper());    im->incStrong(0);    return reinterpret_cast<jlong>(im);}static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);    status_t result = im->getInputManager()->start();    if (result) {        jniThrowRuntimeException(env, "Input manager could not be started.");    }}NativeInputManager::NativeInputManager(jobject contextObj,        jobject serviceObj, const sp<Looper>& looper) :        mLooper(looper), mInteractive(true) {    JNIEnv* env = jniEnv();    mContextObj = env->NewGlobalRef(contextObj);    mServiceObj = env->NewGlobalRef(serviceObj);    {        AutoMutex _l(mLock);        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;        mLocked.pointerSpeed = 0;        mLocked.pointerGesturesEnabled = true;        mLocked.showTouches = false;        mLocked.hardwareRotation = 0;char property[PROPERTY_VALUE_MAX];        if (property_get("ro.sf.hwrotation", property, "0") > 0) {            mLocked.hardwareRotation = atoi(property) / 90;        }    }    mInteractive = true;    sp<EventHub> eventHub = new EventHub();    mInputManager = new InputManager(eventHub, this, this);}

Framework-libinputflinger

|-- frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(        const sp<EventHubInterface>& eventHub,        const sp<InputReaderPolicyInterface>& readerPolicy,        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {    mDispatcher = new InputDispatcher(dispatcherPolicy);    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);    initialize();}InputManager::InputManager(        const sp<InputReaderInterface>& reader,        const sp<InputDispatcherInterface>& dispatcher) :        mReader(reader),        mDispatcher(dispatcher) {    initialize();}void InputManager::initialize() {    mReaderThread = new InputReaderThread(mReader);    mDispatcherThread = new InputDispatcherThread(mDispatcher);}status_t InputManager::start() {    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);    if (result) {        ALOGE("Could not start InputDispatcher thread due to error %d.", result);        return result;    }    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);    if (result) {        ALOGE("Could not start InputReader thread due to error %d.", result);        mDispatcherThread->requestExit();        return result;    }    return OK;}status_t InputManager::stop() {    status_t result = mReaderThread->requestExitAndWait();    if (result) {        ALOGW("Could not stop InputReader thread due to error %d.", result);    }    result = mDispatcherThread->requestExitAndWait();    if (result) {        ALOGW("Could not stop InputDispatcher thread due to error %d.", result);    }    return OK;}

|-- frameworks/native/services/inputflinger/InputReader.cpp

bool InputReaderThread::threadLoop() {    mReader->loopOnce();    return true;}void InputReader::loopOnce() {    int32_t oldGeneration;    int32_t timeoutMillis;    bool inputDevicesChanged = false;    Vector<InputDeviceInfo> inputDevices;    { // acquire lock        AutoMutex _l(mLock);        oldGeneration = mGeneration;        timeoutMillis = -1;        uint32_t changes = mConfigurationChangesToRefresh;        if (changes) {            mConfigurationChangesToRefresh = 0;            timeoutMillis = 0;            refreshConfigurationLocked(changes);        } else if (mNextTimeout != LLONG_MAX) {            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);        }    } // release lock    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);    { // acquire lock        AutoMutex _l(mLock);        mReaderIsAliveCondition.broadcast();        if (count) {            processEventsLocked(mEventBuffer, count);        }        if (mNextTimeout != LLONG_MAX) {            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);            if (now >= mNextTimeout) {#if DEBUG_RAW_EVENTS                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);#endif                mNextTimeout = LLONG_MAX;                timeoutExpiredLocked(now);            }        }        if (oldGeneration != mGeneration) {            inputDevicesChanged = true;            getInputDevicesLocked(inputDevices);        }    } // release lock    // Send out a message that the describes the changed input devices.    if (inputDevicesChanged) {        mPolicy->notifyInputDevicesChanged(inputDevices);    }    // Flush queued events out to the listener.    // This must happen outside of the lock because the listener could potentially call    // back into the InputReader's methods, such as getScanCodeState, or become blocked    // on another thread similarly waiting to acquire the InputReader lock thereby    // resulting in a deadlock.  This situation is actually quite plausible because the    // listener is actually the input dispatcher, which calls into the window manager,    // which occasionally calls into the input reader.    mQueuedListener->flush();}void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {    for (const RawEvent* rawEvent = rawEvents; count;) {        int32_t type = rawEvent->type;        size_t batchSize = 1;        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {            int32_t deviceId = rawEvent->deviceId;            while (batchSize < count) {                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT                        || rawEvent[batchSize].deviceId != deviceId) {                    break;                }                batchSize += 1;            }#if DEBUG_RAW_EVENTS            ALOGD("BatchSize: %d Count: %d", batchSize, count);#endif            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);        } else {            switch (rawEvent->type) {            case EventHubInterface::DEVICE_ADDED:                addDeviceLocked(rawEvent->when, rawEvent->deviceId);                break;            case EventHubInterface::DEVICE_REMOVED:                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);                break;            case EventHubInterface::FINISHED_DEVICE_SCAN:                handleConfigurationChangedLocked(rawEvent->when);                break;            default:                ALOG_ASSERT(false); // can't happen                break;            }        }        count -= batchSize;        rawEvent += batchSize;    }}void InputReader::processEventsForDeviceLocked(int32_t deviceId,        const RawEvent* rawEvents, size_t count) {    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);    if (deviceIndex < 0) {        ALOGW("Discarding event for unknown deviceId %d.", deviceId);        return;    }    InputDevice* device = mDevices.valueAt(deviceIndex);    if (device->isIgnored()) {        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);        return;    }    device->process(rawEvents, count);}void MultiTouchInputMapper::process(const RawEvent* rawEvent) {ALOGD("ALog MultiTouchInputMapper::process");    TouchInputMapper::process(rawEvent);    mMultiTouchMotionAccumulator.process(rawEvent);}void TouchInputMapper::process(const RawEvent* rawEvent) {    mCursorButtonAccumulator.process(rawEvent);    mCursorScrollAccumulator.process(rawEvent);    mTouchButtonAccumulator.process(rawEvent);    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {        sync(rawEvent->when);    }}void TouchInputMapper::sync(nsecs_t when) {    const RawState* last = mRawStatesPending.isEmpty() ?            &mCurrentRawState : &mRawStatesPending.top();    // Push a new state.    mRawStatesPending.push();    RawState* next = &mRawStatesPending.editTop();    next->clear();    next->when = when;    // Sync button state.    next->buttonState = mTouchButtonAccumulator.getButtonState()            | mCursorButtonAccumulator.getButtonState();    // Sync scroll    next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();    next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();    mCursorScrollAccumulator.finishSync();    // Sync touch    syncTouch(when, next);    // Assign pointer ids.    if (!mHavePointerIds) {        assignPointerIds(last, next);    }//#if DEBUG_RAW_EVENTS    ALOGD("ALog syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "            "hovering ids 0x%08x -> 0x%08x",            last->rawPointerData.pointerCount,            next->rawPointerData.pointerCount,            last->rawPointerData.touchingIdBits.value,            next->rawPointerData.touchingIdBits.value,            last->rawPointerData.hoveringIdBits.value,            next->rawPointerData.hoveringIdBits.value);//#endif    processRawTouches(false /*timeout*/);}void TouchInputMapper::processRawTouches(bool timeout) {    if (mDeviceMode == DEVICE_MODE_DISABLED) {        // Drop all input if the device is disabled.        mCurrentRawState.clear();        mRawStatesPending.clear();        return;    }    // Drain any pending touch states. The invariant here is that the mCurrentRawState is always    // valid and must go through the full cook and dispatch cycle. This ensures that anything    // touching the current state will only observe the events that have been dispatched to the    // rest of the pipeline.    const size_t N = mRawStatesPending.size();    size_t count;    for(count = 0; count < N; count++) {        const RawState& next = mRawStatesPending[count];        // A failure to assign the stylus id means that we're waiting on stylus data        // and so should defer the rest of the pipeline.        if (assignExternalStylusId(next, timeout)) {            break;        }        // All ready to go.        clearStylusDataPendingFlags();        mCurrentRawState.copyFrom(next);        if (mCurrentRawState.when < mLastRawState.when) {            mCurrentRawState.when = mLastRawState.when;        }        cookAndDispatch(mCurrentRawState.when);    }    if (count != 0) {        mRawStatesPending.removeItemsAt(0, count);    }    if (mExternalStylusDataPending) {        if (timeout) {            nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;            clearStylusDataPendingFlags();            mCurrentRawState.copyFrom(mLastRawState);#if DEBUG_STYLUS_FUSION            ALOGD("Timeout expired, synthesizing event with new stylus data");#endif            cookAndDispatch(when);        } else if (mExternalStylusFusionTimeout == LLONG_MAX) {            mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);        }    }}void TouchInputMapper::cookAndDispatch(nsecs_t when) {    // Always start with a clean state.    mCurrentCookedState.clear();    // Apply stylus buttons to current raw state.    applyExternalStylusButtonState(when);    // Handle policy on initial down or hover events.    bool initialDown = mLastRawState.rawPointerData.pointerCount == 0            && mCurrentRawState.rawPointerData.pointerCount != 0;    uint32_t policyFlags = 0;    bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;    if (initialDown || buttonsPressed) {        // If this is a touch screen, hide the pointer on an initial down.        if (mDeviceMode == DEVICE_MODE_DIRECT) {            getContext()->fadePointer();        }        if (mParameters.wake) {            policyFlags |= POLICY_FLAG_WAKE;        }    }    // Consume raw off-screen touches before cooking pointer data.    // If touches are consumed, subsequent code will not receive any pointer data.    if (consumeRawTouches(when, policyFlags)) {        mCurrentRawState.rawPointerData.clear();    }    // Cook pointer data.  This call populates the mCurrentCookedState.cookedPointerData structure    // with cooked pointer data that has the same ids and indices as the raw data.    // The following code can use either the raw or cooked data, as needed.    cookPointerData();    // Apply stylus pressure to current cooked state.    applyExternalStylusTouchState(when);    // Synthesize key down from raw buttons if needed.    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,            policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);    // Dispatch the touches either directly or by translation through a pointer on screen.    if (mDeviceMode == DEVICE_MODE_POINTER) {        for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);                !idBits.isEmpty(); ) {            uint32_t id = idBits.clearFirstMarkedBit();            const RawPointerData::Pointer& pointer =                    mCurrentRawState.rawPointerData.pointerForId(id);            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {                mCurrentCookedState.stylusIdBits.markBit(id);            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {                mCurrentCookedState.fingerIdBits.markBit(id);            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {                mCurrentCookedState.mouseIdBits.markBit(id);            }        }        for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);                !idBits.isEmpty(); ) {            uint32_t id = idBits.clearFirstMarkedBit();            const RawPointerData::Pointer& pointer =                    mCurrentRawState.rawPointerData.pointerForId(id);            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {                mCurrentCookedState.stylusIdBits.markBit(id);            }        }        // Stylus takes precedence over all tools, then mouse, then finger.        PointerUsage pointerUsage = mPointerUsage;        if (!mCurrentCookedState.stylusIdBits.isEmpty()) {            mCurrentCookedState.mouseIdBits.clear();            mCurrentCookedState.fingerIdBits.clear();            pointerUsage = POINTER_USAGE_STYLUS;        } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {            mCurrentCookedState.fingerIdBits.clear();            pointerUsage = POINTER_USAGE_MOUSE;        } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||                isPointerDown(mCurrentRawState.buttonState)) {            pointerUsage = POINTER_USAGE_GESTURES;        }        dispatchPointerUsage(when, policyFlags, pointerUsage);    } else {        if (mDeviceMode == DEVICE_MODE_DIRECT                && mConfig.showTouches && mPointerController != NULL) {            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);            mPointerController->setButtonState(mCurrentRawState.buttonState);            mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,                    mCurrentCookedState.cookedPointerData.idToIndex,                    mCurrentCookedState.cookedPointerData.touchingIdBits);        }        if (!mCurrentMotionAborted) {            dispatchButtonRelease(when, policyFlags);            dispatchHoverExit(when, policyFlags);            dispatchTouches(when, policyFlags);            dispatchHoverEnterAndMove(when, policyFlags);            dispatchButtonPress(when, policyFlags);        }        if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {            mCurrentMotionAborted = false;        }    }    // Synthesize key up from raw buttons if needed.    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,            policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);    // Clear some transient state.    mCurrentRawState.rawVScroll = 0;    mCurrentRawState.rawHScroll = 0;    // Copy current touch to last touch in preparation for the next cycle.    mLastRawState.copyFrom(mCurrentRawState);    mLastCookedState.copyFrom(mCurrentCookedState);}void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;    BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;    int32_t metaState = getContext()->getGlobalMetaState();    int32_t buttonState = mCurrentCookedState.buttonState;    if (currentIdBits == lastIdBits) {        if (!currentIdBits.isEmpty()) {            // No pointer id changes so this is a move event.            // The listener takes care of batching moves so we don't have to deal with that here.            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,                    AMOTION_EVENT_EDGE_FLAG_NONE,                    mCurrentCookedState.cookedPointerData.pointerProperties,                    mCurrentCookedState.cookedPointerData.pointerCoords,                    mCurrentCookedState.cookedPointerData.idToIndex,                    currentIdBits, -1,                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);        }    } else {        // There may be pointers going up and pointers going down and pointers moving        // all at the same time.        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);        BitSet32 dispatchedIdBits(lastIdBits.value);        // Update last coordinates of pointers that have moved so that we observe the new        // pointer positions at the same time as other pointers that have just gone up.        bool moveNeeded = updateMovedPointers(                mCurrentCookedState.cookedPointerData.pointerProperties,                mCurrentCookedState.cookedPointerData.pointerCoords,                mCurrentCookedState.cookedPointerData.idToIndex,                mLastCookedState.cookedPointerData.pointerProperties,                mLastCookedState.cookedPointerData.pointerCoords,                mLastCookedState.cookedPointerData.idToIndex,                moveIdBits);        if (buttonState != mLastCookedState.buttonState) {            moveNeeded = true;        }        // Dispatch pointer up events.        while (!upIdBits.isEmpty()) {            uint32_t upId = upIdBits.clearFirstMarkedBit();            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,                    mLastCookedState.cookedPointerData.pointerProperties,                    mLastCookedState.cookedPointerData.pointerCoords,                    mLastCookedState.cookedPointerData.idToIndex,                    dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);            dispatchedIdBits.clearBit(upId);        }        // Dispatch move events if any of the remaining pointers moved from their old locations.        // Although applications receive new locations as part of individual pointer up        // events, they do not generally handle them except when presented in a move event.        if (moveNeeded && !moveIdBits.isEmpty()) {            ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,                    mCurrentCookedState.cookedPointerData.pointerProperties,                    mCurrentCookedState.cookedPointerData.pointerCoords,                    mCurrentCookedState.cookedPointerData.idToIndex,                    dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);        }        // Dispatch pointer down events using the new pointer locations.        while (!downIdBits.isEmpty()) {            uint32_t downId = downIdBits.clearFirstMarkedBit();            dispatchedIdBits.markBit(downId);            if (dispatchedIdBits.count() == 1) {                // First pointer is going down.  Set down time.                mDownTime = when;            }            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,                    mCurrentCookedState.cookedPointerData.pointerProperties,                    mCurrentCookedState.cookedPointerData.pointerCoords,                    mCurrentCookedState.cookedPointerData.idToIndex,                    dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);        }    }}void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,        int32_t action, int32_t actionButton, int32_t flags,        int32_t metaState, int32_t buttonState, int32_t edgeFlags,        const PointerProperties* properties, const PointerCoords* coords,        const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,        float xPrecision, float yPrecision, nsecs_t downTime) {//AnsonCodeALOGD("ALog dispatchMotion source(%d), width(%d), height(%d), orientation(%d)", source, mSurfaceWidth, mSurfaceHeight, mSurfaceOrientation);ALOGD("ALog coords(%f, %f), xP(%f), yP(%f)", coords->getX(), coords->getY(), xPrecision, yPrecision);    PointerCoords pointerCoords[MAX_POINTERS];    PointerProperties pointerProperties[MAX_POINTERS];    uint32_t pointerCount = 0;    while (!idBits.isEmpty()) {        uint32_t id = idBits.clearFirstMarkedBit();        uint32_t index = idToIndex[id];        pointerProperties[pointerCount].copyFrom(properties[index]);        pointerCoords[pointerCount].copyFrom(coords[index]);        if (changedId >= 0 && id == uint32_t(changedId)) {            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;        }        pointerCount += 1;    }    ALOG_ASSERT(pointerCount != 0);    if (changedId >= 0 && pointerCount == 1) {        // Replace initial down and final up action.        // We can compare the action without masking off the changed pointer index        // because we know the index is 0.        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {            action = AMOTION_EVENT_ACTION_DOWN;        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {            action = AMOTION_EVENT_ACTION_UP;        } else {            // Can't happen.            ALOG_ASSERT(false);        }    }    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,            action, actionButton, flags, metaState, buttonState, edgeFlags,            mViewport.displayId, pointerCount, pointerProperties, pointerCoords,            xPrecision, yPrecision, downTime);    getListener()->notifyMotion(&args);}//补充: 此函数对数据进行二次转换, 与屏幕方向等因素有关void TouchInputMapper::cookPointerData() {ALOGD("ALog cookPointerData");    uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;    mCurrentCookedState.cookedPointerData.clear();    mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;    mCurrentCookedState.cookedPointerData.hoveringIdBits =            mCurrentRawState.rawPointerData.hoveringIdBits;    mCurrentCookedState.cookedPointerData.touchingIdBits =            mCurrentRawState.rawPointerData.touchingIdBits;    if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {        mCurrentCookedState.buttonState = 0;    } else {        mCurrentCookedState.buttonState = mCurrentRawState.buttonState;    }    // Walk through the the active pointers and map device coordinates onto    // surface coordinates and adjust for display orientation.    for (uint32_t i = 0; i < currentPointerCount; i++) {        const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];        // Size        float touchMajor, touchMinor, toolMajor, toolMinor, size;        switch (mCalibration.sizeCalibration) {        case Calibration::SIZE_CALIBRATION_GEOMETRIC:        case Calibration::SIZE_CALIBRATION_DIAMETER:        case Calibration::SIZE_CALIBRATION_BOX:        case Calibration::SIZE_CALIBRATION_AREA:            if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {                touchMajor = in.touchMajor;                touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;                toolMajor = in.toolMajor;                toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;                size = mRawPointerAxes.touchMinor.valid                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;            } else if (mRawPointerAxes.touchMajor.valid) {                toolMajor = touchMajor = in.touchMajor;                toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid                        ? in.touchMinor : in.touchMajor;                size = mRawPointerAxes.touchMinor.valid                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;            } else if (mRawPointerAxes.toolMajor.valid) {                touchMajor = toolMajor = in.toolMajor;                touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid                        ? in.toolMinor : in.toolMajor;                size = mRawPointerAxes.toolMinor.valid                        ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;            } else {                ALOG_ASSERT(false, "No touch or tool axes.  "                        "Size calibration should have been resolved to NONE.");                touchMajor = 0;                touchMinor = 0;                toolMajor = 0;                toolMinor = 0;                size = 0;            }            if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {                uint32_t touchingCount =                        mCurrentRawState.rawPointerData.touchingIdBits.count();                if (touchingCount > 1) {                    touchMajor /= touchingCount;                    touchMinor /= touchingCount;                    toolMajor /= touchingCount;                    toolMinor /= touchingCount;                    size /= touchingCount;                }            }            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {                touchMajor *= mGeometricScale;                touchMinor *= mGeometricScale;                toolMajor *= mGeometricScale;                toolMinor *= mGeometricScale;            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {                touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;                touchMinor = touchMajor;                toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;                toolMinor = toolMajor;            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {                touchMinor = touchMajor;                toolMinor = toolMajor;            }            mCalibration.applySizeScaleAndBias(&touchMajor);            mCalibration.applySizeScaleAndBias(&touchMinor);            mCalibration.applySizeScaleAndBias(&toolMajor);            mCalibration.applySizeScaleAndBias(&toolMinor);            size *= mSizeScale;            break;        default:            touchMajor = 0;            touchMinor = 0;            toolMajor = 0;            toolMinor = 0;            size = 0;            break;        }        // Pressure        float pressure;        switch (mCalibration.pressureCalibration) {        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:            pressure = in.pressure * mPressureScale;            break;        default:            pressure = in.isHovering ? 0 : 1;            break;        }        // Tilt and Orientation        float tilt;        float orientation;        if (mHaveTilt) {            float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;            float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;            orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));            tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));        } else {            tilt = 0;            switch (mCalibration.orientationCalibration) {            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:                orientation = in.orientation * mOrientationScale;                break;            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);                int32_t c2 = signExtendNybble(in.orientation & 0x0f);                if (c1 != 0 || c2 != 0) {                    orientation = atan2f(c1, c2) * 0.5f;                    float confidence = hypotf(c1, c2);                    float scale = 1.0f + confidence / 16.0f;                    touchMajor *= scale;                    touchMinor /= scale;                    toolMajor *= scale;                    toolMinor /= scale;                } else {                    orientation = 0;                }                break;            }            default:                orientation = 0;            }        }        // Distance        float distance;        switch (mCalibration.distanceCalibration) {        case Calibration::DISTANCE_CALIBRATION_SCALED:            distance = in.distance * mDistanceScale;            break;        default:            distance = 0;        }        // Coverage        int32_t rawLeft, rawTop, rawRight, rawBottom;        switch (mCalibration.coverageCalibration) {        case Calibration::COVERAGE_CALIBRATION_BOX:            rawLeft = (in.toolMinor & 0xffff0000) >> 16;            rawRight = in.toolMinor & 0x0000ffff;            rawBottom = in.toolMajor & 0x0000ffff;            rawTop = (in.toolMajor & 0xffff0000) >> 16;            break;        default:            rawLeft = rawTop = rawRight = rawBottom = 0;            break;        }        // Adjust X,Y coords for device calibration        // TODO: Adjust coverage coords?        float xTransformed = in.x, yTransformed = in.y;        mAffineTransform.applyTo(xTransformed, yTransformed);        // Adjust X, Y, and coverage coords for surface orientation.        float x, y;        float left, top, right, bottom;/*ALOGD("ALog deviceName %s", getDeviceName().string());//AnsonCode rotationint rot = DISPLAY_ORIENTATION_0;if(mSurfaceOrientation == DISPLAY_ORIENTATION_180)rot = DISPLAY_ORIENTATION_0;else if(mSurfaceOrientation == DISPLAY_ORIENTATION_0)rot = DISPLAY_ORIENTATION_180;*/        switch (mSurfaceOrientation) {        case DISPLAY_ORIENTATION_90:            x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;            y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;            left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;            right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;            bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;            top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;            orientation -= M_PI_2;            if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);            }            break;        case DISPLAY_ORIENTATION_180:            x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;            y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;            left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;            right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;            bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;            top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;            orientation -= M_PI;            if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);            }            break;        case DISPLAY_ORIENTATION_270:            x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;            y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;            left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;            right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;            bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;            top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;            orientation += M_PI_2;            if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {                orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);            }            break;        default:            x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;            y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;            left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;            right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;            bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;            top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;            break;        }        // Write output coords.        PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];        out.clear();        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);        out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);        out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);        } else {            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);        }        // Write output properties.        PointerProperties& properties =                mCurrentCookedState.cookedPointerData.pointerProperties[i];        uint32_t id = in.id;        properties.clear();        properties.id = id;        properties.toolType = in.toolType;        // Write id index.        mCurrentCookedState.cookedPointerData.idToIndex[id] = i;    }}

更多相关文章

  1. C语言函数以及函数的使用
  2. 屏幕方向android:screenOrientation
  3. android唤醒屏幕--保持屏幕唤醒-Reprinted
  4. Android屏幕自适应的四种方法
  5. android-详解Android中的屏幕方向
  6. Android屏幕相关设置
  7. Android获取屏幕宽度与高度

随机推荐

  1. 一键解决Ubuntu下安装Eclipse Android/C/
  2. android Application类的详细介绍
  3. [android] PhoneGap 在 android 下的实现
  4. android stuio eclipse映射下的快捷键
  5. 使用迅雷代替SDK Manager快速下载Android
  6. android 中的xml解析
  7. Android笔记-3
  8. Android开机动画bootanimation
  9. Android使用FFmpeg(三)--ffmpeg实现视频
  10. 安卓第三天---ViewPager控件实现滑动切换