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(const sp<IComposerCallback> callback,ComposerResources * resources)90 HalEventCallback(const sp<IComposerCallback> callback, ComposerResources* resources) 91 : mCallback(callback), mResources(resources) {} 92 onHotplug(Display display,IComposerCallback::Connection connected)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 onRefresh(Display display)104 void onRefresh(Display display) { 105 mResources->setDisplayMustValidateState(display, true); 106 auto ret = mCallback->onRefresh(display); 107 ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str()); 108 } 109 onVsync(Display display,int64_t timestamp)110 void onVsync(Display display, int64_t timestamp) { 111 auto ret = mCallback->onVsync(display, timestamp); 112 ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str()); 113 } 114 115 protected: 116 const sp<IComposerCallback> mCallback; 117 ComposerResources* const mResources; 118 }; 119 registerCallback(const sp<IComposerCallback> & callback)120 Return<void> registerCallback(const sp<IComposerCallback>& callback) override { 121 // no locking as we require this function to be called only once 122 mHalEventCallback = std::make_unique<HalEventCallback>(callback, mResources.get()); 123 mHal->registerEventCallback(mHalEventCallback.get()); 124 return Void(); 125 } 126 getMaxVirtualDisplayCount()127 Return<uint32_t> getMaxVirtualDisplayCount() override { 128 return mHal->getMaxVirtualDisplayCount(); 129 } 130 createVirtualDisplay(uint32_t width,uint32_t height,PixelFormat formatHint,uint32_t outputBufferSlotCount,IComposerClient::createVirtualDisplay_cb hidl_cb)131 Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint, 132 uint32_t outputBufferSlotCount, 133 IComposerClient::createVirtualDisplay_cb hidl_cb) override { 134 Display display = 0; 135 Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display); 136 if (err == Error::NONE) { 137 mResources->addVirtualDisplay(display, outputBufferSlotCount); 138 } 139 140 hidl_cb(err, display, formatHint); 141 return Void(); 142 } 143 destroyVirtualDisplay(Display display)144 Return<Error> destroyVirtualDisplay(Display display) override { 145 Error err = mHal->destroyVirtualDisplay(display); 146 if (err == Error::NONE) { 147 mResources->removeDisplay(display); 148 } 149 150 return err; 151 } 152 createLayer(Display display,uint32_t bufferSlotCount,IComposerClient::createLayer_cb hidl_cb)153 Return<void> createLayer(Display display, uint32_t bufferSlotCount, 154 IComposerClient::createLayer_cb hidl_cb) override { 155 Layer layer = 0; 156 Error err = mHal->createLayer(display, &layer); 157 if (err == Error::NONE) { 158 err = mResources->addLayer(display, layer, bufferSlotCount); 159 if (err != Error::NONE) { 160 // The display entry may have already been removed by onHotplug. 161 // Note: We do not destroy the layer on this error as the hotplug 162 // disconnect invalidates the display id. The implementation should 163 // ensure all layers for the display are destroyed. 164 layer = 0; 165 } 166 } 167 168 hidl_cb(err, layer); 169 return Void(); 170 } 171 destroyLayer(Display display,Layer layer)172 Return<Error> destroyLayer(Display display, Layer layer) override { 173 Error err = mHal->destroyLayer(display, layer); 174 if (err == Error::NONE) { 175 mResources->removeLayer(display, layer); 176 } 177 178 return err; 179 } 180 getActiveConfig(Display display,IComposerClient::getActiveConfig_cb hidl_cb)181 Return<void> getActiveConfig(Display display, 182 IComposerClient::getActiveConfig_cb hidl_cb) override { 183 Config config = 0; 184 Error err = mHal->getActiveConfig(display, &config); 185 hidl_cb(err, config); 186 return Void(); 187 } 188 getClientTargetSupport(Display display,uint32_t width,uint32_t height,PixelFormat format,Dataspace dataspace)189 Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height, 190 PixelFormat format, Dataspace dataspace) override { 191 Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace); 192 return err; 193 } 194 getColorModes(Display display,IComposerClient::getColorModes_cb hidl_cb)195 Return<void> getColorModes(Display display, 196 IComposerClient::getColorModes_cb hidl_cb) override { 197 hidl_vec<ColorMode> modes; 198 Error err = mHal->getColorModes(display, &modes); 199 hidl_cb(err, modes); 200 return Void(); 201 } 202 getDisplayAttribute(Display display,Config config,IComposerClient::Attribute attribute,IComposerClient::getDisplayAttribute_cb hidl_cb)203 Return<void> getDisplayAttribute(Display display, Config config, 204 IComposerClient::Attribute attribute, 205 IComposerClient::getDisplayAttribute_cb hidl_cb) override { 206 int32_t value = 0; 207 Error err = mHal->getDisplayAttribute(display, config, attribute, &value); 208 hidl_cb(err, value); 209 return Void(); 210 } 211 getDisplayConfigs(Display display,IComposerClient::getDisplayConfigs_cb hidl_cb)212 Return<void> getDisplayConfigs(Display display, 213 IComposerClient::getDisplayConfigs_cb hidl_cb) override { 214 hidl_vec<Config> configs; 215 Error err = mHal->getDisplayConfigs(display, &configs); 216 hidl_cb(err, configs); 217 return Void(); 218 } 219 getDisplayName(Display display,IComposerClient::getDisplayName_cb hidl_cb)220 Return<void> getDisplayName(Display display, 221 IComposerClient::getDisplayName_cb hidl_cb) override { 222 hidl_string name; 223 Error err = mHal->getDisplayName(display, &name); 224 hidl_cb(err, name); 225 return Void(); 226 } 227 getDisplayType(Display display,IComposerClient::getDisplayType_cb hidl_cb)228 Return<void> getDisplayType(Display display, 229 IComposerClient::getDisplayType_cb hidl_cb) override { 230 IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID; 231 Error err = mHal->getDisplayType(display, &type); 232 hidl_cb(err, type); 233 return Void(); 234 } 235 getDozeSupport(Display display,IComposerClient::getDozeSupport_cb hidl_cb)236 Return<void> getDozeSupport(Display display, 237 IComposerClient::getDozeSupport_cb hidl_cb) override { 238 bool support = false; 239 Error err = mHal->getDozeSupport(display, &support); 240 hidl_cb(err, support); 241 return Void(); 242 } 243 getHdrCapabilities(Display display,IComposerClient::getHdrCapabilities_cb hidl_cb)244 Return<void> getHdrCapabilities(Display display, 245 IComposerClient::getHdrCapabilities_cb hidl_cb) override { 246 hidl_vec<Hdr> types; 247 float max_lumi = 0.0f; 248 float max_avg_lumi = 0.0f; 249 float min_lumi = 0.0f; 250 Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi); 251 hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi); 252 return Void(); 253 } 254 setActiveConfig(Display display,Config config)255 Return<Error> setActiveConfig(Display display, Config config) override { 256 Error err = mHal->setActiveConfig(display, config); 257 return err; 258 } 259 setColorMode(Display display,ColorMode mode)260 Return<Error> setColorMode(Display display, ColorMode mode) override { 261 Error err = mHal->setColorMode(display, mode); 262 return err; 263 } 264 setPowerMode(Display display,IComposerClient::PowerMode mode)265 Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override { 266 Error err = mHal->setPowerMode(display, mode); 267 return err; 268 } 269 setVsyncEnabled(Display display,IComposerClient::Vsync enabled)270 Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override { 271 Error err = mHal->setVsyncEnabled(display, enabled); 272 return err; 273 } 274 setClientTargetSlotCount(Display display,uint32_t clientTargetSlotCount)275 Return<Error> setClientTargetSlotCount(Display display, 276 uint32_t clientTargetSlotCount) override { 277 return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount); 278 } 279 setInputCommandQueue(const MQDescriptorSync<uint32_t> & descriptor)280 Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override { 281 std::lock_guard<std::mutex> lock(mCommandEngineMutex); 282 return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES; 283 } 284 getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb)285 Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override { 286 // no locking as we require this function to be called inside 287 // executeCommands_cb 288 auto outDescriptor = mCommandEngine->getOutputMQDescriptor(); 289 if (outDescriptor) { 290 hidl_cb(Error::NONE, *outDescriptor); 291 } else { 292 hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor()); 293 } 294 295 return Void(); 296 } 297 executeCommands(uint32_t inLength,const hidl_vec<hidl_handle> & inHandles,IComposerClient::executeCommands_cb hidl_cb)298 Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, 299 IComposerClient::executeCommands_cb hidl_cb) override { 300 std::lock_guard<std::mutex> lock(mCommandEngineMutex); 301 bool outChanged = false; 302 uint32_t outLength = 0; 303 hidl_vec<hidl_handle> outHandles; 304 Error error = 305 mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles); 306 307 hidl_cb(error, outChanged, outLength, outHandles); 308 309 mCommandEngine->reset(); 310 311 return Void(); 312 } 313 314 protected: createResources()315 virtual std::unique_ptr<ComposerResources> createResources() { 316 return ComposerResources::create(); 317 } 318 createCommandEngine()319 virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() { 320 return std::make_unique<ComposerCommandEngine>(mHal, mResources.get()); 321 } 322 destroyResources()323 void destroyResources() { 324 // We want to call hwc2_close here (and move hwc2_open to the 325 // constructor), with the assumption that hwc2_close would 326 // 327 // - clean up all resources owned by the client 328 // - make sure all displays are blank (since there is no layer) 329 // 330 // But since SF used to crash at this point, different hwcomposer2 331 // implementations behave differently on hwc2_close. Our only portable 332 // choice really is to abort(). But that is not an option anymore 333 // because we might also have VTS or VR as clients that can come and go. 334 // 335 // Below we manually clean all resources (layers and virtual 336 // displays), and perform a presentDisplay afterwards. 337 mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) { 338 ALOGW("destroying client resources for display %" PRIu64, display); 339 340 for (auto layer : layers) { 341 mHal->destroyLayer(display, layer); 342 } 343 344 if (isVirtual) { 345 mHal->destroyVirtualDisplay(display); 346 } else { 347 ALOGW("performing a final presentDisplay"); 348 349 std::vector<Layer> changedLayers; 350 std::vector<IComposerClient::Composition> compositionTypes; 351 uint32_t displayRequestMask = 0; 352 std::vector<Layer> requestedLayers; 353 std::vector<uint32_t> requestMasks; 354 mHal->validateDisplay(display, &changedLayers, &compositionTypes, 355 &displayRequestMask, &requestedLayers, &requestMasks); 356 357 mHal->acceptDisplayChanges(display); 358 359 int32_t presentFence = -1; 360 std::vector<Layer> releasedLayers; 361 std::vector<int32_t> releaseFences; 362 mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences); 363 if (presentFence >= 0) { 364 close(presentFence); 365 } 366 for (auto fence : releaseFences) { 367 if (fence >= 0) { 368 close(fence); 369 } 370 } 371 } 372 }); 373 374 mResources.reset(); 375 } 376 377 Hal* const mHal; 378 379 std::unique_ptr<ComposerResources> mResources; 380 381 std::mutex mCommandEngineMutex; 382 std::unique_ptr<ComposerCommandEngine> mCommandEngine; 383 384 std::function<void()> mOnClientDestroyed; 385 std::unique_ptr<HalEventCallback> mHalEventCallback; 386 }; 387 388 } // namespace detail 389 390 using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>; 391 392 } // namespace hal 393 } // namespace V2_1 394 } // namespace composer 395 } // namespace graphics 396 } // namespace hardware 397 } // namespace android 398