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