blob: 0ee858c227bfbfedbb8f4a9cf7330120c988a826 [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);
Kwangkyu Park01f84432023-09-15 17:08:17 +0900259 getCameraServiceLocked();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800260 Callback cb(callback);
261 auto pair = mCallbacks.insert(cb);
262 // Send initial callbacks if callback is newly registered
263 if (pair.second) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800264 for (auto& pair : mDeviceStatusMap) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700265 const std::string& cameraId = pair.first;
Shuzhen Wang43858162020-01-10 13:42:15 -0800266 int32_t status = pair.second.getStatus();
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700267 // Don't send initial callbacks for camera ids which don't support
268 // camera2
269 if (!pair.second.supportsHAL3) {
270 continue;
271 }
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800272
273 // Camera available/unavailable callback
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800274 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800275 ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
276 cb.mAvailable : cb.mUnavailable;
277 msg->setPointer(kCallbackFpKey, (void *) cbFunc);
278 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700279 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700280 mPendingCallbackCnt++;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800281 msg->post();
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800282
283 // Physical camera unavailable callback
Austin Borger0fb3ad92023-06-01 16:51:35 -0700284 std::set<std::string> unavailablePhysicalCameras =
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800285 pair.second.getUnavailablePhysicalIds();
286 for (const auto& physicalCameraId : unavailablePhysicalCameras) {
287 sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
288 ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
289 cb.mPhysicalCamUnavailable;
290 msg->setPointer(kCallbackFpKey, (void *) cbFunc);
291 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700292 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
293 msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700294 mPendingCallbackCnt++;
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800295 msg->post();
296 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800297 }
298 }
299}
300
Austin Borger0fb3ad92023-06-01 16:51:35 -0700301bool CameraManagerGlobal::supportsCamera2ApiLocked(const std::string &cameraId) {
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700302 bool camera2Support = false;
303 auto cs = getCameraServiceLocked();
304 binder::Status serviceRet =
Austin Borger0fb3ad92023-06-01 16:51:35 -0700305 cs->supportsCameraApi(cameraId,
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700306 hardware::ICameraService::API_VERSION_2, &camera2Support);
307 if (!serviceRet.isOk()) {
308 ALOGE("%s: supportsCameraApi2Locked() call failed for cameraId %s",
309 __FUNCTION__, cameraId.c_str());
310 return false;
311 }
312 return camera2Support;
313}
314
Austin Borger0fb3ad92023-06-01 16:51:35 -0700315void CameraManagerGlobal::getCameraIdList(std::vector<std::string>* cameraIds) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800316 // Ensure that we have initialized/refreshed the list of available devices
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800317 Mutex::Autolock _l(mLock);
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700318 // Needed to make sure we're connected to cameraservice
319 getCameraServiceLocked();
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800320 for(auto& deviceStatus : mDeviceStatusMap) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800321 int32_t status = deviceStatus.second.getStatus();
322 if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
323 status == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800324 continue;
325 }
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700326 if (!deviceStatus.second.supportsHAL3) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800327 continue;
328 }
329 cameraIds->push_back(deviceStatus.first);
330 }
331}
332
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800333bool CameraManagerGlobal::validStatus(int32_t status) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800334 switch (status) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800335 case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
336 case hardware::ICameraServiceListener::STATUS_PRESENT:
337 case hardware::ICameraServiceListener::STATUS_ENUMERATING:
338 case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800339 return true;
340 default:
341 return false;
342 }
343}
344
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800345bool CameraManagerGlobal::isStatusAvailable(int32_t status) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800346 switch (status) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800347 case hardware::ICameraServiceListener::STATUS_PRESENT:
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800348 return true;
349 default:
350 return false;
351 }
352}
353
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800354void CameraManagerGlobal::CallbackHandler::onMessageReceived(
Shuzhen Wang7e540682020-04-10 13:30:25 -0700355 const sp<AMessage> &msg) {
356 onMessageReceivedInternal(msg);
357 if (msg->what() == kWhatSendSingleCallback ||
358 msg->what() == kWhatSendSingleAccessCallback ||
359 msg->what() == kWhatSendSinglePhysicalCameraCallback) {
360 notifyParent();
361 }
362}
363
364void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800365 const sp<AMessage> &msg) {
366 switch (msg->what()) {
367 case kWhatSendSingleCallback:
368 {
369 ACameraManager_AvailabilityCallback cb;
370 void* context;
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800371 AString cameraId;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800372 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
373 if (!found) {
374 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
375 return;
376 }
377 found = msg->findPointer(kContextKey, &context);
378 if (!found) {
379 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
380 return;
381 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800382 found = msg->findString(kCameraIdKey, &cameraId);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800383 if (!found) {
384 ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
385 return;
386 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800387 (*cb)(context, cameraId.c_str());
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800388 break;
389 }
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800390 case kWhatSendSingleAccessCallback:
391 {
392 ACameraManager_AccessPrioritiesChangedCallback cb;
393 void* context;
394 AString cameraId;
395 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
396 if (!found) {
397 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
398 return;
399 }
400 found = msg->findPointer(kContextKey, &context);
401 if (!found) {
402 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
403 return;
404 }
405 (*cb)(context);
406 break;
407 }
Shuzhen Wang43858162020-01-10 13:42:15 -0800408 case kWhatSendSinglePhysicalCameraCallback:
409 {
410 ACameraManager_PhysicalCameraAvailabilityCallback cb;
411 void* context;
412 AString cameraId;
413 AString physicalCameraId;
414 bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
415 if (!found) {
416 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
417 return;
418 }
419 if (cb == nullptr) {
420 // Physical camera callback is null
421 return;
422 }
423 found = msg->findPointer(kContextKey, &context);
424 if (!found) {
425 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
426 return;
427 }
428 found = msg->findString(kCameraIdKey, &cameraId);
429 if (!found) {
430 ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
431 return;
432 }
433 found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
434 if (!found) {
435 ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
436 return;
437 }
438 (*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
439 break;
440 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800441 default:
442 ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
443 break;
444 }
445}
446
Shuzhen Wang7e540682020-04-10 13:30:25 -0700447void CameraManagerGlobal::CallbackHandler::notifyParent() {
448 sp<CameraManagerGlobal> parent = mParent.promote();
449 if (parent != nullptr) {
450 parent->onCallbackCalled();
451 }
452}
453
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800454binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() {
455 sp<CameraManagerGlobal> cm = mCameraManager.promote();
456 if (cm != nullptr) {
457 cm->onCameraAccessPrioritiesChanged();
458 } else {
459 ALOGE("Cannot deliver camera access priority callback. Global camera manager died");
460 }
461 return binder::Status::ok();
462}
463
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800464binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700465 int32_t status, const std::string& cameraId) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800466 sp<CameraManagerGlobal> cm = mCameraManager.promote();
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800467 if (cm != nullptr) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700468 cm->onStatusChanged(status, cameraId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800469 } else {
Yin-Chia Yehead91462016-01-06 16:45:08 -0800470 ALOGE("Cannot deliver status change. Global camera manager died");
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800471 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800472 return binder::Status::ok();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800473}
474
Shuzhen Wang43858162020-01-10 13:42:15 -0800475binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700476 int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800477 sp<CameraManagerGlobal> cm = mCameraManager.promote();
478 if (cm != nullptr) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700479 cm->onStatusChanged(status, cameraId, physicalCameraId);
Shuzhen Wang43858162020-01-10 13:42:15 -0800480 } else {
481 ALOGE("Cannot deliver physical camera status change. Global camera manager died");
482 }
483 return binder::Status::ok();
484}
485
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800486void CameraManagerGlobal::onCameraAccessPrioritiesChanged() {
487 Mutex::Autolock _l(mLock);
488 for (auto cb : mCallbacks) {
489 sp<AMessage> msg = new AMessage(kWhatSendSingleAccessCallback, mHandler);
490 ACameraManager_AccessPrioritiesChangedCallback cbFp = cb.mAccessPriorityChanged;
491 if (cbFp != nullptr) {
492 msg->setPointer(kCallbackFpKey, (void *) cbFp);
493 msg->setPointer(kContextKey, cb.mContext);
Shuzhen Wang7e540682020-04-10 13:30:25 -0700494 mPendingCallbackCnt++;
Emilian Peevc6f2ab32019-03-04 11:18:59 -0800495 msg->post();
496 }
497 }
498}
499
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800500void CameraManagerGlobal::onStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700501 int32_t status, const std::string& cameraId) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800502 Mutex::Autolock _l(mLock);
503 onStatusChangedLocked(status, cameraId);
504}
505
506void CameraManagerGlobal::onStatusChangedLocked(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700507 int32_t status, const std::string& cameraId) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800508 if (!validStatus(status)) {
509 ALOGE("%s: Invalid status %d", __FUNCTION__, status);
510 return;
511 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800512
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800513 bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
514 int32_t oldStatus = firstStatus ?
515 status : // first status
Shuzhen Wang43858162020-01-10 13:42:15 -0800516 mDeviceStatusMap[cameraId].getStatus();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800517
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800518 if (!firstStatus &&
519 isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
520 // No status update. No need to send callback
521 return;
522 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800523
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700524 bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
Shuzhen Wang43858162020-01-10 13:42:15 -0800525 if (firstStatus) {
526 mDeviceStatusMap.emplace(std::piecewise_construct,
527 std::forward_as_tuple(cameraId),
528 std::forward_as_tuple(status, supportsHAL3));
529 } else {
530 mDeviceStatusMap[cameraId].updateStatus(status);
531 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800532 // Iterate through all registered callbacks
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700533 if (supportsHAL3) {
534 for (auto cb : mCallbacks) {
535 sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
536 ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
537 cb.mAvailable : cb.mUnavailable;
538 msg->setPointer(kCallbackFpKey, (void *) cbFp);
539 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700540 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700541 mPendingCallbackCnt++;
Jayant Chowdhary80f128b2019-10-30 16:13:31 -0700542 msg->post();
543 }
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800544 }
Guennadi Liakhovetski6034bf52017-12-07 10:28:29 +0100545 if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) {
546 mDeviceStatusMap.erase(cameraId);
547 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800548}
549
Shuzhen Wang43858162020-01-10 13:42:15 -0800550void CameraManagerGlobal::onStatusChanged(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700551 int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800552 Mutex::Autolock _l(mLock);
553 onStatusChangedLocked(status, cameraId, physicalCameraId);
554}
555
556void CameraManagerGlobal::onStatusChangedLocked(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700557 int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800558 if (!validStatus(status)) {
559 ALOGE("%s: Invalid status %d", __FUNCTION__, status);
560 return;
561 }
562
563 auto logicalStatus = mDeviceStatusMap.find(cameraId);
564 if (logicalStatus == mDeviceStatusMap.end()) {
565 ALOGE("%s: Physical camera id %s status change on a non-present id %s",
566 __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
567 return;
568 }
569 int32_t logicalCamStatus = mDeviceStatusMap[cameraId].getStatus();
570 if (logicalCamStatus != hardware::ICameraServiceListener::STATUS_PRESENT &&
571 logicalCamStatus != hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE) {
572 ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
Austin Borger0fb3ad92023-06-01 16:51:35 -0700573 __FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus);
Shuzhen Wang43858162020-01-10 13:42:15 -0800574 return;
575 }
576
577 bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
578
579 bool updated = false;
580 if (status == hardware::ICameraServiceListener::STATUS_PRESENT) {
581 updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId);
582 } else {
583 updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId);
584 }
585
586 // Iterate through all registered callbacks
587 if (supportsHAL3 && updated) {
588 for (auto cb : mCallbacks) {
589 sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
590 ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
591 cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
592 msg->setPointer(kCallbackFpKey, (void *) cbFp);
593 msg->setPointer(kContextKey, cb.mContext);
Austin Borger0fb3ad92023-06-01 16:51:35 -0700594 msg->setString(kCameraIdKey, AString(cameraId.c_str()));
595 msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
Shuzhen Wang7e540682020-04-10 13:30:25 -0700596 mPendingCallbackCnt++;
Shuzhen Wang43858162020-01-10 13:42:15 -0800597 msg->post();
598 }
599 }
600}
601
602int32_t CameraManagerGlobal::StatusAndHAL3Support::getStatus() {
603 std::lock_guard<std::mutex> lock(mLock);
604 return status;
605}
606
607void CameraManagerGlobal::StatusAndHAL3Support::updateStatus(int32_t newStatus) {
608 std::lock_guard<std::mutex> lock(mLock);
609 status = newStatus;
610}
611
612bool CameraManagerGlobal::StatusAndHAL3Support::addUnavailablePhysicalId(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700613 const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800614 std::lock_guard<std::mutex> lock(mLock);
615 auto result = unavailablePhysicalIds.insert(physicalCameraId);
616 return result.second;
617}
618
619bool CameraManagerGlobal::StatusAndHAL3Support::removeUnavailablePhysicalId(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700620 const std::string& physicalCameraId) {
Shuzhen Wang43858162020-01-10 13:42:15 -0800621 std::lock_guard<std::mutex> lock(mLock);
622 auto count = unavailablePhysicalIds.erase(physicalCameraId);
623 return count > 0;
624}
625
Austin Borger0fb3ad92023-06-01 16:51:35 -0700626std::set<std::string> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
Shuzhen Wang4fa28d22020-01-23 15:57:25 -0800627 std::lock_guard<std::mutex> lock(mLock);
628 return unavailablePhysicalIds;
629}
630
Jayant Chowdhary6df26072018-11-06 23:55:12 -0800631} // namespace acam
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800632} // namespace android
633
634/**
635 * ACameraManger Implementation
636 */
637camera_status_t
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800638ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
639 Mutex::Autolock _l(mLock);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800640
Austin Borger0fb3ad92023-06-01 16:51:35 -0700641 std::vector<std::string> idList;
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800642 CameraManagerGlobal::getInstance().getCameraIdList(&idList);
643
644 int numCameras = idList.size();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800645 ACameraIdList *out = new ACameraIdList;
646 if (!out) {
647 ALOGE("Allocate memory for ACameraIdList failed!");
648 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
649 }
650 out->numCameras = numCameras;
Bjoern Johansson1a5954c2017-01-10 10:30:18 -0800651 out->cameraIds = new const char*[numCameras];
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800652 if (!out->cameraIds) {
653 ALOGE("Allocate memory for ACameraIdList failed!");
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800654 deleteCameraIdList(out);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800655 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
656 }
657 for (int i = 0; i < numCameras; i++) {
Austin Borger0fb3ad92023-06-01 16:51:35 -0700658 const char* src = idList[i].c_str();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800659 size_t dstSize = strlen(src) + 1;
660 char* dst = new char[dstSize];
661 if (!dst) {
662 ALOGE("Allocate memory for ACameraIdList failed!");
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800663 deleteCameraIdList(out);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800664 return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
665 }
666 strlcpy(dst, src, dstSize);
667 out->cameraIds[i] = dst;
668 }
669 *cameraIdList = out;
670 return ACAMERA_OK;
671}
672
673void
674ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
675 if (cameraIdList != nullptr) {
676 if (cameraIdList->cameraIds != nullptr) {
677 for (int i = 0; i < cameraIdList->numCameras; i ++) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800678 if (cameraIdList->cameraIds[i] != nullptr) {
679 delete[] cameraIdList->cameraIds[i];
680 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800681 }
682 delete[] cameraIdList->cameraIds;
683 }
684 delete cameraIdList;
685 }
686}
687
688camera_status_t ACameraManager::getCameraCharacteristics(
Yin-Chia Yehdd045bf2018-08-20 12:39:19 -0700689 const char* cameraIdStr, sp<ACameraMetadata>* characteristics) {
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800690 Mutex::Autolock _l(mLock);
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800691
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800692 sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800693 if (cs == nullptr) {
694 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
695 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
696 }
Austin Borger3560b7e2022-10-27 12:20:29 -0700697
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800698 CameraMetadata rawMetadata;
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700699 int targetSdkVersion = android_get_application_target_sdk_version();
Austin Borger0fb3ad92023-06-01 16:51:35 -0700700 binder::Status serviceRet = cs->getCameraCharacteristics(cameraIdStr,
Austin Borger45ec7c22023-01-25 10:59:08 -0800701 targetSdkVersion, /*overrideToPortrait*/false, &rawMetadata);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800702 if (!serviceRet.isOk()) {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800703 switch(serviceRet.serviceSpecificErrorCode()) {
704 case hardware::ICameraService::ERROR_DISCONNECTED:
705 ALOGE("%s: Camera %s has been disconnected", __FUNCTION__, cameraIdStr);
706 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
707 case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
708 ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
709 return ACAMERA_ERROR_INVALID_PARAMETER;
710 default:
711 ALOGE("Get camera characteristics from camera service failed: %s",
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000712 serviceRet.toString8().c_str());
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800713 return ACAMERA_ERROR_UNKNOWN; // should not reach here
714 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800715 }
716
717 *characteristics = new ACameraMetadata(
718 rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
719 return ACAMERA_OK;
720}
721
722camera_status_t
723ACameraManager::openCamera(
724 const char* cameraId,
725 ACameraDevice_StateCallbacks* callback,
726 /*out*/ACameraDevice** outDevice) {
Yin-Chia Yehdd045bf2018-08-20 12:39:19 -0700727 sp<ACameraMetadata> chars;
728 camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800729 Mutex::Autolock _l(mLock);
730 if (ret != ACAMERA_OK) {
731 ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
732 __FUNCTION__, cameraId, ret);
733 return ACAMERA_ERROR_INVALID_PARAMETER;
734 }
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800735
Yin-Chia Yehdd045bf2018-08-20 12:39:19 -0700736 ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800737
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800738 sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800739 if (cs == nullptr) {
740 ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
Yunlian Jiangb01d8f72016-10-04 16:34:18 -0700741 delete device;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800742 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
743 }
744
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800745 sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
746 sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700747 int targetSdkVersion = android_get_application_target_sdk_version();
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800748 // No way to get package name from native.
749 // Send a zero length package name and let camera service figure it out from UID
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800750 binder::Status serviceRet = cs->connectDevice(
Austin Borger0fb3ad92023-06-01 16:51:35 -0700751 callbacks, cameraId, "", {},
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700752 hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/0,
Austin Borger45ec7c22023-01-25 10:59:08 -0800753 targetSdkVersion, /*overrideToPortrait*/false, /*out*/&deviceRemote);
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800754
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800755 if (!serviceRet.isOk()) {
Tomasz Wasilczyk12b04a52023-08-11 15:52:22 +0000756 ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().c_str());
Yin-Chia Yeh3e49be12016-04-12 16:00:33 -0700757 // Convert serviceRet to camera_status_t
758 switch(serviceRet.serviceSpecificErrorCode()) {
759 case hardware::ICameraService::ERROR_DISCONNECTED:
760 ret = ACAMERA_ERROR_CAMERA_DISCONNECTED;
761 break;
762 case hardware::ICameraService::ERROR_CAMERA_IN_USE:
763 ret = ACAMERA_ERROR_CAMERA_IN_USE;
764 break;
765 case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
766 ret = ACAMERA_ERROR_MAX_CAMERA_IN_USE;
767 break;
768 case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
769 ret = ACAMERA_ERROR_INVALID_PARAMETER;
770 break;
771 case hardware::ICameraService::ERROR_DEPRECATED_HAL:
772 // Should not reach here since we filtered legacy HALs earlier
773 ret = ACAMERA_ERROR_INVALID_PARAMETER;
774 break;
775 case hardware::ICameraService::ERROR_DISABLED:
776 ret = ACAMERA_ERROR_CAMERA_DISABLED;
777 break;
778 case hardware::ICameraService::ERROR_PERMISSION_DENIED:
779 ret = ACAMERA_ERROR_PERMISSION_DENIED;
780 break;
781 case hardware::ICameraService::ERROR_INVALID_OPERATION:
782 default:
783 ret = ACAMERA_ERROR_UNKNOWN;
784 break;
785 }
786
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800787 delete device;
Yin-Chia Yeh3e49be12016-04-12 16:00:33 -0700788 return ret;
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800789 }
790 if (deviceRemote == nullptr) {
791 ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
792 delete device;
793 return ACAMERA_ERROR_CAMERA_DISCONNECTED;
794 }
795 device->setRemoteDevice(deviceRemote);
796 *outDevice = device;
797 return ACAMERA_OK;
798}
799
800ACameraManager::~ACameraManager() {
Eino-Ville Talvalaf51fca22016-12-13 11:25:55 -0800801
Yin-Chia Yeh0dea57f2015-12-09 16:46:07 -0800802}