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