1/*
2 * Copyright 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#pragma once
18
19#ifndef LOG_TAG
20#warning "Composer.h included without LOG_TAG"
21#endif
22
23#include <array>
24#include <chrono>
25#include <condition_variable>
26#include <memory>
27#include <mutex>
28#include <vector>
29
30#include <android/hardware/graphics/composer/2.1/IComposer.h>
31#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
32#include <composer-hal/2.1/ComposerClient.h>
33#include <composer-hal/2.1/ComposerHal.h>
34
35namespace android {
36namespace hardware {
37namespace graphics {
38namespace composer {
39namespace V2_1 {
40namespace hal {
41
42namespace detail {
43
44// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
45template <typename Interface, typename Hal>
46class ComposerImpl : public Interface {
47   public:
48    static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
49        return std::make_unique<ComposerImpl>(std::move(hal));
50    }
51
52    ComposerImpl(std::unique_ptr<Hal> hal) : mHal(std::move(hal)) {}
53
54    // IComposer 2.1 interface
55
56    Return<void> getCapabilities(IComposer::getCapabilities_cb hidl_cb) override {
57        const std::array<IComposer::Capability, 3> all_caps = {{
58            IComposer::Capability::SIDEBAND_STREAM,
59            IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM,
60            IComposer::Capability::PRESENT_FENCE_IS_NOT_RELIABLE,
61        }};
62
63        std::vector<IComposer::Capability> caps;
64        for (auto cap : all_caps) {
65            if (mHal->hasCapability(static_cast<hwc2_capability_t>(cap))) {
66                caps.push_back(cap);
67            }
68        }
69
70        hidl_vec<IComposer::Capability> caps_reply;
71        caps_reply.setToExternal(caps.data(), caps.size());
72        hidl_cb(caps_reply);
73        return Void();
74    }
75
76    Return<void> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override {
77        hidl_cb(mHal->dumpDebugInfo());
78        return Void();
79    }
80
81    Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
82        std::unique_lock<std::mutex> lock(mClientMutex);
83        if (!waitForClientDestroyedLocked(lock)) {
84            hidl_cb(Error::NO_RESOURCES, nullptr);
85            return Void();
86        }
87
88        sp<IComposerClient> client = createClient();
89        if (!client) {
90            hidl_cb(Error::NO_RESOURCES, nullptr);
91            return Void();
92        }
93
94        mClient = client;
95        hidl_cb(Error::NONE, client);
96        return Void();
97    }
98
99   protected:
100    bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) {
101        if (mClient != nullptr) {
102            using namespace std::chrono_literals;
103
104            // In surface flinger we delete a composer client on one thread and
105            // then create a new client on another thread. Although surface
106            // flinger ensures the calls are made in that sequence (destroy and
107            // then create), sometimes the calls land in the composer service
108            // inverted (create and then destroy). Wait for a brief period to
109            // see if the existing client is destroyed.
110            ALOGD("waiting for previous client to be destroyed");
111            mClientDestroyedCondition.wait_for(
112                lock, 1s, [this]() -> bool { return mClient.promote() == nullptr; });
113            if (mClient.promote() != nullptr) {
114                ALOGD("previous client was not destroyed");
115            } else {
116                mClient.clear();
117            }
118        }
119
120        return mClient == nullptr;
121    }
122
123    void onClientDestroyed() {
124        std::lock_guard<std::mutex> lock(mClientMutex);
125        mClient.clear();
126        mClientDestroyedCondition.notify_all();
127    }
128
129    virtual IComposerClient* createClient() {
130        auto client = ComposerClient::create(mHal.get());
131        if (!client) {
132            return nullptr;
133        }
134
135        auto clientDestroyed = [this]() { onClientDestroyed(); };
136        client->setOnClientDestroyed(clientDestroyed);
137
138        return client.release();
139    }
140
141    const std::unique_ptr<Hal> mHal;
142
143    std::mutex mClientMutex;
144    wp<IComposerClient> mClient;
145    std::condition_variable mClientDestroyedCondition;
146};
147
148}  // namespace detail
149
150using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
151
152}  // namespace hal
153}  // namespace V2_1
154}  // namespace composer
155}  // namespace graphics
156}  // namespace hardware
157}  // namespace android
158