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