diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java index f073c1c046c58..2bfde242a9871 100755 --- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java +++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java @@ -22,36 +22,24 @@ import static com.android.internal.util.function.pooled.PooledLambdaImpl.acquire import android.os.Message; import com.android.internal.util.function.DecConsumer; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.DodecConsumer; -import com.android.internal.util.function.DodecFunction; import com.android.internal.util.function.HeptConsumer; -import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexConsumer; -import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.NonaConsumer; -import com.android.internal.util.function.NonaFunction; import com.android.internal.util.function.OctConsumer; -import com.android.internal.util.function.OctFunction; import com.android.internal.util.function.QuadConsumer; -import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuadPredicate; import com.android.internal.util.function.QuintConsumer; -import com.android.internal.util.function.QuintFunction; import com.android.internal.util.function.QuintPredicate; import com.android.internal.util.function.TriConsumer; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.TriPredicate; import com.android.internal.util.function.UndecConsumer; -import com.android.internal.util.function.UndecFunction; import com.android.internal.util.function.pooled.PooledLambdaImpl.LambdaType.ReturnType; import java.util.function.BiConsumer; -import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Predicate; import java.util.function.Supplier; /** @@ -193,40 +181,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1) } - */ - static PooledSupplier obtainSupplier( - Predicate function, - A arg1) { - return acquire(PooledLambdaImpl.sPool, - function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null, - null, null, null, null); - } - - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1) } - */ - static PooledSupplier obtainSupplier( - Function function, - A arg1) { - return acquire(PooledLambdaImpl.sPool, - function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -278,42 +232,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2) } - */ - static PooledSupplier obtainSupplier( - BiPredicate function, - A arg1, B arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2) } - */ - static PooledSupplier obtainSupplier( - BiFunction function, - A arg1, B arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -410,24 +328,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 placeholder for a missing argument. Use {@link #__} to get one - * @param arg2 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg1) -> function(arg1, arg2) } - */ - static PooledFunction obtainFunction( - BiFunction function, - ArgumentPlaceholder arg1, B arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -464,24 +364,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 placeholder for a missing argument. Use {@link #__} to get one - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg2) -> function(arg1, arg2) } - */ - static PooledFunction obtainFunction( - BiFunction function, - A arg1, ArgumentPlaceholder arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -535,25 +417,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3) } - */ - static PooledSupplier obtainSupplier( - TriFunction function, - A arg1, B arg2, C arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -573,25 +436,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 placeholder for a missing argument. Use {@link #__} to get one - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg1) -> function(arg1, arg2, arg3) } - */ - static PooledFunction obtainFunction( - TriFunction function, - ArgumentPlaceholder arg1, B arg2, C arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -611,25 +455,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 placeholder for a missing argument. Use {@link #__} to get one - * @param arg3 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg2) -> function(arg1, arg2, arg3) } - */ - static PooledFunction obtainFunction( - TriFunction function, - A arg1, ArgumentPlaceholder arg2, C arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -649,25 +474,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 placeholder for a missing argument. Use {@link #__} to get one - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg3) -> function(arg1, arg2, arg3) } - */ - static PooledFunction obtainFunction( - TriFunction function, - A arg1, B arg2, ArgumentPlaceholder arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -723,26 +529,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4) } - */ - static PooledSupplier obtainSupplier( - QuadFunction function, - A arg1, B arg2, C arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -763,26 +549,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 placeholder for a missing argument. Use {@link #__} to get one - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg1) -> function(arg1, arg2, arg3, arg4) } - */ - static PooledFunction obtainFunction( - QuadFunction function, - ArgumentPlaceholder arg1, B arg2, C arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -803,26 +569,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 placeholder for a missing argument. Use {@link #__} to get one - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg2) -> function(arg1, arg2, arg3, arg4) } - */ - static PooledFunction obtainFunction( - QuadFunction function, - A arg1, ArgumentPlaceholder arg2, C arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -843,26 +589,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 placeholder for a missing argument. Use {@link #__} to get one - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg3) -> function(arg1, arg2, arg3, arg4) } - */ - static PooledFunction obtainFunction( - QuadFunction function, - A arg1, B arg2, ArgumentPlaceholder arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - /** * {@link PooledConsumer} factory * @@ -883,26 +609,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 placeholder for a missing argument. Use {@link #__} to get one - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg4) -> function(arg1, arg2, arg3, arg4) } - */ - static PooledFunction obtainFunction( - QuadFunction function, - A arg1, B arg2, C arg3, ArgumentPlaceholder arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -960,27 +666,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5) } - */ - static PooledSupplier obtainSupplier( - QuintFunction - function, A arg1, B arg2, C arg3, D arg4, E arg5) { - return acquire(PooledLambdaImpl.sPool, - function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -1041,28 +726,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6) } - */ - static PooledSupplier obtainSupplier( - HexFunction function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) { - return acquire(PooledLambdaImpl.sPool, - function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -1125,30 +788,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7) } - */ - static PooledSupplier obtainSupplier( - HeptFunction function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) { - return acquire(PooledLambdaImpl.sPool, - function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -1214,31 +853,6 @@ public interface PooledLambda { null, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) } - */ - static PooledSupplier obtainSupplier( - OctFunction function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) { - return acquire(PooledLambdaImpl.sPool, - function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - null, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -1307,32 +921,6 @@ public interface PooledLambda { arg9, null, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) } - */ - static PooledSupplier obtainSupplier( - NonaFunction function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) { - return acquire(PooledLambdaImpl.sPool, - function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, null, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -1403,33 +991,6 @@ public interface PooledLambda { arg9, arg10, null, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @param arg10 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) } - */ - static PooledSupplier obtainSupplier( - DecFunction function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) { - return acquire(PooledLambdaImpl.sPool, - function, 10, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, arg10, null, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -1503,36 +1064,6 @@ public interface PooledLambda { arg9, arg10, arg11, null); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @param arg10 parameter supplied to {@code function} on call - * @param arg11 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, - * arg11) } - */ - static PooledSupplier obtainSupplier( - UndecFunction function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, - K arg11) { - return acquire(PooledLambdaImpl.sPool, - function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, arg10, arg11, null); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its @@ -1610,38 +1141,6 @@ public interface PooledLambda { arg9, arg10, arg11, arg12); } - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @param arg10 parameter supplied to {@code function} on call - * @param arg11 parameter supplied to {@code function} on call - * @param arg12 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, - * arg11) } - */ - static PooledSupplier obtainSupplier( - DodecFunction function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, - K arg11, L arg12) { - return acquire(PooledLambdaImpl.sPool, - function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, arg10, arg11, arg12); - } - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its diff --git a/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java b/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java index 388548691b775..2001c04bd6451 100644 --- a/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java +++ b/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java @@ -1,454 +1,458 @@ -/* - * Copyright (C) 2020 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; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - -import android.app.Activity; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.Message; -import android.os.ParcelFileDescriptor; -import android.os.Process; -import android.os.SystemClock; -import android.util.Log; - -import androidx.test.filters.LargeTest; - -import com.android.internal.util.function.pooled.PooledConsumer; -import com.android.internal.util.function.pooled.PooledLambda; -import com.android.internal.util.function.pooled.PooledPredicate; - -import org.junit.Assume; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.runners.model.Statement; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.function.Consumer; -import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** Compares the performance of regular lambda and pooled lambda. */ -@LargeTest -public class LambdaPerfTest { - private static final boolean DEBUG = false; - private static final String TAG = LambdaPerfTest.class.getSimpleName(); - - private static final String LAMBDA_FORM_REGULAR = "regular"; - private static final String LAMBDA_FORM_POOLED = "pooled"; - - private static final int WARMUP_ITERATIONS = 1000; - private static final int TEST_ITERATIONS = 3000000; - private static final int TASK_COUNT = 10; - private static final long DELAY_AFTER_BENCH_MS = 1000; - - private String mMethodName; - - private final Bundle mTestResults = new Bundle(); - private final ArrayList mTasks = new ArrayList<>(); - - // The member fields are used to ensure lambda capturing. They don't have the actual meaning. - private final Task mTask = new Task(); - private final Rect mBounds = new Rect(); - private int mTaskId; - private long mTime; - private boolean mTop; - - @Rule - public final TestRule mRule = (base, description) -> new Statement() { - @Override - public void evaluate() throws Throwable { - mMethodName = description.getMethodName(); - mTasks.clear(); - for (int i = 0; i < TASK_COUNT; i++) { - final Task t = new Task(); - mTasks.add(t); - } - base.evaluate(); - - getInstrumentation().sendStatus(Activity.RESULT_OK, mTestResults); - } - }; - - @Test - public void test1ParamConsumer() { - evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTask))); - evaluate(LAMBDA_FORM_POOLED, () -> { - final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, - PooledLambda.__(Task.class), mTask); - forAllTask(c); - c.recycle(); - }); - } - - @Test - public void test2PrimitiveParamsConsumer() { - // Not in Integer#IntegerCache (-128~127) for autoboxing, that will create new object. - mTaskId = 12345; - mTime = 54321; - - evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTaskId, mTime))); - evaluate(LAMBDA_FORM_POOLED, () -> { - final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, - PooledLambda.__(Task.class), mTaskId, mTime); - forAllTask(c); - c.recycle(); - }); - } - - @Test - public void test3ParamsPredicate() { - mTop = true; - // In Integer#IntegerCache. - mTaskId = 10; - - evaluate(LAMBDA_FORM_REGULAR, () -> handleTask(t -> t.doSomething(mBounds, mTop, mTaskId))); - evaluate(LAMBDA_FORM_POOLED, () -> { - final PooledPredicate c = PooledLambda.obtainPredicate(Task::doSomething, - PooledLambda.__(Task.class), mBounds, mTop, mTaskId); - handleTask(c); - c.recycle(); - }); - } - - @Test - public void testMessage() { - evaluate(LAMBDA_FORM_REGULAR, () -> { - final Message m = Message.obtain().setCallback(() -> mTask.doSomething(mTaskId, mTime)); - m.getCallback().run(); - m.recycle(); - }); - evaluate(LAMBDA_FORM_POOLED, () -> { - final Message m = PooledLambda.obtainMessage(Task::doSomething, mTask, mTaskId, mTime); - m.getCallback().run(); - m.recycle(); - }); - } - - @Test - public void testRunnable() { - evaluate(LAMBDA_FORM_REGULAR, () -> { - final Runnable r = mTask::doSomething; - r.run(); - }); - evaluate(LAMBDA_FORM_POOLED, () -> { - final Runnable r = PooledLambda.obtainRunnable(Task::doSomething, mTask).recycleOnUse(); - r.run(); - }); - } - - @Test - public void testMultiThread() { - final int numThread = 3; - - final Runnable regularAction = () -> forAllTask(t -> t.doSomething(mTask)); - final Runnable[] regularActions = new Runnable[numThread]; - Arrays.fill(regularActions, regularAction); - evaluateMultiThread(LAMBDA_FORM_REGULAR, regularActions); - - final Runnable pooledAction = () -> { - final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, - PooledLambda.__(Task.class), mTask); - forAllTask(c); - c.recycle(); - }; - final Runnable[] pooledActions = new Runnable[numThread]; - Arrays.fill(pooledActions, pooledAction); - evaluateMultiThread(LAMBDA_FORM_POOLED, pooledActions); - } - - private void forAllTask(Consumer callback) { - for (int i = mTasks.size() - 1; i >= 0; i--) { - callback.accept(mTasks.get(i)); - } - } - - private void handleTask(Predicate callback) { - for (int i = mTasks.size() - 1; i >= 0; i--) { - final Task task = mTasks.get(i); - if (callback.test(task)) { - return; - } - } - } - - private void evaluate(String title, Runnable action) { - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - action.run(); - } - performGc(); - - final GcStatus startGcStatus = getGcStatus(); - final long startTime = SystemClock.elapsedRealtime(); - for (int i = 0; i < TEST_ITERATIONS; i++) { - action.run(); - } - evaluateResult(title, startGcStatus, startTime); - } - - private void evaluateMultiThread(String title, Runnable[] actions) { - performGc(); - - final CountDownLatch latch = new CountDownLatch(actions.length); - final GcStatus startGcStatus = getGcStatus(); - final long startTime = SystemClock.elapsedRealtime(); - for (Runnable action : actions) { - new Thread() { - @Override - public void run() { - for (int i = 0; i < TEST_ITERATIONS; i++) { - action.run(); - } - latch.countDown(); - }; - }.start(); - } - try { - latch.await(); - } catch (InterruptedException ignored) { - } - evaluateResult(title, startGcStatus, startTime); - } - - private void evaluateResult(String title, GcStatus startStatus, long startTime) { - final float elapsed = SystemClock.elapsedRealtime() - startTime; - // Sleep a while to see if GC may happen. - SystemClock.sleep(DELAY_AFTER_BENCH_MS); - final GcStatus endStatus = getGcStatus(); - final GcInfo info = startStatus.calculateGcTime(endStatus, title, mTestResults); - Log.i(TAG, mMethodName + "_" + title + " execution time: " - + elapsed + "ms (avg=" + String.format("%.5f", elapsed / TEST_ITERATIONS) + "ms)" - + " GC time: " + String.format("%.3f", info.mTotalGcTime) + "ms" - + " GC paused time: " + String.format("%.3f", info.mTotalGcPausedTime) + "ms"); - } - - /** Cleans the test environment. */ - private static void performGc() { - System.gc(); - System.runFinalization(); - System.gc(); - } - - private static GcStatus getGcStatus() { - if (DEBUG) { - Log.i(TAG, "===== Read GC dump ====="); - } - final GcStatus status = new GcStatus(); - final List vmDump = getVmDump(); - Assume.assumeFalse("VM dump is empty", vmDump.isEmpty()); - for (String line : vmDump) { - status.visit(line); - if (line.startsWith("DALVIK THREADS")) { - break; - } - } - return status; - } - - private static List getVmDump() { - final int myPid = Process.myPid(); - // Another approach Debug#dumpJavaBacktraceToFileTimeout requires setenforce 0. - Process.sendSignal(myPid, Process.SIGNAL_QUIT); - // Give a chance to handle the signal. - SystemClock.sleep(100); - - String dump = null; - final String pattern = myPid + " written to: "; - final List logs = shell("logcat -v brief -d tombstoned:I *:S"); - for (int i = logs.size() - 1; i >= 0; i--) { - final String log = logs.get(i); - // Log pattern: Traces for pid 9717 written to: /data/anr/trace_07 - final int pos = log.indexOf(pattern); - if (pos > 0) { - dump = log.substring(pattern.length() + pos); - break; - } - } - - Assume.assumeNotNull("Unable to find VM dump", dump); - // It requires system or root uid to read the trace. - return shell("cat " + dump); - } - - private static List shell(String command) { - final ParcelFileDescriptor.AutoCloseInputStream stream = - new ParcelFileDescriptor.AutoCloseInputStream( - getInstrumentation().getUiAutomation().executeShellCommand(command)); - final ArrayList lines = new ArrayList<>(); - try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) { - String line; - while ((line = br.readLine()) != null) { - lines.add(line); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - return lines; - } - - /** An empty class which provides some methods with different type arguments. */ - static class Task { - void doSomething() { - } - - void doSomething(Task t) { - } - - void doSomething(int taskId, long time) { - } - - boolean doSomething(Rect bounds, boolean top, int taskId) { - return false; - } - } - - static class ValPattern { - static final int TYPE_COUNT = 0; - static final int TYPE_TIME = 1; - static final String PATTERN_COUNT = "(\\d+)"; - static final String PATTERN_TIME = "(\\d+\\.?\\d+)(\\w+)"; - final String mRawPattern; - final Pattern mPattern; - final int mType; - - int mIntValue; - float mFloatValue; - - ValPattern(String p, int type) { - mRawPattern = p; - mPattern = Pattern.compile( - p + (type == TYPE_TIME ? PATTERN_TIME : PATTERN_COUNT) + ".*"); - mType = type; - } - - boolean visit(String line) { - final Matcher matcher = mPattern.matcher(line); - if (!matcher.matches()) { - return false; - } - final String value = matcher.group(1); - if (value == null) { - return false; - } - if (mType == TYPE_COUNT) { - mIntValue = Integer.parseInt(value); - return true; - } - final float time = Float.parseFloat(value); - final String unit = matcher.group(2); - if (unit == null) { - return false; - } - // Refer to art/libartbase/base/time_utils.cc - switch (unit) { - case "s": - mFloatValue = time * 1000; - break; - case "ms": - mFloatValue = time; - break; - case "us": - mFloatValue = time / 1000; - break; - case "ns": - mFloatValue = time / 1000 / 1000; - break; - default: - throw new IllegalArgumentException(); - } - - return true; - } - - @Override - public String toString() { - return mRawPattern + (mType == TYPE_TIME ? (mFloatValue + "ms") : mIntValue); - } - } - - /** Parses the dump pattern of Heap::DumpGcPerformanceInfo. */ - private static class GcStatus { - private static final int TOTAL_GC_TIME_INDEX = 1; - private static final int TOTAL_GC_PAUSED_TIME_INDEX = 5; - - // Refer to art/runtime/gc/heap.cc - final ValPattern[] mPatterns = { - new ValPattern("Total GC count: ", ValPattern.TYPE_COUNT), - new ValPattern("Total GC time: ", ValPattern.TYPE_TIME), - new ValPattern("Total time waiting for GC to complete: ", ValPattern.TYPE_TIME), - new ValPattern("Total blocking GC count: ", ValPattern.TYPE_COUNT), - new ValPattern("Total blocking GC time: ", ValPattern.TYPE_TIME), - new ValPattern("Total mutator paused time: ", ValPattern.TYPE_TIME), - new ValPattern("Total number of allocations ", ValPattern.TYPE_COUNT), - new ValPattern("concurrent copying paused: Sum: ", ValPattern.TYPE_TIME), - new ValPattern("concurrent copying total time: ", ValPattern.TYPE_TIME), - new ValPattern("concurrent copying freed: ", ValPattern.TYPE_COUNT), - new ValPattern("Peak regions allocated ", ValPattern.TYPE_COUNT), - }; - - void visit(String dumpLine) { - for (ValPattern p : mPatterns) { - if (p.visit(dumpLine)) { - if (DEBUG) { - Log.i(TAG, " " + p); - } - } - } - } - - GcInfo calculateGcTime(GcStatus newStatus, String title, Bundle result) { - Log.i(TAG, "===== GC status of " + title + " ====="); - final GcInfo info = new GcInfo(); - for (int i = 0; i < mPatterns.length; i++) { - final ValPattern p = mPatterns[i]; - if (p.mType == ValPattern.TYPE_COUNT) { - final int diff = newStatus.mPatterns[i].mIntValue - p.mIntValue; - Log.i(TAG, " " + p.mRawPattern + diff); - if (diff > 0) { - result.putInt("[" + title + "] " + p.mRawPattern, diff); - } - continue; - } - final float diff = newStatus.mPatterns[i].mFloatValue - p.mFloatValue; - Log.i(TAG, " " + p.mRawPattern + diff + "ms"); - if (diff > 0) { - result.putFloat("[" + title + "] " + p.mRawPattern + "(ms)", diff); - } - if (i == TOTAL_GC_TIME_INDEX) { - info.mTotalGcTime = diff; - } else if (i == TOTAL_GC_PAUSED_TIME_INDEX) { - info.mTotalGcPausedTime = diff; - } - } - return info; - } - } - - private static class GcInfo { - float mTotalGcTime; - float mTotalGcPausedTime; - } -} +/* + * Copyright (C) 2020 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; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import android.app.Activity; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.Message; +import android.os.ParcelFileDescriptor; +import android.os.Process; +import android.os.SystemClock; +import android.util.Log; + +import androidx.test.filters.LargeTest; + +import com.android.internal.util.function.pooled.PooledConsumer; +import com.android.internal.util.function.pooled.PooledLambda; +import com.android.internal.util.function.pooled.PooledPredicate; + +import org.junit.Assume; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runners.model.Statement; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Compares the performance of regular lambda and pooled lambda. */ +@LargeTest +public class LambdaPerfTest { + private static final boolean DEBUG = false; + private static final String TAG = LambdaPerfTest.class.getSimpleName(); + + private static final String LAMBDA_FORM_REGULAR = "regular"; + private static final String LAMBDA_FORM_POOLED = "pooled"; + + private static final int WARMUP_ITERATIONS = 1000; + private static final int TEST_ITERATIONS = 3000000; + private static final int TASK_COUNT = 10; + private static final long DELAY_AFTER_BENCH_MS = 1000; + + private String mMethodName; + + private final Bundle mTestResults = new Bundle(); + private final ArrayList mTasks = new ArrayList<>(); + + // The member fields are used to ensure lambda capturing. They don't have the actual meaning. + private final Task mTask = new Task(); + private final Rect mBounds = new Rect(); + private int mTaskId; + private long mTime; + private boolean mTop; + + @Rule + public final TestRule mRule = (base, description) -> new Statement() { + @Override + public void evaluate() throws Throwable { + mMethodName = description.getMethodName(); + mTasks.clear(); + for (int i = 0; i < TASK_COUNT; i++) { + final Task t = new Task(); + mTasks.add(t); + } + base.evaluate(); + + getInstrumentation().sendStatus(Activity.RESULT_OK, mTestResults); + } + }; + + @Test + public void test1ParamConsumer() { + evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTask))); + evaluate(LAMBDA_FORM_POOLED, () -> { + final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, + PooledLambda.__(Task.class), mTask); + forAllTask(c); + c.recycle(); + }); + } + + @Test + public void test2PrimitiveParamsConsumer() { + // Not in Integer#IntegerCache (-128~127) for autoboxing, that may create new object. + mTaskId = 12345; + mTime = 54321; + + evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTaskId, mTime))); + evaluate(LAMBDA_FORM_POOLED, () -> { + final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, + PooledLambda.__(Task.class), mTaskId, mTime); + forAllTask(c); + c.recycle(); + }); + } + + @Test + public void test3ParamsPredicate() { + mTop = true; + // In Integer#IntegerCache. + mTaskId = 10; + + evaluate(LAMBDA_FORM_REGULAR, () -> handleTask(t -> t.doSomething(mBounds, mTop, mTaskId))); + evaluate(LAMBDA_FORM_POOLED, () -> { + final PooledPredicate c = PooledLambda.obtainPredicate(Task::doSomething, + PooledLambda.__(Task.class), mBounds, mTop, mTaskId); + handleTask(c); + c.recycle(); + }); + } + + @Test + public void testMessage() { + evaluate(LAMBDA_FORM_REGULAR, () -> { + final Message m = Message.obtain().setCallback(() -> mTask.doSomething(mTaskId, mTime)); + m.getCallback().run(); + m.recycle(); + }); + evaluate(LAMBDA_FORM_POOLED, () -> { + final Message m = PooledLambda.obtainMessage(Task::doSomething, mTask, mTaskId, mTime); + m.getCallback().run(); + m.recycle(); + }); + } + + @Test + public void testRunnable() { + evaluate(LAMBDA_FORM_REGULAR, () -> { + final Runnable r = mTask::doSomething; + r.run(); + }); + evaluate(LAMBDA_FORM_POOLED, () -> { + final Runnable r = PooledLambda.obtainRunnable(Task::doSomething, mTask).recycleOnUse(); + r.run(); + }); + } + + @Test + public void testMultiThread() { + final int numThread = 3; + + final Runnable regularAction = () -> forAllTask(t -> t.doSomething(mTask)); + final Runnable[] regularActions = new Runnable[numThread]; + Arrays.fill(regularActions, regularAction); + evaluateMultiThread(LAMBDA_FORM_REGULAR, regularActions); + + final Runnable pooledAction = () -> { + final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, + PooledLambda.__(Task.class), mTask); + forAllTask(c); + c.recycle(); + }; + final Runnable[] pooledActions = new Runnable[numThread]; + Arrays.fill(pooledActions, pooledAction); + evaluateMultiThread(LAMBDA_FORM_POOLED, pooledActions); + } + + private void forAllTask(Consumer callback) { + for (int i = mTasks.size() - 1; i >= 0; i--) { + callback.accept(mTasks.get(i)); + } + } + + private void handleTask(Predicate callback) { + for (int i = mTasks.size() - 1; i >= 0; i--) { + final Task task = mTasks.get(i); + if (callback.test(task)) { + return; + } + } + } + + private void evaluate(String title, Runnable action) { + for (int i = 0; i < WARMUP_ITERATIONS; i++) { + action.run(); + } + performGc(); + + final GcStatus startGcStatus = getGcStatus(); + final long startTime = SystemClock.elapsedRealtime(); + for (int i = 0; i < TEST_ITERATIONS; i++) { + action.run(); + } + evaluateResult(title, startGcStatus, startTime); + } + + private void evaluateMultiThread(String title, Runnable[] actions) { + performGc(); + + final CountDownLatch latch = new CountDownLatch(actions.length); + final GcStatus startGcStatus = getGcStatus(); + final long startTime = SystemClock.elapsedRealtime(); + for (Runnable action : actions) { + new Thread() { + @Override + public void run() { + for (int i = 0; i < TEST_ITERATIONS; i++) { + action.run(); + } + latch.countDown(); + }; + }.start(); + } + try { + latch.await(); + } catch (InterruptedException ignored) { + } + evaluateResult(title, startGcStatus, startTime); + } + + private void evaluateResult(String title, GcStatus startStatus, long startTime) { + final float elapsed = SystemClock.elapsedRealtime() - startTime; + // Sleep a while to see if GC may happen. + SystemClock.sleep(DELAY_AFTER_BENCH_MS); + final GcStatus endStatus = getGcStatus(); + final GcInfo info = startStatus.calculateGcTime(endStatus, title, mTestResults); + mTestResults.putFloat("[" + title + "-execution-time]", elapsed); + Log.i(TAG, mMethodName + "_" + title + " execution time: " + + elapsed + "ms (avg=" + String.format("%.5f", elapsed / TEST_ITERATIONS) + "ms)" + + " GC time: " + String.format("%.3f", info.mTotalGcTime) + "ms" + + " GC paused time: " + String.format("%.3f", info.mTotalGcPausedTime) + "ms"); + } + + /** Cleans the test environment. */ + private static void performGc() { + System.gc(); + System.runFinalization(); + System.gc(); + } + + private static GcStatus getGcStatus() { + if (DEBUG) { + Log.i(TAG, "===== Read GC dump ====="); + } + final GcStatus status = new GcStatus(); + final List vmDump = getVmDump(); + Assume.assumeFalse("VM dump is empty", vmDump.isEmpty()); + for (String line : vmDump) { + status.visit(line); + if (line.startsWith("DALVIK THREADS")) { + break; + } + } + return status; + } + + private static List getVmDump() { + final int myPid = Process.myPid(); + // Another approach Debug#dumpJavaBacktraceToFileTimeout requires setenforce 0. + Process.sendSignal(myPid, Process.SIGNAL_QUIT); + // Give a chance to handle the signal. + SystemClock.sleep(100); + + String dump = null; + final String pattern = myPid + " written to: "; + final List logs = shell("logcat -v brief -d tombstoned:I *:S"); + for (int i = logs.size() - 1; i >= 0; i--) { + final String log = logs.get(i); + // Log pattern: Traces for pid 9717 written to: /data/anr/trace_07 + final int pos = log.indexOf(pattern); + if (pos > 0) { + dump = log.substring(pattern.length() + pos); + if (!dump.startsWith("/data/anr/")) { + dump = "/data/anr/" + dump; + } + break; + } + } + + Assume.assumeNotNull("Unable to find VM dump", dump); + // It requires system or root uid to read the trace. + return shell("cat " + dump); + } + + private static List shell(String command) { + final ParcelFileDescriptor.AutoCloseInputStream stream = + new ParcelFileDescriptor.AutoCloseInputStream( + getInstrumentation().getUiAutomation().executeShellCommand(command)); + final ArrayList lines = new ArrayList<>(); + try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) { + String line; + while ((line = br.readLine()) != null) { + lines.add(line); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return lines; + } + + /** An empty class which provides some methods with different type arguments. */ + static class Task { + void doSomething() { + } + + void doSomething(Task t) { + } + + void doSomething(int taskId, long time) { + } + + boolean doSomething(Rect bounds, boolean top, int taskId) { + return false; + } + } + + static class ValPattern { + static final int TYPE_COUNT = 0; + static final int TYPE_TIME = 1; + static final String PATTERN_COUNT = "(\\d+)"; + static final String PATTERN_TIME = "(\\d+\\.?\\d+)(\\w+)"; + final String mRawPattern; + final Pattern mPattern; + final int mType; + + int mIntValue; + float mFloatValue; + + ValPattern(String p, int type) { + mRawPattern = p; + mPattern = Pattern.compile( + p + (type == TYPE_TIME ? PATTERN_TIME : PATTERN_COUNT) + ".*"); + mType = type; + } + + boolean visit(String line) { + final Matcher matcher = mPattern.matcher(line); + if (!matcher.matches()) { + return false; + } + final String value = matcher.group(1); + if (value == null) { + return false; + } + if (mType == TYPE_COUNT) { + mIntValue = Integer.parseInt(value); + return true; + } + final float time = Float.parseFloat(value); + final String unit = matcher.group(2); + if (unit == null) { + return false; + } + // Refer to art/libartbase/base/time_utils.cc + switch (unit) { + case "s": + mFloatValue = time * 1000; + break; + case "ms": + mFloatValue = time; + break; + case "us": + mFloatValue = time / 1000; + break; + case "ns": + mFloatValue = time / 1000 / 1000; + break; + default: + throw new IllegalArgumentException(); + } + + return true; + } + + @Override + public String toString() { + return mRawPattern + (mType == TYPE_TIME ? (mFloatValue + "ms") : mIntValue); + } + } + + /** Parses the dump pattern of Heap::DumpGcPerformanceInfo. */ + private static class GcStatus { + private static final int TOTAL_GC_TIME_INDEX = 1; + private static final int TOTAL_GC_PAUSED_TIME_INDEX = 5; + + // Refer to art/runtime/gc/heap.cc + final ValPattern[] mPatterns = { + new ValPattern("Total GC count: ", ValPattern.TYPE_COUNT), + new ValPattern("Total GC time: ", ValPattern.TYPE_TIME), + new ValPattern("Total time waiting for GC to complete: ", ValPattern.TYPE_TIME), + new ValPattern("Total blocking GC count: ", ValPattern.TYPE_COUNT), + new ValPattern("Total blocking GC time: ", ValPattern.TYPE_TIME), + new ValPattern("Total mutator paused time: ", ValPattern.TYPE_TIME), + new ValPattern("Total number of allocations ", ValPattern.TYPE_COUNT), + new ValPattern("concurrent copying paused: Sum: ", ValPattern.TYPE_TIME), + new ValPattern("concurrent copying total time: ", ValPattern.TYPE_TIME), + new ValPattern("concurrent copying freed: ", ValPattern.TYPE_COUNT), + new ValPattern("Peak regions allocated ", ValPattern.TYPE_COUNT), + }; + + void visit(String dumpLine) { + for (ValPattern p : mPatterns) { + if (p.visit(dumpLine)) { + if (DEBUG) { + Log.i(TAG, " " + p); + } + } + } + } + + GcInfo calculateGcTime(GcStatus newStatus, String title, Bundle result) { + Log.i(TAG, "===== GC status of " + title + " ====="); + final GcInfo info = new GcInfo(); + for (int i = 0; i < mPatterns.length; i++) { + final ValPattern p = mPatterns[i]; + if (p.mType == ValPattern.TYPE_COUNT) { + final int diff = newStatus.mPatterns[i].mIntValue - p.mIntValue; + Log.i(TAG, " " + p.mRawPattern + diff); + if (diff > 0) { + result.putInt("[" + title + "] " + p.mRawPattern, diff); + } + continue; + } + final float diff = newStatus.mPatterns[i].mFloatValue - p.mFloatValue; + Log.i(TAG, " " + p.mRawPattern + diff + "ms"); + if (diff > 0) { + result.putFloat("[" + title + "] " + p.mRawPattern + "(ms)", diff); + } + if (i == TOTAL_GC_TIME_INDEX) { + info.mTotalGcTime = diff; + } else if (i == TOTAL_GC_PAUSED_TIME_INDEX) { + info.mTotalGcPausedTime = diff; + } + } + return info; + } + } + + private static class GcInfo { + float mTotalGcTime; + float mTotalGcPausedTime; + } +}