PooledLambda
This introduces PooledLambda - a way of obtaining lambdas without the allocations overhead. See PooledLambda javadoc for a guide and PooledLambdaSample for code samples of useful usages. Test: ensure samples of PooledLambdaSample work as described. Change-Id: I46f8ad27bc1de07e19f6e39f89d2cafe4238497a
This commit is contained in:
@@ -298,7 +298,7 @@ public class Binder implements IBinder {
|
||||
long callingIdentity = clearCallingIdentity();
|
||||
Throwable throwableToPropagate = null;
|
||||
try {
|
||||
action.run();
|
||||
action.runOrThrow();
|
||||
} catch (Throwable throwable) {
|
||||
throwableToPropagate = throwable;
|
||||
} finally {
|
||||
@@ -322,7 +322,7 @@ public class Binder implements IBinder {
|
||||
long callingIdentity = clearCallingIdentity();
|
||||
Throwable throwableToPropagate = null;
|
||||
try {
|
||||
return action.get();
|
||||
return action.getOrThrow();
|
||||
} catch (Throwable throwable) {
|
||||
throwableToPropagate = throwable;
|
||||
return null; // overridden by throwing in finally block
|
||||
|
||||
@@ -109,7 +109,9 @@ public final class Message implements Parcelable {
|
||||
// sometimes we store linked lists of these things
|
||||
/*package*/ Message next;
|
||||
|
||||
private static final Object sPoolSync = new Object();
|
||||
|
||||
/** @hide */
|
||||
public static final Object sPoolSync = new Object();
|
||||
private static Message sPool;
|
||||
private static int sPoolSize = 0;
|
||||
|
||||
@@ -370,6 +372,12 @@ public final class Message implements Parcelable {
|
||||
return callback;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public Message setCallback(Runnable r) {
|
||||
callback = r;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a Bundle of arbitrary data associated with this
|
||||
* event, lazily creating it if necessary. Set this value by calling
|
||||
@@ -410,6 +418,16 @@ public final class Message implements Parcelable {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chainable setter for {@link #what}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public Message setWhat(int what) {
|
||||
this.what = what;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends this Message to the Handler specified by {@link #getTarget}.
|
||||
* Throws a null pointer exception if this field has not been set.
|
||||
|
||||
@@ -130,22 +130,29 @@ public final class Pools {
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronized) pool of objects.
|
||||
* Synchronized pool of objects.
|
||||
*
|
||||
* @param <T> The pooled type.
|
||||
*/
|
||||
public static class SynchronizedPool<T> extends SimplePool<T> {
|
||||
private final Object mLock = new Object();
|
||||
private final Object mLock;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param maxPoolSize The max pool size.
|
||||
* @param lock an optional custom object to synchronize on
|
||||
*
|
||||
* @throws IllegalArgumentException If the max pool size is less than zero.
|
||||
*/
|
||||
public SynchronizedPool(int maxPoolSize) {
|
||||
public SynchronizedPool(int maxPoolSize, Object lock) {
|
||||
super(maxPoolSize);
|
||||
mLock = lock;
|
||||
}
|
||||
|
||||
/** @see #SynchronizedPool(int, Object) */
|
||||
public SynchronizedPool(int maxPoolSize) {
|
||||
this(maxPoolSize, new Object());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,7 +32,7 @@ public class FunctionalUtils {
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ThrowingRunnable {
|
||||
void run() throws Exception;
|
||||
void runOrThrow() throws Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,7 +43,7 @@ public class FunctionalUtils {
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ThrowingSupplier<T> {
|
||||
T get() throws Exception;
|
||||
T getOrThrow() throws Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function;
|
||||
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A 4-argument {@link Consumer}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface QuadConsumer<A, B, C, D> {
|
||||
void accept(A a, B b, C c, D d);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function;
|
||||
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A 4-argument {@link Function}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface QuadFunction<A, B, C, D, R> {
|
||||
R apply(A a, B b, C c, D d);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function;
|
||||
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A 4-argument {@link Predicate}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface QuadPredicate<A, B, C, D> {
|
||||
boolean test(A a, B b, C c, D d);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function;
|
||||
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A 3-argument {@link Consumer}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface TriConsumer<A, B, C> {
|
||||
void accept(A a, B b, C c);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function;
|
||||
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A 3-argument {@link Function}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface TriFunction<A, B, C, R> {
|
||||
R apply(A a, B b, C c);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function;
|
||||
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A 3-argument {@link Predicate}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface TriPredicate<A, B, C> {
|
||||
boolean test(A a, B b, C c);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
/**
|
||||
* A placeholder for an argument of type {@code R}
|
||||
*
|
||||
* @see PooledLambda
|
||||
* @hide
|
||||
*/
|
||||
public final class ArgumentPlaceholder<R> {
|
||||
private ArgumentPlaceholder() {}
|
||||
static final ArgumentPlaceholder<?> INSTANCE = new ArgumentPlaceholder<>();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "_";
|
||||
}
|
||||
}
|
||||
132
core/java/com/android/internal/util/function/pooled/OmniFunction.java
Executable file
132
core/java/com/android/internal/util/function/pooled/OmniFunction.java
Executable file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
|
||||
import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
|
||||
import com.android.internal.util.function.QuadConsumer;
|
||||
import com.android.internal.util.function.QuadFunction;
|
||||
import com.android.internal.util.function.TriConsumer;
|
||||
import com.android.internal.util.function.TriFunction;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* An interface implementing all supported function interfaces, delegating each to {@link #invoke}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
abstract class OmniFunction<A, B, C, D, R> implements
|
||||
PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
|
||||
QuadFunction<A, B, C, D, R>,
|
||||
PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
|
||||
PooledPredicate<A>, BiPredicate<A, B>,
|
||||
PooledSupplier<R>, PooledRunnable,
|
||||
ThrowingRunnable, ThrowingSupplier<R>,
|
||||
PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
|
||||
|
||||
abstract R invoke(A a, B b, C c, D d);
|
||||
|
||||
@Override
|
||||
public R apply(A o, B o2) {
|
||||
return invoke(o, o2, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R apply(A o) {
|
||||
return invoke(o, null, null, null);
|
||||
}
|
||||
|
||||
abstract public <V> OmniFunction<A, B, C, D, V> andThen(Function<? super R, ? extends V> after);
|
||||
abstract public OmniFunction<A, B, C, D, R> negate();
|
||||
|
||||
@Override
|
||||
public void accept(A o, B o2) {
|
||||
invoke(o, o2, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(A o) {
|
||||
invoke(o, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
invoke(null, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R get() {
|
||||
return invoke(null, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(A o, B o2) {
|
||||
return (Boolean) invoke(o, o2, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(A o) {
|
||||
return (Boolean) invoke(o, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledRunnable asRunnable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledConsumer<A> asConsumer() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R apply(A a, B b, C c) {
|
||||
return invoke(a, b, c, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(A a, B b, C c) {
|
||||
invoke(a, b, c, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R apply(A a, B b, C c, D d) {
|
||||
return invoke(a, b, c, d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(A a, B b, C c, D d) {
|
||||
invoke(a, b, c, d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runOrThrow() throws Exception {
|
||||
run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public R getOrThrow() throws Exception {
|
||||
return get();
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract public OmniFunction<A, B, C, D, R> recycleOnUse();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* {@link Consumer} + {@link PooledLambda}
|
||||
*
|
||||
* @see PooledLambda
|
||||
* @hide
|
||||
*/
|
||||
public interface PooledConsumer<T> extends PooledLambda, Consumer<T> {
|
||||
|
||||
/** @inheritDoc */
|
||||
PooledConsumer<T> recycleOnUse();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* {@link Function} + {@link PooledLambda}
|
||||
*
|
||||
* @see PooledLambda
|
||||
* @hide
|
||||
*/
|
||||
public interface PooledFunction<A, R> extends PooledLambda, Function<A, R> {
|
||||
|
||||
/**
|
||||
* Ignores the result
|
||||
*/
|
||||
PooledConsumer<A> asConsumer();
|
||||
|
||||
/** @inheritDoc */
|
||||
PooledFunction<A, R> recycleOnUse();
|
||||
}
|
||||
813
core/java/com/android/internal/util/function/pooled/PooledLambda.java
Executable file
813
core/java/com/android/internal/util/function/pooled/PooledLambda.java
Executable file
@@ -0,0 +1,813 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import static com.android.internal.util.function.pooled.PooledLambdaImpl.acquire;
|
||||
import static com.android.internal.util.function.pooled.PooledLambdaImpl.acquireConstSupplier;
|
||||
|
||||
import android.os.Message;
|
||||
|
||||
import com.android.internal.util.function.QuadConsumer;
|
||||
import com.android.internal.util.function.QuadFunction;
|
||||
import com.android.internal.util.function.TriConsumer;
|
||||
import com.android.internal.util.function.TriFunction;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A recyclable anonymous function.
|
||||
* Allows obtaining {@link Function}s/{@link Runnable}s/{@link Supplier}s/etc. without allocating a
|
||||
* new instance each time
|
||||
*
|
||||
* This exploits the mechanic that stateless lambdas (such as plain/non-bound method references)
|
||||
* get translated into a singleton instance, making it possible to create a recyclable container
|
||||
* ({@link PooledLambdaImpl}) holding a reference to such a singleton function, as well as
|
||||
* (possibly partial) arguments required for its invocation.
|
||||
*
|
||||
* To obtain an instance, use one of the factory methods in this class.
|
||||
*
|
||||
* You can call {@link #recycleOnUse} to make the instance automatically recycled upon invocation,
|
||||
* making if effectively <b>one-time use</b>.
|
||||
* This is often the behavior you want, as it allows to not worry about manual recycling.
|
||||
* Some notable examples: {@link android.os.Handler#post(Runnable)},
|
||||
* {@link android.app.Activity#runOnUiThread(Runnable)}, {@link android.view.View#post(Runnable)}
|
||||
*
|
||||
* For factories of functions that take further arguments, the corresponding 'missing' argument's
|
||||
* position is marked by an argument of type {@link ArgumentPlaceholder} with the type parameter
|
||||
* corresponding to missing argument's type.
|
||||
* You can fill the 'missing argument' spot with {@link #__()}
|
||||
* (which is the factory function for {@link ArgumentPlaceholder})
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "unused", "WeakerAccess"})
|
||||
public interface PooledLambda {
|
||||
|
||||
/**
|
||||
* Recycles this instance. No-op if already recycled.
|
||||
*/
|
||||
void recycle();
|
||||
|
||||
/**
|
||||
* Makes this instance automatically {@link #recycle} itself after the first call.
|
||||
*
|
||||
* @return this instance for convenience
|
||||
*/
|
||||
PooledLambda recycleOnUse();
|
||||
|
||||
|
||||
// Factories
|
||||
|
||||
/**
|
||||
* @return {@link ArgumentPlaceholder} with the inferred type parameter value
|
||||
*/
|
||||
static <R> ArgumentPlaceholder<R> __() {
|
||||
return (ArgumentPlaceholder<R>) ArgumentPlaceholder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param typeHint the explicitly specified type of the missing argument
|
||||
* @return {@link ArgumentPlaceholder} with the specified type parameter value
|
||||
*/
|
||||
static <R> ArgumentPlaceholder<R> __(Class<R> typeHint) {
|
||||
return __();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given value into a {@link PooledSupplier}
|
||||
*
|
||||
* @param value a value to wrap
|
||||
* @return a pooled supplier of {@code value}
|
||||
*/
|
||||
static <R> PooledSupplier<R> obtainSupplier(R value) {
|
||||
PooledLambdaImpl r = acquireConstSupplier(ReturnType.OBJECT);
|
||||
r.mFunc = value;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given value into a {@link PooledSupplier}
|
||||
*
|
||||
* @param value a value to wrap
|
||||
* @return a pooled supplier of {@code value}
|
||||
*/
|
||||
static PooledSupplier.OfInt obtainSupplier(int value) {
|
||||
PooledLambdaImpl r = acquireConstSupplier(ReturnType.INT);
|
||||
r.mConstValue = value;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given value into a {@link PooledSupplier}
|
||||
*
|
||||
* @param value a value to wrap
|
||||
* @return a pooled supplier of {@code value}
|
||||
*/
|
||||
static PooledSupplier.OfLong obtainSupplier(long value) {
|
||||
PooledLambdaImpl r = acquireConstSupplier(ReturnType.LONG);
|
||||
r.mConstValue = value;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given value into a {@link PooledSupplier}
|
||||
*
|
||||
* @param value a value to wrap
|
||||
* @return a pooled supplier of {@code value}
|
||||
*/
|
||||
static PooledSupplier.OfDouble obtainSupplier(double value) {
|
||||
PooledLambdaImpl r = acquireConstSupplier(ReturnType.DOUBLE);
|
||||
r.mConstValue = Double.doubleToRawLongBits(value);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledRunnable} 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 PooledRunnable}, equivalent to lambda:
|
||||
* {@code () -> function(arg1) }
|
||||
*/
|
||||
static <A> PooledRunnable obtainRunnable(
|
||||
Consumer<? super A> function,
|
||||
A arg1) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 1, 0, ReturnType.VOID, arg1, 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 <A> PooledSupplier<Boolean> obtainSupplier(
|
||||
Predicate<? super A> function,
|
||||
A arg1) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 1, 0, ReturnType.BOOLEAN, arg1, 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 <A, R> PooledSupplier<R> obtainSupplier(
|
||||
Function<? super A, ? extends R> function,
|
||||
A arg1) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 1, 0, ReturnType.OBJECT, arg1, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory of {@link Message}s that contain an
|
||||
* ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
|
||||
* {@link Message#getCallback internal callback}.
|
||||
*
|
||||
* The callback is equivalent to one obtainable via
|
||||
* {@link #obtainRunnable(Consumer, Object)}
|
||||
*
|
||||
* Note that using this method with {@link android.os.Handler#handleMessage}
|
||||
* is more efficient than the alternative of {@link android.os.Handler#post}
|
||||
* with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
|
||||
* when obtaining {@link Message} and {@link PooledRunnable} from pools separately
|
||||
*
|
||||
* You may optionally set a {@link Message#what} for the message if you want to be
|
||||
* able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
|
||||
* there's no need to do so
|
||||
*
|
||||
* @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 Message} invoking {@code function(arg1) } when handled
|
||||
*/
|
||||
static <A> Message obtainMessage(
|
||||
Consumer<? super A> function,
|
||||
A arg1) {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 1, 0, ReturnType.VOID, arg1, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledRunnable} 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 PooledRunnable}, equivalent to lambda:
|
||||
* {@code () -> function(arg1, arg2) }
|
||||
*/
|
||||
static <A, B> PooledRunnable obtainRunnable(
|
||||
BiConsumer<? super A, ? super B> function,
|
||||
A arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 0, ReturnType.VOID, arg1, arg2, 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 <A, B> PooledSupplier<Boolean> obtainSupplier(
|
||||
BiPredicate<? super A, ? super B> function,
|
||||
A arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, 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 <A, B, R> PooledSupplier<R> obtainSupplier(
|
||||
BiFunction<? super A, ? super B, ? extends R> function,
|
||||
A arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg1) -> function(arg1, arg2) }
|
||||
*/
|
||||
static <A, B> PooledConsumer<A> obtainConsumer(
|
||||
BiConsumer<? super A, ? super B> function,
|
||||
ArgumentPlaceholder<A> arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.VOID, arg1, arg2, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledPredicate} 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 PooledPredicate}, equivalent to lambda:
|
||||
* {@code (arg1) -> function(arg1, arg2) }
|
||||
*/
|
||||
static <A, B> PooledPredicate<A> obtainPredicate(
|
||||
BiPredicate<? super A, ? super B> function,
|
||||
ArgumentPlaceholder<A> arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, 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 <A, B, R> PooledFunction<A, R> obtainFunction(
|
||||
BiFunction<? super A, ? super B, ? extends R> function,
|
||||
ArgumentPlaceholder<A> arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg2) -> function(arg1, arg2) }
|
||||
*/
|
||||
static <A, B> PooledConsumer<B> obtainConsumer(
|
||||
BiConsumer<? super A, ? super B> function,
|
||||
A arg1, ArgumentPlaceholder<B> arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.VOID, arg1, arg2, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledPredicate} 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 PooledPredicate}, equivalent to lambda:
|
||||
* {@code (arg2) -> function(arg1, arg2) }
|
||||
*/
|
||||
static <A, B> PooledPredicate<B> obtainPredicate(
|
||||
BiPredicate<? super A, ? super B> function,
|
||||
A arg1, ArgumentPlaceholder<B> arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, 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 <A, B, R> PooledFunction<B, R> obtainFunction(
|
||||
BiFunction<? super A, ? super B, ? extends R> function,
|
||||
A arg1, ArgumentPlaceholder<B> arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory of {@link Message}s that contain an
|
||||
* ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
|
||||
* {@link Message#getCallback internal callback}.
|
||||
*
|
||||
* The callback is equivalent to one obtainable via
|
||||
* {@link #obtainRunnable(BiConsumer, Object, Object)}
|
||||
*
|
||||
* Note that using this method with {@link android.os.Handler#handleMessage}
|
||||
* is more efficient than the alternative of {@link android.os.Handler#post}
|
||||
* with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
|
||||
* when obtaining {@link Message} and {@link PooledRunnable} from pools separately
|
||||
*
|
||||
* You may optionally set a {@link Message#what} for the message if you want to be
|
||||
* able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
|
||||
* there's no need to do so
|
||||
*
|
||||
* @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 Message} invoking {@code function(arg1, arg2) } when handled
|
||||
*/
|
||||
static <A, B> Message obtainMessage(
|
||||
BiConsumer<? super A, ? super B> function,
|
||||
A arg1, B arg2) {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 2, 0, ReturnType.VOID, arg1, arg2, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledRunnable} 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 PooledRunnable}, equivalent to lambda:
|
||||
* {@code () -> function(arg1, arg2, arg3) }
|
||||
*/
|
||||
static <A, B, C> PooledRunnable obtainRunnable(
|
||||
TriConsumer<? super A, ? super B, ? super C> function,
|
||||
A arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, 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 <A, B, C, R> PooledSupplier<R> obtainSupplier(
|
||||
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
|
||||
A arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg1) -> function(arg1, arg2, arg3) }
|
||||
*/
|
||||
static <A, B, C> PooledConsumer<A> obtainConsumer(
|
||||
TriConsumer<? super A, ? super B, ? super C> function,
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, 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 <A, B, C, R> PooledFunction<A, R> obtainFunction(
|
||||
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg2) -> function(arg1, arg2, arg3) }
|
||||
*/
|
||||
static <A, B, C> PooledConsumer<B> obtainConsumer(
|
||||
TriConsumer<? super A, ? super B, ? super C> function,
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, 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 <A, B, C, R> PooledFunction<B, R> obtainFunction(
|
||||
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg3) -> function(arg1, arg2, arg3) }
|
||||
*/
|
||||
static <A, B, C> PooledConsumer<C> obtainConsumer(
|
||||
TriConsumer<? super A, ? super B, ? super C> function,
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, 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 <A, B, C, R> PooledFunction<C, R> obtainFunction(
|
||||
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory of {@link Message}s that contain an
|
||||
* ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
|
||||
* {@link Message#getCallback internal callback}.
|
||||
*
|
||||
* The callback is equivalent to one obtainable via
|
||||
* {@link #obtainRunnable(TriConsumer, Object, Object, Object)}
|
||||
*
|
||||
* Note that using this method with {@link android.os.Handler#handleMessage}
|
||||
* is more efficient than the alternative of {@link android.os.Handler#post}
|
||||
* with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
|
||||
* when obtaining {@link Message} and {@link PooledRunnable} from pools separately
|
||||
*
|
||||
* You may optionally set a {@link Message#what} for the message if you want to be
|
||||
* able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
|
||||
* there's no need to do so
|
||||
*
|
||||
* @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 Message} invoking {@code function(arg1, arg2, arg3) } when handled
|
||||
*/
|
||||
static <A, B, C> Message obtainMessage(
|
||||
TriConsumer<? super A, ? super B, ? super C> function,
|
||||
A arg1, B arg2, C arg3) {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledRunnable} 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 PooledRunnable}, equivalent to lambda:
|
||||
* {@code () -> function(arg1, arg2, arg3, arg4) }
|
||||
*/
|
||||
static <A, B, C, D> PooledRunnable obtainRunnable(
|
||||
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
|
||||
A arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 <A, B, C, D, R> PooledSupplier<R> obtainSupplier(
|
||||
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
|
||||
A arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg1) -> function(arg1, arg2, arg3, arg4) }
|
||||
*/
|
||||
static <A, B, C, D> PooledConsumer<A> obtainConsumer(
|
||||
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 <A, B, C, D, R> PooledFunction<A, R> obtainFunction(
|
||||
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg2) -> function(arg1, arg2, arg3, arg4) }
|
||||
*/
|
||||
static <A, B, C, D> PooledConsumer<B> obtainConsumer(
|
||||
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 <A, B, C, D, R> PooledFunction<B, R> obtainFunction(
|
||||
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg3) -> function(arg1, arg2, arg3, arg4) }
|
||||
*/
|
||||
static <A, B, C, D> PooledConsumer<C> obtainConsumer(
|
||||
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 <A, B, C, D, R> PooledFunction<C, R> obtainFunction(
|
||||
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledConsumer} 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 PooledConsumer}, equivalent to lambda:
|
||||
* {@code (arg4) -> function(arg1, arg2, arg3, arg4) }
|
||||
*/
|
||||
static <A, B, C, D> PooledConsumer<D> obtainConsumer(
|
||||
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
|
||||
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 <A, B, C, D, R> PooledFunction<D, R> obtainFunction(
|
||||
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
|
||||
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory of {@link Message}s that contain an
|
||||
* ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
|
||||
* {@link Message#getCallback internal callback}.
|
||||
*
|
||||
* The callback is equivalent to one obtainable via
|
||||
* {@link #obtainRunnable(QuadConsumer, Object, Object, Object, Object)}
|
||||
*
|
||||
* Note that using this method with {@link android.os.Handler#handleMessage}
|
||||
* is more efficient than the alternative of {@link android.os.Handler#post}
|
||||
* with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
|
||||
* when obtaining {@link Message} and {@link PooledRunnable} from pools separately
|
||||
*
|
||||
* You may optionally set a {@link Message#what} for the message if you want to be
|
||||
* able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
|
||||
* there's no need to do so
|
||||
*
|
||||
* @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 Message} invoking {@code function(arg1, arg2, arg3, arg4) } when handled
|
||||
*/
|
||||
static <A, B, C, D> Message obtainMessage(
|
||||
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
|
||||
A arg1, B arg2, C arg3, D arg4) {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
}
|
||||
557
core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
Executable file
557
core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
Executable file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pools;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.BitUtils;
|
||||
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.TriConsumer;
|
||||
import com.android.internal.util.function.TriFunction;
|
||||
import com.android.internal.util.function.TriPredicate;
|
||||
|
||||
import java.util.Arrays;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @see PooledLambda
|
||||
* @hide
|
||||
*/
|
||||
final class PooledLambdaImpl<R> extends OmniFunction<Object, Object, Object, Object, R> {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String LOG_TAG = "PooledLambdaImpl";
|
||||
|
||||
private static final int MAX_ARGS = 4;
|
||||
|
||||
private static final int MAX_POOL_SIZE = 50;
|
||||
|
||||
static class Pool extends Pools.SynchronizedPool<PooledLambdaImpl> {
|
||||
|
||||
public Pool(Object lock) {
|
||||
super(MAX_POOL_SIZE, lock);
|
||||
}
|
||||
}
|
||||
|
||||
static final Pool sPool = new Pool(new Object());
|
||||
static final Pool sMessageCallbacksPool = new Pool(Message.sPoolSync);
|
||||
|
||||
private PooledLambdaImpl() {}
|
||||
|
||||
/**
|
||||
* The function reference to be invoked
|
||||
*
|
||||
* May be the return value itself in case when an immediate result constant is provided instead
|
||||
*/
|
||||
Object mFunc;
|
||||
|
||||
/**
|
||||
* A primitive result value to be immediately returned on invocation instead of calling
|
||||
* {@link #mFunc}
|
||||
*/
|
||||
long mConstValue;
|
||||
|
||||
/**
|
||||
* Arguments for {@link #mFunc}
|
||||
*/
|
||||
@Nullable Object[] mArgs = null;
|
||||
|
||||
/**
|
||||
* Flag for {@link #mFlags}
|
||||
*
|
||||
* Indicates whether this instance is recycled
|
||||
*/
|
||||
private static final int FLAG_RECYCLED = 1 << MAX_ARGS;
|
||||
|
||||
/**
|
||||
* Flag for {@link #mFlags}
|
||||
*
|
||||
* Indicates whether this instance should be immediately recycled on invocation
|
||||
* (as requested via {@link PooledLambda#recycleOnUse()}) or not(default)
|
||||
*/
|
||||
private static final int FLAG_RECYCLE_ON_USE = 1 << (MAX_ARGS + 1);
|
||||
|
||||
/**
|
||||
* Flag for {@link #mFlags}
|
||||
*
|
||||
* Indicates that this instance was acquired from {@link #sMessageCallbacksPool} as opposed to
|
||||
* {@link #sPool}
|
||||
*/
|
||||
private static final int FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL = 1 << (MAX_ARGS + 2);
|
||||
|
||||
/** @see #mFlags */
|
||||
static final int MASK_EXPOSED_AS = LambdaType.MASK << (MAX_ARGS + 3);
|
||||
|
||||
/** @see #mFlags */
|
||||
static final int MASK_FUNC_TYPE = LambdaType.MASK <<
|
||||
(MAX_ARGS + 3 + LambdaType.MASK_BIT_COUNT);
|
||||
|
||||
/**
|
||||
* Bit schema:
|
||||
* AAAABCDEEEEEEFFFFFF
|
||||
*
|
||||
* Where:
|
||||
* A - whether {@link #mArgs arg} at corresponding index was specified at
|
||||
* {@link #acquire creation time} (0) or {@link #invoke invocation time} (1)
|
||||
* B - {@link #FLAG_RECYCLED}
|
||||
* C - {@link #FLAG_RECYCLE_ON_USE}
|
||||
* D - {@link #FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL}
|
||||
* E - {@link LambdaType} representing the type of the lambda returned to the caller from a
|
||||
* factory method
|
||||
* F - {@link LambdaType} of {@link #mFunc} as resolved when calling a factory method
|
||||
*/
|
||||
int mFlags = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
if (DEBUG) Log.i(LOG_TAG, this + ".recycle()");
|
||||
if (!isRecycled()) doRecycle();
|
||||
}
|
||||
|
||||
private void doRecycle() {
|
||||
if (DEBUG) Log.i(LOG_TAG, this + ".doRecycle()");
|
||||
Pool pool = (mFlags & FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL) != 0
|
||||
? PooledLambdaImpl.sMessageCallbacksPool
|
||||
: PooledLambdaImpl.sPool;
|
||||
|
||||
mFunc = null;
|
||||
if (mArgs != null) Arrays.fill(mArgs, null);
|
||||
mFlags = FLAG_RECYCLED;
|
||||
mConstValue = 0L;
|
||||
|
||||
pool.release(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
R invoke(Object a1, Object a2, Object a3, Object a4) {
|
||||
checkNotRecycled();
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, this + ".invoke("
|
||||
+ commaSeparateFirstN(
|
||||
new Object[] { a1, a2, a3, a4 },
|
||||
LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
|
||||
+ ")");
|
||||
}
|
||||
boolean ignored = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4);
|
||||
int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
|
||||
if (argCount != LambdaType.MASK_ARG_COUNT) {
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
if (mArgs[i] == ArgumentPlaceholder.INSTANCE) {
|
||||
throw new IllegalStateException("Missing argument #" + i + " among "
|
||||
+ Arrays.toString(mArgs));
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
return doInvoke();
|
||||
} finally {
|
||||
if (isRecycleOnUse()) doRecycle();
|
||||
if (!isRecycled()) {
|
||||
int argsSize = ArrayUtils.size(mArgs);
|
||||
for (int i = 0; i < argsSize; i++) {
|
||||
popArg(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fillInArg(Object invocationArg) {
|
||||
int argsSize = ArrayUtils.size(mArgs);
|
||||
for (int i = 0; i < argsSize; i++) {
|
||||
if (mArgs[i] == ArgumentPlaceholder.INSTANCE) {
|
||||
mArgs[i] = invocationArg;
|
||||
mFlags |= BitUtils.bitAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (invocationArg != null && invocationArg != ArgumentPlaceholder.INSTANCE) {
|
||||
throw new IllegalStateException("No more arguments expected for provided arg "
|
||||
+ invocationArg + " among " + Arrays.toString(mArgs));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkNotRecycled() {
|
||||
if (isRecycled()) throw new IllegalStateException("Instance is recycled: " + this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private R doInvoke() {
|
||||
final int funcType = getFlags(MASK_FUNC_TYPE);
|
||||
final int argCount = LambdaType.decodeArgCount(funcType);
|
||||
final int returnType = LambdaType.decodeReturnType(funcType);
|
||||
|
||||
switch (argCount) {
|
||||
case LambdaType.MASK_ARG_COUNT: {
|
||||
switch (returnType) {
|
||||
case LambdaType.ReturnType.INT: return (R) (Integer) getAsInt();
|
||||
case LambdaType.ReturnType.LONG: return (R) (Long) getAsLong();
|
||||
case LambdaType.ReturnType.DOUBLE: return (R) (Double) getAsDouble();
|
||||
default: return (R) mFunc;
|
||||
}
|
||||
}
|
||||
case 0: {
|
||||
switch (returnType) {
|
||||
case LambdaType.ReturnType.VOID: {
|
||||
((Runnable) mFunc).run();
|
||||
return null;
|
||||
}
|
||||
case LambdaType.ReturnType.BOOLEAN:
|
||||
case LambdaType.ReturnType.OBJECT: {
|
||||
return (R) ((Supplier) mFunc).get();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case 1: {
|
||||
switch (returnType) {
|
||||
case LambdaType.ReturnType.VOID: {
|
||||
((Consumer) mFunc).accept(popArg(0));
|
||||
return null;
|
||||
}
|
||||
case LambdaType.ReturnType.BOOLEAN: {
|
||||
return (R) (Object) ((Predicate) mFunc).test(popArg(0));
|
||||
}
|
||||
case LambdaType.ReturnType.OBJECT: {
|
||||
return (R) ((Function) mFunc).apply(popArg(0));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
switch (returnType) {
|
||||
case LambdaType.ReturnType.VOID: {
|
||||
((BiConsumer) mFunc).accept(popArg(0), popArg(1));
|
||||
return null;
|
||||
}
|
||||
case LambdaType.ReturnType.BOOLEAN: {
|
||||
return (R) (Object) ((BiPredicate) mFunc).test(popArg(0), popArg(1));
|
||||
}
|
||||
case LambdaType.ReturnType.OBJECT: {
|
||||
return (R) ((BiFunction) mFunc).apply(popArg(0), popArg(1));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case 3: {
|
||||
switch (returnType) {
|
||||
case LambdaType.ReturnType.VOID: {
|
||||
((TriConsumer) mFunc).accept(popArg(0), popArg(1), popArg(2));
|
||||
return null;
|
||||
}
|
||||
case LambdaType.ReturnType.BOOLEAN: {
|
||||
return (R) (Object) ((TriPredicate) mFunc).test(
|
||||
popArg(0), popArg(1), popArg(2));
|
||||
}
|
||||
case LambdaType.ReturnType.OBJECT: {
|
||||
return (R) ((TriFunction) mFunc).apply(popArg(0), popArg(1), popArg(2));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case 4: {
|
||||
switch (returnType) {
|
||||
case LambdaType.ReturnType.VOID: {
|
||||
((QuadConsumer) mFunc).accept(popArg(0), popArg(1), popArg(2), popArg(3));
|
||||
return null;
|
||||
}
|
||||
case LambdaType.ReturnType.BOOLEAN: {
|
||||
return (R) (Object) ((QuadPredicate) mFunc).test(
|
||||
popArg(0), popArg(1), popArg(2), popArg(3));
|
||||
}
|
||||
case LambdaType.ReturnType.OBJECT: {
|
||||
return (R) ((QuadFunction) mFunc).apply(
|
||||
popArg(0), popArg(1), popArg(2), popArg(3));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
|
||||
}
|
||||
|
||||
private boolean isConstSupplier() {
|
||||
return LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE)) == LambdaType.MASK_ARG_COUNT;
|
||||
}
|
||||
|
||||
private Object popArg(int index) {
|
||||
Object result = mArgs[index];
|
||||
if (isInvocationArgAtIndex(index)) {
|
||||
mArgs[index] = ArgumentPlaceholder.INSTANCE;
|
||||
mFlags &= ~BitUtils.bitAt(index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isRecycled()) return "<recycled PooledLambda@" + hashCodeHex(this) + ">";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (isConstSupplier()) {
|
||||
sb.append(getFuncTypeAsString()).append("(").append(doInvoke()).append(")");
|
||||
} else {
|
||||
if (mFunc instanceof PooledLambdaImpl) {
|
||||
sb.append(mFunc);
|
||||
} else {
|
||||
sb.append(getFuncTypeAsString()).append("@").append(hashCodeHex(mFunc));
|
||||
}
|
||||
sb.append("(");
|
||||
sb.append(commaSeparateFirstN(mArgs, LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE))));
|
||||
sb.append(")");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String commaSeparateFirstN(@Nullable Object[] arr, int n) {
|
||||
if (arr == null) return "";
|
||||
return TextUtils.join(",", Arrays.copyOf(arr, n));
|
||||
}
|
||||
|
||||
private static String hashCodeHex(Object o) {
|
||||
return Integer.toHexString(o.hashCode());
|
||||
}
|
||||
|
||||
private String getFuncTypeAsString() {
|
||||
if (isRecycled()) throw new IllegalStateException();
|
||||
if (isConstSupplier()) return "supplier";
|
||||
String name = LambdaType.toString(getFlags(MASK_EXPOSED_AS));
|
||||
if (name.endsWith("Consumer")) return "consumer";
|
||||
if (name.endsWith("Function")) return "function";
|
||||
if (name.endsWith("Predicate")) return "predicate";
|
||||
if (name.endsWith("Supplier")) return "supplier";
|
||||
if (name.endsWith("Runnable")) return "runnable";
|
||||
throw new IllegalStateException("Don't know the string representation of " + name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal non-typesafe factory method for {@link PooledLambdaImpl}
|
||||
*/
|
||||
static <E extends PooledLambda> E acquire(Pool pool, Object f,
|
||||
int fNumArgs, int numPlaceholders, int fReturnType,
|
||||
Object a, Object b, Object c, Object d) {
|
||||
PooledLambdaImpl r = acquire(pool);
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG,
|
||||
"acquire(this = @" + hashCodeHex(r)
|
||||
+ ", f = " + f
|
||||
+ ", fNumArgs = " + fNumArgs
|
||||
+ ", numPlaceholders = " + numPlaceholders
|
||||
+ ", fReturnType = " + LambdaType.ReturnType.toString(fReturnType)
|
||||
+ ", a = " + a
|
||||
+ ", b = " + b
|
||||
+ ", c = " + c
|
||||
+ ", d = " + d
|
||||
+ ")");
|
||||
}
|
||||
r.mFunc = f;
|
||||
r.setFlags(MASK_FUNC_TYPE, LambdaType.encode(fNumArgs, fReturnType));
|
||||
r.setFlags(MASK_EXPOSED_AS, LambdaType.encode(numPlaceholders, fReturnType));
|
||||
if (ArrayUtils.size(r.mArgs) < fNumArgs) r.mArgs = new Object[fNumArgs];
|
||||
setIfInBounds(r.mArgs, 0, a);
|
||||
setIfInBounds(r.mArgs, 1, b);
|
||||
setIfInBounds(r.mArgs, 2, c);
|
||||
setIfInBounds(r.mArgs, 3, d);
|
||||
return (E) r;
|
||||
}
|
||||
|
||||
static PooledLambdaImpl acquireConstSupplier(int type) {
|
||||
PooledLambdaImpl r = acquire(PooledLambdaImpl.sPool);
|
||||
int lambdaType = LambdaType.encode(LambdaType.MASK_ARG_COUNT, type);
|
||||
r.setFlags(PooledLambdaImpl.MASK_FUNC_TYPE, lambdaType);
|
||||
r.setFlags(PooledLambdaImpl.MASK_EXPOSED_AS, lambdaType);
|
||||
return r;
|
||||
}
|
||||
|
||||
static PooledLambdaImpl acquire(Pool pool) {
|
||||
PooledLambdaImpl r = pool.acquire();
|
||||
if (r == null) r = new PooledLambdaImpl();
|
||||
r.mFlags &= ~FLAG_RECYCLED;
|
||||
r.setFlags(FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL,
|
||||
pool == sMessageCallbacksPool ? 1 : 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
private static void setIfInBounds(Object[] array, int i, Object a) {
|
||||
if (i < ArrayUtils.size(array)) array[i] = a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmniFunction<Object, Object, Object, Object, R> negate() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> OmniFunction<Object, Object, Object, Object, V> andThen(
|
||||
Function<? super R, ? extends V> after) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAsDouble() {
|
||||
return Double.longBitsToDouble(mConstValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
return (int) mConstValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAsLong() {
|
||||
return mConstValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmniFunction<Object, Object, Object, Object, R> recycleOnUse() {
|
||||
if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
|
||||
mFlags |= FLAG_RECYCLE_ON_USE;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean isRecycled() {
|
||||
return (mFlags & FLAG_RECYCLED) != 0;
|
||||
}
|
||||
|
||||
private boolean isRecycleOnUse() {
|
||||
return (mFlags & FLAG_RECYCLE_ON_USE) != 0;
|
||||
}
|
||||
|
||||
private boolean isInvocationArgAtIndex(int argIndex) {
|
||||
return (mFlags & (1 << argIndex)) != 0;
|
||||
}
|
||||
|
||||
int getFlags(int mask) {
|
||||
return unmask(mask, mFlags);
|
||||
}
|
||||
|
||||
void setFlags(int mask, int value) {
|
||||
mFlags &= ~mask;
|
||||
mFlags |= mask(mask, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 0xFF000, 0xAB -> 0xAB000
|
||||
*/
|
||||
private static int mask(int mask, int value) {
|
||||
return (value << Integer.numberOfTrailingZeros(mask)) & mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* 0xFF000, 0xAB123 -> 0xAB
|
||||
*/
|
||||
private static int unmask(int mask, int bits) {
|
||||
return (bits & mask) / (1 << Integer.numberOfTrailingZeros(mask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract for encoding a supported lambda type in {@link #MASK_BIT_COUNT} bits
|
||||
*/
|
||||
static class LambdaType {
|
||||
public static final int MASK_ARG_COUNT = 0b111;
|
||||
public static final int MASK_RETURN_TYPE = 0b111000;
|
||||
public static final int MASK = MASK_ARG_COUNT | MASK_RETURN_TYPE;
|
||||
public static final int MASK_BIT_COUNT = 6;
|
||||
|
||||
static int encode(int argCount, int returnType) {
|
||||
return mask(MASK_ARG_COUNT, argCount) | mask(MASK_RETURN_TYPE, returnType);
|
||||
}
|
||||
|
||||
static int decodeArgCount(int type) {
|
||||
return type & MASK_ARG_COUNT;
|
||||
}
|
||||
|
||||
static int decodeReturnType(int type) {
|
||||
return unmask(MASK_RETURN_TYPE, type);
|
||||
}
|
||||
|
||||
static String toString(int type) {
|
||||
int argCount = decodeArgCount(type);
|
||||
int returnType = decodeReturnType(type);
|
||||
if (argCount == 0) {
|
||||
if (returnType == ReturnType.VOID) return "Runnable";
|
||||
if (returnType == ReturnType.OBJECT || returnType == ReturnType.BOOLEAN) {
|
||||
return "Supplier";
|
||||
}
|
||||
}
|
||||
return argCountPrefix(argCount) + ReturnType.lambdaSuffix(returnType);
|
||||
}
|
||||
|
||||
private static String argCountPrefix(int argCount) {
|
||||
switch (argCount) {
|
||||
case MASK_ARG_COUNT: return "";
|
||||
case 1: return "";
|
||||
case 2: return "Bi";
|
||||
case 3: return "Tri";
|
||||
case 4: return "Quad";
|
||||
default: throw new IllegalArgumentException("" + argCount);
|
||||
}
|
||||
}
|
||||
|
||||
static class ReturnType {
|
||||
public static final int VOID = 1;
|
||||
public static final int BOOLEAN = 2;
|
||||
public static final int OBJECT = 3;
|
||||
public static final int INT = 4;
|
||||
public static final int LONG = 5;
|
||||
public static final int DOUBLE = 6;
|
||||
|
||||
static String toString(int returnType) {
|
||||
switch (returnType) {
|
||||
case VOID: return "VOID";
|
||||
case BOOLEAN: return "BOOLEAN";
|
||||
case OBJECT: return "OBJECT";
|
||||
case INT: return "INT";
|
||||
case LONG: return "LONG";
|
||||
case DOUBLE: return "DOUBLE";
|
||||
default: return "" + returnType;
|
||||
}
|
||||
}
|
||||
|
||||
static String lambdaSuffix(int type) {
|
||||
return prefix(type) + suffix(type);
|
||||
}
|
||||
|
||||
private static String prefix(int type) {
|
||||
switch (type) {
|
||||
case INT: return "Int";
|
||||
case LONG: return "Long";
|
||||
case DOUBLE: return "Double";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static String suffix(int type) {
|
||||
switch (type) {
|
||||
case VOID: return "Consumer";
|
||||
case BOOLEAN: return "Predicate";
|
||||
case OBJECT: return "Function";
|
||||
default: return "Supplier";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* {@link Predicate} + {@link PooledLambda}
|
||||
*
|
||||
* @see PooledLambda
|
||||
* @hide
|
||||
*/
|
||||
public interface PooledPredicate<T> extends PooledLambda, Predicate<T> {
|
||||
|
||||
/**
|
||||
* Ignores the result
|
||||
*/
|
||||
PooledConsumer<T> asConsumer();
|
||||
|
||||
/** @inheritDoc */
|
||||
PooledPredicate<T> recycleOnUse();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
|
||||
|
||||
/**
|
||||
* {@link Runnable} + {@link PooledLambda}
|
||||
*
|
||||
* @see PooledLambda
|
||||
* @hide
|
||||
*/
|
||||
public interface PooledRunnable extends PooledLambda, Runnable, ThrowingRunnable {
|
||||
/** @inheritDoc */
|
||||
PooledRunnable recycleOnUse();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.function.pooled;
|
||||
|
||||
import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
|
||||
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* {@link Supplier} + {@link PooledLambda}
|
||||
*
|
||||
* @see PooledLambda
|
||||
* @hide
|
||||
*/
|
||||
public interface PooledSupplier<T> extends PooledLambda, Supplier<T>, ThrowingSupplier<T> {
|
||||
|
||||
/**
|
||||
* Ignores the result
|
||||
*/
|
||||
PooledRunnable asRunnable();
|
||||
|
||||
/** @inheritDoc */
|
||||
PooledSupplier<T> recycleOnUse();
|
||||
|
||||
/** {@link PooledLambda} + {@link IntSupplier} */
|
||||
interface OfInt extends IntSupplier, PooledLambda {
|
||||
/** @inheritDoc */
|
||||
PooledSupplier.OfInt recycleOnUse();
|
||||
}
|
||||
|
||||
/** {@link PooledLambda} + {@link LongSupplier} */
|
||||
interface OfLong extends LongSupplier, PooledLambda {
|
||||
/** @inheritDoc */
|
||||
PooledSupplier.OfLong recycleOnUse();
|
||||
}
|
||||
|
||||
/** {@link PooledLambda} + {@link DoubleSupplier} */
|
||||
interface OfDouble extends DoubleSupplier, PooledLambda {
|
||||
/** @inheritDoc */
|
||||
PooledSupplier.OfDouble recycleOnUse();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import static com.android.internal.util.CollectionUtils.size;
|
||||
import static com.android.internal.util.Preconditions.checkArgument;
|
||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||
import static com.android.internal.util.Preconditions.checkState;
|
||||
import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.CheckResult;
|
||||
@@ -69,6 +70,7 @@ import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
import com.android.internal.util.function.pooled.PooledLambda;
|
||||
import com.android.server.FgThread;
|
||||
import com.android.server.SystemService;
|
||||
|
||||
@@ -440,32 +442,35 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
return;
|
||||
}
|
||||
|
||||
Binder.withCleanCallingIdentity(() -> {
|
||||
try {
|
||||
if (containsEither(packageInfo.requestedPermissions,
|
||||
Manifest.permission.RUN_IN_BACKGROUND,
|
||||
Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)) {
|
||||
mIdleController.addPowerSaveWhitelistApp(packageInfo.packageName);
|
||||
} else {
|
||||
mIdleController.removePowerSaveWhitelistApp(packageInfo.packageName);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
/* ignore - local call */
|
||||
}
|
||||
Binder.withCleanCallingIdentity(obtainRunnable(CompanionDeviceManagerService::
|
||||
updateSpecialAccessPermissionAsSystem, this, packageInfo).recycleOnUse());
|
||||
}
|
||||
|
||||
NetworkPolicyManager networkPolicyManager = NetworkPolicyManager.from(getContext());
|
||||
private void updateSpecialAccessPermissionAsSystem(PackageInfo packageInfo) {
|
||||
try {
|
||||
if (containsEither(packageInfo.requestedPermissions,
|
||||
Manifest.permission.USE_DATA_IN_BACKGROUND,
|
||||
Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND)) {
|
||||
networkPolicyManager.addUidPolicy(
|
||||
packageInfo.applicationInfo.uid,
|
||||
NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
|
||||
android.Manifest.permission.RUN_IN_BACKGROUND,
|
||||
android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)) {
|
||||
mIdleController.addPowerSaveWhitelistApp(packageInfo.packageName);
|
||||
} else {
|
||||
networkPolicyManager.removeUidPolicy(
|
||||
packageInfo.applicationInfo.uid,
|
||||
NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
|
||||
mIdleController.removePowerSaveWhitelistApp(packageInfo.packageName);
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
/* ignore - local call */
|
||||
}
|
||||
|
||||
NetworkPolicyManager networkPolicyManager = NetworkPolicyManager.from(getContext());
|
||||
if (containsEither(packageInfo.requestedPermissions,
|
||||
android.Manifest.permission.USE_DATA_IN_BACKGROUND,
|
||||
android.Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND)) {
|
||||
networkPolicyManager.addUidPolicy(
|
||||
packageInfo.applicationInfo.uid,
|
||||
NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
|
||||
} else {
|
||||
networkPolicyManager.removeUidPolicy(
|
||||
packageInfo.applicationInfo.uid,
|
||||
NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> boolean containsEither(T[] array, T a, T b) {
|
||||
@@ -474,17 +479,17 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
|
||||
|
||||
@Nullable
|
||||
private PackageInfo getPackageInfo(String packageName, int userId) {
|
||||
return Binder.withCleanCallingIdentity(() -> {
|
||||
return Binder.withCleanCallingIdentity(PooledLambda.obtainSupplier((context, pkg, id) -> {
|
||||
try {
|
||||
return getContext().getPackageManager().getPackageInfoAsUser(
|
||||
packageName,
|
||||
return context.getPackageManager().getPackageInfoAsUser(
|
||||
pkg,
|
||||
PackageManager.GET_PERMISSIONS | PackageManager.GET_CONFIGURATIONS,
|
||||
userId);
|
||||
id);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.e(LOG_TAG, "Failed to get PackageInfo for package " + packageName, e);
|
||||
Slog.e(LOG_TAG, "Failed to get PackageInfo for package " + pkg, e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}, getContext(), packageName, userId).recycleOnUse());
|
||||
}
|
||||
|
||||
private void recordAssociation(String priviledgedPackage, String deviceAddress) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import static com.android.internal.print.DumpUtils.writePrintJobInfo;
|
||||
import static com.android.internal.print.DumpUtils.writePrinterId;
|
||||
import static com.android.internal.print.DumpUtils.writePrinterInfo;
|
||||
import static com.android.internal.print.DumpUtils.writeStringIfNotNull;
|
||||
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -81,7 +82,6 @@ import com.android.internal.R;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.server.print.RemotePrintService.PrintServiceCallbacks;
|
||||
import com.android.server.print.RemotePrintServiceRecommendationService
|
||||
.RemotePrintServiceRecommendationServiceCallbacks;
|
||||
@@ -462,7 +462,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
|
||||
if (mPrinterDiscoverySession == null) {
|
||||
// If we do not have a session, tell all service to create one.
|
||||
mPrinterDiscoverySession = new PrinterDiscoverySessionMediator(mContext) {
|
||||
mPrinterDiscoverySession = new PrinterDiscoverySessionMediator() {
|
||||
@Override
|
||||
public void onDestroyed() {
|
||||
mPrinterDiscoverySession = null;
|
||||
@@ -1141,12 +1141,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
// just died. Do this off the main thread since we do to allow
|
||||
// calls into the spooler on the main thread.
|
||||
if (Looper.getMainLooper().isCurrentThread()) {
|
||||
BackgroundThread.getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
failScheduledPrintJobsForServiceInternal(serviceName);
|
||||
}
|
||||
});
|
||||
BackgroundThread.getHandler().sendMessage(obtainMessage(
|
||||
UserState::failScheduledPrintJobsForServiceInternal, this, serviceName));
|
||||
} else {
|
||||
failScheduledPrintJobsForServiceInternal(serviceName);
|
||||
}
|
||||
@@ -1341,18 +1337,13 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
|
||||
private final List<PrinterId> mStateTrackedPrinters = new ArrayList<PrinterId>();
|
||||
|
||||
private final Handler mSessionHandler;
|
||||
|
||||
private boolean mIsDestroyed;
|
||||
|
||||
public PrinterDiscoverySessionMediator(Context context) {
|
||||
mSessionHandler = new SessionHandler(context.getMainLooper());
|
||||
PrinterDiscoverySessionMediator() {
|
||||
// Kick off the session creation.
|
||||
List<RemotePrintService> services = new ArrayList<RemotePrintService>(
|
||||
mActiveServices.values());
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION, services)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(UserState.PrinterDiscoverySessionMediator::
|
||||
handleDispatchCreatePrinterDiscoverySession,
|
||||
this, new ArrayList<>(mActiveServices.values())));
|
||||
}
|
||||
|
||||
public void addObserverLocked(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
@@ -1361,12 +1352,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
|
||||
// Bring the added observer up to speed with the printers.
|
||||
if (!mPrinters.isEmpty()) {
|
||||
List<PrinterInfo> printers = new ArrayList<PrinterInfo>(mPrinters.values());
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = observer;
|
||||
args.arg2 = printers;
|
||||
mSessionHandler.obtainMessage(SessionHandler.MSG_PRINTERS_ADDED,
|
||||
args).sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
UserState.PrinterDiscoverySessionMediator::handlePrintersAdded,
|
||||
this, observer, new ArrayList<>(mPrinters.values())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1403,14 +1391,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
return;
|
||||
}
|
||||
|
||||
List<RemotePrintService> services = new ArrayList<RemotePrintService>(
|
||||
mActiveServices.values());
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = services;
|
||||
args.arg2 = priorityList;
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_DISPATCH_START_PRINTER_DISCOVERY, args)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(UserState.PrinterDiscoverySessionMediator::
|
||||
handleDispatchStartPrinterDiscovery, this,
|
||||
new ArrayList<>(mActiveServices.values()), priorityList));
|
||||
}
|
||||
|
||||
public final void stopPrinterDiscoveryLocked(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
@@ -1426,11 +1409,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
if (!mStartedPrinterDiscoveryTokens.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<RemotePrintService> services = new ArrayList<RemotePrintService>(
|
||||
mActiveServices.values());
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_DISPATCH_STOP_PRINTER_DISCOVERY, services)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(UserState.PrinterDiscoverySessionMediator::
|
||||
handleDispatchStopPrinterDiscovery,
|
||||
this, new ArrayList<>(mActiveServices.values())));
|
||||
}
|
||||
|
||||
public void validatePrintersLocked(@NonNull List<PrinterId> printerIds) {
|
||||
@@ -1461,12 +1442,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
// Schedule a notification of the service.
|
||||
RemotePrintService service = mActiveServices.get(serviceName);
|
||||
if (service != null) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = service;
|
||||
args.arg2 = updateList;
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_VALIDATE_PRINTERS, args)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
UserState.PrinterDiscoverySessionMediator::handleValidatePrinters,
|
||||
this, service, updateList));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1493,12 +1471,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
return;
|
||||
}
|
||||
// Ask the service to start tracking.
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = service;
|
||||
args.arg2 = printerId;
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_START_PRINTER_STATE_TRACKING, args)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(UserState.PrinterDiscoverySessionMediator::
|
||||
handleStartPrinterStateTracking, this, service, printerId));
|
||||
}
|
||||
|
||||
public final void stopPrinterStateTrackingLocked(PrinterId printerId) {
|
||||
@@ -1520,12 +1494,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
return;
|
||||
}
|
||||
// Ask the service to start tracking.
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = service;
|
||||
args.arg2 = printerId;
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_STOP_PRINTER_STATE_TRACKING, args)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(UserState.PrinterDiscoverySessionMediator::
|
||||
handleStopPrinterStateTracking, this, service, printerId));
|
||||
}
|
||||
|
||||
public void onDestroyed() {
|
||||
@@ -1551,11 +1521,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
stopPrinterDiscoveryLocked(IPrinterDiscoveryObserver.Stub.asInterface(token));
|
||||
}
|
||||
// Tell the services we are done.
|
||||
List<RemotePrintService> services = new ArrayList<RemotePrintService>(
|
||||
mActiveServices.values());
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION, services)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(UserState.PrinterDiscoverySessionMediator::
|
||||
handleDispatchDestroyPrinterDiscoverySession,
|
||||
this, new ArrayList<>(mActiveServices.values())));
|
||||
}
|
||||
|
||||
public void onPrintersAddedLocked(List<PrinterInfo> printers) {
|
||||
@@ -1579,8 +1547,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
}
|
||||
}
|
||||
if (addedPrinters != null) {
|
||||
mSessionHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_ADDED,
|
||||
addedPrinters).sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
UserState.PrinterDiscoverySessionMediator::handleDispatchPrintersAdded,
|
||||
this, addedPrinters));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1604,8 +1573,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
}
|
||||
}
|
||||
if (removedPrinterIds != null) {
|
||||
mSessionHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
|
||||
removedPrinterIds).sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
UserState.PrinterDiscoverySessionMediator::handleDispatchPrintersRemoved,
|
||||
this, removedPrinterIds));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1646,8 +1616,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
|
||||
ArrayList<PrinterInfo> addedPrinters = new ArrayList<>(1);
|
||||
addedPrinters.add(newPrinter);
|
||||
mSessionHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_ADDED,
|
||||
addedPrinters).sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
UserState.PrinterDiscoverySessionMediator::handleDispatchPrintersAdded,
|
||||
this, addedPrinters));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1661,26 +1632,20 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
return;
|
||||
}
|
||||
// Tell the service to create a session.
|
||||
mSessionHandler.obtainMessage(
|
||||
SessionHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
|
||||
service).sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
RemotePrintService::createPrinterDiscoverySession, service));
|
||||
// Start printer discovery if necessary.
|
||||
if (!mStartedPrinterDiscoveryTokens.isEmpty()) {
|
||||
mSessionHandler.obtainMessage(
|
||||
SessionHandler.MSG_START_PRINTER_DISCOVERY,
|
||||
service).sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
RemotePrintService::startPrinterDiscovery, service, null));
|
||||
}
|
||||
// Start tracking printers if necessary
|
||||
final int trackedPrinterCount = mStateTrackedPrinters.size();
|
||||
for (int i = 0; i < trackedPrinterCount; i++) {
|
||||
PrinterId printerId = mStateTrackedPrinters.get(i);
|
||||
if (printerId.getServiceName().equals(service.getComponentName())) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = service;
|
||||
args.arg2 = printerId;
|
||||
mSessionHandler.obtainMessage(SessionHandler
|
||||
.MSG_START_PRINTER_STATE_TRACKING, args)
|
||||
.sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
RemotePrintService::startPrinterStateTracking, service, printerId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1781,9 +1746,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
for (int i = 0; i < removedPrinterCount; i++) {
|
||||
mPrinters.remove(removedPrinterIds.get(i));
|
||||
}
|
||||
mSessionHandler.obtainMessage(
|
||||
SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
|
||||
removedPrinterIds).sendToTarget();
|
||||
Handler.getMain().sendMessage(obtainMessage(
|
||||
UserState.PrinterDiscoverySessionMediator::handleDispatchPrintersRemoved,
|
||||
this, removedPrinterIds));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1873,134 +1838,6 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
Log.e(LOG_TAG, "Error sending removed printers", re);
|
||||
}
|
||||
}
|
||||
|
||||
private final class SessionHandler extends Handler {
|
||||
public static final int MSG_PRINTERS_ADDED = 1;
|
||||
public static final int MSG_PRINTERS_REMOVED = 2;
|
||||
public static final int MSG_DISPATCH_PRINTERS_ADDED = 3;
|
||||
public static final int MSG_DISPATCH_PRINTERS_REMOVED = 4;
|
||||
|
||||
public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 5;
|
||||
public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 6;
|
||||
public static final int MSG_START_PRINTER_DISCOVERY = 7;
|
||||
public static final int MSG_STOP_PRINTER_DISCOVERY = 8;
|
||||
public static final int MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION = 9;
|
||||
public static final int MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION = 10;
|
||||
public static final int MSG_DISPATCH_START_PRINTER_DISCOVERY = 11;
|
||||
public static final int MSG_DISPATCH_STOP_PRINTER_DISCOVERY = 12;
|
||||
public static final int MSG_VALIDATE_PRINTERS = 13;
|
||||
public static final int MSG_START_PRINTER_STATE_TRACKING = 14;
|
||||
public static final int MSG_STOP_PRINTER_STATE_TRACKING = 15;
|
||||
public static final int MSG_DESTROY_SERVICE = 16;
|
||||
|
||||
SessionHandler(Looper looper) {
|
||||
super(looper, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case MSG_PRINTERS_ADDED: {
|
||||
SomeArgs args = (SomeArgs) message.obj;
|
||||
IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg1;
|
||||
List<PrinterInfo> addedPrinters = (List<PrinterInfo>) args.arg2;
|
||||
args.recycle();
|
||||
handlePrintersAdded(observer, addedPrinters);
|
||||
} break;
|
||||
|
||||
case MSG_PRINTERS_REMOVED: {
|
||||
SomeArgs args = (SomeArgs) message.obj;
|
||||
IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg1;
|
||||
List<PrinterId> removedPrinterIds = (List<PrinterId>) args.arg2;
|
||||
args.recycle();
|
||||
handlePrintersRemoved(observer, removedPrinterIds);
|
||||
}
|
||||
|
||||
case MSG_DISPATCH_PRINTERS_ADDED: {
|
||||
List<PrinterInfo> addedPrinters = (List<PrinterInfo>) message.obj;
|
||||
handleDispatchPrintersAdded(addedPrinters);
|
||||
} break;
|
||||
|
||||
case MSG_DISPATCH_PRINTERS_REMOVED: {
|
||||
List<PrinterId> removedPrinterIds = (List<PrinterId>) message.obj;
|
||||
handleDispatchPrintersRemoved(removedPrinterIds);
|
||||
} break;
|
||||
|
||||
case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
|
||||
RemotePrintService service = (RemotePrintService) message.obj;
|
||||
service.createPrinterDiscoverySession();
|
||||
} break;
|
||||
|
||||
case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
|
||||
RemotePrintService service = (RemotePrintService) message.obj;
|
||||
service.destroyPrinterDiscoverySession();
|
||||
} break;
|
||||
|
||||
case MSG_START_PRINTER_DISCOVERY: {
|
||||
RemotePrintService service = (RemotePrintService) message.obj;
|
||||
service.startPrinterDiscovery(null);
|
||||
} break;
|
||||
|
||||
case MSG_STOP_PRINTER_DISCOVERY: {
|
||||
RemotePrintService service = (RemotePrintService) message.obj;
|
||||
service.stopPrinterDiscovery();
|
||||
} break;
|
||||
|
||||
case MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION: {
|
||||
List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
|
||||
handleDispatchCreatePrinterDiscoverySession(services);
|
||||
} break;
|
||||
|
||||
case MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION: {
|
||||
List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
|
||||
handleDispatchDestroyPrinterDiscoverySession(services);
|
||||
} break;
|
||||
|
||||
case MSG_DISPATCH_START_PRINTER_DISCOVERY: {
|
||||
SomeArgs args = (SomeArgs) message.obj;
|
||||
List<RemotePrintService> services = (List<RemotePrintService>) args.arg1;
|
||||
List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
|
||||
args.recycle();
|
||||
handleDispatchStartPrinterDiscovery(services, printerIds);
|
||||
} break;
|
||||
|
||||
case MSG_DISPATCH_STOP_PRINTER_DISCOVERY: {
|
||||
List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
|
||||
handleDispatchStopPrinterDiscovery(services);
|
||||
} break;
|
||||
|
||||
case MSG_VALIDATE_PRINTERS: {
|
||||
SomeArgs args = (SomeArgs) message.obj;
|
||||
RemotePrintService service = (RemotePrintService) args.arg1;
|
||||
List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
|
||||
args.recycle();
|
||||
handleValidatePrinters(service, printerIds);
|
||||
} break;
|
||||
|
||||
case MSG_START_PRINTER_STATE_TRACKING: {
|
||||
SomeArgs args = (SomeArgs) message.obj;
|
||||
RemotePrintService service = (RemotePrintService) args.arg1;
|
||||
PrinterId printerId = (PrinterId) args.arg2;
|
||||
args.recycle();
|
||||
handleStartPrinterStateTracking(service, printerId);
|
||||
} break;
|
||||
|
||||
case MSG_STOP_PRINTER_STATE_TRACKING: {
|
||||
SomeArgs args = (SomeArgs) message.obj;
|
||||
RemotePrintService service = (RemotePrintService) args.arg1;
|
||||
PrinterId printerId = (PrinterId) args.arg2;
|
||||
args.recycle();
|
||||
handleStopPrinterStateTracking(service, printerId);
|
||||
} break;
|
||||
|
||||
case MSG_DESTROY_SERVICE: {
|
||||
RemotePrintService service = (RemotePrintService) message.obj;
|
||||
service.destroy();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class PrintJobForAppCache {
|
||||
|
||||
@@ -103,7 +103,7 @@ public class DpmMockContext extends MockContext {
|
||||
long callingIdentity = clearCallingIdentity();
|
||||
Throwable throwableToPropagate = null;
|
||||
try {
|
||||
action.run();
|
||||
action.runOrThrow();
|
||||
} catch (Throwable throwable) {
|
||||
throwableToPropagate = throwable;
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user