Home | History | Annotate | Download | only in src
      1 /*
      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 
     17 import java.lang.ref.ReferenceQueue;
     18 import java.lang.ref.PhantomReference;
     19 import java.util.ArrayList;
     20 
     21 public 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  */
    111 class 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  */
    125 class 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 }
    153