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