blob: 4a5a3d5a37384b2d908e7503b911381a2edce750 [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
Igor Murashkin69e22432013-02-20 18:24:43 -080034// Interface used by CameraService
35
36ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
Igor Murashkina2e203b2013-03-01 16:22:28 -080037 const sp<IProCameraCallbacks>& remoteCallback,
38 const String16& clientPackageName,
39 int cameraId,
40 int cameraFacing,
41 int clientPid,
42 uid_t clientUid,
43 int servicePid) :
44 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
45 cameraId, cameraFacing, clientPid, clientUid, servicePid)
Igor Murashkin69e22432013-02-20 18:24:43 -080046{
47 ATRACE_CALL();
48 ALOGI("ProCamera %d: Opened", cameraId);
49
Igor Murashkin69e22432013-02-20 18:24:43 -080050 mExclusiveLock = false;
51}
52
Igor Murashkin69e22432013-02-20 18:24:43 -080053status_t ProCamera2Client::initialize(camera_module_t *module)
54{
55 ATRACE_CALL();
Igor Murashkin69e22432013-02-20 18:24:43 -080056 status_t res;
57
Igor Murashkina2e203b2013-03-01 16:22:28 -080058 res = Camera2ClientBase::initialize(module);
Igor Murashkin69e22432013-02-20 18:24:43 -080059 if (res != OK) {
Igor Murashkina2e203b2013-03-01 16:22:28 -080060 return res;
Igor Murashkin69e22432013-02-20 18:24:43 -080061 }
62
Igor Murashkin418e4932013-02-21 12:02:29 -080063 String8 threadName;
64 mFrameProcessor = new ProFrameProcessor(this);
Igor Murashkina2e203b2013-03-01 16:22:28 -080065 threadName = String8::format("PC2-%d-FrameProc", mCameraId);
Igor Murashkin418e4932013-02-21 12:02:29 -080066 mFrameProcessor->run(threadName.string());
67
68 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
69 FRAME_PROCESSOR_LISTENER_MAX_ID,
70 /*listener*/this);
71
Igor Murashkin69e22432013-02-20 18:24:43 -080072 return OK;
73}
74
75ProCamera2Client::~ProCamera2Client() {
Igor Murashkin69e22432013-02-20 18:24:43 -080076}
77
78status_t ProCamera2Client::exclusiveTryLock() {
79 ATRACE_CALL();
80 ALOGV("%s", __FUNCTION__);
81
Igor Murashkina2e203b2013-03-01 16:22:28 -080082 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -080083 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
84
Igor Murashkin8fdfbe22013-02-27 12:55:20 -080085 if (!mDevice.get()) return PERMISSION_DENIED;
86
Igor Murashkin69e22432013-02-20 18:24:43 -080087 if (!mExclusiveLock) {
88 mExclusiveLock = true;
89
90 if (mRemoteCallback != NULL) {
91 mRemoteCallback->onLockStatusChanged(
92 IProCameraCallbacks::LOCK_ACQUIRED);
93 }
94
95 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
96
97 return OK;
98 }
99
100 // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
101
102 // don't allow recursive locking
103 ALOGW("%s: exclusive lock already exists - recursive locking is not"
104 "allowed", __FUNCTION__);
105
106 return ALREADY_EXISTS;
107}
108
109status_t ProCamera2Client::exclusiveLock() {
110 ATRACE_CALL();
111 ALOGV("%s", __FUNCTION__);
112
Igor Murashkina2e203b2013-03-01 16:22:28 -0800113 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -0800114 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
115
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800116 if (!mDevice.get()) return PERMISSION_DENIED;
117
Igor Murashkin69e22432013-02-20 18:24:43 -0800118 /**
119 * TODO: this should asynchronously 'wait' until the lock becomes available
120 * if another client already has an exclusive lock.
121 *
122 * once we have proper sharing support this will need to do
123 * more than just return immediately
124 */
125 if (!mExclusiveLock) {
126 mExclusiveLock = true;
127
128 if (mRemoteCallback != NULL) {
129 mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
130 }
131
132 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
133
134 return OK;
135 }
136
137 // don't allow recursive locking
138 ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
139 , __FUNCTION__);
140 return ALREADY_EXISTS;
141}
142
143status_t ProCamera2Client::exclusiveUnlock() {
144 ATRACE_CALL();
145 ALOGV("%s", __FUNCTION__);
146
Igor Murashkina2e203b2013-03-01 16:22:28 -0800147 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -0800148 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
149
150 // don't allow unlocking if we have no lock
151 if (!mExclusiveLock) {
152 ALOGW("%s: cannot unlock, no lock was held in the first place",
153 __FUNCTION__);
154 return BAD_VALUE;
155 }
156
157 mExclusiveLock = false;
158 if (mRemoteCallback != NULL ) {
159 mRemoteCallback->onLockStatusChanged(
160 IProCameraCallbacks::LOCK_RELEASED);
161 }
162 ALOGV("%s: exclusive lock released", __FUNCTION__);
163
164 return OK;
165}
166
167bool ProCamera2Client::hasExclusiveLock() {
Igor Murashkina2e203b2013-03-01 16:22:28 -0800168 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -0800169 return mExclusiveLock;
170}
171
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800172void ProCamera2Client::onExclusiveLockStolen() {
173 ALOGV("%s: ProClient lost exclusivity (id %d)",
174 __FUNCTION__, mCameraId);
175
Igor Murashkina2e203b2013-03-01 16:22:28 -0800176 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800177 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
178
179 if (mExclusiveLock && mRemoteCallback.get() != NULL) {
180 mRemoteCallback->onLockStatusChanged(
181 IProCameraCallbacks::LOCK_STOLEN);
182 }
183
184 mExclusiveLock = false;
185
186 //TODO: we should not need to detach the device, merely reset it.
187 detachDevice();
188}
189
Igor Murashkin69e22432013-02-20 18:24:43 -0800190status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
191 bool streaming) {
192 ATRACE_CALL();
193 ALOGV("%s", __FUNCTION__);
194
Igor Murashkina2e203b2013-03-01 16:22:28 -0800195 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800196
197 if (!mDevice.get()) return DEAD_OBJECT;
198
Igor Murashkin69e22432013-02-20 18:24:43 -0800199 if (!mExclusiveLock) {
200 return PERMISSION_DENIED;
201 }
202
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800203 CameraMetadata metadata(request);
204
205 if (streaming) {
206 return mDevice->setStreamingRequest(metadata);
207 } else {
208 return mDevice->capture(metadata);
209 }
210
211 // unreachable. thx gcc for a useless warning
Igor Murashkin69e22432013-02-20 18:24:43 -0800212 return OK;
213}
214
215status_t ProCamera2Client::cancelRequest(int requestId) {
216 ATRACE_CALL();
217 ALOGV("%s", __FUNCTION__);
218
Igor Murashkina2e203b2013-03-01 16:22:28 -0800219 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800220
221 if (!mDevice.get()) return DEAD_OBJECT;
222
Igor Murashkin69e22432013-02-20 18:24:43 -0800223 if (!mExclusiveLock) {
224 return PERMISSION_DENIED;
225 }
226
Igor Murashkina2e203b2013-03-01 16:22:28 -0800227 // TODO: implement
Igor Murashkin69e22432013-02-20 18:24:43 -0800228 ALOGE("%s: not fully implemented yet", __FUNCTION__);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800229 return INVALID_OPERATION;
Igor Murashkin69e22432013-02-20 18:24:43 -0800230}
231
Igor Murashkina2e203b2013-03-01 16:22:28 -0800232//TODO: Remove
Igor Murashkin69e22432013-02-20 18:24:43 -0800233status_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 Murashkin9fb7fa12013-02-20 19:02:36 -0800240 ATRACE_CALL();
241 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800242
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800243 status_t res;
244 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
245
Igor Murashkina2e203b2013-03-01 16:22:28 -0800246 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800247
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800248 if (!mDevice.get()) return DEAD_OBJECT;
Igor Murashkinc0767f12013-02-20 19:29:53 -0800249 mDevice->clearStreamingRequest();
250
251 status_t code;
252 if ((code = mDevice->waitUntilDrained()) != OK) {
253 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
254 }
255
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800256 return mDevice->deleteStream(streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800257}
258
259status_t ProCamera2Client::createStream(int width, int height, int format,
Igor Murashkin5494cdc2013-02-20 19:15:15 -0800260 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800261 /*out*/
262 int* streamId)
263{
264 if (streamId) {
265 *streamId = -1;
266 }
Igor Murashkin69e22432013-02-20 18:24:43 -0800267
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800268 ATRACE_CALL();
269 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
270
271 status_t res;
272 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
273
Igor Murashkina2e203b2013-03-01 16:22:28 -0800274 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800275
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800276 if (!mDevice.get()) return DEAD_OBJECT;
277
Igor Murashkin5494cdc2013-02-20 19:15:15 -0800278 sp<IBinder> binder;
279 sp<ANativeWindow> window;
280 if (bufferProducer != 0) {
281 binder = bufferProducer->asBinder();
282 window = new Surface(bufferProducer);
283 }
284
285 return mDevice->createStream(window, width, height, format, /*size*/1,
286 streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800287}
288
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800289// Create a request object from a template.
290// -- Caller owns the newly allocated metadata
Igor Murashkin69e22432013-02-20 18:24:43 -0800291status_t ProCamera2Client::createDefaultRequest(int templateId,
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800292 /*out*/
293 camera_metadata** request)
294{
295 ATRACE_CALL();
296 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800297
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800298 if (request) {
299 *request = NULL;
300 }
301
302 status_t res;
303 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
304
Igor Murashkina2e203b2013-03-01 16:22:28 -0800305 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800306
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800307 if (!mDevice.get()) return DEAD_OBJECT;
308
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800309 CameraMetadata metadata;
310 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
311 *request = metadata.release();
312 }
313
314 return res;
Igor Murashkin69e22432013-02-20 18:24:43 -0800315}
316
Igor Murashkind127c2c2013-02-21 13:49:26 -0800317status_t ProCamera2Client::getCameraInfo(int cameraId,
318 /*out*/
319 camera_metadata** info)
320{
321 if (cameraId != mCameraId) {
322 return INVALID_OPERATION;
323 }
324
Igor Murashkina2e203b2013-03-01 16:22:28 -0800325 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800326
327 if (!mDevice.get()) return DEAD_OBJECT;
328
Igor Murashkind127c2c2013-02-21 13:49:26 -0800329 CameraMetadata deviceInfo = mDevice->info();
330 *info = deviceInfo.release();
331
332 return OK;
333}
334
Igor Murashkin69e22432013-02-20 18:24:43 -0800335status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
336 String8 result;
337 result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
338 mCameraId,
339 getRemoteCallback()->asBinder().get(),
340 mClientPid);
341 result.append(" State: ");
342
343 // TODO: print dynamic/request section from most recent requests
Igor Murashkin418e4932013-02-21 12:02:29 -0800344 mFrameProcessor->dump(fd, args);
Igor Murashkin69e22432013-02-20 18:24:43 -0800345
Igor Murashkina2e203b2013-03-01 16:22:28 -0800346 return dumpDevice(fd, args);
Igor Murashkin69e22432013-02-20 18:24:43 -0800347}
348
349// IProCameraUser interface
350
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800351void ProCamera2Client::detachDevice() {
Igor Murashkin69e22432013-02-20 18:24:43 -0800352 if (mDevice == 0) return;
353
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800354 ALOGV("Camera %d: Stopping processors", mCameraId);
355
Igor Murashkin418e4932013-02-21 12:02:29 -0800356 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
357 FRAME_PROCESSOR_LISTENER_MAX_ID,
358 /*listener*/this);
359 mFrameProcessor->requestExit();
Igor Murashkin69e22432013-02-20 18:24:43 -0800360 ALOGV("Camera %d: Waiting for threads", mCameraId);
Igor Murashkin418e4932013-02-21 12:02:29 -0800361 mFrameProcessor->join();
Igor Murashkin69e22432013-02-20 18:24:43 -0800362 ALOGV("Camera %d: Disconnecting device", mCameraId);
363
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800364 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
365 {
366 mDevice->clearStreamingRequest();
367
368 status_t code;
369 if ((code = mDevice->waitUntilDrained()) != OK) {
370 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
371 code);
372 }
373 }
374
Igor Murashkina2e203b2013-03-01 16:22:28 -0800375 Camera2ClientBase::detachDevice();
Igor Murashkin69e22432013-02-20 18:24:43 -0800376}
377
378/** Device-related methods */
Igor Murashkin418e4932013-02-21 12:02:29 -0800379void ProCamera2Client::onFrameAvailable(int32_t frameId,
380 const CameraMetadata& frame) {
381 ATRACE_CALL();
382 ALOGV("%s", __FUNCTION__);
383
Igor Murashkina2e203b2013-03-01 16:22:28 -0800384 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin418e4932013-02-21 12:02:29 -0800385 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
386
387 if (mRemoteCallback != NULL) {
388 CameraMetadata tmp(frame);
389 camera_metadata_t* meta = tmp.release();
390 ALOGV("%s: meta = %p ", __FUNCTION__, meta);
391 mRemoteCallback->onResultReceived(frameId, meta);
392 tmp.acquire(meta);
393 }
394
395}
396
Igor Murashkin69e22432013-02-20 18:24:43 -0800397} // namespace android