1 /*
2  * Copyright (c) 2021-2024 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 "dcamera_host.h"
17 
18 #include <cstdlib>
19 #include "iservice_registry.h"
20 #include "iproxy_broker.h"
21 #include "iservmgr_hdi.h"
22 
23 #include "anonymous_string.h"
24 #include "distributed_hardware_log.h"
25 #include "metadata_utils.h"
26 #include "dcamera.h"
27 
28 namespace OHOS {
29 namespace DistributedHardware {
30 OHOS::sptr<DCameraHost> DCameraHost::instance_ = nullptr;
31 DCameraHost::AutoRelease DCameraHost::autoRelease_;
32 
CameraHostImplGetInstance(void)33 extern "C" ICameraHost *CameraHostImplGetInstance(void)
34 {
35     return static_cast<ICameraHost *>(DCameraHost::GetInstance().GetRefPtr());
36 }
37 
GetInstance()38 OHOS::sptr<DCameraHost> DCameraHost::GetInstance()
39 {
40     if (instance_ == nullptr) {
41         instance_ = sptr<DCameraHost>(new DCameraHost());
42         if (instance_ == nullptr) {
43             DHLOGE("Get distributed camera host instance failed.");
44             return nullptr;
45         }
46     }
47     return instance_;
48 }
49 
SetCallback(const sptr<HDI::Camera::V1_0::ICameraHostCallback> & callbackObj)50 int32_t DCameraHost::SetCallback(const sptr<HDI::Camera::V1_0::ICameraHostCallback> &callbackObj)
51 {
52     if (callbackObj == nullptr) {
53         DHLOGE("DCameraHost::SetCallback, input camera host callback is null.");
54         return CamRetCode::INVALID_ARGUMENT;
55     }
56     dCameraHostCallback_ = callbackObj;
57     dCameraHostRecipient_ = sptr<DCameraHostRecipient>(new DCameraHostRecipient());
58     return CamRetCode::NO_ERROR;
59 }
60 
SetCallback_V1_2(const sptr<HDI::Camera::V1_2::ICameraHostCallback> & callbackObj)61 int32_t DCameraHost::SetCallback_V1_2(const sptr<HDI::Camera::V1_2::ICameraHostCallback> &callbackObj)
62 {
63     if (callbackObj == nullptr) {
64         DHLOGE("DCameraHost::SetCallback_V1_2, input camera host callback is null.");
65         return CamRetCode::INVALID_ARGUMENT;
66     }
67     dCameraHostCallback_V1_2_ = callbackObj;
68     dCameraHostRecipient_ = sptr<DCameraHostRecipient>(new DCameraHostRecipient());
69     return CamRetCode::NO_ERROR;
70 }
71 
GetCameraIds(std::vector<std::string> & cameraIds)72 int32_t DCameraHost::GetCameraIds(std::vector<std::string> &cameraIds)
73 {
74     std::lock_guard<std::mutex> autoLock(deviceMapLock_);
75     auto iter = dCameraDeviceMap_.begin();
76     while (iter != dCameraDeviceMap_.end()) {
77         if (!(iter->first).empty()) {
78             cameraIds.push_back(iter->first);
79         }
80         iter++;
81     }
82     return CamRetCode::NO_ERROR;
83 }
84 
GetCameraAbilityFromDev(const std::string & cameraId,std::shared_ptr<CameraAbility> & cameraAbility)85 int32_t DCameraHost::GetCameraAbilityFromDev(const std::string &cameraId, std::shared_ptr<CameraAbility> &cameraAbility)
86 {
87     OHOS::sptr<DCameraDevice> device = nullptr;
88     {
89         std::lock_guard<std::mutex> autoLock(deviceMapLock_);
90         auto iter = dCameraDeviceMap_.find(cameraId);
91         if (iter == dCameraDeviceMap_.end() || iter->second == nullptr) {
92             DHLOGE("DCameraHost::Get Cameradevice failed");
93             return CamRetCode::INVALID_ARGUMENT;
94         } else {
95             device = iter->second;
96         }
97     }
98     if (device->GetDCameraAbility(cameraAbility) != CamRetCode::NO_ERROR) {
99         DHLOGE("DCameraHost::GetCameraAbility, GetDCameraAbility failed.");
100         return CamRetCode::INVALID_ARGUMENT;
101     }
102     return CamRetCode::NO_ERROR;
103 }
104 
GetCameraAbility(const std::string & cameraId,std::vector<uint8_t> & cameraAbility)105 int32_t DCameraHost::GetCameraAbility(const std::string &cameraId, std::vector<uint8_t> &cameraAbility)
106 {
107     if (IsCameraIdInvalid(cameraId)) {
108         DHLOGE("DCameraHost::GetCameraAbility, input cameraId is invalid.");
109         return CamRetCode::INVALID_ARGUMENT;
110     }
111     DHLOGI("DCameraHost::GetCameraAbility for cameraId: %{public}s", GetAnonyString(cameraId).c_str());
112     std::shared_ptr<CameraAbility> ability;
113     int32_t ret = GetCameraAbilityFromDev(cameraId, ability);
114     if (ret != CamRetCode::NO_ERROR) {
115         DHLOGE("DCameraHost::GetCameraAbility, GetCameraAbilityFromDev failed.");
116         return CamRetCode::INVALID_ARGUMENT;
117     }
118     bool retBool = OHOS::Camera::MetadataUtils::ConvertMetadataToVec(ability, cameraAbility);
119     if (!retBool) {
120         DHLOGE("DCameraHost::GetCameraAbility, ConvertMetadataToVec failed.");
121         return CamRetCode::INVALID_ARGUMENT;
122     }
123     do {
124         camera_metadata_item_t item;
125         constexpr uint32_t WIDTH_OFFSET = 1;
126         constexpr uint32_t HEIGHT_OFFSET = 2;
127         constexpr uint32_t UNIT_LENGTH = 3;
128         ret = OHOS::Camera::FindCameraMetadataItem(ability->get(),
129             OHOS_ABILITY_STREAM_AVAILABLE_BASIC_CONFIGURATIONS, &item);
130         DHLOGI("FindCameraMetadataItem item=%{public}u, count=%{public}u, dataType=%{public}u", item.item,
131             item.count, item.data_type);
132         if (ret != CAM_META_SUCCESS) {
133             DHLOGE("Failed to find stream configuration in camera ability with return code %{public}d", ret);
134             break;
135         }
136         if (item.count % UNIT_LENGTH != 0) {
137             DHLOGE("Invalid stream configuration count: %{public}u", item.count);
138             break;
139         }
140         for (uint32_t index = 0; index < item.count; index += UNIT_LENGTH) {
141             int32_t format = item.data.i32[index];
142             int32_t width = item.data.i32[index + WIDTH_OFFSET];
143             int32_t height = item.data.i32[index + HEIGHT_OFFSET];
144             DHLOGD("format: %{public}d, width: %{public}d, height: %{public}d", format, width, height);
145         }
146     } while (0);
147     return CamRetCode::NO_ERROR;
148 }
149 
150 template<typename Callback, typename Device>
OpenCameraImpl(const std::string & cameraId,const Callback & callbackObj,Device & device)151 int32_t DCameraHost::OpenCameraImpl(const std::string &cameraId, const Callback &callbackObj, Device &device)
152 {
153     if (IsCameraIdInvalid(cameraId) || callbackObj == nullptr) {
154         DHLOGE("OpenCameraImpl, open camera id is invalid or camera device callback is null.");
155         return CamRetCode::INVALID_ARGUMENT;
156     }
157 
158     DHLOGI("OpenCameraImpl for cameraId: %{public}s", GetAnonyString(cameraId).c_str());
159 
160     OHOS::sptr<DCameraDevice> dcameraDevice = nullptr;
161     {
162         std::lock_guard<std::mutex> autoLock(deviceMapLock_);
163         auto iter = dCameraDeviceMap_.find(cameraId);
164         if (iter == dCameraDeviceMap_.end()) {
165             DHLOGE("OpenCameraImpl, dcamera device not found.");
166             return CamRetCode::INSUFFICIENT_RESOURCES;
167         }
168 
169         dcameraDevice = iter->second;
170         if (dcameraDevice == nullptr) {
171             DHLOGE("OpenCameraImpl, dcamera device is null.");
172             return INSUFFICIENT_RESOURCES;
173         }
174     }
175 
176     if (dcameraDevice->IsOpened()) {
177         DHLOGE("OpenCameraImpl, dcamera device %{public}s already opened.", GetAnonyString(cameraId).c_str());
178         return CamRetCode::CAMERA_BUSY;
179     }
180 
181     CamRetCode ret = dcameraDevice->OpenDCamera(callbackObj);
182     if (ret != CamRetCode::NO_ERROR) {
183         DHLOGE("OpenCameraImpl, open camera failed.");
184         return ret;
185     }
186     device = dcameraDevice;
187 
188     DHLOGI("OpenCameraImpl, open camera %{public}s success.", GetAnonyString(cameraId).c_str());
189     return CamRetCode::NO_ERROR;
190 }
191 
OpenCamera(const std::string & cameraId,const sptr<ICameraDeviceCallback> & callbackObj,sptr<HDI::Camera::V1_0::ICameraDevice> & device)192 int32_t DCameraHost::OpenCamera(const std::string &cameraId, const sptr<ICameraDeviceCallback> &callbackObj,
193     sptr<HDI::Camera::V1_0::ICameraDevice> &device)
194 {
195     return OpenCameraImpl(cameraId, callbackObj, device);
196 }
197 
OpenCamera_V1_1(const std::string & cameraId,const sptr<ICameraDeviceCallback> & callbackObj,sptr<HDI::Camera::V1_1::ICameraDevice> & device)198 int32_t DCameraHost::OpenCamera_V1_1(const std::string &cameraId, const sptr<ICameraDeviceCallback> &callbackObj,
199     sptr<HDI::Camera::V1_1::ICameraDevice> &device)
200 {
201     return OpenCameraImpl(cameraId, callbackObj, device);
202 }
203 
OpenCamera_V1_2(const std::string & cameraId,const sptr<ICameraDeviceCallback> & callbackObj,sptr<HDI::Camera::V1_2::ICameraDevice> & device)204 int32_t DCameraHost::OpenCamera_V1_2(const std::string &cameraId, const sptr<ICameraDeviceCallback> &callbackObj,
205     sptr<HDI::Camera::V1_2::ICameraDevice> &device)
206 {
207     return OpenCameraImpl(cameraId, callbackObj, device);
208 }
209 
OpenCamera_V1_3(const std::string & cameraId,const sptr<ICameraDeviceCallback> & callbackObj,sptr<ICameraDevice> & device)210 int32_t DCameraHost::OpenCamera_V1_3(const std::string &cameraId, const sptr<ICameraDeviceCallback> &callbackObj,
211     sptr<ICameraDevice> &device)
212 {
213     return OpenCameraImpl(cameraId, callbackObj, device);
214 }
215 
OpenSecureCamera(const std::string & cameraId,const sptr<ICameraDeviceCallback> & callbackObj,sptr<ICameraDevice> & device)216 int32_t DCameraHost::OpenSecureCamera(const std::string &cameraId, const sptr<ICameraDeviceCallback> &callbackObj,
217     sptr<ICameraDevice> &device)
218 {
219     return OpenCameraImpl(cameraId, callbackObj, device);
220 }
221 
GetResourceCost(const std::string & cameraId,OHOS::HDI::Camera::V1_3::CameraDeviceResourceCost & resourceCost)222 int32_t DCameraHost::GetResourceCost(const std::string &cameraId,
223     OHOS::HDI::Camera::V1_3::CameraDeviceResourceCost &resourceCost)
224 {
225     (void)cameraId;
226     (void)resourceCost;
227     return CamRetCode::METHOD_NOT_SUPPORTED;
228 }
229 
NotifyDeviceStateChangeInfo(int notifyType,int deviceState)230 int32_t DCameraHost::NotifyDeviceStateChangeInfo(int notifyType, int deviceState)
231 {
232     (void)notifyType;
233     (void)deviceState;
234     DHLOGI("DCameraHost::NotifyDeviceStateChangeInfo, distributed camera not support.");
235 
236     return CamRetCode::METHOD_NOT_SUPPORTED;
237 }
238 
SetFlashlight(const std::string & cameraId,bool isEnable)239 int32_t DCameraHost::SetFlashlight(const std::string &cameraId, bool isEnable)
240 {
241     (void)cameraId;
242     (void)isEnable;
243     DHLOGI("DCameraHost::SetFlashlight, distributed camera not support.");
244 
245     return CamRetCode::METHOD_NOT_SUPPORTED;
246 }
247 
SetFlashlight_V1_2(float level)248 int32_t DCameraHost::SetFlashlight_V1_2(float level)
249 {
250     (void)level;
251     DHLOGI("DCameraHost::SetFlashlight_V1_2, distributed camera not support.");
252 
253     return CamRetCode::METHOD_NOT_SUPPORTED;
254 }
255 
PreCameraSwitch(const std::string & cameraId)256 int32_t DCameraHost::PreCameraSwitch(const std::string &cameraId)
257 {
258     (void)cameraId;
259     DHLOGI("DCameraHost::PreCameraSwitch, distributed camera not support.");
260 
261     return CamRetCode::METHOD_NOT_SUPPORTED;
262 }
263 
PrelaunchWithOpMode(const PrelaunchConfig & config,int32_t operationMode)264 int32_t DCameraHost::PrelaunchWithOpMode(const PrelaunchConfig &config, int32_t operationMode)
265 {
266     (void)config;
267     (void)operationMode;
268     DHLOGI("DCameraHost::PrelaunchWithOpMode, distributed camera not support.");
269 
270     return CamRetCode::METHOD_NOT_SUPPORTED;
271 }
272 
Prelaunch(const PrelaunchConfig & config)273 int32_t DCameraHost::Prelaunch(const PrelaunchConfig &config)
274 {
275     (void)config;
276     DHLOGI("DCameraHost::Prelaunch, distributed camera not support.");
277 
278     return CamRetCode::METHOD_NOT_SUPPORTED;
279 }
280 
AddDeviceParamCheck(const DHBase & dhBase,const std::string & sinkAbilityInfo,const std::string & sourceCodecInfo,const sptr<IDCameraProviderCallback> & callback)281 DCamRetCode DCameraHost::AddDeviceParamCheck(const DHBase &dhBase, const std::string& sinkAbilityInfo,
282     const std::string &sourceCodecInfo, const sptr<IDCameraProviderCallback> &callback)
283 {
284     if (IsDhBaseInfoInvalid(dhBase)) {
285         DHLOGE("DCameraHost::AddDCameraDevice, devId or dhId is invalid.");
286         return DCamRetCode::INVALID_ARGUMENT;
287     }
288     DHLOGI("DCameraHost::AddDCameraDevice for {devId: %{public}s, dhId: %{public}s}",
289         GetAnonyString(dhBase.deviceId_).c_str(), GetAnonyString(dhBase.dhId_).c_str());
290 
291     if (sinkAbilityInfo.empty() || sinkAbilityInfo.length() > ABILITYINFO_MAX_LENGTH) {
292         DHLOGE("DCameraHost::AddDCameraDevice, input sinkAbilityInfo is invalid.");
293         return DCamRetCode::INVALID_ARGUMENT;
294     }
295 
296     if (sourceCodecInfo.empty() || sourceCodecInfo.length() > ABILITYINFO_MAX_LENGTH) {
297         DHLOGE("DCameraHost::AddDCameraDevice, input sourceCodecInfo is invalid.");
298         return DCamRetCode::INVALID_ARGUMENT;
299     }
300     if (GetCamDevNum() > MAX_DCAMERAS_NUMBER) {
301         DHLOGE("DCameraHost::AddDCameraDevice, cameras exceed the upper limit.");
302         return DCamRetCode::INVALID_ARGUMENT;
303     }
304     return DCamRetCode::SUCCESS;
305 }
306 
AddDCameraDevice(const DHBase & dhBase,const std::string & sinkAbilityInfo,const std::string & sourceCodecInfo,const sptr<IDCameraProviderCallback> & callback)307 DCamRetCode DCameraHost::AddDCameraDevice(const DHBase &dhBase, const std::string& sinkAbilityInfo,
308     const std::string &sourceCodecInfo, const sptr<IDCameraProviderCallback> &callback)
309 {
310     if (AddDeviceParamCheck(dhBase, sinkAbilityInfo, sourceCodecInfo, callback) != DCamRetCode::SUCCESS) {
311         DHLOGE("DCameraHost::AddDCameraDevice, input param is invalid.");
312         return DCamRetCode::INVALID_ARGUMENT;
313     }
314     std::string dCameraId = dhBase.deviceId_ + "__" + dhBase.dhId_;
315     {
316         std::lock_guard<std::mutex> autoLock(deviceMapLock_);
317         if (dCameraDeviceMap_.find(dCameraId) != dCameraDeviceMap_.end()) {
318             if (dCameraDeviceMap_[dCameraId] == nullptr) {
319                 DHLOGI("AddDCameraDevice device is null");
320                 return DCamRetCode::INVALID_ARGUMENT;
321             }
322             dCameraDeviceMap_[dCameraId]->SetDcameraAbility(sinkAbilityInfo);
323             DHLOGI("AddDCameraDevice refresh data success");
324             return DCamRetCode::SUCCESS;
325         }
326     }
327     OHOS::sptr<DCameraDevice> dcameraDevice(new (std::nothrow) DCameraDevice(dhBase, sinkAbilityInfo,
328         sourceCodecInfo));
329     if (dcameraDevice == nullptr) {
330         DHLOGE("DCameraHost::AddDCameraDevice, create dcamera device failed.");
331         return DCamRetCode::INVALID_ARGUMENT;
332     }
333     {
334         std::lock_guard<std::mutex> autoLock(deviceMapLock_);
335         dCameraDeviceMap_[dCameraId] = dcameraDevice;
336     }
337     if (callback == nullptr) {
338         DHLOGE("DCameraHost::SetProviderCallback failed, callback is null");
339         return DCamRetCode::INVALID_ARGUMENT;
340     }
341     dcameraDevice->SetProviderCallback(callback);
342     if (dCameraHostCallback_ != nullptr) {
343         dCameraHostCallback_->OnCameraEvent(dCameraId, CameraEvent::CAMERA_EVENT_DEVICE_ADD);
344     }
345     if (dCameraHostCallback_V1_2_ != nullptr) {
346         dCameraHostCallback_V1_2_->OnCameraEvent(dCameraId, CameraEvent::CAMERA_EVENT_DEVICE_ADD);
347     }
348     sptr<IRemoteObject> remote = OHOS::HDI::hdi_objcast<IDCameraProviderCallback>(callback);
349     if (remote != nullptr) {
350         remote->AddDeathRecipient(dCameraHostRecipient_);
351     }
352     DHLOGI("AddDCameraDevice create dcamera device success, dCameraId: %{public}s", GetAnonyString(dCameraId).c_str());
353     return DCamRetCode::SUCCESS;
354 }
355 
GetCamDevNum()356 size_t DCameraHost::GetCamDevNum()
357 {
358     std::lock_guard<std::mutex> autoLock(deviceMapLock_);
359     return dCameraDeviceMap_.size();
360 }
361 
RemoveDCameraDevice(const DHBase & dhBase)362 DCamRetCode DCameraHost::RemoveDCameraDevice(const DHBase &dhBase)
363 {
364     DHLOGI("DCameraHost::RemoveDCameraDevice for {devId: %{public}s, dhId: %{public}s}",
365         GetAnonyString(dhBase.deviceId_).c_str(), GetAnonyString(dhBase.dhId_).c_str());
366 
367     std::string dCameraId = GetCameraIdByDHBase(dhBase);
368     if (dCameraId.empty()) {
369         DHLOGE("DCameraHost::RemoveDCameraDevice, dhBase not exist.");
370         return DCamRetCode::INVALID_ARGUMENT;
371     }
372 
373     OHOS::sptr<DCameraDevice> dcameraDevice = GetDCameraDeviceByDHBase(dhBase);
374     if (dcameraDevice != nullptr) {
375         if (dcameraDevice->IsOpened()) {
376             dcameraDevice->Close();
377         }
378         dcameraDevice->SetProviderCallback(nullptr);
379         sptr<IDCameraProviderCallback> callback = dcameraDevice->GetProviderCallback();
380         if (callback != nullptr) {
381             sptr<IRemoteObject> remoteObj = OHOS::HDI::hdi_objcast<IDCameraProviderCallback>(callback);
382             if (remoteObj != nullptr) {
383                 remoteObj->RemoveDeathRecipient(dCameraHostRecipient_);
384             }
385         }
386     }
387     {
388         std::lock_guard<std::mutex> autoLock(deviceMapLock_);
389         dCameraDeviceMap_.erase(dCameraId);
390     }
391 
392     if (dCameraHostCallback_ != nullptr) {
393         dCameraHostCallback_->OnCameraEvent(dCameraId, CameraEvent::CAMERA_EVENT_DEVICE_RMV);
394     }
395 
396     if (dCameraHostCallback_V1_2_ != nullptr) {
397         dCameraHostCallback_V1_2_->OnCameraEvent(dCameraId, CameraEvent::CAMERA_EVENT_DEVICE_RMV);
398     }
399 
400     DHLOGI("DCameraHost::RemoveDCameraDevice, remove dcamera device success, dCameraId: %{public}s",
401         GetAnonyString(dCameraId).c_str());
402     return DCamRetCode::SUCCESS;
403 }
404 
IsCameraIdInvalid(const std::string & cameraId)405 bool DCameraHost::IsCameraIdInvalid(const std::string &cameraId)
406 {
407     if (cameraId.empty() || cameraId.length() > ID_MAX_SIZE) {
408         return true;
409     }
410 
411     std::lock_guard<std::mutex> autoLock(deviceMapLock_);
412     auto iter = dCameraDeviceMap_.begin();
413     while (iter != dCameraDeviceMap_.end()) {
414         if (cameraId == iter->first) {
415             return false;
416         }
417         iter++;
418     }
419     return true;
420 }
421 
GetCameraIdByDHBase(const DHBase & dhBase)422 std::string DCameraHost::GetCameraIdByDHBase(const DHBase &dhBase)
423 {
424     std::string dcameraId = dhBase.deviceId_ + "__" + dhBase.dhId_;
425     return dcameraId;
426 }
427 
GetDCameraDeviceByDHBase(const DHBase & dhBase)428 OHOS::sptr<DCameraDevice> DCameraHost::GetDCameraDeviceByDHBase(const DHBase &dhBase)
429 {
430     std::string dCameraId = GetCameraIdByDHBase(dhBase);
431     if (dCameraId.empty()) {
432         DHLOGE("DCameraHost::GetDCameraDeviceByDHBase, dhBase not exist.");
433         return nullptr;
434     }
435 
436     std::lock_guard<std::mutex> autoLock(deviceMapLock_);
437     auto iter = dCameraDeviceMap_.find(dCameraId);
438     if (iter == dCameraDeviceMap_.end()) {
439         DHLOGE("DCameraHost::GetDCameraDeviceByDHBase, dcamera device not found.");
440         return nullptr;
441     }
442     return iter->second;
443 }
444 
NotifyDCameraStatus(const DHBase & dhBase,int32_t result)445 void DCameraHost::NotifyDCameraStatus(const DHBase &dhBase, int32_t result)
446 {
447     std::string dCameraId = GetCameraIdByDHBase(dhBase);
448     if (dCameraId.empty()) {
449         DHLOGE("DCameraHost::NotifyDCameraStatus, dhBase not exist.");
450         return;
451     }
452     if (dCameraHostCallback_ != nullptr) {
453         dCameraHostCallback_->OnCameraStatus(dCameraId, CameraStatus::UN_AVAILABLE);
454     }
455     if (dCameraHostCallback_V1_2_ != nullptr) {
456         dCameraHostCallback_V1_2_->OnCameraStatus(dCameraId, CameraStatus::UN_AVAILABLE);
457     }
458 }
459 
OnRemoteDied(const wptr<IRemoteObject> & remote)460 void DCameraHost::DCameraHostRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
461 {
462     DHLOGE("Exit the current process.");
463     _Exit(0);
464 }
465 } // namespace DistributedHardware
466 } // namespace OHOS
467