blob: eda301240a068a08bbece2237df83b2b921314a1 [file] [log] [blame]
Igor Murashkin985fd302013-02-20 18:24:43 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "ProCamera2Client"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22#include <utils/Trace.h>
23
24#include <cutils/properties.h>
25#include <gui/Surface.h>
26#include <gui/Surface.h>
27#include "camera2/Parameters.h"
28#include "ProCamera2Client.h"
Igor Murashkina91537e2013-02-21 12:02:29 -080029#include "camera2/ProFrameProcessor.h"
Igor Murashkin985fd302013-02-20 18:24:43 -080030
31namespace android {
32using namespace camera2;
33
34static int getCallingPid() {
35 return IPCThreadState::self()->getCallingPid();
36}
37
38static int getCallingUid() {
39 return IPCThreadState::self()->getCallingUid();
40}
41
42// Interface used by CameraService
43
44ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
45 const sp<IProCameraCallbacks>& remoteCallback,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080046 const String16& clientPackageName,
Igor Murashkin985fd302013-02-20 18:24:43 -080047 int cameraId,
48 int cameraFacing,
49 int clientPid,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080050 uid_t clientUid,
Igor Murashkin985fd302013-02-20 18:24:43 -080051 int servicePid):
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080052 ProClient(cameraService, remoteCallback, clientPackageName,
53 cameraId, cameraFacing, clientPid, clientUid, servicePid),
Igor Murashkin985fd302013-02-20 18:24:43 -080054 mSharedCameraCallbacks(remoteCallback)
55{
56 ATRACE_CALL();
57 ALOGI("ProCamera %d: Opened", cameraId);
58
59 mDevice = new Camera2Device(cameraId);
60
61 mExclusiveLock = false;
62}
63
64status_t ProCamera2Client::checkPid(const char* checkLocation) const {
65 int callingPid = getCallingPid();
66 if (callingPid == mClientPid) return NO_ERROR;
67
68 ALOGE("%s: attempt to use a locked camera from a different process"
69 " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
70 return PERMISSION_DENIED;
71}
72
73status_t ProCamera2Client::initialize(camera_module_t *module)
74{
75 ATRACE_CALL();
76 ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
77 status_t res;
78
79 res = mDevice->initialize(module);
80 if (res != OK) {
81 ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
82 __FUNCTION__, mCameraId, strerror(-res), res);
83 return NO_INIT;
84 }
85
86 res = mDevice->setNotifyCallback(this);
87
Igor Murashkina91537e2013-02-21 12:02:29 -080088 String8 threadName;
89 mFrameProcessor = new ProFrameProcessor(this);
90 threadName = String8::format("PC2-%d-FrameProc",
91 mCameraId);
92 mFrameProcessor->run(threadName.string());
93
94 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
95 FRAME_PROCESSOR_LISTENER_MAX_ID,
96 /*listener*/this);
97
Igor Murashkin985fd302013-02-20 18:24:43 -080098 return OK;
99}
100
101ProCamera2Client::~ProCamera2Client() {
102 ATRACE_CALL();
103
104 mDestructionStarted = true;
105
106 disconnect();
107
108 ALOGI("ProCamera %d: Closed", mCameraId);
109}
110
111status_t ProCamera2Client::exclusiveTryLock() {
112 ATRACE_CALL();
113 ALOGV("%s", __FUNCTION__);
114
115 Mutex::Autolock icl(mIProCameraUserLock);
116 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
117
118 if (!mExclusiveLock) {
119 mExclusiveLock = true;
120
121 if (mRemoteCallback != NULL) {
122 mRemoteCallback->onLockStatusChanged(
123 IProCameraCallbacks::LOCK_ACQUIRED);
124 }
125
126 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
127
128 return OK;
129 }
130
131 // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
132
133 // don't allow recursive locking
134 ALOGW("%s: exclusive lock already exists - recursive locking is not"
135 "allowed", __FUNCTION__);
136
137 return ALREADY_EXISTS;
138}
139
140status_t ProCamera2Client::exclusiveLock() {
141 ATRACE_CALL();
142 ALOGV("%s", __FUNCTION__);
143
144 Mutex::Autolock icl(mIProCameraUserLock);
145 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
146
147 /**
148 * TODO: this should asynchronously 'wait' until the lock becomes available
149 * if another client already has an exclusive lock.
150 *
151 * once we have proper sharing support this will need to do
152 * more than just return immediately
153 */
154 if (!mExclusiveLock) {
155 mExclusiveLock = true;
156
157 if (mRemoteCallback != NULL) {
158 mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
159 }
160
161 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
162
163 return OK;
164 }
165
166 // don't allow recursive locking
167 ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
168 , __FUNCTION__);
169 return ALREADY_EXISTS;
170}
171
172status_t ProCamera2Client::exclusiveUnlock() {
173 ATRACE_CALL();
174 ALOGV("%s", __FUNCTION__);
175
176 Mutex::Autolock icl(mIProCameraUserLock);
177 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
178
179 // don't allow unlocking if we have no lock
180 if (!mExclusiveLock) {
181 ALOGW("%s: cannot unlock, no lock was held in the first place",
182 __FUNCTION__);
183 return BAD_VALUE;
184 }
185
186 mExclusiveLock = false;
187 if (mRemoteCallback != NULL ) {
188 mRemoteCallback->onLockStatusChanged(
189 IProCameraCallbacks::LOCK_RELEASED);
190 }
191 ALOGV("%s: exclusive lock released", __FUNCTION__);
192
193 return OK;
194}
195
196bool ProCamera2Client::hasExclusiveLock() {
197 return mExclusiveLock;
198}
199
200status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
201 bool streaming) {
202 ATRACE_CALL();
203 ALOGV("%s", __FUNCTION__);
204
205 Mutex::Autolock icl(mIProCameraUserLock);
206 if (!mExclusiveLock) {
207 return PERMISSION_DENIED;
208 }
209
Igor Murashkin3261fd32013-02-20 19:02:36 -0800210 CameraMetadata metadata(request);
211
212 if (streaming) {
213 return mDevice->setStreamingRequest(metadata);
214 } else {
215 return mDevice->capture(metadata);
216 }
217
218 // unreachable. thx gcc for a useless warning
Igor Murashkin985fd302013-02-20 18:24:43 -0800219 return OK;
220}
221
222status_t ProCamera2Client::cancelRequest(int requestId) {
223 ATRACE_CALL();
224 ALOGV("%s", __FUNCTION__);
225
226 Mutex::Autolock icl(mIProCameraUserLock);
227 if (!mExclusiveLock) {
228 return PERMISSION_DENIED;
229 }
230
231 ALOGE("%s: not fully implemented yet", __FUNCTION__);
Igor Murashkin3261fd32013-02-20 19:02:36 -0800232 return INVALID_OPERATION;
Igor Murashkin985fd302013-02-20 18:24:43 -0800233}
234
235status_t ProCamera2Client::requestStream(int streamId) {
236 ALOGE("%s: not implemented yet", __FUNCTION__);
237
238 return INVALID_OPERATION;
239}
240
241status_t ProCamera2Client::cancelStream(int streamId) {
Igor Murashkin3261fd32013-02-20 19:02:36 -0800242 ATRACE_CALL();
243 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800244
Igor Murashkin3261fd32013-02-20 19:02:36 -0800245 status_t res;
246 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
247
248 Mutex::Autolock icl(mIProCameraUserLock);
249
Igor Murashkin5835cc42013-02-20 19:29:53 -0800250 mDevice->clearStreamingRequest();
251
252 status_t code;
253 if ((code = mDevice->waitUntilDrained()) != OK) {
254 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
255 }
256
Igor Murashkin3261fd32013-02-20 19:02:36 -0800257 return mDevice->deleteStream(streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800258}
259
260status_t ProCamera2Client::createStream(int width, int height, int format,
Igor Murashkin76f8b432013-02-20 19:15:15 -0800261 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin3261fd32013-02-20 19:02:36 -0800262 /*out*/
263 int* streamId)
264{
265 if (streamId) {
266 *streamId = -1;
267 }
Igor Murashkin985fd302013-02-20 18:24:43 -0800268
Igor Murashkin3261fd32013-02-20 19:02:36 -0800269 ATRACE_CALL();
270 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
271
272 status_t res;
273 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
274
275 Mutex::Autolock icl(mIProCameraUserLock);
276
Igor Murashkin76f8b432013-02-20 19:15:15 -0800277 sp<IBinder> binder;
278 sp<ANativeWindow> window;
279 if (bufferProducer != 0) {
280 binder = bufferProducer->asBinder();
281 window = new Surface(bufferProducer);
282 }
283
284 return mDevice->createStream(window, width, height, format, /*size*/1,
285 streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800286}
287
Igor Murashkin3261fd32013-02-20 19:02:36 -0800288// Create a request object from a template.
289// -- Caller owns the newly allocated metadata
Igor Murashkin985fd302013-02-20 18:24:43 -0800290status_t ProCamera2Client::createDefaultRequest(int templateId,
Igor Murashkin3261fd32013-02-20 19:02:36 -0800291 /*out*/
292 camera_metadata** request)
293{
294 ATRACE_CALL();
295 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800296
Igor Murashkin3261fd32013-02-20 19:02:36 -0800297 if (request) {
298 *request = NULL;
299 }
300
301 status_t res;
302 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
303
304 Mutex::Autolock icl(mIProCameraUserLock);
305
306 CameraMetadata metadata;
307 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
308 *request = metadata.release();
309 }
310
311 return res;
Igor Murashkin985fd302013-02-20 18:24:43 -0800312}
313
Igor Murashkin7b33a742013-02-21 13:49:26 -0800314status_t ProCamera2Client::getCameraInfo(int cameraId,
315 /*out*/
316 camera_metadata** info)
317{
318 if (cameraId != mCameraId) {
319 return INVALID_OPERATION;
320 }
321
322 CameraMetadata deviceInfo = mDevice->info();
323 *info = deviceInfo.release();
324
325 return OK;
326}
327
Igor Murashkin985fd302013-02-20 18:24:43 -0800328status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
329 String8 result;
330 result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
331 mCameraId,
332 getRemoteCallback()->asBinder().get(),
333 mClientPid);
334 result.append(" State: ");
335
336 // TODO: print dynamic/request section from most recent requests
Igor Murashkina91537e2013-02-21 12:02:29 -0800337 mFrameProcessor->dump(fd, args);
Igor Murashkin985fd302013-02-20 18:24:43 -0800338
339#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
340
341 result = " Device dump:\n";
342 write(fd, result.string(), result.size());
343
344 status_t res = mDevice->dump(fd, args);
345 if (res != OK) {
346 result = String8::format(" Error dumping device: %s (%d)",
347 strerror(-res), res);
348 write(fd, result.string(), result.size());
349 }
350
351#undef CASE_APPEND_ENUM
352 return NO_ERROR;
353}
354
355// IProCameraUser interface
356
357void ProCamera2Client::disconnect() {
358 ATRACE_CALL();
359 Mutex::Autolock icl(mIProCameraUserLock);
360 status_t res;
361
362 // Allow both client and the media server to disconnect at all times
363 int callingPid = getCallingPid();
364 if (callingPid != mClientPid && callingPid != mServicePid) return;
365
366 if (mDevice == 0) return;
367
368 ALOGV("Camera %d: Shutting down", mCameraId);
Igor Murashkina91537e2013-02-21 12:02:29 -0800369 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
370 FRAME_PROCESSOR_LISTENER_MAX_ID,
371 /*listener*/this);
372 mFrameProcessor->requestExit();
Igor Murashkin985fd302013-02-20 18:24:43 -0800373 ALOGV("Camera %d: Waiting for threads", mCameraId);
Igor Murashkina91537e2013-02-21 12:02:29 -0800374 mFrameProcessor->join();
Igor Murashkin985fd302013-02-20 18:24:43 -0800375 ALOGV("Camera %d: Disconnecting device", mCameraId);
376
377 mDevice->disconnect();
378
379 mDevice.clear();
380
381 ProClient::disconnect();
382}
383
384status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) {
385 ATRACE_CALL();
386 ALOGV("%s: E", __FUNCTION__);
387 Mutex::Autolock icl(mIProCameraUserLock);
388
389 if (mClientPid != 0 && getCallingPid() != mClientPid) {
390 ALOGE("%s: Camera %d: Connection attempt from pid %d; "
391 "current locked to pid %d", __FUNCTION__,
392 mCameraId, getCallingPid(), mClientPid);
393 return BAD_VALUE;
394 }
395
396 mClientPid = getCallingPid();
397
398 mRemoteCallback = client;
399 mSharedCameraCallbacks = client;
400
401 return OK;
402}
403
404/** Device-related methods */
405
406void ProCamera2Client::notifyError(int errorCode, int arg1, int arg2) {
407 ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
408 arg1, arg2);
409}
410
411void ProCamera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) {
412 ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
413 frameNumber, timestamp);
414}
415
416void ProCamera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
417 ALOGV("%s: Autofocus state now %d, last trigger %d",
418 __FUNCTION__, newState, triggerId);
419
420 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
421 if (l.mRemoteCallback != 0) {
422 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
423 1, 0);
424 }
425 if (l.mRemoteCallback != 0) {
426 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
427 1, 0);
428 }
429}
430
431void ProCamera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
432 ALOGV("%s: Autoexposure state now %d, last trigger %d",
433 __FUNCTION__, newState, triggerId);
434}
435
436void ProCamera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
437 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
438 __FUNCTION__, newState, triggerId);
439}
440
441int ProCamera2Client::getCameraId() const {
442 return mCameraId;
443}
444
445const sp<Camera2Device>& ProCamera2Client::getCameraDevice() {
446 return mDevice;
447}
448
449const sp<CameraService>& ProCamera2Client::getCameraService() {
450 return mCameraService;
451}
452
453ProCamera2Client::SharedCameraCallbacks::Lock::Lock(
454 SharedCameraCallbacks &client):
455 mRemoteCallback(client.mRemoteCallback),
456 mSharedClient(client) {
457 mSharedClient.mRemoteCallbackLock.lock();
458}
459
460ProCamera2Client::SharedCameraCallbacks::Lock::~Lock() {
461 mSharedClient.mRemoteCallbackLock.unlock();
462}
463
464ProCamera2Client::SharedCameraCallbacks::SharedCameraCallbacks
465 (const sp<IProCameraCallbacks>&client):
466 mRemoteCallback(client) {
467}
468
469ProCamera2Client::SharedCameraCallbacks&
470 ProCamera2Client::SharedCameraCallbacks::operator=(
471 const sp<IProCameraCallbacks>&client) {
472 Mutex::Autolock l(mRemoteCallbackLock);
473 mRemoteCallback = client;
474 return *this;
475}
476
477void ProCamera2Client::SharedCameraCallbacks::clear() {
478 Mutex::Autolock l(mRemoteCallbackLock);
479 mRemoteCallback.clear();
480}
481
Igor Murashkina91537e2013-02-21 12:02:29 -0800482void ProCamera2Client::onFrameAvailable(int32_t frameId,
483 const CameraMetadata& frame) {
484 ATRACE_CALL();
485 ALOGV("%s", __FUNCTION__);
486
487 Mutex::Autolock icl(mIProCameraUserLock);
488 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
489
490 if (mRemoteCallback != NULL) {
491 CameraMetadata tmp(frame);
492 camera_metadata_t* meta = tmp.release();
493 ALOGV("%s: meta = %p ", __FUNCTION__, meta);
494 mRemoteCallback->onResultReceived(frameId, meta);
495 tmp.acquire(meta);
496 }
497
498}
499
Igor Murashkin985fd302013-02-20 18:24:43 -0800500} // namespace android