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