1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "input_display_bind_helper.h"
17 
18 #include <algorithm>
19 #include <cctype>
20 #include <filesystem>
21 #include <fstream>
22 #include <iostream>
23 #include <list>
24 #include <sstream>
25 
26 #include "mmi_log.h"
27 #include "parameters.h"
28 #include "util.h"
29 
30 #undef MMI_LOG_DOMAIN
31 #define MMI_LOG_DOMAIN MMI_LOG_WINDOW
32 #undef MMI_LOG_TAG
33 #define MMI_LOG_TAG "InputDisplayBindHelper"
34 
35 namespace OHOS {
36 namespace MMI {
37 namespace {
38 const std::string FOLD_SCREEN_FLAG = system::GetParameter("const.window.foldscreen.type", "");
39 const std::string INPUT_DEVICE_NAME_CONFIG { "/sys_prod/etc/input/input_device_name.cfg" };
40 const std::string DIRECTORY { "/sys/devices/virtual/input" };
41 const std::string SEPARATOR { "/" };
42 const std::string SUFFIX { "0000:0000" };
43 const std::string INPUT { "input" };
44 const std::string EVENT { "event" };
45 const std::string NAME { "name" };
46 const int32_t DISPLAY_ID_MAIN { 0 };
47 const int32_t DISPLAY_ID_SUB { 5 };
48 }
49 
50 namespace fs = std::filesystem;
51 
IsDualDisplayFoldDevice()52 static bool IsDualDisplayFoldDevice()
53 {
54     return (!FOLD_SCREEN_FLAG.empty() && FOLD_SCREEN_FLAG[0] == '2');
55 }
56 
GetInputDeviceId() const57 int32_t BindInfo::GetInputDeviceId() const
58 {
59     return inputDeviceId_;
60 }
61 
GetInputDeviceName() const62 std::string BindInfo::GetInputDeviceName() const
63 {
64     return inputDeviceName_;
65 }
66 
GetDisplayId() const67 int32_t BindInfo::GetDisplayId() const
68 {
69     return displayId_;
70 }
71 
GetDisplayName() const72 std::string BindInfo::GetDisplayName() const
73 {
74     return displayName_;
75 }
76 
IsUnbind() const77 bool BindInfo::IsUnbind() const
78 {
79     return ((inputDeviceId_ == -1) || (displayId_ == -1));
80 }
81 
InputDeviceNotBind() const82 bool BindInfo::InputDeviceNotBind() const
83 {
84     return (inputDeviceId_ == -1);
85 }
86 
DisplayNotBind() const87 bool BindInfo::DisplayNotBind() const
88 {
89     return (displayId_ == -1);
90 }
91 
AddInputDevice(int32_t deviceId,const std::string & deviceName)92 bool BindInfo::AddInputDevice(int32_t deviceId, const std::string &deviceName)
93 {
94     if ((inputDeviceId_ != -1) || !inputDeviceName_.empty()) {
95         return false;
96     }
97     inputDeviceId_ = deviceId;
98     inputDeviceName_ = deviceName;
99     return true;
100 }
101 
RemoveInputDevice()102 void BindInfo::RemoveInputDevice()
103 {
104     inputDeviceId_ = -1;
105     inputDeviceName_.clear();
106 }
107 
AddDisplay(int32_t id,const std::string & name)108 bool BindInfo::AddDisplay(int32_t id, const std::string &name)
109 {
110     if ((displayId_ != -1) || !displayName_.empty()) {
111         return false;
112     }
113     displayId_ = id;
114     displayName_ = name;
115     return true;
116 }
117 
RemoveDisplay()118 void BindInfo::RemoveDisplay()
119 {
120     displayId_ = -1;
121     displayName_.clear();
122 }
123 
GetDesc() const124 std::string BindInfo::GetDesc() const
125 {
126     std::ostringstream oss;
127     oss << "InputDevice(id:" << inputDeviceId_ << ",name:" << inputDeviceName_ << "),Display(id:" << displayId_ <<
128         ",name:" << displayName_ << ")";
129     return oss.str();
130 }
131 
operator <(const BindInfo & l,const BindInfo & r)132 bool operator < (const BindInfo &l, const BindInfo &r)
133 {
134     if (l.inputDeviceId_ != r.inputDeviceId_) {
135         return (l.inputDeviceId_ < r.inputDeviceId_);
136     }
137     return (l.displayId_ < r.displayId_);
138 }
139 
operator <<(std::ostream & os,const BindInfo & r)140 std::ostream &operator << (std::ostream &os, const BindInfo &r)
141 {
142     os << r.inputDeviceName_ << "<=>" << r.displayName_ << std::endl;
143     return os;
144 }
145 
operator >>(std::istream & is,BindInfo & r)146 std::istream &operator >> (std::istream &is, BindInfo &r)
147 {
148     std::string line;
149     std::getline(is, line);
150     const std::string delim = "<=>";
151     std::string::size_type pos = line.find(delim);
152     if (pos == std::string::npos) {
153         return is;
154     }
155     r.inputDeviceName_ = line.substr(0, pos);
156     r.displayName_ = line.substr(pos + delim.length());
157     r.inputDeviceId_ = 0;
158     r.displayId_ = 0;
159     return is;
160 }
161 
GetDesc() const162 std::string BindInfos::GetDesc() const
163 {
164     int32_t index = 0;
165     std::ostringstream oss;
166     for (const auto &info : infos_) {
167         oss << "index:" << index << "," << info.GetDesc() << std::endl;
168     }
169     return oss.str();
170 }
171 
GetInfos() const172 const std::list<BindInfo> &BindInfos::GetInfos() const
173 {
174     return infos_;
175 }
176 
GetBindDisplayIdByInputDevice(int32_t inputDeviceId) const177 int32_t BindInfos::GetBindDisplayIdByInputDevice(int32_t inputDeviceId) const
178 {
179     for (const auto &item : infos_) {
180         if (item.GetInputDeviceId() == inputDeviceId) {
181             if (!item.IsUnbind()) {
182                 return item.GetDisplayId();
183             }
184         }
185     }
186     return -1;
187 }
188 
GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const189 std::string BindInfos::GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const
190 {
191     for (const auto &item : infos_) {
192         if (item.GetInputDeviceId() == inputDeviceId) {
193             if (!item.IsUnbind()) {
194                 return item.GetDisplayName();
195             }
196         }
197     }
198     return "";
199 }
200 
GetDisplayNameByInputDevice(const std::string & name) const201 std::string BindInfos::GetDisplayNameByInputDevice(const std::string &name) const
202 {
203     for (const auto &item : infos_) {
204         if (item.GetInputDeviceName() == name) {
205             return item.GetDisplayName();
206         }
207     }
208     return "";
209 }
210 
GetInputDeviceByDisplayName(const std::string & name) const211 std::string BindInfos::GetInputDeviceByDisplayName(const std::string &name) const
212 {
213     for (const auto &item : infos_) {
214         if (item.GetDisplayName() == name) {
215             return item.GetInputDeviceName();
216         }
217     }
218     return "";
219 }
220 
Add(const BindInfo & info)221 bool BindInfos::Add(const BindInfo &info)
222 {
223     auto it = infos_.begin();
224     for (; it != infos_.end(); ++it) {
225         if (info < *it) {
226             break;
227         }
228     }
229     auto it2 = infos_.emplace(it, std::move(info));
230     if (it2 == infos_.end()) {
231         MMI_HILOGE("Duplicate %{public}s", info.GetDesc().c_str());
232     }
233     return true;
234 }
235 
UnbindInputDevice(int32_t deviceId)236 void BindInfos::UnbindInputDevice(int32_t deviceId)
237 {
238     auto it = infos_.begin();
239     for (; it != infos_.end(); ++it) {
240         if (it->GetInputDeviceId() == deviceId) {
241             it->RemoveInputDevice();
242             infos_.erase(it);
243             return;
244         }
245     }
246 }
247 
UnbindDisplay(int32_t displayId)248 void BindInfos::UnbindDisplay(int32_t displayId)
249 {
250     auto it = infos_.begin();
251     for (; it != infos_.end(); ++it) {
252         if (it->GetDisplayId() == displayId) {
253             it->RemoveDisplay();
254             infos_.erase(it);
255             return;
256         }
257     }
258 }
259 
GetUnbindInputDevice(const std::string & displayName)260 BindInfo BindInfos::GetUnbindInputDevice(const std::string &displayName)
261 {
262     auto it = infos_.begin();
263     while (it != infos_.end()) {
264         if (it->InputDeviceNotBind()) {
265             if (it->GetDisplayName() == displayName) {
266                 auto info = std::move(*it);
267                 infos_.erase(it);
268                 return info;
269             }
270         }
271         ++it;
272     }
273     return BindInfo();
274 }
275 
GetUnbindDisplay()276 BindInfo BindInfos::GetUnbindDisplay()
277 {
278     auto it = infos_.begin();
279     while (it != infos_.end()) {
280         if (it->DisplayNotBind()) {
281             auto info = std::move(*it);
282             infos_.erase(it);
283             return info;
284         }
285         ++it;
286     }
287     return BindInfo();
288 }
289 
GetUnbindDisplay(const std::string & inputDeviceName)290 BindInfo BindInfos::GetUnbindDisplay(const std::string &inputDeviceName)
291 {
292     auto it = infos_.begin();
293     while (it != infos_.end()) {
294         if (it->DisplayNotBind()) {
295             if (it->GetInputDeviceName() == inputDeviceName) {
296                 auto info = std::move(*it);
297                 infos_.erase(it);
298                 return info;
299             }
300         }
301         ++it;
302     }
303     return GetUnbindDisplay();
304 }
305 
operator <<(std::ostream & os,const BindInfos & r)306 std::ostream &operator << (std::ostream &os, const BindInfos &r)
307 {
308     const auto &infos = r.GetInfos();
309     for (const auto &info : infos) {
310         if (!info.IsUnbind()) {
311             os << info;
312         }
313     }
314     return os;
315 }
316 
operator >>(std::istream & is,BindInfos & r)317 std::istream &operator >> (std::istream &is, BindInfos &r)
318 {
319     while (!is.eof()) {
320         BindInfo info;
321         is >> info;
322         if (info.IsUnbind()) {
323             break;
324         }
325         r.Add(info);
326     }
327     return is;
328 }
329 
InputDisplayBindHelper(const std::string bindCfgFile)330 InputDisplayBindHelper::InputDisplayBindHelper(const std::string bindCfgFile)
331     : fileName_(bindCfgFile), infos_(std::make_shared<BindInfos>()), configFileInfos_(std::make_shared<BindInfos>())
332 {}
333 
GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const334 std::string InputDisplayBindHelper::GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const
335 {
336     CALL_DEBUG_ENTER;
337     CHKPO(infos_);
338     return infos_->GetBindDisplayNameByInputDevice(inputDeviceId);
339 }
340 
AddInputDevice(int32_t id,const std::string & name)341 void InputDisplayBindHelper::AddInputDevice(int32_t id, const std::string &name)
342 {
343     CALL_DEBUG_ENTER;
344     MMI_HILOGD("Param: id:%{public}d, name:%{public}s", id, name.c_str());
345     auto displayName = configFileInfos_->GetDisplayNameByInputDevice(name);
346     BindInfo info = infos_->GetUnbindInputDevice(displayName);
347     info.AddInputDevice(id, name);
348     infos_->Add(info);
349     Store();
350 }
351 
RemoveInputDevice(int32_t id)352 void InputDisplayBindHelper::RemoveInputDevice(int32_t id)
353 {
354     CALL_DEBUG_ENTER;
355     MMI_HILOGD("Param: id:%{public}d", id);
356     infos_->UnbindInputDevice(id);
357 }
358 
IsDisplayAdd(int32_t id,const std::string & name)359 bool InputDisplayBindHelper::IsDisplayAdd(int32_t id, const std::string &name)
360 {
361     const auto &infos = infos_->GetInfos();
362     for (const auto &info : infos) {
363         if ((info.GetDisplayName() == name) && (info.GetDisplayId() == id)) {
364             return true;
365         }
366     }
367     return false;
368 }
369 
GetDisplayIdNames() const370 std::set<std::pair<int32_t, std::string>> InputDisplayBindHelper::GetDisplayIdNames() const
371 {
372     CALL_DEBUG_ENTER;
373     std::set<std::pair<int32_t, std::string>> idNames;
374     const auto &infos = infos_->GetInfos();
375     for (const auto &info : infos) {
376         if (info.GetDisplayId() != -1) {
377             idNames.insert(std::make_pair(info.GetDisplayId(), info.GetDisplayName()));
378         }
379     }
380     return idNames;
381 }
382 
AddDisplay(int32_t id,const std::string & name)383 void InputDisplayBindHelper::AddDisplay(int32_t id, const std::string &name)
384 {
385     CALL_DEBUG_ENTER;
386     MMI_HILOGD("Param: id:%{public}d, name:%{public}s", id, name.c_str());
387     auto inputDeviceName = configFileInfos_->GetInputDeviceByDisplayName(name);
388     if (IsDualDisplayFoldDevice()) {
389         std::string deviceName = GetInputDeviceById(id);
390         if (!deviceName.empty()) {
391             inputDeviceName = deviceName;
392         }
393     }
394     BindInfo info = infos_->GetUnbindDisplay(inputDeviceName);
395     info.AddDisplay(id, name);
396     infos_->Add(info);
397     Store();
398 }
399 
AddLocalDisplay(int32_t id,const std::string & name)400 void InputDisplayBindHelper::AddLocalDisplay(int32_t id, const std::string &name)
401 {
402     CALL_DEBUG_ENTER;
403     MMI_HILOGD("Param: id:%{public}d, name:%{public}s", id, name.c_str());
404     CHKPV(infos_);
405 
406     const auto &infos = infos_->GetInfos();
407     std::vector<std::string> unbindDevices;
408     for (const auto &info : infos) {
409         if (info.DisplayNotBind()) {
410             unbindDevices.push_back(info.GetInputDeviceName());
411             MMI_HILOGI("Unbind InputDevice, id:%{public}d, inputDevice:%{public}s",
412                 info.GetInputDeviceId(), info.GetInputDeviceName().c_str());
413         }
414     }
415 
416     bool IsStore = false;
417     for (auto &item : unbindDevices) {
418         auto inputDeviceName = item;
419         if (IsDualDisplayFoldDevice()) {
420             std::string deviceName = GetInputDeviceById(id);
421             if (!deviceName.empty()) {
422                 inputDeviceName = deviceName;
423             }
424         }
425         BindInfo info = infos_->GetUnbindDisplay(inputDeviceName);
426         info.AddDisplay(id, name);
427         infos_->Add(info);
428         IsStore = true;
429     }
430     if (IsStore) {
431         Store();
432     }
433     unbindDevices.clear();
434 }
435 
GetInputDeviceById(int32_t id)436 std::string InputDisplayBindHelper::GetInputDeviceById(int32_t id)
437 {
438     CALL_DEBUG_ENTER;
439     if (id != DISPLAY_ID_MAIN && id != DISPLAY_ID_SUB) {
440         return "";
441     }
442 
443     std::string inputNodeName = GetInputNodeNameByCfg(id);
444     if (inputNodeName.empty()) {
445         return "";
446     }
447 
448     std::string inputNode = GetInputNode(inputNodeName);
449     if (inputNode.empty()) {
450         return "";
451     }
452 
453     std::string inputEvent = inputNode;
454     size_t pos = inputEvent.find(INPUT);
455     if (pos != std::string::npos) {
456         inputEvent.replace(pos, INPUT.length(), EVENT);
457     }
458 
459     std::string inputDeviceName;
460     inputDeviceName.append(DIRECTORY).append(SEPARATOR)
461         .append(inputNode).append(SEPARATOR)
462         .append(inputEvent).append(SUFFIX);
463 
464     MMI_HILOGI("GetInputDeviceById, id:%{public}d, inputDevice:%{public}s", id, inputDeviceName.c_str());
465     return inputDeviceName;
466 }
467 
GetInputNodeNameByCfg(int32_t id)468 std::string InputDisplayBindHelper::GetInputNodeNameByCfg(int32_t id)
469 {
470     CALL_DEBUG_ENTER;
471     std::ifstream file(INPUT_DEVICE_NAME_CONFIG);
472     std::string res;
473     if (file.is_open()) {
474         std::string line;
475         while (getline(file, line)) {
476             const std::string delim = "<=>";
477             size_t pos = line.find(delim);
478             if (pos == std::string::npos) {
479                 continue;
480             }
481             std::string displayId = line.substr(0, pos);
482             std::string inputNodeName = line.substr(pos + delim.length());
483             if (!displayId.empty() && !inputNodeName.empty()
484                 && std::all_of(displayId.begin(), displayId.end(), ::isdigit)
485                 && std::atoi(displayId.c_str()) == id) {
486                 res = inputNodeName;
487                 break;
488             }
489         }
490         file.close();
491     }
492     if (!res.empty() && (res.back() == '\n' || res.back() == '\r')) {
493         res.pop_back();
494     }
495     return res;
496 }
497 
GetContent(const std::string & fileName)498 std::string InputDisplayBindHelper::GetContent(const std::string &fileName)
499 {
500     CALL_DEBUG_ENTER;
501     std::string content;
502     char realPath[PATH_MAX] = {};
503     if (realpath(fileName.c_str(), realPath) == nullptr) {
504         MMI_HILOGE("The realpath return nullptr");
505         return content;
506     }
507     std::ifstream file(realPath);
508     if (file.is_open()) {
509         std::string line;
510         while (getline(file, line)) {
511             content.append(line);
512         }
513         file.close();
514     }
515     return content;
516 }
517 
GetInputNode(const std::string & inputNodeName)518 std::string InputDisplayBindHelper::GetInputNode(const std::string &inputNodeName)
519 {
520     CALL_DEBUG_ENTER;
521     std::string inputNode;
522     if (fs::exists(DIRECTORY) && fs::is_directory(DIRECTORY)) {
523         for (const auto& entry : fs::directory_iterator(DIRECTORY)) {
524             std::string node = fs::path(entry.path()).filename();
525             std::string file;
526             file.append(DIRECTORY).append(SEPARATOR)
527                 .append(node).append(SEPARATOR)
528                 .append(NAME);
529             if (inputNodeName == GetContent(file)) {
530                 inputNode = node;
531                 break;
532             }
533         }
534     }
535     return inputNode;
536 }
537 
RemoveDisplay(int32_t id)538 void InputDisplayBindHelper::RemoveDisplay(int32_t id)
539 {
540     CALL_DEBUG_ENTER;
541     MMI_HILOGD("Param: id:%{public}d", id);
542     infos_->UnbindDisplay(id);
543 }
544 
Store()545 void InputDisplayBindHelper::Store()
546 {
547     CALL_DEBUG_ENTER;
548     CHKPV(infos_);
549     char realPath[PATH_MAX] = {};
550     CHKPV(realpath(fileName_.c_str(), realPath));
551     if (!IsValidJsonPath(realPath)) {
552         MMI_HILOGE("file path is invalid");
553         return;
554     }
555     std::ofstream ofs(realPath, std::ios::trunc | std::ios::out | std::ios_base::binary);
556     if (!ofs) {
557         MMI_HILOGE("Open file fail.%{public}s, errno:%{public}d", realPath, errno);
558         return;
559     }
560     ofs << *infos_;
561     ofs.close();
562 }
563 
GetDisplayBindInfo(DisplayBindInfos & infos)564 int32_t InputDisplayBindHelper::GetDisplayBindInfo(DisplayBindInfos &infos)
565 {
566     CALL_DEBUG_ENTER;
567     CHKPR(infos_, RET_ERR);
568     for (const auto &item : infos_->GetInfos()) {
569         infos.push_back({
570             .inputDeviceId = item.GetInputDeviceId(),
571             .inputDeviceName = item.GetInputDeviceName(),
572             .displayId = item.GetDisplayId(),
573             .displayName = item.GetDisplayName(),
574         });
575     }
576     return RET_OK;
577 }
578 
SetDisplayBind(int32_t deviceId,int32_t displayId,std::string & msg)579 int32_t InputDisplayBindHelper::SetDisplayBind(int32_t deviceId, int32_t displayId, std::string &msg)
580 {
581     CALL_DEBUG_ENTER;
582     MMI_HILOGD("Param: deviceId:%{public}d, displayId:%{public}d", deviceId, displayId);
583     if ((deviceId == -1) || (displayId == -1)) {
584         msg = "The deviceId or displayId is invalid";
585         MMI_HILOGE("%s", msg.c_str());
586         return RET_ERR;
587     }
588     if (infos_ == nullptr) {
589         msg = "Infos_ is nullptr";
590         MMI_HILOGE("%s", msg.c_str());
591         return RET_ERR;
592     }
593 
594     BindInfo bindByDevice;
595     BindInfo bindByDisplay;
596     for (const auto &item : infos_->GetInfos()) {
597         if (item.GetInputDeviceId() == deviceId) {
598             bindByDevice = item;
599         }
600         if (item.GetDisplayId() == displayId) {
601             bindByDisplay = item;
602         }
603     }
604     if (bindByDevice.GetInputDeviceId() == -1) {
605         msg = "The deviceId is invalid";
606         MMI_HILOGE("%s", msg.c_str());
607         return RET_ERR;
608     }
609     if (bindByDisplay.GetDisplayId() == -1) {
610         msg = "The displayId is invalid";
611         MMI_HILOGE("%s", msg.c_str());
612         return RET_ERR;
613     }
614 
615     if (infos_->GetBindDisplayIdByInputDevice(deviceId) == displayId) {
616         msg = "The input device and display has alread bind";
617         MMI_HILOGE("%s", msg.c_str());
618         return RET_ERR;
619     }
620 
621     infos_->UnbindInputDevice(bindByDevice.GetInputDeviceId());
622     infos_->UnbindInputDevice(bindByDisplay.GetInputDeviceId());
623     infos_->UnbindDisplay(bindByDevice.GetDisplayId());
624     infos_->UnbindDisplay(bindByDisplay.GetDisplayId());
625 
626     BindInfo info1;
627     info1.AddInputDevice(bindByDevice.GetInputDeviceId(), bindByDevice.GetInputDeviceName());
628     info1.AddDisplay(bindByDisplay.GetDisplayId(), bindByDisplay.GetDisplayName());
629     infos_->Add(info1);
630 
631     if ((bindByDevice.GetDisplayId() != -1) && (bindByDisplay.GetInputDeviceId() != -1)) {
632         MMI_HILOGD("Both display id and input device id are invalid");
633         BindInfo info2;
634         info2.AddInputDevice(bindByDisplay.GetInputDeviceId(), bindByDisplay.GetInputDeviceName());
635         info2.AddDisplay(bindByDevice.GetDisplayId(), bindByDevice.GetDisplayName());
636         infos_->Add(info2);
637         return RET_OK;
638     }
639 
640     if (bindByDevice.GetDisplayId() != -1) {
641         MMI_HILOGD("The display id is invalid");
642         AddDisplay(bindByDevice.GetDisplayId(), bindByDevice.GetDisplayName());
643         return RET_OK;
644     }
645 
646     if (bindByDisplay.GetInputDeviceId() != -1) {
647         MMI_HILOGD("The input device id is invalid");
648         AddInputDevice(bindByDisplay.GetInputDeviceId(), bindByDisplay.GetInputDeviceName());
649         return RET_OK;
650     }
651 
652     msg = "Can not reach here";
653     return RET_ERR;
654 }
655 
Load()656 void InputDisplayBindHelper::Load()
657 {
658     CALL_DEBUG_ENTER;
659     char realPath[PATH_MAX] = {};
660     CHKPV(realpath(fileName_.c_str(), realPath));
661     if (!IsValidJsonPath(realPath)) {
662         MMI_HILOGE("file path is invalid");
663         return;
664     }
665     std::ifstream ifs(realPath);
666     MMI_HILOGEK("Open file end:%{public}s", realPath);
667     if (!ifs) {
668         MMI_HILOGE("Open file fail.%{public}s, errno:%{public}d", realPath, errno);
669         return;
670     }
671     ifs >> *configFileInfos_;
672     ifs.close();
673 }
674 
Dumps() const675 std::string InputDisplayBindHelper::Dumps() const
676 {
677     CALL_DEBUG_ENTER;
678     CHKPO(infos_);
679     std::ostringstream oss;
680     oss << *infos_;
681     return oss.str();
682 }
683 } // namespace MMI
684 } // namespace OHOS
685