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 "ComposerClient.h included without LOG_TAG"
21 #endif
22 
23 #include <memory>
24 #include <mutex>
25 #include <vector>
26 
27 #include <android/hardware/graphics/composer/2.1/IComposerClient.h>
28 #include <composer-hal/2.1/ComposerCommandEngine.h>
29 #include <composer-hal/2.1/ComposerHal.h>
30 #include <composer-resources/2.1/ComposerResources.h>
31 #include <log/log.h>
32 
33 namespace android {
34 namespace hardware {
35 namespace graphics {
36 namespace composer {
37 namespace V2_1 {
38 namespace hal {
39 
40 namespace detail {
41 
42 // ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
43 template <typename Interface, typename Hal>
44 class ComposerClientImpl : public Interface {
45    public:
create(Hal * hal)46     static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
47         auto client = std::make_unique<ComposerClientImpl>(hal);
48         return client->init() ? std::move(client) : nullptr;
49     }
50 
ComposerClientImpl(Hal * hal)51     ComposerClientImpl(Hal* hal) : mHal(hal) {}
52 
~ComposerClientImpl()53     virtual ~ComposerClientImpl() {
54         // not initialized
55         if (!mCommandEngine) {
56             return;
57         }
58 
59         ALOGD("destroying composer client");
60 
61         mHal->unregisterEventCallback();
62         destroyResources();
63         if (mOnClientDestroyed) {
64             mOnClientDestroyed();
65         }
66 
67         ALOGD("removed composer client");
68     }
69 
init()70     bool init() {
71         mResources = createResources();
72         if (!mResources) {
73             ALOGE("failed to create composer resources");
74             return false;
75         }
76 
77         mCommandEngine = createCommandEngine();
78 
79         return true;
80     }
81 
setOnClientDestroyed(std::function<void ()> onClientDestroyed)82     void setOnClientDestroyed(std::function<void()> onClientDestroyed) {
83         mOnClientDestroyed = onClientDestroyed;
84     }
85 
86     // IComposerClient 2.1 interface
87 
88     class HalEventCallback : public Hal::EventCallback {
89        public:
HalEventCallback(const sp<IComposerCallback> callback,ComposerResources * resources)90         HalEventCallback(const sp<IComposerCallback> callback, ComposerResources* resources)
91             : mCallback(callback), mResources(resources) {}
92 
onHotplug(Display display,IComposerCallback::Connection connected)93         void onHotplug(Display display, IComposerCallback::Connection connected) {
94             if (connected == IComposerCallback::Connection::CONNECTED) {
95                 mResources->addPhysicalDisplay(display);
96             } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
97                 mResources->removeDisplay(display);
98             }
99 
100             auto ret = mCallback->onHotplug(display, connected);
101             ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
102         }
103 
onRefresh(Display display)104         void onRefresh(Display display) {
105             mResources->setDisplayMustValidateState(display, true);
106             auto ret = mCallback->onRefresh(display);
107             ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
108         }
109 
onVsync(Display display,int64_t timestamp)110         void onVsync(Display display, int64_t timestamp) {
111             auto ret = mCallback->onVsync(display, timestamp);
112             ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
113         }
114 
115        protected:
116         const sp<IComposerCallback> mCallback;
117         ComposerResources* const mResources;
118     };
119 
registerCallback(const sp<IComposerCallback> & callback)120     Return<void> registerCallback(const sp<IComposerCallback>& callback) override {
121         // no locking as we require this function to be called only once
122         mHalEventCallback = std::make_unique<HalEventCallback>(callback, mResources.get());
123         mHal->registerEventCallback(mHalEventCallback.get());
124         return Void();
125     }
126 
getMaxVirtualDisplayCount()127     Return<uint32_t> getMaxVirtualDisplayCount() override {
128         return mHal->getMaxVirtualDisplayCount();
129     }
130 
createVirtualDisplay(uint32_t width,uint32_t height,PixelFormat formatHint,uint32_t outputBufferSlotCount,IComposerClient::createVirtualDisplay_cb hidl_cb)131     Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
132                                       uint32_t outputBufferSlotCount,
133                                       IComposerClient::createVirtualDisplay_cb hidl_cb) override {
134         Display display = 0;
135         Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display);
136         if (err == Error::NONE) {
137             mResources->addVirtualDisplay(display, outputBufferSlotCount);
138         }
139 
140         hidl_cb(err, display, formatHint);
141         return Void();
142     }
143 
destroyVirtualDisplay(Display display)144     Return<Error> destroyVirtualDisplay(Display display) override {
145         Error err = mHal->destroyVirtualDisplay(display);
146         if (err == Error::NONE) {
147             mResources->removeDisplay(display);
148         }
149 
150         return err;
151     }
152 
createLayer(Display display,uint32_t bufferSlotCount,IComposerClient::createLayer_cb hidl_cb)153     Return<void> createLayer(Display display, uint32_t bufferSlotCount,
154                              IComposerClient::createLayer_cb hidl_cb) override {
155         Layer layer = 0;
156         Error err = mHal->createLayer(display, &layer);
157         if (err == Error::NONE) {
158             err = mResources->addLayer(display, layer, bufferSlotCount);
159             if (err != Error::NONE) {
160                 // The display entry may have already been removed by onHotplug.
161                 // Note: We do not destroy the layer on this error as the hotplug
162                 // disconnect invalidates the display id. The implementation should
163                 // ensure all layers for the display are destroyed.
164                 layer = 0;
165             }
166         }
167 
168         hidl_cb(err, layer);
169         return Void();
170     }
171 
destroyLayer(Display display,Layer layer)172     Return<Error> destroyLayer(Display display, Layer layer) override {
173         Error err = mHal->destroyLayer(display, layer);
174         if (err == Error::NONE) {
175             mResources->removeLayer(display, layer);
176         }
177 
178         return err;
179     }
180 
getActiveConfig(Display display,IComposerClient::getActiveConfig_cb hidl_cb)181     Return<void> getActiveConfig(Display display,
182                                  IComposerClient::getActiveConfig_cb hidl_cb) override {
183         Config config = 0;
184         Error err = mHal->getActiveConfig(display, &config);
185         hidl_cb(err, config);
186         return Void();
187     }
188 
getClientTargetSupport(Display display,uint32_t width,uint32_t height,PixelFormat format,Dataspace dataspace)189     Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height,
190                                          PixelFormat format, Dataspace dataspace) override {
191         Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace);
192         return err;
193     }
194 
getColorModes(Display display,IComposerClient::getColorModes_cb hidl_cb)195     Return<void> getColorModes(Display display,
196                                IComposerClient::getColorModes_cb hidl_cb) override {
197         hidl_vec<ColorMode> modes;
198         Error err = mHal->getColorModes(display, &modes);
199         hidl_cb(err, modes);
200         return Void();
201     }
202 
getDisplayAttribute(Display display,Config config,IComposerClient::Attribute attribute,IComposerClient::getDisplayAttribute_cb hidl_cb)203     Return<void> getDisplayAttribute(Display display, Config config,
204                                      IComposerClient::Attribute attribute,
205                                      IComposerClient::getDisplayAttribute_cb hidl_cb) override {
206         int32_t value = 0;
207         Error err = mHal->getDisplayAttribute(display, config, attribute, &value);
208         hidl_cb(err, value);
209         return Void();
210     }
211 
getDisplayConfigs(Display display,IComposerClient::getDisplayConfigs_cb hidl_cb)212     Return<void> getDisplayConfigs(Display display,
213                                    IComposerClient::getDisplayConfigs_cb hidl_cb) override {
214         hidl_vec<Config> configs;
215         Error err = mHal->getDisplayConfigs(display, &configs);
216         hidl_cb(err, configs);
217         return Void();
218     }
219 
getDisplayName(Display display,IComposerClient::getDisplayName_cb hidl_cb)220     Return<void> getDisplayName(Display display,
221                                 IComposerClient::getDisplayName_cb hidl_cb) override {
222         hidl_string name;
223         Error err = mHal->getDisplayName(display, &name);
224         hidl_cb(err, name);
225         return Void();
226     }
227 
getDisplayType(Display display,IComposerClient::getDisplayType_cb hidl_cb)228     Return<void> getDisplayType(Display display,
229                                 IComposerClient::getDisplayType_cb hidl_cb) override {
230         IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
231         Error err = mHal->getDisplayType(display, &type);
232         hidl_cb(err, type);
233         return Void();
234     }
235 
getDozeSupport(Display display,IComposerClient::getDozeSupport_cb hidl_cb)236     Return<void> getDozeSupport(Display display,
237                                 IComposerClient::getDozeSupport_cb hidl_cb) override {
238         bool support = false;
239         Error err = mHal->getDozeSupport(display, &support);
240         hidl_cb(err, support);
241         return Void();
242     }
243 
getHdrCapabilities(Display display,IComposerClient::getHdrCapabilities_cb hidl_cb)244     Return<void> getHdrCapabilities(Display display,
245                                     IComposerClient::getHdrCapabilities_cb hidl_cb) override {
246         hidl_vec<Hdr> types;
247         float max_lumi = 0.0f;
248         float max_avg_lumi = 0.0f;
249         float min_lumi = 0.0f;
250         Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi);
251         hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
252         return Void();
253     }
254 
setActiveConfig(Display display,Config config)255     Return<Error> setActiveConfig(Display display, Config config) override {
256         Error err = mHal->setActiveConfig(display, config);
257         return err;
258     }
259 
setColorMode(Display display,ColorMode mode)260     Return<Error> setColorMode(Display display, ColorMode mode) override {
261         Error err = mHal->setColorMode(display, mode);
262         return err;
263     }
264 
setPowerMode(Display display,IComposerClient::PowerMode mode)265     Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override {
266         Error err = mHal->setPowerMode(display, mode);
267         return err;
268     }
269 
setVsyncEnabled(Display display,IComposerClient::Vsync enabled)270     Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
271         Error err = mHal->setVsyncEnabled(display, enabled);
272         return err;
273     }
274 
setClientTargetSlotCount(Display display,uint32_t clientTargetSlotCount)275     Return<Error> setClientTargetSlotCount(Display display,
276                                            uint32_t clientTargetSlotCount) override {
277         return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
278     }
279 
setInputCommandQueue(const MQDescriptorSync<uint32_t> & descriptor)280     Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override {
281         std::lock_guard<std::mutex> lock(mCommandEngineMutex);
282         return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES;
283     }
284 
getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb)285     Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override {
286         // no locking as we require this function to be called inside
287         // executeCommands_cb
288         auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
289         if (outDescriptor) {
290             hidl_cb(Error::NONE, *outDescriptor);
291         } else {
292             hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
293         }
294 
295         return Void();
296     }
297 
executeCommands(uint32_t inLength,const hidl_vec<hidl_handle> & inHandles,IComposerClient::executeCommands_cb hidl_cb)298     Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
299                                  IComposerClient::executeCommands_cb hidl_cb) override {
300         std::lock_guard<std::mutex> lock(mCommandEngineMutex);
301         bool outChanged = false;
302         uint32_t outLength = 0;
303         hidl_vec<hidl_handle> outHandles;
304         Error error =
305             mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
306 
307         hidl_cb(error, outChanged, outLength, outHandles);
308 
309         mCommandEngine->reset();
310 
311         return Void();
312     }
313 
314    protected:
createResources()315     virtual std::unique_ptr<ComposerResources> createResources() {
316         return ComposerResources::create();
317     }
318 
createCommandEngine()319     virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() {
320         return std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
321     }
322 
destroyResources()323     void destroyResources() {
324         // We want to call hwc2_close here (and move hwc2_open to the
325         // constructor), with the assumption that hwc2_close would
326         //
327         //  - clean up all resources owned by the client
328         //  - make sure all displays are blank (since there is no layer)
329         //
330         // But since SF used to crash at this point, different hwcomposer2
331         // implementations behave differently on hwc2_close.  Our only portable
332         // choice really is to abort().  But that is not an option anymore
333         // because we might also have VTS or VR as clients that can come and go.
334         //
335         // Below we manually clean all resources (layers and virtual
336         // displays), and perform a presentDisplay afterwards.
337         mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
338             ALOGW("destroying client resources for display %" PRIu64, display);
339 
340             for (auto layer : layers) {
341                 mHal->destroyLayer(display, layer);
342             }
343 
344             if (isVirtual) {
345                 mHal->destroyVirtualDisplay(display);
346             } else {
347                 ALOGW("performing a final presentDisplay");
348 
349                 std::vector<Layer> changedLayers;
350                 std::vector<IComposerClient::Composition> compositionTypes;
351                 uint32_t displayRequestMask = 0;
352                 std::vector<Layer> requestedLayers;
353                 std::vector<uint32_t> requestMasks;
354                 mHal->validateDisplay(display, &changedLayers, &compositionTypes,
355                                       &displayRequestMask, &requestedLayers, &requestMasks);
356 
357                 mHal->acceptDisplayChanges(display);
358 
359                 int32_t presentFence = -1;
360                 std::vector<Layer> releasedLayers;
361                 std::vector<int32_t> releaseFences;
362                 mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
363                 if (presentFence >= 0) {
364                     close(presentFence);
365                 }
366                 for (auto fence : releaseFences) {
367                     if (fence >= 0) {
368                         close(fence);
369                     }
370                 }
371             }
372         });
373 
374         mResources.reset();
375     }
376 
377     Hal* const mHal;
378 
379     std::unique_ptr<ComposerResources> mResources;
380 
381     std::mutex mCommandEngineMutex;
382     std::unique_ptr<ComposerCommandEngine> mCommandEngine;
383 
384     std::function<void()> mOnClientDestroyed;
385     std::unique_ptr<HalEventCallback> mHalEventCallback;
386 };
387 
388 }  // namespace detail
389 
390 using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
391 
392 }  // namespace hal
393 }  // namespace V2_1
394 }  // namespace composer
395 }  // namespace graphics
396 }  // namespace hardware
397 }  // namespace android
398