15d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/* 25d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Copyright (C) 2009 The Android Open Source Project 35d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 45d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Licensed under the Apache License, Version 2.0 (the "License"); 55d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * you may not use this file except in compliance with the License. 65d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * You may obtain a copy of the License at 75d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 85d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * http://www.apache.org/licenses/LICENSE-2.0 95d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Unless required by applicable law or agreed to in writing, software 115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * distributed under the License is distributed on an "AS IS" BASIS, 125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * See the License for the specific language governing permissions and 145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * limitations under the License. 155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.ref.ReferenceQueue; 185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.ref.PhantomReference; 195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.util.ArrayList; 205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaopublic class Bitmap { 225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao String mName; /* for debugging */ 235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao int mWidth, mHeight; 245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Bitmap.NativeWrapper mNativeWrapper; 255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static int sSerial = 100; 275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static ArrayList sPhantomList = new ArrayList<PhantomWrapper>(); 285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static ReferenceQueue<PhantomWrapper> sPhantomQueue = 295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao new ReferenceQueue<PhantomWrapper>(); 305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static BitmapWatcher sWatcher = new BitmapWatcher(sPhantomQueue); 315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao static { 32fa658b079d4795ec72867b7cc4561884714d69b7Dmitry Petrochenko sWatcher.setDaemon(true); 335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao sWatcher.start(); 345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao }; 355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Bitmap(String name, int width, int height, Bitmap.NativeWrapper nativeData) { 375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mName = name; 385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mWidth = width; 395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mHeight = height; 405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mNativeWrapper = nativeData; 415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("Created " + this); 435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public String toString() { 465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return "Bitmap " + mName + ": " + mWidth + "x" + mHeight + " (" + 475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mNativeWrapper.mNativeData + ")"; 485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public void drawAt(int x, int y) { 515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("Drawing " + this); 525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public static void shutDown() { 555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao sWatcher.shutDown(); 565d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao sWatcher.join(); 585d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (InterruptedException ie) { 595d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("join intr"); 605d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 615d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("Bitmap has shut down"); 625d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 635d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 645d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Pretend we're allocating native storage. Just returns a unique 665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * serial number. 675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 685d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao static Bitmap.NativeWrapper allocNativeStorage(int width, int height) { 695d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao int nativeData; 705d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 715d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao synchronized (Bitmap.class) { 725d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao nativeData = sSerial++; 735d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 745d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 755d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Bitmap.NativeWrapper wrapper = new Bitmap.NativeWrapper(nativeData); 765d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao PhantomWrapper phan = new PhantomWrapper(wrapper, sPhantomQueue, 775d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao nativeData); 785d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao sPhantomList.add(phan); 795d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return wrapper; 805d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 815d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 825d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao static void freeNativeStorage(int nativeDataPtr) { 835d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("freeNativeStorage: " + nativeDataPtr); 845d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 855d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 865d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 875d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Wraps a native data pointer in an object. When this object is no 885d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * longer referenced, we free the native data. 895d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 905d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao static class NativeWrapper { 915d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public NativeWrapper(int nativeDataPtr) { 925d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mNativeData = nativeDataPtr; 935d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 945d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public int mNativeData; 955d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 965d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 975d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao @Override 985d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao protected void finalize() throws Throwable { 995d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("finalized " + mNativeData); 1005d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1015d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1025d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1035d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao} 1045d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1055d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/* 1065d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Keep an eye on the native data. 1075d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 1085d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * We keep a copy of the native data pointer value, and set the wrapper 1095d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * as our referent. We need the copy because you can't get the referred-to 1105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * object back out of a PhantomReference. 1115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoclass PhantomWrapper extends PhantomReference { 1135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao PhantomWrapper(Bitmap.NativeWrapper wrapper, 1145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao ReferenceQueue<PhantomWrapper> queue, int nativeDataPtr) 1155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao { 1165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao super(wrapper, queue); 1175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mNativeData = nativeDataPtr; 1185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public int mNativeData; 1215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao} 1225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/* 1245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Thread that watches for un-referenced bitmap data. 1255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoclass BitmapWatcher extends Thread { 1275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao ReferenceQueue<PhantomWrapper> mQueue; 1285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao volatile boolean mQuit = false; 1295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) { 1315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mQueue = queue; 1325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao setName("Bitmap Watcher"); 1335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public void run() { 1365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao while (!mQuit) { 1375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao PhantomWrapper ref = (PhantomWrapper) mQueue.remove(); 1395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao //System.out.println("dequeued ref " + ref.mNativeData + 1405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao // " - " + ref); 1415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Bitmap.freeNativeStorage(ref.mNativeData); 1425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao //ref.clear(); 1435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (InterruptedException ie) { 1445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("intr"); 1455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public void shutDown() { 1505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao mQuit = true; 1515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao interrupt(); 1525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao} 154