15c13d89c1332fcc499379b9064b891187b75ca32Chet Haase/* 25c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * Copyright (C) 2010 The Android Open Source Project 35c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * 45c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 55c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * you may not use this file except in compliance with the License. 65c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * You may obtain a copy of the License at 75c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * 85c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * http://www.apache.org/licenses/LICENSE-2.0 95c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * 105c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * Unless required by applicable law or agreed to in writing, software 115c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * distributed under the License is distributed on an "AS IS" BASIS, 125c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * See the License for the specific language governing permissions and 145c13d89c1332fcc499379b9064b891187b75ca32Chet Haase * limitations under the License. 155c13d89c1332fcc499379b9064b891187b75ca32Chet Haase */ 165c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 175c13d89c1332fcc499379b9064b891187b75ca32Chet Haase#include "ResourceCache.h" 185c13d89c1332fcc499379b9064b891187b75ca32Chet Haase#include "Caches.h" 195c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 205c13d89c1332fcc499379b9064b891187b75ca32Chet Haasenamespace android { 21a35778c799e8073a42b9e22191bde9d838327ab7John Reck 22a35778c799e8073a42b9e22191bde9d838327ab7John Reckusing namespace uirenderer; 23a35778c799e8073a42b9e22191bde9d838327ab7John ReckANDROID_SINGLETON_STATIC_INSTANCE(ResourceCache); 24a35778c799e8073a42b9e22191bde9d838327ab7John Reck 255c13d89c1332fcc499379b9064b891187b75ca32Chet Haasenamespace uirenderer { 265c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 275c13d89c1332fcc499379b9064b891187b75ca32Chet Haase/////////////////////////////////////////////////////////////////////////////// 285c13d89c1332fcc499379b9064b891187b75ca32Chet Haase// Resource cache 295c13d89c1332fcc499379b9064b891187b75ca32Chet Haase/////////////////////////////////////////////////////////////////////////////// 305c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 315c13d89c1332fcc499379b9064b891187b75ca32Chet Haasevoid ResourceCache::logCache() { 325baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("ResourceCache: cacheReport:"); 335c13d89c1332fcc499379b9064b891187b75ca32Chet Haase for (size_t i = 0; i < mCache->size(); ++i) { 345c13d89c1332fcc499379b9064b891187b75ca32Chet Haase ResourceReference* ref = mCache->valueAt(i); 35f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat ALOGD(" ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p", 365c13d89c1332fcc499379b9064b891187b75ca32Chet Haase i, mCache->keyAt(i), mCache->valueAt(i)); 373d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger ALOGD(" ResourceCache: mCache(%zu): refCount, destroyed, type = %d, %d, %d", 383d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger i, ref->refCount, ref->destroyed, ref->resourceType); 395c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 405c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 415c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 425c13d89c1332fcc499379b9064b891187b75ca32Chet HaaseResourceCache::ResourceCache() { 43e7d2295c06ef9b9df6336cbff23007a13fb3f6e4Chet Haase Mutex::Autolock _l(mLock); 44d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik mCache = new KeyedVector<const void*, ResourceReference*>(); 455c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 465c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 475c13d89c1332fcc499379b9064b891187b75ca32Chet HaaseResourceCache::~ResourceCache() { 48e7d2295c06ef9b9df6336cbff23007a13fb3f6e4Chet Haase Mutex::Autolock _l(mLock); 495c13d89c1332fcc499379b9064b891187b75ca32Chet Haase delete mCache; 505c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 515c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 5258ecc204fbcacef34806290492384677a330d4d4Romain Guyvoid ResourceCache::lock() { 5358ecc204fbcacef34806290492384677a330d4d4Romain Guy mLock.lock(); 5458ecc204fbcacef34806290492384677a330d4d4Romain Guy} 5558ecc204fbcacef34806290492384677a330d4d4Romain Guy 5658ecc204fbcacef34806290492384677a330d4d4Romain Guyvoid ResourceCache::unlock() { 5758ecc204fbcacef34806290492384677a330d4d4Romain Guy mLock.unlock(); 5858ecc204fbcacef34806290492384677a330d4d4Romain Guy} 5958ecc204fbcacef34806290492384677a330d4d4Romain Guy 603d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenbergervoid ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) { 613d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger Mutex::Autolock _l(mLock); 623d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger incrementRefcountLocked(resource, resourceType); 635c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 645c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 65d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) { 66e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy incrementRefcount((void*) patchResource, kNinePatch); 67e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 68e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 6958ecc204fbcacef34806290492384677a330d4d4Romain Guyvoid ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) { 708dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy ssize_t index = mCache->indexOfKey(resource); 71d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; 72d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (ref == nullptr || mCache->size() == 0) { 7358ecc204fbcacef34806290492384677a330d4d4Romain Guy ref = new ResourceReference(resourceType); 7458ecc204fbcacef34806290492384677a330d4d4Romain Guy mCache->add(resource, ref); 755c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 7658ecc204fbcacef34806290492384677a330d4d4Romain Guy ref->refCount++; 7758ecc204fbcacef34806290492384677a330d4d4Romain Guy} 7858ecc204fbcacef34806290492384677a330d4d4Romain Guy 7958ecc204fbcacef34806290492384677a330d4d4Romain Guyvoid ResourceCache::decrementRefcount(void* resource) { 8058ecc204fbcacef34806290492384677a330d4d4Romain Guy Mutex::Autolock _l(mLock); 8158ecc204fbcacef34806290492384677a330d4d4Romain Guy decrementRefcountLocked(resource); 825c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 835c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 84d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) { 85e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy decrementRefcount((void*) patchResource); 86e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 87e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 8858ecc204fbcacef34806290492384677a330d4d4Romain Guyvoid ResourceCache::decrementRefcountLocked(void* resource) { 898dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy ssize_t index = mCache->indexOfKey(resource); 90d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; 91d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (ref == nullptr) { 9258ecc204fbcacef34806290492384677a330d4d4Romain Guy // Should not get here - shouldn't get a call to decrement if we're not yet tracking it 935c13d89c1332fcc499379b9064b891187b75ca32Chet Haase return; 945c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 9558ecc204fbcacef34806290492384677a330d4d4Romain Guy ref->refCount--; 965c13d89c1332fcc499379b9064b891187b75ca32Chet Haase if (ref->refCount == 0) { 9797dc9172b0e58979c63de0dedbab656399a62281Romain Guy deleteResourceReferenceLocked(resource, ref); 985c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 995c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 1005c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 101d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) { 102e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy decrementRefcountLocked((void*) patchResource); 103e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 104e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 105e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid ResourceCache::destructor(Res_png_9patch* resource) { 106e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Mutex::Autolock _l(mLock); 107e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy destructorLocked(resource); 108e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 109e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 110e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyvoid ResourceCache::destructorLocked(Res_png_9patch* resource) { 111e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy ssize_t index = mCache->indexOfKey(resource); 112d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; 113d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (ref == nullptr) { 11436fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee // If we're not tracking this resource, just delete it 115e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (Caches::hasInstance()) { 116e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Caches::getInstance().patchCache.removeDeferred(resource); 11736fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee } else { 11836fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee // A Res_png_9patch is actually an array of byte that's larger 11936fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee // than sizeof(Res_png_9patch). It must be freed as an array. 12036fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee delete[] (int8_t*) resource; 121e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 122e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy return; 123e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 124e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy ref->destroyed = true; 125e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (ref->refCount == 0) { 126e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy deleteResourceReferenceLocked(resource, ref); 127e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 128e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy} 129e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 130547e66531d521eb1eadac87edb0f79f8c2f1bbe0Chet Haase/** 131e7d2295c06ef9b9df6336cbff23007a13fb3f6e4Chet Haase * This method should only be called while the mLock mutex is held (that mutex is grabbed 132e7d2295c06ef9b9df6336cbff23007a13fb3f6e4Chet Haase * by the various destructor() and recycle() methods which call this method). 133e7d2295c06ef9b9df6336cbff23007a13fb3f6e4Chet Haase */ 134d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid ResourceCache::deleteResourceReferenceLocked(const void* resource, ResourceReference* ref) { 1350e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck if (ref->destroyed) { 1365c13d89c1332fcc499379b9064b891187b75ca32Chet Haase switch (ref->resourceType) { 137e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy case kNinePatch: { 138e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy if (Caches::hasInstance()) { 139e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource); 14036fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee } else { 14136fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee // A Res_png_9patch is actually an array of byte that's larger 14236fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee // than sizeof(Res_png_9patch). It must be freed as an array. 14336fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee int8_t* patch = (int8_t*) resource; 14436fad8f6fcfbc2087b910600ed5a6f9741177d00Sangkyu Lee delete[] patch; 145e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 146e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy } 147e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy break; 1485c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 1495c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 1505c13d89c1332fcc499379b9064b891187b75ca32Chet Haase mCache->removeItem(resource); 1515c13d89c1332fcc499379b9064b891187b75ca32Chet Haase delete ref; 1525c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 1535c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 1545c13d89c1332fcc499379b9064b891187b75ca32Chet Haase}; // namespace uirenderer 1555c13d89c1332fcc499379b9064b891187b75ca32Chet Haase}; // namespace android 156