blob: 0c6f8afcfa134300ea84cb0825dcc6398d88f4dd [file] [log] [blame]
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -08001/*
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