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 FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_UPDATE_CONFIG_MANAGER_H 17 #define FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_UPDATE_CONFIG_MANAGER_H 18 19 #include <mutex> 20 #include <string> 21 #include <thread> 22 23 #include "base/memory/ace_type.h" 24 #include "base/thread/cancelable_callback.h" 25 #include "base/thread/task_executor.h" 26 #include "core/common/container.h" 27 28 namespace OHOS::Ace { 29 template<class T> 30 class UpdateConfigManager : public virtual AceType { 31 DECLARE_ACE_TYPE(UpdateConfigManager<T>, AceType); 32 public: 33 struct UpdateTask { 34 CancelableCallback<void()> updateTask; 35 std::unordered_map<int32_t, CancelableCallback<void()>> promiseTaskMap; 36 T target; 37 }; 38 UpdateConfigSync(const T & config,std::function<void ()> && task)39 void UpdateConfigSync(const T& config, std::function<void()> &&task) 40 { 41 // Update current state 42 { 43 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 44 currentTask_.updateTask.Cancel(); 45 currentTask_.target = config; 46 } 47 48 task(); 49 } 50 UpdateViewConfigTaskDone(int32_t taskId)51 void UpdateViewConfigTaskDone(int32_t taskId) 52 { 53 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 54 currentTask_.promiseTaskMap.erase(taskId); 55 } 56 CancelAllPromiseTaskLocked()57 void CancelAllPromiseTaskLocked() 58 { 59 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 60 for (auto it = currentTask_.promiseTaskMap.begin(); it != currentTask_.promiseTaskMap.end();) { 61 it = it->second.Cancel() ? currentTask_.promiseTaskMap.erase(it) : ++it; 62 } 63 } 64 CancelUselessTaskLocked()65 void CancelUselessTaskLocked() 66 { 67 currentTask_.updateTask.Cancel(); 68 } 69 70 void UpdatePromiseConfig(const T& config, std::function<void()> &&task, const RefPtr<Container>& container, 71 int32_t taskId, const std::string& taskName, TaskExecutor::TaskType type = TaskExecutor::TaskType::PLATFORM) 72 { 73 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 74 CancelUselessTaskLocked(); 75 CancelableCallback<void()> promiseTask(std::move(task)); 76 currentTask_.promiseTaskMap[taskId] = promiseTask; 77 currentTask_.target = config; 78 79 auto taskExecutor = container->GetTaskExecutor(); 80 CHECK_NULL_VOID(taskExecutor); 81 taskExecutor->PostTask(std::move(promiseTask), type, taskName); 82 } 83 84 void UpdateConfig(const T& config, std::function<void()> &&task, const RefPtr<Container>& container, 85 const std::string& taskName, TaskExecutor::TaskType type = TaskExecutor::TaskType::PLATFORM) 86 { 87 CancelableCallback<void()> cancelableTask(std::move(task)); 88 89 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 90 if (config == currentTask_.target) { 91 // If config is same as current/next state, return directely. 92 return; 93 } else { 94 // Try to cancel useless task. 95 CancelUselessTaskLocked(); 96 // Post new task. 97 PostUpdateConfigTaskLocked(config, std::move(cancelableTask), container, taskName, type); 98 } 99 } 100 StoreConfig(T & config)101 void StoreConfig(T& config) 102 { 103 aceConfig_ = config; 104 } 105 IsConfigsEqual(const ViewportConfig & other)106 bool IsConfigsEqual(const ViewportConfig& other) 107 { 108 return aceConfig_.config_ == other; 109 } 110 StoreInfo(const sptr<OHOS::Rosen::OccupiedAreaChangeInfo> & info)111 void StoreInfo(const sptr<OHOS::Rosen::OccupiedAreaChangeInfo>& info) 112 { 113 info_ = info; 114 } 115 IsInfoEqual(const sptr<OHOS::Rosen::OccupiedAreaChangeInfo> & info)116 bool IsInfoEqual(const sptr<OHOS::Rosen::OccupiedAreaChangeInfo>& info) 117 { 118 if (!info_) { 119 if (info) { 120 return false; 121 } 122 return true; 123 } 124 if (!info) { 125 return false; 126 } 127 auto rect_ = info_->rect_; 128 auto rect = info->rect_; 129 if (info_->textFieldPositionY_ != info->textFieldPositionY_) { 130 return false; 131 } 132 if (info_->textFieldHeight_ != info->textFieldHeight_) { 133 return false; 134 } 135 if (rect_.posX_ != rect.posX_ || rect_.posY_ != rect.posY_ || 136 rect_.width_ != rect.width_ || rect_.height_ != rect.height_) { 137 return false; 138 } 139 return true; 140 } 141 MakeTaskId()142 int32_t MakeTaskId() 143 { 144 return nextTaskId_.fetch_add(1); 145 } 146 private: PostUpdateConfigTaskLocked(const T & config,CancelableCallback<void ()> && task,const RefPtr<Container> & container,const std::string & taskName,TaskExecutor::TaskType type)147 void PostUpdateConfigTaskLocked(const T& config, CancelableCallback<void()> &&task, 148 const RefPtr<Container>& container, const std::string& taskName, TaskExecutor::TaskType type) 149 { 150 currentTask_ = { 151 .updateTask = std::move(task), 152 .target = config, 153 }; 154 auto taskExecutor = container->GetTaskExecutor(); 155 CHECK_NULL_VOID(taskExecutor); 156 taskExecutor->PostTask(currentTask_.updateTask, type, taskName); 157 } 158 159 std::mutex updateTaskMutex_; 160 161 UpdateTask currentTask_; 162 163 std::atomic<int32_t> nextTaskId_ = 0; 164 165 T aceConfig_; 166 167 sptr<OHOS::Rosen::OccupiedAreaChangeInfo> info_ = nullptr; 168 }; 169 } // OHOS::Ace 170 #endif // FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_UPDATE_CONFIG_MANAGER_H 171