blob: 1a78b53b69a4386ff83ba862fa74bea3b2bf7dd1 [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -07001/*
2**
3** Copyright (C) 2008, The Android Open Source Project
Mathias Agopian65ab4712010-07-14 17:59:35 -07004**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "CameraService"
Iliyan Malchev8951a972011-04-14 16:55:59 -070019//#define LOG_NDEBUG 0
Mathias Agopian65ab4712010-07-14 17:59:35 -070020
21#include <stdio.h>
22#include <sys/types.h>
23#include <pthread.h>
24
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080025#include <binder/AppOpsManager.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070026#include <binder/IPCThreadState.h>
27#include <binder/IServiceManager.h>
28#include <binder/MemoryBase.h>
29#include <binder/MemoryHeapBase.h>
30#include <cutils/atomic.h>
Nipun Kwatrab5ca4612010-09-11 19:31:10 -070031#include <cutils/properties.h>
Mathias Agopiandf712ea2012-02-25 18:48:35 -080032#include <gui/Surface.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070033#include <hardware/hardware.h>
34#include <media/AudioSystem.h>
35#include <media/mediaplayer.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070036#include <utils/Errors.h>
37#include <utils/Log.h>
38#include <utils/String16.h>
39
40#include "CameraService.h"
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070041#include "CameraClient.h"
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070042#include "Camera2Client.h"
Igor Murashkin985fd302013-02-20 18:24:43 -080043#include "ProCamera2Client.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070044
45namespace android {
46
47// ----------------------------------------------------------------------------
48// Logging support -- this is for debugging only
49// Use "adb shell dumpsys media.camera -v 1" to change it.
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070050volatile int32_t gLogLevel = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -070051
Steve Blockb8a80522011-12-20 16:23:08 +000052#define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
53#define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
Mathias Agopian65ab4712010-07-14 17:59:35 -070054
55static void setLogLevel(int level) {
56 android_atomic_write(level, &gLogLevel);
57}
58
59// ----------------------------------------------------------------------------
60
61static int getCallingPid() {
62 return IPCThreadState::self()->getCallingPid();
63}
64
65static int getCallingUid() {
66 return IPCThreadState::self()->getCallingUid();
67}
68
69// ----------------------------------------------------------------------------
70
71// This is ugly and only safe if we never re-create the CameraService, but
72// should be ok for now.
73static CameraService *gCameraService;
74
75CameraService::CameraService()
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080076 :mSoundRef(0), mModule(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -070077{
Steve Blockdf64d152012-01-04 20:05:49 +000078 ALOGI("CameraService started (pid=%d)", getpid());
Mathias Agopian65ab4712010-07-14 17:59:35 -070079 gCameraService = this;
80}
81
Iliyan Malchev8951a972011-04-14 16:55:59 -070082void CameraService::onFirstRef()
83{
Igor Murashkin634a5152013-02-20 17:15:11 -080084 LOG1("CameraService::onFirstRef");
85
Iliyan Malchev8951a972011-04-14 16:55:59 -070086 BnCameraService::onFirstRef();
87
88 if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
89 (const hw_module_t **)&mModule) < 0) {
Steve Block29357bc2012-01-06 19:20:56 +000090 ALOGE("Could not load camera HAL module");
Iliyan Malchev8951a972011-04-14 16:55:59 -070091 mNumberOfCameras = 0;
92 }
93 else {
Alex Rayc0dd54f2013-02-20 13:39:37 -080094 ALOGI("Loaded \"%s\" camera module", mModule->common.name);
Iliyan Malchev8951a972011-04-14 16:55:59 -070095 mNumberOfCameras = mModule->get_number_of_cameras();
96 if (mNumberOfCameras > MAX_CAMERAS) {
Steve Block29357bc2012-01-06 19:20:56 +000097 ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
Iliyan Malchev8951a972011-04-14 16:55:59 -070098 mNumberOfCameras, MAX_CAMERAS);
99 mNumberOfCameras = MAX_CAMERAS;
100 }
101 for (int i = 0; i < mNumberOfCameras; i++) {
102 setCameraFree(i);
103 }
104 }
105}
106
Mathias Agopian65ab4712010-07-14 17:59:35 -0700107CameraService::~CameraService() {
108 for (int i = 0; i < mNumberOfCameras; i++) {
109 if (mBusy[i]) {
Steve Block29357bc2012-01-06 19:20:56 +0000110 ALOGE("camera %d is still in use in destructor!", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700111 }
112 }
113
114 gCameraService = NULL;
115}
116
117int32_t CameraService::getNumberOfCameras() {
118 return mNumberOfCameras;
119}
120
121status_t CameraService::getCameraInfo(int cameraId,
122 struct CameraInfo* cameraInfo) {
Iliyan Malchev8951a972011-04-14 16:55:59 -0700123 if (!mModule) {
124 return NO_INIT;
125 }
126
Mathias Agopian65ab4712010-07-14 17:59:35 -0700127 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
128 return BAD_VALUE;
129 }
130
Iliyan Malchev8951a972011-04-14 16:55:59 -0700131 struct camera_info info;
132 status_t rc = mModule->get_camera_info(cameraId, &info);
133 cameraInfo->facing = info.facing;
134 cameraInfo->orientation = info.orientation;
135 return rc;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700136}
137
Igor Murashkin634a5152013-02-20 17:15:11 -0800138int CameraService::getDeviceVersion(int cameraId, int* facing) {
139 struct camera_info info;
140 if (mModule->get_camera_info(cameraId, &info) != OK) {
141 return -1;
142 }
143
144 int deviceVersion;
145 if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
146 deviceVersion = info.device_version;
147 } else {
148 deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
149 }
150
151 if (facing) {
152 *facing = info.facing;
153 }
154
155 return deviceVersion;
156}
157
Mathias Agopian65ab4712010-07-14 17:59:35 -0700158sp<ICamera> CameraService::connect(
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800159 const sp<ICameraClient>& cameraClient,
160 int cameraId,
161 const String16& clientPackageName,
162 int clientUid) {
163
164 String8 clientName8(clientPackageName);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700165 int callingPid = getCallingPid();
Tyler Luu5861a9a2011-10-06 00:00:03 -0500166
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800167 LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
168 clientName8.string(), cameraId);
169
170 if (clientUid == USE_CALLING_UID) {
171 clientUid = getCallingUid();
172 } else {
173 // We only trust our own process to forward client UIDs
174 if (callingPid != getpid()) {
175 ALOGE("CameraService::connect X (pid %d) rejected (don't trust clientUid)",
176 callingPid);
177 return NULL;
178 }
179 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700180
Iliyan Malchev8951a972011-04-14 16:55:59 -0700181 if (!mModule) {
Steve Block29357bc2012-01-06 19:20:56 +0000182 ALOGE("Camera HAL module not loaded");
Iliyan Malchev8951a972011-04-14 16:55:59 -0700183 return NULL;
184 }
185
Mathias Agopian65ab4712010-07-14 17:59:35 -0700186 sp<Client> client;
187 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
Steve Block29357bc2012-01-06 19:20:56 +0000188 ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700189 callingPid, cameraId);
190 return NULL;
191 }
192
Wu-cheng Lia3355432011-05-20 14:54:25 +0800193 char value[PROPERTY_VALUE_MAX];
194 property_get("sys.secpolicy.camera.disabled", value, "0");
195 if (strcmp(value, "1") == 0) {
196 // Camera is disabled by DevicePolicyManager.
Steve Blockdf64d152012-01-04 20:05:49 +0000197 ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
Wu-cheng Lia3355432011-05-20 14:54:25 +0800198 return NULL;
199 }
200
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800201 Mutex::Autolock lock(mServiceLock);
Wu-cheng Li08ad5ef2012-04-19 12:35:00 +0800202 if (mClient[cameraId] != 0) {
203 client = mClient[cameraId].promote();
204 if (client != 0) {
205 if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
206 LOG1("CameraService::connect X (pid %d) (the same client)",
207 callingPid);
208 return client;
209 } else {
Igor Murashkin1d880232013-02-20 16:50:13 -0800210 // TODOSC: need to support 1 regular client, multiple shared clients here
Wu-cheng Li08ad5ef2012-04-19 12:35:00 +0800211 ALOGW("CameraService::connect X (pid %d) rejected (existing client).",
212 callingPid);
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800213 return NULL;
214 }
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800215 }
Wu-cheng Li08ad5ef2012-04-19 12:35:00 +0800216 mClient[cameraId].clear();
217 }
218
Igor Murashkin634a5152013-02-20 17:15:11 -0800219 /*
220 mBusy is set to false as the last step of the Client destructor,
221 after which it is guaranteed that the Client destructor has finished (
222 including any inherited destructors)
223
224 We only need this for a Client subclasses since we don't allow
225 multiple Clents to be opened concurrently, but multiple BasicClient
226 would be fine
227 */
Wu-cheng Li08ad5ef2012-04-19 12:35:00 +0800228 if (mBusy[cameraId]) {
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800229
230 ALOGW("CameraService::connect X (pid %d, \"%s\") rejected"
231 " (camera %d is still busy).", callingPid,
232 clientName8.string(), cameraId);
Wu-cheng Li08ad5ef2012-04-19 12:35:00 +0800233 return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700234 }
235
Igor Murashkin634a5152013-02-20 17:15:11 -0800236 int facing = -1;
237 int deviceVersion = getDeviceVersion(cameraId, &facing);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700238
239 switch(deviceVersion) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700240 case CAMERA_DEVICE_API_VERSION_1_0:
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800241 client = new CameraClient(this, cameraClient,
242 clientPackageName, cameraId,
243 facing, callingPid, clientUid, getpid());
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700244 break;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700245 case CAMERA_DEVICE_API_VERSION_2_0:
Igor Murashkin634a5152013-02-20 17:15:11 -0800246 case CAMERA_DEVICE_API_VERSION_2_1:
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800247 client = new Camera2Client(this, cameraClient,
248 clientPackageName, cameraId,
249 facing, callingPid, clientUid, getpid());
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700250 break;
Igor Murashkin634a5152013-02-20 17:15:11 -0800251 case -1:
252 ALOGE("Invalid camera id %d", cameraId);
253 return NULL;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700254 default:
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700255 ALOGE("Unknown camera device HAL version: %d", deviceVersion);
Tyler Luu5861a9a2011-10-06 00:00:03 -0500256 return NULL;
257 }
258
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700259 if (client->initialize(mModule) != OK) {
260 return NULL;
261 }
262
Igor Murashkinecf17e82012-10-02 16:05:11 -0700263 cameraClient->asBinder()->linkToDeath(this);
264
Mathias Agopian65ab4712010-07-14 17:59:35 -0700265 mClient[cameraId] = client;
Igor Murashkinecf17e82012-10-02 16:05:11 -0700266 LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700267 return client;
268}
269
Igor Murashkin634a5152013-02-20 17:15:11 -0800270sp<IProCameraUser> CameraService::connect(
271 const sp<IProCameraCallbacks>& cameraCb,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800272 int cameraId,
273 const String16& clientPackageName,
274 int clientUid)
Igor Murashkin634a5152013-02-20 17:15:11 -0800275{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700276 int callingPid = getCallingPid();
Igor Murashkin634a5152013-02-20 17:15:11 -0800277
Igor Murashkinc073ba52013-02-26 14:32:34 -0800278 // TODO: use clientPackageName and clientUid with appOpsMangr
279
Igor Murashkin634a5152013-02-20 17:15:11 -0800280 LOG1("CameraService::connectPro E (pid %d, id %d)", callingPid, cameraId);
281
282 if (!mModule) {
283 ALOGE("Camera HAL module not loaded");
284 return NULL;
285 }
286
287 sp<ProClient> client;
288 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
289 ALOGE("CameraService::connectPro X (pid %d) rejected (invalid cameraId %d).",
290 callingPid, cameraId);
291 return NULL;
292 }
293
294 char value[PROPERTY_VALUE_MAX];
295 property_get("sys.secpolicy.camera.disabled", value, "0");
296 if (strcmp(value, "1") == 0) {
297 // Camera is disabled by DevicePolicyManager.
298 ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
299 return NULL;
300 }
301
302 int facing = -1;
303 int deviceVersion = getDeviceVersion(cameraId, &facing);
304
305 switch(deviceVersion) {
306 case CAMERA_DEVICE_API_VERSION_1_0:
307 ALOGE("Camera id %d uses HALv1, doesn't support ProCamera", cameraId);
308 return NULL;
309 break;
310 case CAMERA_DEVICE_API_VERSION_2_0:
Igor Murashkin985fd302013-02-20 18:24:43 -0800311 case CAMERA_DEVICE_API_VERSION_2_1:
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800312 client = new ProCamera2Client(this, cameraCb, String16(),
313 cameraId, facing, callingPid, USE_CALLING_UID, getpid());
Igor Murashkin634a5152013-02-20 17:15:11 -0800314 break;
315 case -1:
316 ALOGE("Invalid camera id %d", cameraId);
317 return NULL;
318 default:
319 ALOGE("Unknown camera device HAL version: %d", deviceVersion);
320 return NULL;
321 }
322
323 if (client->initialize(mModule) != OK) {
324 return NULL;
325 }
326
327 mProClientList[cameraId].push(client);
328
329 cameraCb->asBinder()->linkToDeath(this);
330
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800331 LOG1("CameraService::connectPro X (id %d, this pid is %d)", cameraId,
332 getpid());
Igor Murashkin634a5152013-02-20 17:15:11 -0800333 return client;
334
335
336 return NULL;
337}
338
339void CameraService::removeClientByRemote(const wp<IBinder>& remoteBinder) {
340 int callingPid = getCallingPid();
341 LOG1("CameraService::removeClientByRemote E (pid %d)", callingPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700342
Igor Murashkinecf17e82012-10-02 16:05:11 -0700343 // Declare this before the lock to make absolutely sure the
344 // destructor won't be called with the lock held.
345 Mutex::Autolock lock(mServiceLock);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700346
Igor Murashkinecf17e82012-10-02 16:05:11 -0700347 int outIndex;
Igor Murashkin634a5152013-02-20 17:15:11 -0800348 sp<Client> client = findClientUnsafe(remoteBinder, outIndex);
Igor Murashkinecf17e82012-10-02 16:05:11 -0700349
350 if (client != 0) {
351 // Found our camera, clear and leave.
352 LOG1("removeClient: clear camera %d", outIndex);
353 mClient[outIndex].clear();
354
355 client->unlinkToDeath(this);
Igor Murashkin634a5152013-02-20 17:15:11 -0800356 } else {
357
358 sp<ProClient> clientPro = findProClientUnsafe(remoteBinder);
359
360 if (clientPro != NULL) {
361 // Found our camera, clear and leave.
362 LOG1("removeClient: clear pro %p", clientPro.get());
363
364 clientPro->getRemoteCallback()->asBinder()->unlinkToDeath(this);
365 }
Igor Murashkinecf17e82012-10-02 16:05:11 -0700366 }
367
Igor Murashkin634a5152013-02-20 17:15:11 -0800368 LOG1("CameraService::removeClientByRemote X (pid %d)", callingPid);
369}
370
371sp<CameraService::ProClient> CameraService::findProClientUnsafe(
372 const wp<IBinder>& cameraCallbacksRemote)
373{
374 sp<ProClient> clientPro;
375
376 for (int i = 0; i < mNumberOfCameras; ++i) {
377 Vector<size_t> removeIdx;
378
379 for (size_t j = 0; j < mProClientList[i].size(); ++j) {
380 wp<ProClient> cl = mProClientList[i][j];
381
382 sp<ProClient> clStrong = cl.promote();
383 if (clStrong != NULL && clStrong->getRemote() == cameraCallbacksRemote) {
384 clientPro = clStrong;
385 break;
386 } else if (clStrong == NULL) {
387 // mark to clean up dead ptr
388 removeIdx.push(j);
389 }
390 }
391
392 // remove stale ptrs (in reverse so the indices dont change)
393 for (ssize_t j = (ssize_t)removeIdx.size() - 1; j >= 0; --j) {
394 mProClientList[i].removeAt(removeIdx[j]);
395 }
396
397 }
398
399 return clientPro;
Igor Murashkinecf17e82012-10-02 16:05:11 -0700400}
401
402sp<CameraService::Client> CameraService::findClientUnsafe(
Igor Murashkin294d0ec2012-10-05 10:44:57 -0700403 const wp<IBinder>& cameraClient, int& outIndex) {
Igor Murashkinecf17e82012-10-02 16:05:11 -0700404 sp<Client> client;
405
406 for (int i = 0; i < mNumberOfCameras; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700407
408 // This happens when we have already disconnected (or this is
409 // just another unused camera).
410 if (mClient[i] == 0) continue;
411
412 // Promote mClient. It can fail if we are called from this path:
Igor Murashkin634a5152013-02-20 17:15:11 -0800413 // Client::~Client() -> disconnect() -> removeClientByRemote().
Mathias Agopian65ab4712010-07-14 17:59:35 -0700414 client = mClient[i].promote();
415
Igor Murashkinecf17e82012-10-02 16:05:11 -0700416 // Clean up stale client entry
417 if (client == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700418 mClient[i].clear();
419 continue;
420 }
421
Igor Murashkin294d0ec2012-10-05 10:44:57 -0700422 if (cameraClient == client->getCameraClient()->asBinder()) {
Igor Murashkinecf17e82012-10-02 16:05:11 -0700423 // Found our camera
424 outIndex = i;
425 return client;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700426 }
427 }
428
Igor Murashkinecf17e82012-10-02 16:05:11 -0700429 outIndex = -1;
430 return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700431}
432
Keun young Parkd8973a72012-03-28 14:13:09 -0700433CameraService::Client* CameraService::getClientByIdUnsafe(int cameraId) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700434 if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
Keun young Parkd8973a72012-03-28 14:13:09 -0700435 return mClient[cameraId].unsafe_get();
436}
437
438Mutex* CameraService::getClientLockById(int cameraId) {
439 if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
440 return &mClientLock[cameraId];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700441}
442
Igor Murashkin634a5152013-02-20 17:15:11 -0800443sp<CameraService::BasicClient> CameraService::getClientByRemote(
Igor Murashkin294d0ec2012-10-05 10:44:57 -0700444 const wp<IBinder>& cameraClient) {
Igor Murashkinecf17e82012-10-02 16:05:11 -0700445
446 // Declare this before the lock to make absolutely sure the
447 // destructor won't be called with the lock held.
Igor Murashkin634a5152013-02-20 17:15:11 -0800448 sp<BasicClient> client;
Igor Murashkinecf17e82012-10-02 16:05:11 -0700449
450 Mutex::Autolock lock(mServiceLock);
451
452 int outIndex;
453 client = findClientUnsafe(cameraClient, outIndex);
454
455 return client;
456}
457
Mathias Agopian65ab4712010-07-14 17:59:35 -0700458status_t CameraService::onTransact(
459 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
460 // Permission checks
461 switch (code) {
462 case BnCameraService::CONNECT:
Igor Murashkin634a5152013-02-20 17:15:11 -0800463 case BnCameraService::CONNECT_PRO:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700464 const int pid = getCallingPid();
465 const int self_pid = getpid();
466 if (pid != self_pid) {
467 // we're called from a different process, do the real check
468 if (!checkCallingPermission(
469 String16("android.permission.CAMERA"))) {
470 const int uid = getCallingUid();
Steve Block29357bc2012-01-06 19:20:56 +0000471 ALOGE("Permission Denial: "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700472 "can't use the camera pid=%d, uid=%d", pid, uid);
473 return PERMISSION_DENIED;
474 }
475 }
476 break;
477 }
478
479 return BnCameraService::onTransact(code, data, reply, flags);
480}
481
482// The reason we need this busy bit is a new CameraService::connect() request
483// may come in while the previous Client's destructor has not been run or is
484// still running. If the last strong reference of the previous Client is gone
485// but the destructor has not been finished, we should not allow the new Client
486// to be created because we need to wait for the previous Client to tear down
487// the hardware first.
488void CameraService::setCameraBusy(int cameraId) {
489 android_atomic_write(1, &mBusy[cameraId]);
Igor Murashkinecf17e82012-10-02 16:05:11 -0700490
491 ALOGV("setCameraBusy cameraId=%d", cameraId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700492}
493
494void CameraService::setCameraFree(int cameraId) {
495 android_atomic_write(0, &mBusy[cameraId]);
Igor Murashkinecf17e82012-10-02 16:05:11 -0700496
497 ALOGV("setCameraFree cameraId=%d", cameraId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700498}
499
500// We share the media players for shutter and recording sound for all clients.
501// A reference count is kept to determine when we will actually release the
502// media players.
503
Chih-Chung Changff4f55c2011-10-17 19:03:12 +0800504MediaPlayer* CameraService::newMediaPlayer(const char *file) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700505 MediaPlayer* mp = new MediaPlayer();
506 if (mp->setDataSource(file, NULL) == NO_ERROR) {
Eino-Ville Talvala60a78ac2012-01-05 15:34:53 -0800507 mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700508 mp->prepare();
509 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000510 ALOGE("Failed to load CameraService sounds: %s", file);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700511 return NULL;
512 }
513 return mp;
514}
515
516void CameraService::loadSound() {
517 Mutex::Autolock lock(mSoundLock);
518 LOG1("CameraService::loadSound ref=%d", mSoundRef);
519 if (mSoundRef++) return;
520
521 mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
522 mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
523}
524
525void CameraService::releaseSound() {
526 Mutex::Autolock lock(mSoundLock);
527 LOG1("CameraService::releaseSound ref=%d", mSoundRef);
528 if (--mSoundRef) return;
529
530 for (int i = 0; i < NUM_SOUNDS; i++) {
531 if (mSoundPlayer[i] != 0) {
532 mSoundPlayer[i]->disconnect();
533 mSoundPlayer[i].clear();
534 }
535 }
536}
537
538void CameraService::playSound(sound_kind kind) {
539 LOG1("playSound(%d)", kind);
540 Mutex::Autolock lock(mSoundLock);
541 sp<MediaPlayer> player = mSoundPlayer[kind];
542 if (player != 0) {
Chih-Chung Chang8888a752011-10-20 10:47:26 +0800543 player->seekTo(0);
544 player->start();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700545 }
546}
547
548// ----------------------------------------------------------------------------
549
550CameraService::Client::Client(const sp<CameraService>& cameraService,
Wu-cheng Lib7a67942010-08-17 15:45:37 -0700551 const sp<ICameraClient>& cameraClient,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800552 const String16& clientPackageName,
553 int cameraId, int cameraFacing,
554 int clientPid, uid_t clientUid,
555 int servicePid) :
Igor Murashkin634a5152013-02-20 17:15:11 -0800556 CameraService::BasicClient(cameraService, cameraClient->asBinder(),
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800557 clientPackageName,
558 cameraId, cameraFacing,
559 clientPid, clientUid,
560 servicePid)
Igor Murashkin634a5152013-02-20 17:15:11 -0800561{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700562 int callingPid = getCallingPid();
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800563 LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700564
Mathias Agopian65ab4712010-07-14 17:59:35 -0700565 mCameraClient = cameraClient;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700566
Mathias Agopian65ab4712010-07-14 17:59:35 -0700567 cameraService->setCameraBusy(cameraId);
568 cameraService->loadSound();
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800569
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800570 LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700571}
572
Mathias Agopian65ab4712010-07-14 17:59:35 -0700573// tear down the client
574CameraService::Client::~Client() {
Igor Murashkin634a5152013-02-20 17:15:11 -0800575 mDestructionStarted = true;
576
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700577 mCameraService->releaseSound();
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800578 finishCameraOps();
Igor Murashkin036bc3e2012-10-08 15:09:46 -0700579 // unconditionally disconnect. function is idempotent
580 Client::disconnect();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700581}
582
Igor Murashkin634a5152013-02-20 17:15:11 -0800583CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800584 const sp<IBinder>& remoteCallback,
585 const String16& clientPackageName,
586 int cameraId, int cameraFacing,
587 int clientPid, uid_t clientUid,
588 int servicePid):
589 mClientPackageName(clientPackageName)
Igor Murashkin634a5152013-02-20 17:15:11 -0800590{
591 mCameraService = cameraService;
592 mRemoteCallback = remoteCallback;
593 mCameraId = cameraId;
594 mCameraFacing = cameraFacing;
595 mClientPid = clientPid;
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800596 mClientUid = clientUid;
Igor Murashkin634a5152013-02-20 17:15:11 -0800597 mServicePid = servicePid;
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800598 mOpsActive = false;
Igor Murashkin634a5152013-02-20 17:15:11 -0800599 mDestructionStarted = false;
600}
601
602CameraService::BasicClient::~BasicClient() {
603 mDestructionStarted = true;
604}
605
606void CameraService::BasicClient::disconnect() {
607 mCameraService->removeClientByRemote(mRemoteCallback);
608}
609
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800610status_t CameraService::BasicClient::startCameraOps() {
611 int32_t res;
612
613 mOpsCallback = new OpsCallback(this);
614
615 mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA,
616 mClientPackageName, mOpsCallback);
617 res = mAppOpsManager.startOp(AppOpsManager::OP_CAMERA,
618 mClientUid, mClientPackageName);
619
620 if (res != AppOpsManager::MODE_ALLOWED) {
621 ALOGI("Camera %d: Access for \"%s\" has been revoked",
622 mCameraId, String8(mClientPackageName).string());
623 return PERMISSION_DENIED;
624 }
625 mOpsActive = true;
626 return OK;
627}
628
629status_t CameraService::BasicClient::finishCameraOps() {
630 if (mOpsActive) {
631 mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid,
632 mClientPackageName);
633 mOpsActive = false;
634 }
635 mAppOpsManager.stopWatchingMode(mOpsCallback);
636 mOpsCallback.clear();
637
638 return OK;
639}
640
641void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) {
642 String8 name(packageName);
643 String8 myName(mClientPackageName);
644
645 if (op != AppOpsManager::OP_CAMERA) {
646 ALOGW("Unexpected app ops notification received: %d", op);
647 return;
648 }
649
650 int32_t res;
651 res = mAppOpsManager.checkOp(AppOpsManager::OP_CAMERA,
652 mClientUid, mClientPackageName);
653 ALOGV("checkOp returns: %d, %s ", res,
654 res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" :
655 res == AppOpsManager::MODE_IGNORED ? "IGNORED" :
656 res == AppOpsManager::MODE_ERRORED ? "ERRORED" :
657 "UNKNOWN");
658
659 if (res != AppOpsManager::MODE_ALLOWED) {
660 ALOGI("Camera %d: Access for \"%s\" revoked", mCameraId,
661 myName.string());
662 // Reset the client PID to allow server-initiated disconnect,
663 // and to prevent further calls by client.
664 mClientPid = getCallingPid();
665 notifyError();
666 disconnect();
667 }
668}
669
Mathias Agopian65ab4712010-07-14 17:59:35 -0700670// ----------------------------------------------------------------------------
671
Keun young Parkd8973a72012-03-28 14:13:09 -0700672Mutex* CameraService::Client::getClientLockFromCookie(void* user) {
673 return gCameraService->getClientLockById((int) user);
674}
675
676// Provide client pointer for callbacks. Client lock returned from getClientLockFromCookie should
677// be acquired for this to be safe
678CameraService::Client* CameraService::Client::getClientFromCookie(void* user) {
679 Client* client = gCameraService->getClientByIdUnsafe((int) user);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700680
681 // This could happen if the Client is in the process of shutting down (the
682 // last strong reference is gone, but the destructor hasn't finished
683 // stopping the hardware).
Keun young Parkd8973a72012-03-28 14:13:09 -0700684 if (client == NULL) return NULL;
685
686 // destruction already started, so should not be accessed
687 if (client->mDestructionStarted) return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700688
Mathias Agopian65ab4712010-07-14 17:59:35 -0700689 return client;
690}
691
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800692void CameraService::Client::notifyError() {
693 mCameraClient->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
694}
695
Igor Murashkin036bc3e2012-10-08 15:09:46 -0700696// NOTE: function is idempotent
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700697void CameraService::Client::disconnect() {
Igor Murashkin634a5152013-02-20 17:15:11 -0800698 BasicClient::disconnect();
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700699 mCameraService->setCameraFree(mCameraId);
Wu-cheng Lie09591e2010-10-14 20:17:44 +0800700}
701
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800702CameraService::Client::OpsCallback::OpsCallback(wp<BasicClient> client):
703 mClient(client) {
704}
705
706void CameraService::Client::OpsCallback::opChanged(int32_t op,
707 const String16& packageName) {
708 sp<BasicClient> client = mClient.promote();
709 if (client != NULL) {
710 client->opChanged(op, packageName);
711 }
712}
713
Mathias Agopian65ab4712010-07-14 17:59:35 -0700714// ----------------------------------------------------------------------------
Igor Murashkin634a5152013-02-20 17:15:11 -0800715// IProCamera
716// ----------------------------------------------------------------------------
717
718CameraService::ProClient::ProClient(const sp<CameraService>& cameraService,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800719 const sp<IProCameraCallbacks>& remoteCallback,
720 const String16& clientPackageName,
721 int cameraId,
722 int cameraFacing,
723 int clientPid,
724 uid_t clientUid,
725 int servicePid)
726 : CameraService::BasicClient(cameraService, remoteCallback->asBinder(),
727 clientPackageName, cameraId, cameraFacing,
728 clientPid, clientUid, servicePid)
Igor Murashkin634a5152013-02-20 17:15:11 -0800729{
730 mRemoteCallback = remoteCallback;
731}
732
733CameraService::ProClient::~ProClient() {
734 mDestructionStarted = true;
735
736 ProClient::disconnect();
737}
738
739status_t CameraService::ProClient::connect(const sp<IProCameraCallbacks>& callbacks) {
740 ALOGE("%s: not implemented yet", __FUNCTION__);
741
742 return INVALID_OPERATION;
743}
744
745void CameraService::ProClient::disconnect() {
746 BasicClient::disconnect();
747}
748
749status_t CameraService::ProClient::initialize(camera_module_t* module)
750{
751 ALOGW("%s: not implemented yet", __FUNCTION__);
752 return OK;
753}
754
755status_t CameraService::ProClient::exclusiveTryLock() {
756 ALOGE("%s: not implemented yet", __FUNCTION__);
757 return INVALID_OPERATION;
758}
759
760status_t CameraService::ProClient::exclusiveLock() {
761 ALOGE("%s: not implemented yet", __FUNCTION__);
762 return INVALID_OPERATION;
763}
764
765status_t CameraService::ProClient::exclusiveUnlock() {
766 ALOGE("%s: not implemented yet", __FUNCTION__);
767 return INVALID_OPERATION;
768}
769
770bool CameraService::ProClient::hasExclusiveLock() {
771 ALOGE("%s: not implemented yet", __FUNCTION__);
772 return false;
773}
774
775status_t CameraService::ProClient::submitRequest(camera_metadata_t* request, bool streaming) {
776 ALOGE("%s: not implemented yet", __FUNCTION__);
777
778 free_camera_metadata(request);
779
780 return INVALID_OPERATION;
781}
782
783status_t CameraService::ProClient::cancelRequest(int requestId) {
784 ALOGE("%s: not implemented yet", __FUNCTION__);
785
786 return INVALID_OPERATION;
787}
788
789status_t CameraService::ProClient::requestStream(int streamId) {
790 ALOGE("%s: not implemented yet", __FUNCTION__);
791
792 return INVALID_OPERATION;
793}
794
795status_t CameraService::ProClient::cancelStream(int streamId) {
796 ALOGE("%s: not implemented yet", __FUNCTION__);
797
798 return INVALID_OPERATION;
799}
800
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800801void CameraService::ProClient::notifyError() {
802 ALOGE("%s: not implemented yet", __FUNCTION__);
803}
804
Igor Murashkin634a5152013-02-20 17:15:11 -0800805// ----------------------------------------------------------------------------
Mathias Agopian65ab4712010-07-14 17:59:35 -0700806
807static const int kDumpLockRetries = 50;
808static const int kDumpLockSleep = 60000;
809
810static bool tryLock(Mutex& mutex)
811{
812 bool locked = false;
813 for (int i = 0; i < kDumpLockRetries; ++i) {
814 if (mutex.tryLock() == NO_ERROR) {
815 locked = true;
816 break;
817 }
818 usleep(kDumpLockSleep);
819 }
820 return locked;
821}
822
823status_t CameraService::dump(int fd, const Vector<String16>& args) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700824 String8 result;
825 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
Eino-Ville Talvala611f6192012-05-31 12:28:23 -0700826 result.appendFormat("Permission Denial: "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700827 "can't dump CameraService from pid=%d, uid=%d\n",
828 getCallingPid(),
829 getCallingUid());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700830 write(fd, result.string(), result.size());
831 } else {
832 bool locked = tryLock(mServiceLock);
833 // failed to lock - CameraService is probably deadlocked
834 if (!locked) {
Eino-Ville Talvala611f6192012-05-31 12:28:23 -0700835 result.append("CameraService may be deadlocked\n");
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700836 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700837 }
838
839 bool hasClient = false;
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700840 if (!mModule) {
841 result = String8::format("No camera module available!\n");
842 write(fd, result.string(), result.size());
843 return NO_ERROR;
844 }
845
846 result = String8::format("Camera module HAL API version: 0x%x\n",
847 mModule->common.hal_api_version);
848 result.appendFormat("Camera module API version: 0x%x\n",
849 mModule->common.module_api_version);
850 result.appendFormat("Camera module name: %s\n",
851 mModule->common.name);
852 result.appendFormat("Camera module author: %s\n",
853 mModule->common.author);
854 result.appendFormat("Number of camera devices: %d\n\n", mNumberOfCameras);
855 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700856 for (int i = 0; i < mNumberOfCameras; i++) {
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700857 result = String8::format("Camera %d static information:\n", i);
858 camera_info info;
859
860 status_t rc = mModule->get_camera_info(i, &info);
861 if (rc != OK) {
862 result.appendFormat(" Error reading static information!\n");
863 write(fd, result.string(), result.size());
864 } else {
865 result.appendFormat(" Facing: %s\n",
866 info.facing == CAMERA_FACING_BACK ? "BACK" : "FRONT");
867 result.appendFormat(" Orientation: %d\n", info.orientation);
868 int deviceVersion;
869 if (mModule->common.module_api_version <
870 CAMERA_MODULE_API_VERSION_2_0) {
871 deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
872 } else {
873 deviceVersion = info.device_version;
874 }
875 result.appendFormat(" Device version: 0x%x\n", deviceVersion);
876 if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
877 result.appendFormat(" Device static metadata:\n");
878 write(fd, result.string(), result.size());
Eino-Ville Talvala428b77a2012-07-30 09:55:30 -0700879 dump_indented_camera_metadata(info.static_camera_characteristics,
880 fd, 2, 4);
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700881 } else {
882 write(fd, result.string(), result.size());
883 }
884 }
885
Mathias Agopian65ab4712010-07-14 17:59:35 -0700886 sp<Client> client = mClient[i].promote();
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700887 if (client == 0) {
888 result = String8::format(" Device is closed, no client instance\n");
889 write(fd, result.string(), result.size());
890 continue;
891 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700892 hasClient = true;
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700893 result = String8::format(" Device is open. Client instance dump:\n");
894 write(fd, result.string(), result.size());
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700895 client->dump(fd, args);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700896 }
897 if (!hasClient) {
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700898 result = String8::format("\nNo active camera clients yet.\n");
899 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700900 }
901
902 if (locked) mServiceLock.unlock();
903
904 // change logging level
905 int n = args.size();
906 for (int i = 0; i + 1 < n; i++) {
Eino-Ville Talvala611f6192012-05-31 12:28:23 -0700907 String16 verboseOption("-v");
908 if (args[i] == verboseOption) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700909 String8 levelStr(args[i+1]);
910 int level = atoi(levelStr.string());
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700911 result = String8::format("\nSetting log level to %d.\n", level);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700912 setLogLevel(level);
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700913 write(fd, result.string(), result.size());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700914 }
915 }
Eino-Ville Talvalaf5926132012-07-17 13:54:20 -0700916
Mathias Agopian65ab4712010-07-14 17:59:35 -0700917 }
918 return NO_ERROR;
919}
920
Igor Murashkinecf17e82012-10-02 16:05:11 -0700921/*virtual*/void CameraService::binderDied(
922 const wp<IBinder> &who) {
923
Igor Murashkin294d0ec2012-10-05 10:44:57 -0700924 /**
925 * While tempting to promote the wp<IBinder> into a sp,
926 * it's actually not supported by the binder driver
927 */
928
Igor Murashkinecf17e82012-10-02 16:05:11 -0700929 ALOGV("java clients' binder died");
930
Igor Murashkin634a5152013-02-20 17:15:11 -0800931 sp<BasicClient> cameraClient = getClientByRemote(who);
Igor Murashkinecf17e82012-10-02 16:05:11 -0700932
Igor Murashkin294d0ec2012-10-05 10:44:57 -0700933 if (cameraClient == 0) {
Igor Murashkinecf17e82012-10-02 16:05:11 -0700934 ALOGV("java clients' binder death already cleaned up (normal case)");
935 return;
936 }
937
Igor Murashkinecf17e82012-10-02 16:05:11 -0700938 ALOGW("Disconnecting camera client %p since the binder for it "
939 "died (this pid %d)", cameraClient.get(), getCallingPid());
940
941 cameraClient->disconnect();
942
943}
944
Mathias Agopian65ab4712010-07-14 17:59:35 -0700945}; // namespace android