• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "input_display_bind_helper.h"
16 
17 #include <fstream>
18 #include <iostream>
19 #include <list>
20 #include <sstream>
21 
22 #include "mmi_log.h"
23 #include "util.h"
24 
25 namespace OHOS {
26 namespace MMI {
27 namespace {
28 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "InputDisplayBindHelper" };
29 }
30 class BindInfo {
31 public:
GetInputDeviceId() const32     int32_t GetInputDeviceId() const
33     {
34         return inputDeviceId_;
35     }
GetInputDeviceName() const36     std::string GetInputDeviceName() const
37     {
38         return inputDeviceName_;
39     }
GetDisplayId() const40     int32_t GetDisplayId() const
41     {
42         return displayId_;
43     }
GetDisplayName() const44     std::string GetDisplayName() const
45     {
46         return displayName_;
47     }
IsUnbind() const48     bool IsUnbind() const
49     {
50         return ((inputDeviceId_ == -1) || (displayId_ == -1));
51     }
InputDeviceNotBind() const52     bool InputDeviceNotBind() const
53     {
54         return (inputDeviceId_ == -1);
55     }
DisplayNotBind() const56     bool DisplayNotBind() const
57     {
58         return (displayId_ == -1);
59     }
60     bool AddInputDevice(int32_t deviceId, const std::string &deviceName);
61     void RemoveInputDevice();
62     bool AddDisplay(int32_t id, const std::string &name);
63     void RemoveDisplay();
64     std::string GetDesc() const;
65     friend bool operator < (const BindInfo &l, const BindInfo &r);
66     friend std::ostream &operator << (std::ostream &os, const BindInfo &r);
67     friend std::istream &operator >> (std::istream &is, BindInfo &r);
68 
69 private:
70     int32_t inputDeviceId_{ -1 };
71     std::string inputDeviceName_;
72     int32_t displayId_{ -1 };
73     std::string displayName_;
74 };
75 
76 class BindInfos {
77 public:
78     bool Add(const BindInfo &info);
79     void UnbindInputDevice(int32_t deviceId);
80     void UnbindDisplay(int32_t displayId);
81     BindInfo GetUnbindInputDevice(const std::string &displayName);
82     BindInfo GetUnbindDisplay(const std::string &inputDeviceName);
83     std::string GetDisplayNameByInputDevice(const std::string &name) const;
84     int32_t GetBindDisplayIdByInputDevice(int32_t inputDeviceId) const;
85     std::string GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const;
86     std::string GetInputDeviceByDisplayName(const std::string &name) const;
87     std::string GetDesc() const;
GetInfos() const88     const std::list<BindInfo> &GetInfos() const
89     {
90         return infos_;
91     }
92     friend std::ostream &operator << (std::ostream &os, const BindInfos &r);
93     friend std::istream &operator >> (std::istream &is, BindInfos &r);
94 
95 private:
96     BindInfo GetUnbindInputDevice();
97     BindInfo GetUnbindInfo();
98     BindInfo GetUnbindDisplay();
99     std::list<BindInfo> infos_;
100 };
101 
AddInputDevice(int32_t deviceId,const std::string & deviceName)102 bool BindInfo::AddInputDevice(int32_t deviceId, const std::string &deviceName)
103 {
104     if ((inputDeviceId_ != -1) || !inputDeviceName_.empty()) {
105         return false;
106     }
107     inputDeviceId_ = deviceId;
108     inputDeviceName_ = deviceName;
109     return true;
110 }
111 
RemoveInputDevice()112 void BindInfo::RemoveInputDevice()
113 {
114     inputDeviceId_ = -1;
115     inputDeviceName_.clear();
116 }
AddDisplay(int32_t id,const std::string & name)117 bool BindInfo::AddDisplay(int32_t id, const std::string &name)
118 {
119     if ((displayId_ != -1) || !displayName_.empty()) {
120         return false;
121     }
122     displayId_ = id;
123     displayName_ = name;
124     return true;
125 }
RemoveDisplay()126 void BindInfo::RemoveDisplay()
127 {
128     displayId_ = -1;
129     displayName_.clear();
130 }
GetDesc() const131 std::string BindInfo::GetDesc() const
132 {
133     std::ostringstream oss;
134     oss << "InputDevice(id:" << inputDeviceId_ << ",name:" << inputDeviceName_ << "),Display(id:" << displayId_ <<
135         ",name:" << displayName_ << ")";
136     return oss.str();
137 }
138 
operator <(const BindInfo & l,const BindInfo & r)139 bool operator < (const BindInfo &l, const BindInfo &r)
140 {
141     if (l.inputDeviceId_ != r.inputDeviceId_) {
142         return (l.inputDeviceId_ < r.inputDeviceId_);
143     }
144     return (l.displayId_ < r.displayId_);
145 }
146 
operator <<(std::ostream & os,const BindInfo & r)147 std::ostream &operator << (std::ostream &os, const BindInfo &r)
148 {
149     os << r.inputDeviceName_ << "<=>" << r.displayName_ << std::endl;
150     return os;
151 }
152 
operator >>(std::istream & is,BindInfo & r)153 std::istream &operator >> (std::istream &is, BindInfo &r)
154 {
155     std::string line;
156     std::getline(is, line);
157     const std::string delim = "<=>";
158     std::string::size_type pos = line.find(delim);
159     if (pos == std::string::npos) {
160         return is;
161     }
162     r.inputDeviceName_ = line.substr(0, pos);
163     r.displayName_ = line.substr(pos + delim.length());
164     r.inputDeviceId_ = 0;
165     r.displayId_ = 0;
166     return is;
167 }
168 
GetDesc() const169 std::string BindInfos::GetDesc() const
170 {
171     int32_t index = 0;
172     std::ostringstream oss;
173     for (const auto &info : infos_) {
174         oss << "index:" << index << "," << info.GetDesc() << std::endl;
175     }
176     return oss.str();
177 }
178 
GetBindDisplayIdByInputDevice(int32_t inputDeviceId) const179 int32_t BindInfos::GetBindDisplayIdByInputDevice(int32_t inputDeviceId) const
180 {
181     for (const auto &item : infos_) {
182         if (item.GetInputDeviceId() == inputDeviceId) {
183             if (!item.IsUnbind()) {
184                 return item.GetDisplayId();
185             }
186         }
187     }
188     return -1;
189 }
190 
GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const191 std::string BindInfos::GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const
192 {
193     for (const auto &item : infos_) {
194         if (item.GetInputDeviceId() == inputDeviceId) {
195             if (!item.IsUnbind()) {
196                 return item.GetDisplayName();
197             }
198         }
199     }
200     return "";
201 }
202 
GetDisplayNameByInputDevice(const std::string & name) const203 std::string BindInfos::GetDisplayNameByInputDevice(const std::string &name) const
204 {
205     for (const auto &item : infos_) {
206         if (item.GetInputDeviceName() == name) {
207             return item.GetDisplayName();
208         }
209     }
210     return "";
211 }
212 
GetInputDeviceByDisplayName(const std::string & name) const213 std::string BindInfos::GetInputDeviceByDisplayName(const std::string &name) const
214 {
215     for (const auto &item : infos_) {
216         if (item.GetDisplayName() == name) {
217             return item.GetInputDeviceName();
218         }
219     }
220     return "";
221 }
222 
Add(const BindInfo & info)223 bool BindInfos::Add(const BindInfo &info)
224 {
225     auto it = infos_.begin();
226     for (; it != infos_.end(); ++it) {
227         if (info < *it) {
228             break;
229         }
230     }
231     auto it2 = infos_.emplace(it, std::move(info));
232     if (it2 == infos_.end()) {
233         MMI_HILOGE("Duplicate %{public}s", info.GetDesc().c_str());
234     }
235     return true;
236 }
237 
UnbindInputDevice(int32_t deviceId)238 void BindInfos::UnbindInputDevice(int32_t deviceId)
239 {
240     auto it = infos_.begin();
241     for (; it != infos_.end(); ++it) {
242         if (it->GetInputDeviceId() == deviceId) {
243             it->RemoveInputDevice();
244             if (it->IsUnbind()) {
245                 infos_.erase(it);
246             }
247             return;
248         }
249     }
250 }
251 
UnbindDisplay(int32_t displayId)252 void BindInfos::UnbindDisplay(int32_t displayId)
253 {
254     auto it = infos_.begin();
255     for (; it != infos_.end(); ++it) {
256         if (it->GetDisplayId() == displayId) {
257             it->RemoveDisplay();
258             if (it->IsUnbind()) {
259                 infos_.erase(it);
260             }
261             return;
262         }
263     }
264 }
265 
GetUnbindInfo()266 BindInfo BindInfos::GetUnbindInfo()
267 {
268     auto it = infos_.begin();
269     while (it != infos_.end()) {
270         if (it->IsUnbind()) {
271             auto info = std::move(*it);
272             infos_.erase(it);
273             return info;
274         }
275         ++it;
276     }
277     return BindInfo();
278 }
279 
GetUnbindInputDevice(const std::string & displayName)280 BindInfo BindInfos::GetUnbindInputDevice(const std::string &displayName)
281 {
282     auto it = infos_.begin();
283     while (it != infos_.end()) {
284         if (it->InputDeviceNotBind()) {
285             if (it->GetDisplayName() == displayName) {
286                 auto info = std::move(*it);
287                 infos_.erase(it);
288                 return info;
289             }
290         }
291         ++it;
292     }
293     return BindInfo();
294 }
295 
GetUnbindDisplay()296 BindInfo BindInfos::GetUnbindDisplay()
297 {
298     auto it = infos_.begin();
299     while (it != infos_.end()) {
300         if (it->DisplayNotBind()) {
301             auto info = std::move(*it);
302             infos_.erase(it);
303             return info;
304         }
305         ++it;
306     }
307     return BindInfo();
308 }
309 
GetUnbindDisplay(const std::string & inputDeviceName)310 BindInfo BindInfos::GetUnbindDisplay(const std::string &inputDeviceName)
311 {
312     auto it = infos_.begin();
313     while (it != infos_.end()) {
314         if (it->DisplayNotBind()) {
315             if (it->GetInputDeviceName() == inputDeviceName) {
316                 auto info = std::move(*it);
317                 infos_.erase(it);
318                 return info;
319             }
320         }
321         ++it;
322     }
323     return GetUnbindDisplay();
324 }
325 
operator <<(std::ostream & os,const BindInfos & r)326 std::ostream &operator << (std::ostream &os, const BindInfos &r)
327 {
328     const auto &infos = r.GetInfos();
329     for (const auto &info : infos) {
330         if (!info.IsUnbind()) {
331             os << info;
332         }
333     }
334     return os;
335 }
336 
operator >>(std::istream & is,BindInfos & r)337 std::istream &operator >> (std::istream &is, BindInfos &r)
338 {
339     while (!is.eof()) {
340         BindInfo info;
341         is >> info;
342         if (info.IsUnbind()) {
343             break;
344         }
345         r.Add(info);
346     }
347     return is;
348 }
349 
InputDisplayBindHelper(const std::string bindCfgFile)350 InputDisplayBindHelper::InputDisplayBindHelper(const std::string bindCfgFile)
351     : fileName_(bindCfgFile), infos_(std::make_shared<BindInfos>()), configFileInfos_(std::make_shared<BindInfos>())
352 {}
353 
GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const354 std::string InputDisplayBindHelper::GetBindDisplayNameByInputDevice(int32_t inputDeviceId) const
355 {
356     CALL_DEBUG_ENTER;
357     if (infos_ == nullptr) {
358         return {};
359     }
360     return infos_->GetBindDisplayNameByInputDevice(inputDeviceId);
361 }
362 
AddInputDevice(int32_t id,const std::string & name)363 void InputDisplayBindHelper::AddInputDevice(int32_t id, const std::string &name)
364 {
365     CALL_DEBUG_ENTER;
366     MMI_HILOGD("Param: id:%{public}d, name:%{public}s", id, name.c_str());
367     auto displayName = configFileInfos_->GetDisplayNameByInputDevice(name);
368     BindInfo info = infos_->GetUnbindInputDevice(displayName);
369     info.AddInputDevice(id, name);
370     infos_->Add(info);
371     Store();
372 }
373 
RemoveInputDevice(int32_t id)374 void InputDisplayBindHelper::RemoveInputDevice(int32_t id)
375 {
376     CALL_DEBUG_ENTER;
377     MMI_HILOGD("Param: id:%{public}d", id);
378     infos_->UnbindInputDevice(id);
379 }
380 
IsDisplayAdd(int32_t id,const std::string & name)381 bool InputDisplayBindHelper::IsDisplayAdd(int32_t id, const std::string &name)
382 {
383     const auto &infos = infos_->GetInfos();
384     for (const auto &info : infos) {
385         if ((info.GetDisplayName() == name) && (info.GetDisplayId() == id)) {
386             return true;
387         }
388     }
389     return false;
390 }
391 
GetDisplayIdNames() const392 std::set<std::pair<int32_t, std::string>> InputDisplayBindHelper::GetDisplayIdNames() const
393 {
394     CALL_DEBUG_ENTER;
395     std::set<std::pair<int32_t, std::string>> idNames;
396     const auto &infos = infos_->GetInfos();
397     for (const auto &info : infos) {
398         if (info.GetDisplayId() != -1) {
399             idNames.insert(std::make_pair(info.GetDisplayId(), info.GetDisplayName()));
400         }
401     }
402     return idNames;
403 }
404 
AddDisplay(int32_t id,const std::string & name)405 void InputDisplayBindHelper::AddDisplay(int32_t id, const std::string &name)
406 {
407     CALL_DEBUG_ENTER;
408     MMI_HILOGD("Param: id:%{public}d, name:%{public}s", id, name.c_str());
409     auto inputDeviceName = configFileInfos_->GetInputDeviceByDisplayName(name);
410     BindInfo info = infos_->GetUnbindDisplay(inputDeviceName);
411     info.AddDisplay(id, name);
412     infos_->Add(info);
413     Store();
414 }
415 
RemoveDisplay(int32_t id)416 void InputDisplayBindHelper::RemoveDisplay(int32_t id)
417 {
418     CALL_DEBUG_ENTER;
419     MMI_HILOGD("Param: id:%{public}d", id);
420     infos_->UnbindDisplay(id);
421 }
422 
Store()423 void InputDisplayBindHelper::Store()
424 {
425     CALL_DEBUG_ENTER;
426     if (infos_ == nullptr) {
427         return;
428     }
429     char *canonicalPath = realpath(fileName_.c_str(), nullptr);
430     if (canonicalPath == nullptr) {
431         MMI_HILOGE("file name is empty");
432         return;
433     }
434     if (!IsValidJsonPath(canonicalPath)) {
435         MMI_HILOGE("file path is invalid");
436         return;
437     }
438     std::ofstream ofs(canonicalPath, std::ios::trunc | std::ios::out | std::ios_base::binary);
439     if (!ofs) {
440         MMI_HILOGE("Open file fail.%{public}s, errno:%{public}d", canonicalPath, errno);
441         return;
442     }
443     ofs << *infos_;
444     ofs.close();
445     free(canonicalPath);
446     canonicalPath = nullptr;
447 }
448 
GetDisplayBindInfo(DisplayBindInfos & infos)449 int32_t InputDisplayBindHelper::GetDisplayBindInfo(DisplayBindInfos &infos)
450 {
451     CALL_DEBUG_ENTER;
452     if (infos_ == nullptr) {
453         MMI_HILOGE("Infos_ is nullptr");
454         return RET_ERR;
455     }
456     for (const auto &item : infos_->GetInfos()) {
457         infos.push_back({
458             .inputDeviceId = item.GetInputDeviceId(),
459             .inputDeviceName = item.GetInputDeviceName(),
460             .displayId = item.GetDisplayId(),
461             .displayName = item.GetDisplayName(),
462         });
463     }
464     return RET_OK;
465 }
466 
SetDisplayBind(int32_t deviceId,int32_t displayId,std::string & msg)467 int32_t InputDisplayBindHelper::SetDisplayBind(int32_t deviceId, int32_t displayId, std::string &msg)
468 {
469     CALL_DEBUG_ENTER;
470     MMI_HILOGD("Param: deviceId:%{public}d, displayId:%{public}d", deviceId, displayId);
471     if ((deviceId == -1) || (displayId == -1)) {
472         msg = "The deviceId or displayId is invalid";
473         MMI_HILOGE("%s", msg.c_str());
474         return RET_ERR;
475     }
476     if (infos_ == nullptr) {
477         msg = "Infos_ is nullptr";
478         MMI_HILOGE("%s", msg.c_str());
479         return RET_ERR;
480     }
481 
482     BindInfo bindByDevice;
483     BindInfo bindByDisplay;
484     for (const auto &item : infos_->GetInfos()) {
485         if (item.GetInputDeviceId() == deviceId) {
486             bindByDevice = item;
487         }
488         if (item.GetDisplayId() == displayId) {
489             bindByDisplay = item;
490         }
491     }
492     if (bindByDevice.GetInputDeviceId() == -1) {
493         msg = "The deviceId is invalid";
494         MMI_HILOGE("%s", msg.c_str());
495         return RET_ERR;
496     }
497     if (bindByDisplay.GetDisplayId() == -1) {
498         msg = "The displayId is invalid";
499         MMI_HILOGE("%s", msg.c_str());
500         return RET_ERR;
501     }
502 
503     if (infos_->GetBindDisplayIdByInputDevice(deviceId) == displayId) {
504         msg = "The input device and display has alread bind";
505         MMI_HILOGE("%s", msg.c_str());
506         return RET_ERR;
507     }
508 
509     infos_->UnbindInputDevice(bindByDevice.GetInputDeviceId());
510     infos_->UnbindInputDevice(bindByDisplay.GetInputDeviceId());
511     infos_->UnbindDisplay(bindByDevice.GetDisplayId());
512     infos_->UnbindDisplay(bindByDisplay.GetDisplayId());
513 
514     BindInfo info1;
515     info1.AddInputDevice(bindByDevice.GetInputDeviceId(), bindByDevice.GetInputDeviceName());
516     info1.AddDisplay(bindByDisplay.GetDisplayId(), bindByDisplay.GetDisplayName());
517     infos_->Add(info1);
518 
519     if ((bindByDevice.GetDisplayId() != -1) && (bindByDisplay.GetInputDeviceId() != -1)) {
520         MMI_HILOGD("Both display id and input device id are invalid");
521         BindInfo info2;
522         info2.AddInputDevice(bindByDisplay.GetInputDeviceId(), bindByDisplay.GetInputDeviceName());
523         info2.AddDisplay(bindByDevice.GetDisplayId(), bindByDevice.GetDisplayName());
524         infos_->Add(info2);
525         return RET_OK;
526     }
527 
528     if (bindByDevice.GetDisplayId() != -1) {
529         MMI_HILOGD("The display id is invalid");
530         AddDisplay(bindByDevice.GetDisplayId(), bindByDevice.GetDisplayName());
531         return RET_OK;
532     }
533 
534     if (bindByDisplay.GetInputDeviceId() != -1) {
535         MMI_HILOGD("The input device id is invalid");
536         AddInputDevice(bindByDisplay.GetInputDeviceId(), bindByDisplay.GetInputDeviceName());
537         return RET_OK;
538     }
539 
540     msg = "Can not reach here";
541     return RET_ERR;
542 }
543 
Load()544 void InputDisplayBindHelper::Load()
545 {
546     CALL_DEBUG_ENTER;
547     char *canonicalPath = realpath(fileName_.c_str(), nullptr);
548     if (canonicalPath == nullptr) {
549         MMI_HILOGE("file name is empty");
550         return;
551     }
552     if (!IsValidJsonPath(canonicalPath)) {
553         MMI_HILOGE("file path is invalid");
554         return;
555     }
556     std::ifstream ifs(canonicalPath);
557     MMI_HILOGEK("Open file end:%{public}s", canonicalPath);
558     if (!ifs) {
559         MMI_HILOGE("Open file fail.%{public}s, errno:%{public}d", canonicalPath, errno);
560         return;
561     }
562     ifs >> *configFileInfos_;
563     ifs.close();
564     free(canonicalPath);
565     canonicalPath = nullptr;
566 }
567 
Dumps() const568 std::string InputDisplayBindHelper::Dumps() const
569 {
570     CALL_DEBUG_ENTER;
571     if (infos_ == nullptr) {
572         return {};
573     }
574     std::ostringstream oss;
575     oss << *infos_;
576     return oss.str();
577 }
578 } // namespace MMI
579 } // namespace OHOS