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