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