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
1295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) {
1305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        mQueue = queue;
1315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        setName("Bitmap Watcher");
1325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public void run() {
13510cd86bf39484102a7ed9aebef37fd55f0addba1randy.jeong        while (true) {
1365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            try {
1375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                PhantomWrapper ref = (PhantomWrapper) mQueue.remove();
1385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                //System.out.println("dequeued ref " + ref.mNativeData +
1395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                //    " - " + ref);
1405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                Bitmap.freeNativeStorage(ref.mNativeData);
1415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                //ref.clear();
1425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            } catch (InterruptedException ie) {
1435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                System.out.println("intr");
14410cd86bf39484102a7ed9aebef37fd55f0addba1randy.jeong                break;
1455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            }
1465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
1475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public void shutDown() {
1505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        interrupt();
1515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao}
153