diff options
Diffstat (limited to 'src/com/android/photos/data/SparseArrayBitmapPool.java')
-rw-r--r-- | src/com/android/photos/data/SparseArrayBitmapPool.java | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/src/com/android/photos/data/SparseArrayBitmapPool.java b/src/com/android/photos/data/SparseArrayBitmapPool.java deleted file mode 100644 index 95e10267b..000000000 --- a/src/com/android/photos/data/SparseArrayBitmapPool.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.data; - -import android.graphics.Bitmap; -import android.util.SparseArray; - -import android.util.Pools.Pool; -import android.util.Pools.SimplePool; - -/** - * Bitmap pool backed by a sparse array indexing linked lists of bitmaps - * sharing the same width. Performance will degrade if using this to store - * many bitmaps with the same width but many different heights. - */ -public class SparseArrayBitmapPool { - - private int mCapacityBytes; - private SparseArray<Node> mStore = new SparseArray<Node>(); - private int mSizeBytes = 0; - - private Pool<Node> mNodePool; - private Node mPoolNodesHead = null; - private Node mPoolNodesTail = null; - - protected static class Node { - Bitmap bitmap; - - // Each node is part of two doubly linked lists: - // - A pool-level list (accessed by mPoolNodesHead and mPoolNodesTail) - // that is used for FIFO eviction of nodes when the pool gets full. - // - A bucket-level list for each index of the sparse array, so that - // each index can store more than one item. - Node prevInBucket; - Node nextInBucket; - Node nextInPool; - Node prevInPool; - } - - /** - * @param capacityBytes Maximum capacity of the pool in bytes. - * @param nodePool Shared pool to use for recycling linked list nodes, or null. - */ - public SparseArrayBitmapPool(int capacityBytes, Pool<Node> nodePool) { - mCapacityBytes = capacityBytes; - if (nodePool == null) { - mNodePool = new SimplePool<Node>(32); - } else { - mNodePool = nodePool; - } - } - - /** - * Set the maximum capacity of the pool, and if necessary trim it down to size. - */ - public synchronized void setCapacity(int capacityBytes) { - mCapacityBytes = capacityBytes; - - // No-op unless current size exceeds the new capacity. - freeUpCapacity(0); - } - - private void freeUpCapacity(int bytesNeeded) { - int targetSize = mCapacityBytes - bytesNeeded; - // Repeatedly remove the oldest node until we have freed up at least bytesNeeded. - while (mPoolNodesTail != null && mSizeBytes > targetSize) { - unlinkAndRecycleNode(mPoolNodesTail, true); - } - } - - private void unlinkAndRecycleNode(Node n, boolean recycleBitmap) { - // Unlink the node from its sparse array bucket list. - if (n.prevInBucket != null) { - // This wasn't the head, update the previous node. - n.prevInBucket.nextInBucket = n.nextInBucket; - } else { - // This was the head of the bucket, replace it with the next node. - mStore.put(n.bitmap.getWidth(), n.nextInBucket); - } - if (n.nextInBucket != null) { - // This wasn't the tail, update the next node. - n.nextInBucket.prevInBucket = n.prevInBucket; - } - - // Unlink the node from the pool-wide list. - if (n.prevInPool != null) { - // This wasn't the head, update the previous node. - n.prevInPool.nextInPool = n.nextInPool; - } else { - // This was the head of the pool-wide list, update the head pointer. - mPoolNodesHead = n.nextInPool; - } - if (n.nextInPool != null) { - // This wasn't the tail, update the next node. - n.nextInPool.prevInPool = n.prevInPool; - } else { - // This was the tail, update the tail pointer. - mPoolNodesTail = n.prevInPool; - } - - // Recycle the node. - n.nextInBucket = null; - n.nextInPool = null; - n.prevInBucket = null; - n.prevInPool = null; - mSizeBytes -= n.bitmap.getByteCount(); - if (recycleBitmap) n.bitmap.recycle(); - n.bitmap = null; - mNodePool.release(n); - } - - /** - * @return Capacity of the pool in bytes. - */ - public synchronized int getCapacity() { - return mCapacityBytes; - } - - /** - * @return Total size in bytes of the bitmaps stored in the pool. - */ - public synchronized int getSize() { - return mSizeBytes; - } - - /** - * @return Bitmap from the pool with the desired height/width or null if none available. - */ - public synchronized Bitmap get(int width, int height) { - Node cur = mStore.get(width); - - // Traverse the list corresponding to the width bucket in the - // sparse array, and unlink and return the first bitmap that - // also has the correct height. - while (cur != null) { - if (cur.bitmap.getHeight() == height) { - Bitmap b = cur.bitmap; - unlinkAndRecycleNode(cur, false); - return b; - } - cur = cur.nextInBucket; - } - return null; - } - - /** - * Adds the given bitmap to the pool. - * @return Whether the bitmap was added to the pool. - */ - public synchronized boolean put(Bitmap b) { - if (b == null) { - return false; - } - - // Ensure there is enough room to contain the new bitmap. - int bytes = b.getByteCount(); - freeUpCapacity(bytes); - - Node newNode = mNodePool.acquire(); - if (newNode == null) { - newNode = new Node(); - } - newNode.bitmap = b; - - // We append to the head, and freeUpCapacity clears from the tail, - // resulting in FIFO eviction. - newNode.prevInBucket = null; - newNode.prevInPool = null; - newNode.nextInPool = mPoolNodesHead; - mPoolNodesHead = newNode; - - // Insert the node into its appropriate bucket based on width. - int key = b.getWidth(); - newNode.nextInBucket = mStore.get(key); - if (newNode.nextInBucket != null) { - // The bucket already had nodes, update the old head. - newNode.nextInBucket.prevInBucket = newNode; - } - mStore.put(key, newNode); - - if (newNode.nextInPool == null) { - // This is the only node in the list, update the tail pointer. - mPoolNodesTail = newNode; - } else { - newNode.nextInPool.prevInPool = newNode; - } - mSizeBytes += bytes; - return true; - } - - /** - * Empty the pool, recycling all the bitmaps currently in it. - */ - public synchronized void clear() { - // Clearing is equivalent to ensuring all the capacity is available. - freeUpCapacity(mCapacityBytes); - } -} |