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