ACameraDevice.cpp revision 0dea57fd9fc4b2ccaab97d9477359fbd5a626f5c
1/*
2 * Copyright (C) 2015 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_NDEBUG 0
18#define LOG_TAG "ACameraDevice"
19
20#include <inttypes.h>
21#include "ACameraDevice.h"
22#include "ACameraMetadata.h"
23#include "ACaptureRequest.h"
24
25using namespace android;
26
27namespace android {
28// Static member definitions
29const char* CameraDevice::kContextKey   = "Context";
30const char* CameraDevice::kDeviceKey    = "Device";
31const char* CameraDevice::kErrorCodeKey = "ErrorCode";
32const char* CameraDevice::kCallbackKey  = "Callback";
33
34/**
35 * CameraDevice Implementation
36 */
37CameraDevice::CameraDevice(
38        const char* id,
39        ACameraDevice_StateCallbacks* cb,
40        std::unique_ptr<ACameraMetadata> chars,
41        ACameraDevice* wrapper) :
42        mCameraId(id),
43        mAppCallbacks(*cb),
44        mChars(std::move(chars)),
45        mServiceCallback(new ServiceCallback(this)),
46        mWrapper(wrapper),
47        mInError(false),
48        mError(ACAMERA_OK),
49        mIdle(true) {
50    mClosing = false;
51    // Setup looper thread to perfrom device callbacks to app
52    mCbLooper = new ALooper;
53    mCbLooper->setName("C2N-dev-looper");
54    status_t ret = mCbLooper->start(
55            /*runOnCallingThread*/false,
56            /*canCallJava*/       true,
57            PRIORITY_FOREGROUND);
58    mHandler = new CallbackHandler();
59    mCbLooper->registerHandler(mHandler);
60}
61
62CameraDevice::~CameraDevice() {
63    Mutex::Autolock _l(mDeviceLock);
64    if (mCbLooper != nullptr) {
65        mCbLooper->unregisterHandler(mHandler->id());
66        mCbLooper->stop();
67    }
68    mCbLooper.clear();
69    mHandler.clear();
70    if (!isClosed()) {
71        disconnectLocked();
72    }
73}
74
75// TODO: cached created request?
76camera_status_t
77CameraDevice::createCaptureRequest(
78        ACameraDevice_request_template templateId,
79        ACaptureRequest** request) const {
80    Mutex::Autolock _l(mDeviceLock);
81    camera_status_t ret = checkCameraClosedOrErrorLocked();
82    if (ret != ACAMERA_OK) {
83        return ret;
84    }
85    if (mRemote == nullptr) {
86        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
87    }
88    CameraMetadata rawRequest;
89    status_t remoteRet = mRemote->createDefaultRequest(templateId, &rawRequest);
90    if (remoteRet == BAD_VALUE) {
91        ALOGW("Create capture request failed! template %d is not supported on this device",
92            templateId);
93        return ACAMERA_ERROR_UNSUPPORTED;
94    } else if (remoteRet != OK) {
95        ALOGE("Create capture request failed! error %d", remoteRet);
96        return ACAMERA_ERROR_UNKNOWN;
97    }
98    ACaptureRequest* outReq = new ACaptureRequest();
99    outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
100    outReq->targets  = new ACameraOutputTargets();
101    *request = outReq;
102    return ACAMERA_OK;
103}
104
105void
106CameraDevice::disconnectLocked() {
107    if (mClosing.exchange(true)) {
108        // Already closing, just return
109        ALOGW("Camera device %s is already closing.", getId());
110        return;
111    }
112
113    if (mRemote != nullptr) {
114        mRemote->disconnect();
115    }
116    mRemote = nullptr;
117}
118
119void
120CameraDevice::setRemoteDevice(sp<ICameraDeviceUser> remote) {
121    Mutex::Autolock _l(mDeviceLock);
122    mRemote = remote;
123}
124
125camera_status_t
126CameraDevice::checkCameraClosedOrErrorLocked() const {
127    if (mRemote == nullptr) {
128        ALOGE("%s: camera device already closed", __FUNCTION__);
129        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
130    }
131    if (mInError) {// triggered by onDeviceError
132        ALOGE("%s: camera device has encountered a serious error", __FUNCTION__);
133        return mError;
134    }
135    return ACAMERA_OK;
136}
137
138void
139CameraDevice::onCaptureErrorLocked(
140        ICameraDeviceCallbacks::CameraErrorCode errorCode,
141        const CaptureResultExtras& resultExtras) {
142    // TODO: implement!
143}
144
145void CameraDevice::CallbackHandler::onMessageReceived(
146        const sp<AMessage> &msg) {
147    switch (msg->what()) {
148        case kWhatOnDisconnected:
149        case kWhatOnError:
150            break;
151        default:
152            ALOGE("%s:Error: unknown device callback %d", __FUNCTION__, msg->what());
153            return;
154    }
155    // Check the common part of all message
156    void* context;
157    bool found = msg->findPointer(kContextKey, &context);
158    if (!found) {
159        ALOGE("%s: Cannot find callback context!", __FUNCTION__);
160        return;
161    }
162    ACameraDevice* dev;
163    found = msg->findPointer(kDeviceKey, (void**) &dev);
164    if (!found) {
165        ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
166        return;
167    }
168    switch (msg->what()) {
169        case kWhatOnDisconnected:
170        {
171            ACameraDevice_StateCallback onDisconnected;
172            found = msg->findPointer(kCallbackKey, (void**) &onDisconnected);
173            if (!found) {
174                ALOGE("%s: Cannot find onDisconnected!", __FUNCTION__);
175                return;
176            }
177            (*onDisconnected)(context, dev);
178            break;
179        }
180        case kWhatOnError:
181        {
182            ACameraDevice_ErrorStateCallback onError;
183            found = msg->findPointer(kCallbackKey, (void**) &onError);
184            if (!found) {
185                ALOGE("%s: Cannot find onError!", __FUNCTION__);
186                return;
187            }
188            int errorCode;
189            found = msg->findInt32(kErrorCodeKey, &errorCode);
190            if (!found) {
191                ALOGE("%s: Cannot find error code!", __FUNCTION__);
192                return;
193            }
194            (*onError)(context, dev, errorCode);
195        }
196    }
197}
198
199/**
200  * Camera service callback implementation
201  */
202void
203CameraDevice::ServiceCallback::onDeviceError(
204        CameraErrorCode errorCode,
205        const CaptureResultExtras& resultExtras) {
206    ALOGD("Device error received, code %d, frame number %" PRId64 ", request ID %d, subseq ID %d",
207            errorCode, resultExtras.frameNumber, resultExtras.requestId, resultExtras.burstId);
208
209    sp<CameraDevice> dev = mDevice.promote();
210    if (dev == nullptr) {
211        return; // device has been closed
212    }
213
214    Mutex::Autolock _l(dev->mDeviceLock);
215    if (dev->mRemote == nullptr) {
216        return; // device has been disconnected
217    }
218    switch (errorCode) {
219        case ERROR_CAMERA_DISCONNECTED:
220        {
221            // should be clear mRemote here?
222            // TODO: close current session
223            sp<AMessage> msg = new AMessage(kWhatOnDisconnected, dev->mHandler);
224            msg->setPointer(kContextKey, dev->mAppCallbacks.context);
225            msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
226            msg->setPointer(kCallbackKey, (void*) dev->mAppCallbacks.onDisconnected);
227            msg->post();
228            break;
229        }
230        default:
231            ALOGE("Unknown error from camera device: %d", errorCode);
232            // no break
233        case ERROR_CAMERA_DEVICE:
234        case ERROR_CAMERA_SERVICE:
235        {
236            dev->mInError = true;
237            switch (errorCode) {
238                case ERROR_CAMERA_DEVICE:
239                    dev->mError = ACAMERA_ERROR_CAMERA_DEVICE;
240                    break;
241                case ERROR_CAMERA_SERVICE:
242                    dev->mError = ACAMERA_ERROR_CAMERA_SERVICE;
243                    break;
244                default:
245                    dev->mError = ACAMERA_ERROR_UNKNOWN;
246                    break;
247            }
248            sp<AMessage> msg = new AMessage(kWhatOnError, dev->mHandler);
249            msg->setPointer(kContextKey, dev->mAppCallbacks.context);
250            msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
251            msg->setPointer(kCallbackKey, (void*) dev->mAppCallbacks.onError);
252            msg->setInt32(kErrorCodeKey, errorCode);
253            msg->post();
254            break;
255        }
256        case ERROR_CAMERA_REQUEST:
257        case ERROR_CAMERA_RESULT:
258        case ERROR_CAMERA_BUFFER:
259            dev->onCaptureErrorLocked(errorCode, resultExtras);
260            break;
261    }
262}
263
264void
265CameraDevice::ServiceCallback::onDeviceIdle() {
266    ALOGV("Camera is now idle");
267    sp<CameraDevice> dev = mDevice.promote();
268    if (dev == nullptr) {
269        return; // device has been closed
270    }
271
272    Mutex::Autolock _l(dev->mDeviceLock);
273    if (dev->mRemote == nullptr) {
274        return; // device has been disconnected
275    }
276    if (!dev->mIdle) {
277        // TODO: send idle callback to current session
278    }
279    dev->mIdle = true;
280}
281
282void
283CameraDevice::ServiceCallback::onCaptureStarted(
284        const CaptureResultExtras& resultExtras,
285        int64_t timestamp) {
286}
287
288void
289CameraDevice::ServiceCallback::onResultReceived(
290        const CameraMetadata& metadata,
291        const CaptureResultExtras& resultExtras) {
292}
293
294void
295CameraDevice::ServiceCallback::onPrepared(int) {
296    // Prepare not yet implemented in NDK
297    return;
298}
299
300} // namespace android
301