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