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.setDaemon(true);
     33         sWatcher.start();
     34     };
     35 
     36     Bitmap(String name, int width, int height, Bitmap.NativeWrapper nativeData) {
     37         mName = name;
     38         mWidth = width;
     39         mHeight = height;
     40         mNativeWrapper = nativeData;
     41 
     42         System.out.println("Created " + this);
     43     }
     44 
     45     public String toString() {
     46         return "Bitmap " + mName + ": " + mWidth + "x" + mHeight + " (" +
     47                 mNativeWrapper.mNativeData + ")";
     48     }
     49 
     50     public void drawAt(int x, int y) {
     51         System.out.println("Drawing " + this);
     52     }
     53 
     54     public static void shutDown() {
     55         sWatcher.shutDown();
     56         try {
     57             sWatcher.join();
     58         } catch (InterruptedException ie) {
     59             System.out.println("join intr");
     60         }
     61         System.out.println("Bitmap has shut down");
     62     }
     63 
     64     /*
     65      * Pretend we're allocating native storage.  Just returns a unique
     66      * serial number.
     67      */
     68     static Bitmap.NativeWrapper allocNativeStorage(int width, int height) {
     69         int nativeData;
     70 
     71         synchronized (Bitmap.class) {
     72             nativeData = sSerial++;
     73         }
     74 
     75         Bitmap.NativeWrapper wrapper = new Bitmap.NativeWrapper(nativeData);
     76         PhantomWrapper phan = new PhantomWrapper(wrapper, sPhantomQueue,
     77                 nativeData);
     78         sPhantomList.add(phan);
     79         return wrapper;
     80     }
     81 
     82     static void freeNativeStorage(int nativeDataPtr) {
     83         System.out.println("freeNativeStorage: " + nativeDataPtr);
     84     }
     85 
     86     /*
     87      * Wraps a native data pointer in an object.  When this object is no
     88      * longer referenced, we free the native data.
     89      */
     90     static class NativeWrapper {
     91         public NativeWrapper(int nativeDataPtr) {
     92             mNativeData = nativeDataPtr;
     93         }
     94         public int mNativeData;
     95 
     96         /*
     97         @Override
     98         protected void finalize() throws Throwable {
     99             System.out.println("finalized " + mNativeData);
    100         }
    101         */
    102     }
    103 }
    104 
    105 /*
    106  * Keep an eye on the native data.
    107  *
    108  * We keep a copy of the native data pointer value, and set the wrapper
    109  * as our referent.  We need the copy because you can't get the referred-to
    110  * object back out of a PhantomReference.
    111  */
    112 class PhantomWrapper extends PhantomReference {
    113     PhantomWrapper(Bitmap.NativeWrapper wrapper,
    114         ReferenceQueue<PhantomWrapper> queue, int nativeDataPtr)
    115     {
    116         super(wrapper, queue);
    117         mNativeData = nativeDataPtr;
    118     }
    119 
    120     public int mNativeData;
    121 }
    122 
    123 /*
    124  * Thread that watches for un-referenced bitmap data.
    125  */
    126 class BitmapWatcher extends Thread {
    127     ReferenceQueue<PhantomWrapper> mQueue;
    128 
    129     BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) {
    130         mQueue = queue;
    131         setName("Bitmap Watcher");
    132     }
    133 
    134     public void run() {
    135         while (true) {
    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                 break;
    145             }
    146         }
    147     }
    148 
    149     public void shutDown() {
    150         interrupt();
    151     }
    152 }
    153