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 // we do not have HWC2_CAPABILITY_SKIP_VALIDATE defined in 71 // IComposer::Capability. However, this is defined in hwcomposer2.h, 72 // so if the device returns it, add it manually to be returned to the 73 // client 74 if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) { 75 caps.push_back(static_cast<IComposer::Capability>(HWC2_CAPABILITY_SKIP_VALIDATE)); 76 } 77 78 hidl_vec<IComposer::Capability> caps_reply; 79 caps_reply.setToExternal(caps.data(), caps.size()); 80 hidl_cb(caps_reply); 81 return Void(); 82 } 83 dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb)84 Return<void> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override { 85 hidl_cb(mHal->dumpDebugInfo()); 86 return Void(); 87 } 88 createClient(IComposer::createClient_cb hidl_cb)89 Return<void> createClient(IComposer::createClient_cb hidl_cb) override { 90 std::unique_lock<std::mutex> lock(mClientMutex); 91 if (!waitForClientDestroyedLocked(lock)) { 92 hidl_cb(Error::NO_RESOURCES, nullptr); 93 return Void(); 94 } 95 96 sp<IComposerClient> client = createClient(); 97 if (!client) { 98 hidl_cb(Error::NO_RESOURCES, nullptr); 99 return Void(); 100 } 101 102 mClient = client; 103 hidl_cb(Error::NONE, client); 104 return Void(); 105 } 106 107 protected: waitForClientDestroyedLocked(std::unique_lock<std::mutex> & lock)108 bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) { 109 if (mClient != nullptr) { 110 using namespace std::chrono_literals; 111 112 // In surface flinger we delete a composer client on one thread and 113 // then create a new client on another thread. Although surface 114 // flinger ensures the calls are made in that sequence (destroy and 115 // then create), sometimes the calls land in the composer service 116 // inverted (create and then destroy). Wait for a brief period to 117 // see if the existing client is destroyed. 118 ALOGD("waiting for previous client to be destroyed"); 119 mClientDestroyedCondition.wait_for(lock, 1s, 120 [this]() -> bool { return mClient == nullptr; }); 121 if (mClient != nullptr) { 122 ALOGD("previous client was not destroyed"); 123 } 124 } 125 126 return mClient == nullptr; 127 } 128 onClientDestroyed()129 void onClientDestroyed() { 130 std::lock_guard<std::mutex> lock(mClientMutex); 131 mClient.clear(); 132 mClientDestroyedCondition.notify_all(); 133 } 134 createClient()135 virtual IComposerClient* createClient() { 136 auto client = ComposerClient::create(mHal.get()); 137 if (!client) { 138 return nullptr; 139 } 140 141 auto clientDestroyed = [this]() { onClientDestroyed(); }; 142 client->setOnClientDestroyed(clientDestroyed); 143 144 return client.release(); 145 } 146 147 const std::unique_ptr<Hal> mHal; 148 149 std::mutex mClientMutex; 150 wp<IComposerClient> mClient; 151 std::condition_variable mClientDestroyedCondition; 152 }; 153 154 } // namespace detail 155 156 using Composer = detail::ComposerImpl<IComposer, ComposerHal>; 157 158 } // namespace hal 159 } // namespace V2_1 160 } // namespace composer 161 } // namespace graphics 162 } // namespace hardware 163 } // namespace android 164