Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.favicons.cache;
7 import android.graphics.Bitmap;
9 /**
10 * Objects stored in the Favicon cache - allow for the bitmap to be tagged to indicate if it has
11 * been scaled. Unscaled bitmaps are not included in the scaled-bitmap cache's size calculation.
12 */
13 public class FaviconCacheElement implements Comparable<FaviconCacheElement> {
14 // Was this Favicon computed via scaling another primary Favicon, or is this a primary Favicon?
15 final boolean isPrimary;
17 // The Favicon bitmap.
18 Bitmap faviconPayload;
20 // If set, faviconPayload is absent. Since the underlying ICO may contain multiple primary
21 // payloads, primary payloads are never truly deleted from the cache, but instead have their
22 // payload deleted and this flag set on their FaviconCacheElement. That way, the cache always
23 // has a record of the existence of a primary payload, even if it is no longer in the cache.
24 // This means that when a request comes in that will be best served using a primary that is in
25 // the database but no longer cached, we know that it exists and can go get it (Useful when ICO
26 // support is added).
27 volatile boolean invalidated;
29 final int imageSize;
31 // Used for LRU pruning.
32 final FaviconsForURL backpointer;
34 public FaviconCacheElement(Bitmap payload, boolean primary, int size, FaviconsForURL backpointer) {
35 this.faviconPayload = payload;
36 this.isPrimary = primary;
37 this.imageSize = size;
38 this.backpointer = backpointer;
39 }
41 public FaviconCacheElement(Bitmap faviconPayload, boolean isPrimary, FaviconsForURL backpointer) {
42 this.faviconPayload = faviconPayload;
43 this.isPrimary = isPrimary;
44 this.backpointer = backpointer;
46 if (faviconPayload != null) {
47 imageSize = faviconPayload.getWidth();
48 } else {
49 imageSize = 0;
50 }
51 }
53 public int sizeOf() {
54 if (invalidated) {
55 return 0;
56 }
57 return faviconPayload.getRowBytes() * faviconPayload.getHeight();
58 }
60 /**
61 * Establish an ordering on FaviconCacheElements based on size and validity. An element is
62 * considered "greater than" another if it is valid and the other is not, or if it contains a
63 * larger payload.
64 *
65 * @param another The FaviconCacheElement to compare to this one.
66 * @return -1 if this element is less than the given one, 1 if the other one is larger than this
67 * and 0 if both are of equal value.
68 */
69 @Override
70 public int compareTo(FaviconCacheElement another) {
71 if (invalidated && !another.invalidated) {
72 return -1;
73 }
75 if (!invalidated && another.invalidated) {
76 return 1;
77 }
79 if (invalidated) {
80 return 0;
81 }
83 final int w1 = imageSize;
84 final int w2 = another.imageSize;
85 if (w1 > w2) {
86 return 1;
87 } else if (w2 > w1) {
88 return -1;
89 }
90 return 0;
91 }
93 /**
94 * Called when this element is evicted from the cache.
95 *
96 * If primary, drop the payload and set invalid. If secondary, just unlink from parent node.
97 */
98 public void onEvictedFromCache() {
99 if (isPrimary) {
100 // So we keep a record of which primaries exist in the database for this URL, we
101 // don't actually delete the entry for primaries. Instead, we delete their payload
102 // and flag them as invalid. This way, we can later figure out that what a request
103 // really want is one of the primaries that have been dropped from the cache, and we
104 // can go get it.
105 invalidated = true;
106 faviconPayload = null;
107 } else {
108 // Secondaries don't matter - just delete them.
109 if (backpointer == null) {
110 return;
111 }
112 backpointer.favicons.remove(this);
113 }
114 }
115 }