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#pragma once
17
18#ifndef FD_BUFFER_H
19#define FD_BUFFER_H
20
21#include <android-base/unique_fd.h>
22#include <android/util/EncodedBuffer.h>
23#include <utils/Errors.h>
24
25namespace android {
26namespace os {
27namespace incidentd {
28
29using namespace android::base;
30using namespace android::util;
31
32/**
33 * Reads data from fd into a buffer, fd must be closed explicitly.
34 */
35class FdBuffer {
36public:
37    FdBuffer();
38    ~FdBuffer();
39
40    /**
41     * Read the data until the timeout is hit or we hit eof.
42     * Returns NO_ERROR if there were no errors or if we timed out.
43     * Will mark the file O_NONBLOCK.
44     */
45    status_t read(int fd, int64_t timeoutMs);
46
47    /**
48     * Read the data until we hit eof.
49     * Returns NO_ERROR if there were no errors.
50     */
51    status_t readFully(int fd);
52
53    /**
54     * Read processed results by streaming data to a parsing process, e.g. incident helper.
55     * The parsing process provides IO fds which are 'toFd' and 'fromFd'. The function
56     * reads original data in 'fd' and writes to parsing process through 'toFd', then it reads
57     * and stores the processed data from 'fromFd' in memory for later usage.
58     * This function behaves in a streaming fashion in order to save memory usage.
59     * Returns NO_ERROR if there were no errors or if we timed out.
60     *
61     * Poll will return POLLERR if fd is from sysfs, handle this edge case.
62     */
63    status_t readProcessedDataInStream(int fd, unique_fd toFd, unique_fd fromFd, int64_t timeoutMs,
64                                       const bool isSysfs = false);
65
66    /**
67     * Whether we timed out.
68     */
69    bool timedOut() const { return mTimedOut; }
70
71    /**
72     * If more than 4 MB is read, we truncate the data and return success.
73     * Downstream tools must handle truncated incident reports as best as possible
74     * anyway because they could be cut off for a lot of reasons and it's best
75     * to get as much useful information out of the system as possible. If this
76     * happens, truncated() will return true so it can be marked. If the data is
77     * exactly 4 MB, truncated is still set. Sorry.
78     */
79    bool truncated() const { return mTruncated; }
80
81    /**
82     * How much data was read.
83     */
84    size_t size() const;
85
86    /**
87     * How long the read took in milliseconds.
88     */
89    int64_t durationMs() const { return mFinishTime - mStartTime; }
90
91    /**
92     * Reader API for data stored in FdBuffer
93     */
94    EncodedBuffer::iterator data() const;
95
96    /**
97     * Return the internal buffer, don't call unless you are familiar with EncodedBuffer.
98     */
99    EncodedBuffer* getInternalBuffer() { return &mBuffer; }
100
101private:
102    EncodedBuffer mBuffer;
103    int64_t mStartTime;
104    int64_t mFinishTime;
105    bool mTimedOut;
106    bool mTruncated;
107};
108
109}  // namespace incidentd
110}  // namespace os
111}  // namespace android
112
113#endif  // FD_BUFFER_H
114