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 "uds_socket.h"
27 #include "proto.h"
28
29 namespace OHOS {
30 namespace MMI {
31 namespace {
32 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "UDSSession" };
33 const std::string FOUNDATION = "foundation";
34 } // namespace
35
UDSSession(const std::string & programName,const int32_t moduleType,const int32_t fd,const int32_t uid,const int32_t pid)36 UDSSession::UDSSession(const std::string &programName, const int32_t moduleType, const int32_t fd,
37 const int32_t uid, const int32_t pid)
38 : programName_(programName),
39 moduleType_(moduleType),
40 fd_(fd),
41 uid_(uid),
42 pid_(pid)
43 {
44 UpdateDescript();
45 events_[ANR_DISPATCH] = {};
46 events_[ANR_MONITOR] = {};
47 isAnrProcess_[ANR_DISPATCH] = false;
48 isAnrProcess_[ANR_MONITOR] = false;
49 }
50
SendMsg(const char * buf,size_t size) const51 bool UDSSession::SendMsg(const char *buf, size_t size) const
52 {
53 CHKPF(buf);
54 if ((size == 0) || (size > MAX_PACKET_BUF_SIZE)) {
55 MMI_HILOGE("buf size:%{public}zu", size);
56 return false;
57 }
58 if (fd_ < 0) {
59 MMI_HILOGE("The fd_ is less than 0");
60 return false;
61 }
62
63 int32_t idx = 0;
64 int32_t retryCount = 0;
65 const int32_t bufSize = static_cast<int32_t>(size);
66 int32_t remSize = bufSize;
67 while (remSize > 0 && retryCount < SEND_RETRY_LIMIT) {
68 retryCount += 1;
69 auto count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL);
70 if (count < 0) {
71 if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
72 MMI_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d", errno);
73 continue;
74 }
75 MMI_HILOGE("Send return failed,error:%{public}d fd:%{public}d", errno, fd_);
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 (retryCount >= SEND_RETRY_LIMIT || remSize != 0) {
86 MMI_HILOGE("Send too many times:%{public}d/%{public}d,size:%{public}d/%{public}d fd:%{public}d",
87 retryCount, SEND_RETRY_LIMIT, idx, bufSize, fd_);
88 return false;
89 }
90 return true;
91 }
92
Close()93 void UDSSession::Close()
94 {
95 CALL_DEBUG_ENTER;
96 MMI_HILOGD("Enter fd_:%{public}d.", fd_);
97 if (fd_ >= 0) {
98 close(fd_);
99 fd_ = -1;
100 UpdateDescript();
101 }
102 }
103
UpdateDescript()104 void UDSSession::UpdateDescript()
105 {
106 std::ostringstream oss;
107 oss << "fd = " << fd_
108 << ", programName = " << programName_
109 << ", moduleType = " << moduleType_
110 << ((fd_ < 0) ? ", closed" : ", opened")
111 << ", uid = " << uid_
112 << ", pid = " << pid_
113 << ", tokenType = " << tokenType_
114 << std::endl;
115 descript_ = oss.str().c_str();
116 }
117
SendMsg(NetPacket & pkt) const118 bool UDSSession::SendMsg(NetPacket &pkt) const
119 {
120 if (pkt.ChkRWError()) {
121 MMI_HILOGE("Read and write status is error");
122 return false;
123 }
124 StreamBuffer buf;
125 pkt.MakeData(buf);
126 return SendMsg(buf.Data(), buf.Size());
127 }
128
SaveANREvent(int32_t type,int32_t id,int64_t time,int32_t timerId)129 void UDSSession::SaveANREvent(int32_t type, int32_t id, int64_t time, int32_t timerId)
130 {
131 CALL_DEBUG_ENTER;
132 EventTime eventTime = { id, time, timerId };
133 auto iter = events_.find(type);
134 if (iter != events_.end()) {
135 iter->second.push_back(eventTime);
136 }
137 }
138
GetTimerIds(int32_t type)139 std::vector<int32_t> UDSSession::GetTimerIds(int32_t type)
140 {
141 auto iter = events_.find(type);
142 if (iter == events_.end()) {
143 MMI_HILOGE("Current events have no event type:%{public}d", type);
144 return {};
145 }
146 std::vector<int32_t> timers;
147 for (auto &item : iter->second) {
148 timers.push_back(item.timerId);
149 item.timerId = -1;
150 }
151 events_[iter->first] = iter->second;
152 return timers;
153 }
154
DelEvents(int32_t type,int32_t id)155 std::list<int32_t> UDSSession::DelEvents(int32_t type, int32_t id)
156 {
157 CALL_DEBUG_ENTER;
158 MMI_HILOGD("Delete events, anr type:%{public}d, id:%{public}d", type, id);
159 auto iter = events_.find(type);
160 if (iter == events_.end()) {
161 MMI_HILOGE("Current events have no event type:%{public}d", type);
162 return {};
163 }
164 auto &events = iter->second;
165 int32_t canDelEventCount = 0;
166 std::list<int32_t> timerIds;
167 for (auto &item : events) {
168 if (item.id > id) {
169 break;
170 }
171 MMI_HILOGD("Delete event, anr type:%{public}d, id:%{public}d, timerId:%{public}d", type, item.id, item.timerId);
172 timerIds.push_back(item.timerId);
173 ++canDelEventCount;
174 }
175 if (canDelEventCount == 0) {
176 MMI_HILOGW("Can not find event:%{public}d", id);
177 return timerIds;
178 }
179 events.erase(events.begin(), events.begin() + canDelEventCount);
180
181 if (events.empty()) {
182 isAnrProcess_[type] = false;
183 return timerIds;
184 }
185 MMI_HILOGD("First event, anr type:%{public}d, id:%{public}d, timerId:%{public}d", type,
186 events.begin()->id, events.begin()->timerId);
187 int64_t endTime = 0;
188 if (!AddInt64(events.begin()->eventTime, INPUT_UI_TIMEOUT_TIME, endTime)) {
189 MMI_HILOGE("The addition of endTime overflows");
190 return timerIds;
191 }
192 auto currentTime = GetSysClockTime();
193 if (currentTime < endTime) {
194 isAnrProcess_[type] = false;
195 }
196 return timerIds;
197 }
198
GetEarliestEventTime(int32_t type) const199 int64_t UDSSession::GetEarliestEventTime(int32_t type) const
200 {
201 CALL_DEBUG_ENTER;
202 auto iter = events_.find(type);
203 if (iter != events_.end()) {
204 if (iter->second.empty()) {
205 MMI_HILOGD("Current events is empty");
206 return 0;
207 }
208 return iter->second.begin()->eventTime;
209 }
210 return 0;
211 }
212
IsEventQueueEmpty(int32_t type)213 bool UDSSession::IsEventQueueEmpty(int32_t type)
214 {
215 CALL_DEBUG_ENTER;
216 auto iter = events_.find(type);
217 return (iter == events_.end() || (iter->second.empty()));
218 }
219 } // namespace MMI
220 } // namespace OHOS