10f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines/*
20f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * Copyright (C) 2009 The Android Open Source Project
30f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *
40f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
50f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * you may not use this file except in compliance with the License.
60f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * You may obtain a copy of the License at
70f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *
80f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *      http://www.apache.org/licenses/LICENSE-2.0
90f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *
100f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * Unless required by applicable law or agreed to in writing, software
110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
120f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * See the License for the specific language governing permissions and
140f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * limitations under the License.
150f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines */
160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
170f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsContext.h"
180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsThreadIO.h"
190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsgApiStructs.h"
200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
210f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include <unistd.h>
220f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include <sys/types.h>
230f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include <sys/socket.h>
240f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
250f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include <fcntl.h>
260f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include <poll.h>
270f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
280f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
290f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesusing namespace android;
300f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesusing namespace android::renderscript;
310f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
320f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen HinesThreadIO::ThreadIO() {
330f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mRunning = true;
340f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mPureFifo = false;
350f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mMaxInlineSize = 1024;
360f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
380f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen HinesThreadIO::~ThreadIO() {
390f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
400f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
410f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::init() {
420f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToClient.init();
430f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToCore.init();
440f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
450f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
460f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::shutdown() {
470f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mRunning = false;
480f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToCore.shutdown();
490f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
500f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
510f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) {
520f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("coreHeader %i %i", cmdID, dataLen);
530f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    CoreCmdHeader *hdr = (CoreCmdHeader *)&mSendBuffer[0];
540f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    hdr->bytes = dataLen;
550f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    hdr->cmdID = cmdID;
560f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mSendLen = dataLen + sizeof(CoreCmdHeader);
570f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //mToCoreSocket.writeAsync(&hdr, sizeof(hdr));
580f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("coreHeader ret ");
590f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return &mSendBuffer[sizeof(CoreCmdHeader)];
600f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
610f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
620f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::coreCommit() {
630f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToCore.writeAsync(&mSendBuffer, mSendLen);
640f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
650f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
660f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::clientShutdown() {
670f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToClient.shutdown();
680f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
690f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
700f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::coreWrite(const void *data, size_t len) {
710f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGV("core write %p %i", data, (int)len);
720f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToCore.writeAsync(data, len, true);
730f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
740f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
750f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::coreRead(void *data, size_t len) {
760f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGV("core read %p %i", data, (int)len);
770f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToCore.read(data, len);
780f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
790f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
800f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::coreSetReturn(const void *data, size_t dataLen) {
810f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    uint32_t buf;
820f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (data == NULL) {
830f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        data = &buf;
840f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        dataLen = sizeof(buf);
850f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
860f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
870f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToCore.readReturn(data, dataLen);
880f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
890f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
900f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::coreGetReturn(void *data, size_t dataLen) {
910f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    uint32_t buf;
920f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (data == NULL) {
930f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        data = &buf;
940f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        dataLen = sizeof(buf);
950f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
960f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
970f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToCore.writeWaitReturn(data, dataLen);
980f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
990f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1000f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid ThreadIO::setTimeoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) {
1010f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //mToCore.setTimeoutCallback(cb, dat, timeout);
1020f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
1030f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1040f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesbool ThreadIO::playCoreCommands(Context *con, int waitFd) {
1050f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    bool ret = false;
1060f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    const bool isLocal = !isPureFifo();
1070f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1080f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    uint8_t buf[2 * 1024];
1090f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    const CoreCmdHeader *cmd = (const CoreCmdHeader *)&buf[0];
1100f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    const void * data = (const void *)&buf[sizeof(CoreCmdHeader)];
1110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1120f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    struct pollfd p[2];
1130f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    p[0].fd = mToCore.getReadFd();
1140f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    p[0].events = POLLIN;
1150f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    p[0].revents = 0;
1160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    p[1].fd = waitFd;
1170f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    p[1].events = POLLIN;
1180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    p[1].revents = 0;
1190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    int pollCount = 1;
1200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (waitFd >= 0) {
1210f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        pollCount = 2;
1220f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
1230f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1240f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (con->props.mLogTimes) {
1250f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        con->timerSet(Context::RS_TIMER_IDLE);
1260f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
1270f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1280f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    int waitTime = -1;
1290f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    while (mRunning) {
1300f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        int pr = poll(p, pollCount, waitTime);
1310f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        if (pr <= 0) {
1320f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            break;
1330f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
1340f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1350f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        if (p[0].revents) {
1360f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            size_t r = 0;
1370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            if (isLocal) {
1380f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                r = mToCore.read(&buf[0], sizeof(CoreCmdHeader));
1390f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                mToCore.read(&buf[sizeof(CoreCmdHeader)], cmd->bytes);
1400f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                if (r != sizeof(CoreCmdHeader)) {
1410f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                    // exception or timeout occurred.
1420f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                    break;
1430f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                }
1440f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            } else {
1450f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                r = mToCore.read((void *)&cmd->cmdID, sizeof(cmd->cmdID));
1460f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
1470f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1480f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1490f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            ret = true;
1500f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            if (con->props.mLogTimes) {
1510f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                con->timerSet(Context::RS_TIMER_INTERNAL);
1520f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
1530f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            //ALOGV("playCoreCommands 3 %i %i", cmd->cmdID, cmd->bytes);
1540f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1550f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            if (cmd->cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) {
1560f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                rsAssert(cmd->cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *)));
1570f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                ALOGE("playCoreCommands error con %p, cmd %i", con, cmd->cmdID);
1580f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
1590f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1600f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            if (isLocal) {
1610f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                gPlaybackFuncs[cmd->cmdID](con, data, cmd->bytes);
1620f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            } else {
1630f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                gPlaybackRemoteFuncs[cmd->cmdID](con, this);
1640f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
1650f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1660f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            if (con->props.mLogTimes) {
1670f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                con->timerSet(Context::RS_TIMER_IDLE);
1680f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
1690f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1700f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            if (waitFd < 0) {
1710f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                // If we don't have a secondary wait object we should stop blocking now
1720f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                // that at least one command has been processed.
1730f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                waitTime = 0;
1740f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
1750f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
1760f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1770f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        if (p[1].revents && !p[0].revents) {
1780f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            // We want to finish processing fifo events before processing the vsync.
1790f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            // Otherwise we can end up falling behind and having tremendous lag.
1800f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            break;
1810f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
1820f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
1830f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return ret;
1840f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
1850f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1860f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen HinesRsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) {
1870f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("getClientHeader");
1880f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToClient.read(&mLastClientHeader, sizeof(mLastClientHeader));
1890f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1900f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    receiveLen[0] = mLastClientHeader.bytes;
1910f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    usrID[0] = mLastClientHeader.userID;
1920f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("getClientHeader %i %i %i", mLastClientHeader.cmdID, usrID[0], receiveLen[0]);
1930f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return (RsMessageToClientType)mLastClientHeader.cmdID;
1940f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
1950f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
1960f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen HinesRsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen,
1970f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                                uint32_t *usrID, size_t bufferLen) {
1980f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("getClientPayload");
1990f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    receiveLen[0] = mLastClientHeader.bytes;
2000f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    usrID[0] = mLastClientHeader.userID;
2010f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (bufferLen < mLastClientHeader.bytes) {
2020f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return RS_MESSAGE_TO_CLIENT_RESIZE;
2030f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
2040f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (receiveLen[0]) {
2050f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        mToClient.read(data, receiveLen[0]);
2060f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
2070f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("getClientPayload x");
2080f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return (RsMessageToClientType)mLastClientHeader.cmdID;
2090f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
2100f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
2110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesbool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data,
2120f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                            size_t dataLen, bool waitForSpace) {
2130f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
2140f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("sendToClient %i %i %i", cmdID, usrID, (int)dataLen);
2150f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    ClientCmdHeader hdr;
2160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    hdr.bytes = dataLen;
2170f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    hdr.cmdID = cmdID;
2180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    hdr.userID = usrID;
2190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
2200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    mToClient.writeAsync(&hdr, sizeof(hdr));
2210f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (dataLen) {
2220f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        mToClient.writeAsync(data, dataLen);
2230f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
2240f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
2250f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("sendToClient x");
2260f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return true;
2270f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
2280f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
229