/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.favicons.cache; import android.graphics.Bitmap; /** * Objects stored in the Favicon cache - allow for the bitmap to be tagged to indicate if it has * been scaled. Unscaled bitmaps are not included in the scaled-bitmap cache's size calculation. */ public class FaviconCacheElement implements Comparable<FaviconCacheElement> { // Was this Favicon computed via scaling another primary Favicon, or is this a primary Favicon? final boolean mIsPrimary; // The Favicon bitmap. Bitmap mFaviconPayload; // If set, mFaviconPayload is absent. Since the underlying ICO may contain multiple primary // payloads, primary payloads are never truly deleted from the cache, but instead have their // payload deleted and this flag set on their FaviconCacheElement. That way, the cache always // has a record of the existence of a primary payload, even if it is no longer in the cache. // This means that when a request comes in that will be best served using a primary that is in // the database but no longer cached, we know that it exists and can go get it (Useful when ICO // support is added). volatile boolean mInvalidated; final int mImageSize; // Used for LRU pruning. final FaviconsForURL mBackpointer; public FaviconCacheElement(Bitmap payload, boolean isPrimary, int imageSize, FaviconsForURL backpointer) { mFaviconPayload = payload; mIsPrimary = isPrimary; mImageSize = imageSize; mBackpointer = backpointer; } public FaviconCacheElement(Bitmap payload, boolean isPrimary, FaviconsForURL backpointer) { mFaviconPayload = payload; mIsPrimary = isPrimary; mBackpointer = backpointer; if (payload != null) { mImageSize = payload.getWidth(); } else { mImageSize = 0; } } public int sizeOf() { if (mInvalidated) { return 0; } return mFaviconPayload.getRowBytes() * mFaviconPayload.getHeight(); } /** * Establish an ordering on FaviconCacheElements based on size and validity. An element is * considered "greater than" another if it is valid and the other is not, or if it contains a * larger payload. * * @param another The FaviconCacheElement to compare to this one. * @return -1 if this element is less than the given one, 1 if the other one is larger than this * and 0 if both are of equal value. */ @Override public int compareTo(FaviconCacheElement another) { if (mInvalidated && !another.mInvalidated) { return -1; } if (!mInvalidated && another.mInvalidated) { return 1; } if (mInvalidated) { return 0; } final int w1 = mImageSize; final int w2 = another.mImageSize; if (w1 > w2) { return 1; } else if (w2 > w1) { return -1; } return 0; } /** * Called when this element is evicted from the cache. * * If primary, drop the payload and set invalid. If secondary, just unlink from parent node. */ public void onEvictedFromCache() { if (mIsPrimary) { // So we keep a record of which primaries exist in the database for this URL, we // don't actually delete the entry for primaries. Instead, we delete their payload // and flag them as invalid. This way, we can later figure out that what a request // really want is one of the primaries that have been dropped from the cache, and we // can go get it. mInvalidated = true; mFaviconPayload = null; } else { // Secondaries don't matter - just delete them. if (mBackpointer == null) { return; } mBackpointer.mFavicons.remove(this); } } }