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 "ComposerResources.h included without LOG_TAG"
21#endif
22
23#include <memory>
24#include <mutex>
25#include <unordered_map>
26#include <vector>
27
28#include <android/hardware/graphics/mapper/2.0/IMapper.h>
29#include <log/log.h>
30
31namespace android {
32namespace hardware {
33namespace graphics {
34namespace composer {
35namespace V2_1 {
36namespace hal {
37
38// wrapper for IMapper to import buffers and sideband streams
39class ComposerHandleImporter {
40   public:
41    bool init() {
42        mMapper = mapper::V2_0::IMapper::getService();
43        ALOGE_IF(!mMapper, "failed to get mapper service");
44        return mMapper != nullptr;
45    }
46
47    Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) {
48        if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) {
49            *outBufferHandle = nullptr;
50            return Error::NONE;
51        }
52
53        mapper::V2_0::Error error;
54        const native_handle_t* bufferHandle;
55        mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
56            error = tmpError;
57            bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
58        });
59        if (error != mapper::V2_0::Error::NONE) {
60            return Error::NO_RESOURCES;
61        }
62
63        *outBufferHandle = bufferHandle;
64        return Error::NONE;
65    }
66
67    void freeBuffer(const native_handle_t* bufferHandle) {
68        if (bufferHandle) {
69            mMapper->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
70        }
71    }
72
73    Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) {
74        const native_handle_t* streamHandle = nullptr;
75        if (rawHandle) {
76            streamHandle = native_handle_clone(rawHandle);
77            if (!streamHandle) {
78                return Error::NO_RESOURCES;
79            }
80        }
81
82        *outStreamHandle = streamHandle;
83        return Error::NONE;
84    }
85
86    void freeStream(const native_handle_t* streamHandle) {
87        if (streamHandle) {
88            native_handle_close(streamHandle);
89            native_handle_delete(const_cast<native_handle_t*>(streamHandle));
90        }
91    }
92
93   private:
94    sp<mapper::V2_0::IMapper> mMapper;
95};
96
97class ComposerHandleCache {
98   public:
99    enum class HandleType {
100        INVALID,
101        BUFFER,
102        STREAM,
103    };
104
105    ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize)
106        : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {}
107
108    // must be initialized later with initCache
109    ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {}
110
111    ~ComposerHandleCache() {
112        switch (mHandleType) {
113            case HandleType::BUFFER:
114                for (auto handle : mHandles) {
115                    mImporter.freeBuffer(handle);
116                }
117                break;
118            case HandleType::STREAM:
119                for (auto handle : mHandles) {
120                    mImporter.freeStream(handle);
121                }
122                break;
123            default:
124                break;
125        }
126    }
127
128    ComposerHandleCache(const ComposerHandleCache&) = delete;
129    ComposerHandleCache& operator=(const ComposerHandleCache&) = delete;
130
131    bool initCache(HandleType type, uint32_t cacheSize) {
132        // already initialized
133        if (mHandleType != HandleType::INVALID) {
134            return false;
135        }
136
137        mHandleType = type;
138        mHandles.resize(cacheSize, nullptr);
139
140        return true;
141    }
142
143    Error lookupCache(uint32_t slot, const native_handle_t** outHandle) {
144        if (slot < mHandles.size()) {
145            *outHandle = mHandles[slot];
146            return Error::NONE;
147        } else {
148            return Error::BAD_PARAMETER;
149        }
150    }
151
152    Error updateCache(uint32_t slot, const native_handle_t* handle,
153                      const native_handle** outReplacedHandle) {
154        if (slot < mHandles.size()) {
155            auto& cachedHandle = mHandles[slot];
156            *outReplacedHandle = cachedHandle;
157            cachedHandle = handle;
158            return Error::NONE;
159        } else {
160            return Error::BAD_PARAMETER;
161        }
162    }
163
164    // when fromCache is true, look up in the cache; otherwise, update the cache
165    Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
166                    const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
167        if (fromCache) {
168            *outReplacedHandle = nullptr;
169            return lookupCache(slot, outHandle);
170        } else {
171            *outHandle = inHandle;
172            return updateCache(slot, inHandle, outReplacedHandle);
173        }
174    }
175
176   private:
177    ComposerHandleImporter& mImporter;
178    HandleType mHandleType = HandleType::INVALID;
179    std::vector<const native_handle_t*> mHandles;
180};
181
182// layer resource
183class ComposerLayerResource {
184   public:
185    ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize)
186        : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize),
187          mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {}
188
189    Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
190                    const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
191        return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
192    }
193
194    Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
195                            const native_handle_t** outHandle,
196                            const native_handle** outReplacedHandle) {
197        return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle,
198                                              outReplacedHandle);
199    }
200
201   protected:
202    ComposerHandleCache mBufferCache;
203    ComposerHandleCache mSidebandStreamCache;
204};
205
206// display resource
207class ComposerDisplayResource {
208   public:
209    enum class DisplayType {
210        PHYSICAL,
211        VIRTUAL,
212    };
213
214    ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
215                            uint32_t outputBufferCacheSize)
216        : mType(type),
217          mClientTargetCache(importer),
218          mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER,
219                             outputBufferCacheSize) {}
220
221    bool initClientTargetCache(uint32_t cacheSize) {
222        return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
223    }
224
225    bool isVirtual() const { return mType == DisplayType::VIRTUAL; }
226
227    Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
228                          const native_handle_t** outHandle,
229                          const native_handle** outReplacedHandle) {
230        return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle,
231                                            outReplacedHandle);
232    }
233
234    Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
235                          const native_handle_t** outHandle,
236                          const native_handle** outReplacedHandle) {
237        return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
238                                            outReplacedHandle);
239    }
240
241    bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) {
242        auto result = mLayerResources.emplace(layer, std::move(layerResource));
243        return result.second;
244    }
245
246    bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; }
247
248    ComposerLayerResource* findLayerResource(Layer layer) {
249        auto layerIter = mLayerResources.find(layer);
250        if (layerIter == mLayerResources.end()) {
251            return nullptr;
252        }
253
254        return layerIter->second.get();
255    }
256
257    std::vector<Layer> getLayers() const {
258        std::vector<Layer> layers;
259        layers.reserve(mLayerResources.size());
260        for (const auto& layerKey : mLayerResources) {
261            layers.push_back(layerKey.first);
262        }
263        return layers;
264    }
265
266   protected:
267    const DisplayType mType;
268    ComposerHandleCache mClientTargetCache;
269    ComposerHandleCache mOutputBufferCache;
270
271    std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
272};
273
274class ComposerResources {
275   private:
276    template <bool isBuffer>
277    class ReplacedHandle;
278
279   public:
280    static std::unique_ptr<ComposerResources> create() {
281        auto resources = std::make_unique<ComposerResources>();
282        return resources->init() ? std::move(resources) : nullptr;
283    }
284
285    ComposerResources() = default;
286    virtual ~ComposerResources() = default;
287
288    bool init() { return mImporter.init(); }
289
290    using RemoveDisplay =
291        std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>;
292    void clear(RemoveDisplay removeDisplay) {
293        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
294        for (const auto& displayKey : mDisplayResources) {
295            Display display = displayKey.first;
296            const ComposerDisplayResource& displayResource = *displayKey.second;
297            removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers());
298        }
299        mDisplayResources.clear();
300    }
301
302    Error addPhysicalDisplay(Display display) {
303        auto displayResource =
304            createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0);
305
306        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
307        auto result = mDisplayResources.emplace(display, std::move(displayResource));
308        return result.second ? Error::NONE : Error::BAD_DISPLAY;
309    }
310
311    Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) {
312        auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL,
313                                                     outputBufferCacheSize);
314
315        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
316        auto result = mDisplayResources.emplace(display, std::move(displayResource));
317        return result.second ? Error::NONE : Error::BAD_DISPLAY;
318    }
319
320    Error removeDisplay(Display display) {
321        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
322        return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY;
323    }
324
325    Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) {
326        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
327        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
328        if (!displayResource) {
329            return Error::BAD_DISPLAY;
330        }
331
332        return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE
333                                                                             : Error::BAD_PARAMETER;
334    }
335
336    Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) {
337        auto layerResource = createLayerResource(bufferCacheSize);
338
339        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
340        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
341        if (!displayResource) {
342            return Error::BAD_DISPLAY;
343        }
344
345        return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE
346                                                                          : Error::BAD_LAYER;
347    }
348
349    Error removeLayer(Display display, Layer layer) {
350        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
351        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
352        if (!displayResource) {
353            return Error::BAD_DISPLAY;
354        }
355
356        return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER;
357    }
358
359    using ReplacedBufferHandle = ReplacedHandle<true>;
360    using ReplacedStreamHandle = ReplacedHandle<false>;
361
362    Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
363                                 const native_handle_t* rawHandle,
364                                 const native_handle_t** outBufferHandle,
365                                 ReplacedBufferHandle* outReplacedBuffer) {
366        return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle,
367                                               outBufferHandle, outReplacedBuffer);
368    }
369
370    Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
371                                 const native_handle_t* rawHandle,
372                                 const native_handle_t** outBufferHandle,
373                                 ReplacedBufferHandle* outReplacedBuffer) {
374        return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle,
375                                               outBufferHandle, outReplacedBuffer);
376    }
377
378    Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
379                         const native_handle_t* rawHandle, const native_handle_t** outBufferHandle,
380                         ReplacedBufferHandle* outReplacedBuffer) {
381        return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle,
382                                              outBufferHandle, outReplacedBuffer);
383    }
384
385    Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle,
386                                 const native_handle_t** outStreamHandle,
387                                 ReplacedStreamHandle* outReplacedStream) {
388        return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle,
389                                                       outStreamHandle, outReplacedStream);
390    }
391
392   protected:
393    virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
394        ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
395        return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
396    }
397
398    virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) {
399        return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize);
400    }
401
402    ComposerDisplayResource* findDisplayResourceLocked(Display display) {
403        auto iter = mDisplayResources.find(display);
404        if (iter == mDisplayResources.end()) {
405            return nullptr;
406        }
407        return iter->second.get();
408    }
409
410    ComposerHandleImporter mImporter;
411
412    std::mutex mDisplayResourcesMutex;
413    std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources;
414
415   private:
416    enum class Cache {
417        CLIENT_TARGET,
418        OUTPUT_BUFFER,
419        LAYER_BUFFER,
420        LAYER_SIDEBAND_STREAM,
421    };
422
423    // When a buffer in the cache is replaced by a new one, we must keep it
424    // alive until it has been replaced in ComposerHal.
425    template <bool isBuffer>
426    class ReplacedHandle {
427       public:
428        ReplacedHandle() = default;
429        ReplacedHandle(const ReplacedHandle&) = delete;
430        ReplacedHandle& operator=(const ReplacedHandle&) = delete;
431
432        ~ReplacedHandle() { reset(); }
433
434        void reset(ComposerHandleImporter* importer = nullptr,
435                   const native_handle_t* handle = nullptr) {
436            if (mHandle) {
437                if (isBuffer) {
438                    mImporter->freeBuffer(mHandle);
439                } else {
440                    mImporter->freeStream(mHandle);
441                }
442            }
443
444            mImporter = importer;
445            mHandle = handle;
446        }
447
448       private:
449        ComposerHandleImporter* mImporter = nullptr;
450        const native_handle_t* mHandle = nullptr;
451    };
452
453    template <Cache cache, bool isBuffer>
454    Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache,
455                    const native_handle_t* rawHandle, const native_handle_t** outHandle,
456                    ReplacedHandle<isBuffer>* outReplacedHandle) {
457        Error error;
458
459        // import the raw handle (or ignore raw handle when fromCache is true)
460        const native_handle_t* importedHandle = nullptr;
461        if (!fromCache) {
462            error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle)
463                               : mImporter.importStream(rawHandle, &importedHandle);
464            if (error != Error::NONE) {
465                return error;
466            }
467        }
468
469        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
470
471        // find display/layer resource
472        const bool needLayerResource =
473            (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM);
474        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
475        ComposerLayerResource* layerResource = (displayResource && needLayerResource)
476                                                   ? displayResource->findLayerResource(layer)
477                                                   : nullptr;
478
479        // lookup or update cache
480        const native_handle_t* replacedHandle = nullptr;
481        if (displayResource && (!needLayerResource || layerResource)) {
482            switch (cache) {
483                case Cache::CLIENT_TARGET:
484                    error = displayResource->getClientTarget(slot, fromCache, importedHandle,
485                                                             outHandle, &replacedHandle);
486                    break;
487                case Cache::OUTPUT_BUFFER:
488                    error = displayResource->getOutputBuffer(slot, fromCache, importedHandle,
489                                                             outHandle, &replacedHandle);
490                    break;
491                case Cache::LAYER_BUFFER:
492                    error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle,
493                                                     &replacedHandle);
494                    break;
495                case Cache::LAYER_SIDEBAND_STREAM:
496                    error = layerResource->getSidebandStream(slot, fromCache, importedHandle,
497                                                             outHandle, &replacedHandle);
498                    break;
499                default:
500                    error = Error::BAD_PARAMETER;
501                    break;
502            }
503
504            if (error != Error::NONE) {
505                ALOGW("invalid cache %d slot %d", int(cache), int(slot));
506            }
507        } else if (!displayResource) {
508            error = Error::BAD_DISPLAY;
509        } else {
510            error = Error::BAD_LAYER;
511        }
512
513        // clean up on errors
514        if (error != Error::NONE) {
515            if (!fromCache) {
516                if (isBuffer) {
517                    mImporter.freeBuffer(importedHandle);
518                } else {
519                    mImporter.freeStream(importedHandle);
520                }
521            }
522            return error;
523        }
524
525        outReplacedHandle->reset(&mImporter, replacedHandle);
526
527        return Error::NONE;
528    }
529};
530
531}  // namespace hal
532}  // namespace V2_1
533}  // namespace composer
534}  // namespace graphics
535}  // namespace hardware
536}  // namespace android
537