• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "incidentd"
18 
19 #include "FdBuffer.h"
20 
21 #include <cutils/log.h>
22 #include <utils/SystemClock.h>
23 
24 #include <fcntl.h>
25 #include <poll.h>
26 #include <unistd.h>
27 
28 const ssize_t BUFFER_SIZE = 16 * 1024;
29 const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
30 
31 
FdBuffer()32 FdBuffer::FdBuffer()
33     :mBuffers(),
34      mStartTime(-1),
35      mFinishTime(-1),
36      mCurrentWritten(-1),
37      mTimedOut(false),
38      mTruncated(false)
39 {
40 }
41 
~FdBuffer()42 FdBuffer::~FdBuffer()
43 {
44     const int N = mBuffers.size();
45     for (int i=0; i<N; i++) {
46         uint8_t* buf = mBuffers[i];
47         free(buf);
48     }
49 }
50 
51 status_t
read(int fd,int64_t timeout)52 FdBuffer::read(int fd, int64_t timeout)
53 {
54     struct pollfd pfds = {
55         .fd = fd,
56         .events = POLLIN
57     };
58     mStartTime = uptimeMillis();
59 
60     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
61 
62     uint8_t* buf = NULL;
63     while (true) {
64         if (mCurrentWritten >= BUFFER_SIZE || mCurrentWritten < 0) {
65             if (mBuffers.size() == MAX_BUFFER_COUNT) {
66                 mTruncated = true;
67                 break;
68             }
69             buf = (uint8_t*)malloc(BUFFER_SIZE);
70             if (buf == NULL) {
71                 return NO_MEMORY;
72             }
73             mBuffers.push_back(buf);
74             mCurrentWritten = 0;
75         }
76 
77         int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
78         if (remainingTime <= 0) {
79             mTimedOut = true;
80             break;
81         }
82 
83         int count = poll(&pfds, 1, remainingTime);
84         if (count == 0) {
85             mTimedOut = true;
86             break;
87         } else if (count < 0) {
88             return -errno;
89         } else {
90             if ((pfds.revents & POLLERR) != 0) {
91                 return errno != 0 ? -errno : UNKNOWN_ERROR;
92             } else {
93                 ssize_t amt = ::read(fd, buf + mCurrentWritten, BUFFER_SIZE - mCurrentWritten);
94                 if (amt < 0) {
95                     if (errno == EAGAIN || errno == EWOULDBLOCK) {
96                         continue;
97                     } else {
98                         return -errno;
99                     }
100                 } else if (amt == 0) {
101                     break;
102                 }
103                 mCurrentWritten += amt;
104             }
105         }
106     }
107 
108     mFinishTime = uptimeMillis();
109     return NO_ERROR;
110 }
111 
112 size_t
size()113 FdBuffer::size()
114 {
115     return ((mBuffers.size() - 1) * BUFFER_SIZE) + mCurrentWritten;
116 }
117 
118 status_t
write(ReportRequestSet * reporter)119 FdBuffer::write(ReportRequestSet* reporter)
120 {
121     const int N = mBuffers.size() - 1;
122     for (int i=0; i<N; i++) {
123         reporter->write(mBuffers[i], BUFFER_SIZE);
124     }
125     reporter->write(mBuffers[N], mCurrentWritten);
126     return NO_ERROR;
127 }
128 
129 
130