blob: ed5c3baceeeae8174dd1d08d20a521c02efbdd79 [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 "ACameraManager"
19
20#include <memory>
21#include "ACameraManager.h"
22#include "ACameraMetadata.h"
23#include "ACameraDevice.h"
24#include <utils/Vector.h>
25#include <stdlib.h>
26#include <camera/VendorTagDescriptor.h>
27
28using namespace android;
29
30//constants shared between ACameraManager and CameraManagerGlobal
31namespace {
32 const int kMaxCameraIdLen = 32;
33}
34
35namespace android {
36// Static member definitions
37const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
38const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
39const char* CameraManagerGlobal::kContextKey = "CallbackContext";
40Mutex CameraManagerGlobal::sLock;
41CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
42
43CameraManagerGlobal&
44CameraManagerGlobal::getInstance() {
45 Mutex::Autolock _l(sLock);
46 CameraManagerGlobal* instance = sInstance;
47 if (instance == nullptr) {
48 instance = new CameraManagerGlobal();
49 sInstance = instance;
50 }
51 return *instance;
52}
53
54CameraManagerGlobal::~CameraManagerGlobal() {
55 // clear sInstance so next getInstance call knows to create a new one
56 Mutex::Autolock _sl(sLock);
57 sInstance = nullptr;
58 Mutex::Autolock _l(mLock);
59 if (mCameraService != nullptr) {
60 IInterface::asBinder(mCameraService)->unlinkToDeath(mDeathNotifier);
Yin-Chia Yehead91462016-01-06 16:45:08 -080061 mCameraService->removeListener(mCameraServiceListener);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080062 }
63 mDeathNotifier.clear();
64 if (mCbLooper != nullptr) {
65 mCbLooper->unregisterHandler(mHandler->id());
66 mCbLooper->stop();
67 }
68 mCbLooper.clear();
69 mHandler.clear();
70 mCameraServiceListener.clear();
71 mCameraService.clear();
72}
73
74sp<ICameraService> CameraManagerGlobal::getCameraService() {
75 Mutex::Autolock _l(mLock);
76 if (mCameraService.get() == nullptr) {
77 sp<IServiceManager> sm = defaultServiceManager();
78 sp<IBinder> binder;
79 do {
80 binder = sm->getService(String16(kCameraServiceName));
81 if (binder != nullptr) {
82 break;
83 }
84 ALOGW("CameraService not published, waiting...");
85 usleep(kCameraServicePollDelay);
86 } while(true);
87 if (mDeathNotifier == nullptr) {
88 mDeathNotifier = new DeathNotifier(this);
89 }
90 binder->linkToDeath(mDeathNotifier);
91 mCameraService = interface_cast<ICameraService>(binder);
92
93 // Setup looper thread to perfrom availiability callbacks
94 if (mCbLooper == nullptr) {
95 mCbLooper = new ALooper;
96 mCbLooper->setName("C2N-mgr-looper");
97 status_t ret = mCbLooper->start(
98 /*runOnCallingThread*/false,
99 /*canCallJava*/ true,
Yin-Chia Yehead91462016-01-06 16:45:08 -0800100 PRIORITY_DEFAULT);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800101 if (mHandler == nullptr) {
102 mHandler = new CallbackHandler();
103 }
104 mCbLooper->registerHandler(mHandler);
105 }
106
107 // register ICameraServiceListener
108 if (mCameraServiceListener == nullptr) {
109 mCameraServiceListener = new CameraServiceListener(this);
110 }
111 mCameraService->addListener(mCameraServiceListener);
112
113 // setup vendor tags
114 sp<VendorTagDescriptor> desc;
115 status_t ret = mCameraService->getCameraVendorTagDescriptor(/*out*/desc);
116
117 if (ret == OK) {
118 ret = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
119 if (ret != OK) {
120 ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
121 __FUNCTION__, strerror(-ret), ret);
122 }
123 } else if (ret == -EOPNOTSUPP) {
124 ALOGW("%s: Camera HAL too old; does not support vendor tags",
125 __FUNCTION__);
126 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
127 } else {
128 ALOGE("%s: Failed to get vendor tag descriptors, received error %s (%d)",
129 __FUNCTION__, strerror(-ret), ret);
130 }
131 }
132 ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
133 return mCameraService;
134}
135
136void CameraManagerGlobal::DeathNotifier::binderDied(const wp<IBinder>&)
137{
138 ALOGE("Camera service binderDied!");
139 sp<CameraManagerGlobal> cm = mCameraManager.promote();
140 if (cm != nullptr) {
141 AutoMutex lock(cm->mLock);
142 for (auto pair : cm->mDeviceStatusMap) {
143 int32_t cameraId = pair.first;
144 cm->onStatusChangedLocked(
145 ICameraServiceListener::STATUS_NOT_PRESENT, cameraId);
146 }
147 cm->mCameraService.clear();
148 // TODO: consider adding re-connect call here?
149 }
150}
151
152void CameraManagerGlobal::registerAvailabilityCallback(
153 const ACameraManager_AvailabilityCallbacks *callback) {
154 Mutex::Autolock _l(mLock);
155 Callback cb(callback);
156 auto pair = mCallbacks.insert(cb);
157 // Send initial callbacks if callback is newly registered
158 if (pair.second) {
159 for (auto pair : mDeviceStatusMap) {
160 int32_t cameraId = pair.first;
161 Status status = pair.second;
162
163 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
164 ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
165 callback->onCameraAvailable : callback->onCameraUnavailable;
166 msg->setPointer(kCallbackFpKey, (void *) cb);
167 msg->setPointer(kContextKey, callback->context);
168 msg->setInt32(kCameraIdKey, cameraId);
169 msg->post();
170 }
171 }
172}
173
174void CameraManagerGlobal::unregisterAvailabilityCallback(
175 const ACameraManager_AvailabilityCallbacks *callback) {
176 Mutex::Autolock _l(mLock);
177 Callback cb(callback);
178 mCallbacks.erase(cb);
179}
180
181bool CameraManagerGlobal::validStatus(Status status) {
182 switch (status) {
183 case ICameraServiceListener::STATUS_NOT_PRESENT:
184 case ICameraServiceListener::STATUS_PRESENT:
185 case ICameraServiceListener::STATUS_ENUMERATING:
186 case ICameraServiceListener::STATUS_NOT_AVAILABLE:
187 return true;
188 default:
189 return false;
190 }
191}
192
193bool CameraManagerGlobal::isStatusAvailable(Status status) {
194 switch (status) {
195 case ICameraServiceListener::STATUS_PRESENT:
196 return true;
197 default:
198 return false;
199 }
200}
201
202void CameraManagerGlobal::CallbackHandler::sendSingleCallback(
203 int32_t cameraId, void* context,
204 ACameraManager_AvailabilityCallback cb) const {
205 char cameraIdStr[kMaxCameraIdLen];
206 snprintf(cameraIdStr, sizeof(cameraIdStr), "%d", cameraId);
207 (*cb)(context, cameraIdStr);
208}
209
210void CameraManagerGlobal::CallbackHandler::onMessageReceived(
211 const sp<AMessage> &msg) {
212 switch (msg->what()) {
213 case kWhatSendSingleCallback:
214 {
215 ACameraManager_AvailabilityCallback cb;
216 void* context;
217 int32_t cameraId;
218 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
219 if (!found) {
220 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
221 return;
222 }
223 found = msg->findPointer(kContextKey, &context);
224 if (!found) {
225 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
226 return;
227 }
228 found = msg->findInt32(kCameraIdKey, &cameraId);
229 if (!found) {
230 ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
231 return;
232 }
233 sendSingleCallback(cameraId, context, cb);
234 break;
235 }
236 default:
237 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
238 break;
239 }
240}
241
242void CameraManagerGlobal::CameraServiceListener::onStatusChanged(
243 Status status, int32_t cameraId) {
244 sp<CameraManagerGlobal> cm = mCameraManager.promote();
245 if (cm == nullptr) {
Yin-Chia Yehead91462016-01-06 16:45:08 -0800246 ALOGE("Cannot deliver status change. Global camera manager died");
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800247 return;
248 }
249 cm->onStatusChanged(status, cameraId);
250}
251
252void CameraManagerGlobal::onStatusChanged(
253 Status status, int32_t cameraId) {
254 Mutex::Autolock _l(mLock);
255 onStatusChangedLocked(status, cameraId);
256}
257
258void CameraManagerGlobal::onStatusChangedLocked(
259 Status status, int32_t cameraId) {
260 if (!validStatus(status)) {
261 ALOGE("%s: Invalid status %d", __FUNCTION__, status);
262 return;
263 }
264
265 bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
266 Status oldStatus = firstStatus ?
267 status : // first status
268 mDeviceStatusMap[cameraId];
269
270 if (!firstStatus &&
271 isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
272 // No status update. No need to send callback
273 return;
274 }
275
276 // Iterate through all registered callbacks
277 mDeviceStatusMap[cameraId] = status;
278 for (auto cb : mCallbacks) {
279 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
280 ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
281 cb.mAvailable : cb.mUnavailable;
282 msg->setPointer(kCallbackFpKey, (void *) cbFp);
283 msg->setPointer(kContextKey, cb.mContext);
284 msg->setInt32(kCameraIdKey, cameraId);
285 msg->post();
286 }
287}
288
289} // namespace android
290
291/**
292 * ACameraManger Implementation
293 */
294camera_status_t
295ACameraManager::getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList) {
296 if (mCachedCameraIdList.numCameras == kCameraIdListNotInit) {
297 int numCameras = 0;
298 Vector<char *> cameraIds;
299 sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
300 if (cs == nullptr) {
301 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
302 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
303 }
304 // Get number of cameras
305 int numAllCameras = cs->getNumberOfCameras(ICameraService::CAMERA_TYPE_ALL);
306 // Filter API2 compatible cameras and push to cameraIds
307 for (int i = 0; i < numAllCameras; i++) {
308 // TODO: Only suppot HALs that supports API2 directly now
309 status_t camera2Support = cs->supportsCameraApi(i, ICameraService::API_VERSION_2);
310 char buf[kMaxCameraIdLen];
311 if (camera2Support == OK) {
312 numCameras++;
313 mCameraIds.insert(i);
314 snprintf(buf, sizeof(buf), "%d", i);
315 size_t cameraIdSize = strlen(buf) + 1;
316 char *cameraId = new char[cameraIdSize];
317 if (!cameraId) {
318 ALOGE("Allocate memory for ACameraIdList failed!");
319 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
320 }
321 strlcpy(cameraId, buf, cameraIdSize);
322 cameraIds.push(cameraId);
323 }
324 }
325 mCachedCameraIdList.numCameras = numCameras;
326 mCachedCameraIdList.cameraIds = new const char*[numCameras];
327 if (!mCachedCameraIdList.cameraIds) {
328 ALOGE("Allocate memory for ACameraIdList failed!");
329 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
330 }
331 for (int i = 0; i < numCameras; i++) {
332 mCachedCameraIdList.cameraIds[i] = cameraIds[i];
333 }
334 }
335 *cameraIdList = &mCachedCameraIdList;
336 return ACAMERA_OK;
337}
338
339camera_status_t
340ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
341 Mutex::Autolock _l(mLock);
342 ACameraIdList* cachedList;
343 camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
344 if (ret != ACAMERA_OK) {
345 ALOGE("Get camera ID list failed! err: %d", ret);
346 return ret;
347 }
348
349 int numCameras = cachedList->numCameras;
350 ACameraIdList *out = new ACameraIdList;
351 if (!out) {
352 ALOGE("Allocate memory for ACameraIdList failed!");
353 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
354 }
355 out->numCameras = numCameras;
356 out->cameraIds = new const char*[numCameras];
357 if (!out->cameraIds) {
358 ALOGE("Allocate memory for ACameraIdList failed!");
359 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
360 }
361 for (int i = 0; i < numCameras; i++) {
362 const char* src = cachedList->cameraIds[i];
363 size_t dstSize = strlen(src) + 1;
364 char* dst = new char[dstSize];
365 if (!dst) {
366 ALOGE("Allocate memory for ACameraIdList failed!");
367 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
368 }
369 strlcpy(dst, src, dstSize);
370 out->cameraIds[i] = dst;
371 }
372 *cameraIdList = out;
373 return ACAMERA_OK;
374}
375
376void
377ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
378 if (cameraIdList != nullptr) {
379 if (cameraIdList->cameraIds != nullptr) {
380 for (int i = 0; i < cameraIdList->numCameras; i ++) {
381 delete[] cameraIdList->cameraIds[i];
382 }
383 delete[] cameraIdList->cameraIds;
384 }
385 delete cameraIdList;
386 }
387}
388
389camera_status_t ACameraManager::getCameraCharacteristics(
390 const char *cameraIdStr, ACameraMetadata **characteristics) {
391 Mutex::Autolock _l(mLock);
392 ACameraIdList* cachedList;
393 // Make sure mCameraIds is initialized
394 camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
395 if (ret != ACAMERA_OK) {
396 ALOGE("%s: Get camera ID list failed! err: %d", __FUNCTION__, ret);
397 return ret;
398 }
399 int cameraId = atoi(cameraIdStr);
400 if (mCameraIds.count(cameraId) == 0) {
401 ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
402 return ACAMERA_ERROR_INVALID_PARAMETER;
403 }
404 sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
405 if (cs == nullptr) {
406 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
407 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
408 }
409 CameraMetadata rawMetadata;
410 status_t serviceRet = cs->getCameraCharacteristics(cameraId, &rawMetadata);
411 if (serviceRet != OK) {
412 ALOGE("Get camera characteristics from camera service failed! Err %d", ret);
413 return ACAMERA_ERROR_UNKNOWN; // should not reach here
414 }
415
416 *characteristics = new ACameraMetadata(
417 rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
418 return ACAMERA_OK;
419}
420
421camera_status_t
422ACameraManager::openCamera(
423 const char* cameraId,
424 ACameraDevice_StateCallbacks* callback,
425 /*out*/ACameraDevice** outDevice) {
426 ACameraMetadata* rawChars;
427 camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
428 Mutex::Autolock _l(mLock);
429 if (ret != ACAMERA_OK) {
430 ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
431 __FUNCTION__, cameraId, ret);
432 return ACAMERA_ERROR_INVALID_PARAMETER;
433 }
434 std::unique_ptr<ACameraMetadata> chars(rawChars);
435 rawChars = nullptr;
436
437 ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(chars));
438
439 sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
440 if (cs == nullptr) {
441 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
442 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
443 }
444
445 int id = atoi(cameraId);
446 sp<ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
447 sp<ICameraDeviceUser> deviceRemote;
448 // No way to get package name from native.
449 // Send a zero length package name and let camera service figure it out from UID
450 status_t serviceRet = cs->connectDevice(
451 callbacks, id, String16(""),
452 ICameraService::USE_CALLING_UID, /*out*/deviceRemote);
453
454 if (serviceRet != OK) {
455 ALOGE("%s: connect camera device failed! err %d", __FUNCTION__, serviceRet);
456 // TODO: generate better error message here
457 delete device;
458 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
459 }
460 if (deviceRemote == nullptr) {
461 ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
462 delete device;
463 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
464 }
465 device->setRemoteDevice(deviceRemote);
466 *outDevice = device;
467 return ACAMERA_OK;
468}
469
470ACameraManager::~ACameraManager() {
471 Mutex::Autolock _l(mLock);
472 if (mCachedCameraIdList.numCameras != kCameraIdListNotInit) {
473 for (int i = 0; i < mCachedCameraIdList.numCameras; i++) {
474 delete[] mCachedCameraIdList.cameraIds[i];
475 }
476 delete[] mCachedCameraIdList.cameraIds;
477 }
478}
479