1 /*
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
28 #include "api_pro/ProCamera2Client.h"
29 #include "common/CameraDeviceBase.h"
30
31 namespace android {
32 using namespace camera2;
33
34 // Interface used by CameraService
35
ProCamera2Client(const sp<CameraService> & cameraService,const sp<IProCameraCallbacks> & remoteCallback,const String16 & clientPackageName,int cameraId,int cameraFacing,int clientPid,uid_t clientUid,int servicePid)36 ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
37 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)
46 {
47 ATRACE_CALL();
48 ALOGI("ProCamera %d: Opened", cameraId);
49
50 mExclusiveLock = false;
51 }
52
initialize(camera_module_t * module)53 status_t ProCamera2Client::initialize(camera_module_t *module)
54 {
55 ATRACE_CALL();
56 status_t res;
57
58 res = Camera2ClientBase::initialize(module);
59 if (res != OK) {
60 return res;
61 }
62
63 String8 threadName;
64 mFrameProcessor = new FrameProcessorBase(mDevice);
65 threadName = String8::format("PC2-%d-FrameProc", mCameraId);
66 mFrameProcessor->run(threadName.string());
67
68 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
69 FRAME_PROCESSOR_LISTENER_MAX_ID,
70 /*listener*/this);
71
72 return OK;
73 }
74
~ProCamera2Client()75 ProCamera2Client::~ProCamera2Client() {
76 }
77
exclusiveTryLock()78 status_t ProCamera2Client::exclusiveTryLock() {
79 ATRACE_CALL();
80 ALOGV("%s", __FUNCTION__);
81
82 Mutex::Autolock icl(mBinderSerializationLock);
83 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
84
85 if (!mDevice.get()) return PERMISSION_DENIED;
86
87 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
exclusiveLock()109 status_t ProCamera2Client::exclusiveLock() {
110 ATRACE_CALL();
111 ALOGV("%s", __FUNCTION__);
112
113 Mutex::Autolock icl(mBinderSerializationLock);
114 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
115
116 if (!mDevice.get()) return PERMISSION_DENIED;
117
118 /**
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
exclusiveUnlock()143 status_t ProCamera2Client::exclusiveUnlock() {
144 ATRACE_CALL();
145 ALOGV("%s", __FUNCTION__);
146
147 Mutex::Autolock icl(mBinderSerializationLock);
148 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
hasExclusiveLock()167 bool ProCamera2Client::hasExclusiveLock() {
168 Mutex::Autolock icl(mBinderSerializationLock);
169 return mExclusiveLock;
170 }
171
onExclusiveLockStolen()172 void ProCamera2Client::onExclusiveLockStolen() {
173 ALOGV("%s: ProClient lost exclusivity (id %d)",
174 __FUNCTION__, mCameraId);
175
176 Mutex::Autolock icl(mBinderSerializationLock);
177 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
submitRequest(camera_metadata_t * request,bool streaming)190 status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
191 bool streaming) {
192 ATRACE_CALL();
193 ALOGV("%s", __FUNCTION__);
194
195 Mutex::Autolock icl(mBinderSerializationLock);
196
197 if (!mDevice.get()) return DEAD_OBJECT;
198
199 if (!mExclusiveLock) {
200 return PERMISSION_DENIED;
201 }
202
203 CameraMetadata metadata(request);
204
205 if (!enforceRequestPermissions(metadata)) {
206 return PERMISSION_DENIED;
207 }
208
209 if (streaming) {
210 return mDevice->setStreamingRequest(metadata);
211 } else {
212 return mDevice->capture(metadata);
213 }
214
215 // unreachable. thx gcc for a useless warning
216 return OK;
217 }
218
cancelRequest(int requestId)219 status_t ProCamera2Client::cancelRequest(int requestId) {
220 (void)requestId;
221 ATRACE_CALL();
222 ALOGV("%s", __FUNCTION__);
223
224 Mutex::Autolock icl(mBinderSerializationLock);
225
226 if (!mDevice.get()) return DEAD_OBJECT;
227
228 if (!mExclusiveLock) {
229 return PERMISSION_DENIED;
230 }
231
232 // TODO: implement
233 ALOGE("%s: not fully implemented yet", __FUNCTION__);
234 return INVALID_OPERATION;
235 }
236
deleteStream(int streamId)237 status_t ProCamera2Client::deleteStream(int streamId) {
238 ATRACE_CALL();
239 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
240
241 status_t res;
242 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
243
244 Mutex::Autolock icl(mBinderSerializationLock);
245
246 if (!mDevice.get()) return DEAD_OBJECT;
247 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
254 return mDevice->deleteStream(streamId);
255 }
256
createStream(int width,int height,int format,const sp<IGraphicBufferProducer> & bufferProducer,int * streamId)257 status_t ProCamera2Client::createStream(int width, int height, int format,
258 const sp<IGraphicBufferProducer>& bufferProducer,
259 /*out*/
260 int* streamId)
261 {
262 if (streamId) {
263 *streamId = -1;
264 }
265
266 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
272 Mutex::Autolock icl(mBinderSerializationLock);
273
274 if (!mDevice.get()) return DEAD_OBJECT;
275
276 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,
284 streamId);
285 }
286
287 // Create a request object from a template.
288 // -- Caller owns the newly allocated metadata
createDefaultRequest(int templateId,camera_metadata ** request)289 status_t ProCamera2Client::createDefaultRequest(int templateId,
290 /*out*/
291 camera_metadata** request)
292 {
293 ATRACE_CALL();
294 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
295
296 if (request) {
297 *request = NULL;
298 }
299
300 status_t res;
301 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
302
303 Mutex::Autolock icl(mBinderSerializationLock);
304
305 if (!mDevice.get()) return DEAD_OBJECT;
306
307 CameraMetadata metadata;
308 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
309 *request = metadata.release();
310 }
311
312 return res;
313 }
314
getCameraInfo(int cameraId,camera_metadata ** info)315 status_t ProCamera2Client::getCameraInfo(int cameraId,
316 /*out*/
317 camera_metadata** info)
318 {
319 if (cameraId != mCameraId) {
320 return INVALID_OPERATION;
321 }
322
323 Mutex::Autolock icl(mBinderSerializationLock);
324
325 if (!mDevice.get()) return DEAD_OBJECT;
326
327 CameraMetadata deviceInfo = mDevice->info();
328 *info = deviceInfo.release();
329
330 return OK;
331 }
332
dump(int fd,const Vector<String16> & args)333 status_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:\n");
340 write(fd, result.string(), result.size());
341
342 // TODO: print dynamic/request section from most recent requests
343 mFrameProcessor->dump(fd, args);
344 return dumpDevice(fd, args);
345 }
346
347 // IProCameraUser interface
348
detachDevice()349 void ProCamera2Client::detachDevice() {
350 if (mDevice == 0) return;
351
352 ALOGV("Camera %d: Stopping processors", mCameraId);
353
354 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
355 FRAME_PROCESSOR_LISTENER_MAX_ID,
356 /*listener*/this);
357 mFrameProcessor->requestExit();
358 ALOGV("Camera %d: Waiting for threads", mCameraId);
359 mFrameProcessor->join();
360 ALOGV("Camera %d: Disconnecting device", mCameraId);
361
362 // 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
373 Camera2ClientBase::detachDevice();
374 }
375
onResultAvailable(const CaptureResult & result)376 void ProCamera2Client::onResultAvailable(const CaptureResult& result) {
377 ATRACE_CALL();
378 ALOGV("%s", __FUNCTION__);
379
380 Mutex::Autolock icl(mBinderSerializationLock);
381 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
382
383 if (mRemoteCallback != NULL) {
384 CameraMetadata tmp(result.mMetadata);
385 camera_metadata_t* meta = tmp.release();
386 ALOGV("%s: meta = %p ", __FUNCTION__, meta);
387 mRemoteCallback->onResultReceived(result.mResultExtras.requestId, meta);
388 tmp.acquire(meta);
389 }
390 }
391
enforceRequestPermissions(CameraMetadata & metadata)392 bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {
393
394 const int pid = IPCThreadState::self()->getCallingPid();
395 const int selfPid = getpid();
396 camera_metadata_entry_t entry;
397
398 /**
399 * Mixin default important security values
400 * - android.led.transmit = defaulted ON
401 */
402 CameraMetadata staticInfo = mDevice->info();
403 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
404 for(size_t i = 0; i < entry.count; ++i) {
405 uint8_t led = entry.data.u8[i];
406
407 switch(led) {
408 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
409 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
410 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
411 metadata.update(ANDROID_LED_TRANSMIT,
412 &transmitDefault, 1);
413 }
414 break;
415 }
416 }
417 }
418
419 // We can do anything!
420 if (pid == selfPid) {
421 return true;
422 }
423
424 /**
425 * Permission check special fields in the request
426 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
427 */
428 entry = metadata.find(ANDROID_LED_TRANSMIT);
429 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
430 String16 permissionString =
431 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
432 if (!checkCallingPermission(permissionString)) {
433 const int uid = IPCThreadState::self()->getCallingUid();
434 ALOGE("Permission Denial: "
435 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
436 return false;
437 }
438 }
439
440 return true;
441 }
442
443 } // namespace android
444