1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <dlfcn.h>
17 #include <algorithm>
18 #include "camera_host_service.h"
19 #include "camera_device_service.h"
20 #include "v1_0/icamera_device.h"
21 #include "camera_host_service_callback.h"
22 #include "camera_device_service_callback.h"
23 #include "camera_hal_hisysevent.h"
24 
25 namespace OHOS::Camera {
26 OHOS::sptr<CameraHostService> CameraHostService::cameraHostService_ = nullptr;
27 
CameraHostServiceGetInstance(void)28 extern "C" ICameraHost *CameraHostServiceGetInstance(void)
29 {
30     OHOS::sptr<CameraHostService> service = CameraHostService::GetInstance();
31     if (service == nullptr) {
32         CAMERA_LOGE("Camera host service is nullptr");
33         return nullptr;
34     }
35 
36     return service.GetRefPtr();
37 }
38 
GetVdiLibList(std::vector<std::string> & vdiLibList)39 int32_t CameraHostService::GetVdiLibList(std::vector<std::string> &vdiLibList)
40 {
41     std::vector<std::string>().swap(vdiLibList);
42     ReleaseHcsTree();
43     const struct DeviceResourceIface *pDevResIns = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
44     if (pDevResIns == nullptr) {
45         CAMERA_LOGE("get hcs interface failed.");
46         return OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT;
47     }
48 
49     SetHcsBlobPath(CONFIG_PATH_NAME);
50     const struct DeviceResourceNode *pRootNode = pDevResIns->GetRootNode();
51     if (pRootNode == nullptr) {
52         CAMERA_LOGE("GetRootNode failed");
53         return OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT;
54     }
55     if (pRootNode->name != nullptr) {
56         CAMERA_LOGI("pRootNode = %{public}s", pRootNode->name);
57     }
58 
59     const char *vdiLib = nullptr;
60     int32_t elemNum = pDevResIns->GetElemNum(pRootNode, "vdiLibList");
61     for (int i = 0; i < elemNum; i++) {
62         pDevResIns->GetStringArrayElem(pRootNode, "vdiLibList", i, &vdiLib, nullptr);
63         if (vdiLib == nullptr) {
64             CAMERA_LOGE("Get vdi lib list failed");
65             return OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT;
66         }
67         vdiLibList.push_back(std::string(vdiLib));
68     }
69 
70     if (vdiLibList.size() == 0) {
71         CAMERA_LOGE("Vdi library list is empty");
72         return OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT;
73     }
74 
75     return OHOS::HDI::Camera::V1_0::NO_ERROR;
76 }
77 
HdfCloseVdiLoaderList(std::vector<struct HdfVdiObject * > & cameraHostVdiLoaderList)78 void CameraHostService::HdfCloseVdiLoaderList(std::vector<struct HdfVdiObject *> &cameraHostVdiLoaderList)
79 {
80     for (auto cameraHostVdiLoader : cameraHostVdiLoaderList) {
81         if (cameraHostVdiLoader != nullptr) {
82             HdfCloseVdi(cameraHostVdiLoader);
83             cameraHostVdiLoader = nullptr;
84         }
85     }
86     std::vector<struct HdfVdiObject *>().swap(cameraHostVdiLoaderList);
87 }
88 
GetInstance()89 OHOS::sptr<CameraHostService> CameraHostService::GetInstance()
90 {
91     if (cameraHostService_ != nullptr) {
92         return cameraHostService_;
93     }
94     std::vector<std::string> vdiLibList;
95     if (GetVdiLibList(vdiLibList) != OHOS::HDI::Camera::V1_0::NO_ERROR) {
96         CAMERA_LOGE("Can not get vdi lib name");
97         return nullptr;
98     }
99     std::vector<ICameraHostVdi*> cameraHostVdiList;
100     std::vector<struct HdfVdiObject *> cameraHostVdiLoaderList;
101     for (auto vdiLib : vdiLibList) {
102         struct HdfVdiObject *cameraHostVdiLoader = HdfLoadVdi(vdiLib.c_str());
103         if (cameraHostVdiLoader == nullptr || cameraHostVdiLoader->vdiBase == nullptr) {
104             CAMERA_LOGE("Hdf load camera host vdi failed!");
105             return nullptr;
106         }
107         uint32_t version = HdfGetVdiVersion(cameraHostVdiLoader);
108         if (version != 1) {
109             HdfCloseVdi(cameraHostVdiLoader);
110             HdfCloseVdiLoaderList(cameraHostVdiLoaderList);
111             CAMERA_LOGE("Get camera host vdi version failed!");
112             return nullptr;
113         }
114         struct VdiWrapperCameraHost *vdiWrapper = reinterpret_cast<struct VdiWrapperCameraHost *>(
115             cameraHostVdiLoader->vdiBase);
116         if (vdiWrapper->module == nullptr) {
117             HdfCloseVdi(cameraHostVdiLoader);
118             HdfCloseVdiLoaderList(cameraHostVdiLoaderList);
119             CAMERA_LOGE("Hdf load camera host vdi failed, module is nullptr!");
120             return nullptr;
121         }
122         ICameraHostVdi *cameraHostVdi = reinterpret_cast<ICameraHostVdi *>(vdiWrapper->module);
123         cameraHostVdiList.push_back(cameraHostVdi);
124         cameraHostVdiLoaderList.push_back(cameraHostVdiLoader);
125     }
126     cameraHostService_ = new (std::nothrow) CameraHostService(cameraHostVdiList, cameraHostVdiLoaderList);
127     if (cameraHostService_ == nullptr) {
128         CAMERA_LOGE("Camera host service is nullptr");
129         HdfCloseVdiLoaderList(cameraHostVdiLoaderList);
130         return nullptr;
131     }
132 
133     return cameraHostService_;
134 }
135 
CameraHostService(std::vector<ICameraHostVdi * > cameraHostVdiList,std::vector<struct HdfVdiObject * > cameraHostVdiLoaderList)136 CameraHostService::CameraHostService(std::vector<ICameraHostVdi*> cameraHostVdiList,
137     std::vector<struct HdfVdiObject *> cameraHostVdiLoaderList)
138     : cameraHostVdiList_(cameraHostVdiList), cameraHostVdiLoaderList_(cameraHostVdiLoaderList)
139 {
140     CAMERA_LOGD("ctor, instance");
141 }
142 
~CameraHostService()143 CameraHostService::~CameraHostService()
144 {
145     HdfCloseVdiLoaderList(cameraHostVdiLoaderList_);
146     CAMERA_LOGD("dtor, instance");
147 }
148 
SetCallback(const OHOS::sptr<ICameraHostCallback> & callbackObj)149 int32_t CameraHostService::SetCallback(const OHOS::sptr<ICameraHostCallback> &callbackObj)
150 {
151     for (auto cameraHostVdi : cameraHostVdiList_) {
152         CHECK_IF_PTR_NULL_RETURN_VALUE(cameraHostVdi, OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT);
153         OHOS::sptr<ICameraHostVdiCallback> vdiCallbackObj = new CameraHostServiceCallback(callbackObj,
154             cameraHostVdi, cameraIdInfoList_);
155         if (vdiCallbackObj == nullptr) {
156             CAMERA_LOGE("Camera host service set callback failed, vdiCallbackObj is nullptr");
157             return OHOS::HDI::Camera::V1_0::INSUFFICIENT_RESOURCES;
158         }
159         int32_t ret = cameraHostVdi->SetCallback(vdiCallbackObj);
160         if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR) {
161             CAMERA_LOGE("Camera host service set callback failed");
162             return ret;
163         }
164     }
165 
166     return OHOS::HDI::Camera::V1_0::NO_ERROR;
167 }
168 
GetCameraIds(std::vector<std::string> & cameraIds)169 int32_t CameraHostService::GetCameraIds(std::vector<std::string> &cameraIds)
170 {
171     std::vector<std::string>().swap(cameraIds);
172     if (cameraIdInfoList_.size() == 0) {
173         int32_t ret = UpdateCameraIdMapList();
174         if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR) {
175             CAMERA_LOGE("Camera get cameraIds failed");
176             return ret;
177         }
178     }
179     for (auto cameraIdInfo : cameraIdInfoList_) {
180         if (cameraIdInfo.isDeleted == false) {
181             cameraIds.push_back(cameraIdInfo.currentCameraId);
182         }
183     }
184 
185     return OHOS::HDI::Camera::V1_0::NO_ERROR;
186 }
187 
GetCameraAbility(const std::string & cameraId,std::vector<uint8_t> & cameraAbility)188 int32_t CameraHostService::GetCameraAbility(const std::string &cameraId,
189     std::vector<uint8_t> &cameraAbility)
190 {
191     ICameraHostVdi* cameraHostVdi = GetCameraHostVdi(cameraId);
192     CHECK_IF_PTR_NULL_RETURN_VALUE(cameraHostVdi, OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT);
193 
194     std::string vdiCameraId = GetVendorCameraId(cameraId);
195     if (vdiCameraId == "") {
196         CAMERA_LOGE("Get vendor camera id failed");
197         return OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT;
198     }
199 
200     return cameraHostVdi->GetCameraAbility(vdiCameraId, cameraAbility);
201 }
202 
OpenCamera(const std::string & cameraId,const sptr<ICameraDeviceCallback> & callbackObj,sptr<ICameraDevice> & device)203 int32_t CameraHostService::OpenCamera(const std::string &cameraId, const sptr<ICameraDeviceCallback> &callbackObj,
204     sptr<ICameraDevice> &device)
205 {
206     CAMERAHALPERFSYSEVENT(TIME_FOR_OPEN_CAMERA);
207     ICameraHostVdi* cameraHostVdi = GetCameraHostVdi(cameraId);
208     CHECK_IF_PTR_NULL_RETURN_VALUE(cameraHostVdi, OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT);
209 
210     std::string vdiCameraId = GetVendorCameraId(cameraId);
211     if (vdiCameraId == "") {
212         CAMERA_LOGE("Get vendor camera id failed");
213         return OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT;
214     }
215 
216     OHOS::sptr<ICameraDeviceVdi> deviceVdi = nullptr;
217     OHOS::sptr<ICameraDeviceVdiCallback> vdiCallbackObj = new CameraDeviceServiceCallback(callbackObj);
218     if (vdiCallbackObj == nullptr) {
219         CAMERA_LOGE("Open camera error, vdiCallbackObj is nullptr");
220         return OHOS::HDI::Camera::V1_0::INSUFFICIENT_RESOURCES;
221     }
222     int32_t ret = cameraHostVdi->OpenCamera(vdiCameraId, vdiCallbackObj, deviceVdi);
223     if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR) {
224         CAMERA_LOGE("Open camera error, ret=%{public}d", ret);
225         return ret;
226     }
227     if (deviceVdi == nullptr) {
228         CAMERA_LOGE("Open camera error, deviceVdi is nullptr");
229         return OHOS::HDI::Camera::V1_0::INSUFFICIENT_RESOURCES;
230     }
231     device = new CameraDeviceService(deviceVdi);
232     if (device == nullptr) {
233         CAMERA_LOGE("Open camera error, device is nullptr");
234         return OHOS::HDI::Camera::V1_0::INSUFFICIENT_RESOURCES;
235     }
236 
237     return OHOS::HDI::Camera::V1_0::NO_ERROR;
238 }
239 
SetFlashlight(const std::string & cameraId,bool isEnable)240 int32_t CameraHostService::SetFlashlight(const std::string &cameraId, bool isEnable)
241 {
242     ICameraHostVdi* cameraHostVdi = GetCameraHostVdi(cameraId);
243     CHECK_IF_PTR_NULL_RETURN_VALUE(cameraHostVdi, OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT);
244 
245     std::string vdiCameraId = GetVendorCameraId(cameraId);
246     if (vdiCameraId == "") {
247         CAMERA_LOGE("Get vendor camera id failed");
248         return OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT;
249     }
250 
251     return cameraHostVdi->SetFlashlight(vdiCameraId, isEnable);
252 }
253 
UpdateCameraIdMapList()254 int32_t CameraHostService::UpdateCameraIdMapList()
255 {
256     std::vector<CameraIdInfo>().swap(cameraIdInfoList_);
257     int32_t currentCameraIndex = 1;
258     for (auto cameraHostVdi : cameraHostVdiList_) {
259         CHECK_IF_PTR_NULL_RETURN_VALUE(cameraHostVdi, OHOS::HDI::Camera::V1_0::INVALID_ARGUMENT);
260 
261         std::vector<std::string> vdiCameraIds;
262         int32_t ret = cameraHostVdi->GetCameraIds(vdiCameraIds);
263         if (ret != OHOS::HDI::Camera::V1_0::NO_ERROR) {
264             CAMERA_LOGE("Camera host service set callback failed");
265             return ret;
266         }
267         for (auto id : vdiCameraIds) {
268             struct CameraIdInfo cameraIdInfo;
269             std::string currentCameraId = "lcam00" + std::to_string(currentCameraIndex);
270             cameraIdInfo.currentCameraId = currentCameraId;
271             cameraIdInfo.cameraHostVdi = cameraHostVdi;
272             cameraIdInfo.vendorCameraId = id;
273             cameraIdInfo.isDeleted = false;
274             cameraIdInfoList_.push_back(cameraIdInfo);
275             currentCameraIndex++;
276         }
277     }
278 
279     return OHOS::HDI::Camera::V1_0::NO_ERROR;
280 }
281 
GetCameraHostVdi(const std::string & currentCameraId)282 ICameraHostVdi* CameraHostService::GetCameraHostVdi(const std::string &currentCameraId)
283 {
284     auto itr = std::find_if(cameraIdInfoList_.begin(), cameraIdInfoList_.end(),
285         [&currentCameraId](const struct CameraIdInfo &cameraIdInfo) {
286             return currentCameraId == cameraIdInfo.currentCameraId;
287         });
288     if (itr == cameraIdInfoList_.end()) {
289         CAMERA_LOGE("Get camera host vdi failed, current camera id = %{public}s doesn't exist",
290             currentCameraId.c_str());
291         return nullptr;
292     }
293 
294     return itr->cameraHostVdi;
295 }
296 
GetVendorCameraId(const std::string & currentCameraId)297 const std::string CameraHostService::GetVendorCameraId(const std::string &currentCameraId)
298 {
299     auto itr = std::find_if(cameraIdInfoList_.begin(), cameraIdInfoList_.end(),
300         [&currentCameraId](const struct CameraIdInfo &cameraIdInfo) {
301             return currentCameraId == cameraIdInfo.currentCameraId;
302         });
303     if (itr == cameraIdInfoList_.end()) {
304         CAMERA_LOGE("Get vendor camera id failed, current camera id = %{public}s doesn't exist",
305             currentCameraId.c_str());
306         return std::string("");
307     }
308 
309     return itr->vendorCameraId;
310 }
311 } // end namespace OHOS::Camera
312