• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
35 namespace android {
36 namespace hardware {
37 namespace graphics {
38 namespace composer {
39 namespace V2_1 {
40 namespace hal {
41 
42 namespace detail {
43 
44 // ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
45 template <typename Interface, typename Hal>
46 class ComposerImpl : public Interface {
47    public:
create(std::unique_ptr<Hal> hal)48     static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
49         return std::make_unique<ComposerImpl>(std::move(hal));
50     }
51 
ComposerImpl(std::unique_ptr<Hal> hal)52     ComposerImpl(std::unique_ptr<Hal> hal) : mHal(std::move(hal)) {}
53 
54     // IComposer 2.1 interface
55 
getCapabilities(IComposer::getCapabilities_cb hidl_cb)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 
dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb)76     Return<void> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override {
77         hidl_cb(mHal->dumpDebugInfo());
78         return Void();
79     }
80 
createClient(IComposer::createClient_cb hidl_cb)81     Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
82         std::unique_lock<std::mutex> lock(mClientMutex);
83         bool destroyed = waitForClientDestroyedLocked(lock);
84         if (!destroyed) {
85             hidl_cb(Error::NO_RESOURCES, nullptr);
86             return Void();
87         }
88 
89         sp<IComposerClient> client = createClient();
90         if (!client) {
91             hidl_cb(Error::NO_RESOURCES, nullptr);
92             return Void();
93         }
94 
95         mClient = client;
96         hidl_cb(Error::NONE, client);
97         return Void();
98     }
99 
100    protected:
waitForClientDestroyedLocked(std::unique_lock<std::mutex> & lock)101     bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) {
102         if (mClient != nullptr) {
103             using namespace std::chrono_literals;
104 
105             // In surface flinger we delete a composer client on one thread and
106             // then create a new client on another thread. Although surface
107             // flinger ensures the calls are made in that sequence (destroy and
108             // then create), sometimes the calls land in the composer service
109             // inverted (create and then destroy). Wait for a brief period to
110             // see if the existing client is destroyed.
111             ALOGD("waiting for previous client to be destroyed");
112             mClientDestroyedCondition.wait_for(lock, 1s,
113                                                [this]() -> bool { return mClient == nullptr; });
114             if (mClient != nullptr) {
115                 ALOGD("previous client was not destroyed");
116             }
117         }
118 
119         return mClient == nullptr;
120     }
121 
onClientDestroyed()122     void onClientDestroyed() {
123         std::lock_guard<std::mutex> lock(mClientMutex);
124         mClient.clear();
125         mClientDestroyedCondition.notify_all();
126     }
127 
createClient()128     virtual IComposerClient* createClient() {
129         auto client = ComposerClient::create(mHal.get());
130         if (!client) {
131             return nullptr;
132         }
133 
134         auto clientDestroyed = [this]() { onClientDestroyed(); };
135         client->setOnClientDestroyed(clientDestroyed);
136 
137         return client.release();
138     }
139 
140     const std::unique_ptr<Hal> mHal;
141 
142     std::mutex mClientMutex;
143     wp<IComposerClient> mClient;
144     std::condition_variable mClientDestroyedCondition;
145 };
146 
147 }  // namespace detail
148 
149 using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
150 
151 }  // namespace hal
152 }  // namespace V2_1
153 }  // namespace composer
154 }  // namespace graphics
155 }  // namespace hardware
156 }  // namespace android
157