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