summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java53
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java52
-rw-r--r--tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java17
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java1
4 files changed, 105 insertions, 18 deletions
diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java
new file mode 100644
index 000000000000..01fe45d2644c
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.util.LongSparseLongArray;
+
+/**
+ * Delegate used to provide new implementation the native methods of {@link VirtualRefBasePtr}
+ *
+ * Through the layoutlib_create tool, the original native methods of VirtualRefBasePtr have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ */
+@SuppressWarnings("unused")
+public class VirtualRefBasePtr_Delegate {
+ private static final DelegateManager<Object> sManager = new DelegateManager<>(Object.class);
+ private static final LongSparseLongArray sRefCount = new LongSparseLongArray();
+
+ @LayoutlibDelegate
+ /*package*/ static synchronized void nIncStrong(long ptr) {
+ long counter = sRefCount.get(ptr);
+ sRefCount.put(ptr, ++counter);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static synchronized void nDecStrong(long ptr) {
+ long counter = sRefCount.get(ptr);
+
+ if (counter > 1) {
+ sRefCount.put(ptr, --counter);
+ } else {
+ sRefCount.delete(ptr);
+ sManager.removeJavaReferenceFor(ptr);
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index baf2e2e11564..c59b1a66bb02 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -22,9 +22,11 @@ import com.android.layoutlib.bridge.util.SparseWeakArray;
import android.annotation.Nullable;
import android.util.SparseArray;
+import java.io.PrintStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
/**
* Manages native delegates.
@@ -73,14 +75,14 @@ import java.util.List;
public final class DelegateManager<T> {
@SuppressWarnings("FieldCanBeLocal")
private final Class<T> mClass;
- private final SparseWeakArray<T> mDelegates = new SparseWeakArray<T>();
+ private static final SparseWeakArray<Object> sDelegates = new SparseWeakArray<>();
/** list used to store delegates when their main object holds a reference to them.
* This is to ensure that the WeakReference in the SparseWeakArray doesn't get GC'ed
* @see #addNewDelegate(Object)
* @see #removeJavaReferenceFor(long)
*/
- private final List<T> mJavaReferences = new ArrayList<T>();
- private int mDelegateCounter = 0;
+ private static final List<Object> sJavaReferences = new ArrayList<>();
+ private static final AtomicLong sDelegateCounter = new AtomicLong(1);
public DelegateManager(Class<T> theClass) {
mClass = theClass;
@@ -97,9 +99,12 @@ public final class DelegateManager<T> {
* @return the delegate or null if not found.
*/
@Nullable
- public synchronized T getDelegate(long native_object) {
+ public T getDelegate(long native_object) {
if (native_object > 0) {
- T delegate = mDelegates.get(native_object);
+ Object delegate;
+ synchronized (DelegateManager.class) {
+ delegate = sDelegates.get(native_object);
+ }
if (Debug.DEBUG) {
if (delegate == null) {
@@ -109,7 +114,8 @@ public final class DelegateManager<T> {
}
assert delegate != null;
- return delegate;
+ //noinspection unchecked
+ return (T)delegate;
}
return null;
}
@@ -119,12 +125,13 @@ public final class DelegateManager<T> {
* @param newDelegate the delegate to add
* @return a unique native int to identify the delegate
*/
- public synchronized long addNewDelegate(T newDelegate) {
- long native_object = ++mDelegateCounter;
-
- mDelegates.put(native_object, newDelegate);
- assert !mJavaReferences.contains(newDelegate);
- mJavaReferences.add(newDelegate);
+ public long addNewDelegate(T newDelegate) {
+ long native_object = sDelegateCounter.getAndIncrement();
+ synchronized (DelegateManager.class) {
+ sDelegates.put(native_object, newDelegate);
+ assert !sJavaReferences.contains(newDelegate);
+ sJavaReferences.add(newDelegate);
+ }
if (Debug.DEBUG) {
System.out.println(
@@ -140,14 +147,23 @@ public final class DelegateManager<T> {
* Removes the main reference on the given delegate.
* @param native_object the native integer representing the delegate.
*/
- public synchronized void removeJavaReferenceFor(long native_object) {
- T delegate = getDelegate(native_object);
+ public void removeJavaReferenceFor(long native_object) {
+ synchronized (DelegateManager.class) {
+ T delegate = getDelegate(native_object);
- if (Debug.DEBUG) {
- System.out.println("Removing main Java ref on " + mClass.getSimpleName() +
- " with int " + native_object);
+ if (Debug.DEBUG) {
+ System.out.println("Removing main Java ref on " + mClass.getSimpleName() +
+ " with int " + native_object);
+ }
+
+ sJavaReferences.remove(delegate);
}
+ }
- mJavaReferences.remove(delegate);
+ public synchronized static void dump(PrintStream out) {
+ for (Object reference : sJavaReferences) {
+ int idx = sDelegates.indexOfValue(reference);
+ out.printf("[%d] %s\n", sDelegates.keyAt(idx), reference.getClass().getSimpleName());
+ }
}
}
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index a5561fab953c..09dd5f078b9a 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -31,6 +31,7 @@ import com.android.io.FolderWrapper;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.impl.RenderAction;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback;
import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
@@ -52,6 +53,7 @@ import android.util.DisplayMetrics;
import java.io.File;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@@ -298,6 +300,16 @@ public class Main {
renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012);
}
+ private static void gc() {
+ // See RuntimeUtil#gc in jlibs (http://jlibs.in/)
+ Object obj = new Object();
+ WeakReference ref = new WeakReference<Object>(obj);
+ obj = null;
+ while(ref.get() != null) {
+ System.gc();
+ }
+ }
+
@AfterClass
public static void tearDown() {
sLayoutLibLog = null;
@@ -305,6 +317,11 @@ public class Main {
sProjectResources = null;
sLogger = null;
sBridge = null;
+
+ gc();
+
+ System.out.println("Objects still linked from the DelegateManager:");
+ DelegateManager.dump(System.out);
}
/** Test expand_layout.xml */
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 1a00cc942c42..483bddc21859 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -302,6 +302,7 @@ public final class CreateInfo implements ICreateInfo {
"android.text.StaticLayout",
"android.util.PathParser",
"android.view.Display",
+ "com.android.internal.util.VirtualRefBasePtr",
"com.android.internal.view.animation.NativeInterpolatorFactoryHelper",
"libcore.icu.ICU",
};