blob: 251fdabc87dcb32b2005ee67560e9da418179070 [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 Murashkin71381052013-03-04 14:53:08 -080030#include "CameraDeviceBase.h"
Igor Murashkin69e22432013-02-20 18:24:43 -080031
32namespace android {
33using namespace camera2;
34
Igor Murashkin69e22432013-02-20 18:24:43 -080035// Interface used by CameraService
36
37ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
Igor Murashkina2e203b2013-03-01 16:22:28 -080038 const sp<IProCameraCallbacks>& remoteCallback,
39 const String16& clientPackageName,
40 int cameraId,
41 int cameraFacing,
42 int clientPid,
43 uid_t clientUid,
44 int servicePid) :
45 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
46 cameraId, cameraFacing, clientPid, clientUid, servicePid)
Igor Murashkin69e22432013-02-20 18:24:43 -080047{
48 ATRACE_CALL();
49 ALOGI("ProCamera %d: Opened", cameraId);
50
Igor Murashkin69e22432013-02-20 18:24:43 -080051 mExclusiveLock = false;
52}
53
Igor Murashkin69e22432013-02-20 18:24:43 -080054status_t ProCamera2Client::initialize(camera_module_t *module)
55{
56 ATRACE_CALL();
Igor Murashkin69e22432013-02-20 18:24:43 -080057 status_t res;
58
Igor Murashkina2e203b2013-03-01 16:22:28 -080059 res = Camera2ClientBase::initialize(module);
Igor Murashkin69e22432013-02-20 18:24:43 -080060 if (res != OK) {
Igor Murashkina2e203b2013-03-01 16:22:28 -080061 return res;
Igor Murashkin69e22432013-02-20 18:24:43 -080062 }
63
Igor Murashkin418e4932013-02-21 12:02:29 -080064 String8 threadName;
Igor Murashkin71381052013-03-04 14:53:08 -080065 mFrameProcessor = new ProFrameProcessor(mDevice);
Igor Murashkina2e203b2013-03-01 16:22:28 -080066 threadName = String8::format("PC2-%d-FrameProc", mCameraId);
Igor Murashkin418e4932013-02-21 12:02:29 -080067 mFrameProcessor->run(threadName.string());
68
69 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
70 FRAME_PROCESSOR_LISTENER_MAX_ID,
71 /*listener*/this);
72
Igor Murashkin69e22432013-02-20 18:24:43 -080073 return OK;
74}
75
76ProCamera2Client::~ProCamera2Client() {
Igor Murashkin69e22432013-02-20 18:24:43 -080077}
78
79status_t ProCamera2Client::exclusiveTryLock() {
80 ATRACE_CALL();
81 ALOGV("%s", __FUNCTION__);
82
Igor Murashkina2e203b2013-03-01 16:22:28 -080083 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -080084 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
85
Igor Murashkin8fdfbe22013-02-27 12:55:20 -080086 if (!mDevice.get()) return PERMISSION_DENIED;
87
Igor Murashkin69e22432013-02-20 18:24:43 -080088 if (!mExclusiveLock) {
89 mExclusiveLock = true;
90
91 if (mRemoteCallback != NULL) {
92 mRemoteCallback->onLockStatusChanged(
93 IProCameraCallbacks::LOCK_ACQUIRED);
94 }
95
96 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
97
98 return OK;
99 }
100
101 // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
102
103 // don't allow recursive locking
104 ALOGW("%s: exclusive lock already exists - recursive locking is not"
105 "allowed", __FUNCTION__);
106
107 return ALREADY_EXISTS;
108}
109
110status_t ProCamera2Client::exclusiveLock() {
111 ATRACE_CALL();
112 ALOGV("%s", __FUNCTION__);
113
Igor Murashkina2e203b2013-03-01 16:22:28 -0800114 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -0800115 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
116
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800117 if (!mDevice.get()) return PERMISSION_DENIED;
118
Igor Murashkin69e22432013-02-20 18:24:43 -0800119 /**
120 * TODO: this should asynchronously 'wait' until the lock becomes available
121 * if another client already has an exclusive lock.
122 *
123 * once we have proper sharing support this will need to do
124 * more than just return immediately
125 */
126 if (!mExclusiveLock) {
127 mExclusiveLock = true;
128
129 if (mRemoteCallback != NULL) {
130 mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
131 }
132
133 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
134
135 return OK;
136 }
137
138 // don't allow recursive locking
139 ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
140 , __FUNCTION__);
141 return ALREADY_EXISTS;
142}
143
144status_t ProCamera2Client::exclusiveUnlock() {
145 ATRACE_CALL();
146 ALOGV("%s", __FUNCTION__);
147
Igor Murashkina2e203b2013-03-01 16:22:28 -0800148 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -0800149 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
150
151 // don't allow unlocking if we have no lock
152 if (!mExclusiveLock) {
153 ALOGW("%s: cannot unlock, no lock was held in the first place",
154 __FUNCTION__);
155 return BAD_VALUE;
156 }
157
158 mExclusiveLock = false;
159 if (mRemoteCallback != NULL ) {
160 mRemoteCallback->onLockStatusChanged(
161 IProCameraCallbacks::LOCK_RELEASED);
162 }
163 ALOGV("%s: exclusive lock released", __FUNCTION__);
164
165 return OK;
166}
167
168bool ProCamera2Client::hasExclusiveLock() {
Igor Murashkina2e203b2013-03-01 16:22:28 -0800169 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin69e22432013-02-20 18:24:43 -0800170 return mExclusiveLock;
171}
172
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800173void ProCamera2Client::onExclusiveLockStolen() {
174 ALOGV("%s: ProClient lost exclusivity (id %d)",
175 __FUNCTION__, mCameraId);
176
Igor Murashkina2e203b2013-03-01 16:22:28 -0800177 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800178 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
179
180 if (mExclusiveLock && mRemoteCallback.get() != NULL) {
181 mRemoteCallback->onLockStatusChanged(
182 IProCameraCallbacks::LOCK_STOLEN);
183 }
184
185 mExclusiveLock = false;
186
187 //TODO: we should not need to detach the device, merely reset it.
188 detachDevice();
189}
190
Igor Murashkin69e22432013-02-20 18:24:43 -0800191status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
192 bool streaming) {
193 ATRACE_CALL();
194 ALOGV("%s", __FUNCTION__);
195
Igor Murashkina2e203b2013-03-01 16:22:28 -0800196 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800197
198 if (!mDevice.get()) return DEAD_OBJECT;
199
Igor Murashkin69e22432013-02-20 18:24:43 -0800200 if (!mExclusiveLock) {
201 return PERMISSION_DENIED;
202 }
203
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800204 CameraMetadata metadata(request);
205
Igor Murashkinb2d99922013-04-23 14:51:29 -0700206 if (!enforceRequestPermissions(metadata)) {
207 return PERMISSION_DENIED;
208 }
209
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800210 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 Murashkin69e22432013-02-20 18:24:43 -0800217 return OK;
218}
219
220status_t ProCamera2Client::cancelRequest(int requestId) {
221 ATRACE_CALL();
222 ALOGV("%s", __FUNCTION__);
223
Igor Murashkina2e203b2013-03-01 16:22:28 -0800224 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800225
226 if (!mDevice.get()) return DEAD_OBJECT;
227
Igor Murashkin69e22432013-02-20 18:24:43 -0800228 if (!mExclusiveLock) {
229 return PERMISSION_DENIED;
230 }
231
Igor Murashkina2e203b2013-03-01 16:22:28 -0800232 // TODO: implement
Igor Murashkin69e22432013-02-20 18:24:43 -0800233 ALOGE("%s: not fully implemented yet", __FUNCTION__);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800234 return INVALID_OPERATION;
Igor Murashkin69e22432013-02-20 18:24:43 -0800235}
236
Igor Murashkin7cf9a7e2013-03-04 16:14:23 -0800237status_t ProCamera2Client::deleteStream(int streamId) {
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800238 ATRACE_CALL();
239 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800240
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800241 status_t res;
242 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
243
Igor Murashkina2e203b2013-03-01 16:22:28 -0800244 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800245
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800246 if (!mDevice.get()) return DEAD_OBJECT;
Igor Murashkinc0767f12013-02-20 19:29:53 -0800247 mDevice->clearStreamingRequest();
248
249 status_t code;
250 if ((code = mDevice->waitUntilDrained()) != OK) {
251 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
252 }
253
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800254 return mDevice->deleteStream(streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800255}
256
257status_t ProCamera2Client::createStream(int width, int height, int format,
Igor Murashkin5494cdc2013-02-20 19:15:15 -0800258 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800259 /*out*/
260 int* streamId)
261{
262 if (streamId) {
263 *streamId = -1;
264 }
Igor Murashkin69e22432013-02-20 18:24:43 -0800265
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800266 ATRACE_CALL();
267 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
268
269 status_t res;
270 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
271
Igor Murashkina2e203b2013-03-01 16:22:28 -0800272 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800273
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800274 if (!mDevice.get()) return DEAD_OBJECT;
275
Igor Murashkin5494cdc2013-02-20 19:15:15 -0800276 sp<IBinder> binder;
277 sp<ANativeWindow> window;
278 if (bufferProducer != 0) {
279 binder = bufferProducer->asBinder();
280 window = new Surface(bufferProducer);
281 }
282
283 return mDevice->createStream(window, width, height, format, /*size*/1,
284 streamId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800285}
286
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800287// Create a request object from a template.
288// -- Caller owns the newly allocated metadata
Igor Murashkin69e22432013-02-20 18:24:43 -0800289status_t ProCamera2Client::createDefaultRequest(int templateId,
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800290 /*out*/
291 camera_metadata** request)
292{
293 ATRACE_CALL();
294 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
Igor Murashkin69e22432013-02-20 18:24:43 -0800295
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800296 if (request) {
297 *request = NULL;
298 }
299
300 status_t res;
301 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
302
Igor Murashkina2e203b2013-03-01 16:22:28 -0800303 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800304
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800305 if (!mDevice.get()) return DEAD_OBJECT;
306
Igor Murashkin9fb7fa12013-02-20 19:02:36 -0800307 CameraMetadata metadata;
308 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
309 *request = metadata.release();
310 }
311
312 return res;
Igor Murashkin69e22432013-02-20 18:24:43 -0800313}
314
Igor Murashkind127c2c2013-02-21 13:49:26 -0800315status_t ProCamera2Client::getCameraInfo(int cameraId,
316 /*out*/
317 camera_metadata** info)
318{
319 if (cameraId != mCameraId) {
320 return INVALID_OPERATION;
321 }
322
Igor Murashkina2e203b2013-03-01 16:22:28 -0800323 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800324
325 if (!mDevice.get()) return DEAD_OBJECT;
326
Igor Murashkind127c2c2013-02-21 13:49:26 -0800327 CameraMetadata deviceInfo = mDevice->info();
328 *info = deviceInfo.release();
329
330 return OK;
331}
332
Igor Murashkin69e22432013-02-20 18:24:43 -0800333status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
334 String8 result;
335 result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
336 mCameraId,
337 getRemoteCallback()->asBinder().get(),
338 mClientPid);
339 result.append(" State: ");
340
341 // TODO: print dynamic/request section from most recent requests
Igor Murashkin418e4932013-02-21 12:02:29 -0800342 mFrameProcessor->dump(fd, args);
Igor Murashkin69e22432013-02-20 18:24:43 -0800343
Igor Murashkina2e203b2013-03-01 16:22:28 -0800344 return dumpDevice(fd, args);
Igor Murashkin69e22432013-02-20 18:24:43 -0800345}
346
347// IProCameraUser interface
348
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800349void ProCamera2Client::detachDevice() {
Igor Murashkin69e22432013-02-20 18:24:43 -0800350 if (mDevice == 0) return;
351
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800352 ALOGV("Camera %d: Stopping processors", mCameraId);
353
Igor Murashkin418e4932013-02-21 12:02:29 -0800354 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
355 FRAME_PROCESSOR_LISTENER_MAX_ID,
356 /*listener*/this);
357 mFrameProcessor->requestExit();
Igor Murashkin69e22432013-02-20 18:24:43 -0800358 ALOGV("Camera %d: Waiting for threads", mCameraId);
Igor Murashkin418e4932013-02-21 12:02:29 -0800359 mFrameProcessor->join();
Igor Murashkin69e22432013-02-20 18:24:43 -0800360 ALOGV("Camera %d: Disconnecting device", mCameraId);
361
Igor Murashkin8fdfbe22013-02-27 12:55:20 -0800362 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
363 {
364 mDevice->clearStreamingRequest();
365
366 status_t code;
367 if ((code = mDevice->waitUntilDrained()) != OK) {
368 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
369 code);
370 }
371 }
372
Igor Murashkina2e203b2013-03-01 16:22:28 -0800373 Camera2ClientBase::detachDevice();
Igor Murashkin69e22432013-02-20 18:24:43 -0800374}
375
376/** Device-related methods */
Igor Murashkin418e4932013-02-21 12:02:29 -0800377void ProCamera2Client::onFrameAvailable(int32_t frameId,
378 const CameraMetadata& frame) {
379 ATRACE_CALL();
380 ALOGV("%s", __FUNCTION__);
381
Igor Murashkina2e203b2013-03-01 16:22:28 -0800382 Mutex::Autolock icl(mBinderSerializationLock);
Igor Murashkin418e4932013-02-21 12:02:29 -0800383 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
384
385 if (mRemoteCallback != NULL) {
386 CameraMetadata tmp(frame);
387 camera_metadata_t* meta = tmp.release();
388 ALOGV("%s: meta = %p ", __FUNCTION__, meta);
389 mRemoteCallback->onResultReceived(frameId, meta);
390 tmp.acquire(meta);
391 }
392
393}
394
Igor Murashkinb2d99922013-04-23 14:51:29 -0700395bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {
396
397 const int pid = IPCThreadState::self()->getCallingPid();
398 const int selfPid = getpid();
399 camera_metadata_entry_t entry;
400
401 /**
402 * Mixin default important security values
403 * - android.led.transmit = defaulted ON
404 */
405 CameraMetadata staticInfo = mDevice->info();
406 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
407 for(size_t i = 0; i < entry.count; ++i) {
408 uint8_t led = entry.data.u8[i];
409
410 switch(led) {
411 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
412 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
413 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
414 metadata.update(ANDROID_LED_TRANSMIT,
415 &transmitDefault, 1);
416 }
417 break;
418 }
419 }
420 }
421
422 // We can do anything!
423 if (pid == selfPid) {
424 return true;
425 }
426
427 /**
428 * Permission check special fields in the request
429 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
430 */
431 entry = metadata.find(ANDROID_LED_TRANSMIT);
432 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
433 String16 permissionString =
434 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
435 if (!checkCallingPermission(permissionString)) {
436 const int uid = IPCThreadState::self()->getCallingUid();
437 ALOGE("Permission Denial: "
438 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
439 return false;
440 }
441 }
442
443 return true;
444}
445
Igor Murashkin69e22432013-02-20 18:24:43 -0800446} // namespace android