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 "uds_session.h"
17 
18 #include <cinttypes>
19 #include <sstream>
20 
21 #include <fcntl.h>
22 #include <sys/types.h>
23 #include <sys/un.h>
24 #include <unistd.h>
25 
26 #include "hisysevent.h"
27 #include "proto.h"
28 #include "uds_socket.h"
29 
30 #undef MMI_LOG_TAG
31 #define MMI_LOG_TAG "UDSSession"
32 
33 namespace OHOS {
34 namespace MMI {
35 namespace {
36 const std::string FOUNDATION = "foundation";
37 } // namespace
38 
UDSSession(const std::string & programName,const int32_t moduleType,const int32_t fd,const int32_t uid,const int32_t pid)39 UDSSession::UDSSession(const std::string &programName, const int32_t moduleType, const int32_t fd,
40     const int32_t uid, const int32_t pid)
41     : programName_(programName),
42       moduleType_(moduleType),
43       fd_(fd),
44       uid_(uid),
45       pid_(pid)
46 {
47     UpdateDescript();
48     events_[ANR_DISPATCH] = {};
49     events_[ANR_MONITOR] = {};
50     isAnrProcess_[ANR_DISPATCH] = false;
51     isAnrProcess_[ANR_MONITOR] = false;
52 }
53 
SendMsg(const char * buf,size_t size) const54 bool UDSSession::SendMsg(const char *buf, size_t size) const
55 {
56     CHKPF(buf);
57     if ((size == 0) || (size > MAX_PACKET_BUF_SIZE)) {
58         MMI_HILOGE("buf size:%{public}zu", size);
59         return false;
60     }
61     if (fd_ < 0) {
62         MMI_HILOGE("The fd_ is less than 0");
63         return false;
64     }
65 
66     int32_t idx = 0;
67     int32_t retryCount = 0;
68     const int32_t bufSize = static_cast<int32_t>(size);
69     int32_t remSize = bufSize;
70     int32_t socketErrorNo = 0;
71     while (remSize > 0 && retryCount < SEND_RETRY_LIMIT) {
72         retryCount += 1;
73         auto count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL);
74         if (count < 0) {
75             if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
76                 socketErrorNo = errno;
77                 continue;
78             }
79             if (errno == ENOTSOCK) {
80                 MMI_HILOGE("Got ENOTSOCK error, turn the socket to invalid");
81                 invalidSocket_ = true;
82             }
83             MMI_HILOGE("Send return failed,error:%{public}d fd:%{public}d, pid:%{public}d", errno, fd_, pid_);
84             return false;
85         }
86         idx += count;
87         remSize -= count;
88         if (remSize > 0) {
89             MMI_HILOGW("Remsize:%{public}d", remSize);
90             usleep(SEND_RETRY_SLEEP_TIME);
91         }
92     }
93     if (socketErrorNo == EWOULDBLOCK) {
94         ReportSocketBufferFull();
95     }
96     if (retryCount >= SEND_RETRY_LIMIT || remSize != 0) {
97         MMI_HILOGE("Send too many times:%{public}d/%{public}d,size:%{public}d/%{public}d errno:%{public}d, "
98                    "fd:%{public}d, pid:%{public}d", retryCount, SEND_RETRY_LIMIT, idx, bufSize, errno, fd_, pid_);
99         return false;
100     }
101     return true;
102 }
103 
Close()104 void UDSSession::Close()
105 {
106     CALL_DEBUG_ENTER;
107     MMI_HILOGD("Enter fd_:%{public}d", fd_);
108     if (fd_ >= 0) {
109         close(fd_);
110         fd_ = -1;
111         UpdateDescript();
112     }
113 }
114 
UpdateDescript()115 void UDSSession::UpdateDescript()
116 {
117     std::ostringstream oss;
118     oss << "fd = " << fd_
119         << ", programName = " << programName_
120         << ", moduleType = " << moduleType_
121         << ((fd_ < 0) ? ", closed" : ", opened")
122         << ", uid = " << uid_
123         << ", pid = " << pid_
124         << ", tokenType = " << tokenType_
125         << std::endl;
126     descript_ = oss.str().c_str();
127 }
128 
SendMsg(NetPacket & pkt) const129 bool UDSSession::SendMsg(NetPacket &pkt) const
130 {
131     if (pkt.ChkRWError()) {
132         MMI_HILOGE("Read and write status is error");
133         return false;
134     }
135     StreamBuffer buf;
136     pkt.MakeData(buf);
137     return SendMsg(buf.Data(), buf.Size());
138 }
139 
ReportSocketBufferFull() const140 void UDSSession::ReportSocketBufferFull() const
141 {
142     int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MODAL_INPUT,
143         "INPUT_EVENT_SOCKET_TIMEOUT",
144         OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
145         "MSG",
146         "remote client buffer full, cant send msg",
147         "PROGRAM_NAME",
148         programName_,
149         "REMOTE_PID",
150         pid_);
151     if (ret != 0) {
152         MMI_HILOGE("save input event socket timeout failed, ret:%{public}d", ret);
153     }
154 }
155 
SaveANREvent(int32_t type,int32_t id,int64_t time,int32_t timerId)156 void UDSSession::SaveANREvent(int32_t type, int32_t id, int64_t time, int32_t timerId)
157 {
158     CALL_DEBUG_ENTER;
159     EventTime eventTime = { id, time, timerId };
160     auto iter = events_.find(type);
161     if (iter != events_.end()) {
162         iter->second.push_back(eventTime);
163     }
164 }
165 
GetTimerIds(int32_t type)166 std::vector<int32_t> UDSSession::GetTimerIds(int32_t type)
167 {
168     auto iter = events_.find(type);
169     if (iter == events_.end()) {
170         MMI_HILOGE("Current events have no event type:%{public}d", type);
171         return {};
172     }
173     std::vector<int32_t> timers;
174     for (auto &item : iter->second) {
175         timers.push_back(item.timerId);
176         item.timerId = -1;
177     }
178     events_[iter->first] = iter->second;
179     return timers;
180 }
181 
DelEvents(int32_t type,int32_t id)182 std::list<int32_t> UDSSession::DelEvents(int32_t type, int32_t id)
183 {
184     CALL_DEBUG_ENTER;
185     MMI_HILOGD("Delete events, anr type:%{public}d, id:%{public}d, pid:%{public}d", type, id, pid_);
186     auto iter = events_.find(type);
187     if (iter == events_.end()) {
188         MMI_HILOGE("Current events have no event type:%{public}d pid:%{public}d", type, pid_);
189         return {};
190     }
191     auto &events = iter->second;
192     int32_t canDelEventCount = 0;
193     std::list<int32_t> timerIds;
194     for (auto &item : events) {
195         if (item.id > id) {
196             break;
197         }
198         MMI_HILOGD("Delete event, anr type:%{public}d, id:%{public}d, timerId:%{public}d", type, item.id, item.timerId);
199         timerIds.push_back(item.timerId);
200         ++canDelEventCount;
201     }
202     if (canDelEventCount == 0) {
203         MMI_HILOGD("Can not find event:%{public}d pid:%{public}d type:%{public}d", id, pid_, type);
204         return timerIds;
205     }
206     events.erase(events.begin(), events.begin() + canDelEventCount);
207 
208     if (events.empty()) {
209         isAnrProcess_[type] = false;
210         return timerIds;
211     }
212     MMI_HILOGD("First event, anr type:%{public}d, id:%{public}d, timerId:%{public}d, pid: %{public}d",
213         type, events.begin()->id, events.begin()->timerId, pid_);
214     int64_t endTime = 0;
215     if (!AddInt64(events.begin()->eventTime, INPUT_UI_TIMEOUT_TIME, endTime)) {
216         MMI_HILOGE("The addition of endTime overflows");
217         return timerIds;
218     }
219     auto currentTime = GetSysClockTime();
220     if (currentTime < endTime) {
221         isAnrProcess_[type] = false;
222     }
223     return timerIds;
224 }
225 
GetEarliestEventTime(int32_t type) const226 int64_t UDSSession::GetEarliestEventTime(int32_t type) const
227 {
228     CALL_DEBUG_ENTER;
229     auto iter = events_.find(type);
230     if (iter != events_.end()) {
231         if (iter->second.empty()) {
232             MMI_HILOGD("Current events is empty");
233             return 0;
234         }
235         return iter->second.begin()->eventTime;
236     }
237     return 0;
238 }
239 
IsEventQueueEmpty(int32_t type)240 bool UDSSession::IsEventQueueEmpty(int32_t type)
241 {
242     CALL_DEBUG_ENTER;
243     auto iter = events_.find(type);
244     return (iter == events_.end() || (iter->second.empty()));
245 }
246 } // namespace MMI
247 } // namespace OHOS