1 /*
2  * Copyright (C) 2016 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 package libcore.util;
18 
19 import com.android.layoutlib.bridge.impl.DelegateManager;
20 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
21 
22 /**
23  * Delegate implementing the native methods of {@link NativeAllocationRegistry}
24  *
25  * Through the layoutlib_create tool, the original native methods of NativeAllocationRegistry have
26  * been replaced by calls to methods of the same name in this delegate class.
27  *
28  * This class behaves like the original native implementation, but in Java, keeping previously
29  * native data into its own objects and mapping them to int that are sent back and forth between
30  * it and the original NativeAllocationRegistry class.
31  *
32  * @see DelegateManager
33  */
34 public class NativeAllocationRegistry_Delegate {
35 
36     // ---- delegate manager ----
37     private static final DelegateManager<NativeAllocationRegistry_Delegate> sManager =
38             new DelegateManager<>(NativeAllocationRegistry_Delegate.class);
39 
40     private final FreeFunction mFinalizer;
41 
NativeAllocationRegistry_Delegate(FreeFunction finalizer)42     private NativeAllocationRegistry_Delegate(FreeFunction finalizer) {
43         mFinalizer = finalizer;
44     }
45 
46     /**
47      * The result of this method should be cached by the class and reused.
48      */
createFinalizer(FreeFunction finalizer)49     public static long createFinalizer(FreeFunction finalizer) {
50         return sManager.addNewDelegate(new NativeAllocationRegistry_Delegate(finalizer));
51     }
52 
53     @LayoutlibDelegate
registerNativeAllocation(long size)54     /*package*/ static void registerNativeAllocation(long size) {
55         NativeAllocationRegistry.registerNativeAllocation_Original(size);
56     }
57 
58     @LayoutlibDelegate
registerNativeAllocation(NativeAllocationRegistry registry, Object referent, long nativePtr)59     /*package*/ static Runnable registerNativeAllocation(NativeAllocationRegistry registry,
60             Object referent,
61             long nativePtr) {
62         // Mark the object as already "natively" tracked.
63         // This allows the DelegateManager to dispose objects without waiting
64         // for an explicit call when the referent does not exist anymore.
65         sManager.markAsNativeAllocation(referent, nativePtr);
66         return registry.registerNativeAllocation_Original(referent, nativePtr);
67     }
68 
69     @LayoutlibDelegate
applyFreeFunction(long freeFunction, long nativePtr)70     /*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) {
71         // This method MIGHT run in the context of the finalizer thread. If the delegate method
72         // crashes, it could bring down the VM. That's why we catch all the exceptions and ignore
73         // them.
74         try {
75             NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction);
76             if (delegate != null) {
77                 delegate.mFinalizer.free(nativePtr);
78             }
79         } catch (Throwable ignore) {
80         }
81     }
82 
83     public interface FreeFunction {
free(long nativePtr)84         void free(long nativePtr);
85     }
86 }
87