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