Merge "Implement VirtualRefBasePtr native methods" into nyc-dev

This commit is contained in:
Diego Perez
2016-03-31 08:14:25 +00:00
committed by Android (Google) Code Review
4 changed files with 105 additions and 18 deletions

View File

@@ -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);
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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 */

View File

@@ -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",
};