Merge "Implement VirtualRefBasePtr native methods" into nyc-dev
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user