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