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
31namespace android {
32using namespace camera2;
33
34// Interface used by CameraService
35
36ProCamera2Client::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
53status_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
75ProCamera2Client::~ProCamera2Client() {
76}
77
78status_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
109status_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
143status_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
167bool ProCamera2Client::hasExclusiveLock() {
168    Mutex::Autolock icl(mBinderSerializationLock);
169    return mExclusiveLock;
170}
171
172void 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
190status_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
219status_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
237status_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
257status_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
289status_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
315status_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
333status_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
349void 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
376void 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
392bool 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