1 /*
2 * Copyright (c) 2021-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 <sstream>
17 #include <unistd.h>
18 #include <regex.h>
19 #include <cstdio>
20 #include <cstdlib>
21 #include "ui_driver.h"
22 #include "widget_operator.h"
23 #include "window_operator.h"
24 #include "ui_controller.h"
25 #include "frontend_api_handler.h"
26
27 namespace OHOS::uitest {
28 using namespace std;
29 using namespace nlohmann;
30 using namespace nlohmann::detail;
31
32 class UIEventObserver : public BackendClass {
33 public:
UIEventObserver()34 UIEventObserver() {};
GetFrontendClassDef() const35 const FrontEndClassDef &GetFrontendClassDef() const override
36 {
37 return UI_EVENT_OBSERVER_DEF;
38 };
39 };
40
41 class UiEventFowarder : public UiEventListener {
42 public:
UiEventFowarder()43 UiEventFowarder() {};
44
IncRef(const string & ref)45 void IncRef(const string &ref)
46 {
47 auto find = refCountMap_.find(ref);
48 if (find != refCountMap_.end()) {
49 find->second++;
50 } else {
51 refCountMap_.insert(make_pair(ref, 1));
52 }
53 }
54
DecAndGetRef(const string & ref)55 uint32_t DecAndGetRef(const string &ref)
56 {
57 auto find = refCountMap_.find(ref);
58 if (find != refCountMap_.end()) {
59 find->second--;
60 if (find->second == 0) {
61 refCountMap_.erase(find);
62 return 0;
63 }
64 return find->second;
65 }
66 return 0;
67 }
68
OnEvent(const std::string & event,const UiEventSourceInfo & source)69 void OnEvent(const std::string &event, const UiEventSourceInfo &source) override
70 {
71 const auto &server = FrontendApiServer::Get();
72 json uiElementInfo;
73 uiElementInfo["bundleName"] = source.bundleName;
74 uiElementInfo["type"] = source.type;
75 uiElementInfo["text"] = source.text;
76 auto count = callBackInfos_.count(event);
77 size_t index = 0;
78 while (index < count) {
79 auto find = callBackInfos_.find(event);
80 if (find == callBackInfos_.end()) {
81 return;
82 }
83 const auto &observerRef = find->second.first;
84 const auto &callbackRef = find->second.second;
85 ApiCallInfo in;
86 ApiReplyInfo out;
87 in.apiId_ = "UIEventObserver.once";
88 in.callerObjRef_ = observerRef;
89 in.paramList_.push_back(uiElementInfo);
90 in.paramList_.push_back(callbackRef);
91 in.paramList_.push_back(DecAndGetRef(observerRef) == 0);
92 in.paramList_.push_back(DecAndGetRef(callbackRef) == 0);
93 server.Callback(in, out);
94 callBackInfos_.erase(find);
95 index++;
96 }
97 }
98
AddCallbackInfo(const string && event,const string & observerRef,const string && cbRef)99 void AddCallbackInfo(const string &&event, const string &observerRef, const string &&cbRef)
100 {
101 auto count = callBackInfos_.count(event);
102 auto find = callBackInfos_.find(event);
103 for (size_t index = 0; index < count; index++) {
104 if (find != callBackInfos_.end()) {
105 if (find->second.first == observerRef && find->second.second == cbRef) {
106 return;
107 }
108 find++;
109 }
110 }
111 callBackInfos_.insert(make_pair(event, make_pair(observerRef, cbRef)));
112 IncRef(observerRef);
113 IncRef(cbRef);
114 }
115
116 private:
117 multimap<string, pair<string, string>> callBackInfos_;
118 map<string, int> refCountMap_;
119 };
120
121 struct ApiMethod {
122 string_view apiId_ = "";
123 vector<string> paramTypes_;
124 size_t defaultArgCount_ = 0;
125 bool convertError_ = false;
126 };
127 /** API argument type list map.*/
128 static multimap<string, ApiMethod> sApiArgTypesMap;
129
ParseMethodSignature(string_view signature,vector<string> & types,size_t & defArg)130 static void ParseMethodSignature(string_view signature, vector<string> &types, size_t &defArg)
131 {
132 int charIndex = 0;
133 constexpr size_t BUF_LEN = 32;
134 char buf[BUF_LEN];
135 size_t tokenLen = 0;
136 size_t defArgCount = 0;
137 string token;
138 for (char ch : signature) {
139 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
140 buf[tokenLen++] = ch;
141 } else if (ch == '?') {
142 defArgCount++;
143 } else if (ch == ',' || ch == '?' || ch == ')') {
144 if (tokenLen > 0) {
145 token = string_view(buf, tokenLen);
146 DCHECK(find(DATA_TYPE_SCOPE.begin(), DATA_TYPE_SCOPE.end(), token) != DATA_TYPE_SCOPE.end());
147 types.emplace_back(token);
148 }
149 tokenLen = 0; // consume token and reset buffer
150 if (ch == ')') {
151 // add return value type to the end of types.
152 string retType = string(signature.substr(charIndex + 2));
153 types.emplace_back(retType);
154 break; // end parsing
155 }
156 }
157 charIndex++;
158 }
159 defArg = defArgCount;
160 }
161
162 /** Parse frontend method definitions to collect type information.*/
ParseFrontendMethodsSignature()163 static void ParseFrontendMethodsSignature()
164 {
165 for (auto classDef : FRONTEND_CLASS_DEFS) {
166 LOG_D("parse class %{public}s", string(classDef->name_).c_str());
167 if (classDef->methods_ == nullptr || classDef->methodCount_ <= 0) {
168 continue;
169 }
170 for (size_t idx = 0; idx < classDef->methodCount_; idx++) {
171 auto methodDef = classDef->methods_[idx];
172 auto paramTypes = vector<string>();
173 size_t hasDefaultArg = 0;
174 ParseMethodSignature(methodDef.signature_, paramTypes, hasDefaultArg);
175 ApiMethod method {methodDef.name_, paramTypes, hasDefaultArg, methodDef.convertError_};
176 sApiArgTypesMap.insert(make_pair(string(methodDef.name_), method));
177 }
178 }
179 }
180
ParseExtensionMethodsSignature()181 static void ParseExtensionMethodsSignature()
182 {
183 auto paramTypesForGetAllProperties = vector<string>();
184 paramTypesForGetAllProperties.push_back("");
185 string getAllProperties = "Component.getAllProperties";
186 ApiMethod methodForGetAllProperties{getAllProperties, paramTypesForGetAllProperties, 0, false};
187 sApiArgTypesMap.insert(make_pair(getAllProperties, methodForGetAllProperties));
188
189 auto paramTypesForAamsWorkMode = vector<string>();
190 paramTypesForAamsWorkMode.push_back("int");
191 paramTypesForAamsWorkMode.push_back("");
192 string setAamsWorkMode = "Driver.SetAamsWorkMode";
193 ApiMethod methodForAamsWorkMode {setAamsWorkMode, paramTypesForAamsWorkMode, 0, false};
194 sApiArgTypesMap.insert(make_pair(setAamsWorkMode, methodForAamsWorkMode));
195
196 auto paramTypesForCloseAamsEvent = vector<string>();
197 paramTypesForCloseAamsEvent.push_back("");
198 string closeAamsEvent = "Driver.CloseAamsEvent";
199 ApiMethod methodForCloseAamsEvent{closeAamsEvent, paramTypesForCloseAamsEvent, 0, false};
200 sApiArgTypesMap.insert(make_pair(closeAamsEvent, methodForCloseAamsEvent));
201
202 auto paramTypesForOpenAamsEvent = vector<string>();
203 paramTypesForOpenAamsEvent.push_back("");
204 string openAamsEvent = "Driver.OpenAamsEvent";
205 ApiMethod methodForOpenAamsEvent{openAamsEvent, paramTypesForOpenAamsEvent, 0, false};
206 sApiArgTypesMap.insert(make_pair(openAamsEvent, methodForOpenAamsEvent));
207 }
208
GetClassName(const string & apiName,char splitter)209 static string GetClassName(const string &apiName, char splitter)
210 {
211 auto classNameLen = apiName.find(splitter);
212 if (classNameLen == std::string::npos) {
213 return "";
214 }
215 return apiName.substr(0, classNameLen);
216 }
217
CheckAndDoApiMapping(string_view apiName,char splitter,const map<string,string> & apiMap)218 static string CheckAndDoApiMapping(string_view apiName, char splitter, const map<string, string> &apiMap)
219 {
220 string output = string(apiName);
221 auto classNameLen = output.find(splitter);
222 if (classNameLen == std::string::npos) {
223 return output;
224 }
225 string className = output.substr(0, classNameLen);
226 auto result = apiMap.find(className);
227 if (result == apiMap.end()) {
228 return output;
229 }
230 auto specialMapItem = apiMap.find(output);
231 if (specialMapItem != apiMap.end()) {
232 output = specialMapItem->second;
233 } else {
234 output.replace(0, classNameLen, result->second);
235 }
236 LOG_D("original className: %{public}s, modified to: %{public}s", className.c_str(), output.c_str());
237 return output;
238 }
239
FrontendApiServer()240 FrontendApiServer::FrontendApiServer()
241 {
242 old2NewApiMap_["By"] = "On";
243 old2NewApiMap_["UiDriver"] = "Driver";
244 old2NewApiMap_["UiComponent"] = "Component";
245 old2NewApiMap_["By.id"] = "On.accessibilityId";
246 old2NewApiMap_["By.key"] = "On.id";
247 old2NewApiMap_["UiComponent.getId"] = "Component.getAccessibilityId";
248 old2NewApiMap_["UiComponent.getKey"] = "Component.getId";
249 old2NewApiMap_["UiWindow.isActived"] = "UiWindow.isActive";
250 new2OldApiMap_["On"] = "By" ;
251 new2OldApiMap_["Driver"] = "UiDriver" ;
252 new2OldApiMap_["Component"] = "UiComponent" ;
253 }
254
255 /**
256 * map api8 old api call to new api.
257 * return old api name if it's an old api call.
258 * return empty string if it's a new api call.
259 */
260 static const std::map<ErrCode, std::vector<ErrCode>> ErrCodeMap = {
261 /**Correspondence between old and new error codes*/
262 {NO_ERROR, {NO_ERROR}},
263 {ERR_COMPONENT_LOST, {WIDGET_LOST, WINDOW_LOST}},
264 {ERR_NO_SYSTEM_CAPABILITY, {USAGE_ERROR}},
265 {ERR_INTERNAL, {INTERNAL_ERROR}},
266 {ERR_INITIALIZE_FAILED, {USAGE_ERROR}},
267 {ERR_INVALID_INPUT, {USAGE_ERROR}},
268 {ERR_ASSERTION_FAILED, {ASSERTION_FAILURE}},
269 {ERR_OPERATION_UNSUPPORTED, {INTERNAL_ERROR}},
270 {ERR_API_USAGE, {INTERNAL_ERROR}},
271 };
272
ApiMapPre(ApiCallInfo & inModifier) const273 string FrontendApiServer::ApiMapPre(ApiCallInfo &inModifier) const
274 {
275 // 0. add convert error label
276 const auto find = sApiArgTypesMap.find(inModifier.apiId_);
277 if (find != sApiArgTypesMap.end()) {
278 inModifier.convertError_ = find->second.convertError_;
279 }
280 // 1. map method name
281 const string &className = GetClassName(inModifier.apiId_, '.');
282 const auto result = old2NewApiMap_.find(className);
283 if (result == old2NewApiMap_.end()) {
284 auto iter = old2NewApiMap_.find(inModifier.apiId_);
285 if (iter != old2NewApiMap_.end()) {
286 LOG_D("original api:%{public}s, modified to:%{public}s", inModifier.apiId_.c_str(),
287 iter->second.c_str());
288 inModifier.apiId_ = iter->second;
289 }
290 return "";
291 }
292 string oldApiName = inModifier.apiId_;
293 inModifier.apiId_ = CheckAndDoApiMapping(inModifier.apiId_, '.', old2NewApiMap_);
294 LOG_D("Modify call name to %{public}s", inModifier.apiId_.c_str());
295 // 2. map callerObjRef
296 if (inModifier.callerObjRef_.find(className) == 0) {
297 inModifier.callerObjRef_.replace(0, className.length(), result->second);
298 LOG_D("Modify callobjref to %{public}s", inModifier.callerObjRef_.c_str());
299 }
300 // 3. map parameters
301 // find method signature of old api
302 if (find == sApiArgTypesMap.end()) {
303 return oldApiName;
304 }
305 const auto &argTypes = find->second.paramTypes_;
306 size_t argCount = inModifier.paramList_.size();
307 if (argTypes.size() - 1 < argCount) {
308 // parameter number invalid
309 return oldApiName;
310 }
311 for (size_t i = 0; i < argCount; i++) {
312 auto &argItem = inModifier.paramList_.at(i);
313 const string &argType = argTypes.at(i);
314 if (argType != "string" && argItem.type() == value_t::string) {
315 argItem = CheckAndDoApiMapping(argItem.get<string>(), '#', old2NewApiMap_);
316 }
317 }
318 return oldApiName;
319 }
320
ErrCodeMapping(ApiCallErr & apiErr)321 static void ErrCodeMapping(ApiCallErr &apiErr)
322 {
323 ErrCode ec = apiErr.code_;
324 auto msg = apiErr.message_;
325 auto findCode = ErrCodeMap.find(ec);
326 if (findCode != ErrCodeMap.end() && !findCode->second.empty()) {
327 apiErr = ApiCallErr(findCode->second.at(0), msg);
328 }
329 }
330
331 /** map new error code and api Object to old error code and api Object. */
ApiMapPost(const string & oldApiName,ApiReplyInfo & out) const332 void FrontendApiServer::ApiMapPost(const string &oldApiName, ApiReplyInfo &out) const
333 {
334 json &value = out.resultValue_;
335 const auto type = value.type();
336 // 1. error code conversion
337 ErrCodeMapping(out.exception_);
338 // 2. ret value conversion
339 const auto find = sApiArgTypesMap.find(oldApiName);
340 if (find == sApiArgTypesMap.end()) {
341 return;
342 }
343 string &retType = find->second.paramTypes_.back();
344 if ((retType == "string") || (retType == "[string]")) {
345 return;
346 }
347 if (type == value_t::string) {
348 value = CheckAndDoApiMapping(value.get<string>(), '#', new2OldApiMap_);
349 } else if (type == value_t::array) {
350 for (auto &item : value) {
351 if (item.type() == value_t::string) {
352 item = CheckAndDoApiMapping(item.get<string>(), '#', new2OldApiMap_);
353 }
354 }
355 }
356 }
357
Get()358 FrontendApiServer &FrontendApiServer::Get()
359 {
360 static FrontendApiServer singleton;
361 return singleton;
362 }
363
AddHandler(string_view apiId,ApiInvokeHandler handler)364 void FrontendApiServer::AddHandler(string_view apiId, ApiInvokeHandler handler)
365 {
366 if (handler == nullptr) {
367 return;
368 }
369 handlers_.insert(make_pair(apiId, handler));
370 }
371
SetCallbackHandler(ApiInvokeHandler handler)372 void FrontendApiServer::SetCallbackHandler(ApiInvokeHandler handler)
373 {
374 callbackHandler_ = handler;
375 }
376
Callback(const ApiCallInfo & in,ApiReplyInfo & out) const377 void FrontendApiServer::Callback(const ApiCallInfo& in, ApiReplyInfo& out) const
378 {
379 if (callbackHandler_ == nullptr) {
380 out.exception_ = ApiCallErr(ERR_INTERNAL, "No callback handler set!");
381 return;
382 }
383 callbackHandler_(in, out);
384 }
385
HasHandlerFor(std::string_view apiId) const386 bool FrontendApiServer::HasHandlerFor(std::string_view apiId) const
387 {
388 string apiIdstr = CheckAndDoApiMapping(apiId, '.', old2NewApiMap_);
389 return handlers_.find(apiIdstr) != handlers_.end();
390 }
391
RemoveHandler(string_view apiId)392 void FrontendApiServer::RemoveHandler(string_view apiId)
393 {
394 handlers_.erase(string(apiId));
395 }
396
AddCommonPreprocessor(string_view name,ApiInvokeHandler processor)397 void FrontendApiServer::AddCommonPreprocessor(string_view name, ApiInvokeHandler processor)
398 {
399 if (processor == nullptr) {
400 return;
401 }
402 commonPreprocessors_.insert(make_pair(name, processor));
403 }
404
RemoveCommonPreprocessor(string_view name)405 void FrontendApiServer::RemoveCommonPreprocessor(string_view name)
406 {
407 commonPreprocessors_.erase(string(name));
408 }
409
Call(const ApiCallInfo & in,ApiReplyInfo & out) const410 void FrontendApiServer::Call(const ApiCallInfo &in, ApiReplyInfo &out) const
411 {
412 LOG_I("Begin to invoke api '%{public}s', '%{public}s'", in.apiId_.data(), in.paramList_.dump().data());
413 auto call = in;
414 // initialize method signature
415 if (sApiArgTypesMap.empty()) {
416 ParseFrontendMethodsSignature();
417 ParseExtensionMethodsSignature();
418 }
419 string oldApiName = ApiMapPre(call);
420 out.convertError_ = call.convertError_;
421 auto find = handlers_.find(call.apiId_);
422 if (find == handlers_.end()) {
423 out.exception_ = ApiCallErr(ERR_INTERNAL, "No handler found for api '" + call.apiId_ + "'");
424 return;
425 }
426 try {
427 for (auto &[name, processor] : commonPreprocessors_) {
428 processor(call, out);
429 if (out.exception_.code_ != NO_ERROR) {
430 out.exception_.message_ = "(PreProcessing: " + name + ")" + out.exception_.message_;
431 if (oldApiName.length() > 0) {
432 ApiMapPost(oldApiName, out);
433 }
434 return; // error during pre-processing, abort
435 }
436 }
437 } catch (std::exception &ex) {
438 out.exception_ = ApiCallErr(ERR_INTERNAL, "Preprocessor failed: " + string(ex.what()));
439 }
440 try {
441 find->second(call, out);
442 } catch (std::exception &ex) {
443 // catch possible json-parsing error
444 out.exception_ = ApiCallErr(ERR_INTERNAL, "Handler failed: " + string(ex.what()));
445 }
446 if (oldApiName.length() > 0) {
447 ApiMapPost(oldApiName, out);
448 }
449 if (out.convertError_ && out.exception_.code_ == ERR_INVALID_INPUT) {
450 out.exception_.code_ = ERR_INVALID_PARAM; // 401 to 17000007
451 }
452 }
453
ApiTransact(const ApiCallInfo & in,ApiReplyInfo & out)454 void ApiTransact(const ApiCallInfo &in, ApiReplyInfo &out)
455 {
456 LOG_I("Begin to invoke api '%{public}s', '%{public}s'", in.apiId_.data(), in.paramList_.dump().data());
457 FrontendApiServer::Get().Call(in, out);
458 }
459
460 /** Backend objects cache.*/
461 static map<string, unique_ptr<BackendClass>> sBackendObjects;
462 /** UiDriver binding map.*/
463 static map<string, string> sDriverBindingMap;
464
465
466 #define CHECK_CALL_ARG(condition, code, message, error) \
467 if (!(condition)) { \
468 error = ApiCallErr((code), (message)); \
469 return; \
470 }
471
ConvertError(ApiReplyInfo & out)472 static void ConvertError(ApiReplyInfo &out)
473 {
474 if (out.convertError_ && out.exception_.code_ == ERR_INVALID_INPUT) {
475 out.exception_.code_ = ERR_INVALID_PARAM; // 401 to 17000007
476 }
477 }
478
479 /** Check if the json value represents and illegal data of expected type.*/
CheckCallArgType(string_view expect,const json & value,bool isDefAgc,ApiCallErr & error)480 static void CheckCallArgType(string_view expect, const json &value, bool isDefAgc, ApiCallErr &error)
481 {
482 const auto type = value.type();
483 if (isDefAgc && type == value_t::null) {
484 return;
485 }
486 const auto isInteger = type == value_t::number_integer || type == value_t::number_unsigned;
487 auto begin0 = FRONTEND_CLASS_DEFS.begin();
488 auto end0 = FRONTEND_CLASS_DEFS.end();
489 auto begin1 = FRONTEND_JSON_DEFS.begin();
490 auto end1 = FRONTEND_JSON_DEFS.end();
491 auto find0 = find_if(begin0, end0, [&expect](const FrontEndClassDef *def) { return def->name_ == expect; });
492 auto find1 = find_if(begin1, end1, [&expect](const FrontEndJsonDef *def) { return def->name_ == expect; });
493 if (expect == "int") {
494 CHECK_CALL_ARG(isInteger && atoi(value.dump().c_str()) >= 0, ERR_INVALID_INPUT,
495 "Expect integer which cannot be less than 0", error);
496 } else if (expect == "signedInt") {
497 CHECK_CALL_ARG(isInteger, ERR_INVALID_INPUT, "Expect signedInt", error);
498 } else if (expect == "float") {
499 CHECK_CALL_ARG(isInteger || type == value_t::number_float, ERR_INVALID_INPUT, "Expect float", error);
500 } else if (expect == "bool") {
501 CHECK_CALL_ARG(type == value_t::boolean, ERR_INVALID_INPUT, "Expect boolean", error);
502 } else if (expect == "string") {
503 CHECK_CALL_ARG(type == value_t::string, ERR_INVALID_INPUT, "Expect string", error);
504 } else if (find0 != end0) {
505 CHECK_CALL_ARG(type == value_t::string, ERR_INVALID_INPUT, "Expect " + string(expect), error);
506 const auto findRef = sBackendObjects.find(value.get<string>());
507 CHECK_CALL_ARG(findRef != sBackendObjects.end(), ERR_INTERNAL, "Bad object ref", error);
508 } else if (find1 != end1) {
509 CHECK_CALL_ARG(type == value_t::object, ERR_INVALID_INPUT, "Expect " + string(expect), error);
510 auto copy = value;
511 for (size_t idx = 0; idx < (*find1)->propCount_; idx++) {
512 auto def = (*find1)->props_ + idx;
513 const auto propName = string(def->name_);
514 if (!value.contains(propName)) {
515 CHECK_CALL_ARG(!(def->required_), ERR_INVALID_INPUT, "Missing property " + propName, error);
516 continue;
517 }
518 copy.erase(propName);
519 // check json property value type recursive
520 CheckCallArgType(def->type_, value[propName], !def->required_, error);
521 if (error.code_ != NO_ERROR) {
522 error.message_ = "Illegal value of property '" + propName + "': " + error.message_;
523 return;
524 }
525 }
526 CHECK_CALL_ARG(copy.empty(), ERR_INVALID_INPUT, "Illegal property of " + string(expect), error);
527 } else {
528 CHECK_CALL_ARG(false, ERR_INTERNAL, "Unknown target type " + string(expect), error);
529 }
530 }
531
532 /** Checks ApiCallInfo data, deliver exception and abort invocation if check fails.*/
APiCallInfoChecker(const ApiCallInfo & in,ApiReplyInfo & out)533 static void APiCallInfoChecker(const ApiCallInfo &in, ApiReplyInfo &out)
534 {
535 auto count = sApiArgTypesMap.count(in.apiId_);
536 // return nullptr by default
537 out.resultValue_ = nullptr;
538 auto find = sApiArgTypesMap.find(in.apiId_);
539 size_t index = 0;
540 while (index < count) {
541 if (find == sApiArgTypesMap.end()) {
542 return;
543 }
544 bool checkArgNum = false;
545 bool checkArgType = true;
546 out.exception_ = {NO_ERROR, "No Error"};
547 auto &types = find->second.paramTypes_;
548 auto argSupportDefault = find->second.defaultArgCount_;
549 // check argument count.(last item of "types" is return value type)
550 auto maxArgc = types.size() - 1;
551 auto minArgc = maxArgc - argSupportDefault;
552 auto argc = in.paramList_.size();
553 checkArgNum = argc <= maxArgc && argc >= minArgc;
554 if (!checkArgNum) {
555 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Illegal argument count");
556 ++find;
557 ++index;
558 continue;
559 }
560 // check argument type
561 for (size_t idx = 0; idx < argc; idx++) {
562 auto isDefArg = (idx >= minArgc) ? true : false;
563 CheckCallArgType(types.at(idx), in.paramList_.at(idx), isDefArg, out.exception_);
564 if (out.exception_.code_ != NO_ERROR) {
565 out.exception_.message_ = "Check arg" + to_string(idx) + " failed: " + out.exception_.message_;
566 checkArgType = false;
567 break;
568 }
569 }
570 if (checkArgType) {
571 return;
572 }
573 ++find;
574 ++index;
575 }
576 ConvertError(out);
577 }
578
579 /** Store the backend object and return the reference-id.*/
StoreBackendObject(unique_ptr<BackendClass> ptr,string_view ownerRef="")580 static string StoreBackendObject(unique_ptr<BackendClass> ptr, string_view ownerRef = "")
581 {
582 static map<string, uint32_t> sObjectCounts;
583 DCHECK(ptr != nullptr);
584 const auto typeName = string(ptr->GetFrontendClassDef().name_);
585 auto find = sObjectCounts.find(typeName);
586 uint32_t index = 0;
587 if (find != sObjectCounts.end()) {
588 index = find->second;
589 }
590 auto ref = typeName + "#" + to_string(index);
591 sObjectCounts[typeName] = index + 1;
592 sBackendObjects[ref] = move(ptr);
593 if (!ownerRef.empty()) {
594 DCHECK(sBackendObjects.find(string(ownerRef)) != sBackendObjects.end());
595 sDriverBindingMap[ref] = ownerRef;
596 }
597 return ref;
598 }
599
600 /** Retrieve the stored backend object by reference-id.*/
601 template <typename T, typename = enable_if<is_base_of_v<BackendClass, T>>>
GetBackendObject(string_view ref)602 static T &GetBackendObject(string_view ref)
603 {
604 auto find = sBackendObjects.find(string(ref));
605 DCHECK(find != sBackendObjects.end() && find->second != nullptr);
606 return *(reinterpret_cast<T *>(find->second.get()));
607 }
608
GetBoundUiDriver(string_view ref)609 static UiDriver &GetBoundUiDriver(string_view ref)
610 {
611 auto find0 = sDriverBindingMap.find(string(ref));
612 DCHECK(find0 != sDriverBindingMap.end());
613 auto find1 = sBackendObjects.find(find0->second);
614 DCHECK(find1 != sBackendObjects.end() && find1->second != nullptr);
615 return *(reinterpret_cast<UiDriver *>(find1->second.get()));
616 }
617
618 /** Delete stored backend objects.*/
BackendObjectsCleaner(const ApiCallInfo & in,ApiReplyInfo & out)619 static void BackendObjectsCleaner(const ApiCallInfo &in, ApiReplyInfo &out)
620 {
621 stringstream ss("Deleted objects[");
622 DCHECK(in.paramList_.type() == value_t::array);
623 for (const auto &item : in.paramList_) {
624 DCHECK(item.type() == value_t::string); // must be objRef
625 const auto ref = item.get<string>();
626 auto findBinding = sDriverBindingMap.find(ref);
627 if (findBinding != sDriverBindingMap.end()) {
628 sDriverBindingMap.erase(findBinding);
629 }
630 auto findObject = sBackendObjects.find(ref);
631 if (findObject == sBackendObjects.end()) {
632 LOG_W("No such object living: %{public}s", ref.c_str());
633 continue;
634 }
635 sBackendObjects.erase(findObject);
636 ss << ref << ",";
637 }
638 ss << "]";
639 LOG_D("%{public}s", ss.str().c_str());
640 }
641
ReadCallArg(const ApiCallInfo & in,size_t index)642 template <typename T> static T ReadCallArg(const ApiCallInfo &in, size_t index)
643 {
644 DCHECK(in.paramList_.type() == value_t::array);
645 DCHECK(index <= in.paramList_.size());
646 return in.paramList_.at(index).get<T>();
647 }
648
ReadCallArg(const ApiCallInfo & in,size_t index,T defValue)649 template <typename T> static T ReadCallArg(const ApiCallInfo &in, size_t index, T defValue)
650 {
651 DCHECK(in.paramList_.type() == value_t::array);
652 if (index >= in.paramList_.size()) {
653 return defValue;
654 }
655 auto type = in.paramList_.at(index).type();
656 if (type == value_t::null) {
657 return defValue;
658 } else {
659 return in.paramList_.at(index).get<T>();
660 }
661 }
662
CheckRegExp(string regex)663 ApiCallErr CheckRegExp(string regex)
664 {
665 regex_t preg;
666 int rc;
667 const int errorLength = 100;
668 char errorBuffer[errorLength] = "";
669 ApiCallErr error(NO_ERROR);
670 char *patternValue = const_cast<char*>(regex.data());
671 if ((rc = regcomp(&preg, patternValue, REG_EXTENDED)) != 0) {
672 regerror(rc, &preg, errorBuffer, errorLength);
673 LOG_E("Regcomp error : %{public}s", errorBuffer);
674 error.code_ = ERR_INVALID_INPUT;
675 error.message_ = errorBuffer;
676 }
677 return error;
678 }
GenericOnAttrBuilder(const ApiCallInfo & in,ApiReplyInfo & out)679 template <UiAttr kAttr, typename T> static void GenericOnAttrBuilder(const ApiCallInfo &in, ApiReplyInfo &out)
680 {
681 // always create and return a new selector
682 auto selector = make_unique<WidgetSelector>();
683 if (in.callerObjRef_ != REF_SEED_ON) { // copy-construct from the caller if it's not seed
684 *selector = GetBackendObject<WidgetSelector>(in.callerObjRef_);
685 }
686 string testValue = "";
687 if constexpr (std::is_same<string, T>::value) {
688 testValue = ReadCallArg<string>(in, INDEX_ZERO);
689 } else if constexpr (std::is_same<bool, T>::value) { // bool testValue can be defaulted to true
690 testValue = ReadCallArg<bool>(in, INDEX_ZERO, true) ? "true" : "false";
691 } else {
692 testValue = to_string(ReadCallArg<T>(in, INDEX_ZERO));
693 }
694 auto matchPattern = ReadCallArg<uint8_t>(in, INDEX_ONE, ValueMatchPattern::EQ); // match pattern argument
695 if (matchPattern == ValueMatchPattern::REG_EXP || matchPattern == ValueMatchPattern::REG_EXP_ICASE) {
696 out.exception_.code_ = NO_ERROR;
697 out.exception_ = CheckRegExp(testValue);
698 }
699 if (out.exception_.code_ != NO_ERROR) {
700 return;
701 }
702 auto matcher = WidgetMatchModel(kAttr, testValue, static_cast<ValueMatchPattern>(matchPattern));
703 selector->AddMatcher(matcher);
704 out.resultValue_ = StoreBackendObject(move(selector));
705 }
706
RegisterOnBuilders()707 static void RegisterOnBuilders()
708 {
709 auto &server = FrontendApiServer::Get();
710 server.AddHandler("On.accessibilityId", GenericOnAttrBuilder<UiAttr::ACCESSIBILITY_ID, int32_t>);
711 server.AddHandler("On.text", GenericOnAttrBuilder<UiAttr::TEXT, string>);
712 server.AddHandler("On.id", GenericOnAttrBuilder<UiAttr::ID, string>);
713 server.AddHandler("On.description", GenericOnAttrBuilder<UiAttr::DESCRIPTION, string>);
714 server.AddHandler("On.type", GenericOnAttrBuilder<UiAttr::TYPE, string>);
715 server.AddHandler("On.hint", GenericOnAttrBuilder<UiAttr::HINT, string>);
716 server.AddHandler("On.enabled", GenericOnAttrBuilder<UiAttr::ENABLED, bool>);
717 server.AddHandler("On.focused", GenericOnAttrBuilder<UiAttr::FOCUSED, bool>);
718 server.AddHandler("On.selected", GenericOnAttrBuilder<UiAttr::SELECTED, bool>);
719 server.AddHandler("On.clickable", GenericOnAttrBuilder<UiAttr::CLICKABLE, bool>);
720 server.AddHandler("On.longClickable", GenericOnAttrBuilder<UiAttr::LONG_CLICKABLE, bool>);
721 server.AddHandler("On.scrollable", GenericOnAttrBuilder<UiAttr::SCROLLABLE, bool>);
722 server.AddHandler("On.checkable", GenericOnAttrBuilder<UiAttr::CHECKABLE, bool>);
723 server.AddHandler("On.checked", GenericOnAttrBuilder<UiAttr::CHECKED, bool>);
724 server.AddHandler("On.originalText", GenericOnAttrBuilder<UiAttr::ORIGINALTEXT, string>);
725
726 auto genericRelativeBuilder = [](const ApiCallInfo &in, ApiReplyInfo &out) {
727 const auto attrName = in.apiId_.substr(ON_DEF.name_.length() + 1); // On.xxx()->xxx
728 // always create and return a new selector
729 auto selector = make_unique<WidgetSelector>();
730 if (in.callerObjRef_ != REF_SEED_ON) { // copy-construct from the caller if it's not seed
731 *selector = GetBackendObject<WidgetSelector>(in.callerObjRef_);
732 }
733 if (attrName == "isBefore") {
734 auto &that = GetBackendObject<WidgetSelector>(ReadCallArg<string>(in, INDEX_ZERO));
735 selector->AddRearLocator(that, out.exception_);
736 } else if (attrName == "isAfter") {
737 auto &that = GetBackendObject<WidgetSelector>(ReadCallArg<string>(in, INDEX_ZERO));
738 selector->AddFrontLocator(that, out.exception_);
739 } else if (attrName == "within") {
740 auto &that = GetBackendObject<WidgetSelector>(ReadCallArg<string>(in, INDEX_ZERO));
741 selector->AddParentLocator(that, out.exception_);
742 } else if (attrName == "inWindow") {
743 auto hostApp = ReadCallArg<string>(in, INDEX_ZERO);
744 selector->AddAppLocator(hostApp);
745 } else if (attrName == "inDisplay" || attrName == "belongingDisplay") {
746 auto displayId = ReadCallArg<int32_t>(in, INDEX_ZERO);
747 selector->AddDisplayLocator(displayId);
748 }
749 out.resultValue_ = StoreBackendObject(move(selector));
750 };
751 server.AddHandler("On.isBefore", genericRelativeBuilder);
752 server.AddHandler("On.isAfter", genericRelativeBuilder);
753 server.AddHandler("On.within", genericRelativeBuilder);
754 server.AddHandler("On.inWindow", genericRelativeBuilder);
755 server.AddHandler("On.inDisplay", genericRelativeBuilder);
756 server.AddHandler("On.belongingDisplay", genericRelativeBuilder);
757 }
758
RegisterUiDriverComponentFinders()759 static void RegisterUiDriverComponentFinders()
760 {
761 auto &server = FrontendApiServer::Get();
762 auto genericFindWidgetHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
763 const auto driverRef = in.callerObjRef_;
764 auto &driver = GetBackendObject<UiDriver>(driverRef);
765 auto &selector = GetBackendObject<WidgetSelector>(ReadCallArg<string>(in, INDEX_ZERO));
766 UiOpArgs uiOpArgs;
767 vector<unique_ptr<Widget>> recv;
768 if (in.apiId_ == "Driver.waitForComponent") {
769 uiOpArgs.waitWidgetMaxMs_ = ReadCallArg<int32_t>(in, INDEX_ONE);
770 selector.SetWantMulti(false);
771 auto result = driver.WaitForWidget(selector, uiOpArgs, out.exception_);
772 if (result != nullptr) {
773 recv.emplace_back(move(result));
774 }
775 } else {
776 selector.SetWantMulti(in.apiId_ == "Driver.findComponents");
777 driver.FindWidgets(selector, recv, out.exception_);
778 }
779 if (out.exception_.code_ != NO_ERROR) {
780 LOG_W("genericFindWidgetHandler has error: %{public}s", out.exception_.message_.c_str());
781 return;
782 }
783 if (in.apiId_ == "Driver.assertComponentExist") {
784 if (recv.empty()) { // widget-exist assertion failure, deliver exception
785 out.exception_.code_ = ERR_ASSERTION_FAILED;
786 out.exception_.message_ = "Component not exist matching: " + selector.Describe();
787 }
788 } else if (in.apiId_ == "Driver.findComponents") { // return widget array, maybe empty
789 for (auto &ptr : recv) {
790 out.resultValue_.emplace_back(StoreBackendObject(move(ptr), driverRef));
791 }
792 } else if (recv.empty()) { // return first one or null
793 out.resultValue_ = nullptr;
794 } else {
795 out.resultValue_ = StoreBackendObject(move(*(recv.begin())), driverRef);
796 }
797 };
798 server.AddHandler("Driver.findComponent", genericFindWidgetHandler);
799 server.AddHandler("Driver.findComponents", genericFindWidgetHandler);
800 server.AddHandler("Driver.waitForComponent", genericFindWidgetHandler);
801 server.AddHandler("Driver.assertComponentExist", genericFindWidgetHandler);
802 }
803
RegisterUiDriverWindowFinder()804 static void RegisterUiDriverWindowFinder()
805 {
806 auto findWindowHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
807 const auto driverRef = in.callerObjRef_;
808 auto &driver = GetBackendObject<UiDriver>(driverRef);
809 auto filterJson = ReadCallArg<json>(in, INDEX_ZERO);
810 if (filterJson.empty()) {
811 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "WindowFilter cannot be empty");
812 return;
813 }
814 auto matcher = [&filterJson](const Window &window) -> bool {
815 bool match = true;
816 if (filterJson.contains("bundleName")) {
817 match = match && (filterJson["bundleName"].get<string>() == window.bundleName_);
818 }
819 if (filterJson.contains("title")) {
820 match = match && (filterJson["title"].get<string>() == window.title_);
821 }
822 if (filterJson.contains("focused")) {
823 match = match && (filterJson["focused"].get<bool>() == window.focused_);
824 }
825 if (filterJson.contains("actived")) {
826 match = match && (filterJson["actived"].get<bool>() == window.actived_);
827 }
828 if (filterJson.contains("active")) {
829 match = match && (filterJson["active"].get<bool>() == window.actived_);
830 }
831 if (filterJson.contains("displayId")) {
832 match = match && (filterJson["displayId"].get<int32_t>() == window.displayId_);
833 }
834 return match;
835 };
836 auto window = driver.FindWindow(matcher, out.exception_);
837 if (window == nullptr) {
838 LOG_W("There is no match window by %{public}s", filterJson.dump().data());
839 out.resultValue_ = nullptr;
840 } else {
841 out.resultValue_ = StoreBackendObject(move(window), driverRef);
842 }
843 };
844 FrontendApiServer::Get().AddHandler("Driver.findWindow", findWindowHandler);
845 }
846
RegisterUiDriverMiscMethods()847 static void RegisterUiDriverMiscMethods()
848 {
849 auto &server = FrontendApiServer::Get();
850 auto create = [](const ApiCallInfo &in, ApiReplyInfo &out) {
851 auto driver = make_unique<UiDriver>();
852 if (driver->CheckStatus(true, out.exception_)) {
853 out.resultValue_ = StoreBackendObject(move(driver));
854 }
855 };
856 server.AddHandler("Driver.create", create);
857
858 auto createUIEventObserver = [](const ApiCallInfo &in, ApiReplyInfo &out) {
859 auto observer = make_unique<UIEventObserver>();
860 out.resultValue_ = StoreBackendObject(move(observer), in.callerObjRef_);
861 };
862 server.AddHandler("Driver.createUIEventObserver", createUIEventObserver);
863
864 auto delay = [](const ApiCallInfo &in, ApiReplyInfo &out) {
865 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
866 auto time = ReadCallArg<int32_t>(in, INDEX_ZERO);
867 driver.DelayMs(time);
868 };
869 server.AddHandler("Driver.delayMs", delay);
870
871 auto screenCap = [](const ApiCallInfo &in, ApiReplyInfo &out) {
872 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
873 auto fd = ReadCallArg<uint32_t>(in, INDEX_ZERO);
874 auto null = json();
875 auto displayId = UNASSIGNED;
876 Rect rect = {0, 0, 0, 0};
877 if (in.apiId_ == "Driver.screenCapture") {
878 auto rectJson = ReadCallArg<json>(in, INDEX_ONE, null);
879 if (!rectJson.empty()) {
880 rect = Rect(rectJson["left"], rectJson["right"], rectJson["top"], rectJson["bottom"]);
881 displayId = ReadArgFromJson<int32_t>(rectJson, "displayId", UNASSIGNED);
882 }
883 } else if (in.apiId_ == "Driver.screenCap") {
884 displayId = ReadCallArg<uint32_t>(in, INDEX_ONE, UNASSIGNED);
885 }
886 if (!driver.CheckDisplayExist(displayId)) {
887 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Invalid display id.");
888 return;
889 }
890 driver.TakeScreenCap(fd, out.exception_, rect, displayId);
891 out.resultValue_ = (out.exception_.code_ == NO_ERROR);
892 };
893 server.AddHandler("Driver.screenCap", screenCap);
894 server.AddHandler("Driver.screenCapture", screenCap);
895 }
896
RegisterUiDriverKeyOperation()897 static void RegisterUiDriverKeyOperation()
898 {
899 auto &server = FrontendApiServer::Get();
900 auto pressBack = [](const ApiCallInfo &in, ApiReplyInfo &out) {
901 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
902 UiOpArgs uiOpArgs;
903 auto displayId = ReadCallArg<uint32_t>(in, INDEX_ZERO, UNASSIGNED);
904 driver.TriggerKey(Back(), uiOpArgs, out.exception_, displayId);
905 ConvertError(out);
906 };
907 server.AddHandler("Driver.pressBack", pressBack);
908 auto pressHome = [](const ApiCallInfo &in, ApiReplyInfo &out) {
909 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
910 auto displayId = ReadCallArg<uint32_t>(in, INDEX_ZERO, UNASSIGNED);
911 UiOpArgs uiOpArgs;
912 auto keyAction = CombinedKeys(KEYCODE_WIN, KEYCODE_D, KEYCODE_NONE);
913 driver.TriggerKey(keyAction, uiOpArgs, out.exception_);
914 driver.TriggerKey(Home(), uiOpArgs, out.exception_, displayId);
915 ConvertError(out);
916 };
917 server.AddHandler("Driver.pressHome", pressHome);
918 auto triggerKey = [](const ApiCallInfo &in, ApiReplyInfo &out) {
919 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
920 UiOpArgs uiOpArgs;
921 auto key = AnonymousSingleKey(ReadCallArg<int32_t>(in, INDEX_ZERO));
922 auto displayId = ReadCallArg<uint32_t>(in, INDEX_ONE, UNASSIGNED);
923 driver.TriggerKey(key, uiOpArgs, out.exception_, displayId);
924 };
925 server.AddHandler("Driver.triggerKey", triggerKey);
926 auto triggerCombineKeys = [](const ApiCallInfo &in, ApiReplyInfo &out) {
927 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
928 UiOpArgs uiOpArgs;
929 auto key0 = ReadCallArg<int32_t>(in, INDEX_ZERO);
930 auto key1 = ReadCallArg<int32_t>(in, INDEX_ONE);
931 auto key2 = ReadCallArg<int32_t>(in, INDEX_TWO, KEYCODE_NONE);
932 auto displayId = ReadCallArg<uint32_t>(in, INDEX_THREE, UNASSIGNED);
933 auto keyAction = CombinedKeys(key0, key1, key2);
934 driver.TriggerKey(keyAction, uiOpArgs, out.exception_, displayId);
935 };
936 server.AddHandler("Driver.triggerCombineKeys", triggerCombineKeys);
937 }
938
RegisterUiDriverInputText()939 static void RegisterUiDriverInputText()
940 {
941 auto &server = FrontendApiServer::Get();
942 auto inputText = [](const ApiCallInfo &in, ApiReplyInfo &out) {
943 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
944 UiOpArgs uiOpArgs;
945 auto pointJson = ReadCallArg<json>(in, INDEX_ZERO);
946 auto displayId = ReadArgFromJson<int32_t>(pointJson, "displayId", UNASSIGNED);
947 auto point = Point(pointJson["x"], pointJson["y"], displayId);
948 auto text = ReadCallArg<string>(in, INDEX_ONE);
949 auto inputModeJson = ReadCallArg<json>(in, INDEX_TWO, json());
950 ReadInputModeFromJson(inputModeJson, uiOpArgs.inputByPasteBoard_, uiOpArgs.inputAdditional_);
951 auto touch = GenericClick(TouchOp::CLICK, point);
952 driver.PerformTouch(touch, uiOpArgs, out.exception_);
953 if (out.exception_.code_ != NO_ERROR) {
954 return;
955 }
956 static constexpr uint32_t focusTimeMs = 500;
957 driver.DelayMs(focusTimeMs);
958 if (uiOpArgs.inputAdditional_) {
959 driver.TriggerKey(MoveToEnd(), uiOpArgs, out.exception_, displayId);
960 driver.DelayMs(focusTimeMs);
961 }
962 driver.InputText(text, out.exception_, uiOpArgs, displayId);
963 };
964 server.AddHandler("Driver.inputText", inputText);
965 }
966
RegisterUiEventObserverMethods()967 static void RegisterUiEventObserverMethods()
968 {
969 static bool observerDelegateRegistered = false;
970 static auto fowarder = std::make_shared<UiEventFowarder>();
971 auto &server = FrontendApiServer::Get();
972 auto once = [](const ApiCallInfo &in, ApiReplyInfo &out) {
973 auto &driver = GetBoundUiDriver(in.callerObjRef_);
974 auto event = ReadCallArg<string>(in, INDEX_ZERO);
975 auto cbRef = ReadCallArg<string>(in, INDEX_ONE);
976 fowarder->AddCallbackInfo(move(event), in.callerObjRef_, move(cbRef));
977 if (!observerDelegateRegistered) {
978 driver.RegisterUiEventListener(fowarder);
979 observerDelegateRegistered = true;
980 }
981 };
982 server.AddHandler("UIEventObserver.once", once);
983 }
984
CheckSwipeVelocityPps(UiOpArgs & args)985 static void CheckSwipeVelocityPps(UiOpArgs& args)
986 {
987 if (args.swipeVelocityPps_ < args.minSwipeVelocityPps_ || args.swipeVelocityPps_ > args.maxSwipeVelocityPps_) {
988 LOG_W("The swipe velocity out of range");
989 args.swipeVelocityPps_ = args.defaultSwipeVelocityPps_;
990 }
991 }
992
TouchParamsConverts(const ApiCallInfo & in,Point & point0,Point & point1,UiOpArgs & uiOpArgs)993 static void TouchParamsConverts(const ApiCallInfo &in, Point &point0, Point &point1, UiOpArgs &uiOpArgs)
994 {
995 auto params = in.paramList_;
996 auto count = params.size();
997 DCHECK(count > ZERO && count < SIX);
998 if (params.at(0).type() != value_t::object) {
999 point0 = Point(ReadCallArg<int32_t>(in, INDEX_ZERO), ReadCallArg<int32_t>(in, INDEX_ONE));
1000 point1 = Point(ReadCallArg<int32_t>(in, INDEX_TWO, 0), ReadCallArg<int32_t>(in, INDEX_THREE, 0));
1001 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_FOUR, uiOpArgs.swipeVelocityPps_);
1002 return;
1003 }
1004 auto pointJson = ReadCallArg<json>(in, INDEX_ZERO);
1005 auto displayId = ReadArgFromJson<int32_t>(pointJson, "displayId", UNASSIGNED);
1006 point0 = Point(pointJson["x"], pointJson["y"], displayId);
1007 if (count == 1) {
1008 return;
1009 }
1010 if (params.at(1).type() != value_t::object) { // longClickAt
1011 uiOpArgs.longClickHoldMs_ = ReadCallArg<uint32_t>(in, INDEX_ONE, uiOpArgs.longClickHoldMs_);
1012 } else {
1013 auto pointJson1 = ReadCallArg<json>(in, INDEX_ONE);
1014 auto displayId1 = ReadArgFromJson<int32_t>(pointJson1, "displayId", UNASSIGNED);
1015 point1 = Point(pointJson1["x"], pointJson1["y"], displayId1);
1016 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_TWO, uiOpArgs.swipeVelocityPps_);
1017 uiOpArgs.longClickHoldMs_ = ReadCallArg<uint32_t>(in, INDEX_THREE, uiOpArgs.longClickHoldMs_);
1018 }
1019 }
1020
RegisterUiDriverTouchOperators()1021 static void RegisterUiDriverTouchOperators()
1022 {
1023 auto &server = FrontendApiServer::Get();
1024 auto genericClick = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1025 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1026 auto point0 = Point(0, 0);
1027 auto point1 = Point(0, 0);
1028 UiOpArgs uiOpArgs;
1029 TouchParamsConverts(in, point0, point1, uiOpArgs);
1030 auto op = TouchOp::CLICK;
1031 if (in.apiId_ == "Driver.longClick" || in.apiId_ == "Driver.longClickAt") {
1032 op = TouchOp::LONG_CLICK;
1033 } else if (in.apiId_ == "Driver.doubleClick" || in.apiId_ == "Driver.doubleClickAt") {
1034 op = TouchOp::DOUBLE_CLICK_P;
1035 } else if (in.apiId_ == "Driver.swipe" || in.apiId_ == "Driver.swipeBetween") {
1036 op = TouchOp::SWIPE;
1037 } else if (in.apiId_ == "Driver.drag" || in.apiId_ == "Driver.dragBetween") {
1038 op = TouchOp::DRAG;
1039 }
1040 CheckSwipeVelocityPps(uiOpArgs);
1041 const uint32_t minLongClickHoldMs = 1500;
1042 if (uiOpArgs.longClickHoldMs_ < minLongClickHoldMs) {
1043 out.exception_ = ApiCallErr(ERR_INVALID_PARAM, "Invalid longclick hold time");
1044 return;
1045 }
1046 if (op == TouchOp::SWIPE || op == TouchOp::DRAG) {
1047 if (point0.displayId_ != point1.displayId_) {
1048 out.exception_ = ApiCallErr(ERR_INVALID_PARAM,
1049 "The start point and end point must belong to the same display.");
1050 return;
1051 }
1052 auto touch = GenericSwipe(op, point0, point1);
1053 driver.PerformTouch(touch, uiOpArgs, out.exception_);
1054 } else {
1055 auto touch = GenericClick(op, point0);
1056 driver.PerformTouch(touch, uiOpArgs, out.exception_);
1057 }
1058 ConvertError(out);
1059 };
1060 server.AddHandler("Driver.click", genericClick);
1061 server.AddHandler("Driver.longClick", genericClick);
1062 server.AddHandler("Driver.doubleClick", genericClick);
1063 server.AddHandler("Driver.swipe", genericClick);
1064 server.AddHandler("Driver.drag", genericClick);
1065 server.AddHandler("Driver.longClickAt", genericClick);
1066 server.AddHandler("Driver.dragBetween", genericClick);
1067 server.AddHandler("Driver.doubleClickAt", genericClick);
1068 server.AddHandler("Driver.clickAt", genericClick);
1069 server.AddHandler("Driver.swipeBetween", genericClick);
1070 }
1071
CheckMultiPointerOperatorsPoint(const PointerMatrix & pointer)1072 static bool CheckMultiPointerOperatorsPoint(const PointerMatrix& pointer)
1073 {
1074 for (uint32_t fingerIndex = 0; fingerIndex < pointer.GetFingers(); fingerIndex++) {
1075 for (uint32_t stepIndex = 0; stepIndex < pointer.GetSteps(); stepIndex++) {
1076 if (pointer.At(fingerIndex, stepIndex).flags_ != 1) {
1077 return false;
1078 }
1079 }
1080 }
1081 return true;
1082 }
1083
CreateFlingPoint(Point & to,Point & from,Point screenSize,Direction direction)1084 static void CreateFlingPoint(Point &to, Point &from, Point screenSize, Direction direction)
1085 {
1086 from = Point(0, 0, screenSize.displayId_);
1087 to = Point(screenSize.px_ / INDEX_TWO, screenSize.py_ / INDEX_TWO, screenSize.displayId_);
1088 switch (direction) {
1089 case TO_LEFT:
1090 from.px_ = to.px_ - screenSize.px_ / INDEX_FOUR;
1091 from.py_ = to.py_;
1092 break;
1093 case TO_RIGHT:
1094 from.px_ = to.px_ + screenSize.px_ / INDEX_FOUR;
1095 from.py_ = to.py_;
1096 break;
1097 case TO_UP:
1098 from.px_ = to.px_;
1099 from.py_ = to.py_ - screenSize.py_ / INDEX_FOUR;
1100 break;
1101 case TO_DOWN:
1102 from.px_ = to.px_;
1103 from.py_ = to.py_ + screenSize.py_ / INDEX_FOUR;
1104 break;
1105 default:
1106 break;
1107 }
1108 }
1109
RegisterUiDriverFlingOperators()1110 static void RegisterUiDriverFlingOperators()
1111 {
1112 auto &server = FrontendApiServer::Get();
1113 auto genericFling = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1114 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1115 UiOpArgs uiOpArgs;
1116 auto op = TouchOp::FLING;
1117 auto params = in.paramList_;
1118 Point from;
1119 Point to;
1120 if (params.size() != INDEX_FOUR) {
1121 auto displayId = ReadCallArg<int32_t>(in, INDEX_TWO, UNASSIGNED);
1122 auto screenSize = driver.GetDisplaySize(out.exception_, displayId);
1123 auto direction = ReadCallArg<Direction>(in, INDEX_ZERO);
1124 CreateFlingPoint(to, from, screenSize, direction);
1125 uiOpArgs.swipeStepsCounts_ = INDEX_TWO;
1126 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_ONE);
1127 } else {
1128 auto pointJson0 = ReadCallArg<json>(in, INDEX_ZERO);
1129 auto pointJson1 = ReadCallArg<json>(in, INDEX_ONE);
1130 if (pointJson0.empty() || pointJson1.empty()) {
1131 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Point cannot be empty");
1132 return;
1133 }
1134 auto displayId0 = ReadArgFromJson<int32_t>(pointJson0, "displayId", UNASSIGNED);
1135 auto displayId1 = ReadArgFromJson<int32_t>(pointJson1, "displayId", UNASSIGNED);
1136 from = Point(pointJson0["x"], pointJson0["y"], displayId0);
1137 to = Point(pointJson1["x"], pointJson1["y"], displayId1);
1138 auto stepLength = ReadCallArg<uint32_t>(in, INDEX_TWO);
1139 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_THREE);
1140 const int32_t distanceX = to.px_ - from.px_;
1141 const int32_t distanceY = to.py_ - from.py_;
1142 const uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY);
1143 if (stepLength <= 0 || stepLength > distance) {
1144 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "The stepLen is out of range");
1145 return;
1146 }
1147 uiOpArgs.swipeStepsCounts_ = distance / stepLength;
1148 }
1149 CheckSwipeVelocityPps(uiOpArgs);
1150 if (from.displayId_ != to.displayId_) {
1151 out.exception_ = ApiCallErr(ERR_INVALID_INPUT,
1152 "The start point and end point must belong to the same display.");
1153 return;
1154 }
1155 auto touch = GenericSwipe(op, from, to);
1156 driver.PerformTouch(touch, uiOpArgs, out.exception_);
1157 };
1158 server.AddHandler("Driver.fling", genericFling);
1159 }
1160
RegisterUiDriverMultiPointerOperators()1161 static void RegisterUiDriverMultiPointerOperators()
1162 {
1163 auto &server = FrontendApiServer::Get();
1164 auto multiPointerAction = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1165 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1166 auto &pointer = GetBackendObject<PointerMatrix>(ReadCallArg<string>(in, INDEX_ZERO));
1167 if (!CheckMultiPointerOperatorsPoint(pointer)) {
1168 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "There is not all coordinate points are set");
1169 return;
1170 }
1171 UiOpArgs uiOpArgs;
1172 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_ONE, uiOpArgs.swipeVelocityPps_);
1173 auto touch = MultiPointerAction(pointer);
1174 CheckSwipeVelocityPps(uiOpArgs);
1175 if (in.apiId_ == "Driver.injectMultiPointerAction") {
1176 driver.PerformTouch(touch, uiOpArgs, out.exception_);
1177 out.resultValue_ = (out.exception_.code_ == NO_ERROR);
1178 } else if (in.apiId_ == "Driver.injectPenPointerAction") {
1179 if (pointer.GetFingers() != 1) {
1180 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Finger number must be 1 when injecting pen action");
1181 return;
1182 }
1183 uiOpArgs.touchPressure_ = ReadCallArg<float>(in, INDEX_TWO, uiOpArgs.touchPressure_);
1184 driver.PerformPenTouch(touch, uiOpArgs, out.exception_);
1185 }
1186 };
1187 server.AddHandler("Driver.injectMultiPointerAction", multiPointerAction);
1188 server.AddHandler("Driver.injectPenPointerAction", multiPointerAction);
1189 }
1190
RegisterUiDriverMouseClickOperators()1191 static void RegisterUiDriverMouseClickOperators()
1192 {
1193 auto &server = FrontendApiServer::Get();
1194 auto mouseClick = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1195 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1196 UiOpArgs uiOpArgs;
1197 auto pointJson = ReadCallArg<json>(in, INDEX_ZERO);
1198 auto displayId = ReadArgFromJson<int32_t>(pointJson, "displayId", UNASSIGNED);
1199 auto point = Point(pointJson["x"], pointJson["y"], displayId);
1200 auto button = ReadCallArg<MouseButton>(in, INDEX_ONE);
1201 auto key1 = ReadCallArg<int32_t>(in, INDEX_TWO, KEYCODE_NONE);
1202 auto key2 = ReadCallArg<int32_t>(in, INDEX_THREE, KEYCODE_NONE);
1203 uiOpArgs.longClickHoldMs_ = ReadCallArg<uint32_t>(in, INDEX_FOUR, uiOpArgs.longClickHoldMs_);
1204 const uint32_t minLongClickHoldMs = 1500;
1205 if (uiOpArgs.longClickHoldMs_ < minLongClickHoldMs) {
1206 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Invalid longclick hold time");
1207 return;
1208 }
1209 auto op = TouchOp::CLICK;
1210 if (in.apiId_ == "Driver.mouseDoubleClick") {
1211 op = TouchOp::DOUBLE_CLICK_P;
1212 } else if (in.apiId_ == "Driver.mouseLongClick") {
1213 op = TouchOp::LONG_CLICK;
1214 }
1215 auto touch = MouseClick(op, point, button, key1, key2);
1216 driver.PerformMouseAction(touch, uiOpArgs, out.exception_);
1217 };
1218 server.AddHandler("Driver.mouseClick", mouseClick);
1219 server.AddHandler("Driver.mouseDoubleClick", mouseClick);
1220 server.AddHandler("Driver.mouseLongClick", mouseClick);
1221 }
1222
RegisterUiDriverMouseMoveOperators()1223 static void RegisterUiDriverMouseMoveOperators()
1224 {
1225 auto &server = FrontendApiServer::Get();
1226 auto mouseSwipe = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1227 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1228 auto pointJson1 = ReadCallArg<json>(in, INDEX_ZERO);
1229 auto pointJson2 = ReadCallArg<json>(in, INDEX_ONE);
1230 auto displayId1 = ReadArgFromJson<int32_t>(pointJson1, "displayId", UNASSIGNED);
1231 auto displayId2 = ReadArgFromJson<int32_t>(pointJson2, "displayId", UNASSIGNED);
1232 auto from = Point(pointJson1["x"], pointJson1["y"], displayId1);
1233 auto to = Point(pointJson2["x"], pointJson2["y"], displayId2);
1234 if (from.displayId_ != to.displayId_) {
1235 out.exception_ = ApiCallErr(ERR_INVALID_INPUT,
1236 "The start point and end point must belong to the same display.");
1237 return;
1238 }
1239 UiOpArgs uiOpArgs;
1240 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_TWO, uiOpArgs.swipeVelocityPps_);
1241 uiOpArgs.longClickHoldMs_ = ReadCallArg<uint32_t>(in, INDEX_THREE, uiOpArgs.longClickHoldMs_);
1242 const uint32_t minLongClickHoldMs = 1500;
1243 if (uiOpArgs.longClickHoldMs_ < minLongClickHoldMs) {
1244 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Invalid longclick hold time");
1245 return;
1246 }
1247 CheckSwipeVelocityPps(uiOpArgs);
1248 auto op = TouchOp::SWIPE;
1249 if (in.apiId_ == "Driver.mouseDrag") {
1250 op = TouchOp::DRAG;
1251 }
1252 auto touch = MouseSwipe(op, from, to);
1253 driver.PerformMouseAction(touch, uiOpArgs, out.exception_);
1254 };
1255 server.AddHandler("Driver.mouseMoveWithTrack", mouseSwipe);
1256 server.AddHandler("Driver.mouseDrag", mouseSwipe);
1257 auto mouseMoveTo = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1258 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1259 auto pointJson = ReadCallArg<json>(in, INDEX_ZERO);
1260 UiOpArgs uiOpArgs;
1261 auto displayId = ReadArgFromJson<int32_t>(pointJson, "displayId", UNASSIGNED);
1262 auto point = Point(pointJson["x"], pointJson["y"], displayId);
1263 auto touch = MouseMoveTo(point);
1264 driver.PerformMouseAction(touch, uiOpArgs, out.exception_);
1265 };
1266 server.AddHandler("Driver.mouseMoveTo", mouseMoveTo);
1267 }
1268
RegisterUiDriverMouseScrollOperators()1269 static void RegisterUiDriverMouseScrollOperators()
1270 {
1271 auto &server = FrontendApiServer::Get();
1272 auto mouseScroll = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1273 const uint32_t maxScrollSpeed = 500;
1274 const uint32_t defaultScrollSpeed = 20;
1275 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1276 Point point(0, 0);
1277 uint32_t speed = defaultScrollSpeed;
1278 uint32_t scrollValue = 0;
1279 UiOpArgs uiOpArgs;
1280 auto key1 = KEYCODE_NONE;
1281 auto key2 = KEYCODE_NONE;
1282 if (in.apiId_ == "Driver.crownRotate") {
1283 if (!driver.IsWearable()) {
1284 out.exception_ = ApiCallErr(ERR_NO_SYSTEM_CAPABILITY, "Capability not support");
1285 return;
1286 }
1287 scrollValue = ReadCallArg<int32_t>(in, INDEX_ZERO);
1288 speed = ReadCallArg<uint32_t>(in, INDEX_ONE, defaultScrollSpeed);
1289 auto screenSize = driver.GetDisplaySize(out.exception_, UNASSIGNED);
1290 point = Point(screenSize.px_ / 2, screenSize.py_ / 2, screenSize.displayId_);
1291 } else if (in.apiId_ == "Driver.mouseScroll") {
1292 auto pointJson = ReadCallArg<json>(in, INDEX_ZERO);
1293 auto displayId = ReadArgFromJson<int32_t>(pointJson, "displayId", UNASSIGNED);
1294 point = Point(pointJson["x"], pointJson["y"], displayId);
1295 scrollValue = ReadCallArg<int32_t>(in, INDEX_TWO);
1296 auto adown = ReadCallArg<bool>(in, INDEX_ONE);
1297 scrollValue = adown ? scrollValue : -scrollValue;
1298 key1 = ReadCallArg<int32_t>(in, INDEX_THREE, KEYCODE_NONE);
1299 key2 = ReadCallArg<int32_t>(in, INDEX_FOUR, KEYCODE_NONE);
1300 speed = ReadCallArg<uint32_t>(in, INDEX_FIVE, defaultScrollSpeed);
1301 }
1302 if (speed < 1 || speed > maxScrollSpeed) {
1303 speed = defaultScrollSpeed;
1304 }
1305 auto touch = MouseScroll(point, scrollValue, key1, key2, speed);
1306 driver.PerformMouseAction(touch, uiOpArgs, out.exception_);
1307 ConvertError(out);
1308 };
1309 server.AddHandler("Driver.mouseScroll", mouseScroll);
1310 server.AddHandler("Driver.crownRotate", mouseScroll);
1311 }
1312
RegisterUiDriverTouchPadOperators()1313 static void RegisterUiDriverTouchPadOperators()
1314 {
1315 auto &server = FrontendApiServer::Get();
1316 auto touchPadMultiFingerSwipe = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1317 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1318 UiOpArgs uiOpArgs;
1319 auto fingers = ReadCallArg<int32_t>(in, INDEX_ZERO);
1320 if (fingers < 3 || fingers > 4) {
1321 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Number of illegal fingers");
1322 return;
1323 }
1324 auto direction = ReadCallArg<Direction>(in, INDEX_ONE);
1325 if (direction < TO_LEFT || direction > TO_DOWN) {
1326 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Illegal direction");
1327 return;
1328 }
1329 auto stay = false;
1330 auto speed = uiOpArgs.defaultTouchPadSwipeVelocityPps_;
1331 auto touchPadSwipeOptions = ReadCallArg<json>(in, INDEX_TWO, json());
1332 if (!touchPadSwipeOptions.empty()) {
1333 if (touchPadSwipeOptions.contains("stay") && touchPadSwipeOptions["stay"].is_boolean()) {
1334 stay = touchPadSwipeOptions["stay"];
1335 }
1336 if (touchPadSwipeOptions.contains("speed") && touchPadSwipeOptions["speed"].is_number()) {
1337 speed = touchPadSwipeOptions["speed"];
1338 }
1339 if (speed < uiOpArgs.minSwipeVelocityPps_ || speed > uiOpArgs.maxSwipeVelocityPps_) {
1340 LOG_W("The swipe velocity out of range");
1341 speed = uiOpArgs.defaultTouchPadSwipeVelocityPps_;
1342 }
1343 }
1344 uiOpArgs.swipeVelocityPps_ = speed;
1345 auto touch = TouchPadAction(fingers, direction, stay);
1346 driver.PerformTouchPadAction(touch, uiOpArgs, out.exception_);
1347 };
1348 server.AddHandler("Driver.touchPadMultiFingerSwipe", touchPadMultiFingerSwipe);
1349 }
1350
RegisterUiDriverPenOperators()1351 static void RegisterUiDriverPenOperators()
1352 {
1353 auto &server = FrontendApiServer::Get();
1354 auto genericPenAction = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1355 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1356 UiOpArgs uiOpArgs;
1357 auto point0Json = ReadCallArg<json>(in, INDEX_ZERO);
1358 auto displayId = ReadArgFromJson<int32_t>(point0Json, "displayId", UNASSIGNED);
1359 const auto point0 = Point(point0Json["x"], point0Json["y"], displayId);
1360 const auto screenSize = driver.GetDisplaySize(out.exception_, displayId);
1361 const auto screen = Rect(0, screenSize.px_, 0, screenSize.py_);
1362 if (!RectAlgorithm::IsInnerPoint(screen, point0)) {
1363 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "The point is not on the screen");
1364 return;
1365 }
1366 auto point1 = Point(0, 0);
1367 auto op = TouchOp::CLICK;
1368 if (in.apiId_ == "Driver.penLongClick") {
1369 op = TouchOp::LONG_CLICK;
1370 uiOpArgs.touchPressure_ = ReadCallArg<float>(in, INDEX_ONE, uiOpArgs.touchPressure_);
1371 } else if (in.apiId_ == "Driver.penDoubleClick") {
1372 op = TouchOp::DOUBLE_CLICK_P;
1373 } else if (in.apiId_ == "Driver.penSwipe") {
1374 op = TouchOp::SWIPE;
1375 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_TWO, uiOpArgs.swipeVelocityPps_);
1376 CheckSwipeVelocityPps(uiOpArgs);
1377 auto point1Json = ReadCallArg<json>(in, INDEX_ONE);
1378 auto displayId1 = ReadArgFromJson<int32_t>(point1Json, "displayId", UNASSIGNED);
1379 point1 = Point(point1Json["x"], point1Json["y"], displayId1);
1380 if (!RectAlgorithm::IsInnerPoint(screen, point1)) {
1381 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "The point is not on the screen");
1382 return;
1383 }
1384 uiOpArgs.touchPressure_ = ReadCallArg<float>(in, INDEX_THREE, uiOpArgs.touchPressure_);
1385 }
1386 if (op == TouchOp::SWIPE) {
1387 auto touch = GenericSwipe(op, point0, point1);
1388 driver.PerformPenTouch(touch, uiOpArgs, out.exception_);
1389 } else {
1390 auto touch = GenericClick(op, point0);
1391 driver.PerformPenTouch(touch, uiOpArgs, out.exception_);
1392 }
1393 };
1394 server.AddHandler("Driver.penClick", genericPenAction);
1395 server.AddHandler("Driver.penLongClick", genericPenAction);
1396 server.AddHandler("Driver.penDoubleClick", genericPenAction);
1397 server.AddHandler("Driver.penSwipe", genericPenAction);
1398 }
1399
RegisterUiDriverDisplayOperators()1400 static void RegisterUiDriverDisplayOperators()
1401 {
1402 auto &server = FrontendApiServer::Get();
1403 auto genericDisplayOperator = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1404 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1405 if (in.apiId_ == "Driver.setDisplayRotation") {
1406 auto rotation = ReadCallArg<DisplayRotation>(in, INDEX_ZERO);
1407 driver.SetDisplayRotation(rotation, out.exception_);
1408 } else if (in.apiId_ == "Driver.setDisplayRotationEnabled") {
1409 auto enabled = ReadCallArg<bool>(in, INDEX_ZERO);
1410 driver.SetDisplayRotationEnabled(enabled, out.exception_);
1411 } else if (in.apiId_ == "Driver.waitForIdle") {
1412 auto idleTime = ReadCallArg<int32_t>(in, INDEX_ZERO);
1413 auto timeout = ReadCallArg<int32_t>(in, INDEX_ONE);
1414 out.resultValue_ = driver.WaitForUiSteady(idleTime, timeout, out.exception_);
1415 } else if (in.apiId_ == "Driver.wakeUpDisplay") {
1416 driver.WakeUpDisplay(out.exception_);
1417 }
1418 };
1419 auto genericGetDisplayAttrOperator = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1420 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1421 auto displayId = ReadCallArg<int32_t>(in, INDEX_ZERO, UNASSIGNED);
1422 if (!driver.CheckDisplayExist(displayId)) {
1423 out.exception_ = ApiCallErr(ERR_INVALID_PARAM, "Invalid display id.");
1424 return;
1425 }
1426 if (in.apiId_ == "Driver.getDisplayRotation") {
1427 out.resultValue_ = driver.GetDisplayRotation(out.exception_, displayId);
1428 } else if (in.apiId_ == "Driver.getDisplaySize") {
1429 auto result = driver.GetDisplaySize(out.exception_, displayId);
1430 json data;
1431 data["x"] = result.px_;
1432 data["y"] = result.py_;
1433 out.resultValue_ = data;
1434 } else if (in.apiId_ == "Driver.getDisplayDensity") {
1435 auto result = driver.GetDisplayDensity(out.exception_, displayId);
1436 json data;
1437 data["x"] = result.px_;
1438 data["y"] = result.py_;
1439 out.resultValue_ = data;
1440 }
1441 };
1442 server.AddHandler("Driver.setDisplayRotation", genericDisplayOperator);
1443 server.AddHandler("Driver.getDisplayRotation", genericGetDisplayAttrOperator);
1444 server.AddHandler("Driver.setDisplayRotationEnabled", genericDisplayOperator);
1445 server.AddHandler("Driver.waitForIdle", genericDisplayOperator);
1446 server.AddHandler("Driver.wakeUpDisplay", genericDisplayOperator);
1447 server.AddHandler("Driver.getDisplaySize", genericGetDisplayAttrOperator);
1448 server.AddHandler("Driver.getDisplayDensity", genericGetDisplayAttrOperator);
1449 }
1450
1451 template <UiAttr kAttr, bool kString = false>
GenericComponentAttrGetter(const ApiCallInfo & in,ApiReplyInfo & out)1452 static void GenericComponentAttrGetter(const ApiCallInfo &in, ApiReplyInfo &out)
1453 {
1454 constexpr auto attrName = ATTR_NAMES[kAttr];
1455 auto &image = GetBackendObject<Widget>(in.callerObjRef_);
1456 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1457 auto snapshot = driver.RetrieveWidget(image, out.exception_);
1458 if (out.exception_.code_ != NO_ERROR) {
1459 out.resultValue_ = nullptr; // exception, return null
1460 return;
1461 }
1462 if (attrName == ATTR_NAMES[UiAttr::BOUNDSCENTER]) { // getBoundsCenter
1463 const auto bounds = snapshot->GetBounds();
1464 json data;
1465 data["x"] = bounds.GetCenterX();
1466 data["y"] = bounds.GetCenterY();
1467 data["displayId"] = snapshot->GetDisplayId();
1468 out.resultValue_ = data;
1469 return;
1470 }
1471 if (attrName == ATTR_NAMES[UiAttr::BOUNDS]) { // getBounds
1472 const auto bounds = snapshot->GetBounds();
1473 json data;
1474 data["left"] = bounds.left_;
1475 data["top"] = bounds.top_;
1476 data["right"] = bounds.right_;
1477 data["bottom"] = bounds.bottom_;
1478 data["displayId"] = snapshot->GetDisplayId();
1479 out.resultValue_ = data;
1480 return;
1481 }
1482 if (attrName == ATTR_NAMES[UiAttr::DISPLAY_ID]) {
1483 out.resultValue_ = snapshot->GetDisplayId();
1484 return;
1485 }
1486 // convert value-string to json value of target type
1487 auto attrValue = snapshot->GetAttr(kAttr);
1488 if (attrValue == "NA") {
1489 out.resultValue_ = nullptr; // no such attribute, return null
1490 } else if (kString) {
1491 out.resultValue_ = attrValue;
1492 } else {
1493 out.resultValue_ = nlohmann::json::parse(attrValue);
1494 }
1495 }
1496
RegisterExtensionHandler()1497 static void RegisterExtensionHandler()
1498 {
1499 auto &server = FrontendApiServer::Get();
1500 auto genericOperationHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1501 auto &image = GetBackendObject<Widget>(in.callerObjRef_);
1502 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1503 auto snapshot = driver.RetrieveWidget(image, out.exception_);
1504 if (out.exception_.code_ != NO_ERROR || snapshot == nullptr) {
1505 out.resultValue_ = nullptr; // exception, return null
1506 return;
1507 }
1508 json data;
1509 for (auto i = 0; i < UiAttr::HIERARCHY + 1; ++i) {
1510 if (i == UiAttr::BOUNDS) {
1511 const auto bounds = snapshot->GetBounds();
1512 json rect;
1513 rect["left"] = bounds.left_;
1514 rect["top"] = bounds.top_;
1515 rect["right"] = bounds.right_;
1516 rect["bottom"] = bounds.bottom_;
1517 data["bounds"] = rect;
1518 continue;
1519 }
1520 data[ATTR_NAMES[i].data()] = snapshot->GetAttr(static_cast<UiAttr> (i));
1521 }
1522 out.resultValue_ = data;
1523 };
1524 server.AddHandler("Component.getAllProperties", genericOperationHandler);
1525
1526 auto genericSetModeHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1527 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1528 auto mode = ReadCallArg<uint32_t>(in, INDEX_ZERO);
1529 DCHECK(mode < AamsWorkMode::END);
1530 driver.SetAamsWorkMode(static_cast<AamsWorkMode>(mode));
1531 };
1532 server.AddHandler("Driver.SetAamsWorkMode", genericSetModeHandler);
1533 auto genericCloseAamsEventHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1534 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1535 driver.CloseAamsEvent();
1536 };
1537 server.AddHandler("Driver.CloseAamsEvent", genericCloseAamsEventHandler);
1538 auto genericOpenAamsEventHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1539 auto &driver = GetBackendObject<UiDriver>(in.callerObjRef_);
1540 driver.OpenAamsEvent();
1541 };
1542 server.AddHandler("Driver.OpenAamsEvent", genericOpenAamsEventHandler);
1543 }
1544
RegisterUiComponentAttrGetters()1545 static void RegisterUiComponentAttrGetters()
1546 {
1547 auto &server = FrontendApiServer::Get();
1548 server.AddHandler("Component.getAccessibilityId", GenericComponentAttrGetter<UiAttr::ACCESSIBILITY_ID>);
1549 server.AddHandler("Component.getText", GenericComponentAttrGetter<UiAttr::TEXT, true>);
1550 server.AddHandler("Component.getHint", GenericComponentAttrGetter<UiAttr::HINT, true>);
1551 server.AddHandler("Component.getDescription", GenericComponentAttrGetter<UiAttr::DESCRIPTION, true>);
1552 server.AddHandler("Component.getId", GenericComponentAttrGetter<UiAttr::ID, true>);
1553 server.AddHandler("Component.getType", GenericComponentAttrGetter<UiAttr::TYPE, true>);
1554 server.AddHandler("Component.isEnabled", GenericComponentAttrGetter<UiAttr::ENABLED>);
1555 server.AddHandler("Component.isFocused", GenericComponentAttrGetter<UiAttr::FOCUSED>);
1556 server.AddHandler("Component.isSelected", GenericComponentAttrGetter<UiAttr::SELECTED>);
1557 server.AddHandler("Component.isClickable", GenericComponentAttrGetter<UiAttr::CLICKABLE>);
1558 server.AddHandler("Component.isLongClickable", GenericComponentAttrGetter<UiAttr::LONG_CLICKABLE>);
1559 server.AddHandler("Component.isScrollable", GenericComponentAttrGetter<UiAttr::SCROLLABLE>);
1560 server.AddHandler("Component.isCheckable", GenericComponentAttrGetter<UiAttr::CHECKABLE>);
1561 server.AddHandler("Component.isChecked", GenericComponentAttrGetter<UiAttr::CHECKED>);
1562 server.AddHandler("Component.getBounds", GenericComponentAttrGetter<UiAttr::BOUNDS>);
1563 server.AddHandler("Component.getBoundsCenter", GenericComponentAttrGetter<UiAttr::BOUNDSCENTER>);
1564 server.AddHandler("Component.getDisplayId", GenericComponentAttrGetter<UiAttr::DISPLAY_ID>);
1565 server.AddHandler("Component.getOriginalText", GenericComponentAttrGetter<UiAttr::ORIGINALTEXT, true>);
1566 }
1567
RegisterUiComponentClickOperation()1568 static void RegisterUiComponentClickOperation()
1569 {
1570 auto &server = FrontendApiServer::Get();
1571 auto genericOperationHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1572 auto &widget = GetBackendObject<Widget>(in.callerObjRef_);
1573 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1574 UiOpArgs uiOpArgs;
1575 auto wOp = WidgetOperator(driver, widget, uiOpArgs);
1576 if (in.apiId_ == "Component.click") {
1577 wOp.GenericClick(TouchOp::CLICK, out.exception_);
1578 } else if (in.apiId_ == "Component.longClick") {
1579 wOp.GenericClick(TouchOp::LONG_CLICK, out.exception_);
1580 } else if (in.apiId_ == "Component.doubleClick") {
1581 wOp.GenericClick(TouchOp::DOUBLE_CLICK_P, out.exception_);
1582 }
1583 };
1584 server.AddHandler("Component.click", genericOperationHandler);
1585 server.AddHandler("Component.longClick", genericOperationHandler);
1586 server.AddHandler("Component.doubleClick", genericOperationHandler);
1587 }
1588
RegisterUiComponentMoveOperation()1589 static void RegisterUiComponentMoveOperation()
1590 {
1591 auto &server = FrontendApiServer::Get();
1592 auto genericOperationHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1593 auto &widget = GetBackendObject<Widget>(in.callerObjRef_);
1594 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1595 UiOpArgs uiOpArgs;
1596 auto wOp = WidgetOperator(driver, widget, uiOpArgs);
1597 if (in.apiId_ == "Component.scrollToTop") {
1598 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_ZERO, uiOpArgs.swipeVelocityPps_);
1599 CheckSwipeVelocityPps(uiOpArgs);
1600 wOp.ScrollToEnd(true, out.exception_);
1601 } else if (in.apiId_ == "Component.scrollToBottom") {
1602 uiOpArgs.swipeVelocityPps_ = ReadCallArg<uint32_t>(in, INDEX_ZERO, uiOpArgs.swipeVelocityPps_);
1603 CheckSwipeVelocityPps(uiOpArgs);
1604 wOp.ScrollToEnd(false, out.exception_);
1605 } else if (in.apiId_ == "Component.dragTo") {
1606 auto &widgetTo = GetBackendObject<Widget>(ReadCallArg<string>(in, INDEX_ZERO));
1607 wOp.DragIntoWidget(widgetTo, out.exception_);
1608 } else if (in.apiId_ == "Component.scrollSearch") {
1609 auto &selector = GetBackendObject<WidgetSelector>(ReadCallArg<string>(in, INDEX_ZERO));
1610 bool vertical = ReadCallArg<bool>(in, INDEX_ONE, true);
1611 uiOpArgs.scrollWidgetDeadZone_ = ReadCallArg<int32_t>(in, INDEX_TWO, 80);
1612 if (!wOp.CheckDeadZone(vertical, out.exception_)) {
1613 return;
1614 }
1615 auto res = wOp.ScrollFindWidget(selector, vertical, out.exception_);
1616 if (res != nullptr) {
1617 out.resultValue_ = StoreBackendObject(move(res), sDriverBindingMap.find(in.callerObjRef_)->second);
1618 }
1619 }
1620 };
1621 server.AddHandler("Component.scrollToTop", genericOperationHandler);
1622 server.AddHandler("Component.scrollToBottom", genericOperationHandler);
1623 server.AddHandler("Component.dragTo", genericOperationHandler);
1624 server.AddHandler("Component.scrollSearch", genericOperationHandler);
1625 }
1626
RegisterUiComponentTextOperation()1627 static void RegisterUiComponentTextOperation()
1628 {
1629 auto &server = FrontendApiServer::Get();
1630 auto genericOperationHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1631 auto &widget = GetBackendObject<Widget>(in.callerObjRef_);
1632 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1633 UiOpArgs uiOpArgs;
1634 auto wOp = WidgetOperator(driver, widget, uiOpArgs);
1635 if (in.apiId_ == "Component.inputText") {
1636 auto inputModeJson = ReadCallArg<json>(in, INDEX_ONE, json());
1637 ReadInputModeFromJson(inputModeJson, uiOpArgs.inputByPasteBoard_, uiOpArgs.inputAdditional_);
1638 auto wOpToInput = WidgetOperator(driver, widget, uiOpArgs);
1639 wOpToInput.InputText(ReadCallArg<string>(in, INDEX_ZERO), out.exception_);
1640 } else if (in.apiId_ == "Component.clearText") {
1641 wOp.InputText("", out.exception_);
1642 }
1643 };
1644 server.AddHandler("Component.inputText", genericOperationHandler);
1645 server.AddHandler("Component.clearText", genericOperationHandler);
1646 }
1647
RegisterUiDriverMultiFingerOperations()1648 static void RegisterUiDriverMultiFingerOperations()
1649 {
1650 auto &server = FrontendApiServer::Get();
1651 auto genericOperationHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1652 auto &widget = GetBackendObject<Widget>(in.callerObjRef_);
1653 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1654 UiOpArgs uiOpArgs;
1655 auto wOp = WidgetOperator(driver, widget, uiOpArgs);
1656 if (in.apiId_ == "Component.pinchOut") {
1657 auto pinchScale = ReadCallArg<float_t>(in, INDEX_ZERO);
1658 if (pinchScale < 1) {
1659 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Expect integer which gerater 1");
1660 }
1661 wOp.PinchWidget(pinchScale, out.exception_);
1662 } else if (in.apiId_ == "Component.pinchIn") {
1663 auto pinchScale = ReadCallArg<float_t>(in, INDEX_ZERO);
1664 if (pinchScale > 1) {
1665 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Expect integer which ranges from 0 to 1.");
1666 }
1667 wOp.PinchWidget(pinchScale, out.exception_);
1668 }
1669 };
1670 server.AddHandler("Component.pinchOut", genericOperationHandler);
1671 server.AddHandler("Component.pinchIn", genericOperationHandler);
1672 }
1673
RegisterUiWindowAttrGetters()1674 static void RegisterUiWindowAttrGetters()
1675 {
1676 auto &server = FrontendApiServer::Get();
1677 auto genericGetter = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1678 auto &window = GetBackendObject<Window>(in.callerObjRef_);
1679 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1680 auto snapshot = driver.RetrieveWindow(window, out.exception_);
1681 if (out.exception_.code_ != NO_ERROR) {
1682 out.resultValue_ = nullptr; // exception, return null
1683 return;
1684 }
1685 if (in.apiId_ == "UiWindow.getBundleName") {
1686 out.resultValue_ = snapshot->bundleName_;
1687 } else if (in.apiId_ == "UiWindow.getBounds") {
1688 json data;
1689 data["left"] = snapshot->bounds_.left_;
1690 data["top"] = snapshot->bounds_.top_;
1691 data["right"] = snapshot->bounds_.right_;
1692 data["bottom"] = snapshot->bounds_.bottom_;
1693 data["displayId"] = snapshot->displayId_;
1694 out.resultValue_ = data;
1695 } else if (in.apiId_ == "UiWindow.getTitle") {
1696 out.resultValue_ = snapshot->title_;
1697 } else if (in.apiId_ == "UiWindow.getWindowMode") {
1698 out.resultValue_ = (uint8_t)(snapshot->mode_ - 1);
1699 } else if (in.apiId_ == "UiWindow.isFocused") {
1700 out.resultValue_ = snapshot->focused_;
1701 } else if (in.apiId_ == "UiWindow.isActive") {
1702 out.resultValue_ = snapshot->actived_;
1703 } else if (in.apiId_ == "UiWindow.getDisplayId") {
1704 out.resultValue_ = snapshot->displayId_;
1705 }
1706 };
1707 server.AddHandler("UiWindow.getBundleName", genericGetter);
1708 server.AddHandler("UiWindow.getBounds", genericGetter);
1709 server.AddHandler("UiWindow.getTitle", genericGetter);
1710 server.AddHandler("UiWindow.getWindowMode", genericGetter);
1711 server.AddHandler("UiWindow.isFocused", genericGetter);
1712 server.AddHandler("UiWindow.isActive", genericGetter);
1713 server.AddHandler("UiWindow.getDisplayId", genericGetter);
1714 }
1715
RegisterUiWindowOperators()1716 static void RegisterUiWindowOperators()
1717 {
1718 auto &server = FrontendApiServer::Get();
1719 auto genericWinOperationHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1720 auto &image = GetBackendObject<Window>(in.callerObjRef_);
1721 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1722 auto window = driver.RetrieveWindow(image, out.exception_);
1723 if (out.exception_.code_ != NO_ERROR || window == nullptr) {
1724 return;
1725 }
1726 UiOpArgs uiOpArgs;
1727 auto wOp = WindowOperator(driver, *window, uiOpArgs);
1728 auto action = in.apiId_;
1729 if (action == "UiWindow.resize") {
1730 auto width = ReadCallArg<int32_t>(in, INDEX_ZERO);
1731 auto highth = ReadCallArg<int32_t>(in, INDEX_ONE);
1732 auto direction = ReadCallArg<ResizeDirection>(in, INDEX_TWO);
1733 if ((((direction == LEFT) || (direction == RIGHT)) && highth != window->bounds_.GetHeight()) ||
1734 (((direction == D_UP) || (direction == D_DOWN)) && width != window->bounds_.GetWidth())) {
1735 out.exception_ = ApiCallErr(ERR_OPERATION_UNSUPPORTED, "Resize cannot be done in this direction");
1736 return;
1737 }
1738 wOp.Resize(width, highth, direction, out);
1739 } else if (action == "UiWindow.focus") {
1740 wOp.Focus(out);
1741 }
1742 };
1743 server.AddHandler("UiWindow.focus", genericWinOperationHandler);
1744 server.AddHandler("UiWindow.resize", genericWinOperationHandler);
1745 }
1746
RegisterUiWinBarOperators()1747 static void RegisterUiWinBarOperators()
1748 {
1749 auto &server = FrontendApiServer::Get();
1750 auto genericWinBarOperationHandler = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1751 auto &image = GetBackendObject<Window>(in.callerObjRef_);
1752 auto &driver = GetBoundUiDriver(in.callerObjRef_);
1753 auto window = driver.RetrieveWindow(image, out.exception_);
1754 if (out.exception_.code_ != NO_ERROR || window == nullptr) {
1755 return;
1756 }
1757 UiOpArgs uiOpArgs;
1758 auto wOp = WindowOperator(driver, *window, uiOpArgs);
1759 auto action = in.apiId_;
1760 if (driver.IsAdjustWindowModeEnable()) {
1761 if (action == "UiWindow.split") {
1762 wOp.Split(out);
1763 } else if (action == "UiWindow.maximize") {
1764 wOp.Maximize(out);
1765 } else if (action == "UiWindow.resume") {
1766 wOp.Resume(out);
1767 } else if (action == "UiWindow.minimize") {
1768 wOp.Minimize(out);
1769 } else if (action == "UiWindow.close") {
1770 wOp.Close(out);
1771 } else if (action == "UiWindow.moveTo") {
1772 auto endX = ReadCallArg<uint32_t>(in, INDEX_ZERO);
1773 auto endY = ReadCallArg<uint32_t>(in, INDEX_ONE);
1774 wOp.MoveTo(endX, endY, out);
1775 }
1776 } else {
1777 out.exception_ = ApiCallErr(ERR_OPERATION_UNSUPPORTED, "this device can not support this action");
1778 }
1779 };
1780 server.AddHandler("UiWindow.split", genericWinBarOperationHandler);
1781 server.AddHandler("UiWindow.maximize", genericWinBarOperationHandler);
1782 server.AddHandler("UiWindow.resume", genericWinBarOperationHandler);
1783 server.AddHandler("UiWindow.minimize", genericWinBarOperationHandler);
1784 server.AddHandler("UiWindow.close", genericWinBarOperationHandler);
1785 server.AddHandler("UiWindow.moveTo", genericWinBarOperationHandler);
1786 }
1787
RegisterPointerMatrixOperators()1788 static void RegisterPointerMatrixOperators()
1789 {
1790 auto &server = FrontendApiServer::Get();
1791 auto create = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1792 UiOpArgs uiOpArgs;
1793 auto finger = ReadCallArg<uint32_t>(in, INDEX_ZERO);
1794 if (finger < 1 || finger > uiOpArgs.maxMultiTouchFingers) {
1795 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Number of illegal fingers");
1796 return;
1797 }
1798 auto step = ReadCallArg<uint32_t>(in, INDEX_ONE);
1799 if (step < 1 || step > uiOpArgs.maxMultiTouchSteps) {
1800 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Number of illegal steps");
1801 return;
1802 }
1803 out.resultValue_ = StoreBackendObject(make_unique<PointerMatrix>(finger, step));
1804 };
1805 server.AddHandler("PointerMatrix.create", create);
1806
1807 auto setPoint = [](const ApiCallInfo &in, ApiReplyInfo &out) {
1808 auto &pointer = GetBackendObject<PointerMatrix>(in.callerObjRef_);
1809 auto finger = ReadCallArg<uint32_t>(in, INDEX_ZERO);
1810 if (finger < 0 || finger >= pointer.GetFingers()) {
1811 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Number of illegal fingers");
1812 return;
1813 }
1814 auto step = ReadCallArg<uint32_t>(in, INDEX_ONE);
1815 if (step < 0 || step >= pointer.GetSteps()) {
1816 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Number of illegal steps");
1817 return;
1818 }
1819 auto pointJson = ReadCallArg<json>(in, INDEX_TWO);
1820 if (pointJson.empty()) {
1821 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "Point cannot be empty");
1822 return;
1823 }
1824 auto displayId = ReadArgFromJson<int32_t>(pointJson, "displayId", UNASSIGNED);
1825 if (!(finger == 0 && step == 0) && pointer.At(0, 0).point_.displayId_ != displayId) {
1826 out.exception_ = ApiCallErr(ERR_INVALID_INPUT, "All points must belong to the same display.");
1827 return;
1828 }
1829 const auto point = Point(pointJson["x"], pointJson["y"], displayId);
1830 pointer.At(finger, step).point_ = point;
1831 pointer.At(finger, step).flags_ = 1;
1832 };
1833 server.AddHandler("PointerMatrix.setPoint", setPoint);
1834 }
1835
1836 /** Register frontendApiHandlers and preprocessors on startup.*/
RegisterApiHandlers()1837 __attribute__((constructor)) static void RegisterApiHandlers()
1838 {
1839 auto &server = FrontendApiServer::Get();
1840 server.AddCommonPreprocessor("APiCallInfoChecker", APiCallInfoChecker);
1841 server.AddHandler("BackendObjectsCleaner", BackendObjectsCleaner);
1842 RegisterOnBuilders();
1843 RegisterUiDriverComponentFinders();
1844 RegisterUiDriverWindowFinder();
1845 RegisterUiDriverMiscMethods();
1846 RegisterUiDriverKeyOperation();
1847 RegisterUiDriverInputText();
1848 RegisterUiDriverTouchOperators();
1849 RegisterUiComponentAttrGetters();
1850 RegisterUiComponentClickOperation();
1851 RegisterUiComponentMoveOperation();
1852 RegisterUiComponentTextOperation();
1853 RegisterUiDriverMultiFingerOperations();
1854 RegisterUiWindowAttrGetters();
1855 RegisterUiWindowOperators();
1856 RegisterUiWinBarOperators();
1857 RegisterPointerMatrixOperators();
1858 RegisterUiDriverFlingOperators();
1859 RegisterUiDriverMultiPointerOperators();
1860 RegisterUiDriverDisplayOperators();
1861 RegisterUiDriverMouseClickOperators();
1862 RegisterUiDriverMouseMoveOperators();
1863 RegisterUiDriverMouseScrollOperators();
1864 RegisterUiEventObserverMethods();
1865 RegisterExtensionHandler();
1866 RegisterUiDriverTouchPadOperators();
1867 RegisterUiDriverPenOperators();
1868 }
1869 } // namespace OHOS::uitest
1870