1 /*
2 * Copyright (c) 2025 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 "adapter/ohos/entrance/event_pass_through_subscriber.h"
17
18 namespace OHOS::Ace {
19 namespace {
20 constexpr int32_t PUBLISHER_UID = 7800;
21 const std::string TOUCH_EVENTS_PASS_THROUGH = "touch.events.pass.through";
22 const std::string GAME_INFO_TO_GAME_RESAMPLE = "touch.events.game.resample";
23 const std::string TOUCH_EVENTS_UEGAME_START = "touch.events.uegame.start";
24 } // namespace
25
SubscribeEvent(int32_t instanceId)26 void EventPassThroughSubscribeProxy::SubscribeEvent(int32_t instanceId)
27 {
28 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "Subscribe touch.events.pass.through Event");
29 std::lock_guard<std::mutex> lock(mutex_);
30 if (eventPassThroughReceiver_ == nullptr) {
31 // create subscribe info
32 MatchingSkills matchingSkills;
33 // add common events
34 matchingSkills.AddEvent(TOUCH_EVENTS_PASS_THROUGH);
35 matchingSkills.AddEvent(GAME_INFO_TO_GAME_RESAMPLE);
36 matchingSkills.AddEvent(TOUCH_EVENTS_UEGAME_START);
37 CommonEventSubscribeInfo subscribeInfo(matchingSkills);
38 subscribeInfo.SetPublisherUid(PUBLISHER_UID);
39 subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::ThreadMode::HANDLER);
40
41 // init Receiver
42 eventPassThroughReceiver_ = std::make_shared<EventPassThroughSubscriber>(subscribeInfo);
43 eventPassThroughReceiver_->AddInstanceId(instanceId);
44 eventReceiver_ = std::shared_ptr<CommonEventSubscriber>(eventPassThroughReceiver_);
45
46 // create subscription
47 CommonEventManager::SubscribeCommonEvent(eventReceiver_);
48 } else {
49 eventPassThroughReceiver_->AddInstanceId(instanceId);
50 }
51 }
52
UnSubscribeEvent()53 void EventPassThroughSubscribeProxy::UnSubscribeEvent()
54 {
55 std::lock_guard<std::mutex> lock(mutex_);
56 if (eventReceiver_ != nullptr) {
57 CommonEventManager::UnSubscribeCommonEvent(eventReceiver_);
58 eventReceiver_ = nullptr;
59 eventPassThroughReceiver_ = nullptr;
60 }
61 }
62
UnSubscribeEvent(int32_t instanceId)63 void EventPassThroughSubscribeProxy::UnSubscribeEvent(int32_t instanceId)
64 {
65 std::lock_guard<std::mutex> lock(mutex_);
66 if (eventReceiver_ != nullptr) {
67 if (eventPassThroughReceiver_->EraseContainerAddCheckUnSubscribe(instanceId)) {
68 CommonEventManager::UnSubscribeCommonEvent(eventReceiver_);
69 eventReceiver_ = nullptr;
70 eventPassThroughReceiver_ = nullptr;
71 }
72 }
73 }
74
OnReceiveEvent(const CommonEventData & data)75 void EventPassThroughSubscriber::OnReceiveEvent(const CommonEventData& data)
76 {
77 auto want = data.GetWant();
78 std::string action = want.GetAction();
79 std::string bundleName = want.GetBundle();
80 if (bundleName.empty()) {
81 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "OnReceiveEvent empty bundleName");
82 return;
83 }
84 bool needPassThrough = false;
85 {
86 std::lock_guard<std::mutex> lock(instanceMapMutex_);
87 for (const auto& instanceId : instanceMap_) {
88 auto container = Platform::AceContainer::GetContainer(instanceId);
89 if (!container) {
90 continue;
91 }
92 if (container->GetBundleName() == bundleName) {
93 needPassThrough = true;
94 break;
95 }
96 }
97 }
98 if (!needPassThrough) {
99 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "OnReceiveEvent no matched bundleName");
100 return;
101 }
102
103 if (action == TOUCH_EVENTS_UEGAME_START) {
104 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "OnReceiveEvent %{public}s", action.c_str());
105 AceApplicationInfo::GetInstance().SetTouchPadIdChanged(true);
106 return;
107 }
108 if (action != TOUCH_EVENTS_PASS_THROUGH && action != GAME_INFO_TO_GAME_RESAMPLE) {
109 return;
110 }
111 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "OnReceiveEvent %{public}s", action.c_str());
112 TouchPassMode mode =
113 (action == TOUCH_EVENTS_PASS_THROUGH) ? TouchPassMode::PASS_THROUGH : TouchPassMode::ACCELERATE;
114 AceApplicationInfo::GetInstance().SetTouchEventPassMode(mode);
115 {
116 std::lock_guard<std::mutex> lock(instanceMapMutex_);
117 for (const auto& instanceId : instanceMap_) {
118 auto container = Platform::AceContainer::GetContainer(instanceId);
119 if (!container) {
120 continue;
121 }
122 auto taskExecutor = container->GetTaskExecutor();
123 CHECK_NULL_VOID(taskExecutor);
124 taskExecutor->PostTask(
125 [mode, instanceId]() {
126 auto container = Platform::AceContainer::GetContainer(instanceId);
127 CHECK_NULL_VOID(container);
128 auto pipeline = container->GetPipelineContext();
129 CHECK_NULL_VOID(pipeline);
130 if (mode == TouchPassMode::PASS_THROUGH) {
131 pipeline->SetTouchPassThrough(true);
132 pipeline->SetTouchAccelarate(false);
133 } else {
134 pipeline->SetTouchAccelarate(true);
135 pipeline->SetTouchPassThrough(false);
136 }
137 },
138 TaskExecutor::TaskType::UI, "ArkUIReceiveEventsPassThroughAsync");
139 }
140 }
141 }
142
AddInstanceId(int32_t instanceId)143 void EventPassThroughSubscriber::AddInstanceId(int32_t instanceId)
144 {
145 std::lock_guard<std::mutex> lock(instanceMapMutex_);
146 instanceMap_.emplace(instanceId);
147 }
148
EraseContainerAddCheckUnSubscribe(int32_t instanceId)149 bool EventPassThroughSubscriber::EraseContainerAddCheckUnSubscribe(int32_t instanceId)
150 {
151 std::lock_guard<std::mutex> lock(instanceMapMutex_);
152 instanceMap_.erase(instanceId);
153 return instanceMap_.empty();
154 }
155 } // namespace OHOS::Ace
156