SurfaceComposerClient.cpp revision 4d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6
1/* 2 * Copyright (C) 2007 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 "SurfaceComposerClient" 18 19#include <stdint.h> 20#include <sys/types.h> 21 22#include <utils/Errors.h> 23#include <utils/Log.h> 24#include <utils/Singleton.h> 25#include <utils/SortedVector.h> 26#include <utils/String8.h> 27#include <utils/threads.h> 28 29#include <binder/IMemory.h> 30#include <binder/IServiceManager.h> 31 32#include <ui/DisplayInfo.h> 33 34#include <gui/IGraphicBufferProducer.h> 35#include <gui/ISurfaceComposer.h> 36#include <gui/ISurfaceComposerClient.h> 37#include <gui/SurfaceComposerClient.h> 38 39#include <private/gui/ComposerService.h> 40#include <private/gui/LayerState.h> 41 42namespace android { 43// --------------------------------------------------------------------------- 44 45ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); 46 47ComposerService::ComposerService() 48: Singleton<ComposerService>() { 49 Mutex::Autolock _l(mLock); 50 connectLocked(); 51} 52 53void ComposerService::connectLocked() { 54 const String16 name("SurfaceFlinger"); 55 while (getService(name, &mComposerService) != NO_ERROR) { 56 usleep(250000); 57 } 58 assert(mComposerService != NULL); 59 60 // Create the death listener. 61 class DeathObserver : public IBinder::DeathRecipient { 62 ComposerService& mComposerService; 63 virtual void binderDied(const wp<IBinder>& who) { 64 ALOGW("ComposerService remote (surfaceflinger) died [%p]", 65 who.unsafe_get()); 66 mComposerService.composerServiceDied(); 67 } 68 public: 69 DeathObserver(ComposerService& mgr) : mComposerService(mgr) { } 70 }; 71 72 mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this)); 73 mComposerService->asBinder()->linkToDeath(mDeathObserver); 74} 75 76/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() { 77 ComposerService& instance = ComposerService::getInstance(); 78 Mutex::Autolock _l(instance.mLock); 79 if (instance.mComposerService == NULL) { 80 ComposerService::getInstance().connectLocked(); 81 assert(instance.mComposerService != NULL); 82 ALOGD("ComposerService reconnected"); 83 } 84 return instance.mComposerService; 85} 86 87void ComposerService::composerServiceDied() 88{ 89 Mutex::Autolock _l(mLock); 90 mComposerService = NULL; 91 mDeathObserver = NULL; 92} 93 94// --------------------------------------------------------------------------- 95 96static inline 97int compare_type(const ComposerState& lhs, const ComposerState& rhs) { 98 if (lhs.client < rhs.client) return -1; 99 if (lhs.client > rhs.client) return 1; 100 if (lhs.state.surface < rhs.state.surface) return -1; 101 if (lhs.state.surface > rhs.state.surface) return 1; 102 return 0; 103} 104 105static inline 106int compare_type(const DisplayState& lhs, const DisplayState& rhs) { 107 return compare_type(lhs.token, rhs.token); 108} 109 110class Composer : public Singleton<Composer> 111{ 112 friend class Singleton<Composer>; 113 114 mutable Mutex mLock; 115 SortedVector<ComposerState> mComposerStates; 116 SortedVector<DisplayState > mDisplayStates; 117 uint32_t mForceSynchronous; 118 uint32_t mTransactionNestCount; 119 bool mAnimation; 120 121 Composer() : Singleton<Composer>(), 122 mForceSynchronous(0), mTransactionNestCount(0), 123 mAnimation(false) 124 { } 125 126 void openGlobalTransactionImpl(); 127 void closeGlobalTransactionImpl(bool synchronous); 128 void setAnimationTransactionImpl(); 129 130 layer_state_t* getLayerStateLocked( 131 const sp<SurfaceComposerClient>& client, const sp<IBinder>& id); 132 133 DisplayState& getDisplayStateLocked(const sp<IBinder>& token); 134 135public: 136 sp<IBinder> createDisplay(const String8& displayName, bool secure); 137 sp<IBinder> getBuiltInDisplay(int32_t id); 138 139 status_t setPosition(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 140 float x, float y); 141 status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 142 uint32_t w, uint32_t h); 143 status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 144 int32_t z); 145 status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 146 uint32_t flags, uint32_t mask); 147 status_t setTransparentRegionHint( 148 const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 149 const Region& transparentRegion); 150 status_t setAlpha(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 151 float alpha); 152 status_t setMatrix(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 153 float dsdx, float dtdx, float dsdy, float dtdy); 154 status_t setOrientation(int orientation); 155 status_t setCrop(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 156 const Rect& crop); 157 status_t setLayerStack(const sp<SurfaceComposerClient>& client, 158 const sp<IBinder>& id, uint32_t layerStack); 159 160 void setDisplaySurface(const sp<IBinder>& token, 161 const sp<IGraphicBufferProducer>& bufferProducer); 162 void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack); 163 void setDisplayProjection(const sp<IBinder>& token, 164 uint32_t orientation, 165 const Rect& layerStackRect, 166 const Rect& displayRect); 167 168 static void setAnimationTransaction() { 169 Composer::getInstance().setAnimationTransactionImpl(); 170 } 171 172 static void openGlobalTransaction() { 173 Composer::getInstance().openGlobalTransactionImpl(); 174 } 175 176 static void closeGlobalTransaction(bool synchronous) { 177 Composer::getInstance().closeGlobalTransactionImpl(synchronous); 178 } 179}; 180 181ANDROID_SINGLETON_STATIC_INSTANCE(Composer); 182 183// --------------------------------------------------------------------------- 184 185sp<IBinder> Composer::createDisplay(const String8& displayName, bool secure) { 186 return ComposerService::getComposerService()->createDisplay(displayName, 187 secure); 188} 189 190sp<IBinder> Composer::getBuiltInDisplay(int32_t id) { 191 return ComposerService::getComposerService()->getBuiltInDisplay(id); 192} 193 194void Composer::openGlobalTransactionImpl() { 195 { // scope for the lock 196 Mutex::Autolock _l(mLock); 197 mTransactionNestCount += 1; 198 } 199} 200 201void Composer::closeGlobalTransactionImpl(bool synchronous) { 202 sp<ISurfaceComposer> sm(ComposerService::getComposerService()); 203 204 Vector<ComposerState> transaction; 205 Vector<DisplayState> displayTransaction; 206 uint32_t flags = 0; 207 208 { // scope for the lock 209 Mutex::Autolock _l(mLock); 210 mForceSynchronous |= synchronous; 211 if (!mTransactionNestCount) { 212 ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior " 213 "call to openGlobalTransaction()."); 214 } else if (--mTransactionNestCount) { 215 return; 216 } 217 218 transaction = mComposerStates; 219 mComposerStates.clear(); 220 221 displayTransaction = mDisplayStates; 222 mDisplayStates.clear(); 223 224 if (mForceSynchronous) { 225 flags |= ISurfaceComposer::eSynchronous; 226 } 227 if (mAnimation) { 228 flags |= ISurfaceComposer::eAnimation; 229 } 230 231 mForceSynchronous = false; 232 mAnimation = false; 233 } 234 235 sm->setTransactionState(transaction, displayTransaction, flags); 236} 237 238void Composer::setAnimationTransactionImpl() { 239 Mutex::Autolock _l(mLock); 240 mAnimation = true; 241} 242 243layer_state_t* Composer::getLayerStateLocked( 244 const sp<SurfaceComposerClient>& client, const sp<IBinder>& id) { 245 246 ComposerState s; 247 s.client = client->mClient; 248 s.state.surface = id; 249 250 ssize_t index = mComposerStates.indexOf(s); 251 if (index < 0) { 252 // we don't have it, add an initialized layer_state to our list 253 index = mComposerStates.add(s); 254 } 255 256 ComposerState* const out = mComposerStates.editArray(); 257 return &(out[index].state); 258} 259 260status_t Composer::setPosition(const sp<SurfaceComposerClient>& client, 261 const sp<IBinder>& id, float x, float y) { 262 Mutex::Autolock _l(mLock); 263 layer_state_t* s = getLayerStateLocked(client, id); 264 if (!s) 265 return BAD_INDEX; 266 s->what |= layer_state_t::ePositionChanged; 267 s->x = x; 268 s->y = y; 269 return NO_ERROR; 270} 271 272status_t Composer::setSize(const sp<SurfaceComposerClient>& client, 273 const sp<IBinder>& id, uint32_t w, uint32_t h) { 274 Mutex::Autolock _l(mLock); 275 layer_state_t* s = getLayerStateLocked(client, id); 276 if (!s) 277 return BAD_INDEX; 278 s->what |= layer_state_t::eSizeChanged; 279 s->w = w; 280 s->h = h; 281 282 // Resizing a surface makes the transaction synchronous. 283 mForceSynchronous = true; 284 285 return NO_ERROR; 286} 287 288status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, 289 const sp<IBinder>& id, int32_t z) { 290 Mutex::Autolock _l(mLock); 291 layer_state_t* s = getLayerStateLocked(client, id); 292 if (!s) 293 return BAD_INDEX; 294 s->what |= layer_state_t::eLayerChanged; 295 s->z = z; 296 return NO_ERROR; 297} 298 299status_t Composer::setFlags(const sp<SurfaceComposerClient>& client, 300 const sp<IBinder>& id, uint32_t flags, 301 uint32_t mask) { 302 Mutex::Autolock _l(mLock); 303 layer_state_t* s = getLayerStateLocked(client, id); 304 if (!s) 305 return BAD_INDEX; 306 s->what |= layer_state_t::eVisibilityChanged; 307 s->flags &= ~mask; 308 s->flags |= (flags & mask); 309 s->mask |= mask; 310 return NO_ERROR; 311} 312 313status_t Composer::setTransparentRegionHint( 314 const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, 315 const Region& transparentRegion) { 316 Mutex::Autolock _l(mLock); 317 layer_state_t* s = getLayerStateLocked(client, id); 318 if (!s) 319 return BAD_INDEX; 320 s->what |= layer_state_t::eTransparentRegionChanged; 321 s->transparentRegion = transparentRegion; 322 return NO_ERROR; 323} 324 325status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client, 326 const sp<IBinder>& id, float alpha) { 327 Mutex::Autolock _l(mLock); 328 layer_state_t* s = getLayerStateLocked(client, id); 329 if (!s) 330 return BAD_INDEX; 331 s->what |= layer_state_t::eAlphaChanged; 332 s->alpha = alpha; 333 return NO_ERROR; 334} 335 336status_t Composer::setLayerStack(const sp<SurfaceComposerClient>& client, 337 const sp<IBinder>& id, uint32_t layerStack) { 338 Mutex::Autolock _l(mLock); 339 layer_state_t* s = getLayerStateLocked(client, id); 340 if (!s) 341 return BAD_INDEX; 342 s->what |= layer_state_t::eLayerStackChanged; 343 s->layerStack = layerStack; 344 return NO_ERROR; 345} 346 347status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client, 348 const sp<IBinder>& id, float dsdx, float dtdx, 349 float dsdy, float dtdy) { 350 Mutex::Autolock _l(mLock); 351 layer_state_t* s = getLayerStateLocked(client, id); 352 if (!s) 353 return BAD_INDEX; 354 s->what |= layer_state_t::eMatrixChanged; 355 layer_state_t::matrix22_t matrix; 356 matrix.dsdx = dsdx; 357 matrix.dtdx = dtdx; 358 matrix.dsdy = dsdy; 359 matrix.dtdy = dtdy; 360 s->matrix = matrix; 361 return NO_ERROR; 362} 363 364status_t Composer::setCrop(const sp<SurfaceComposerClient>& client, 365 const sp<IBinder>& id, const Rect& crop) { 366 Mutex::Autolock _l(mLock); 367 layer_state_t* s = getLayerStateLocked(client, id); 368 if (!s) 369 return BAD_INDEX; 370 s->what |= layer_state_t::eCropChanged; 371 s->crop = crop; 372 return NO_ERROR; 373} 374 375// --------------------------------------------------------------------------- 376 377DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) { 378 DisplayState s; 379 s.token = token; 380 ssize_t index = mDisplayStates.indexOf(s); 381 if (index < 0) { 382 // we don't have it, add an initialized layer_state to our list 383 s.what = 0; 384 index = mDisplayStates.add(s); 385 } 386 return mDisplayStates.editItemAt(index); 387} 388 389void Composer::setDisplaySurface(const sp<IBinder>& token, 390 const sp<IGraphicBufferProducer>& bufferProducer) { 391 Mutex::Autolock _l(mLock); 392 DisplayState& s(getDisplayStateLocked(token)); 393 s.surface = bufferProducer; 394 s.what |= DisplayState::eSurfaceChanged; 395} 396 397void Composer::setDisplayLayerStack(const sp<IBinder>& token, 398 uint32_t layerStack) { 399 Mutex::Autolock _l(mLock); 400 DisplayState& s(getDisplayStateLocked(token)); 401 s.layerStack = layerStack; 402 s.what |= DisplayState::eLayerStackChanged; 403} 404 405void Composer::setDisplayProjection(const sp<IBinder>& token, 406 uint32_t orientation, 407 const Rect& layerStackRect, 408 const Rect& displayRect) { 409 Mutex::Autolock _l(mLock); 410 DisplayState& s(getDisplayStateLocked(token)); 411 s.orientation = orientation; 412 s.viewport = layerStackRect; 413 s.frame = displayRect; 414 s.what |= DisplayState::eDisplayProjectionChanged; 415 mForceSynchronous = true; // TODO: do we actually still need this? 416} 417 418// --------------------------------------------------------------------------- 419 420SurfaceComposerClient::SurfaceComposerClient() 421 : mStatus(NO_INIT), mComposer(Composer::getInstance()) 422{ 423} 424 425void SurfaceComposerClient::onFirstRef() { 426 sp<ISurfaceComposer> sm(ComposerService::getComposerService()); 427 if (sm != 0) { 428 sp<ISurfaceComposerClient> conn = sm->createConnection(); 429 if (conn != 0) { 430 mClient = conn; 431 mStatus = NO_ERROR; 432 } 433 } 434} 435 436SurfaceComposerClient::~SurfaceComposerClient() { 437 dispose(); 438} 439 440status_t SurfaceComposerClient::initCheck() const { 441 return mStatus; 442} 443 444sp<IBinder> SurfaceComposerClient::connection() const { 445 return (mClient != 0) ? mClient->asBinder() : 0; 446} 447 448status_t SurfaceComposerClient::linkToComposerDeath( 449 const sp<IBinder::DeathRecipient>& recipient, 450 void* cookie, uint32_t flags) { 451 sp<ISurfaceComposer> sm(ComposerService::getComposerService()); 452 return sm->asBinder()->linkToDeath(recipient, cookie, flags); 453} 454 455void SurfaceComposerClient::dispose() { 456 // this can be called more than once. 457 sp<ISurfaceComposerClient> client; 458 Mutex::Autolock _lm(mLock); 459 if (mClient != 0) { 460 client = mClient; // hold ref while lock is held 461 mClient.clear(); 462 } 463 mStatus = NO_INIT; 464} 465 466sp<SurfaceControl> SurfaceComposerClient::createSurface( 467 const String8& name, 468 uint32_t w, 469 uint32_t h, 470 PixelFormat format, 471 uint32_t flags) 472{ 473 sp<SurfaceControl> sur; 474 if (mStatus == NO_ERROR) { 475 sp<IBinder> handle; 476 sp<IGraphicBufferProducer> gbp; 477 status_t err = mClient->createSurface(name, w, h, format, flags, 478 &handle, &gbp); 479 ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); 480 if (err == NO_ERROR) { 481 sur = new SurfaceControl(this, handle, gbp); 482 } 483 } 484 return sur; 485} 486 487sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, 488 bool secure) { 489 return Composer::getInstance().createDisplay(displayName, secure); 490} 491 492sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) { 493 return Composer::getInstance().getBuiltInDisplay(id); 494} 495 496status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) { 497 if (mStatus != NO_ERROR) 498 return mStatus; 499 status_t err = mClient->destroySurface(sid); 500 return err; 501} 502 503inline Composer& SurfaceComposerClient::getComposer() { 504 return mComposer; 505} 506 507// ---------------------------------------------------------------------------- 508 509void SurfaceComposerClient::openGlobalTransaction() { 510 Composer::openGlobalTransaction(); 511} 512 513void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) { 514 Composer::closeGlobalTransaction(synchronous); 515} 516 517void SurfaceComposerClient::setAnimationTransaction() { 518 Composer::setAnimationTransaction(); 519} 520 521// ---------------------------------------------------------------------------- 522 523status_t SurfaceComposerClient::setCrop(const sp<IBinder>& id, const Rect& crop) { 524 return getComposer().setCrop(this, id, crop); 525} 526 527status_t SurfaceComposerClient::setPosition(const sp<IBinder>& id, float x, float y) { 528 return getComposer().setPosition(this, id, x, y); 529} 530 531status_t SurfaceComposerClient::setSize(const sp<IBinder>& id, uint32_t w, uint32_t h) { 532 return getComposer().setSize(this, id, w, h); 533} 534 535status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) { 536 return getComposer().setLayer(this, id, z); 537} 538 539status_t SurfaceComposerClient::hide(const sp<IBinder>& id) { 540 return getComposer().setFlags(this, id, 541 layer_state_t::eLayerHidden, 542 layer_state_t::eLayerHidden); 543} 544 545status_t SurfaceComposerClient::show(const sp<IBinder>& id) { 546 return getComposer().setFlags(this, id, 547 0, 548 layer_state_t::eLayerHidden); 549} 550 551status_t SurfaceComposerClient::setFlags(const sp<IBinder>& id, uint32_t flags, 552 uint32_t mask) { 553 return getComposer().setFlags(this, id, flags, mask); 554} 555 556status_t SurfaceComposerClient::setTransparentRegionHint(const sp<IBinder>& id, 557 const Region& transparentRegion) { 558 return getComposer().setTransparentRegionHint(this, id, transparentRegion); 559} 560 561status_t SurfaceComposerClient::setAlpha(const sp<IBinder>& id, float alpha) { 562 return getComposer().setAlpha(this, id, alpha); 563} 564 565status_t SurfaceComposerClient::setLayerStack(const sp<IBinder>& id, uint32_t layerStack) { 566 return getComposer().setLayerStack(this, id, layerStack); 567} 568 569status_t SurfaceComposerClient::setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, 570 float dsdy, float dtdy) { 571 return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy); 572} 573 574// ---------------------------------------------------------------------------- 575 576void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token, 577 const sp<IGraphicBufferProducer>& bufferProducer) { 578 Composer::getInstance().setDisplaySurface(token, bufferProducer); 579} 580 581void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token, 582 uint32_t layerStack) { 583 Composer::getInstance().setDisplayLayerStack(token, layerStack); 584} 585 586void SurfaceComposerClient::setDisplayProjection(const sp<IBinder>& token, 587 uint32_t orientation, 588 const Rect& layerStackRect, 589 const Rect& displayRect) { 590 Composer::getInstance().setDisplayProjection(token, orientation, 591 layerStackRect, displayRect); 592} 593 594// ---------------------------------------------------------------------------- 595 596status_t SurfaceComposerClient::getDisplayInfo( 597 const sp<IBinder>& display, DisplayInfo* info) 598{ 599 return ComposerService::getComposerService()->getDisplayInfo(display, info); 600} 601 602void SurfaceComposerClient::blankDisplay(const sp<IBinder>& token) { 603 ComposerService::getComposerService()->blank(token); 604} 605 606void SurfaceComposerClient::unblankDisplay(const sp<IBinder>& token) { 607 ComposerService::getComposerService()->unblank(token); 608} 609 610// ---------------------------------------------------------------------------- 611 612status_t ScreenshotClient::capture( 613 const sp<IBinder>& display, 614 const sp<IGraphicBufferProducer>& producer, 615 uint32_t reqWidth, uint32_t reqHeight, 616 uint32_t minLayerZ, uint32_t maxLayerZ) { 617 sp<ISurfaceComposer> s(ComposerService::getComposerService()); 618 if (s == NULL) return NO_INIT; 619 return s->captureScreen(display, producer, 620 reqWidth, reqHeight, minLayerZ, maxLayerZ); 621} 622 623ScreenshotClient::ScreenshotClient() 624 : mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) { 625} 626 627status_t ScreenshotClient::update(const sp<IBinder>& display) { 628 sp<ISurfaceComposer> s(ComposerService::getComposerService()); 629 if (s == NULL) return NO_INIT; 630 mHeap = 0; 631 return s->captureScreen(display, &mHeap, 632 &mWidth, &mHeight, &mFormat, 0, 0, 633 0, -1UL); 634} 635 636status_t ScreenshotClient::update(const sp<IBinder>& display, 637 uint32_t reqWidth, uint32_t reqHeight) { 638 sp<ISurfaceComposer> s(ComposerService::getComposerService()); 639 if (s == NULL) return NO_INIT; 640 mHeap = 0; 641 return s->captureScreen(display, &mHeap, 642 &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, 643 0, -1UL); 644} 645 646status_t ScreenshotClient::update(const sp<IBinder>& display, 647 uint32_t reqWidth, uint32_t reqHeight, 648 uint32_t minLayerZ, uint32_t maxLayerZ) { 649 sp<ISurfaceComposer> s(ComposerService::getComposerService()); 650 if (s == NULL) return NO_INIT; 651 mHeap = 0; 652 return s->captureScreen(display, &mHeap, 653 &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, 654 minLayerZ, maxLayerZ); 655} 656 657void ScreenshotClient::release() { 658 mHeap = 0; 659} 660 661void const* ScreenshotClient::getPixels() const { 662 return mHeap->getBase(); 663} 664 665uint32_t ScreenshotClient::getWidth() const { 666 return mWidth; 667} 668 669uint32_t ScreenshotClient::getHeight() const { 670 return mHeight; 671} 672 673PixelFormat ScreenshotClient::getFormat() const { 674 return mFormat; 675} 676 677uint32_t ScreenshotClient::getStride() const { 678 return mWidth; 679} 680 681size_t ScreenshotClient::getSize() const { 682 return mHeap->getSize(); 683} 684 685// ---------------------------------------------------------------------------- 686}; // namespace android 687