blob: 9d03cbd3d4d9237062c10b979fdf3720b98f5a8b [file] [log] [blame]
jeffhao5d1ac922011-09-29 17:41:15 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import java.lang.ref.ReferenceQueue;
18import java.lang.ref.PhantomReference;
19import java.util.ArrayList;
20
21public class Bitmap {
22 String mName; /* for debugging */
23 int mWidth, mHeight;
24 Bitmap.NativeWrapper mNativeWrapper;
25
26 private static int sSerial = 100;
27 private static ArrayList sPhantomList = new ArrayList<PhantomWrapper>();
28 private static ReferenceQueue<PhantomWrapper> sPhantomQueue =
29 new ReferenceQueue<PhantomWrapper>();
30 private static BitmapWatcher sWatcher = new BitmapWatcher(sPhantomQueue);
31 static {
32 sWatcher.start();
33 };
34
35 Bitmap(String name, int width, int height, Bitmap.NativeWrapper nativeData) {
36 mName = name;
37 mWidth = width;
38 mHeight = height;
39 mNativeWrapper = nativeData;
40
41 System.out.println("Created " + this);
42 }
43
44 public String toString() {
45 return "Bitmap " + mName + ": " + mWidth + "x" + mHeight + " (" +
46 mNativeWrapper.mNativeData + ")";
47 }
48
49 public void drawAt(int x, int y) {
50 System.out.println("Drawing " + this);
51 }
52
53 public static void shutDown() {
54 sWatcher.shutDown();
55 try {
56 sWatcher.join();
57 } catch (InterruptedException ie) {
58 System.out.println("join intr");
59 }
60 System.out.println("Bitmap has shut down");
61 }
62
63 /*
64 * Pretend we're allocating native storage. Just returns a unique
65 * serial number.
66 */
67 static Bitmap.NativeWrapper allocNativeStorage(int width, int height) {
68 int nativeData;
69
70 synchronized (Bitmap.class) {
71 nativeData = sSerial++;
72 }
73
74 Bitmap.NativeWrapper wrapper = new Bitmap.NativeWrapper(nativeData);
75 PhantomWrapper phan = new PhantomWrapper(wrapper, sPhantomQueue,
76 nativeData);
77 sPhantomList.add(phan);
78 return wrapper;
79 }
80
81 static void freeNativeStorage(int nativeDataPtr) {
82 System.out.println("freeNativeStorage: " + nativeDataPtr);
83 }
84
85 /*
86 * Wraps a native data pointer in an object. When this object is no
87 * longer referenced, we free the native data.
88 */
89 static class NativeWrapper {
90 public NativeWrapper(int nativeDataPtr) {
91 mNativeData = nativeDataPtr;
92 }
93 public int mNativeData;
94
95 /*
96 @Override
97 protected void finalize() throws Throwable {
98 System.out.println("finalized " + mNativeData);
99 }
100 */
101 }
102}
103
104/*
105 * Keep an eye on the native data.
106 *
107 * We keep a copy of the native data pointer value, and set the wrapper
108 * as our referent. We need the copy because you can't get the referred-to
109 * object back out of a PhantomReference.
110 */
111class PhantomWrapper extends PhantomReference {
112 PhantomWrapper(Bitmap.NativeWrapper wrapper,
113 ReferenceQueue<PhantomWrapper> queue, int nativeDataPtr)
114 {
115 super(wrapper, queue);
116 mNativeData = nativeDataPtr;
117 }
118
119 public int mNativeData;
120}
121
122/*
123 * Thread that watches for un-referenced bitmap data.
124 */
125class BitmapWatcher extends Thread {
126 ReferenceQueue<PhantomWrapper> mQueue;
127 volatile boolean mQuit = false;
128
129 BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) {
130 mQueue = queue;
131 setName("Bitmap Watcher");
132 }
133
134 public void run() {
135 while (!mQuit) {
136 try {
137 PhantomWrapper ref = (PhantomWrapper) mQueue.remove();
138 //System.out.println("dequeued ref " + ref.mNativeData +
139 // " - " + ref);
140 Bitmap.freeNativeStorage(ref.mNativeData);
141 //ref.clear();
142 } catch (InterruptedException ie) {
143 System.out.println("intr");
144 }
145 }
146 }
147
148 public void shutDown() {
149 mQuit = true;
150 interrupt();
151 }
152}