blob: 24d5282df13bfd4746522ce033b1ca74f3bb739d [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
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080074sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080075 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);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080091 mCameraService = interface_cast<hardware::ICameraService>(binder);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080092
93 // Setup looper thread to perfrom availiability callbacks
94 if (mCbLooper == nullptr) {
95 mCbLooper = new ALooper;
96 mCbLooper->setName("C2N-mgr-looper");
Eino-Ville Talvala02bf0322016-02-18 12:41:10 -080097 status_t err = mCbLooper->start(
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080098 /*runOnCallingThread*/false,
99 /*canCallJava*/ true,
Yin-Chia Yehead91462016-01-06 16:45:08 -0800100 PRIORITY_DEFAULT);
Eino-Ville Talvala02bf0322016-02-18 12:41:10 -0800101 if (err != OK) {
102 ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
103 __FUNCTION__, strerror(-err), err);
104 mCbLooper.clear();
105 return nullptr;
106 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800107 if (mHandler == nullptr) {
108 mHandler = new CallbackHandler();
109 }
110 mCbLooper->registerHandler(mHandler);
111 }
112
113 // register ICameraServiceListener
114 if (mCameraServiceListener == nullptr) {
115 mCameraServiceListener = new CameraServiceListener(this);
116 }
117 mCameraService->addListener(mCameraServiceListener);
118
119 // setup vendor tags
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800120 sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
121 binder::Status ret = mCameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800122
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800123 if (ret.isOk()) {
124 status_t err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
125 if (err != OK) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800126 ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800127 __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800128 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800129 } else if (ret.serviceSpecificErrorCode() ==
130 hardware::ICameraService::ERROR_DEPRECATED_HAL) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800131 ALOGW("%s: Camera HAL too old; does not support vendor tags",
132 __FUNCTION__);
133 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
134 } else {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800135 ALOGE("%s: Failed to get vendor tag descriptors: %s",
136 __FUNCTION__, ret.toString8().string());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800137 }
138 }
139 ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
140 return mCameraService;
141}
142
143void CameraManagerGlobal::DeathNotifier::binderDied(const wp<IBinder>&)
144{
145 ALOGE("Camera service binderDied!");
146 sp<CameraManagerGlobal> cm = mCameraManager.promote();
147 if (cm != nullptr) {
148 AutoMutex lock(cm->mLock);
149 for (auto pair : cm->mDeviceStatusMap) {
150 int32_t cameraId = pair.first;
151 cm->onStatusChangedLocked(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800152 CameraServiceListener::STATUS_NOT_PRESENT, cameraId);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800153 }
154 cm->mCameraService.clear();
155 // TODO: consider adding re-connect call here?
156 }
157}
158
159void CameraManagerGlobal::registerAvailabilityCallback(
160 const ACameraManager_AvailabilityCallbacks *callback) {
161 Mutex::Autolock _l(mLock);
162 Callback cb(callback);
163 auto pair = mCallbacks.insert(cb);
164 // Send initial callbacks if callback is newly registered
165 if (pair.second) {
166 for (auto pair : mDeviceStatusMap) {
167 int32_t cameraId = pair.first;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800168 int32_t status = pair.second;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800169
170 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
171 ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
172 callback->onCameraAvailable : callback->onCameraUnavailable;
173 msg->setPointer(kCallbackFpKey, (void *) cb);
174 msg->setPointer(kContextKey, callback->context);
175 msg->setInt32(kCameraIdKey, cameraId);
176 msg->post();
177 }
178 }
179}
180
181void CameraManagerGlobal::unregisterAvailabilityCallback(
182 const ACameraManager_AvailabilityCallbacks *callback) {
183 Mutex::Autolock _l(mLock);
184 Callback cb(callback);
185 mCallbacks.erase(cb);
186}
187
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800188bool CameraManagerGlobal::validStatus(int32_t status) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800189 switch (status) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800190 case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
191 case hardware::ICameraServiceListener::STATUS_PRESENT:
192 case hardware::ICameraServiceListener::STATUS_ENUMERATING:
193 case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800194 return true;
195 default:
196 return false;
197 }
198}
199
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800200bool CameraManagerGlobal::isStatusAvailable(int32_t status) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800201 switch (status) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800202 case hardware::ICameraServiceListener::STATUS_PRESENT:
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800203 return true;
204 default:
205 return false;
206 }
207}
208
209void CameraManagerGlobal::CallbackHandler::sendSingleCallback(
210 int32_t cameraId, void* context,
211 ACameraManager_AvailabilityCallback cb) const {
212 char cameraIdStr[kMaxCameraIdLen];
213 snprintf(cameraIdStr, sizeof(cameraIdStr), "%d", cameraId);
214 (*cb)(context, cameraIdStr);
215}
216
217void CameraManagerGlobal::CallbackHandler::onMessageReceived(
218 const sp<AMessage> &msg) {
219 switch (msg->what()) {
220 case kWhatSendSingleCallback:
221 {
222 ACameraManager_AvailabilityCallback cb;
223 void* context;
224 int32_t cameraId;
225 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
226 if (!found) {
227 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
228 return;
229 }
230 found = msg->findPointer(kContextKey, &context);
231 if (!found) {
232 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
233 return;
234 }
235 found = msg->findInt32(kCameraIdKey, &cameraId);
236 if (!found) {
237 ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
238 return;
239 }
240 sendSingleCallback(cameraId, context, cb);
241 break;
242 }
243 default:
244 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
245 break;
246 }
247}
248
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800249binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
250 int32_t status, int32_t cameraId) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800251 sp<CameraManagerGlobal> cm = mCameraManager.promote();
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800252 if (cm != nullptr) {
253 cm->onStatusChanged(status, cameraId);
254 } else {
Yin-Chia Yehead91462016-01-06 16:45:08 -0800255 ALOGE("Cannot deliver status change. Global camera manager died");
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800256 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800257 return binder::Status::ok();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800258}
259
260void CameraManagerGlobal::onStatusChanged(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800261 int32_t status, int32_t cameraId) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800262 Mutex::Autolock _l(mLock);
263 onStatusChangedLocked(status, cameraId);
264}
265
266void CameraManagerGlobal::onStatusChangedLocked(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800267 int32_t status, int32_t cameraId) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800268 if (!validStatus(status)) {
269 ALOGE("%s: Invalid status %d", __FUNCTION__, status);
270 return;
271 }
272
273 bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800274 int32_t oldStatus = firstStatus ?
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800275 status : // first status
276 mDeviceStatusMap[cameraId];
277
278 if (!firstStatus &&
279 isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
280 // No status update. No need to send callback
281 return;
282 }
283
284 // Iterate through all registered callbacks
285 mDeviceStatusMap[cameraId] = status;
286 for (auto cb : mCallbacks) {
287 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
288 ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
289 cb.mAvailable : cb.mUnavailable;
290 msg->setPointer(kCallbackFpKey, (void *) cbFp);
291 msg->setPointer(kContextKey, cb.mContext);
292 msg->setInt32(kCameraIdKey, cameraId);
293 msg->post();
294 }
295}
296
297} // namespace android
298
299/**
300 * ACameraManger Implementation
301 */
302camera_status_t
303ACameraManager::getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList) {
304 if (mCachedCameraIdList.numCameras == kCameraIdListNotInit) {
305 int numCameras = 0;
306 Vector<char *> cameraIds;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800307 sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800308 if (cs == nullptr) {
309 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
310 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
311 }
312 // Get number of cameras
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800313 int numAllCameras = 0;
314 binder::Status serviceRet = cs->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_ALL,
315 &numAllCameras);
316 if (!serviceRet.isOk()) {
317 ALOGE("%s: Error getting camera count: %s", __FUNCTION__,
318 serviceRet.toString8().string());
319 numAllCameras = 0;
320 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800321 // Filter API2 compatible cameras and push to cameraIds
322 for (int i = 0; i < numAllCameras; i++) {
323 // TODO: Only suppot HALs that supports API2 directly now
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800324 bool camera2Support = false;
325 serviceRet = cs->supportsCameraApi(i, hardware::ICameraService::API_VERSION_2,
326 &camera2Support);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800327 char buf[kMaxCameraIdLen];
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800328 if (camera2Support) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800329 numCameras++;
330 mCameraIds.insert(i);
331 snprintf(buf, sizeof(buf), "%d", i);
332 size_t cameraIdSize = strlen(buf) + 1;
333 char *cameraId = new char[cameraIdSize];
334 if (!cameraId) {
335 ALOGE("Allocate memory for ACameraIdList failed!");
336 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
337 }
338 strlcpy(cameraId, buf, cameraIdSize);
339 cameraIds.push(cameraId);
340 }
341 }
342 mCachedCameraIdList.numCameras = numCameras;
343 mCachedCameraIdList.cameraIds = new const char*[numCameras];
344 if (!mCachedCameraIdList.cameraIds) {
345 ALOGE("Allocate memory for ACameraIdList failed!");
346 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
347 }
348 for (int i = 0; i < numCameras; i++) {
349 mCachedCameraIdList.cameraIds[i] = cameraIds[i];
350 }
351 }
352 *cameraIdList = &mCachedCameraIdList;
353 return ACAMERA_OK;
354}
355
356camera_status_t
357ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
358 Mutex::Autolock _l(mLock);
359 ACameraIdList* cachedList;
360 camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
361 if (ret != ACAMERA_OK) {
362 ALOGE("Get camera ID list failed! err: %d", ret);
363 return ret;
364 }
365
366 int numCameras = cachedList->numCameras;
367 ACameraIdList *out = new ACameraIdList;
368 if (!out) {
369 ALOGE("Allocate memory for ACameraIdList failed!");
370 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
371 }
372 out->numCameras = numCameras;
373 out->cameraIds = new const char*[numCameras];
374 if (!out->cameraIds) {
375 ALOGE("Allocate memory for ACameraIdList failed!");
376 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
377 }
378 for (int i = 0; i < numCameras; i++) {
379 const char* src = cachedList->cameraIds[i];
380 size_t dstSize = strlen(src) + 1;
381 char* dst = new char[dstSize];
382 if (!dst) {
383 ALOGE("Allocate memory for ACameraIdList failed!");
384 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
385 }
386 strlcpy(dst, src, dstSize);
387 out->cameraIds[i] = dst;
388 }
389 *cameraIdList = out;
390 return ACAMERA_OK;
391}
392
393void
394ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
395 if (cameraIdList != nullptr) {
396 if (cameraIdList->cameraIds != nullptr) {
397 for (int i = 0; i < cameraIdList->numCameras; i ++) {
398 delete[] cameraIdList->cameraIds[i];
399 }
400 delete[] cameraIdList->cameraIds;
401 }
402 delete cameraIdList;
403 }
404}
405
406camera_status_t ACameraManager::getCameraCharacteristics(
407 const char *cameraIdStr, ACameraMetadata **characteristics) {
408 Mutex::Autolock _l(mLock);
409 ACameraIdList* cachedList;
410 // Make sure mCameraIds is initialized
411 camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
412 if (ret != ACAMERA_OK) {
413 ALOGE("%s: Get camera ID list failed! err: %d", __FUNCTION__, ret);
414 return ret;
415 }
416 int cameraId = atoi(cameraIdStr);
417 if (mCameraIds.count(cameraId) == 0) {
418 ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
419 return ACAMERA_ERROR_INVALID_PARAMETER;
420 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800421 sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800422 if (cs == nullptr) {
423 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
424 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
425 }
426 CameraMetadata rawMetadata;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800427 binder::Status serviceRet = cs->getCameraCharacteristics(cameraId, &rawMetadata);
428 if (!serviceRet.isOk()) {
429 ALOGE("Get camera characteristics from camera service failed: %s",
430 serviceRet.toString8().string());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800431 return ACAMERA_ERROR_UNKNOWN; // should not reach here
432 }
433
434 *characteristics = new ACameraMetadata(
435 rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
436 return ACAMERA_OK;
437}
438
439camera_status_t
440ACameraManager::openCamera(
441 const char* cameraId,
442 ACameraDevice_StateCallbacks* callback,
443 /*out*/ACameraDevice** outDevice) {
444 ACameraMetadata* rawChars;
445 camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
446 Mutex::Autolock _l(mLock);
447 if (ret != ACAMERA_OK) {
448 ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
449 __FUNCTION__, cameraId, ret);
450 return ACAMERA_ERROR_INVALID_PARAMETER;
451 }
452 std::unique_ptr<ACameraMetadata> chars(rawChars);
453 rawChars = nullptr;
454
455 ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(chars));
456
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800457 sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800458 if (cs == nullptr) {
459 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
460 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
461 }
462
463 int id = atoi(cameraId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800464 sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
465 sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800466 // No way to get package name from native.
467 // Send a zero length package name and let camera service figure it out from UID
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800468 binder::Status serviceRet = cs->connectDevice(
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800469 callbacks, id, String16(""),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800470 hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800471
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800472 if (!serviceRet.isOk()) {
473 ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().string());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800474 delete device;
475 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
476 }
477 if (deviceRemote == nullptr) {
478 ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
479 delete device;
480 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
481 }
482 device->setRemoteDevice(deviceRemote);
483 *outDevice = device;
484 return ACAMERA_OK;
485}
486
487ACameraManager::~ACameraManager() {
488 Mutex::Autolock _l(mLock);
489 if (mCachedCameraIdList.numCameras != kCameraIdListNotInit) {
490 for (int i = 0; i < mCachedCameraIdList.numCameras; i++) {
491 delete[] mCachedCameraIdList.cameraIds[i];
492 }
493 delete[] mCachedCameraIdList.cameraIds;
494 }
495}