• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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