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 "ComposerResources.h included without LOG_TAG" 21 #endif 22 23 #include <memory> 24 #include <mutex> 25 #include <unordered_map> 26 #include <vector> 27 28 #include <android/hardware/graphics/mapper/2.0/IMapper.h> 29 #include <android/hardware/graphics/mapper/3.0/IMapper.h> 30 #include <log/log.h> 31 32 namespace android { 33 namespace hardware { 34 namespace graphics { 35 namespace composer { 36 namespace V2_1 { 37 namespace hal { 38 39 // wrapper for IMapper to import buffers and sideband streams 40 class ComposerHandleImporter { 41 public: init()42 bool init() { 43 mMapper3 = mapper::V3_0::IMapper::getService(); 44 if (mMapper3) { 45 return true; 46 } 47 ALOGD_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0"); 48 49 mMapper2 = mapper::V2_0::IMapper::getService(); 50 ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service"); 51 52 return mMapper2 != nullptr; 53 } 54 importBuffer(const native_handle_t * rawHandle,const native_handle_t ** outBufferHandle)55 Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) { 56 if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) { 57 *outBufferHandle = nullptr; 58 return Error::NONE; 59 } 60 61 const native_handle_t* bufferHandle; 62 if (mMapper2) { 63 mapper::V2_0::Error error; 64 mMapper2->importBuffer( 65 rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { 66 error = tmpError; 67 bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); 68 }); 69 if (error != mapper::V2_0::Error::NONE) { 70 return Error::NO_RESOURCES; 71 } 72 } 73 if (mMapper3) { 74 mapper::V3_0::Error error; 75 mMapper3->importBuffer( 76 rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { 77 error = tmpError; 78 bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); 79 }); 80 if (error != mapper::V3_0::Error::NONE) { 81 return Error::NO_RESOURCES; 82 } 83 } 84 85 *outBufferHandle = bufferHandle; 86 return Error::NONE; 87 } 88 freeBuffer(const native_handle_t * bufferHandle)89 void freeBuffer(const native_handle_t* bufferHandle) { 90 if (bufferHandle) { 91 if (mMapper2) { 92 mMapper2->freeBuffer( 93 static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); 94 } else if (mMapper3) { 95 mMapper3->freeBuffer( 96 static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); 97 } 98 } 99 } 100 importStream(const native_handle_t * rawHandle,const native_handle_t ** outStreamHandle)101 Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) { 102 const native_handle_t* streamHandle = nullptr; 103 if (rawHandle) { 104 streamHandle = native_handle_clone(rawHandle); 105 if (!streamHandle) { 106 return Error::NO_RESOURCES; 107 } 108 } 109 110 *outStreamHandle = streamHandle; 111 return Error::NONE; 112 } 113 freeStream(const native_handle_t * streamHandle)114 void freeStream(const native_handle_t* streamHandle) { 115 if (streamHandle) { 116 native_handle_close(streamHandle); 117 native_handle_delete(const_cast<native_handle_t*>(streamHandle)); 118 } 119 } 120 121 private: 122 sp<mapper::V2_0::IMapper> mMapper2; 123 sp<mapper::V3_0::IMapper> mMapper3; 124 }; 125 126 class ComposerHandleCache { 127 public: 128 enum class HandleType { 129 INVALID, 130 BUFFER, 131 STREAM, 132 }; 133 ComposerHandleCache(ComposerHandleImporter & importer,HandleType type,uint32_t cacheSize)134 ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize) 135 : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {} 136 137 // must be initialized later with initCache ComposerHandleCache(ComposerHandleImporter & importer)138 ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {} 139 ~ComposerHandleCache()140 ~ComposerHandleCache() { 141 switch (mHandleType) { 142 case HandleType::BUFFER: 143 for (auto handle : mHandles) { 144 mImporter.freeBuffer(handle); 145 } 146 break; 147 case HandleType::STREAM: 148 for (auto handle : mHandles) { 149 mImporter.freeStream(handle); 150 } 151 break; 152 default: 153 break; 154 } 155 } 156 157 ComposerHandleCache(const ComposerHandleCache&) = delete; 158 ComposerHandleCache& operator=(const ComposerHandleCache&) = delete; 159 initCache(HandleType type,uint32_t cacheSize)160 bool initCache(HandleType type, uint32_t cacheSize) { 161 // already initialized 162 if (mHandleType != HandleType::INVALID) { 163 return false; 164 } 165 166 mHandleType = type; 167 mHandles.resize(cacheSize, nullptr); 168 169 return true; 170 } 171 lookupCache(uint32_t slot,const native_handle_t ** outHandle)172 Error lookupCache(uint32_t slot, const native_handle_t** outHandle) { 173 if (slot >= 0 && slot < mHandles.size()) { 174 *outHandle = mHandles[slot]; 175 return Error::NONE; 176 } else { 177 return Error::BAD_PARAMETER; 178 } 179 } 180 updateCache(uint32_t slot,const native_handle_t * handle,const native_handle ** outReplacedHandle)181 Error updateCache(uint32_t slot, const native_handle_t* handle, 182 const native_handle** outReplacedHandle) { 183 if (slot >= 0 && slot < mHandles.size()) { 184 auto& cachedHandle = mHandles[slot]; 185 *outReplacedHandle = cachedHandle; 186 cachedHandle = handle; 187 return Error::NONE; 188 } else { 189 return Error::BAD_PARAMETER; 190 } 191 } 192 193 // when fromCache is true, look up in the cache; otherwise, update the cache getHandle(uint32_t slot,bool fromCache,const native_handle_t * inHandle,const native_handle_t ** outHandle,const native_handle ** outReplacedHandle)194 Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 195 const native_handle_t** outHandle, const native_handle** outReplacedHandle) { 196 if (fromCache) { 197 *outReplacedHandle = nullptr; 198 return lookupCache(slot, outHandle); 199 } else { 200 *outHandle = inHandle; 201 return updateCache(slot, inHandle, outReplacedHandle); 202 } 203 } 204 205 private: 206 ComposerHandleImporter& mImporter; 207 HandleType mHandleType = HandleType::INVALID; 208 std::vector<const native_handle_t*> mHandles; 209 }; 210 211 // layer resource 212 class ComposerLayerResource { 213 public: ComposerLayerResource(ComposerHandleImporter & importer,uint32_t bufferCacheSize)214 ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize) 215 : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize), 216 mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {} 217 218 virtual ~ComposerLayerResource() = default; 219 getBuffer(uint32_t slot,bool fromCache,const native_handle_t * inHandle,const native_handle_t ** outHandle,const native_handle ** outReplacedHandle)220 Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 221 const native_handle_t** outHandle, const native_handle** outReplacedHandle) { 222 return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); 223 } 224 getSidebandStream(uint32_t slot,bool fromCache,const native_handle_t * inHandle,const native_handle_t ** outHandle,const native_handle ** outReplacedHandle)225 Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 226 const native_handle_t** outHandle, 227 const native_handle** outReplacedHandle) { 228 return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle, 229 outReplacedHandle); 230 } 231 232 protected: 233 ComposerHandleCache mBufferCache; 234 ComposerHandleCache mSidebandStreamCache; 235 }; 236 237 // display resource 238 class ComposerDisplayResource { 239 public: 240 enum class DisplayType { 241 PHYSICAL, 242 VIRTUAL, 243 }; 244 245 virtual ~ComposerDisplayResource() = default; 246 ComposerDisplayResource(DisplayType type,ComposerHandleImporter & importer,uint32_t outputBufferCacheSize)247 ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, 248 uint32_t outputBufferCacheSize) 249 : mType(type), 250 mClientTargetCache(importer), 251 mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 252 outputBufferCacheSize), 253 mMustValidate(true) {} 254 initClientTargetCache(uint32_t cacheSize)255 bool initClientTargetCache(uint32_t cacheSize) { 256 return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); 257 } 258 isVirtual()259 bool isVirtual() const { return mType == DisplayType::VIRTUAL; } 260 getClientTarget(uint32_t slot,bool fromCache,const native_handle_t * inHandle,const native_handle_t ** outHandle,const native_handle ** outReplacedHandle)261 Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 262 const native_handle_t** outHandle, 263 const native_handle** outReplacedHandle) { 264 return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle, 265 outReplacedHandle); 266 } 267 getOutputBuffer(uint32_t slot,bool fromCache,const native_handle_t * inHandle,const native_handle_t ** outHandle,const native_handle ** outReplacedHandle)268 Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 269 const native_handle_t** outHandle, 270 const native_handle** outReplacedHandle) { 271 return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle, 272 outReplacedHandle); 273 } 274 addLayer(Layer layer,std::unique_ptr<ComposerLayerResource> layerResource)275 bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) { 276 auto result = mLayerResources.emplace(layer, std::move(layerResource)); 277 return result.second; 278 } 279 removeLayer(Layer layer)280 bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; } 281 findLayerResource(Layer layer)282 ComposerLayerResource* findLayerResource(Layer layer) { 283 auto layerIter = mLayerResources.find(layer); 284 if (layerIter == mLayerResources.end()) { 285 return nullptr; 286 } 287 288 return layerIter->second.get(); 289 } 290 getLayers()291 std::vector<Layer> getLayers() const { 292 std::vector<Layer> layers; 293 layers.reserve(mLayerResources.size()); 294 for (const auto& layerKey : mLayerResources) { 295 layers.push_back(layerKey.first); 296 } 297 return layers; 298 } 299 setMustValidateState(bool mustValidate)300 void setMustValidateState(bool mustValidate) { mMustValidate = mustValidate; } 301 mustValidate()302 bool mustValidate() const { return mMustValidate; } 303 304 protected: 305 const DisplayType mType; 306 ComposerHandleCache mClientTargetCache; 307 ComposerHandleCache mOutputBufferCache; 308 bool mMustValidate; 309 310 std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources; 311 }; 312 313 class ComposerResources { 314 private: 315 template <bool isBuffer> 316 class ReplacedHandle; 317 318 public: create()319 static std::unique_ptr<ComposerResources> create() { 320 auto resources = std::make_unique<ComposerResources>(); 321 return resources->init() ? std::move(resources) : nullptr; 322 } 323 324 ComposerResources() = default; 325 virtual ~ComposerResources() = default; 326 init()327 bool init() { return mImporter.init(); } 328 329 using RemoveDisplay = 330 std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>; clear(RemoveDisplay removeDisplay)331 void clear(RemoveDisplay removeDisplay) { 332 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 333 for (const auto& displayKey : mDisplayResources) { 334 Display display = displayKey.first; 335 const ComposerDisplayResource& displayResource = *displayKey.second; 336 removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers()); 337 } 338 mDisplayResources.clear(); 339 } 340 addPhysicalDisplay(Display display)341 Error addPhysicalDisplay(Display display) { 342 auto displayResource = 343 createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0); 344 345 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 346 auto result = mDisplayResources.emplace(display, std::move(displayResource)); 347 return result.second ? Error::NONE : Error::BAD_DISPLAY; 348 } 349 addVirtualDisplay(Display display,uint32_t outputBufferCacheSize)350 Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) { 351 auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL, 352 outputBufferCacheSize); 353 354 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 355 auto result = mDisplayResources.emplace(display, std::move(displayResource)); 356 return result.second ? Error::NONE : Error::BAD_DISPLAY; 357 } 358 removeDisplay(Display display)359 Error removeDisplay(Display display) { 360 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 361 return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY; 362 } 363 setDisplayClientTargetCacheSize(Display display,uint32_t clientTargetCacheSize)364 Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) { 365 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 366 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 367 if (!displayResource) { 368 return Error::BAD_DISPLAY; 369 } 370 371 return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE 372 : Error::BAD_PARAMETER; 373 } 374 addLayer(Display display,Layer layer,uint32_t bufferCacheSize)375 Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) { 376 auto layerResource = createLayerResource(bufferCacheSize); 377 378 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 379 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 380 if (!displayResource) { 381 return Error::BAD_DISPLAY; 382 } 383 384 return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE 385 : Error::BAD_LAYER; 386 } 387 removeLayer(Display display,Layer layer)388 Error removeLayer(Display display, Layer layer) { 389 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 390 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 391 if (!displayResource) { 392 return Error::BAD_DISPLAY; 393 } 394 395 return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER; 396 } 397 398 using ReplacedBufferHandle = ReplacedHandle<true>; 399 using ReplacedStreamHandle = ReplacedHandle<false>; 400 getDisplayClientTarget(Display display,uint32_t slot,bool fromCache,const native_handle_t * rawHandle,const native_handle_t ** outBufferHandle,ReplacedBufferHandle * outReplacedBuffer)401 Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache, 402 const native_handle_t* rawHandle, 403 const native_handle_t** outBufferHandle, 404 ReplacedBufferHandle* outReplacedBuffer) { 405 return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle, 406 outBufferHandle, outReplacedBuffer); 407 } 408 getDisplayOutputBuffer(Display display,uint32_t slot,bool fromCache,const native_handle_t * rawHandle,const native_handle_t ** outBufferHandle,ReplacedBufferHandle * outReplacedBuffer)409 Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache, 410 const native_handle_t* rawHandle, 411 const native_handle_t** outBufferHandle, 412 ReplacedBufferHandle* outReplacedBuffer) { 413 return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle, 414 outBufferHandle, outReplacedBuffer); 415 } 416 getLayerBuffer(Display display,Layer layer,uint32_t slot,bool fromCache,const native_handle_t * rawHandle,const native_handle_t ** outBufferHandle,ReplacedBufferHandle * outReplacedBuffer)417 Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache, 418 const native_handle_t* rawHandle, const native_handle_t** outBufferHandle, 419 ReplacedBufferHandle* outReplacedBuffer) { 420 return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle, 421 outBufferHandle, outReplacedBuffer); 422 } 423 getLayerSidebandStream(Display display,Layer layer,const native_handle_t * rawHandle,const native_handle_t ** outStreamHandle,ReplacedStreamHandle * outReplacedStream)424 Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle, 425 const native_handle_t** outStreamHandle, 426 ReplacedStreamHandle* outReplacedStream) { 427 return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle, 428 outStreamHandle, outReplacedStream); 429 } 430 setDisplayMustValidateState(Display display,bool mustValidate)431 void setDisplayMustValidateState(Display display, bool mustValidate) { 432 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 433 auto* displayResource = findDisplayResourceLocked(display); 434 if (displayResource) { 435 displayResource->setMustValidateState(mustValidate); 436 } 437 } 438 mustValidateDisplay(Display display)439 bool mustValidateDisplay(Display display) { 440 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 441 auto* displayResource = findDisplayResourceLocked(display); 442 if (displayResource) { 443 return displayResource->mustValidate(); 444 } 445 return false; 446 } 447 448 protected: createDisplayResource(ComposerDisplayResource::DisplayType type,uint32_t outputBufferCacheSize)449 virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource( 450 ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) { 451 return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); 452 } 453 createLayerResource(uint32_t bufferCacheSize)454 virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) { 455 return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize); 456 } 457 findDisplayResourceLocked(Display display)458 ComposerDisplayResource* findDisplayResourceLocked(Display display) { 459 auto iter = mDisplayResources.find(display); 460 if (iter == mDisplayResources.end()) { 461 return nullptr; 462 } 463 return iter->second.get(); 464 } 465 466 ComposerHandleImporter mImporter; 467 468 std::mutex mDisplayResourcesMutex; 469 std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources; 470 471 private: 472 enum class Cache { 473 CLIENT_TARGET, 474 OUTPUT_BUFFER, 475 LAYER_BUFFER, 476 LAYER_SIDEBAND_STREAM, 477 }; 478 479 // When a buffer in the cache is replaced by a new one, we must keep it 480 // alive until it has been replaced in ComposerHal. 481 template <bool isBuffer> 482 class ReplacedHandle { 483 public: 484 ReplacedHandle() = default; 485 ReplacedHandle(const ReplacedHandle&) = delete; 486 ReplacedHandle& operator=(const ReplacedHandle&) = delete; 487 ~ReplacedHandle()488 ~ReplacedHandle() { reset(); } 489 490 void reset(ComposerHandleImporter* importer = nullptr, 491 const native_handle_t* handle = nullptr) { 492 if (mHandle) { 493 if (isBuffer) { 494 mImporter->freeBuffer(mHandle); 495 } else { 496 mImporter->freeStream(mHandle); 497 } 498 } 499 500 mImporter = importer; 501 mHandle = handle; 502 } 503 504 private: 505 ComposerHandleImporter* mImporter = nullptr; 506 const native_handle_t* mHandle = nullptr; 507 }; 508 509 template <Cache cache, bool isBuffer> getHandle(Display display,Layer layer,uint32_t slot,bool fromCache,const native_handle_t * rawHandle,const native_handle_t ** outHandle,ReplacedHandle<isBuffer> * outReplacedHandle)510 Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache, 511 const native_handle_t* rawHandle, const native_handle_t** outHandle, 512 ReplacedHandle<isBuffer>* outReplacedHandle) { 513 Error error; 514 515 // import the raw handle (or ignore raw handle when fromCache is true) 516 const native_handle_t* importedHandle = nullptr; 517 if (!fromCache) { 518 error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle) 519 : mImporter.importStream(rawHandle, &importedHandle); 520 if (error != Error::NONE) { 521 return error; 522 } 523 } 524 525 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 526 527 // find display/layer resource 528 const bool needLayerResource = 529 (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM); 530 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 531 ComposerLayerResource* layerResource = (displayResource && needLayerResource) 532 ? displayResource->findLayerResource(layer) 533 : nullptr; 534 535 // lookup or update cache 536 const native_handle_t* replacedHandle = nullptr; 537 if (displayResource && (!needLayerResource || layerResource)) { 538 switch (cache) { 539 case Cache::CLIENT_TARGET: 540 error = displayResource->getClientTarget(slot, fromCache, importedHandle, 541 outHandle, &replacedHandle); 542 break; 543 case Cache::OUTPUT_BUFFER: 544 error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, 545 outHandle, &replacedHandle); 546 break; 547 case Cache::LAYER_BUFFER: 548 error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle, 549 &replacedHandle); 550 break; 551 case Cache::LAYER_SIDEBAND_STREAM: 552 error = layerResource->getSidebandStream(slot, fromCache, importedHandle, 553 outHandle, &replacedHandle); 554 break; 555 default: 556 error = Error::BAD_PARAMETER; 557 break; 558 } 559 560 if (error != Error::NONE) { 561 ALOGW("invalid cache %d slot %d", int(cache), int(slot)); 562 } 563 } else if (!displayResource) { 564 error = Error::BAD_DISPLAY; 565 } else { 566 error = Error::BAD_LAYER; 567 } 568 569 // clean up on errors 570 if (error != Error::NONE) { 571 if (!fromCache) { 572 if (isBuffer) { 573 mImporter.freeBuffer(importedHandle); 574 } else { 575 mImporter.freeStream(importedHandle); 576 } 577 } 578 return error; 579 } 580 581 outReplacedHandle->reset(&mImporter, replacedHandle); 582 583 return Error::NONE; 584 } 585 }; 586 587 } // namespace hal 588 } // namespace V2_1 589 } // namespace composer 590 } // namespace graphics 591 } // namespace hardware 592 } // namespace android 593