blob: 5ebe7138a00c4dbfb8be826a772c20e1b81617f6 [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"
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 Murashkin3261fd32013-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 Murashkin985fd302013-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 Murashkin3261fd32013-02-20 19:02:36 -0800219 return INVALID_OPERATION;
Igor Murashkin985fd302013-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 Murashkin3261fd32013-02-20 19:02:36 -0800229 ATRACE_CALL();
230 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800231
Igor Murashkin3261fd32013-02-20 19:02:36 -0800232 status_t res;
233 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
234
235 Mutex::Autolock icl(mIProCameraUserLock);
236
237 return mDevice->deleteStream(streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800238}
239
240status_t ProCamera2Client::createStream(int width, int height, int format,
Igor Murashkin3261fd32013-02-20 19:02:36 -0800241 const sp<Surface>& surface,
242 /*out*/
243 int* streamId)
244{
245 if (streamId) {
246 *streamId = -1;
247 }
Igor Murashkin985fd302013-02-20 18:24:43 -0800248
Igor Murashkin3261fd32013-02-20 19:02:36 -0800249 ATRACE_CALL();
250 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
251
252 status_t res;
253 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
254
255 Mutex::Autolock icl(mIProCameraUserLock);
256
257 return mDevice->createStream(surface, width, height, format, /*size*/1, streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800258}
259
Igor Murashkin3261fd32013-02-20 19:02:36 -0800260// Create a request object from a template.
261// -- Caller owns the newly allocated metadata
Igor Murashkin985fd302013-02-20 18:24:43 -0800262status_t ProCamera2Client::createDefaultRequest(int templateId,
Igor Murashkin3261fd32013-02-20 19:02:36 -0800263 /*out*/
264 camera_metadata** request)
265{
266 ATRACE_CALL();
267 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800268
Igor Murashkin3261fd32013-02-20 19:02:36 -0800269 if (request) {
270 *request = NULL;
271 }
272
273 status_t res;
274 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
275
276 Mutex::Autolock icl(mIProCameraUserLock);
277
278 CameraMetadata metadata;
279 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
280 *request = metadata.release();
281 }
282
283 return res;
Igor Murashkin985fd302013-02-20 18:24:43 -0800284}
285
Igor Murashkin985fd302013-02-20 18:24:43 -0800286status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
287 String8 result;
288 result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
289 mCameraId,
290 getRemoteCallback()->asBinder().get(),
291 mClientPid);
292 result.append(" State: ");
293
294 // TODO: print dynamic/request section from most recent requests
295
296#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
297
298 result = " Device dump:\n";
299 write(fd, result.string(), result.size());
300
301 status_t res = mDevice->dump(fd, args);
302 if (res != OK) {
303 result = String8::format(" Error dumping device: %s (%d)",
304 strerror(-res), res);
305 write(fd, result.string(), result.size());
306 }
307
308#undef CASE_APPEND_ENUM
309 return NO_ERROR;
310}
311
312// IProCameraUser interface
313
314void ProCamera2Client::disconnect() {
315 ATRACE_CALL();
316 Mutex::Autolock icl(mIProCameraUserLock);
317 status_t res;
318
319 // Allow both client and the media server to disconnect at all times
320 int callingPid = getCallingPid();
321 if (callingPid != mClientPid && callingPid != mServicePid) return;
322
323 if (mDevice == 0) return;
324
325 ALOGV("Camera %d: Shutting down", mCameraId);
326 ALOGV("Camera %d: Waiting for threads", mCameraId);
327 ALOGV("Camera %d: Disconnecting device", mCameraId);
328
329 mDevice->disconnect();
330
331 mDevice.clear();
332
333 ProClient::disconnect();
334}
335
336status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) {
337 ATRACE_CALL();
338 ALOGV("%s: E", __FUNCTION__);
339 Mutex::Autolock icl(mIProCameraUserLock);
340
341 if (mClientPid != 0 && getCallingPid() != mClientPid) {
342 ALOGE("%s: Camera %d: Connection attempt from pid %d; "
343 "current locked to pid %d", __FUNCTION__,
344 mCameraId, getCallingPid(), mClientPid);
345 return BAD_VALUE;
346 }
347
348 mClientPid = getCallingPid();
349
350 mRemoteCallback = client;
351 mSharedCameraCallbacks = client;
352
353 return OK;
354}
355
356/** Device-related methods */
357
358void ProCamera2Client::notifyError(int errorCode, int arg1, int arg2) {
359 ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
360 arg1, arg2);
361}
362
363void ProCamera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) {
364 ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
365 frameNumber, timestamp);
366}
367
368void ProCamera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
369 ALOGV("%s: Autofocus state now %d, last trigger %d",
370 __FUNCTION__, newState, triggerId);
371
372 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
373 if (l.mRemoteCallback != 0) {
374 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
375 1, 0);
376 }
377 if (l.mRemoteCallback != 0) {
378 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
379 1, 0);
380 }
381}
382
383void ProCamera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
384 ALOGV("%s: Autoexposure state now %d, last trigger %d",
385 __FUNCTION__, newState, triggerId);
386}
387
388void ProCamera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
389 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
390 __FUNCTION__, newState, triggerId);
391}
392
393int ProCamera2Client::getCameraId() const {
394 return mCameraId;
395}
396
397const sp<Camera2Device>& ProCamera2Client::getCameraDevice() {
398 return mDevice;
399}
400
401const sp<CameraService>& ProCamera2Client::getCameraService() {
402 return mCameraService;
403}
404
405ProCamera2Client::SharedCameraCallbacks::Lock::Lock(
406 SharedCameraCallbacks &client):
407 mRemoteCallback(client.mRemoteCallback),
408 mSharedClient(client) {
409 mSharedClient.mRemoteCallbackLock.lock();
410}
411
412ProCamera2Client::SharedCameraCallbacks::Lock::~Lock() {
413 mSharedClient.mRemoteCallbackLock.unlock();
414}
415
416ProCamera2Client::SharedCameraCallbacks::SharedCameraCallbacks
417 (const sp<IProCameraCallbacks>&client):
418 mRemoteCallback(client) {
419}
420
421ProCamera2Client::SharedCameraCallbacks&
422 ProCamera2Client::SharedCameraCallbacks::operator=(
423 const sp<IProCameraCallbacks>&client) {
424 Mutex::Autolock l(mRemoteCallbackLock);
425 mRemoteCallback = client;
426 return *this;
427}
428
429void ProCamera2Client::SharedCameraCallbacks::clear() {
430 Mutex::Autolock l(mRemoteCallbackLock);
431 mRemoteCallback.clear();
432}
433
434} // namespace android