1/*
2 * Copyright (C) 2017 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#ifndef STAGEFRIGHT_FOUNDATION_FILE_DESCRIPTOR_H_
18#define STAGEFRIGHT_FOUNDATION_FILE_DESCRIPTOR_H_
19
20#include <memory>
21
22namespace android {
23
24/**
25 * FileDescriptor is a utility class for managing file descriptors in a scoped way.
26 *
27 * usage:
28 *
29 * status_t function(int fd) {
30 *   FileDescriptor::Autoclose managedFd(fd);
31 *   if (error_condition)
32 *     return ERROR;
33 *   next_function(managedFd.release());
34 * }
35 */
36struct FileDescriptor {
37    // created this class with minimal methods. more methods can be added here to manage
38    // a shared file descriptor object.
39
40    /**
41     * A locally scoped managed file descriptor object. This object is not shareable/copiable and
42     * is not thread safe.
43     */
44    struct Autoclose {
45        // created this class with minimal methods
46        /**
47         * Creates a locally scoped file descriptor holder object taking ownership of the passed in
48         * file descriptor.
49         */
50        Autoclose(int fd)
51            : mFd(fd) {
52
53        }
54
55        ~Autoclose() {
56            if (isValid()) {
57                ::close(mFd);
58                mFd = kInvalidFileDescriptor;
59            }
60        }
61
62        /**
63         * Releases the managed file descriptor from the holder. This invalidates the (remaining)
64         * file descriptor in this object.
65         */
66        int release() {
67            int managedFd = mFd;
68            mFd = kInvalidFileDescriptor;
69            return managedFd;
70        }
71
72        /**
73         * Checks whether the managed file descriptor is valid
74         */
75        bool isValid() const {
76            return mFd >= 0;
77        }
78
79    private:
80        // not yet needed
81
82        /**
83         * Returns the managed file descriptor from this object without releasing the ownership.
84         * The returned file descriptor has the same lifecycle as the managed file descriptor
85         * in this object. Therefore, care must be taken that it is not closed, and that this
86         * object keeps managing the returned file descriptor for the duration of its use.
87         */
88        int get() const {
89            return mFd;
90        }
91
92    private:
93        int mFd;
94
95        enum {
96            kInvalidFileDescriptor = -1,
97        };
98
99        DISALLOW_EVIL_CONSTRUCTORS(Autoclose);
100    };
101
102private:
103    std::shared_ptr<Autoclose> mSharedFd;
104};
105
106}  // namespace android
107
108#endif  // STAGEFRIGHT_FOUNDATION_FLAGGED_H_
109
110