bool Fpc1020Sensor::AuthenticationThread::threadLoop()
{
    ALOGV("Started authentication thread");

    do {
        int ret = doSingleAuthentication();
        if (ret) {
            ALOGW("Authentication attempt failed: %d", ret);
            mSensor->mErrorCb(ret, mSensor->mCbData);
        }
    } while (!exitPending() && mSensor->mWaitingForWakeup);

    handleShutdown();
    return false;
}
/**
 * Handle notifications from the SCTP stack.
 * Returns JNI_TRUE if the notification is one that is of interest to the
 * Java API, otherwise JNI_FALSE.
 */
jboolean handleNotification
  (JNIEnv* env, int fd, jobject resultContainerObj, union sctp_notification* snp,
   int read, jboolean isEOR, struct sockaddr* sap) {
    switch (snp->sn_header.sn_type) {
        case SCTP_SEND_FAILED:
            handleSendFailed(env, fd, resultContainerObj, &snp->sn_send_failed,
                    read, isEOR, sap);
            return JNI_TRUE;
        case SCTP_ASSOC_CHANGE:
            handleAssocChange(env, resultContainerObj, &snp->sn_assoc_change);
            return JNI_TRUE;
        case SCTP_SHUTDOWN_EVENT:
            handleShutdown(env, resultContainerObj, &snp->sn_shutdown_event);
            return JNI_TRUE;
        case SCTP_PEER_ADDR_CHANGE:
            handlePeerAddrChange(env, resultContainerObj, &snp->sn_paddr_change);
            return JNI_TRUE;
        default :
            /* the Java API is not interested in this event, maybe we are? */
            handleUninteresting(snp);
    }
    return JNI_FALSE;
}
bool Fpc1020Sensor::EnrollmentThread::threadLoop()
{
    int ret, enrolledId, stepsRemaining = Fpc1020Sensor::EnrollmentStepCount;
    fingerprint_enroll_rsp_t *resp =
            (fingerprint_enroll_rsp_t *) mSensor->mQseecom.getReceiveBuffer();
    fingerprint_end_enroll_cmd_t *endReq =
            (fingerprint_end_enroll_cmd_t *) mSensor->mQseecom.getSendBuffer();
    fingerprint_end_enroll_rsp_t *endResp =
            (fingerprint_end_enroll_rsp_t *) mSensor->mQseecom.getReceiveBuffer();

    ALOGV("Started enrollment thread");
    while (!exitPending()) {
        ret = waitForTouchDown();
        if (ret) {
            goto out;
        }
        mSensor->mAcquiredCb(mSensor->mCbData);
        ret = mSensor->sendCommand(CLIENT_CMD_FP_GET_IMAGE_WITH_CAC);
        if (ret) {
            goto out;
        }
        ret = mSensor->sendCommand(CLIENT_CMD_FP_DO_ENROLL);
        if (ret) {
            goto out;
        }

        ALOGD("Enrollment step done: result %d progress %d", resp->result, resp->progress);

        if (resp->result == 3) {
            // The return value of 3 means 'enrollment done'
            break;
        } else if (resp->result == 0) {
            stepsRemaining--;
            // While empiric evidence shows the number of enrollment steps is
            // always 20, the protocol doesn't provide any guarantee for it.
            // Safeguard against that case.
            if (stepsRemaining <= 0) {
                stepsRemaining = 1;
            }
            mSensor->mEnrollmentCb(0xffffffff, stepsRemaining, mSensor->mCbData);
        } else {
            ALOGI("Enrollment step returned error (%d), ignoring.", resp->result);
        }
    }

    memset(endReq->unknown, 0, sizeof(endReq->unknown));
    endReq->identifier_len = 0; // identifier unused for now

    ret = mSensor->sendCommand(CLIENT_CMD_FP_END_ENROLL);
    if (ret) {
        goto out;
    }

    ALOGD("Enrollment thread finished: result %d id 0x%08x", endResp->result, endResp->id);
    enrolledId = endResp->id;
    if (endResp->result != 0) {
        ret = -EIO;
    }

out:
    ret = adjustReturnValueForCancel(ret);
    handleShutdown();

    if (ret == 0) {
        // Do the final enrollment callback after doing the cleanup, so
        // we're in idle state when doing this call. Upper layers query
        // the enrollment list more or less directly after this callback,
        // so if we aren't in idle state at this point, we're prone to
        // race conditions.
        mSensor->mEnrollmentCb(enrolledId, 0, mSensor->mCbData);
    } else {
        ALOGD("Enrollment failed: %d", ret);
        mSensor->mErrorCb(ret, mSensor->mCbData);
    }

    return false;
}