1 /*
2 * Copyright (C) 2022 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 "accessible_ability_connection.h"
17
18 #include <hitrace_meter.h>
19
20 #include "ability_manager_client.h"
21 #include "accessible_ability_manager_service.h"
22 #include "hilog_wrapper.h"
23 #include "utils.h"
24
25 namespace OHOS {
26 namespace Accessibility {
AccessibleAbilityConnection(int32_t accountId,int32_t connectionId,AccessibilityAbilityInfo & abilityInfo)27 AccessibleAbilityConnection::AccessibleAbilityConnection(int32_t accountId, int32_t connectionId,
28 AccessibilityAbilityInfo &abilityInfo)
29 : accountId_(accountId), connectionId_(connectionId), abilityInfo_(abilityInfo)
30 {
31 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(
32 Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner());
33 }
34
~AccessibleAbilityConnection()35 AccessibleAbilityConnection::~AccessibleAbilityConnection()
36 {
37 HILOG_DEBUG();
38 if (abilityClient_ && abilityClient_->AsObject()) {
39 abilityClient_->AsObject()->RemoveDeathRecipient(deathRecipient_);
40 abilityClient_ = nullptr;
41 }
42 }
43
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t resultCode)44 void AccessibleAbilityConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
45 const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
46 {
47 HILOG_INFO();
48 if (!eventHandler_) {
49 HILOG_ERROR("eventHandler_ is nullptr.");
50 return;
51 }
52
53 eventHandler_->PostTask(std::bind([element, remoteObject, resultCode](int32_t accountId) -> void {
54 HILOG_DEBUG("ResultCode is %{public}d", resultCode);
55 FinishAsyncTrace(HITRACE_TAG_ACCESSIBILITY_MANAGER, "AccessibleAbilityConnect",
56 static_cast<int32_t>(TraceTaskId::ACCESSIBLE_ABILITY_CONNECT));
57 std::string bundleName = element.GetBundleName();
58 std::string abilityName = element.GetAbilityName();
59 auto accountData = Singleton<AccessibleAbilityManagerService>::GetInstance().GetAccountData(accountId);
60 if (!accountData) {
61 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
62 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
63 HILOG_ERROR("accountData is nullptr.");
64 return;
65 }
66
67 if (resultCode != NO_ERROR) {
68 accountData->RemoveEnabledAbility(Utils::GetUri(element));
69 accountData->RemoveConnectingA11yAbility(Utils::GetUri(element));
70 accountData->UpdateAbilities();
71 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
72 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
73 return;
74 }
75
76 if (!remoteObject) {
77 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
78 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
79 HILOG_ERROR("AccessibleAbilityConnection::OnAbilityConnectDone get remoteObject failed");
80 return;
81 }
82
83 sptr<AccessibleAbilityConnection> connection = accountData->GetConnectingA11yAbility(Utils::GetUri(element));
84 if (!connection) {
85 HILOG_ERROR("connection is nullptr");
86 return;
87 }
88
89 accountData->AddConnectedAbility(connection);
90 accountData->RemoveConnectingA11yAbility(Utils::GetUri(element));
91 Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
92 connection->InitAbilityClient(remoteObject);
93 accountData->UpdateEnableAbilityListsState();
94 }, accountId_), "OnAbilityConnectDone");
95 }
96
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int32_t resultCode)97 void AccessibleAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode)
98 {
99 HILOG_INFO("resultCode[%{public}d]", resultCode);
100 }
101
OnAccessibilityEvent(AccessibilityEventInfo & eventInfo)102 void AccessibleAbilityConnection::OnAccessibilityEvent(AccessibilityEventInfo &eventInfo)
103 {
104 HILOG_DEBUG();
105 if (!abilityClient_) {
106 HILOG_ERROR("OnAccessibilityEvent failed");
107 return;
108 }
109
110 std::vector<std::string> filterBundleNames = abilityInfo_.GetFilterBundleNames();
111 if (IsWantedEvent(eventInfo.GetEventType()) && (filterBundleNames.empty() || find(filterBundleNames.begin(),
112 filterBundleNames.end(), eventInfo.GetBundleName()) != filterBundleNames.end())) {
113 abilityClient_->OnAccessibilityEvent(eventInfo);
114 HILOG_DEBUG("windowId[%{public}d] evtType[%{public}d] windowChangeType[%{public}d] GestureId[%{public}d]",
115 eventInfo.GetWindowId(), eventInfo.GetEventType(), eventInfo.GetWindowChangeTypes(),
116 eventInfo.GetGestureType());
117 }
118 }
119
OnKeyPressEvent(const MMI::KeyEvent & keyEvent,const int32_t sequence)120 bool AccessibleAbilityConnection::OnKeyPressEvent(const MMI::KeyEvent &keyEvent, const int32_t sequence)
121 {
122 if (!abilityClient_) {
123 HILOG_ERROR("OnKeyPressEvent failed");
124 return false;
125 }
126
127 if (!(abilityInfo_.GetCapabilityValues() & Capability::CAPABILITY_KEY_EVENT_OBSERVER)) {
128 HILOG_ERROR("Capability failed");
129 return false;
130 }
131
132 abilityClient_->OnKeyPressEvent(keyEvent, sequence);
133 return true;
134 }
135
SetAbilityInfoTargetBundleName(const std::vector<std::string> & targetBundleNames)136 void AccessibleAbilityConnection::SetAbilityInfoTargetBundleName(const std::vector<std::string> &targetBundleNames)
137 {
138 HILOG_DEBUG();
139 abilityInfo_.SetFilterBundleNames(targetBundleNames);
140 }
141
IsWantedEvent(int32_t eventType)142 bool AccessibleAbilityConnection::IsWantedEvent(int32_t eventType)
143 {
144 uint32_t type = static_cast<uint32_t>(eventType);
145 if ((type & abilityInfo_.GetEventTypes()) != type) {
146 HILOG_DEBUG("EventType(%{public}d) is not wanted", type);
147 return false;
148 }
149 return true;
150 }
151
CreateWant(AppExecFwk::ElementName & element)152 AAFwk::Want CreateWant(AppExecFwk::ElementName& element)
153 {
154 AAFwk::Want want;
155 want.SetElement(element);
156
157 return want;
158 }
159
Disconnect()160 void AccessibleAbilityConnection::Disconnect()
161 {
162 HILOG_DEBUG();
163
164 if (accountId_ == Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountId()) {
165 Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
166 }
167
168 if (!abilityClient_) {
169 HILOG_ERROR("abilityClient is nullptr");
170 return;
171 }
172 abilityClient_->Disconnect(connectionId_);
173
174 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
175 if (!abilityManagerClient) {
176 HILOG_ERROR("abilityManagerClient is nullptr");
177 return;
178 }
179 if (abilityManagerClient->DisconnectAbility(this) != ERR_OK) {
180 HILOG_ERROR("Disconnect failed!");
181 return;
182 }
183 }
184
Connect(const AppExecFwk::ElementName & element)185 void AccessibleAbilityConnection::Connect(const AppExecFwk::ElementName &element)
186 {
187 HILOG_DEBUG();
188 StartAsyncTrace(HITRACE_TAG_ACCESSIBILITY_MANAGER, "AccessibleAbilityConnect",
189 static_cast<int32_t>(TraceTaskId::ACCESSIBLE_ABILITY_CONNECT));
190 std::string bundleName = element.GetBundleName();
191 std::string abilityName = element.GetAbilityName();
192
193 elementName_ = element;
194 HILOG_DEBUG("bundleName[%{public}s], abilityName [%{public}s], accountId [%{public}d]",
195 bundleName.c_str(), abilityName.c_str(), accountId_);
196
197 auto bundleMgr = Singleton<AccessibleAbilityManagerService>::GetInstance().GetBundleMgrProxy();
198 if (!bundleMgr) {
199 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
200 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
201 HILOG_ERROR("get bundleMgr failed");
202 return;
203 }
204 int uid = bundleMgr->GetUidByBundleName(bundleName, accountId_);
205 HILOG_DEBUG("uid is %{public}d ", uid);
206
207 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
208 if (!abilityManagerClient) {
209 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
210 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
211 HILOG_ERROR("abilityManagerClient is nullptr");
212 return;
213 }
214 AAFwk::Want want = CreateWant(elementName_);
215 if (abilityManagerClient->ConnectAbility(want, this, nullptr, uid / UID_MASK) != ERR_OK) {
216 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
217 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
218 HILOG_ERROR("ConnectAbility failed!");
219 return;
220 }
221 }
222
GetChannelId()223 int32_t AccessibleAbilityConnection::GetChannelId()
224 {
225 HILOG_DEBUG("connectionId_ is %{public}d", connectionId_);
226 return connectionId_;
227 }
228
OnAbilityConnectDoneSync(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject)229 void AccessibleAbilityConnection::OnAbilityConnectDoneSync(const AppExecFwk::ElementName &element,
230 const sptr<IRemoteObject> &remoteObject)
231 {
232 HILOG_DEBUG();
233 auto accountData = Singleton<AccessibleAbilityManagerService>::GetInstance().GetAccountData(accountId_);
234 if (!accountData) {
235 HILOG_ERROR("accountData is nullptr.");
236 return;
237 }
238 if (!remoteObject) {
239 HILOG_ERROR("AccessibleAbilityConnection::OnAbilityConnectDone get remoteObject failed");
240 return;
241 }
242 elementName_ = element;
243
244 sptr<AccessibleAbilityConnection> pointer = this;
245 accountData->AddConnectedAbility(pointer);
246 Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
247 InitAbilityClient(remoteObject);
248 }
249
OnAbilityDisconnectDoneSync(const AppExecFwk::ElementName & element)250 void AccessibleAbilityConnection::OnAbilityDisconnectDoneSync(const AppExecFwk::ElementName &element)
251 {
252 HILOG_DEBUG();
253
254 if (accountId_ == Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountId()) {
255 Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
256 }
257
258 if (!abilityClient_) {
259 HILOG_ERROR("abilityClient_ is nullptr");
260 return;
261 }
262 abilityClient_->Disconnect(connectionId_);
263 }
264
InitAbilityClient(const sptr<IRemoteObject> & remoteObject)265 void AccessibleAbilityConnection::InitAbilityClient(const sptr<IRemoteObject> &remoteObject)
266 {
267 std::string bundleName = elementName_.GetBundleName();
268 std::string abilityName = elementName_.GetAbilityName();
269 abilityClient_ = new(std::nothrow) AccessibleAbilityClientProxy(remoteObject);
270 if (!abilityClient_) {
271 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
272 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
273 HILOG_ERROR("abilityClient_ is null");
274 return;
275 }
276
277 if (!deathRecipient_) {
278 deathRecipient_ = new(std::nothrow) AccessibleAbilityConnectionDeathRecipient(
279 accountId_, elementName_, eventHandler_);
280 if (!deathRecipient_) {
281 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
282 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
283 HILOG_ERROR("deathRecipient_ is null");
284 return;
285 }
286 }
287
288 if (!abilityClient_->AsObject() || !abilityClient_->AsObject()->AddDeathRecipient(deathRecipient_)) {
289 HILOG_ERROR("Failed to add death recipient");
290 }
291
292 channel_ = new(std::nothrow) AccessibleAbilityChannel(accountId_, abilityInfo_.GetId());
293 if (!channel_) {
294 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
295 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
296 HILOG_ERROR("channel_ is null");
297 return;
298 }
299 abilityClient_->Init(channel_, connectionId_);
300 }
301
OnRemoteDied(const wptr<IRemoteObject> & remote)302 void AccessibleAbilityConnection::AccessibleAbilityConnectionDeathRecipient::OnRemoteDied(
303 const wptr<IRemoteObject> &remote)
304 {
305 Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
306 A11yError::ERROR_A11Y_APPLICATION_DISCONNECT_ABNORMALLY,
307 recipientElementName_.GetBundleName(), recipientElementName_.GetAbilityName());
308 if (!handler_) {
309 HILOG_ERROR("handler_ is nullptr");
310 return;
311 }
312 std::shared_ptr<AppExecFwk::ElementName> sharedElementName =
313 std::make_shared<AppExecFwk::ElementName>(recipientElementName_);
314 handler_->PostTask(std::bind([](int32_t accountId, std::shared_ptr<AppExecFwk::ElementName> elementName) -> void {
315 HILOG_DEBUG();
316
317 auto &aams = Singleton<AccessibleAbilityManagerService>::GetInstance();
318 auto accountData = aams.GetAccountData(accountId);
319 if (!accountData) {
320 HILOG_ERROR("accountData is null.");
321 return;
322 }
323
324 std::string uri = Utils::GetUri(*elementName);
325 sptr<AccessibleAbilityConnection> connection = accountData->GetAccessibleAbilityConnection(uri);
326 if (!connection) {
327 HILOG_ERROR("There is no connection for %{public}s.", uri.c_str());
328 return;
329 }
330 accountData->RemoveConnectedAbility(*elementName);
331 accountData->RemoveEnabledAbility(uri);
332
333 std::string uiTestUri = Utils::GetUri("ohos.uitest", "uitestability");
334 if (uri == uiTestUri) {
335 accountData->RemoveInstalledAbility("ohos.uitest");
336 }
337
338 accountData->UpdateAbilities();
339 aams.UpdateAccessibilityManagerService();
340 }, accountId_, sharedElementName), "OnRemoteDied");
341 }
342 } // namespace Accessibility
343 } // namespace OHOS