xref: /aosp_15_r20/art/test/079-phantom/src/Bitmap.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2009 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.ref.ReferenceQueue;
18*795d594fSAndroid Build Coastguard Worker import java.lang.ref.PhantomReference;
19*795d594fSAndroid Build Coastguard Worker import java.util.ArrayList;
20*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.CountDownLatch;
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker public class Bitmap {
23*795d594fSAndroid Build Coastguard Worker     String mName;           /* for debugging */
24*795d594fSAndroid Build Coastguard Worker     int mWidth, mHeight;
25*795d594fSAndroid Build Coastguard Worker     Bitmap.NativeWrapper mNativeWrapper;
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker     private static int sSerial = 100;
28*795d594fSAndroid Build Coastguard Worker     private static ArrayList sPhantomList = new ArrayList<PhantomWrapper>();
29*795d594fSAndroid Build Coastguard Worker     private static ReferenceQueue<PhantomWrapper> sPhantomQueue =
30*795d594fSAndroid Build Coastguard Worker             new ReferenceQueue<PhantomWrapper>();
31*795d594fSAndroid Build Coastguard Worker     private static BitmapWatcher sWatcher = new BitmapWatcher(sPhantomQueue);
32*795d594fSAndroid Build Coastguard Worker     static {
33*795d594fSAndroid Build Coastguard Worker         sWatcher.setDaemon(true);
sWatcher.start()34*795d594fSAndroid Build Coastguard Worker         sWatcher.start();
35*795d594fSAndroid Build Coastguard Worker     };
36*795d594fSAndroid Build Coastguard Worker 
Bitmap(String name, int width, int height, Bitmap.NativeWrapper nativeData)37*795d594fSAndroid Build Coastguard Worker     Bitmap(String name, int width, int height, Bitmap.NativeWrapper nativeData) {
38*795d594fSAndroid Build Coastguard Worker         mName = name;
39*795d594fSAndroid Build Coastguard Worker         mWidth = width;
40*795d594fSAndroid Build Coastguard Worker         mHeight = height;
41*795d594fSAndroid Build Coastguard Worker         mNativeWrapper = nativeData;
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker         System.out.println("Created " + this);
44*795d594fSAndroid Build Coastguard Worker     }
45*795d594fSAndroid Build Coastguard Worker 
toString()46*795d594fSAndroid Build Coastguard Worker     public String toString() {
47*795d594fSAndroid Build Coastguard Worker         return "Bitmap " + mName + ": " + mWidth + "x" + mHeight + " (" +
48*795d594fSAndroid Build Coastguard Worker                 mNativeWrapper.mNativeData + ")";
49*795d594fSAndroid Build Coastguard Worker     }
50*795d594fSAndroid Build Coastguard Worker 
drawAt(int x, int y)51*795d594fSAndroid Build Coastguard Worker     public void drawAt(int x, int y) {
52*795d594fSAndroid Build Coastguard Worker         System.out.println("Drawing " + this);
53*795d594fSAndroid Build Coastguard Worker     }
54*795d594fSAndroid Build Coastguard Worker 
shutDown()55*795d594fSAndroid Build Coastguard Worker     public static void shutDown() {
56*795d594fSAndroid Build Coastguard Worker         sWatcher.shutDown();
57*795d594fSAndroid Build Coastguard Worker         try {
58*795d594fSAndroid Build Coastguard Worker             sWatcher.join();
59*795d594fSAndroid Build Coastguard Worker         } catch (InterruptedException ie) {
60*795d594fSAndroid Build Coastguard Worker             System.out.println("join intr");
61*795d594fSAndroid Build Coastguard Worker         }
62*795d594fSAndroid Build Coastguard Worker         System.out.println("Bitmap has shut down");
63*795d594fSAndroid Build Coastguard Worker     }
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker     /*
66*795d594fSAndroid Build Coastguard Worker      * Pretend we're allocating native storage.  Just returns a unique
67*795d594fSAndroid Build Coastguard Worker      * serial number.
68*795d594fSAndroid Build Coastguard Worker      */
allocNativeStorage(int width, int height)69*795d594fSAndroid Build Coastguard Worker     static Bitmap.NativeWrapper allocNativeStorage(int width, int height) {
70*795d594fSAndroid Build Coastguard Worker         int nativeData;
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker         synchronized (Bitmap.class) {
73*795d594fSAndroid Build Coastguard Worker             nativeData = sSerial++;
74*795d594fSAndroid Build Coastguard Worker         }
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker         Bitmap.NativeWrapper wrapper = new Bitmap.NativeWrapper(nativeData);
77*795d594fSAndroid Build Coastguard Worker         PhantomWrapper phan = new PhantomWrapper(wrapper, sPhantomQueue,
78*795d594fSAndroid Build Coastguard Worker                 nativeData);
79*795d594fSAndroid Build Coastguard Worker         sPhantomList.add(phan);
80*795d594fSAndroid Build Coastguard Worker         wrapper.mPhantomWrapper = phan;
81*795d594fSAndroid Build Coastguard Worker         return wrapper;
82*795d594fSAndroid Build Coastguard Worker     }
83*795d594fSAndroid Build Coastguard Worker 
freeNativeStorage(int nativeDataPtr, CountDownLatch freeSignal)84*795d594fSAndroid Build Coastguard Worker     static void freeNativeStorage(int nativeDataPtr, CountDownLatch freeSignal) {
85*795d594fSAndroid Build Coastguard Worker         System.out.println("freeNativeStorage: " + nativeDataPtr);
86*795d594fSAndroid Build Coastguard Worker         // Wake up the main thread that is [or will be] blocked until this native data is freed.
87*795d594fSAndroid Build Coastguard Worker         freeSignal.countDown();
88*795d594fSAndroid Build Coastguard Worker     }
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker     /*
91*795d594fSAndroid Build Coastguard Worker      * Wraps a native data pointer in an object.  When this object is no
92*795d594fSAndroid Build Coastguard Worker      * longer referenced, we free the native data.
93*795d594fSAndroid Build Coastguard Worker      */
94*795d594fSAndroid Build Coastguard Worker     static class NativeWrapper {
NativeWrapper(int nativeDataPtr)95*795d594fSAndroid Build Coastguard Worker         public NativeWrapper(int nativeDataPtr) {
96*795d594fSAndroid Build Coastguard Worker             mNativeData = nativeDataPtr;
97*795d594fSAndroid Build Coastguard Worker         }
98*795d594fSAndroid Build Coastguard Worker         public int mNativeData;
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker         // The PhantomWrapper corresponding to this NativeWrapper.
101*795d594fSAndroid Build Coastguard Worker         public PhantomWrapper mPhantomWrapper;
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker         /*
104*795d594fSAndroid Build Coastguard Worker         @Override
105*795d594fSAndroid Build Coastguard Worker         protected void finalize() throws Throwable {
106*795d594fSAndroid Build Coastguard Worker             System.out.println("finalized " + mNativeData);
107*795d594fSAndroid Build Coastguard Worker         }
108*795d594fSAndroid Build Coastguard Worker         */
109*795d594fSAndroid Build Coastguard Worker     }
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker /*
113*795d594fSAndroid Build Coastguard Worker  * Keep an eye on the native data.
114*795d594fSAndroid Build Coastguard Worker  *
115*795d594fSAndroid Build Coastguard Worker  * We keep a copy of the native data pointer value, and set the wrapper
116*795d594fSAndroid Build Coastguard Worker  * as our referent.  We need the copy because you can't get the referred-to
117*795d594fSAndroid Build Coastguard Worker  * object back out of a PhantomReference.
118*795d594fSAndroid Build Coastguard Worker  */
119*795d594fSAndroid Build Coastguard Worker class PhantomWrapper extends PhantomReference {
PhantomWrapper(Bitmap.NativeWrapper wrapper, ReferenceQueue<PhantomWrapper> queue, int nativeDataPtr)120*795d594fSAndroid Build Coastguard Worker     PhantomWrapper(Bitmap.NativeWrapper wrapper,
121*795d594fSAndroid Build Coastguard Worker         ReferenceQueue<PhantomWrapper> queue, int nativeDataPtr)
122*795d594fSAndroid Build Coastguard Worker     {
123*795d594fSAndroid Build Coastguard Worker         super(wrapper, queue);
124*795d594fSAndroid Build Coastguard Worker         mNativeData = nativeDataPtr;
125*795d594fSAndroid Build Coastguard Worker     }
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker     public int mNativeData;
128*795d594fSAndroid Build Coastguard Worker     // This will be signaled once mNativeData has been freed.
129*795d594fSAndroid Build Coastguard Worker     public CountDownLatch mFreeSignal = new CountDownLatch(1);
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker /*
133*795d594fSAndroid Build Coastguard Worker  * Thread that watches for un-referenced bitmap data.
134*795d594fSAndroid Build Coastguard Worker  */
135*795d594fSAndroid Build Coastguard Worker class BitmapWatcher extends Thread {
136*795d594fSAndroid Build Coastguard Worker     ReferenceQueue<PhantomWrapper> mQueue;
137*795d594fSAndroid Build Coastguard Worker 
BitmapWatcher(ReferenceQueue<PhantomWrapper> queue)138*795d594fSAndroid Build Coastguard Worker     BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) {
139*795d594fSAndroid Build Coastguard Worker         mQueue = queue;
140*795d594fSAndroid Build Coastguard Worker         setName("Bitmap Watcher");
141*795d594fSAndroid Build Coastguard Worker     }
142*795d594fSAndroid Build Coastguard Worker 
run()143*795d594fSAndroid Build Coastguard Worker     public void run() {
144*795d594fSAndroid Build Coastguard Worker         while (true) {
145*795d594fSAndroid Build Coastguard Worker             try {
146*795d594fSAndroid Build Coastguard Worker                 PhantomWrapper ref = (PhantomWrapper) mQueue.remove();
147*795d594fSAndroid Build Coastguard Worker                 //System.out.println("dequeued ref " + ref.mNativeData +
148*795d594fSAndroid Build Coastguard Worker                 //    " - " + ref);
149*795d594fSAndroid Build Coastguard Worker                 Bitmap.freeNativeStorage(ref.mNativeData, ref.mFreeSignal);
150*795d594fSAndroid Build Coastguard Worker             } catch (InterruptedException ie) {
151*795d594fSAndroid Build Coastguard Worker                 System.out.println("intr");
152*795d594fSAndroid Build Coastguard Worker                 break;
153*795d594fSAndroid Build Coastguard Worker             }
154*795d594fSAndroid Build Coastguard Worker         }
155*795d594fSAndroid Build Coastguard Worker     }
156*795d594fSAndroid Build Coastguard Worker 
shutDown()157*795d594fSAndroid Build Coastguard Worker     public void shutDown() {
158*795d594fSAndroid Build Coastguard Worker         interrupt();
159*795d594fSAndroid Build Coastguard Worker     }
160*795d594fSAndroid Build Coastguard Worker }
161