QemuClient.cpp revision 5a622cba8c5287d5e6577f940a22343a7cae977f
133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/*
233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Copyright (C) 2011 The Android Open Source Project
333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine *
433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License");
533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * you may not use this file except in compliance with the License.
633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * You may obtain a copy of the License at
733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine *
833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine *      http://www.apache.org/licenses/LICENSE-2.0
933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine *
1033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software
1133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS,
1233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * See the License for the specific language governing permissions and
1433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * limitations under the License.
1533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine */
1633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
1733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/*
1833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Contains implementation of classes that encapsulate connection to camera
1933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * services in the emulator via qemu pipe.
2033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine */
2133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
2249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine#define LOG_NDEBUG 1
2333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine#define LOG_TAG "EmulatedCamera_QemuClient"
2433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine#include <cutils/log.h>
255467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine#include "EmulatedCamera.h"
2633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine#include "QemuClient.h"
2733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
284d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine#define LOG_QUERIES 0
294d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine#if LOG_QUERIES
30112bc5e57e206ec3e0bc5a335b62eae2eb8892e8Steve Block#define LOGQ(...)   ALOGD(__VA_ARGS__)
314d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine#else
324d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine#define LOGQ(...)   (void(0))
334d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine
344d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine#endif  // LOG_QUERIES
3533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkinenamespace android {
3633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
3733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/****************************************************************************
3833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Qemu query
3933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine ***************************************************************************/
4033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
4133bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineQemuQuery::QemuQuery()
425467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    : mQuery(mQueryPrealloc),
4349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine      mQueryDeliveryStatus(NO_ERROR),
445467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyBuffer(NULL),
455467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyData(NULL),
465467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplySize(0),
475467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyDataSize(0),
485467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyStatus(0)
4933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
505467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    *mQuery = '\0';
5133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
5233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
5333bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineQemuQuery::QemuQuery(const char* query_string)
545467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    : mQuery(mQueryPrealloc),
5549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine      mQueryDeliveryStatus(NO_ERROR),
565467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyBuffer(NULL),
575467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyData(NULL),
585467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplySize(0),
595467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyDataSize(0),
605467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyStatus(0)
6133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
6249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    mQueryDeliveryStatus = QemuQuery::createQuery(query_string, NULL);
6333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
6433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
6533bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineQemuQuery::QemuQuery(const char* query_name, const char* query_param)
665467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    : mQuery(mQueryPrealloc),
6749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine      mQueryDeliveryStatus(NO_ERROR),
685467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyBuffer(NULL),
695467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyData(NULL),
705467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplySize(0),
715467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyDataSize(0),
725467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mReplyStatus(0)
7333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
7449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    mQueryDeliveryStatus = QemuQuery::createQuery(query_name, query_param);
7533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
7633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
7733bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineQemuQuery::~QemuQuery()
7833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
795467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    QemuQuery::resetQuery();
8033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
8133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
825467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t QemuQuery::createQuery(const char* name, const char* param)
8333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
8433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Reset from the previous use. */
855467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    resetQuery();
8633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
8733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Query name cannot be NULL or an empty string. */
8833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (name == NULL || *name == '\0') {
895a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: NULL or an empty string is passed as query name.",
9033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine             __FUNCTION__);
9149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        mQueryDeliveryStatus = EINVAL;
9233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EINVAL;
9333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
9433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
9533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    const size_t name_len = strlen(name);
9633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    const size_t param_len = (param != NULL) ? strlen(param) : 0;
9733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    const size_t required = strlen(name) + (param_len ? (param_len + 2) : 1);
9833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
995467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (required > sizeof(mQueryPrealloc)) {
10033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        /* Preallocated buffer was too small. Allocate a bigger query buffer. */
1015467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mQuery = new char[required];
1025467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        if (mQuery == NULL) {
1035a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Unable to allocate %d bytes for query buffer",
10433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine                 __FUNCTION__, required);
10549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            mQueryDeliveryStatus = ENOMEM;
10633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine            return ENOMEM;
10733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        }
10833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
10933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
1105467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    /* At this point mQuery buffer is big enough for the query. */
11133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (param_len) {
1125467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        sprintf(mQuery, "%s %s", name, param);
11333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
1145467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        memcpy(mQuery, name, name_len + 1);
11533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
11633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
11733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    return NO_ERROR;
11833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
11933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
1205467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t QemuQuery::completeQuery(status_t status)
12133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
12233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Save query completion status. */
12349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    mQueryDeliveryStatus = status;
12449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (mQueryDeliveryStatus != NO_ERROR) {
12549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return mQueryDeliveryStatus;
12633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
12733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
12833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Make sure reply buffer contains at least 'ok', or 'ko'.
12933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * Note that 'ok', or 'ko' prefixes are always 3 characters long: in case
13033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * there are more data in the reply, that data will be separated from 'ok'/'ko'
13133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * with a ':'. If there is no more data in the reply, the prefix will be
13233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * zero-terminated, and the terminator will be inculded in the reply. */
1335467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mReplyBuffer == NULL || mReplySize < 3) {
1345a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Invalid reply to the query", __FUNCTION__);
13549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        mQueryDeliveryStatus = EINVAL;
13633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EINVAL;
13733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
13833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
13933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Lets see the reply status. */
1405467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (!memcmp(mReplyBuffer, "ok", 2)) {
1415467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mReplyStatus = 1;
1425467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    } else if (!memcmp(mReplyBuffer, "ko", 2)) {
1435467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mReplyStatus = 0;
14433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
1455a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Invalid query reply: '%s'", __FUNCTION__, mReplyBuffer);
14649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        mQueryDeliveryStatus = EINVAL;
14733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EINVAL;
14833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
14933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
15033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Lets see if there are reply data that follow. */
1515467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mReplySize > 3) {
15233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        /* There are extra data. Make sure they are separated from the status
15333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine         * with a ':' */
1545467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        if (mReplyBuffer[2] != ':') {
1555a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Invalid query reply: '%s'", __FUNCTION__, mReplyBuffer);
15649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            mQueryDeliveryStatus = EINVAL;
15733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine            return EINVAL;
15833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        }
1595467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mReplyData = mReplyBuffer + 3;
1605467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mReplyDataSize = mReplySize - 3;
16133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
16233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        /* Make sure reply buffer containing just 'ok'/'ko' ends with
16333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine         * zero-terminator. */
1645467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        if (mReplyBuffer[2] != '\0') {
1655a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Invalid query reply: '%s'", __FUNCTION__, mReplyBuffer);
16649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            mQueryDeliveryStatus = EINVAL;
16733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine            return EINVAL;
16833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        }
16933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
17033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
17133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    return NO_ERROR;
17233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
17333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
1745467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinevoid QemuQuery::resetQuery()
17533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
1765467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mQuery != NULL && mQuery != mQueryPrealloc) {
1775467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        delete[] mQuery;
17833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
1795467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mQuery = mQueryPrealloc;
18049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    mQueryDeliveryStatus = NO_ERROR;
1815467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mReplyBuffer != NULL) {
1825467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        free(mReplyBuffer);
1835467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mReplyBuffer = NULL;
18433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
1855467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mReplyData = NULL;
18649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    mReplySize = mReplyDataSize = 0;
1875467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mReplyStatus = 0;
18833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
18933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
19033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/****************************************************************************
19133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Qemu client base
19233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine ***************************************************************************/
19333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
19433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/* Camera service name. */
1955467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkineconst char QemuClient::mCameraServiceName[]   = "camera";
19633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
19733bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineQemuClient::QemuClient()
1985467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    : mPipeFD(-1)
19933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
20033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
20133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
20233bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineQemuClient::~QemuClient()
20333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
2045467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mPipeFD >= 0) {
2055467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        close(mPipeFD);
20633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
20733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
20833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
20933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/****************************************************************************
21033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Qemu client API
21133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine ***************************************************************************/
21233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
2135467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t QemuClient::connectClient(const char* param)
21433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
215629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s: '%s'", __FUNCTION__, param ? param : "");
21633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
21733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Make sure that client is not connected already. */
2185467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mPipeFD >= 0) {
2195a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Qemu client is already connected", __FUNCTION__);
22033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EINVAL;
22133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
22233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
22333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Select one of the two: 'factory', or 'emulated camera' service */
22433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (param == NULL || *param == '\0') {
22533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        /* No parameters: connect to the factory service. */
22633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        char pipe_name[512];
2275467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", mCameraServiceName);
2285467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mPipeFD = qemu_pipe_open(pipe_name);
22933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
23033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        /* One extra char ':' that separates service name and parameters + six
23133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine         * characters for 'qemud:'. This is required by qemu pipe protocol. */
2325467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        char* connection_str = new char[strlen(mCameraServiceName) +
23333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine                                        strlen(param) + 8];
2345467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        sprintf(connection_str, "qemud:%s:%s", mCameraServiceName, param);
23533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
2365467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mPipeFD = qemu_pipe_open(connection_str);
23733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        delete[] connection_str;
23833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
2395467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mPipeFD < 0) {
2405a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Unable to connect to the camera service '%s': %s",
24133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine             __FUNCTION__, param ? param : "Factory", strerror(errno));
24233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return errno ? errno : EINVAL;
24333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
24433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
24533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    return NO_ERROR;
24633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
24733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
2485467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinevoid QemuClient::disconnectClient()
24933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
250629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
25116232484c709c565adfbf557025c52f61295c058Vladimir Chtchetkine
2525467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mPipeFD >= 0) {
2535467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        close(mPipeFD);
2545467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mPipeFD = -1;
25533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
25633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
25733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
2585467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t QemuClient::sendMessage(const void* data, size_t data_size)
25933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
2605467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mPipeFD < 0) {
2615a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Qemu client is not connected", __FUNCTION__);
26233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EINVAL;
26333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
26433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
26533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Note that we don't use here qemud_client_send, since with qemu pipes we
26633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * don't need to provide payload size prior to payload when we're writing to
26733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * the pipe. So, we can use simple write, and qemu pipe will take care of the
26833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * rest, calling the receiving end with the number of bytes transferred. */
2695467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    const size_t written = qemud_fd_write(mPipeFD, data, data_size);
27033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (written == data_size) {
27133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return NO_ERROR;
27233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
2735a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Error sending data via qemu pipe: '%s'",
27433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine             __FUNCTION__, strerror(errno));
27549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return errno ? errno : EIO;
27633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
27733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
27833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
2795467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t QemuClient::receiveMessage(void** data, size_t* data_size)
28033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
28133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    *data = NULL;
28233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    *data_size = 0;
28333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
2845467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mPipeFD < 0) {
2855a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Qemu client is not connected", __FUNCTION__);
28633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EINVAL;
28733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
28833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
28933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* The way the service replies to a query, it sends payload size first, and
29033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * then it sends the payload itself. Note that payload size is sent as a
29133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * string, containing 8 characters representing a hexadecimal payload size
29233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine     * value. Note also, that the string doesn't contain zero-terminator. */
29333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    size_t payload_size;
29433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    char payload_size_str[9];
2955467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    int rd_res = qemud_fd_read(mPipeFD, payload_size_str, 8);
29633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (rd_res != 8) {
2975a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Unable to obtain payload size: %s",
29833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine             __FUNCTION__, strerror(errno));
29933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return errno ? errno : EIO;
30033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
30133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
30233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Convert payload size. */
30333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    errno = 0;
30433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    payload_size_str[8] = '\0';
30533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    payload_size = strtol(payload_size_str, NULL, 16);
30633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (errno) {
3075a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Invalid payload size '%s'", __FUNCTION__, payload_size_str);
30833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EIO;
30933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
31033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
31133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Allocate payload data buffer, and read the payload there. */
31233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    *data = malloc(payload_size);
31333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (*data == NULL) {
3145a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Unable to allocate %d bytes payload buffer",
31533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine             __FUNCTION__, payload_size);
31633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return ENOMEM;
31733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
3185467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    rd_res = qemud_fd_read(mPipeFD, *data, payload_size);
31933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (static_cast<size_t>(rd_res) == payload_size) {
32033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        *data_size = payload_size;
32133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return NO_ERROR;
32233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
3235a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Read size %d doesnt match expected payload size %d: %s",
32433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine             __FUNCTION__, rd_res, payload_size, strerror(errno));
32533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        free(*data);
32633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        *data = NULL;
32733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return errno ? errno : EIO;
32833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
32933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
33033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
3315467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t QemuClient::doQuery(QemuQuery* query)
33233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
33333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Make sure that query has been successfuly constructed. */
33449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (query->mQueryDeliveryStatus != NO_ERROR) {
3355a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Query is invalid", __FUNCTION__);
33649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return query->mQueryDeliveryStatus;
33733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
33833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
3394d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine    LOGQ("Send query '%s'", query->mQuery);
3404d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine
34133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Send the query. */
3425467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    status_t res = sendMessage(query->mQuery, strlen(query->mQuery) + 1);
34333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (res == NO_ERROR) {
34433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        /* Read the response. */
3455467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        res = receiveMessage(reinterpret_cast<void**>(&query->mReplyBuffer),
3465467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                      &query->mReplySize);
3474d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine        if (res == NO_ERROR) {
3484d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine            LOGQ("Response to query '%s': Status = '%.2s', %d bytes in response",
3494d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine                 query->mQuery, query->mReplyBuffer, query->mReplySize);
3504d4736067242295ccd8dc9fef989b04cac242a75Vladimir Chtchetkine        } else {
3515a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s Response to query '%s' has failed: %s",
3525467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                 __FUNCTION__, query->mQuery, strerror(res));
35333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        }
35433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
3555a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Send query '%s' failed: %s",
3565467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine             __FUNCTION__, query->mQuery, strerror(res));
35733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
35833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
35933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Complete the query, and return its completion handling status. */
36049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    const status_t res1 = query->completeQuery(res);
3615a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res1 != NO_ERROR && res1 != res,
36249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            "%s: Error %d in query '%s' completion",
36349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            __FUNCTION__, res1, query->mQuery);
36449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    return res1;
36533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
36633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
36733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/****************************************************************************
36833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Qemu client for the 'factory' service.
36933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine ***************************************************************************/
37033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
37133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/*
37233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Factory service queries.
37333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine */
37433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
37533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/* Queries list of cameras connected to the host. */
3765467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkineconst char FactoryQemuClient::mQueryList[] = "list";
37733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
37833bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineFactoryQemuClient::FactoryQemuClient()
37933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    : QemuClient()
38033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
38133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
38233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
38333bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineFactoryQemuClient::~FactoryQemuClient()
38433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
38533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
38633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
3875467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t FactoryQemuClient::listCameras(char** list)
38833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
389629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
39016232484c709c565adfbf557025c52f61295c058Vladimir Chtchetkine
3915467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    QemuQuery query(mQueryList);
39249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (doQuery(&query) || !query.isQuerySucceeded()) {
3935a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: List cameras query failed: %s", __FUNCTION__,
39449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine             query.mReplyData ? query.mReplyData : "No error message");
3955467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        return query.getCompletionStatus();
39633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
39733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
39833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Make sure there is a list returned. */
3995467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (query.mReplyDataSize == 0) {
4005a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: No camera list is returned.", __FUNCTION__);
40133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return EINVAL;
40233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
40333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
40433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    /* Copy the list over. */
4055467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    *list = (char*)malloc(query.mReplyDataSize);
40633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    if (*list != NULL) {
4075467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        memcpy(*list, query.mReplyData, query.mReplyDataSize);
408112bc5e57e206ec3e0bc5a335b62eae2eb8892e8Steve Block        ALOGD("Emulated camera list: %s", *list);
40933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return NO_ERROR;
41033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    } else {
4115a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Unable to allocate %d bytes",
4125467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine             __FUNCTION__, query.mReplyDataSize);
41333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        return ENOMEM;
41433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
41533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
41633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
41733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/****************************************************************************
41833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Qemu client for an 'emulated camera' service.
41933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine ***************************************************************************/
42033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
42133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/*
42233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine * Emulated camera queries
42333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine */
42433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
42533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/* Connect to the camera device. */
4265467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkineconst char CameraQemuClient::mQueryConnect[]    = "connect";
42733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/* Disconect from the camera device. */
4285467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkineconst char CameraQemuClient::mQueryDisconnect[] = "disconnect";
42933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/* Start capturing video from the camera device. */
4305467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkineconst char CameraQemuClient::mQueryStart[]      = "start";
43133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/* Stop capturing video from the camera device. */
4325467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkineconst char CameraQemuClient::mQueryStop[]       = "stop";
43333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine/* Get next video frame from the camera device. */
4345467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkineconst char CameraQemuClient::mQueryFrame[]      = "frame";
43533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
43633bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineCameraQemuClient::CameraQemuClient()
43733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    : QemuClient()
43833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
43933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
44033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
44133bda475286a625337ed184e7053fc29e403d57bVladimir ChtchetkineCameraQemuClient::~CameraQemuClient()
44233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
44333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
44433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
44533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
4465467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t CameraQemuClient::queryConnect()
44733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
448629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
44916232484c709c565adfbf557025c52f61295c058Vladimir Chtchetkine
4505467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    QemuQuery query(mQueryConnect);
4515467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    doQuery(&query);
4525467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    const status_t res = query.getCompletionStatus();
4535a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s",
4545467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine            __FUNCTION__, query.mReplyData ? query.mReplyData :
45549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                                             "No error message");
45633bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    return res;
45733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
45833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
4595467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t CameraQemuClient::queryDisconnect()
46033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
461629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
46216232484c709c565adfbf557025c52f61295c058Vladimir Chtchetkine
4635467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    QemuQuery query(mQueryDisconnect);
4645467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    doQuery(&query);
4655467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    const status_t res = query.getCompletionStatus();
4665a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s",
4675467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine            __FUNCTION__, query.mReplyData ? query.mReplyData :
46849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                                             "No error message");
46933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    return res;
47033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
47133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
4725467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t CameraQemuClient::queryStart(uint32_t pixel_format,
47333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine                                      int width,
47433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine                                      int height)
47533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
476629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
47716232484c709c565adfbf557025c52f61295c058Vladimir Chtchetkine
47833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    char query_str[256];
47933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    snprintf(query_str, sizeof(query_str), "%s dim=%dx%d pix=%d",
4805467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine             mQueryStart, width, height, pixel_format);
48133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    QemuQuery query(query_str);
4825467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    doQuery(&query);
4835467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    const status_t res = query.getCompletionStatus();
4845a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s",
4855467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine            __FUNCTION__, query.mReplyData ? query.mReplyData :
48649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                                             "No error message");
48733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    return res;
48833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
48933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
4905467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t CameraQemuClient::queryStop()
49133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
492629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
49316232484c709c565adfbf557025c52f61295c058Vladimir Chtchetkine
4945467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    QemuQuery query(mQueryStop);
4955467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    doQuery(&query);
4965467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    const status_t res = query.getCompletionStatus();
4975a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: Query failed: %s",
4985467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine            __FUNCTION__, query.mReplyData ? query.mReplyData :
49949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                                             "No error message");
50033bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    return res;
50133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
50233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
5035467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t CameraQemuClient::queryFrame(void* vframe,
50433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine                                      void* pframe,
50533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine                                      size_t vframe_size,
506031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine                                      size_t pframe_size,
507031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine                                      float r_scale,
508031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine                                      float g_scale,
509031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine                                      float b_scale,
510031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine                                      float exposure_comp)
51133bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine{
512629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
51349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
51433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    char query_str[256];
515031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine    snprintf(query_str, sizeof(query_str), "%s video=%d preview=%d whiteb=%g,%g,%g expcomp=%g",
5165467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine             mQueryFrame, (vframe && vframe_size) ? vframe_size : 0,
517031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine             (pframe && pframe_size) ? pframe_size : 0, r_scale, g_scale, b_scale,
518031b92f4c7edf17aa6e75e6c4ec3582e0413b744Vladimir Chtchetkine             exposure_comp);
51933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    QemuQuery query(query_str);
5205467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    doQuery(&query);
5215467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    const status_t res = query.getCompletionStatus();
52249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if( res != NO_ERROR) {
5235a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Query failed: %s",
52449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine             __FUNCTION__, query.mReplyData ? query.mReplyData :
52533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine                                              "No error message");
52649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return res;
52749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    }
52849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
52949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    /* Copy requested frames. */
53049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    size_t cur_offset = 0;
53149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    const uint8_t* frame = reinterpret_cast<const uint8_t*>(query.mReplyData);
53249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    /* Video frame is always first. */
53349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (vframe != NULL && vframe_size != 0) {
53449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        /* Make sure that video frame is in. */
53549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        if ((query.mReplyDataSize - cur_offset) >= vframe_size) {
53649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            memcpy(vframe, frame, vframe_size);
53749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            cur_offset += vframe_size;
53849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        } else {
5395a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Reply %d bytes is to small to contain %d bytes video frame",
54049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                 __FUNCTION__, query.mReplyDataSize - cur_offset, vframe_size);
54149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            return EINVAL;
54233bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        }
54349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    }
54449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (pframe != NULL && pframe_size != 0) {
54549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        /* Make sure that preview frame is in. */
54649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        if ((query.mReplyDataSize - cur_offset) >= pframe_size) {
54749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            memcpy(pframe, frame + cur_offset, pframe_size);
54849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            cur_offset += pframe_size;
54949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        } else {
5505a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Reply %d bytes is to small to contain %d bytes preview frame",
55149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                 __FUNCTION__, query.mReplyDataSize - cur_offset, pframe_size);
55249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            return EINVAL;
55333bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine        }
55433bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine    }
55533bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
55649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    return NO_ERROR;
55733bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}
55833bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine
55933bda475286a625337ed184e7053fc29e403d57bVladimir Chtchetkine}; /* namespace android */
560