CameraService.cpp revision d8973a71a3d1dd670e5dcdf6e94ec0cd45444eec
165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/*
265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**
365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Copyright (C) 2008, The Android Open Source Project
465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**
565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Licensed under the Apache License, Version 2.0 (the "License");
665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** you may not use this file except in compliance with the License.
765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** You may obtain a copy of the License at
865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**
965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**     http://www.apache.org/licenses/LICENSE-2.0
1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**
1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Unless required by applicable law or agreed to in writing, software
1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** distributed under the License is distributed on an "AS IS" BASIS,
1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** See the License for the specific language governing permissions and
1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** limitations under the License.
1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian*/
1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define LOG_TAG "CameraService"
198951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev//#define LOG_NDEBUG 0
2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <stdio.h>
2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/types.h>
2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <pthread.h>
242fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li#include <time.h>
2565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
2665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <binder/IPCThreadState.h>
2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <binder/IServiceManager.h>
2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <binder/MemoryBase.h>
2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <binder/MemoryHeapBase.h>
3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <cutils/atomic.h>
31b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra#include <cutils/properties.h>
32bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis#include <gui/SurfaceTextureClient.h>
33df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <gui/Surface.h>
3465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <hardware/hardware.h>
3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/AudioSystem.h>
3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/mediaplayer.h>
372fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li#include <utils/Condition.h>
3865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/Errors.h>
3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/Log.h>
4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/String16.h>
4165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
4265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "CameraService.h"
438951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev#include "CameraHardwareInterface.h"
4465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
4565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android {
4665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
472fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li#define WAIT_RELEASE_TIMEOUT 250 // 250ms
482fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
4965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// Logging support -- this is for debugging only
5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// Use "adb shell dumpsys media.camera -v 1" to change it.
5265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic volatile int32_t gLogLevel = 0;
5365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
54b8a805261bf0282e992d3608035e47d05a898710Steve Block#define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
55b8a805261bf0282e992d3608035e47d05a898710Steve Block#define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic void setLogLevel(int level) {
5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    android_atomic_write(level, &gLogLevel);
5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic int getCallingPid() {
6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return IPCThreadState::self()->getCallingPid();
6565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic int getCallingUid() {
6865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return IPCThreadState::self()->getCallingUid();
6965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
7065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
712fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Listatic long long getTimeInMs() {
722fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    struct timeval t;
732fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    t.tv_sec = t.tv_usec = 0;
742fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    gettimeofday(&t, NULL);
752fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    return t.tv_sec * 1000LL + t.tv_usec / 1000;
762fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li}
772fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
7865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// This is ugly and only safe if we never re-create the CameraService, but
8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// should be ok for now.
8265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic CameraService *gCameraService;
8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianCameraService::CameraService()
858951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev:mSoundRef(0), mModule(0)
8665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
87df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("CameraService started (pid=%d)", getpid());
888951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    gCameraService = this;
898951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev}
9065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
918951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchevvoid CameraService::onFirstRef()
928951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev{
938951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    BnCameraService::onFirstRef();
9465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
958951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
968951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev                (const hw_module_t **)&mModule) < 0) {
9729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not load camera HAL module");
988951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        mNumberOfCameras = 0;
998951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    }
1008951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    else {
1018951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        mNumberOfCameras = mModule->get_number_of_cameras();
1028951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        if (mNumberOfCameras > MAX_CAMERAS) {
10329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
1048951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev                    mNumberOfCameras, MAX_CAMERAS);
1058951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev            mNumberOfCameras = MAX_CAMERAS;
1068951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        }
1078951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        for (int i = 0; i < mNumberOfCameras; i++) {
1088951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev            setCameraFree(i);
1098951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        }
11065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
11165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
11265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
11365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianCameraService::~CameraService() {
11465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (int i = 0; i < mNumberOfCameras; i++) {
11565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (mBusy[i]) {
11629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("camera %d is still in use in destructor!", i);
11765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
11865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
11965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
12065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    gCameraService = NULL;
12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
12265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianint32_t CameraService::getNumberOfCameras() {
12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mNumberOfCameras;
12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
12765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::getCameraInfo(int cameraId,
12865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                                      struct CameraInfo* cameraInfo) {
1298951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    if (!mModule) {
1308951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        return NO_INIT;
1318951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    }
1328951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
13365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
13465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return BAD_VALUE;
13565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1378951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    struct camera_info info;
1388951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    status_t rc = mModule->get_camera_info(cameraId, &info);
1398951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    cameraInfo->facing = info.facing;
1408951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    cameraInfo->orientation = info.orientation;
1418951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    return rc;
14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
14365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiansp<ICamera> CameraService::connect(
1452fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        const sp<ICameraClient>& cameraClient, int cameraId, bool force, bool keep) {
14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
1475861a9a98c641261c4807c976c750e4611b3a57dTyler Luu    sp<CameraHardwareInterface> hardware = NULL;
1485861a9a98c641261c4807c976c750e4611b3a57dTyler Luu
14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
15065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1518951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    if (!mModule) {
15229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Camera HAL module not loaded");
1538951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        return NULL;
1548951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    }
1558951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
15665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<Client> client;
15765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
15829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
15965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            callingPid, cameraId);
16065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NULL;
16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
163a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li    char value[PROPERTY_VALUE_MAX];
164a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li    property_get("sys.secpolicy.camera.disabled", value, "0");
165a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li    if (strcmp(value, "1") == 0) {
166a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li        // Camera is disabled by DevicePolicyManager.
167df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
168a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li        return NULL;
169a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li    }
170a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li
1712fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    if (keep && !checkCallingPermission(String16("android.permission.KEEP_CAMERA"))) {
1722fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        ALOGE("connect X (pid %d) rejected (no KEEP_CAMERA permission).", callingPid);
1732fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        return NULL;
1742fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    }
1752fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
17665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mServiceLock);
1772fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    // Check if there is an existing client.
1782fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    client = mClient[cameraId].promote();
1792fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    if (client != 0 &&
1802fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
1812fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        LOG1("connect X (pid %d) (the same client)", callingPid);
1822fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        return client;
1832fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    }
1842fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
1852fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    if (!force) {
1862fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        if (mClient[cameraId].promote() != 0) {
1872fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            ALOGW("connect X (pid %d) rejected (existing client).", callingPid);
1882fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            return NULL;
18965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
19065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mClient[cameraId].clear();
1912fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        if (mBusy[cameraId]) {
1922fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            ALOGW("connect X (pid %d) rejected (camera %d is still busy).",
1932fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                  callingPid, cameraId);
1942fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            return NULL;
1952fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        }
1962fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    } else { // force == true
1972fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        int i = 0;
1982fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        long long start_time = getTimeInMs();
1992fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        while (i < mNumberOfCameras) {
2002fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            if (getTimeInMs() - start_time >= 3000LL) {
2012fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                ALOGE("connect X (pid %d) rejected (timeout 3s)", callingPid);
2022fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                return NULL;
2032fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            }
20465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
2052fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            client = mClient[i].promote();
2062fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            if (client != 0) {
2072fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                if (client->keep()) {
2082fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    ALOGW("connect X (pid %d) rejected (existing client wants to keeps the camera)",
2092fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                          callingPid);
2102fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    return NULL;
2112fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                } else {
2122fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    ALOGW("New client (pid %d, id=%d). Disconnect the existing client (id=%d).",
2132fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                         callingPid, cameraId, i);
2142fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    // Do not hold mServiceLock because disconnect will try to get it.
2152fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    mServiceLock.unlock();
2162fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    client->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0, &i);
2172fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    client->waitRelease(WAIT_RELEASE_TIMEOUT);
2182fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    client->disconnectInternal(false);
2192fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    mServiceLock.lock();
2202fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    // Restart from the first client because a new client may have connected
2212fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    // when mServiceLock is unlocked.
2222fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    i = 0;
2232fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    continue;
2242fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                }
2252fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            }
2262fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
2272fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            if (mBusy[i]) {
2282fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                // Give the client a chance to release the hardware.
2292fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                mServiceLock.unlock();
2302fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                usleep(10 * 1000);
2312fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                mServiceLock.lock();
2322fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                i = 0; // Restart from the first client
2332fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                continue;
2342fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            }
2352fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
2362fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            i++;
2372fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        }
23865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
23965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
2408951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    struct camera_info info;
2418951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    if (mModule->get_camera_info(cameraId, &info) != OK) {
24229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid camera id %d", cameraId);
243b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li        return NULL;
244b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li    }
2458951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
2468951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    char camera_device_name[10];
2478951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    snprintf(camera_device_name, sizeof(camera_device_name), "%d", cameraId);
2488951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
2495861a9a98c641261c4807c976c750e4611b3a57dTyler Luu    hardware = new CameraHardwareInterface(camera_device_name);
2505861a9a98c641261c4807c976c750e4611b3a57dTyler Luu    if (hardware->initialize(&mModule->common) != OK) {
2515861a9a98c641261c4807c976c750e4611b3a57dTyler Luu        hardware.clear();
2525861a9a98c641261c4807c976c750e4611b3a57dTyler Luu        return NULL;
2535861a9a98c641261c4807c976c750e4611b3a57dTyler Luu    }
2545861a9a98c641261c4807c976c750e4611b3a57dTyler Luu
2552fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    client = new Client(this, cameraClient, hardware, cameraId, info.facing,
2562fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                        callingPid, keep);
2572fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    // We need to clear the hardware here. After the destructor of mServiceLock
2582fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    // finishes, a new client may connect and disconnect this client. If this
2592fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    // reference is not cleared, the destructor of CameraHardwareInterface
2602fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    // cannot run. The new client will not be able to connect.
2612fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    hardware.clear();
26265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mClient[cameraId] = client;
2632fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    LOG1("CameraService::connect X (id %d)", cameraId);
26465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return client;
26565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
26665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
26765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
26865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
26965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("CameraService::removeClient E (pid %d)", callingPid);
27065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
27165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (int i = 0; i < mNumberOfCameras; i++) {
27265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // Declare this before the lock to make absolutely sure the
27365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // destructor won't be called with the lock held.
27465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        sp<Client> client;
27565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
27665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        Mutex::Autolock lock(mServiceLock);
27765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
27865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // This happens when we have already disconnected (or this is
27965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // just another unused camera).
28065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (mClient[i] == 0) continue;
28165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
28265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // Promote mClient. It can fail if we are called from this path:
28365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // Client::~Client() -> disconnect() -> removeClient().
28465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        client = mClient[i].promote();
28565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
28665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (client == 0) {
28765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            mClient[i].clear();
28865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            continue;
28965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
29065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
29165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
29265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            // Found our camera, clear and leave.
29365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            LOG1("removeClient: clear camera %d", i);
29465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            mClient[i].clear();
29565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
29665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
29765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
29865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
29965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("CameraService::removeClient X (pid %d)", callingPid);
30065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
30165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
302d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young ParkCameraService::Client* CameraService::getClientByIdUnsafe(int cameraId) {
30365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
304d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    return mClient[cameraId].unsafe_get();
305d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park}
306d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
307d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young ParkMutex* CameraService::getClientLockById(int cameraId) {
308d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
309d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    return &mClientLock[cameraId];
31065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
31165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
31265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::onTransact(
31365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
31465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // Permission checks
31565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    switch (code) {
31665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case BnCameraService::CONNECT:
31765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            const int pid = getCallingPid();
31865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            const int self_pid = getpid();
31965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            if (pid != self_pid) {
32065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                // we're called from a different process, do the real check
32165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                if (!checkCallingPermission(
32265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        String16("android.permission.CAMERA"))) {
32365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    const int uid = getCallingUid();
32429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Permission Denial: "
32565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                         "can't use the camera pid=%d, uid=%d", pid, uid);
32665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    return PERMISSION_DENIED;
32765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                }
32865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
32965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
33065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
33165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
33265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return BnCameraService::onTransact(code, data, reply, flags);
33365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
33465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
33565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// The reason we need this busy bit is a new CameraService::connect() request
33665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// may come in while the previous Client's destructor has not been run or is
33765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// still running. If the last strong reference of the previous Client is gone
33865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// but the destructor has not been finished, we should not allow the new Client
33965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// to be created because we need to wait for the previous Client to tear down
34065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// the hardware first.
34165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::setCameraBusy(int cameraId) {
34265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    android_atomic_write(1, &mBusy[cameraId]);
34365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
34465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
34565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::setCameraFree(int cameraId) {
34665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    android_atomic_write(0, &mBusy[cameraId]);
34765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
34865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
34965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// We share the media players for shutter and recording sound for all clients.
35065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// A reference count is kept to determine when we will actually release the
35165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// media players.
35265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
353ff4f55c8d77e276dbcceedb4e560ca1d91ba38baChih-Chung ChangMediaPlayer* CameraService::newMediaPlayer(const char *file) {
35465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    MediaPlayer* mp = new MediaPlayer();
35565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mp->setDataSource(file, NULL) == NO_ERROR) {
35660a78ac9535878984b0777788760b9ee7465c5e6Eino-Ville Talvala        mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
35765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mp->prepare();
35865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    } else {
35929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to load CameraService sounds: %s", file);
36065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NULL;
36165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
36265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mp;
36365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
36465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
36565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::loadSound() {
36665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mSoundLock);
36765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("CameraService::loadSound ref=%d", mSoundRef);
36865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mSoundRef++) return;
36965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
37065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
37165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
37265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
37365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
37465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::releaseSound() {
37565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mSoundLock);
37665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("CameraService::releaseSound ref=%d", mSoundRef);
37765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (--mSoundRef) return;
37865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
37965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (int i = 0; i < NUM_SOUNDS; i++) {
38065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (mSoundPlayer[i] != 0) {
38165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            mSoundPlayer[i]->disconnect();
38265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            mSoundPlayer[i].clear();
38365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
38465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
38565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
38665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
38765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::playSound(sound_kind kind) {
38865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("playSound(%d)", kind);
38965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mSoundLock);
39065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<MediaPlayer> player = mSoundPlayer[kind];
39165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (player != 0) {
3928888a75f01d904541e409e858d23e4150ace34b6Chih-Chung Chang        player->seekTo(0);
3938888a75f01d904541e409e858d23e4150ace34b6Chih-Chung Chang        player->start();
39465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
39565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
39665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
39765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
39865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
39965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianCameraService::Client::Client(const sp<CameraService>& cameraService,
400b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li        const sp<ICameraClient>& cameraClient,
401b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li        const sp<CameraHardwareInterface>& hardware,
4022fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        int cameraId, int cameraFacing, int clientPid, bool keep) {
40365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
4042fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
40565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
40665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraService = cameraService;
40765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraClient = cameraClient;
408b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li    mHardware = hardware;
40965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraId = cameraId;
410e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    mCameraFacing = cameraFacing;
41165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mClientPid = clientPid;
4122fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    mKeep = keep;
41365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mMsgEnabled = 0;
414bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis    mSurface = 0;
415bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis    mPreviewWindow = 0;
416d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    mDestructionStarted = false;
41765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->setCallbacks(notifyCallback,
41865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            dataCallback,
41965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            dataCallbackTimestamp,
42065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            (void *)cameraId);
42165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
42257c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    // Enable zoom, error, focus, and metadata messages by default
42357c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
424d620506220a15177942a8168d09c517740e908d0Wu-cheng Li                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
42565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
42665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // Callback is disabled by default
4279e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
428e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
429b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    mPlayShutterSound = true;
43065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    cameraService->setCameraBusy(cameraId);
43165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    cameraService->loadSound();
4322fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
43365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
43465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
43565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// tear down the client
43665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianCameraService::Client::~Client() {
437d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    // this lock should never be NULL
438d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Mutex* lock = mCameraService->getClientLockById(mCameraId);
439d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    lock->lock();
440d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    mDestructionStarted = true;
441d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    // client will not be accessed from callback. should unlock to prevent dead-lock in disconnect
442d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    lock->unlock();
44365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
44465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
44565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
44665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // set mClientPid to let disconnet() tear down the hardware
44765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mClientPid = callingPid;
44865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disconnect();
44965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraService->releaseSound();
45065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
45165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
45265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
45365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
45465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
45565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::checkPid() const {
45665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
45765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (callingPid == mClientPid) return NO_ERROR;
45865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
4595ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block    ALOGW("attempt to use a locked camera from a different process"
46065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian         " (old pid %d, new pid %d)", mClientPid, callingPid);
46165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return EBUSY;
46265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
46365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
46465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::checkPidAndHardware() const {
46565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPid();
46665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
46765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mHardware == 0) {
46829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
46965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return INVALID_OPERATION;
47065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
47165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return NO_ERROR;
47265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
47365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
47465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::lock() {
47565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
47665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("lock (pid %d)", callingPid);
47765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
47865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
47965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // lock camera to this client if the the camera is unlocked
48065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mClientPid == 0) {
48165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mClientPid = callingPid;
48265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NO_ERROR;
48365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
48465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
48565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
48665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return checkPid();
48765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
48865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
48965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::unlock() {
49065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
49165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("unlock (pid %d)", callingPid);
49265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
49365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
49465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // allow anyone to use camera (after they lock the camera)
49565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPid();
49665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result == NO_ERROR) {
4974ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mHardware->recordingEnabled()) {
49829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Not allowed to unlock camera during recording.");
4994ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li            return INVALID_OPERATION;
5004ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        }
50165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mClientPid = 0;
50265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        LOG1("clear mCameraClient (pid %d)", callingPid);
50365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // we need to remove the reference to ICameraClient so that when the app
50465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // goes away, the reference count goes to 0.
50565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mCameraClient.clear();
50665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
50765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return result;
50865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
50965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
51065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// connect a new client to the camera
51165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::connect(const sp<ICameraClient>& client) {
51265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
51365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("connect E (pid %d)", callingPid);
51465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
51565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
51665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mClientPid != 0 && checkPid() != NO_ERROR) {
5175ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
51865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                mClientPid, callingPid);
51965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return EBUSY;
52065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
52165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
52265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
52365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        LOG1("Connect to the same client");
52465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NO_ERROR;
52565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
52665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5279e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
52865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mClientPid = callingPid;
52965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraClient = client;
53065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
53165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("connect X (pid %d)", callingPid);
53265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return NO_ERROR;
53365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
53465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5357574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Listatic void disconnectWindow(const sp<ANativeWindow>& window) {
5367574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li    if (window != 0) {
537c3da3434cb57f47284ea06bb9065eaa2fe033efbMathias Agopian        status_t result = native_window_api_disconnect(window.get(),
5387574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li                NATIVE_WINDOW_API_CAMERA);
5397574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li        if (result != NO_ERROR) {
5405ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
5417574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li                    result);
5427574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li        }
5437574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li    }
5447574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li}
5457574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li
54665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::disconnect() {
5472fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    disconnectInternal(true);
5482fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li}
5492fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
5502fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Livoid CameraService::Client::disconnectInternal(bool needCheckPid) {
55165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int callingPid = getCallingPid();
5522fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    LOG1("disconnectInternal E (pid %d)", callingPid);
55365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
55465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5552fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    if (needCheckPid) {
5562fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        if (checkPid() != NO_ERROR) {
5572fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            ALOGW("different client - don't disconnect");
5582fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            return;
5592fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        }
56065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5612fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        if (mClientPid <= 0) {
5622fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
5632fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li            return;
5642fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        }
56565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
56665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
56765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // Make sure disconnect() is done once and once only, whether it is called
56865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // from the user directly, or called by the destructor.
56965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mHardware == 0) return;
57065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
57165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("hardware teardown");
57265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // Before destroying mHardware, we must make sure it's in the
57365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // idle state.
57465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // Turn off all messages.
57565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disableMsgType(CAMERA_MSG_ALL_MSGS);
57665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->stopPreview();
57765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->cancelPicture();
57865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // Release the hardware resources.
57965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->release();
58003dfce9672b36c1a334959a602f909b8410bec50Mathias Agopian
5814b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis    // Release the held ANativeWindow resources.
5824b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis    if (mPreviewWindow != 0) {
5837574da5a501fc9289fee49fdaf1fdb9d47dae2b6Wu-cheng Li        disconnectWindow(mPreviewWindow);
5844b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis        mPreviewWindow = 0;
5854b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis        mHardware->setPreviewWindow(mPreviewWindow);
5864b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis    }
58765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware.clear();
58865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
58965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraService->removeClient(mCameraClient);
59065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraService->setCameraFree(mCameraId);
5912fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    mReleaseCondition.signal();
5922fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
5932fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    LOG1("disconnectInternal X (pid %d)", callingPid);
5942fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li}
59565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5962fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Livoid CameraService::Client::waitRelease(int ms) {
5972fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    Mutex::Autolock lock(mLock);
5982fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    if (mHardware != 0) {
5992fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        mReleaseCondition.waitRelative(mLock, ms * 1000000);
6002fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    }
60165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
60265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
60365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
60465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6050ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennisstatus_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
6060ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        const sp<ANativeWindow>& window) {
60765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
60865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPidAndHardware();
60965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
61065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
61165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // return if no change in surface.
6128b1027d3f873fc15c70f8645f1856936b69241a4Mathias Agopian    if (binder == mSurface) {
6130ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        return NO_ERROR;
61465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
61565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6160ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    if (window != 0) {
617c3da3434cb57f47284ea06bb9065eaa2fe033efbMathias Agopian        result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
6180ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        if (result != NO_ERROR) {
61929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
6200ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis                    result);
6210ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis            return result;
6220ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        }
62365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
624bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis
6250ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    // If preview has been already started, register preview buffers now.
62665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mHardware->previewEnabled()) {
6270ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        if (window != 0) {
6289bc7af17974f448291a44912566ec7472a0d798bMathias Agopian            native_window_set_scaling_mode(window.get(),
6299bc7af17974f448291a44912566ec7472a0d798bMathias Agopian                    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
6300ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis            native_window_set_buffers_transform(window.get(), mOrientation);
6310ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis            result = mHardware->setPreviewWindow(window);
63265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
63365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
63465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6350ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    if (result == NO_ERROR) {
6360ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        // Everything has succeeded.  Disconnect the old window and remember the
6370ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        // new window.
6380ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        disconnectWindow(mPreviewWindow);
6390ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        mSurface = binder;
6400ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        mPreviewWindow = window;
6410ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    } else {
6420ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        // Something went wrong after we connected to the new window, so
6430ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        // disconnect here.
6440ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        disconnectWindow(window);
6450ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    }
6460ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis
64765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return result;
64865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
64965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6500ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis// set the Surface that the preview will use
6510ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennisstatus_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
6520ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
6530ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis
6540ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
6550ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    sp<ANativeWindow> window(surface);
6560ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    return setPreviewWindow(binder, window);
6570ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis}
6580ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis
659bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis// set the SurfaceTexture that the preview will use
660bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennisstatus_t CameraService::Client::setPreviewTexture(
661bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis        const sp<ISurfaceTexture>& surfaceTexture) {
662bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis    LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
663bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis            getCallingPid());
664bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis
6650ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    sp<IBinder> binder;
6660ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    sp<ANativeWindow> window;
667bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis    if (surfaceTexture != 0) {
6680ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        binder = surfaceTexture->asBinder();
6690ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis        window = new SurfaceTextureClient(surfaceTexture);
670bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis    }
6710ed3ec00d0242c9dc77532fe0cf0082645b6662cJamie Gennis    return setPreviewWindow(binder, window);
672bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis}
673bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis
67465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// set the preview callback flag to affect how the received frames from
67565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// preview are handled.
67665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
67765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
67865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
67965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkPidAndHardware() != NO_ERROR) return;
68065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
68165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mPreviewCallbackFlag = callback_flag;
6829e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev    if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
6830667de7038238c31af77865eb6d83c5ae9ca1b1eWu-cheng Li        enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
6840667de7038238c31af77865eb6d83c5ae9ca1b1eWu-cheng Li    } else {
6850667de7038238c31af77865eb6d83c5ae9ca1b1eWu-cheng Li        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
68665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
68765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
68865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
68965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// start preview mode
69065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::startPreview() {
69165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("startPreview (pid %d)", getCallingPid());
69265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return startCameraMode(CAMERA_PREVIEW_MODE);
69365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
69465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
69565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// start recording mode
69665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::startRecording() {
69765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("startRecording (pid %d)", getCallingPid());
69865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return startCameraMode(CAMERA_RECORDING_MODE);
69965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
70065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
70165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// start preview or recording
70265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::startCameraMode(camera_mode mode) {
70365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("startCameraMode(%d)", mode);
70465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
70565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPidAndHardware();
70665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
70765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
70865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    switch(mode) {
70965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case CAMERA_PREVIEW_MODE:
7104b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis            if (mSurface == 0 && mPreviewWindow == 0) {
71165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                LOG1("mSurface is not set yet.");
71265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                // still able to start preview in this case.
71365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
71465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return startPreviewMode();
71565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case CAMERA_RECORDING_MODE:
7164b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis            if (mSurface == 0 && mPreviewWindow == 0) {
71729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
71865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                return INVALID_OPERATION;
71965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
72065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return startRecordingMode();
72165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        default:
72265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return UNKNOWN_ERROR;
72365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
72465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
72565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
72665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::startPreviewMode() {
72765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("startPreviewMode");
72865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = NO_ERROR;
72965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
73065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // if preview has been enabled, nothing needs to be done
73165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mHardware->previewEnabled()) {
73265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NO_ERROR;
73365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
73465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
73503dfce9672b36c1a334959a602f909b8410bec50Mathias Agopian    if (mPreviewWindow != 0) {
7369bc7af17974f448291a44912566ec7472a0d798bMathias Agopian        native_window_set_scaling_mode(mPreviewWindow.get(),
7379bc7af17974f448291a44912566ec7472a0d798bMathias Agopian                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
73803dfce9672b36c1a334959a602f909b8410bec50Mathias Agopian        native_window_set_buffers_transform(mPreviewWindow.get(),
73903dfce9672b36c1a334959a602f909b8410bec50Mathias Agopian                mOrientation);
74065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
74103dfce9672b36c1a334959a602f909b8410bec50Mathias Agopian    mHardware->setPreviewWindow(mPreviewWindow);
74203dfce9672b36c1a334959a602f909b8410bec50Mathias Agopian    result = mHardware->startPreview();
74303dfce9672b36c1a334959a602f909b8410bec50Mathias Agopian
74465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return result;
74565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
74665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
74765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::startRecordingMode() {
74865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("startRecordingMode");
74965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = NO_ERROR;
75065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
75165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // if recording has been enabled, nothing needs to be done
75265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mHardware->recordingEnabled()) {
75365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NO_ERROR;
75465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
75565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
75665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // if preview has not been started, start preview first
75765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (!mHardware->previewEnabled()) {
75865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        result = startPreviewMode();
75965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (result != NO_ERROR) {
76065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return result;
76165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
76265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
76365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
76465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // start recording mode
76565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
76665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraService->playSound(SOUND_RECORDING);
76765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    result = mHardware->startRecording();
76865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) {
76929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("mHardware->startRecording() failed with status %d", result);
77065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
77165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return result;
77265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
77365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
77465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// stop preview mode
77565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::stopPreview() {
77665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("stopPreview (pid %d)", getCallingPid());
77765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
77865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkPidAndHardware() != NO_ERROR) return;
77965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
7804b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis
78165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
78265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->stopPreview();
78365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
78465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mPreviewBuffer.clear();
78565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
78665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
78765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// stop recording mode
78865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::stopRecording() {
78965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("stopRecording (pid %d)", getCallingPid());
79065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
79165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkPidAndHardware() != NO_ERROR) return;
79265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
79365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mCameraService->playSound(SOUND_RECORDING);
79465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disableMsgType(CAMERA_MSG_VIDEO_FRAME);
79565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->stopRecording();
79665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
79765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mPreviewBuffer.clear();
79865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
79965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
80065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// release a recording frame
80165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
80265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
80365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkPidAndHardware() != NO_ERROR) return;
80465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->releaseRecordingFrame(mem);
80565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
80665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
807e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dongstatus_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
808e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong{
809e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong    LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
810e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong    Mutex::Autolock lock(mLock);
811e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong    if (checkPidAndHardware() != NO_ERROR) {
812e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong        return UNKNOWN_ERROR;
813e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong    }
814e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong    return mHardware->storeMetaDataInBuffers(enabled);
815e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong}
816e2ad6734eccc4b9ea7857c747ff9469a9c11ba09James Dong
81765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbool CameraService::Client::previewEnabled() {
81865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("previewEnabled (pid %d)", getCallingPid());
81965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
82065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
82165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkPidAndHardware() != NO_ERROR) return false;
82265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mHardware->previewEnabled();
82365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
82465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
82565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbool CameraService::Client::recordingEnabled() {
82665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("recordingEnabled (pid %d)", getCallingPid());
82765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
82865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
82965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkPidAndHardware() != NO_ERROR) return false;
83065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mHardware->recordingEnabled();
83165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
83265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
83365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::autoFocus() {
83465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("autoFocus (pid %d)", getCallingPid());
83565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
83665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
83765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPidAndHardware();
83865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
83965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
84065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mHardware->autoFocus();
84165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
84265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
84365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::cancelAutoFocus() {
84465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("cancelAutoFocus (pid %d)", getCallingPid());
84565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
84665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
84765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPidAndHardware();
84865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
84965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
85065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mHardware->cancelAutoFocus();
85165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
85265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
85365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// take a picture - image is returned in callback
854e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dongstatus_t CameraService::Client::takePicture(int msgType) {
855e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong    LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
85665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
85765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
85865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPidAndHardware();
85965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
86065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
861e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong    if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
862e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong        (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
86329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
864e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong                " cannot be both enabled");
865e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong        return BAD_VALUE;
866e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong    }
867e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong
868e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong    // We only accept picture related message types
869e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong    // and ignore other types of messages for takePicture().
870e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong    int picMsgType = msgType
871e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong                        & (CAMERA_MSG_SHUTTER |
872e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong                           CAMERA_MSG_POSTVIEW_FRAME |
873e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong                           CAMERA_MSG_RAW_IMAGE |
874e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
875e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong                           CAMERA_MSG_COMPRESSED_IMAGE);
876e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong
877e468ac57f6e8afc6078c76d4eb1ac327112a3de0James Dong    enableMsgType(picMsgType);
87865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
87965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mHardware->takePicture();
88065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
88165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
88265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// set preview/capture parameters - key/value pairs
88365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::setParameters(const String8& params) {
88465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
88565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
88665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
88765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPidAndHardware();
88865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
88965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
89065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    CameraParameters p(params);
89165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mHardware->setParameters(p);
89265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
89365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
89465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// get preview/capture parameters - key/value pairs
89565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianString8 CameraService::Client::getParameters() const {
89665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
89765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkPidAndHardware() != NO_ERROR) return String8();
89865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
89965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    String8 params(mHardware->getParameters().flatten());
90065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
90165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return params;
90265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
90365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
904b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra// enable shutter sound
905b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatrastatus_t CameraService::Client::enableShutterSound(bool enable) {
906b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    LOG1("enableShutterSound (pid %d)", getCallingPid());
907b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra
908b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    status_t result = checkPidAndHardware();
909b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    if (result != NO_ERROR) return result;
910b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra
911b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    if (enable) {
912b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        mPlayShutterSound = true;
913b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        return OK;
914b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    }
915b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra
916b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    // Disabling shutter sound may not be allowed. In that case only
917b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    // allow the mediaserver process to disable the sound.
918b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    char value[PROPERTY_VALUE_MAX];
919b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    property_get("ro.camera.sound.forced", value, "0");
920b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    if (strcmp(value, "0") != 0) {
921b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        // Disabling shutter sound is not allowed. Deny if the current
922b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        // process is not mediaserver.
923b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        if (getCallingPid() != getpid()) {
92429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
925b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra            return PERMISSION_DENIED;
926b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        }
927b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    }
928b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra
929b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    mPlayShutterSound = false;
930b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    return OK;
931b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra}
932b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra
93365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
93465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG1("sendCommand (pid %d)", getCallingPid());
9354a73f3da3501db6e95473a4a653d6319c6d618e2Wu-cheng Li    int orientation;
93665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock lock(mLock);
93765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t result = checkPidAndHardware();
93865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (result != NO_ERROR) return result;
93965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
94065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
941e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        // Mirror the preview if the camera is front-facing.
942e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
943e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        if (orientation == -1) return BAD_VALUE;
944e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li
9454a73f3da3501db6e95473a4a653d6319c6d618e2Wu-cheng Li        if (mOrientation != orientation) {
9464a73f3da3501db6e95473a4a653d6319c6d618e2Wu-cheng Li            mOrientation = orientation;
947b9f588677910cac6ffc0346092bfcfe1c6620b90Wu-cheng Li            if (mPreviewWindow != 0) {
948b9f588677910cac6ffc0346092bfcfe1c6620b90Wu-cheng Li                native_window_set_buffers_transform(mPreviewWindow.get(),
949b9f588677910cac6ffc0346092bfcfe1c6620b90Wu-cheng Li                        mOrientation);
950b9f588677910cac6ffc0346092bfcfe1c6620b90Wu-cheng Li            }
9514a73f3da3501db6e95473a4a653d6319c6d618e2Wu-cheng Li        }
95265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return OK;
953b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
954b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        switch (arg1) {
955b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra            case 0:
956b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra                enableShutterSound(false);
957b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra                break;
958b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra            case 1:
959b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra                enableShutterSound(true);
960b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra                break;
961b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra            default:
962b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra                return BAD_VALUE;
963b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        }
964b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        return OK;
9653b7b358d1a45844ca427626554ff81f472fd1583Nipun Kwatra    } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
9663b7b358d1a45844ca427626554ff81f472fd1583Nipun Kwatra        mCameraService->playSound(SOUND_RECORDING);
9672fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    } else if (cmd == CAMERA_CMD_PING) {
9682fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        // If mHardware is 0, checkPidAndHardware will return error.
9692fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li        return OK;
97065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
97165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
97265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return mHardware->sendCommand(cmd, arg1, arg2);
97365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
97465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
97565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
97665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
97765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::enableMsgType(int32_t msgType) {
97865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    android_atomic_or(msgType, &mMsgEnabled);
97965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->enableMsgType(msgType);
98065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
98165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
98265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::disableMsgType(int32_t msgType) {
98365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    android_atomic_and(~msgType, &mMsgEnabled);
98465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mHardware->disableMsgType(msgType);
98565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
98665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
98765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define CHECK_MESSAGE_INTERVAL 10 // 10ms
98865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
98965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int sleepCount = 0;
99065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    while (mMsgEnabled & msgType) {
99165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (mLock.tryLock() == NO_ERROR) {
99265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            if (sleepCount > 0) {
99365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                LOG1("lockIfMessageWanted(%d): waited for %d ms",
99465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
99565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
99665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            return true;
99765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
99865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (sleepCount++ == 0) {
99965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
100065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
100165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        usleep(CHECK_MESSAGE_INTERVAL * 1000);
100265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
10035ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block    ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
100465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return false;
100565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
100665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
100765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
100865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1009d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young ParkMutex* CameraService::Client::getClientLockFromCookie(void* user) {
1010d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    return gCameraService->getClientLockById((int) user);
1011d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park}
1012d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
1013d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park// Provide client pointer for callbacks. Client lock returned from getClientLockFromCookie should
1014d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park// be acquired for this to be safe
1015d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young ParkCameraService::Client* CameraService::Client::getClientFromCookie(void* user) {
1016d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Client* client = gCameraService->getClientByIdUnsafe((int) user);
101765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
101865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // This could happen if the Client is in the process of shutting down (the
101965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // last strong reference is gone, but the destructor hasn't finished
102065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // stopping the hardware).
1021d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (client == NULL) return NULL;
1022d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
1023d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    // destruction already started, so should not be accessed
1024d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (client->mDestructionStarted) return NULL;
102565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
102665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // The checks below are not necessary and are for debugging only.
102765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (client->mCameraService.get() != gCameraService) {
102829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("mismatch service!");
102965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NULL;
103065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
103165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
103265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (client->mHardware == 0) {
103329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("mHardware == 0: callback after disconnect()?");
103465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return NULL;
103565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
103665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
103765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return client;
103865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
103965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
104065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// Callback messages can be dispatched to internal handlers or pass to our
104165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// client's callback functions, depending on the message type.
104265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//
104365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// notifyCallback:
104465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      CAMERA_MSG_SHUTTER              handleShutter
104565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      (others)                        c->notifyCallback
104665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// dataCallback:
104765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      CAMERA_MSG_PREVIEW_FRAME        handlePreviewData
104865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      CAMERA_MSG_POSTVIEW_FRAME       handlePostview
104965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      CAMERA_MSG_RAW_IMAGE            handleRawPicture
105065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      CAMERA_MSG_COMPRESSED_IMAGE     handleCompressedPicture
105165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      (others)                        c->dataCallback
105265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// dataCallbackTimestamp
105365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//      (others)                        c->dataCallbackTimestamp
105465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//
105565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// NOTE: the *Callback functions grab mLock of the client before passing
105665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// control to handle* functions. So the handle* functions must release the
105765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// lock before calling the ICameraClient's callbacks, so those callbacks can
105865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// invoke methods in the Client class again (For example, the preview frame
105965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// callback may want to releaseRecordingFrame). The handle* functions must
106065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// release the lock after all accesses to member variables, so it must be
106165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// handled very carefully.
106265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
106365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
106465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        int32_t ext2, void* user) {
106565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG2("notifyCallback(%d)", msgType);
106665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1067d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Mutex* lock = getClientLockFromCookie(user);
1068d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (lock == NULL) return;
1069d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Mutex::Autolock alock(*lock);
1070d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
1071d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Client* client = getClientFromCookie(user);
1072d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (client == NULL) return;
1073d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
107465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (!client->lockIfMessageWanted(msgType)) return;
107565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
107665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    switch (msgType) {
107765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case CAMERA_MSG_SHUTTER:
107865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            // ext1 is the dimension of the yuv picture.
1079108dddf924d714c811dd565b8f4c7a0178cca2f2Iliyan Malchev            client->handleShutter();
108065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
108165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        default:
108265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            client->handleGenericNotify(msgType, ext1, ext2);
108365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
108465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
108565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
108665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
108765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::dataCallback(int32_t msgType,
1088ff09ef8f18eed29bce50c7817df2fd52d2b50cf6Wu-cheng Li        const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
108965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG2("dataCallback(%d)", msgType);
109065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1091d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Mutex* lock = getClientLockFromCookie(user);
1092d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (lock == NULL) return;
1093d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Mutex::Autolock alock(*lock);
1094d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
1095d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Client* client = getClientFromCookie(user);
1096d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (client == NULL) return;
109765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1098d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (!client->lockIfMessageWanted(msgType)) return;
109957c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    if (dataPtr == 0 && metadata == NULL) {
110029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Null data returned in data callback");
110165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
110265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return;
110365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
110465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
110557c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
110665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case CAMERA_MSG_PREVIEW_FRAME:
110757c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li            client->handlePreviewData(msgType, dataPtr, metadata);
110865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
110965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case CAMERA_MSG_POSTVIEW_FRAME:
111065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            client->handlePostview(dataPtr);
111165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
111265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case CAMERA_MSG_RAW_IMAGE:
111365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            client->handleRawPicture(dataPtr);
111465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
111565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        case CAMERA_MSG_COMPRESSED_IMAGE:
111665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            client->handleCompressedPicture(dataPtr);
111765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
111865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        default:
111957c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li            client->handleGenericData(msgType, dataPtr, metadata);
112065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
112165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
112265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
112365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
112465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
112565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
112665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG2("dataCallbackTimestamp(%d)", msgType);
112765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1128d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Mutex* lock = getClientLockFromCookie(user);
1129d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (lock == NULL) return;
1130d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Mutex::Autolock alock(*lock);
1131d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
1132d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    Client* client = getClientFromCookie(user);
1133d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (client == NULL) return;
1134d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
1135986ef2ad4c96952711d87af481f3afb40aa10775James Dong    if (!client->lockIfMessageWanted(msgType)) return;
113665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
113765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (dataPtr == 0) {
113829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Null data returned in data with timestamp callback");
113965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
114065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return;
114165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
114265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
114365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
114465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
114565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
114665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// snapshot taken callback
1147108dddf924d714c811dd565b8f4c7a0178cca2f2Iliyan Malchevvoid CameraService::Client::handleShutter(void) {
1148b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    if (mPlayShutterSound) {
1149b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra        mCameraService->playSound(SOUND_SHUTTER);
1150b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra    }
115165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
115265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
115365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
115465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mLock.unlock();
115565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
115665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
115765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
115865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disableMsgType(CAMERA_MSG_SHUTTER);
115965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
116065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
116165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
116265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
116365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// preview callback - frame buffer update
116457c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Livoid CameraService::Client::handlePreviewData(int32_t msgType,
116557c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                                              const sp<IMemory>& mem,
116657c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                                              camera_frame_metadata_t *metadata) {
116765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    ssize_t offset;
116865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    size_t size;
116965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
117065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
117165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // local copy of the callback flags
117265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int flags = mPreviewCallbackFlag;
117365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
117465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // is callback enabled?
11759e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev    if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
117665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // If the enable bit is off, the copy-out and one-shot bits are ignored
117765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        LOG2("frame callback is disabled");
117865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mLock.unlock();
117965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return;
118065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
118165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
118265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // hold a strong pointer to the client
118365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
118465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
118565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // clear callback flags if no client or one-shot mode
11869e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev    if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
118765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        LOG2("Disable preview callback");
11889e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev        mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
11899e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev                                  CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
11909e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev                                  CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
11910667de7038238c31af77865eb6d83c5ae9ca1b1eWu-cheng Li        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
119265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
119365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
119465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
119565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // Is the received frame copied out or not?
11969e626526453f91999bdf3de4c2ec8e55c5d90511Iliyan Malchev        if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
119765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            LOG2("frame is copied");
119857c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li            copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
119965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        } else {
120065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            LOG2("frame is forwarded");
120165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            mLock.unlock();
120257c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li            c->dataCallback(msgType, mem, metadata);
120365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
120465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    } else {
120565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mLock.unlock();
120665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
120765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
120865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
120965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// picture callback - postview image ready
121065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::handlePostview(const sp<IMemory>& mem) {
121165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
121265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
121365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
121465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
121565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
121657c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
121765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
121865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
121965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
122065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// picture callback - raw image ready
122165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
122265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disableMsgType(CAMERA_MSG_RAW_IMAGE);
122365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
122465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    ssize_t offset;
122565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    size_t size;
122665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
122765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
122865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
122965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
123065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
123157c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
123265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
123365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
123465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
123565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// picture callback - compressed picture ready
123665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
123765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
123865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
123965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
124065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
124165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
124257c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
124365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
124465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
124565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
124665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
124765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::handleGenericNotify(int32_t msgType,
124865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int32_t ext1, int32_t ext2) {
124965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
125065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
125165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
125265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        c->notifyCallback(msgType, ext1, ext2);
125365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
125465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
125565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
125665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::handleGenericData(int32_t msgType,
125757c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
125865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
125965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
126065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
126157c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li        c->dataCallback(msgType, dataPtr, metadata);
126265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
126365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
126465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
126565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
126665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int32_t msgType, const sp<IMemory>& dataPtr) {
126765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<ICameraClient> c = mCameraClient;
126865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
126965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (c != 0) {
127065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
127165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
127265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
127365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
127465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid CameraService::Client::copyFrameAndPostCopiedFrame(
127557c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li        int32_t msgType, const sp<ICameraClient>& client,
127657c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li        const sp<IMemoryHeap>& heap, size_t offset, size_t size,
127757c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li        camera_frame_metadata_t *metadata) {
127865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    LOG2("copyFrameAndPostCopiedFrame");
127965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // It is necessary to copy out of pmem before sending this to
128065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // the callback. For efficiency, reuse the same MemoryHeapBase
128165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // provided it's big enough. Don't allocate the memory or
128265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // perform the copy if there's no callback.
128365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // hold the preview lock while we grab a reference to the preview buffer
128465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<MemoryHeapBase> previewBuffer;
128565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
128665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mPreviewBuffer == 0) {
128765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
128865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    } else if (size > mPreviewBuffer->virtualSize()) {
128965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mPreviewBuffer.clear();
129065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
129165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
129265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mPreviewBuffer == 0) {
129329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to allocate space for preview buffer");
129465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mLock.unlock();
129565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return;
129665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
129765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    previewBuffer = mPreviewBuffer;
129865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
129965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
130065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
130165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
130265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (frame == 0) {
130329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to allocate space for frame callback");
130465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mLock.unlock();
130565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return;
130665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
130765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
130865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLock.unlock();
130957c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    client->dataCallback(msgType, frame, metadata);
131065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
131165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1312e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Liint CameraService::Client::getOrientation(int degrees, bool mirror) {
1313e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    if (!mirror) {
1314e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        if (degrees == 0) return 0;
1315e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
1316e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
1317e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
1318e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    } else {  // Do mirror (horizontal flip)
1319e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        if (degrees == 0) {           // FLIP_H and ROT_0
1320e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li            return HAL_TRANSFORM_FLIP_H;
1321e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        } else if (degrees == 90) {   // FLIP_H and ROT_90
1322e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li            return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
1323e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        } else if (degrees == 180) {  // FLIP_H and ROT_180
1324e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li            return HAL_TRANSFORM_FLIP_V;
1325e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        } else if (degrees == 270) {  // FLIP_H and ROT_270
1326e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li            return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
1327e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li        }
1328e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    }
132929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
1330e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    return -1;
1331e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li}
1332e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li
13332fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li// Whether the client wants to keep the camera from taking
13342fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Libool CameraService::Client::keep() const {
13352fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    return mKeep;
13362fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li}
1337e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li
133865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
133965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
134065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic const int kDumpLockRetries = 50;
134165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic const int kDumpLockSleep = 60000;
134265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
134365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic bool tryLock(Mutex& mutex)
134465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
134565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    bool locked = false;
134665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (int i = 0; i < kDumpLockRetries; ++i) {
134765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (mutex.tryLock() == NO_ERROR) {
134865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            locked = true;
134965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            break;
135065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
135165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        usleep(kDumpLockSleep);
135265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
135365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return locked;
135465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
135565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
135665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CameraService::dump(int fd, const Vector<String16>& args) {
135765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    static const char* kDeadlockedString = "CameraService may be deadlocked\n";
135865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
135965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    const size_t SIZE = 256;
136065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    char buffer[SIZE];
136165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    String8 result;
136265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
136365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        snprintf(buffer, SIZE, "Permission Denial: "
136465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                "can't dump CameraService from pid=%d, uid=%d\n",
136565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                getCallingPid(),
136665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                getCallingUid());
136765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        result.append(buffer);
136865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        write(fd, result.string(), result.size());
136965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    } else {
137065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        bool locked = tryLock(mServiceLock);
137165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // failed to lock - CameraService is probably deadlocked
137265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (!locked) {
137365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            String8 result(kDeadlockedString);
137465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            write(fd, result.string(), result.size());
137565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
137665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
137765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        bool hasClient = false;
137865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        for (int i = 0; i < mNumberOfCameras; i++) {
137965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            sp<Client> client = mClient[i].promote();
138065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            if (client == 0) continue;
138165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            hasClient = true;
138265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            sprintf(buffer, "Client[%d] (%p) PID: %d\n",
138365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    i,
138465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    client->getCameraClient()->asBinder().get(),
138565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    client->mClientPid);
138665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            result.append(buffer);
138765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            write(fd, result.string(), result.size());
138865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            client->mHardware->dump(fd, args);
138965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
139065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (!hasClient) {
139165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            result.append("No camera client yet.\n");
139265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            write(fd, result.string(), result.size());
139365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
139465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
139565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (locked) mServiceLock.unlock();
139665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
139765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // change logging level
139865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        int n = args.size();
139965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        for (int i = 0; i + 1 < n; i++) {
140065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            if (args[i] == String16("-v")) {
140165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                String8 levelStr(args[i+1]);
140265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                int level = atoi(levelStr.string());
140365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                sprintf(buffer, "Set Log Level to %d", level);
140465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                result.append(buffer);
140565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                setLogLevel(level);
140665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
140765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
140865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
140965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return NO_ERROR;
141065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
141165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
141265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; // namespace android
1413