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