• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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