blob: 761179669500a545d96df4cbbd8a28dc5257a8a6 [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,
46 int cameraId,
47 int cameraFacing,
48 int clientPid,
49 int servicePid):
50 ProClient(cameraService, remoteCallback,
51 cameraId, cameraFacing, clientPid, servicePid),
52 mSharedCameraCallbacks(remoteCallback)
53{
54 ATRACE_CALL();
55 ALOGI("ProCamera %d: Opened", cameraId);
56
57 mDevice = new Camera2Device(cameraId);
58
59 mExclusiveLock = false;
60}
61
62status_t ProCamera2Client::checkPid(const char* checkLocation) const {
63 int callingPid = getCallingPid();
64 if (callingPid == mClientPid) return NO_ERROR;
65
66 ALOGE("%s: attempt to use a locked camera from a different process"
67 " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
68 return PERMISSION_DENIED;
69}
70
71status_t ProCamera2Client::initialize(camera_module_t *module)
72{
73 ATRACE_CALL();
74 ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
75 status_t res;
76
77 res = mDevice->initialize(module);
78 if (res != OK) {
79 ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
80 __FUNCTION__, mCameraId, strerror(-res), res);
81 return NO_INIT;
82 }
83
84 res = mDevice->setNotifyCallback(this);
85
Igor Murashkina91537e2013-02-21 12:02:29 -080086 String8 threadName;
87 mFrameProcessor = new ProFrameProcessor(this);
88 threadName = String8::format("PC2-%d-FrameProc",
89 mCameraId);
90 mFrameProcessor->run(threadName.string());
91
92 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
93 FRAME_PROCESSOR_LISTENER_MAX_ID,
94 /*listener*/this);
95
Igor Murashkin985fd302013-02-20 18:24:43 -080096 return OK;
97}
98
99ProCamera2Client::~ProCamera2Client() {
100 ATRACE_CALL();
101
102 mDestructionStarted = true;
103
104 disconnect();
105
106 ALOGI("ProCamera %d: Closed", mCameraId);
107}
108
109status_t ProCamera2Client::exclusiveTryLock() {
110 ATRACE_CALL();
111 ALOGV("%s", __FUNCTION__);
112
113 Mutex::Autolock icl(mIProCameraUserLock);
114 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
115
116 if (!mExclusiveLock) {
117 mExclusiveLock = true;
118
119 if (mRemoteCallback != NULL) {
120 mRemoteCallback->onLockStatusChanged(
121 IProCameraCallbacks::LOCK_ACQUIRED);
122 }
123
124 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
125
126 return OK;
127 }
128
129 // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
130
131 // don't allow recursive locking
132 ALOGW("%s: exclusive lock already exists - recursive locking is not"
133 "allowed", __FUNCTION__);
134
135 return ALREADY_EXISTS;
136}
137
138status_t ProCamera2Client::exclusiveLock() {
139 ATRACE_CALL();
140 ALOGV("%s", __FUNCTION__);
141
142 Mutex::Autolock icl(mIProCameraUserLock);
143 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
144
145 /**
146 * TODO: this should asynchronously 'wait' until the lock becomes available
147 * if another client already has an exclusive lock.
148 *
149 * once we have proper sharing support this will need to do
150 * more than just return immediately
151 */
152 if (!mExclusiveLock) {
153 mExclusiveLock = true;
154
155 if (mRemoteCallback != NULL) {
156 mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
157 }
158
159 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
160
161 return OK;
162 }
163
164 // don't allow recursive locking
165 ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
166 , __FUNCTION__);
167 return ALREADY_EXISTS;
168}
169
170status_t ProCamera2Client::exclusiveUnlock() {
171 ATRACE_CALL();
172 ALOGV("%s", __FUNCTION__);
173
174 Mutex::Autolock icl(mIProCameraUserLock);
175 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
176
177 // don't allow unlocking if we have no lock
178 if (!mExclusiveLock) {
179 ALOGW("%s: cannot unlock, no lock was held in the first place",
180 __FUNCTION__);
181 return BAD_VALUE;
182 }
183
184 mExclusiveLock = false;
185 if (mRemoteCallback != NULL ) {
186 mRemoteCallback->onLockStatusChanged(
187 IProCameraCallbacks::LOCK_RELEASED);
188 }
189 ALOGV("%s: exclusive lock released", __FUNCTION__);
190
191 return OK;
192}
193
194bool ProCamera2Client::hasExclusiveLock() {
195 return mExclusiveLock;
196}
197
198status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
199 bool streaming) {
200 ATRACE_CALL();
201 ALOGV("%s", __FUNCTION__);
202
203 Mutex::Autolock icl(mIProCameraUserLock);
204 if (!mExclusiveLock) {
205 return PERMISSION_DENIED;
206 }
207
Igor Murashkin3261fd32013-02-20 19:02:36 -0800208 CameraMetadata metadata(request);
209
210 if (streaming) {
211 return mDevice->setStreamingRequest(metadata);
212 } else {
213 return mDevice->capture(metadata);
214 }
215
216 // unreachable. thx gcc for a useless warning
Igor Murashkin985fd302013-02-20 18:24:43 -0800217 return OK;
218}
219
220status_t ProCamera2Client::cancelRequest(int requestId) {
221 ATRACE_CALL();
222 ALOGV("%s", __FUNCTION__);
223
224 Mutex::Autolock icl(mIProCameraUserLock);
225 if (!mExclusiveLock) {
226 return PERMISSION_DENIED;
227 }
228
229 ALOGE("%s: not fully implemented yet", __FUNCTION__);
Igor Murashkin3261fd32013-02-20 19:02:36 -0800230 return INVALID_OPERATION;
Igor Murashkin985fd302013-02-20 18:24:43 -0800231}
232
233status_t ProCamera2Client::requestStream(int streamId) {
234 ALOGE("%s: not implemented yet", __FUNCTION__);
235
236 return INVALID_OPERATION;
237}
238
239status_t ProCamera2Client::cancelStream(int streamId) {
Igor Murashkin3261fd32013-02-20 19:02:36 -0800240 ATRACE_CALL();
241 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800242
Igor Murashkin3261fd32013-02-20 19:02:36 -0800243 status_t res;
244 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
245
246 Mutex::Autolock icl(mIProCameraUserLock);
247
Igor Murashkin5835cc42013-02-20 19:29:53 -0800248 mDevice->clearStreamingRequest();
249
250 status_t code;
251 if ((code = mDevice->waitUntilDrained()) != OK) {
252 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
253 }
254
Igor Murashkin3261fd32013-02-20 19:02:36 -0800255 return mDevice->deleteStream(streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800256}
257
258status_t ProCamera2Client::createStream(int width, int height, int format,
Igor Murashkin76f8b432013-02-20 19:15:15 -0800259 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin3261fd32013-02-20 19:02:36 -0800260 /*out*/
261 int* streamId)
262{
263 if (streamId) {
264 *streamId = -1;
265 }
Igor Murashkin985fd302013-02-20 18:24:43 -0800266
Igor Murashkin3261fd32013-02-20 19:02:36 -0800267 ATRACE_CALL();
268 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
269
270 status_t res;
271 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
272
273 Mutex::Autolock icl(mIProCameraUserLock);
274
Igor Murashkin76f8b432013-02-20 19:15:15 -0800275 sp<IBinder> binder;
276 sp<ANativeWindow> window;
277 if (bufferProducer != 0) {
278 binder = bufferProducer->asBinder();
279 window = new Surface(bufferProducer);
280 }
281
282 return mDevice->createStream(window, width, height, format, /*size*/1,
283 streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800284}
285
Igor Murashkin3261fd32013-02-20 19:02:36 -0800286// Create a request object from a template.
287// -- Caller owns the newly allocated metadata
Igor Murashkin985fd302013-02-20 18:24:43 -0800288status_t ProCamera2Client::createDefaultRequest(int templateId,
Igor Murashkin3261fd32013-02-20 19:02:36 -0800289 /*out*/
290 camera_metadata** request)
291{
292 ATRACE_CALL();
293 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800294
Igor Murashkin3261fd32013-02-20 19:02:36 -0800295 if (request) {
296 *request = NULL;
297 }
298
299 status_t res;
300 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
301
302 Mutex::Autolock icl(mIProCameraUserLock);
303
304 CameraMetadata metadata;
305 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
306 *request = metadata.release();
307 }
308
309 return res;
Igor Murashkin985fd302013-02-20 18:24:43 -0800310}
311
Igor Murashkin985fd302013-02-20 18:24:43 -0800312status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
313 String8 result;
314 result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
315 mCameraId,
316 getRemoteCallback()->asBinder().get(),
317 mClientPid);
318 result.append(" State: ");
319
320 // TODO: print dynamic/request section from most recent requests
Igor Murashkina91537e2013-02-21 12:02:29 -0800321 mFrameProcessor->dump(fd, args);
Igor Murashkin985fd302013-02-20 18:24:43 -0800322
323#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
324
325 result = " Device dump:\n";
326 write(fd, result.string(), result.size());
327
328 status_t res = mDevice->dump(fd, args);
329 if (res != OK) {
330 result = String8::format(" Error dumping device: %s (%d)",
331 strerror(-res), res);
332 write(fd, result.string(), result.size());
333 }
334
335#undef CASE_APPEND_ENUM
336 return NO_ERROR;
337}
338
339// IProCameraUser interface
340
341void ProCamera2Client::disconnect() {
342 ATRACE_CALL();
343 Mutex::Autolock icl(mIProCameraUserLock);
344 status_t res;
345
346 // Allow both client and the media server to disconnect at all times
347 int callingPid = getCallingPid();
348 if (callingPid != mClientPid && callingPid != mServicePid) return;
349
350 if (mDevice == 0) return;
351
352 ALOGV("Camera %d: Shutting down", mCameraId);
Igor Murashkina91537e2013-02-21 12:02:29 -0800353 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
354 FRAME_PROCESSOR_LISTENER_MAX_ID,
355 /*listener*/this);
356 mFrameProcessor->requestExit();
Igor Murashkin985fd302013-02-20 18:24:43 -0800357 ALOGV("Camera %d: Waiting for threads", mCameraId);
Igor Murashkina91537e2013-02-21 12:02:29 -0800358 mFrameProcessor->join();
Igor Murashkin985fd302013-02-20 18:24:43 -0800359 ALOGV("Camera %d: Disconnecting device", mCameraId);
360
361 mDevice->disconnect();
362
363 mDevice.clear();
364
365 ProClient::disconnect();
366}
367
368status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) {
369 ATRACE_CALL();
370 ALOGV("%s: E", __FUNCTION__);
371 Mutex::Autolock icl(mIProCameraUserLock);
372
373 if (mClientPid != 0 && getCallingPid() != mClientPid) {
374 ALOGE("%s: Camera %d: Connection attempt from pid %d; "
375 "current locked to pid %d", __FUNCTION__,
376 mCameraId, getCallingPid(), mClientPid);
377 return BAD_VALUE;
378 }
379
380 mClientPid = getCallingPid();
381
382 mRemoteCallback = client;
383 mSharedCameraCallbacks = client;
384
385 return OK;
386}
387
388/** Device-related methods */
389
390void ProCamera2Client::notifyError(int errorCode, int arg1, int arg2) {
391 ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
392 arg1, arg2);
393}
394
395void ProCamera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) {
396 ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
397 frameNumber, timestamp);
398}
399
400void ProCamera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
401 ALOGV("%s: Autofocus state now %d, last trigger %d",
402 __FUNCTION__, newState, triggerId);
403
404 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
405 if (l.mRemoteCallback != 0) {
406 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
407 1, 0);
408 }
409 if (l.mRemoteCallback != 0) {
410 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
411 1, 0);
412 }
413}
414
415void ProCamera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
416 ALOGV("%s: Autoexposure state now %d, last trigger %d",
417 __FUNCTION__, newState, triggerId);
418}
419
420void ProCamera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
421 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
422 __FUNCTION__, newState, triggerId);
423}
424
425int ProCamera2Client::getCameraId() const {
426 return mCameraId;
427}
428
429const sp<Camera2Device>& ProCamera2Client::getCameraDevice() {
430 return mDevice;
431}
432
433const sp<CameraService>& ProCamera2Client::getCameraService() {
434 return mCameraService;
435}
436
437ProCamera2Client::SharedCameraCallbacks::Lock::Lock(
438 SharedCameraCallbacks &client):
439 mRemoteCallback(client.mRemoteCallback),
440 mSharedClient(client) {
441 mSharedClient.mRemoteCallbackLock.lock();
442}
443
444ProCamera2Client::SharedCameraCallbacks::Lock::~Lock() {
445 mSharedClient.mRemoteCallbackLock.unlock();
446}
447
448ProCamera2Client::SharedCameraCallbacks::SharedCameraCallbacks
449 (const sp<IProCameraCallbacks>&client):
450 mRemoteCallback(client) {
451}
452
453ProCamera2Client::SharedCameraCallbacks&
454 ProCamera2Client::SharedCameraCallbacks::operator=(
455 const sp<IProCameraCallbacks>&client) {
456 Mutex::Autolock l(mRemoteCallbackLock);
457 mRemoteCallback = client;
458 return *this;
459}
460
461void ProCamera2Client::SharedCameraCallbacks::clear() {
462 Mutex::Autolock l(mRemoteCallbackLock);
463 mRemoteCallback.clear();
464}
465
Igor Murashkina91537e2013-02-21 12:02:29 -0800466void ProCamera2Client::onFrameAvailable(int32_t frameId,
467 const CameraMetadata& frame) {
468 ATRACE_CALL();
469 ALOGV("%s", __FUNCTION__);
470
471 Mutex::Autolock icl(mIProCameraUserLock);
472 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
473
474 if (mRemoteCallback != NULL) {
475 CameraMetadata tmp(frame);
476 camera_metadata_t* meta = tmp.release();
477 ALOGV("%s: meta = %p ", __FUNCTION__, meta);
478 mRemoteCallback->onResultReceived(frameId, meta);
479 tmp.acquire(meta);
480 }
481
482}
483
Igor Murashkin985fd302013-02-20 18:24:43 -0800484} // namespace android