1/*
2 * Copyright 2018 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#pragma once
18
19#ifndef LOG_TAG
20#warning "Mapper.h included without LOG_TAG"
21#endif
22
23#include <memory>
24
25#include <android/hardware/graphics/mapper/2.0/IMapper.h>
26#include <log/log.h>
27#include <mapper-hal/2.0/MapperHal.h>
28
29namespace android {
30namespace hardware {
31namespace graphics {
32namespace mapper {
33namespace V2_0 {
34namespace hal {
35
36namespace detail {
37
38// MapperImpl implements V2_*::IMapper on top of V2_*::hal::MapperHal
39template <typename Interface, typename Hal>
40class MapperImpl : public Interface {
41   public:
42    bool init(std::unique_ptr<Hal> hal) {
43        mHal = std::move(hal);
44        return true;
45    }
46
47    // IMapper 2.0 interface
48
49    Return<void> createDescriptor(const V2_0::IMapper::BufferDescriptorInfo& descriptorInfo,
50                                  IMapper::createDescriptor_cb hidl_cb) override {
51        BufferDescriptor descriptor;
52        Error error = mHal->createDescriptor(descriptorInfo, &descriptor);
53        hidl_cb(error, descriptor);
54        return Void();
55    }
56
57    Return<void> importBuffer(const hidl_handle& rawHandle,
58                              IMapper::importBuffer_cb hidl_cb) override {
59        if (!rawHandle.getNativeHandle()) {
60            hidl_cb(Error::BAD_BUFFER, nullptr);
61            return Void();
62        }
63
64        native_handle_t* bufferHandle = nullptr;
65        Error error = mHal->importBuffer(rawHandle.getNativeHandle(), &bufferHandle);
66        if (error != Error::NONE) {
67            hidl_cb(error, nullptr);
68            return Void();
69        }
70
71        void* buffer = addImportedBuffer(bufferHandle);
72        if (!buffer) {
73            mHal->freeBuffer(bufferHandle);
74            hidl_cb(Error::NO_RESOURCES, nullptr);
75            return Void();
76        }
77
78        hidl_cb(error, buffer);
79        return Void();
80    }
81
82    Return<Error> freeBuffer(void* buffer) override {
83        native_handle_t* bufferHandle = removeImportedBuffer(buffer);
84        if (!bufferHandle) {
85            return Error::BAD_BUFFER;
86        }
87
88        return mHal->freeBuffer(bufferHandle);
89    }
90
91    Return<void> lock(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
92                      const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb) override {
93        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
94        if (!bufferHandle) {
95            hidl_cb(Error::BAD_BUFFER, nullptr);
96            return Void();
97        }
98
99        base::unique_fd fenceFd;
100        Error error = getFenceFd(acquireFence, &fenceFd);
101        if (error != Error::NONE) {
102            hidl_cb(error, nullptr);
103            return Void();
104        }
105
106        void* data = nullptr;
107        error = mHal->lock(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &data);
108        hidl_cb(error, data);
109        return Void();
110    }
111
112    Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
113                           const hidl_handle& acquireFence,
114                           IMapper::lockYCbCr_cb hidl_cb) override {
115        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
116        if (!bufferHandle) {
117            hidl_cb(Error::BAD_BUFFER, YCbCrLayout{});
118            return Void();
119        }
120
121        base::unique_fd fenceFd;
122        Error error = getFenceFd(acquireFence, &fenceFd);
123        if (error != Error::NONE) {
124            hidl_cb(error, YCbCrLayout{});
125            return Void();
126        }
127
128        YCbCrLayout layout{};
129        error = mHal->lockYCbCr(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &layout);
130        hidl_cb(error, layout);
131        return Void();
132    }
133
134    Return<void> unlock(void* buffer, IMapper::unlock_cb hidl_cb) override {
135        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
136        if (!bufferHandle) {
137            hidl_cb(Error::BAD_BUFFER, nullptr);
138            return Void();
139        }
140
141        base::unique_fd fenceFd;
142        Error error = mHal->unlock(bufferHandle, &fenceFd);
143        if (error != Error::NONE) {
144            hidl_cb(error, nullptr);
145            return Void();
146        }
147
148        NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
149        hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
150        return Void();
151    }
152
153   protected:
154    // these functions can be overriden to do true imported buffer management
155    virtual void* addImportedBuffer(native_handle_t* bufferHandle) {
156        return static_cast<void*>(bufferHandle);
157    }
158
159    virtual native_handle_t* removeImportedBuffer(void* buffer) {
160        return static_cast<native_handle_t*>(buffer);
161    }
162
163    virtual const native_handle_t* getImportedBuffer(void* buffer) const {
164        return static_cast<const native_handle_t*>(buffer);
165    }
166
167    // convert fenceFd to or from hidl_handle
168    static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
169        auto handle = fenceHandle.getNativeHandle();
170        if (handle && handle->numFds > 1) {
171            ALOGE("invalid fence handle with %d fds", handle->numFds);
172            return Error::BAD_VALUE;
173        }
174
175        int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
176        if (fenceFd >= 0) {
177            fenceFd = dup(fenceFd);
178            if (fenceFd < 0) {
179                return Error::NO_RESOURCES;
180            }
181        }
182
183        outFenceFd->reset(fenceFd);
184
185        return Error::NONE;
186    }
187
188    static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
189        native_handle_t* handle = nullptr;
190        if (fenceFd >= 0) {
191            handle = native_handle_init(handleStorage, 1, 0);
192            handle->data[0] = fenceFd;
193        }
194
195        return hidl_handle(handle);
196    }
197
198    std::unique_ptr<Hal> mHal;
199};
200
201}  // namespace detail
202
203using Mapper = detail::MapperImpl<IMapper, MapperHal>;
204
205}  // namespace hal
206}  // namespace V2_0
207}  // namespace mapper
208}  // namespace graphics
209}  // namespace hardware
210}  // namespace android
211