blob: 3ecf845d016376bed0f082744657b5f3f5911ff6 [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>
Ivan Podogovee844a82016-09-15 11:32:41 +010025#include <cutils/properties.h>
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080026#include <stdlib.h>
Jayant Chowdharyf5b9cc62020-09-08 16:25:17 -070027#include <camera/CameraUtils.h>
Austin Borger0fb3ad92023-06-01 16:51:35 -070028#include <camera/StringUtils.h>
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080029#include <camera/VendorTagDescriptor.h>
30
Jayant Chowdhary6df26072018-11-06 23:55:12 -080031using namespace android::acam;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080032
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080033namespace android {
Jayant Chowdhary6df26072018-11-06 23:55:12 -080034namespace acam {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080035// Static member definitions
36const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
Shuzhen Wang43858162020-01-10 13:42:15 -080037const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId";
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080038const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
39const char* CameraManagerGlobal::kContextKey = "CallbackContext";
Shuzhen Wang7e540682020-04-10 13:30:25 -070040const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080041Mutex CameraManagerGlobal::sLock;
42CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
43
44CameraManagerGlobal&
45CameraManagerGlobal::getInstance() {
46 Mutex::Autolock _l(sLock);
47 CameraManagerGlobal* instance = sInstance;
48 if (instance == nullptr) {
49 instance = new CameraManagerGlobal();
50 sInstance = instance;
51 }
52 return *instance;
53}
54
55CameraManagerGlobal::~CameraManagerGlobal() {
56 // clear sInstance so next getInstance call knows to create a new one
57 Mutex::Autolock _sl(sLock);
58 sInstance = nullptr;
59 Mutex::Autolock _l(mLock);
60 if (mCameraService != nullptr) {
61 IInterface::asBinder(mCameraService)->unlinkToDeath(mDeathNotifier);
Yin-Chia Yehead91462016-01-06 16:45:08 -080062 mCameraService->removeListener(mCameraServiceListener);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080063 }
64 mDeathNotifier.clear();
65 if (mCbLooper != nullptr) {
66 mCbLooper->unregisterHandler(mHandler->id());
67 mCbLooper->stop();
68 }
69 mCbLooper.clear();
70 mHandler.clear();
71 mCameraServiceListener.clear();
72 mCameraService.clear();
73}
74
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080075sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080076 Mutex::Autolock _l(mLock);
Jayant Chowdhary80f128b2019-10-30 16:13:31 -070077 return getCameraServiceLocked();
78}
79
80sp<hardware::ICameraService> CameraManagerGlobal::getCameraServiceLocked() {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080081 if (mCameraService.get() == nullptr) {
Jayant Chowdharyf5b9cc62020-09-08 16:25:17 -070082 if (CameraUtils::isCameraServiceDisabled()) {
Ivan Podogovee844a82016-09-15 11:32:41 +010083 return mCameraService;
84 }
85
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080086 sp<IServiceManager> sm = defaultServiceManager();
87 sp<IBinder> binder;
88 do {
Austin Borger0fb3ad92023-06-01 16:51:35 -070089 binder = sm->getService(toString16(kCameraServiceName));
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -080090 if (binder != nullptr) {
91 break;
92 }
93 ALOGW("CameraService not published, waiting...");
94 usleep(kCameraServicePollDelay);
95 } while(true);
96 if (mDeathNotifier == nullptr) {
97 mDeathNotifier = new DeathNotifier(this);
98 }
99 binder->linkToDeath(mDeathNotifier);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800100 mCameraService = interface_cast<hardware::ICameraService>(binder);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800101
102 // Setup looper thread to perfrom availiability callbacks
103 if (mCbLooper == nullptr) {
104 mCbLooper = new ALooper;
105 mCbLooper->setName("C2N-mgr-looper");
Eino-Ville Talvala02bf0322016-02-18 12:41:10 -0800106 status_t err = mCbLooper->start(
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800107 /*runOnCallingThread*/false,
108 /*canCallJava*/ true,
Yin-Chia Yehead91462016-01-06 16:45:08 -0800109 PRIORITY_DEFAULT);
Eino-Ville Talvala02bf0322016-02-18 12:41:10 -0800110 if (err != OK) {
111 ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
112 __FUNCTION__, strerror(-err), err);
113 mCbLooper.clear();
114 return nullptr;
115 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800116 if (mHandler == nullptr) {
Shuzhen Wang7e540682020-04-10 13:30:25 -0700117 mHandler = new CallbackHandler(this);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800118 }
119 mCbLooper->registerHandler(mHandler);
120 }
121
122 // register ICameraServiceListener
123 if (mCameraServiceListener == nullptr) {
124 mCameraServiceListener = new CameraServiceListener(this);
125 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800126 std::vector<hardware::CameraStatus> cameraStatuses{};
127 mCameraService->addListener(mCameraServiceListener, &cameraStatuses);
128 for (auto& c : cameraStatuses) {
129 onStatusChangedLocked(c.status, c.cameraId);
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800130
131 for (auto& unavailablePhysicalId : c.unavailablePhysicalIds) {
132 onStatusChangedLocked(hardware::ICameraServiceListener::STATUS_NOT_PRESENT,
133 c.cameraId, unavailablePhysicalId);
134 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800135 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800136
137 // setup vendor tags
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800138 sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
139 binder::Status ret = mCameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800140
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800141 if (ret.isOk()) {
Emilian Peev71c73a22017-03-21 16:35:51 +0000142 if (0 < desc->getTagCount()) {
143 status_t err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
144 if (err != OK) {
145 ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
146 __FUNCTION__, strerror(-err), err);
147 }
148 } else {
149 sp<VendorTagDescriptorCache> cache =
150 new VendorTagDescriptorCache();
151 binder::Status res =
152 mCameraService->getCameraVendorTagCache(
153 /*out*/cache.get());
154 if (res.serviceSpecificErrorCode() ==
155 hardware::ICameraService::ERROR_DISCONNECTED) {
156 // No camera module available, not an error on devices with no cameras
157 VendorTagDescriptorCache::clearGlobalVendorTagCache();
158 } else if (res.isOk()) {
159 status_t err =
160 VendorTagDescriptorCache::setAsGlobalVendorTagCache(
161 cache);
162 if (err != OK) {
163 ALOGE("%s: Failed to set vendor tag cache,"
164 "received error %s (%d)", __FUNCTION__,
165 strerror(-err), err);
166 }
167 } else {
168 VendorTagDescriptorCache::clearGlobalVendorTagCache();
169 ALOGE("%s: Failed to setup vendor tag cache: %s",
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000170 __FUNCTION__, res.toString8().c_str());
Emilian Peev71c73a22017-03-21 16:35:51 +0000171 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800172 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800173 } else if (ret.serviceSpecificErrorCode() ==
174 hardware::ICameraService::ERROR_DEPRECATED_HAL) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800175 ALOGW("%s: Camera HAL too old; does not support vendor tags",
176 __FUNCTION__);
177 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
178 } else {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800179 ALOGE("%s: Failed to get vendor tag descriptors: %s",
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000180 __FUNCTION__, ret.toString8().c_str());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800181 }
182 }
183 ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
184 return mCameraService;
185}
186
187void CameraManagerGlobal::DeathNotifier::binderDied(const wp<IBinder>&)
188{
189 ALOGE("Camera service binderDied!");
190 sp<CameraManagerGlobal> cm = mCameraManager.promote();
191 if (cm != nullptr) {
192 AutoMutex lock(cm->mLock);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700193 std::vector<std::string> cameraIdList;
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800194 for (auto& pair : cm->mDeviceStatusMap) {
Rucha Katakwarc6e64012021-08-12 06:32:42 +0000195 cameraIdList.push_back(pair.first);
196 }
197
Austin Borger0fb3ad92023-06-01 16:51:35 -0700198 for (const std::string& cameraId : cameraIdList) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800199 cm->onStatusChangedLocked(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800200 CameraServiceListener::STATUS_NOT_PRESENT, cameraId);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800201 }
202 cm->mCameraService.clear();
203 // TODO: consider adding re-connect call here?
204 }
205}
206
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800207void CameraManagerGlobal::registerExtendedAvailabilityCallback(
208 const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800209 return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800210}
211
212void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
213 const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
214 Mutex::Autolock _l(mLock);
Shuzhen Wang7e540682020-04-10 13:30:25 -0700215
216 drainPendingCallbacksLocked();
217
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800218 Callback cb(callback);
219 mCallbacks.erase(cb);
220}
221
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800222void CameraManagerGlobal::registerAvailabilityCallback(
223 const ACameraManager_AvailabilityCallbacks *callback) {
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800224 return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(callback);
225}
226
227void CameraManagerGlobal::unregisterAvailabilityCallback(
228 const ACameraManager_AvailabilityCallbacks *callback) {
229 Mutex::Autolock _l(mLock);
Shuzhen Wang7e540682020-04-10 13:30:25 -0700230
231 drainPendingCallbacksLocked();
232
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800233 Callback cb(callback);
234 mCallbacks.erase(cb);
235}
236
Shuzhen Wang7e540682020-04-10 13:30:25 -0700237void CameraManagerGlobal::onCallbackCalled() {
238 Mutex::Autolock _l(mLock);
239 if (mPendingCallbackCnt > 0) {
240 mPendingCallbackCnt--;
241 }
242 mCallbacksCond.signal();
243}
244
245void CameraManagerGlobal::drainPendingCallbacksLocked() {
246 while (mPendingCallbackCnt > 0) {
247 auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout);
248 if (res != NO_ERROR) {
249 ALOGE("%s: Error waiting to drain callbacks: %s(%d)",
250 __FUNCTION__, strerror(-res), res);
251 break;
252 }
253 }
254}
255
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800256template<class T>
257void CameraManagerGlobal::registerAvailCallback(const T *callback) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800258 Mutex::Autolock _l(mLock);
259 Callback cb(callback);
260 auto pair = mCallbacks.insert(cb);
261 // Send initial callbacks if callback is newly registered
262 if (pair.second) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800263 for (auto& pair : mDeviceStatusMap) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700264 const std::string& cameraId = pair.first;
Shuzhen Wang43858162020-01-10 13:42:15 -0800265 int32_t status = pair.second.getStatus();
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700266 // Don't send initial callbacks for camera ids which don't support
267 // camera2
268 if (!pair.second.supportsHAL3) {
269 continue;
270 }
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800271
272 // Camera available/unavailable callback
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800273 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800274 ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
275 cb.mAvailable : cb.mUnavailable;
276 msg->setPointer(kCallbackFpKey, (void *) cbFunc);
277 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700278 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700279 mPendingCallbackCnt++;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800280 msg->post();
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800281
282 // Physical camera unavailable callback
Austin Borger0fb3ad92023-06-01 16:51:35 -0700283 std::set<std::string> unavailablePhysicalCameras =
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800284 pair.second.getUnavailablePhysicalIds();
285 for (const auto& physicalCameraId : unavailablePhysicalCameras) {
286 sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
287 ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
288 cb.mPhysicalCamUnavailable;
289 msg->setPointer(kCallbackFpKey, (void *) cbFunc);
290 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700291 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
292 msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700293 mPendingCallbackCnt++;
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800294 msg->post();
295 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800296 }
297 }
298}
299
Austin Borger0fb3ad92023-06-01 16:51:35 -0700300bool CameraManagerGlobal::supportsCamera2ApiLocked(const std::string &cameraId) {
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700301 bool camera2Support = false;
302 auto cs = getCameraServiceLocked();
303 binder::Status serviceRet =
Austin Borger0fb3ad92023-06-01 16:51:35 -0700304 cs->supportsCameraApi(cameraId,
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700305 hardware::ICameraService::API_VERSION_2, &camera2Support);
306 if (!serviceRet.isOk()) {
307 ALOGE("%s: supportsCameraApi2Locked() call failed for cameraId %s",
308 __FUNCTION__, cameraId.c_str());
309 return false;
310 }
311 return camera2Support;
312}
313
Austin Borger0fb3ad92023-06-01 16:51:35 -0700314void CameraManagerGlobal::getCameraIdList(std::vector<std::string>* cameraIds) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800315 // Ensure that we have initialized/refreshed the list of available devices
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800316 Mutex::Autolock _l(mLock);
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700317 // Needed to make sure we're connected to cameraservice
318 getCameraServiceLocked();
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800319 for(auto& deviceStatus : mDeviceStatusMap) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800320 int32_t status = deviceStatus.second.getStatus();
321 if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
322 status == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800323 continue;
324 }
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700325 if (!deviceStatus.second.supportsHAL3) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800326 continue;
327 }
328 cameraIds->push_back(deviceStatus.first);
329 }
330}
331
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800332bool CameraManagerGlobal::validStatus(int32_t status) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800333 switch (status) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800334 case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
335 case hardware::ICameraServiceListener::STATUS_PRESENT:
336 case hardware::ICameraServiceListener::STATUS_ENUMERATING:
337 case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800338 return true;
339 default:
340 return false;
341 }
342}
343
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800344bool CameraManagerGlobal::isStatusAvailable(int32_t status) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800345 switch (status) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800346 case hardware::ICameraServiceListener::STATUS_PRESENT:
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800347 return true;
348 default:
349 return false;
350 }
351}
352
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800353void CameraManagerGlobal::CallbackHandler::onMessageReceived(
Shuzhen Wang7e540682020-04-10 13:30:25 -0700354 const sp<AMessage> &msg) {
355 onMessageReceivedInternal(msg);
356 if (msg->what() == kWhatSendSingleCallback ||
357 msg->what() == kWhatSendSingleAccessCallback ||
358 msg->what() == kWhatSendSinglePhysicalCameraCallback) {
359 notifyParent();
360 }
361}
362
363void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800364 const sp<AMessage> &msg) {
365 switch (msg->what()) {
366 case kWhatSendSingleCallback:
367 {
368 ACameraManager_AvailabilityCallback cb;
369 void* context;
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800370 AString cameraId;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800371 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
372 if (!found) {
373 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
374 return;
375 }
376 found = msg->findPointer(kContextKey, &context);
377 if (!found) {
378 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
379 return;
380 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800381 found = msg->findString(kCameraIdKey, &cameraId);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800382 if (!found) {
383 ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
384 return;
385 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800386 (*cb)(context, cameraId.c_str());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800387 break;
388 }
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800389 case kWhatSendSingleAccessCallback:
390 {
391 ACameraManager_AccessPrioritiesChangedCallback cb;
392 void* context;
393 AString cameraId;
394 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
395 if (!found) {
396 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
397 return;
398 }
399 found = msg->findPointer(kContextKey, &context);
400 if (!found) {
401 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
402 return;
403 }
404 (*cb)(context);
405 break;
406 }
Shuzhen Wang43858162020-01-10 13:42:15 -0800407 case kWhatSendSinglePhysicalCameraCallback:
408 {
409 ACameraManager_PhysicalCameraAvailabilityCallback cb;
410 void* context;
411 AString cameraId;
412 AString physicalCameraId;
413 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
414 if (!found) {
415 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
416 return;
417 }
418 if (cb == nullptr) {
419 // Physical camera callback is null
420 return;
421 }
422 found = msg->findPointer(kContextKey, &context);
423 if (!found) {
424 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
425 return;
426 }
427 found = msg->findString(kCameraIdKey, &cameraId);
428 if (!found) {
429 ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
430 return;
431 }
432 found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
433 if (!found) {
434 ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
435 return;
436 }
437 (*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
438 break;
439 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800440 default:
441 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
442 break;
443 }
444}
445
Shuzhen Wang7e540682020-04-10 13:30:25 -0700446void CameraManagerGlobal::CallbackHandler::notifyParent() {
447 sp<CameraManagerGlobal> parent = mParent.promote();
448 if (parent != nullptr) {
449 parent->onCallbackCalled();
450 }
451}
452
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800453binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() {
454 sp<CameraManagerGlobal> cm = mCameraManager.promote();
455 if (cm != nullptr) {
456 cm->onCameraAccessPrioritiesChanged();
457 } else {
458 ALOGE("Cannot deliver camera access priority callback. Global camera manager died");
459 }
460 return binder::Status::ok();
461}
462
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800463binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700464 int32_t status, const std::string& cameraId) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800465 sp<CameraManagerGlobal> cm = mCameraManager.promote();
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800466 if (cm != nullptr) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700467 cm->onStatusChanged(status, cameraId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800468 } else {
Yin-Chia Yehead91462016-01-06 16:45:08 -0800469 ALOGE("Cannot deliver status change. Global camera manager died");
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800470 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800471 return binder::Status::ok();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800472}
473
Shuzhen Wang43858162020-01-10 13:42:15 -0800474binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700475 int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800476 sp<CameraManagerGlobal> cm = mCameraManager.promote();
477 if (cm != nullptr) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700478 cm->onStatusChanged(status, cameraId, physicalCameraId);
Shuzhen Wang43858162020-01-10 13:42:15 -0800479 } else {
480 ALOGE("Cannot deliver physical camera status change. Global camera manager died");
481 }
482 return binder::Status::ok();
483}
484
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800485void CameraManagerGlobal::onCameraAccessPrioritiesChanged() {
486 Mutex::Autolock _l(mLock);
487 for (auto cb : mCallbacks) {
488 sp<AMessage> msg = new AMessage(kWhatSendSingleAccessCallback, mHandler);
489 ACameraManager_AccessPrioritiesChangedCallback cbFp = cb.mAccessPriorityChanged;
490 if (cbFp != nullptr) {
491 msg->setPointer(kCallbackFpKey, (void *) cbFp);
492 msg->setPointer(kContextKey, cb.mContext);
Shuzhen Wang7e540682020-04-10 13:30:25 -0700493 mPendingCallbackCnt++;
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800494 msg->post();
495 }
496 }
497}
498
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800499void CameraManagerGlobal::onStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700500 int32_t status, const std::string& cameraId) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800501 Mutex::Autolock _l(mLock);
502 onStatusChangedLocked(status, cameraId);
503}
504
505void CameraManagerGlobal::onStatusChangedLocked(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700506 int32_t status, const std::string& cameraId) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800507 if (!validStatus(status)) {
508 ALOGE("%s: Invalid status %d", __FUNCTION__, status);
509 return;
510 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800511
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800512 bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
513 int32_t oldStatus = firstStatus ?
514 status : // first status
Shuzhen Wang43858162020-01-10 13:42:15 -0800515 mDeviceStatusMap[cameraId].getStatus();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800516
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800517 if (!firstStatus &&
518 isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
519 // No status update. No need to send callback
520 return;
521 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800522
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700523 bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
Shuzhen Wang43858162020-01-10 13:42:15 -0800524 if (firstStatus) {
525 mDeviceStatusMap.emplace(std::piecewise_construct,
526 std::forward_as_tuple(cameraId),
527 std::forward_as_tuple(status, supportsHAL3));
528 } else {
529 mDeviceStatusMap[cameraId].updateStatus(status);
530 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800531 // Iterate through all registered callbacks
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700532 if (supportsHAL3) {
533 for (auto cb : mCallbacks) {
534 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
535 ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
536 cb.mAvailable : cb.mUnavailable;
537 msg->setPointer(kCallbackFpKey, (void *) cbFp);
538 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700539 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700540 mPendingCallbackCnt++;
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700541 msg->post();
542 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800543 }
Guennadi Liakhovetski6034bf52017-12-07 10:28:29 +0100544 if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) {
545 mDeviceStatusMap.erase(cameraId);
546 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800547}
548
Shuzhen Wang43858162020-01-10 13:42:15 -0800549void CameraManagerGlobal::onStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700550 int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800551 Mutex::Autolock _l(mLock);
552 onStatusChangedLocked(status, cameraId, physicalCameraId);
553}
554
555void CameraManagerGlobal::onStatusChangedLocked(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700556 int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800557 if (!validStatus(status)) {
558 ALOGE("%s: Invalid status %d", __FUNCTION__, status);
559 return;
560 }
561
562 auto logicalStatus = mDeviceStatusMap.find(cameraId);
563 if (logicalStatus == mDeviceStatusMap.end()) {
564 ALOGE("%s: Physical camera id %s status change on a non-present id %s",
565 __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
566 return;
567 }
568 int32_t logicalCamStatus = mDeviceStatusMap[cameraId].getStatus();
569 if (logicalCamStatus != hardware::ICameraServiceListener::STATUS_PRESENT &&
570 logicalCamStatus != hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE) {
571 ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
Austin Borger0fb3ad92023-06-01 16:51:35 -0700572 __FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus);
Shuzhen Wang43858162020-01-10 13:42:15 -0800573 return;
574 }
575
576 bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
577
578 bool updated = false;
579 if (status == hardware::ICameraServiceListener::STATUS_PRESENT) {
580 updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId);
581 } else {
582 updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId);
583 }
584
585 // Iterate through all registered callbacks
586 if (supportsHAL3 && updated) {
587 for (auto cb : mCallbacks) {
588 sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
589 ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
590 cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
591 msg->setPointer(kCallbackFpKey, (void *) cbFp);
592 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700593 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
594 msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700595 mPendingCallbackCnt++;
Shuzhen Wang43858162020-01-10 13:42:15 -0800596 msg->post();
597 }
598 }
599}
600
601int32_t CameraManagerGlobal::StatusAndHAL3Support::getStatus() {
602 std::lock_guard<std::mutex> lock(mLock);
603 return status;
604}
605
606void CameraManagerGlobal::StatusAndHAL3Support::updateStatus(int32_t newStatus) {
607 std::lock_guard<std::mutex> lock(mLock);
608 status = newStatus;
609}
610
611bool CameraManagerGlobal::StatusAndHAL3Support::addUnavailablePhysicalId(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700612 const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800613 std::lock_guard<std::mutex> lock(mLock);
614 auto result = unavailablePhysicalIds.insert(physicalCameraId);
615 return result.second;
616}
617
618bool CameraManagerGlobal::StatusAndHAL3Support::removeUnavailablePhysicalId(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700619 const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800620 std::lock_guard<std::mutex> lock(mLock);
621 auto count = unavailablePhysicalIds.erase(physicalCameraId);
622 return count > 0;
623}
624
Austin Borger0fb3ad92023-06-01 16:51:35 -0700625std::set<std::string> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800626 std::lock_guard<std::mutex> lock(mLock);
627 return unavailablePhysicalIds;
628}
629
Jayant Chowdhary6df26072018-11-06 23:55:12 -0800630} // namespace acam
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800631} // namespace android
632
633/**
634 * ACameraManger Implementation
635 */
636camera_status_t
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800637ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
638 Mutex::Autolock _l(mLock);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800639
Austin Borger0fb3ad92023-06-01 16:51:35 -0700640 std::vector<std::string> idList;
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800641 CameraManagerGlobal::getInstance().getCameraIdList(&idList);
642
643 int numCameras = idList.size();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800644 ACameraIdList *out = new ACameraIdList;
645 if (!out) {
646 ALOGE("Allocate memory for ACameraIdList failed!");
647 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
648 }
649 out->numCameras = numCameras;
Bjoern Johansson1a5954c2017-01-10 10:30:18 -0800650 out->cameraIds = new const char*[numCameras];
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800651 if (!out->cameraIds) {
652 ALOGE("Allocate memory for ACameraIdList failed!");
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800653 deleteCameraIdList(out);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800654 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
655 }
656 for (int i = 0; i < numCameras; i++) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700657 const char* src = idList[i].c_str();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800658 size_t dstSize = strlen(src) + 1;
659 char* dst = new char[dstSize];
660 if (!dst) {
661 ALOGE("Allocate memory for ACameraIdList failed!");
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800662 deleteCameraIdList(out);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800663 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
664 }
665 strlcpy(dst, src, dstSize);
666 out->cameraIds[i] = dst;
667 }
668 *cameraIdList = out;
669 return ACAMERA_OK;
670}
671
672void
673ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
674 if (cameraIdList != nullptr) {
675 if (cameraIdList->cameraIds != nullptr) {
676 for (int i = 0; i < cameraIdList->numCameras; i ++) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800677 if (cameraIdList->cameraIds[i] != nullptr) {
678 delete[] cameraIdList->cameraIds[i];
679 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800680 }
681 delete[] cameraIdList->cameraIds;
682 }
683 delete cameraIdList;
684 }
685}
686
687camera_status_t ACameraManager::getCameraCharacteristics(
Yin-Chia Yehdd045bf2018-08-20 12:39:19 -0700688 const char* cameraIdStr, sp<ACameraMetadata>* characteristics) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800689 Mutex::Autolock _l(mLock);
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800690
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800691 sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800692 if (cs == nullptr) {
693 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
694 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
695 }
Austin Borger3560b7e2022-10-27 12:20:29 -0700696
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800697 CameraMetadata rawMetadata;
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700698 int targetSdkVersion = android_get_application_target_sdk_version();
Austin Borger0fb3ad92023-06-01 16:51:35 -0700699 binder::Status serviceRet = cs->getCameraCharacteristics(cameraIdStr,
Austin Borger45ec7c22023-01-25 10:59:08 -0800700 targetSdkVersion, /*overrideToPortrait*/false, &rawMetadata);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800701 if (!serviceRet.isOk()) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800702 switch(serviceRet.serviceSpecificErrorCode()) {
703 case hardware::ICameraService::ERROR_DISCONNECTED:
704 ALOGE("%s: Camera %s has been disconnected", __FUNCTION__, cameraIdStr);
705 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
706 case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
707 ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
708 return ACAMERA_ERROR_INVALID_PARAMETER;
709 default:
710 ALOGE("Get camera characteristics from camera service failed: %s",
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000711 serviceRet.toString8().c_str());
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800712 return ACAMERA_ERROR_UNKNOWN; // should not reach here
713 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800714 }
715
716 *characteristics = new ACameraMetadata(
717 rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
718 return ACAMERA_OK;
719}
720
721camera_status_t
722ACameraManager::openCamera(
723 const char* cameraId,
724 ACameraDevice_StateCallbacks* callback,
725 /*out*/ACameraDevice** outDevice) {
Yin-Chia Yehdd045bf2018-08-20 12:39:19 -0700726 sp<ACameraMetadata> chars;
727 camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800728 Mutex::Autolock _l(mLock);
729 if (ret != ACAMERA_OK) {
730 ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
731 __FUNCTION__, cameraId, ret);
732 return ACAMERA_ERROR_INVALID_PARAMETER;
733 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800734
Yin-Chia Yehdd045bf2018-08-20 12:39:19 -0700735 ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800736
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800737 sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800738 if (cs == nullptr) {
739 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
Yunlian Jiangb01d8f72016-10-04 16:34:18 -0700740 delete device;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800741 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
742 }
743
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800744 sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
745 sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700746 int targetSdkVersion = android_get_application_target_sdk_version();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800747 // No way to get package name from native.
748 // Send a zero length package name and let camera service figure it out from UID
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800749 binder::Status serviceRet = cs->connectDevice(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700750 callbacks, cameraId, "", {},
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700751 hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/0,
Austin Borger45ec7c22023-01-25 10:59:08 -0800752 targetSdkVersion, /*overrideToPortrait*/false, /*out*/&deviceRemote);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800753
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800754 if (!serviceRet.isOk()) {
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000755 ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().c_str());
Yin-Chia Yeh3e49be12016-04-12 16:00:33 -0700756 // Convert serviceRet to camera_status_t
757 switch(serviceRet.serviceSpecificErrorCode()) {
758 case hardware::ICameraService::ERROR_DISCONNECTED:
759 ret = ACAMERA_ERROR_CAMERA_DISCONNECTED;
760 break;
761 case hardware::ICameraService::ERROR_CAMERA_IN_USE:
762 ret = ACAMERA_ERROR_CAMERA_IN_USE;
763 break;
764 case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
765 ret = ACAMERA_ERROR_MAX_CAMERA_IN_USE;
766 break;
767 case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
768 ret = ACAMERA_ERROR_INVALID_PARAMETER;
769 break;
770 case hardware::ICameraService::ERROR_DEPRECATED_HAL:
771 // Should not reach here since we filtered legacy HALs earlier
772 ret = ACAMERA_ERROR_INVALID_PARAMETER;
773 break;
774 case hardware::ICameraService::ERROR_DISABLED:
775 ret = ACAMERA_ERROR_CAMERA_DISABLED;
776 break;
777 case hardware::ICameraService::ERROR_PERMISSION_DENIED:
778 ret = ACAMERA_ERROR_PERMISSION_DENIED;
779 break;
780 case hardware::ICameraService::ERROR_INVALID_OPERATION:
781 default:
782 ret = ACAMERA_ERROR_UNKNOWN;
783 break;
784 }
785
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800786 delete device;
Yin-Chia Yeh3e49be12016-04-12 16:00:33 -0700787 return ret;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800788 }
789 if (deviceRemote == nullptr) {
790 ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
791 delete device;
792 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
793 }
794 device->setRemoteDevice(deviceRemote);
795 *outDevice = device;
796 return ACAMERA_OK;
797}
798
799ACameraManager::~ACameraManager() {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800800
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800801}