blob: 6fed8b4b86ad236f4d36627e1fe33f60e5a1c9b2 [file] [log] [blame]
Igor Murashkin69e22432013-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 Murashkin418e4932013-02-21 12:02:29 -080029#include "camera2/ProFrameProcessor.h"
Igor Murashkin69e22432013-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 Talvala48af7e82013-02-19 10:40:14 -080046 const String16& clientPackageName,
Igor Murashkin69e22432013-02-20 18:24:43 -080047 int cameraId,
48 int cameraFacing,
49 int clientPid,
Eino-Ville Talvala48af7e82013-02-19 10:40:14 -080050 uid_t clientUid,
Igor Murashkin69e22432013-02-20 18:24:43 -080051 int servicePid):
Eino-Ville Talvala48af7e82013-02-19 10:40:14 -080052 ProClient(cameraService, remoteCallback, clientPackageName,
53 cameraId, cameraFacing, clientPid, clientUid, servicePid),
Igor Murashkin69e22432013-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 Murashkin418e4932013-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 Murashkin69e22432013-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
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800118 if (!mDevice.get()) return PERMISSION_DENIED;
119
Igor Murashkin69e22432013-02-20 18:24:43 -0800120 if (!mExclusiveLock) {
121 mExclusiveLock = true;
122
123 if (mRemoteCallback != NULL) {
124 mRemoteCallback->onLockStatusChanged(
125 IProCameraCallbacks::LOCK_ACQUIRED);
126 }
127
128 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
129
130 return OK;
131 }
132
133 // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
134
135 // don't allow recursive locking
136 ALOGW("%s: exclusive lock already exists - recursive locking is not"
137 "allowed", __FUNCTION__);
138
139 return ALREADY_EXISTS;
140}
141
142status_t ProCamera2Client::exclusiveLock() {
143 ATRACE_CALL();
144 ALOGV("%s", __FUNCTION__);
145
146 Mutex::Autolock icl(mIProCameraUserLock);
147 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
148
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800149 if (!mDevice.get()) return PERMISSION_DENIED;
150
Igor Murashkin69e22432013-02-20 18:24:43 -0800151 /**
152 * TODO: this should asynchronously 'wait' until the lock becomes available
153 * if another client already has an exclusive lock.
154 *
155 * once we have proper sharing support this will need to do
156 * more than just return immediately
157 */
158 if (!mExclusiveLock) {
159 mExclusiveLock = true;
160
161 if (mRemoteCallback != NULL) {
162 mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
163 }
164
165 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
166
167 return OK;
168 }
169
170 // don't allow recursive locking
171 ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
172 , __FUNCTION__);
173 return ALREADY_EXISTS;
174}
175
176status_t ProCamera2Client::exclusiveUnlock() {
177 ATRACE_CALL();
178 ALOGV("%s", __FUNCTION__);
179
180 Mutex::Autolock icl(mIProCameraUserLock);
181 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
182
183 // don't allow unlocking if we have no lock
184 if (!mExclusiveLock) {
185 ALOGW("%s: cannot unlock, no lock was held in the first place",
186 __FUNCTION__);
187 return BAD_VALUE;
188 }
189
190 mExclusiveLock = false;
191 if (mRemoteCallback != NULL ) {
192 mRemoteCallback->onLockStatusChanged(
193 IProCameraCallbacks::LOCK_RELEASED);
194 }
195 ALOGV("%s: exclusive lock released", __FUNCTION__);
196
197 return OK;
198}
199
200bool ProCamera2Client::hasExclusiveLock() {
201 return mExclusiveLock;
202}
203
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800204void ProCamera2Client::onExclusiveLockStolen() {
205 ALOGV("%s: ProClient lost exclusivity (id %d)",
206 __FUNCTION__, mCameraId);
207
208 Mutex::Autolock icl(mIProCameraUserLock);
209 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
210
211 if (mExclusiveLock && mRemoteCallback.get() != NULL) {
212 mRemoteCallback->onLockStatusChanged(
213 IProCameraCallbacks::LOCK_STOLEN);
214 }
215
216 mExclusiveLock = false;
217
218 //TODO: we should not need to detach the device, merely reset it.
219 detachDevice();
220}
221
Igor Murashkin69e22432013-02-20 18:24:43 -0800222status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
223 bool streaming) {
224 ATRACE_CALL();
225 ALOGV("%s", __FUNCTION__);
226
227 Mutex::Autolock icl(mIProCameraUserLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800228
229 if (!mDevice.get()) return DEAD_OBJECT;
230
Igor Murashkin69e22432013-02-20 18:24:43 -0800231 if (!mExclusiveLock) {
232 return PERMISSION_DENIED;
233 }
234
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800235 CameraMetadata metadata(request);
236
237 if (streaming) {
238 return mDevice->setStreamingRequest(metadata);
239 } else {
240 return mDevice->capture(metadata);
241 }
242
243 // unreachable. thx gcc for a useless warning
Igor Murashkin69e22432013-02-20 18:24:43 -0800244 return OK;
245}
246
247status_t ProCamera2Client::cancelRequest(int requestId) {
248 ATRACE_CALL();
249 ALOGV("%s", __FUNCTION__);
250
251 Mutex::Autolock icl(mIProCameraUserLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800252
253 if (!mDevice.get()) return DEAD_OBJECT;
254
Igor Murashkin69e22432013-02-20 18:24:43 -0800255 if (!mExclusiveLock) {
256 return PERMISSION_DENIED;
257 }
258
259 ALOGE("%s: not fully implemented yet", __FUNCTION__);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800260 return INVALID_OPERATION;
Igor Murashkin69e22432013-02-20 18:24:43 -0800261}
262
263status_t ProCamera2Client::requestStream(int streamId) {
264 ALOGE("%s: not implemented yet", __FUNCTION__);
265
266 return INVALID_OPERATION;
267}
268
269status_t ProCamera2Client::cancelStream(int streamId) {
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800270 ATRACE_CALL();
271 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800272
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800273 status_t res;
274 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
275
276 Mutex::Autolock icl(mIProCameraUserLock);
277
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800278 if (!mDevice.get()) return DEAD_OBJECT;
Igor Murashkinc0767f12013-02-20 19:29:53 -0800279 mDevice->clearStreamingRequest();
280
281 status_t code;
282 if ((code = mDevice->waitUntilDrained()) != OK) {
283 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
284 }
285
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800286 return mDevice->deleteStream(streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800287}
288
289status_t ProCamera2Client::createStream(int width, int height, int format,
Igor Murashkin5494cdc2013-02-20 19:15:15 -0800290 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800291 /*out*/
292 int* streamId)
293{
294 if (streamId) {
295 *streamId = -1;
296 }
Igor Murashkin69e22432013-02-20 18:24:43 -0800297
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800298 ATRACE_CALL();
299 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
300
301 status_t res;
302 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
303
304 Mutex::Autolock icl(mIProCameraUserLock);
305
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800306 if (!mDevice.get()) return DEAD_OBJECT;
307
Igor Murashkin5494cdc2013-02-20 19:15:15 -0800308 sp<IBinder> binder;
309 sp<ANativeWindow> window;
310 if (bufferProducer != 0) {
311 binder = bufferProducer->asBinder();
312 window = new Surface(bufferProducer);
313 }
314
315 return mDevice->createStream(window, width, height, format, /*size*/1,
316 streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800317}
318
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800319// Create a request object from a template.
320// -- Caller owns the newly allocated metadata
Igor Murashkin69e22432013-02-20 18:24:43 -0800321status_t ProCamera2Client::createDefaultRequest(int templateId,
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800322 /*out*/
323 camera_metadata** request)
324{
325 ATRACE_CALL();
326 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800327
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800328 if (request) {
329 *request = NULL;
330 }
331
332 status_t res;
333 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
334
335 Mutex::Autolock icl(mIProCameraUserLock);
336
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800337 if (!mDevice.get()) return DEAD_OBJECT;
338
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800339 CameraMetadata metadata;
340 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
341 *request = metadata.release();
342 }
343
344 return res;
Igor Murashkin69e22432013-02-20 18:24:43 -0800345}
346
Igor Murashkind127c2c2013-02-21 13:49:26 -0800347status_t ProCamera2Client::getCameraInfo(int cameraId,
348 /*out*/
349 camera_metadata** info)
350{
351 if (cameraId != mCameraId) {
352 return INVALID_OPERATION;
353 }
354
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800355 Mutex::Autolock icl(mIProCameraUserLock);
356
357 if (!mDevice.get()) return DEAD_OBJECT;
358
Igor Murashkind127c2c2013-02-21 13:49:26 -0800359 CameraMetadata deviceInfo = mDevice->info();
360 *info = deviceInfo.release();
361
362 return OK;
363}
364
Igor Murashkin69e22432013-02-20 18:24:43 -0800365status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
366 String8 result;
367 result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
368 mCameraId,
369 getRemoteCallback()->asBinder().get(),
370 mClientPid);
371 result.append(" State: ");
372
373 // TODO: print dynamic/request section from most recent requests
Igor Murashkin418e4932013-02-21 12:02:29 -0800374 mFrameProcessor->dump(fd, args);
Igor Murashkin69e22432013-02-20 18:24:43 -0800375
376#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
377
378 result = " Device dump:\n";
379 write(fd, result.string(), result.size());
380
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800381 if (!mDevice.get()) {
382 result = " *** Device is detached\n";
383 write(fd, result.string(), result.size());
384 return NO_ERROR;
385 }
386
Igor Murashkin69e22432013-02-20 18:24:43 -0800387 status_t res = mDevice->dump(fd, args);
388 if (res != OK) {
389 result = String8::format(" Error dumping device: %s (%d)",
390 strerror(-res), res);
391 write(fd, result.string(), result.size());
392 }
393
394#undef CASE_APPEND_ENUM
395 return NO_ERROR;
396}
397
398// IProCameraUser interface
399
400void ProCamera2Client::disconnect() {
401 ATRACE_CALL();
402 Mutex::Autolock icl(mIProCameraUserLock);
403 status_t res;
404
405 // Allow both client and the media server to disconnect at all times
406 int callingPid = getCallingPid();
407 if (callingPid != mClientPid && callingPid != mServicePid) return;
408
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800409 ALOGV("Camera %d: Shutting down", mCameraId);
410
411 detachDevice();
412 ProClient::disconnect();
413
414 ALOGV("Camera %d: Shut down complete complete", mCameraId);
415}
416
417void ProCamera2Client::detachDevice() {
Igor Murashkin69e22432013-02-20 18:24:43 -0800418 if (mDevice == 0) return;
419
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800420 ALOGV("Camera %d: Stopping processors", mCameraId);
421
Igor Murashkin418e4932013-02-21 12:02:29 -0800422 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
423 FRAME_PROCESSOR_LISTENER_MAX_ID,
424 /*listener*/this);
425 mFrameProcessor->requestExit();
Igor Murashkin69e22432013-02-20 18:24:43 -0800426 ALOGV("Camera %d: Waiting for threads", mCameraId);
Igor Murashkin418e4932013-02-21 12:02:29 -0800427 mFrameProcessor->join();
Igor Murashkin69e22432013-02-20 18:24:43 -0800428 ALOGV("Camera %d: Disconnecting device", mCameraId);
429
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800430 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
431 {
432 mDevice->clearStreamingRequest();
433
434 status_t code;
435 if ((code = mDevice->waitUntilDrained()) != OK) {
436 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
437 code);
438 }
439 }
440
Igor Murashkin69e22432013-02-20 18:24:43 -0800441 mDevice->disconnect();
442
443 mDevice.clear();
444
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800445 ALOGV("Camera %d: Detach complete", mCameraId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800446}
447
448status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) {
449 ATRACE_CALL();
450 ALOGV("%s: E", __FUNCTION__);
451 Mutex::Autolock icl(mIProCameraUserLock);
452
453 if (mClientPid != 0 && getCallingPid() != mClientPid) {
454 ALOGE("%s: Camera %d: Connection attempt from pid %d; "
455 "current locked to pid %d", __FUNCTION__,
456 mCameraId, getCallingPid(), mClientPid);
457 return BAD_VALUE;
458 }
459
460 mClientPid = getCallingPid();
461
462 mRemoteCallback = client;
463 mSharedCameraCallbacks = client;
464
465 return OK;
466}
467
468/** Device-related methods */
469
470void ProCamera2Client::notifyError(int errorCode, int arg1, int arg2) {
471 ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
472 arg1, arg2);
473}
474
475void ProCamera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) {
476 ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
477 frameNumber, timestamp);
478}
479
480void ProCamera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
481 ALOGV("%s: Autofocus state now %d, last trigger %d",
482 __FUNCTION__, newState, triggerId);
483
484 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
485 if (l.mRemoteCallback != 0) {
486 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
487 1, 0);
488 }
489 if (l.mRemoteCallback != 0) {
490 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
491 1, 0);
492 }
493}
494
495void ProCamera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
496 ALOGV("%s: Autoexposure state now %d, last trigger %d",
497 __FUNCTION__, newState, triggerId);
498}
499
500void ProCamera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
501 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
502 __FUNCTION__, newState, triggerId);
503}
504
505int ProCamera2Client::getCameraId() const {
506 return mCameraId;
507}
508
509const sp<Camera2Device>& ProCamera2Client::getCameraDevice() {
510 return mDevice;
511}
512
513const sp<CameraService>& ProCamera2Client::getCameraService() {
514 return mCameraService;
515}
516
517ProCamera2Client::SharedCameraCallbacks::Lock::Lock(
518 SharedCameraCallbacks &client):
519 mRemoteCallback(client.mRemoteCallback),
520 mSharedClient(client) {
521 mSharedClient.mRemoteCallbackLock.lock();
522}
523
524ProCamera2Client::SharedCameraCallbacks::Lock::~Lock() {
525 mSharedClient.mRemoteCallbackLock.unlock();
526}
527
528ProCamera2Client::SharedCameraCallbacks::SharedCameraCallbacks
529 (const sp<IProCameraCallbacks>&client):
530 mRemoteCallback(client) {
531}
532
533ProCamera2Client::SharedCameraCallbacks&
534 ProCamera2Client::SharedCameraCallbacks::operator=(
535 const sp<IProCameraCallbacks>&client) {
536 Mutex::Autolock l(mRemoteCallbackLock);
537 mRemoteCallback = client;
538 return *this;
539}
540
541void ProCamera2Client::SharedCameraCallbacks::clear() {
542 Mutex::Autolock l(mRemoteCallbackLock);
543 mRemoteCallback.clear();
544}
545
Igor Murashkin418e4932013-02-21 12:02:29 -0800546void ProCamera2Client::onFrameAvailable(int32_t frameId,
547 const CameraMetadata& frame) {
548 ATRACE_CALL();
549 ALOGV("%s", __FUNCTION__);
550
551 Mutex::Autolock icl(mIProCameraUserLock);
552 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
553
554 if (mRemoteCallback != NULL) {
555 CameraMetadata tmp(frame);
556 camera_metadata_t* meta = tmp.release();
557 ALOGV("%s: meta = %p ", __FUNCTION__, meta);
558 mRemoteCallback->onResultReceived(frameId, meta);
559 tmp.acquire(meta);
560 }
561
562}
563
Igor Murashkin69e22432013-02-20 18:24:43 -0800564} // namespace android