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