1 /* 2 * Copyright (C) 2011 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 #define LOG_TAG "Sprites" 18 //#define LOG_NDEBUG 0 19 20 #include "SpriteController.h" 21 22 #include <android-base/logging.h> 23 #include <gui/Surface.h> 24 #include <utils/String8.h> 25 26 namespace android { 27 28 // --- SpriteController --- 29 SpriteController(const sp<Looper> & looper,int32_t overlayLayer,ParentSurfaceProvider parentSurfaceProvider)30 SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer, 31 ParentSurfaceProvider parentSurfaceProvider) 32 : mLooper(looper), 33 mOverlayLayer(overlayLayer), 34 mHandler(sp<Handler>::make()), 35 mParentSurfaceProvider(std::move(parentSurfaceProvider)) { 36 mLocked.transactionNestingCount = 0; 37 mLocked.deferredSpriteUpdate = false; 38 } 39 setHandlerController(const std::shared_ptr<android::SpriteController> & controller)40 void SpriteController::setHandlerController( 41 const std::shared_ptr<android::SpriteController>& controller) { 42 // Initialize the weak message handler outside the constructor, because we cannot get a shared 43 // pointer to self in the constructor. 44 mHandler->spriteController = controller; 45 } 46 ~SpriteController()47 SpriteController::~SpriteController() { 48 mLooper->removeMessages(mHandler); 49 50 if (mSurfaceComposerClient != NULL) { 51 mSurfaceComposerClient->dispose(); 52 mSurfaceComposerClient.clear(); 53 } 54 } 55 createSprite()56 sp<Sprite> SpriteController::createSprite() { 57 return sp<SpriteImpl>::make(*this); 58 } 59 openTransaction()60 void SpriteController::openTransaction() { 61 AutoMutex _l(mLock); 62 63 mLocked.transactionNestingCount += 1; 64 } 65 closeTransaction()66 void SpriteController::closeTransaction() { 67 AutoMutex _l(mLock); 68 69 LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0, 70 "Sprite closeTransaction() called but there is no open sprite transaction"); 71 72 mLocked.transactionNestingCount -= 1; 73 if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) { 74 mLocked.deferredSpriteUpdate = false; 75 mLooper->sendMessage(mHandler, Message(Handler::MSG_UPDATE_SPRITES)); 76 } 77 } 78 invalidateSpriteLocked(const sp<SpriteImpl> & sprite)79 void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) { 80 bool wasEmpty = mLocked.invalidatedSprites.empty(); 81 mLocked.invalidatedSprites.push_back(sprite); 82 if (wasEmpty) { 83 if (mLocked.transactionNestingCount != 0) { 84 mLocked.deferredSpriteUpdate = true; 85 } else { 86 mLooper->sendMessage(mHandler, Message(Handler::MSG_UPDATE_SPRITES)); 87 } 88 } 89 } 90 disposeSurfaceLocked(const sp<SurfaceControl> & surfaceControl)91 void SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) { 92 bool wasEmpty = mLocked.disposedSurfaces.empty(); 93 mLocked.disposedSurfaces.push_back(surfaceControl); 94 if (wasEmpty) { 95 mLooper->sendMessage(mHandler, Message(Handler::MSG_DISPOSE_SURFACES)); 96 } 97 } 98 doUpdateSprites()99 void SpriteController::doUpdateSprites() { 100 // Collect information about sprite updates. 101 // Each sprite update record includes a reference to its associated sprite so we can 102 // be certain the sprites will not be deleted while this function runs. Sprites 103 // may invalidate themselves again during this time but we will handle those changes 104 // in the next iteration. 105 Vector<SpriteUpdate> updates; 106 size_t numSprites; 107 { // acquire lock 108 AutoMutex _l(mLock); 109 110 numSprites = mLocked.invalidatedSprites.size(); 111 for (size_t i = 0; i < numSprites; i++) { 112 const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites[i]; 113 114 updates.push(SpriteUpdate(sprite, sprite->getStateLocked())); 115 sprite->resetDirtyLocked(); 116 } 117 mLocked.invalidatedSprites.clear(); 118 } // release lock 119 120 // Create missing surfaces. 121 bool surfaceChanged = false; 122 for (size_t i = 0; i < numSprites; i++) { 123 SpriteUpdate& update = updates.editItemAt(i); 124 125 if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) { 126 update.state.surfaceWidth = update.state.icon.width(); 127 update.state.surfaceHeight = update.state.icon.height(); 128 update.state.surfaceDrawn = false; 129 update.state.surfaceVisible = false; 130 update.state.surfaceControl = 131 obtainSurface(update.state.surfaceWidth, update.state.surfaceHeight, 132 update.state.displayId, update.state.skipScreenshot); 133 if (update.state.surfaceControl != NULL) { 134 update.surfaceChanged = surfaceChanged = true; 135 } 136 } 137 } 138 139 // Resize and/or reparent sprites if needed. 140 SurfaceComposerClient::Transaction t; 141 bool needApplyTransaction = false; 142 for (size_t i = 0; i < numSprites; i++) { 143 SpriteUpdate& update = updates.editItemAt(i); 144 if (update.state.surfaceControl == nullptr) { 145 continue; 146 } 147 148 if (update.state.wantSurfaceVisible()) { 149 int32_t desiredWidth = update.state.icon.width(); 150 int32_t desiredHeight = update.state.icon.height(); 151 // TODO(b/331260947): investigate using a larger surface width with smaller sprites. 152 if (update.state.surfaceWidth != desiredWidth || 153 update.state.surfaceHeight != desiredHeight) { 154 needApplyTransaction = true; 155 156 update.state.surfaceControl->updateDefaultBufferSize(desiredWidth, desiredHeight); 157 update.state.surfaceWidth = desiredWidth; 158 update.state.surfaceHeight = desiredHeight; 159 update.state.surfaceDrawn = false; 160 update.surfaceChanged = surfaceChanged = true; 161 162 if (update.state.surfaceVisible) { 163 t.hide(update.state.surfaceControl); 164 update.state.surfaceVisible = false; 165 } 166 } 167 } 168 169 // If surface has changed to a new display, we have to reparent it. 170 if (update.state.dirty & DIRTY_DISPLAY_ID) { 171 t.reparent(update.state.surfaceControl, mParentSurfaceProvider(update.state.displayId)); 172 needApplyTransaction = true; 173 } 174 } 175 if (needApplyTransaction) { 176 t.apply(); 177 } 178 179 // Redraw sprites if needed. 180 for (size_t i = 0; i < numSprites; i++) { 181 SpriteUpdate& update = updates.editItemAt(i); 182 183 if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) { 184 update.state.surfaceDrawn = false; 185 update.surfaceChanged = surfaceChanged = true; 186 } 187 188 if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn 189 && update.state.wantSurfaceVisible()) { 190 sp<Surface> surface = update.state.surfaceControl->getSurface(); 191 if (update.state.icon.draw(surface)) { 192 update.state.surfaceDrawn = true; 193 update.surfaceChanged = surfaceChanged = true; 194 } 195 } 196 } 197 198 needApplyTransaction = false; 199 for (size_t i = 0; i < numSprites; i++) { 200 SpriteUpdate& update = updates.editItemAt(i); 201 202 bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible() 203 && update.state.surfaceDrawn; 204 bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible; 205 bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible; 206 if (update.state.surfaceControl != NULL && 207 (becomingVisible || becomingHidden || 208 (wantSurfaceVisibleAndDrawn && 209 (update.state.dirty & 210 (DIRTY_ALPHA | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER | 211 DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID | DIRTY_ICON_STYLE | 212 DIRTY_DRAW_DROP_SHADOW | DIRTY_SKIP_SCREENSHOT))))) { 213 needApplyTransaction = true; 214 215 if (wantSurfaceVisibleAndDrawn 216 && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) { 217 t.setAlpha(update.state.surfaceControl, 218 update.state.alpha); 219 } 220 221 if (wantSurfaceVisibleAndDrawn 222 && (becomingVisible || (update.state.dirty & (DIRTY_POSITION 223 | DIRTY_HOTSPOT)))) { 224 t.setPosition( 225 update.state.surfaceControl, 226 update.state.positionX - update.state.icon.hotSpotX, 227 update.state.positionY - update.state.icon.hotSpotY); 228 } 229 230 if (wantSurfaceVisibleAndDrawn 231 && (becomingVisible 232 || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) { 233 t.setMatrix( 234 update.state.surfaceControl, 235 update.state.transformationMatrix.dsdx, 236 update.state.transformationMatrix.dtdx, 237 update.state.transformationMatrix.dsdy, 238 update.state.transformationMatrix.dtdy); 239 } 240 241 if (wantSurfaceVisibleAndDrawn && 242 (becomingVisible || 243 (update.state.dirty & 244 (DIRTY_HOTSPOT | DIRTY_ICON_STYLE | DIRTY_DRAW_DROP_SHADOW)))) { 245 Parcel p; 246 p.writeInt32(static_cast<int32_t>(update.state.icon.style)); 247 p.writeFloat(update.state.icon.hotSpotX); 248 p.writeFloat(update.state.icon.hotSpotY); 249 p.writeBool(update.state.icon.drawNativeDropShadow); 250 251 // Pass cursor metadata in the sprite surface so that when Android is running as a 252 // client OS (e.g. ARC++) the host OS can get the requested cursor metadata and 253 // update mouse cursor in the host OS. 254 t.setMetadata(update.state.surfaceControl, gui::METADATA_MOUSE_CURSOR, p); 255 } 256 257 int32_t surfaceLayer = mOverlayLayer + update.state.layer; 258 if (wantSurfaceVisibleAndDrawn 259 && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) { 260 t.setLayer(update.state.surfaceControl, surfaceLayer); 261 } 262 263 if (wantSurfaceVisibleAndDrawn && 264 (becomingVisible || (update.state.dirty & DIRTY_SKIP_SCREENSHOT))) { 265 int32_t flags = 266 update.state.skipScreenshot ? ISurfaceComposerClient::eSkipScreenshot : 0; 267 t.setFlags(update.state.surfaceControl, flags, 268 ISurfaceComposerClient::eSkipScreenshot); 269 } 270 271 if (becomingVisible) { 272 t.show(update.state.surfaceControl); 273 274 update.state.surfaceVisible = true; 275 update.surfaceChanged = surfaceChanged = true; 276 } else if (becomingHidden) { 277 t.hide(update.state.surfaceControl); 278 279 update.state.surfaceVisible = false; 280 update.surfaceChanged = surfaceChanged = true; 281 } 282 } 283 } 284 285 if (needApplyTransaction) { 286 status_t status = t.apply(); 287 if (status) { 288 ALOGE("Error applying Surface transaction"); 289 } 290 } 291 292 // If any surfaces were changed, write back the new surface properties to the sprites. 293 if (surfaceChanged) { // acquire lock 294 AutoMutex _l(mLock); 295 296 for (size_t i = 0; i < numSprites; i++) { 297 const SpriteUpdate& update = updates.itemAt(i); 298 299 if (update.surfaceChanged) { 300 update.sprite->setSurfaceLocked(update.state.surfaceControl, 301 update.state.surfaceWidth, update.state.surfaceHeight, 302 update.state.surfaceDrawn, update.state.surfaceVisible); 303 } 304 } 305 } // release lock 306 307 // Clear the sprite update vector outside the lock. It is very important that 308 // we do not clear sprite references inside the lock since we could be releasing 309 // the last remaining reference to the sprite here which would result in the 310 // sprite being deleted and the lock being reacquired by the sprite destructor 311 // while already held. 312 updates.clear(); 313 } 314 doDisposeSurfaces()315 void SpriteController::doDisposeSurfaces() { 316 // Collect disposed surfaces. 317 std::vector<sp<SurfaceControl>> disposedSurfaces; 318 { // acquire lock 319 AutoMutex _l(mLock); 320 321 disposedSurfaces = mLocked.disposedSurfaces; 322 mLocked.disposedSurfaces.clear(); 323 } // release lock 324 325 // Remove the parent from all surfaces. 326 SurfaceComposerClient::Transaction t; 327 for (const sp<SurfaceControl>& sc : disposedSurfaces) { 328 t.reparent(sc, nullptr); 329 } 330 t.apply(); 331 332 // Release the last reference to each surface outside of the lock. 333 // We don't want the surfaces to be deleted while we are holding our lock. 334 disposedSurfaces.clear(); 335 } 336 ensureSurfaceComposerClient()337 void SpriteController::ensureSurfaceComposerClient() { 338 if (mSurfaceComposerClient == NULL) { 339 mSurfaceComposerClient = sp<SurfaceComposerClient>::make(); 340 } 341 } 342 obtainSurface(int32_t width,int32_t height,ui::LogicalDisplayId displayId,bool hideOnMirrored)343 sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height, 344 ui::LogicalDisplayId displayId, 345 bool hideOnMirrored) { 346 ensureSurfaceComposerClient(); 347 348 const sp<SurfaceControl> parent = mParentSurfaceProvider(displayId); 349 if (parent == nullptr) { 350 LOG(ERROR) << "Failed to get the parent surface for pointers on display " << displayId; 351 } 352 353 int32_t createFlags = ISurfaceComposerClient::eHidden | ISurfaceComposerClient::eCursorWindow; 354 if (hideOnMirrored) { 355 createFlags |= ISurfaceComposerClient::eSkipScreenshot; 356 } 357 const sp<SurfaceControl> surfaceControl = 358 mSurfaceComposerClient->createSurface(String8("Sprite"), width, height, 359 PIXEL_FORMAT_RGBA_8888, createFlags, 360 parent ? parent->getHandle() : nullptr); 361 if (surfaceControl == nullptr || !surfaceControl->isValid()) { 362 ALOGE("Error creating sprite surface."); 363 return nullptr; 364 } 365 return surfaceControl; 366 } 367 368 // --- SpriteController::Handler --- 369 handleMessage(const android::Message & message)370 void SpriteController::Handler::handleMessage(const android::Message& message) { 371 auto controller = spriteController.lock(); 372 if (!controller) { 373 return; 374 } 375 376 switch (message.what) { 377 case MSG_UPDATE_SPRITES: 378 controller->doUpdateSprites(); 379 break; 380 case MSG_DISPOSE_SURFACES: 381 controller->doDisposeSurfaces(); 382 break; 383 } 384 } 385 386 // --- SpriteController::SpriteImpl --- 387 SpriteImpl(SpriteController & controller)388 SpriteController::SpriteImpl::SpriteImpl(SpriteController& controller) : mController(controller) {} 389 ~SpriteImpl()390 SpriteController::SpriteImpl::~SpriteImpl() { 391 AutoMutex _m(mController.mLock); 392 393 // Let the controller take care of deleting the last reference to sprite 394 // surfaces so that we do not block the caller on an IPC here. 395 if (mLocked.state.surfaceControl != NULL) { 396 mController.disposeSurfaceLocked(mLocked.state.surfaceControl); 397 mLocked.state.surfaceControl.clear(); 398 } 399 } 400 setIcon(const SpriteIcon & icon)401 void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) { 402 AutoMutex _l(mController.mLock); 403 404 uint32_t dirty; 405 if (icon.isValid()) { 406 mLocked.state.icon.bitmap = icon.bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888); 407 if (!mLocked.state.icon.isValid() || mLocked.state.icon.hotSpotX != icon.hotSpotX || 408 mLocked.state.icon.hotSpotY != icon.hotSpotY || 409 mLocked.state.icon.drawNativeDropShadow != icon.drawNativeDropShadow) { 410 mLocked.state.icon.hotSpotX = icon.hotSpotX; 411 mLocked.state.icon.hotSpotY = icon.hotSpotY; 412 mLocked.state.icon.drawNativeDropShadow = icon.drawNativeDropShadow; 413 dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_DRAW_DROP_SHADOW; 414 } else { 415 dirty = DIRTY_BITMAP; 416 } 417 418 if (mLocked.state.icon.style != icon.style) { 419 mLocked.state.icon.style = icon.style; 420 dirty |= DIRTY_ICON_STYLE; 421 } 422 } else if (mLocked.state.icon.isValid()) { 423 mLocked.state.icon.bitmap.reset(); 424 dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_ICON_STYLE | DIRTY_DRAW_DROP_SHADOW; 425 } else { 426 return; // setting to invalid icon and already invalid so nothing to do 427 } 428 429 invalidateLocked(dirty); 430 } 431 setVisible(bool visible)432 void SpriteController::SpriteImpl::setVisible(bool visible) { 433 AutoMutex _l(mController.mLock); 434 435 if (mLocked.state.visible != visible) { 436 mLocked.state.visible = visible; 437 invalidateLocked(DIRTY_VISIBILITY); 438 } 439 } 440 setPosition(float x,float y)441 void SpriteController::SpriteImpl::setPosition(float x, float y) { 442 AutoMutex _l(mController.mLock); 443 444 if (mLocked.state.positionX != x || mLocked.state.positionY != y) { 445 mLocked.state.positionX = x; 446 mLocked.state.positionY = y; 447 invalidateLocked(DIRTY_POSITION); 448 } 449 } 450 setLayer(int32_t layer)451 void SpriteController::SpriteImpl::setLayer(int32_t layer) { 452 AutoMutex _l(mController.mLock); 453 454 if (mLocked.state.layer != layer) { 455 mLocked.state.layer = layer; 456 invalidateLocked(DIRTY_LAYER); 457 } 458 } 459 setAlpha(float alpha)460 void SpriteController::SpriteImpl::setAlpha(float alpha) { 461 AutoMutex _l(mController.mLock); 462 463 if (mLocked.state.alpha != alpha) { 464 mLocked.state.alpha = alpha; 465 invalidateLocked(DIRTY_ALPHA); 466 } 467 } 468 setTransformationMatrix(const SpriteTransformationMatrix & matrix)469 void SpriteController::SpriteImpl::setTransformationMatrix( 470 const SpriteTransformationMatrix& matrix) { 471 AutoMutex _l(mController.mLock); 472 473 if (mLocked.state.transformationMatrix != matrix) { 474 mLocked.state.transformationMatrix = matrix; 475 invalidateLocked(DIRTY_TRANSFORMATION_MATRIX); 476 } 477 } 478 setDisplayId(ui::LogicalDisplayId displayId)479 void SpriteController::SpriteImpl::setDisplayId(ui::LogicalDisplayId displayId) { 480 AutoMutex _l(mController.mLock); 481 482 if (mLocked.state.displayId != displayId) { 483 mLocked.state.displayId = displayId; 484 invalidateLocked(DIRTY_DISPLAY_ID); 485 } 486 } 487 setSkipScreenshot(bool skip)488 void SpriteController::SpriteImpl::setSkipScreenshot(bool skip) { 489 AutoMutex _l(mController.mLock); 490 491 if (mLocked.state.skipScreenshot != skip) { 492 mLocked.state.skipScreenshot = skip; 493 invalidateLocked(DIRTY_SKIP_SCREENSHOT); 494 } 495 } 496 invalidateLocked(uint32_t dirty)497 void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) { 498 bool wasDirty = mLocked.state.dirty; 499 mLocked.state.dirty |= dirty; 500 501 if (!wasDirty) { 502 mController.invalidateSpriteLocked(sp<SpriteImpl>::fromExisting(this)); 503 } 504 } 505 506 } // namespace android 507