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