ProCamera2Client.cpp revision 7b82efe7a376c882f8f938e1c41b8311a8cdda4a
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2013 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
17edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#define LOG_TAG "ProCamera2Client"
18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#define ATRACE_TAG ATRACE_TAG_CAMERA
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project//#define LOG_NDEBUG 0
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h>
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Trace.h>
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <cutils/properties.h>
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <gui/Surface.h>
26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <gui/Surface.h>
27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "api_pro/ProCamera2Client.h"
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "common/CameraDeviceBase.h"
30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
31edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace android {
32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectusing namespace camera2;
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// Interface used by CameraService
35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                   const sp<IProCameraCallbacks>& remoteCallback,
38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                   const String16& clientPackageName,
39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                   int cameraId,
40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                   int cameraFacing,
41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                   int clientPid,
42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                   uid_t clientUid,
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                   int servicePid) :
4420f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
4520f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian                cameraId, cameraFacing, clientPid, clientUid, servicePid)
46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
4717b2ad027b4b72b96dfb663c0ea001972da7ef58Mathias Agopian    ATRACE_CALL();
4817b2ad027b4b72b96dfb663c0ea001972da7ef58Mathias Agopian    ALOGI("ProCamera %d: Opened", cameraId);
49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
509f96145725ff3f265712d607d19078fb91a5c8ecMathias Agopian    mExclusiveLock = false;
519f96145725ff3f265712d607d19078fb91a5c8ecMathias Agopian}
529f96145725ff3f265712d607d19078fb91a5c8ecMathias Agopian
53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t ProCamera2Client::initialize(camera_module_t *module)
54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
550926f50664c739eaee60341f8e8c694dc9a4f3ebMathias Agopian    ATRACE_CALL();
56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t res;
57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
58b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy    res = Camera2ClientBase::initialize(module);
59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (res != OK) {
6020f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian        return res;
61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    String8 threadName;
64b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy    mFrameProcessor = new FrameProcessorBase(mDevice);
65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    threadName = String8::format("PC2-%d-FrameProc", mCameraId);
66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mFrameProcessor->run(threadName.string());
67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
6820f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
69bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
70b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy                                      /*listener*/this);
71bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
72bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian    return OK;
73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
75bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias AgopianProCamera2Client::~ProCamera2Client() {
76b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy}
77bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
78bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopianstatus_t ProCamera2Client::exclusiveTryLock() {
79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ATRACE_CALL();
80edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ALOGV("%s", __FUNCTION__);
8120f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
8220f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    Mutex::Autolock icl(mBinderSerializationLock);
83b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
8420f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
8520f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    if (!mDevice.get()) return PERMISSION_DENIED;
8620f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
8720f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    if (!mExclusiveLock) {
88bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian        mExclusiveLock = true;
89bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
90b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy        if (mRemoteCallback != NULL) {
91bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian            mRemoteCallback->onLockStatusChanged(
92bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian                              IProCameraCallbacks::LOCK_ACQUIRED);
93edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
95bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian        ALOGV("%s: exclusive lock acquired", __FUNCTION__);
96b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy
97bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian        return OK;
98bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian    }
99bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
102b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy    // don't allow recursive locking
103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ALOGW("%s: exclusive lock already exists - recursive locking is not"
104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project          "allowed", __FUNCTION__);
105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return ALREADY_EXISTS;
10720f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian}
10820f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
10920f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopianstatus_t ProCamera2Client::exclusiveLock() {
11020f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    ATRACE_CALL();
11120f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    ALOGV("%s", __FUNCTION__);
11220f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
11320f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    Mutex::Autolock icl(mBinderSerializationLock);
11420f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
11520f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
11620f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    if (!mDevice.get()) return PERMISSION_DENIED;
11720f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
11820f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    /**
119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project     * TODO: this should asynchronously 'wait' until the lock becomes available
12020f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian     * if another client already has an exclusive lock.
12120f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian     *
12220f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian     * once we have proper sharing support this will need to do
12320f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian     * more than just return immediately
124edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project     */
125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (!mExclusiveLock) {
126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mExclusiveLock = true;
127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (mRemoteCallback != NULL) {
129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        ALOGV("%s: exclusive lock acquired", __FUNCTION__);
133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return OK;
135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
13620f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
13720f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    // don't allow recursive locking
13820f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
13920f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian                                                                , __FUNCTION__);
14020f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    return ALREADY_EXISTS;
14120f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian}
142bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
143bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopianstatus_t ProCamera2Client::exclusiveUnlock() {
144bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian    ATRACE_CALL();
14520f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    ALOGV("%s", __FUNCTION__);
14620f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
14720f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    Mutex::Autolock icl(mBinderSerializationLock);
14820f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
14920f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
15020f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    // don't allow unlocking if we have no lock
15120f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    if (!mExclusiveLock) {
15220f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian        ALOGW("%s: cannot unlock, no lock was held in the first place",
15320f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian              __FUNCTION__);
15420f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian        return BAD_VALUE;
15520f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    }
15620f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian
15720f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    mExclusiveLock = false;
15820f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    if (mRemoteCallback != NULL ) {
15920f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian        mRemoteCallback->onLockStatusChanged(
16020f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian                                       IProCameraCallbacks::LOCK_RELEASED);
16120f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    }
16220f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian    ALOGV("%s: exclusive lock released", __FUNCTION__);
163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return OK;
165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
166bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectbool ProCamera2Client::hasExclusiveLock() {
168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock icl(mBinderSerializationLock);
169b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy    return mExclusiveLock;
170b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy}
171b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy
172bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopianvoid ProCamera2Client::onExclusiveLockStolen() {
173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ALOGV("%s: ProClient lost exclusivity (id %d)",
174edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project          __FUNCTION__, mCameraId);
175bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock icl(mBinderSerializationLock);
177edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
178bed9dd128dfbdc7d9dbca005078536dadc0b9359Mathias Agopian
179edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (mExclusiveLock && mRemoteCallback.get() != NULL) {
180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mRemoteCallback->onLockStatusChanged(
181edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                       IProCameraCallbacks::LOCK_STOLEN);
182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mExclusiveLock = false;
185edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
186b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy    //TODO: we should not need to detach the device, merely reset it.
187b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy    detachDevice();
188b8a2e98cd7edbe7513543670c94f6b5efa74462fRomain Guy}
189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t ProCamera2Client::submitRequest(camera_metadata_t* request,
191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                                         bool streaming) {
192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ATRACE_CALL();
193edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ALOGV("%s", __FUNCTION__);
194edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
195edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock icl(mBinderSerializationLock);
196edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
197edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (!mDevice.get()) return DEAD_OBJECT;
198edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
199edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (!mExclusiveLock) {
200edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return PERMISSION_DENIED;
201edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
202edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
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, /*size*/1,
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: ");
340
341    // TODO: print dynamic/request section from most recent requests
342    mFrameProcessor->dump(fd, args);
343
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
376/** Device-related methods */
377void ProCamera2Client::onFrameAvailable(int32_t frameId,
378                                        const CameraMetadata& frame) {
379    ATRACE_CALL();
380    ALOGV("%s", __FUNCTION__);
381
382    Mutex::Autolock icl(mBinderSerializationLock);
383    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
395bool 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
446} // namespace android
447