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 #ifndef CAMERA_PICKER_NAPI_H 17 #define CAMERA_PICKER_NAPI_H 18 19 #include <atomic> 20 #include <memory> 21 #include <stdint.h> 22 #include <utility> 23 24 #include "ability_context.h" 25 #include "camera_device.h" 26 #include "camera_napi_utils.h" 27 #include "context.h" 28 #include "ui_content.h" 29 #include "ui_extension_ability/ui_extension_context.h" 30 31 namespace OHOS { 32 namespace CameraStandard { 33 34 typedef struct { 35 std::string saveUri; 36 CameraPosition cameraPosition; 37 int videoDuration; 38 } PickerProfile; 39 40 enum class PickerContextType : uint32_t { UNKNOWN, UI_EXTENSION, ABILITY }; 41 struct PickerContextProxy { PickerContextProxyPickerContextProxy42 PickerContextProxy(std::shared_ptr<AbilityRuntime::Context> context) : mContext_(context) 43 { 44 if (AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context) != nullptr) { 45 type_ = PickerContextType::UI_EXTENSION; 46 } else if (AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context) != nullptr) { 47 type_ = PickerContextType::ABILITY; 48 } else { 49 type_ = PickerContextType::UNKNOWN; 50 } 51 } 52 GetTypePickerContextProxy53 PickerContextType GetType() 54 { 55 return type_; 56 } 57 GetBundleNamePickerContextProxy58 std::string GetBundleName() 59 { 60 auto context = mContext_.lock(); 61 if (context != nullptr) { 62 return context->GetBundleName(); 63 } 64 return ""; 65 } 66 GetUIContentPickerContextProxy67 Ace::UIContent* GetUIContent() 68 { 69 auto context = mContext_.lock(); 70 if (context == nullptr) { 71 return nullptr; 72 } 73 switch (type_) { 74 case PickerContextType::UI_EXTENSION: { 75 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context); 76 if (ctx != nullptr) { 77 return ctx->GetUIContent(); 78 } 79 break; 80 } 81 case PickerContextType::ABILITY: { 82 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context); 83 if (ctx != nullptr) { 84 return ctx->GetUIContent(); 85 } 86 break; 87 } 88 default: 89 // Do nothing 90 break; 91 } 92 return nullptr; 93 } 94 StartAbilityForResultPickerContextProxy95 ErrCode StartAbilityForResult(const AAFwk::Want& want, int requestCode, AbilityRuntime::RuntimeTask&& task) 96 { 97 auto context = mContext_.lock(); 98 if (context == nullptr) { 99 return ERR_INVALID_OPERATION; 100 } 101 switch (type_) { 102 case PickerContextType::UI_EXTENSION: { 103 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context); 104 if (ctx != nullptr) { 105 return ctx->StartAbilityForResult(want, requestCode, std::move(task)); 106 } 107 break; 108 } 109 case PickerContextType::ABILITY: { 110 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context); 111 if (ctx != nullptr) { 112 return ctx->StartAbilityForResult(want, requestCode, std::move(task)); 113 } 114 break; 115 } 116 default: 117 // Do nothing 118 break; 119 } 120 return ERR_INVALID_OPERATION; 121 } 122 123 private: 124 std::weak_ptr<AbilityRuntime::Context> mContext_; 125 PickerContextType type_ = PickerContextType::UNKNOWN; 126 }; 127 128 enum class PickerMediaType : uint32_t { PHOTO, VIDEO }; 129 130 class UIExtensionCallback { 131 public: 132 explicit UIExtensionCallback(std::shared_ptr<PickerContextProxy> contextProxy); 133 void OnRelease(int32_t releaseCode); 134 void OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result); 135 void OnReceive(const OHOS::AAFwk::WantParams& request); 136 void OnError(int32_t code, const std::string& name, const std::string& message); 137 void OnRemoteReady(const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy); 138 void OnDestroy(); 139 void CloseWindow(); 140 SetSessionId(int32_t sessionId)141 inline void SetSessionId(int32_t sessionId) 142 { 143 sessionId_ = sessionId; 144 } 145 WaitResultLock()146 inline void WaitResultLock() 147 { 148 std::unique_lock<std::mutex> lock(cbMutex_); 149 while (!isCallbackReturned_) { 150 cbFinishCondition_.wait(lock); 151 } 152 } 153 NotifyResultLock()154 inline void NotifyResultLock() 155 { 156 std::unique_lock<std::mutex> lock(cbMutex_); 157 cbFinishCondition_.notify_one(); 158 } 159 GetResultCode()160 inline int32_t GetResultCode() 161 { 162 return resultCode_; 163 } 164 GetResultUri()165 inline std::string GetResultUri() 166 { 167 return resultUri_; 168 } 169 GetResultMediaType()170 inline std::string GetResultMediaType() 171 { 172 if (resultMode_ == "VIDEO") { 173 return "video"; 174 } 175 return "photo"; 176 } 177 178 private: 179 bool FinishPicker(int32_t code); 180 int32_t sessionId_ = 0; 181 int32_t resultCode_ = 0; 182 std::string resultUri_ = ""; 183 std::string resultMode_ = ""; 184 std::shared_ptr<PickerContextProxy> contextProxy_; 185 std::condition_variable cbFinishCondition_; 186 std::mutex cbMutex_; 187 bool isCallbackReturned_ = false; 188 }; 189 190 class CameraPickerNapi { 191 public: 192 static napi_value Init(napi_env env, napi_value exports); 193 static napi_value CreatePickerMediaType(napi_env env); 194 static napi_value CreatePickerProfile(napi_env env); 195 static napi_value CreatePickerResult(napi_env env); 196 197 static napi_value Pick(napi_env env, napi_callback_info info); 198 199 static napi_value CameraPickerNapiConstructor(napi_env env, napi_callback_info info); 200 static void CameraPickerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint); 201 CameraPickerNapi(); 202 ~CameraPickerNapi(); 203 204 private: 205 napi_env env_; 206 static thread_local uint32_t cameraPickerTaskId; 207 static thread_local napi_ref sConstructor_; 208 static thread_local napi_ref mediaTypeRef_; 209 }; 210 211 struct CameraPickerAsyncContext : public AsyncContext { 212 std::string resultUri; 213 std::string errorMsg; 214 PickerProfile pickerProfile; 215 AAFwk::Want want; 216 std::shared_ptr<PickerContextProxy> contextProxy; 217 std::shared_ptr<UIExtensionCallback> uiExtCallback; 218 int32_t resultCode; 219 bool bRetBool; 220 }; 221 } // namespace CameraStandard 222 } // namespace OHOS 223 224 #endif /* CAMERA_PICKER_NAPI_H */ 225