1 /* 2 * Copyright (c) 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 #ifndef CAMERA_PICKER_IMPL_H 17 #define CAMERA_PICKER_IMPL_H 18 19 #include <cstdint> 20 #include <memory> 21 #include <mutex> 22 #include <type_traits> 23 #include <unordered_map> 24 #include <unordered_set> 25 26 #include "ability_context.h" 27 #include "camera_device.h" 28 #include "camera_log.h" 29 #include "cj_common_ffi.h" 30 #include "ffi_remote_data.h" 31 #include "ui_content.h" 32 #include "ui_extension_base/ui_extension_context.h" 33 34 namespace OHOS { 35 namespace CameraStandard { 36 37 struct CJPickerResult { 38 int32_t resultCode; 39 char *resultUri; 40 int32_t mediaType; 41 }; 42 43 struct CJPickerProfile { 44 int32_t cameraPosition; 45 char *saveUri; 46 int32_t videoDuration; 47 }; 48 49 typedef struct { 50 std::string saveUri; 51 CameraPosition cameraPosition; 52 int videoDuration; 53 } PickerProfile; 54 55 void Pick(OHOS::AbilityRuntime::Context *context, CArrI32 pickerMediaTypes, CJPickerProfile pickerProfile, 56 int64_t callbackId); 57 58 enum class PickerContextType : uint32_t { UNKNOWN, UI_EXTENSION, ABILITY }; 59 struct PickerContextProxy { PickerContextProxyPickerContextProxy60 PickerContextProxy(std::shared_ptr<AbilityRuntime::Context> context) : mContext_(context) 61 { 62 if (AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context) != nullptr) { 63 type_ = PickerContextType::UI_EXTENSION; 64 } else if (AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context) != nullptr) { 65 type_ = PickerContextType::ABILITY; 66 } else { 67 type_ = PickerContextType::UNKNOWN; 68 } 69 } 70 GetTypePickerContextProxy71 PickerContextType GetType() 72 { 73 return type_; 74 } 75 GetBundleNamePickerContextProxy76 std::string GetBundleName() 77 { 78 auto context = mContext_.lock(); 79 if (context != nullptr) { 80 return context->GetBundleName(); 81 } 82 return ""; 83 } 84 GetUIContentPickerContextProxy85 Ace::UIContent *GetUIContent() 86 { 87 auto context = mContext_.lock(); 88 if (context == nullptr) { 89 return nullptr; 90 } 91 switch (type_) { 92 case PickerContextType::UI_EXTENSION: { 93 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context); 94 if (ctx != nullptr) { 95 return ctx->GetUIContent(); 96 } 97 break; 98 } 99 case PickerContextType::ABILITY: { 100 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context); 101 if (ctx != nullptr) { 102 return ctx->GetUIContent(); 103 } 104 break; 105 } 106 default: 107 // Do nothing 108 break; 109 } 110 return nullptr; 111 } 112 StartAbilityForResultPickerContextProxy113 ErrCode StartAbilityForResult(const AAFwk::Want &want, int requestCode, AbilityRuntime::RuntimeTask &&task) 114 { 115 auto context = mContext_.lock(); 116 if (context == nullptr) { 117 return ERR_INVALID_OPERATION; 118 } 119 switch (type_) { 120 case PickerContextType::UI_EXTENSION: { 121 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context); 122 if (ctx != nullptr) { 123 return ctx->StartAbilityForResult(want, requestCode, std::move(task)); 124 } 125 break; 126 } 127 case PickerContextType::ABILITY: { 128 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context); 129 if (ctx != nullptr) { 130 return ctx->StartAbilityForResult(want, requestCode, std::move(task)); 131 } 132 break; 133 } 134 default: 135 break; 136 } 137 return ERR_INVALID_OPERATION; 138 } 139 140 private: 141 std::weak_ptr<AbilityRuntime::Context> mContext_; 142 PickerContextType type_ = PickerContextType::UNKNOWN; 143 }; 144 145 enum class PickerMediaType : uint32_t { PHOTO, VIDEO }; 146 147 class UIExtensionCallback { 148 public: 149 explicit UIExtensionCallback(std::shared_ptr<PickerContextProxy> contextProxy); 150 void OnRelease(int32_t releaseCode); 151 void OnResult(int32_t resultCode, const OHOS::AAFwk::Want &result); 152 void OnReceive(const OHOS::AAFwk::WantParams &request); 153 void OnError(int32_t code, const std::string &name, const std::string &message); 154 void OnRemoteReady(const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy> &uiProxy); 155 void OnDestroy(); 156 void CloseWindow(); 157 SetSessionId(int32_t sessionId)158 inline void SetSessionId(int32_t sessionId) 159 { 160 sessionId_ = sessionId; 161 } 162 WaitResultLock()163 inline void WaitResultLock() 164 { 165 std::unique_lock<std::mutex> lock(cbMutex_); 166 while (!isCallbackReturned_) { 167 cbFinishCondition_.wait(lock); 168 } 169 } 170 NotifyResultLock()171 inline void NotifyResultLock() 172 { 173 std::unique_lock<std::mutex> lock(cbMutex_); 174 cbFinishCondition_.notify_one(); 175 } 176 GetResultCode()177 inline int32_t GetResultCode() 178 { 179 return resultCode_; 180 } 181 GetResultUri()182 inline std::string GetResultUri() 183 { 184 return resultUri_; 185 } 186 GetResultMediaType()187 inline std::string GetResultMediaType() 188 { 189 if (resultMode_ == "VIDEO") { 190 return "video"; 191 } 192 return "photo"; 193 } 194 195 private: 196 bool FinishPicker(int32_t code); 197 int32_t sessionId_ = 0; 198 int32_t resultCode_ = 0; 199 std::string resultUri_ = ""; 200 std::string resultMode_ = ""; 201 std::shared_ptr<PickerContextProxy> contextProxy_; 202 std::condition_variable cbFinishCondition_; 203 std::mutex cbMutex_; 204 bool isCallbackReturned_ = false; 205 }; 206 } // namespace CameraStandard 207 } // namespace OHOS 208 209 #endif