|
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/. */ |
|
4 |
|
5 package org.mozilla.gecko.favicons.cache; |
|
6 |
|
7 import android.graphics.Bitmap; |
|
8 |
|
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; |
|
16 |
|
17 // The Favicon bitmap. |
|
18 Bitmap faviconPayload; |
|
19 |
|
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; |
|
28 |
|
29 final int imageSize; |
|
30 |
|
31 // Used for LRU pruning. |
|
32 final FaviconsForURL backpointer; |
|
33 |
|
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 } |
|
40 |
|
41 public FaviconCacheElement(Bitmap faviconPayload, boolean isPrimary, FaviconsForURL backpointer) { |
|
42 this.faviconPayload = faviconPayload; |
|
43 this.isPrimary = isPrimary; |
|
44 this.backpointer = backpointer; |
|
45 |
|
46 if (faviconPayload != null) { |
|
47 imageSize = faviconPayload.getWidth(); |
|
48 } else { |
|
49 imageSize = 0; |
|
50 } |
|
51 } |
|
52 |
|
53 public int sizeOf() { |
|
54 if (invalidated) { |
|
55 return 0; |
|
56 } |
|
57 return faviconPayload.getRowBytes() * faviconPayload.getHeight(); |
|
58 } |
|
59 |
|
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 } |
|
74 |
|
75 if (!invalidated && another.invalidated) { |
|
76 return 1; |
|
77 } |
|
78 |
|
79 if (invalidated) { |
|
80 return 0; |
|
81 } |
|
82 |
|
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 } |
|
92 |
|
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 } |