Loading core/api/current.txt +3 −1 Original line number Diff line number Diff line Loading @@ -33261,7 +33261,7 @@ package android.os { } public interface IBinder { method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default void addFrozenStateChangeCallback(@NonNull android.os.IBinder.FrozenStateChangeCallback) throws android.os.RemoteException; method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default void addFrozenStateChangeCallback(@NonNull java.util.concurrent.Executor, @NonNull android.os.IBinder.FrozenStateChangeCallback) throws android.os.RemoteException; method public void dump(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException; method public void dumpAsync(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException; method @Nullable public String getInterfaceDescriptor() throws android.os.RemoteException; Loading Loading @@ -33885,6 +33885,7 @@ package android.os { method public void finishBroadcast(); method public Object getBroadcastCookie(int); method public E getBroadcastItem(int); method @FlaggedApi("android.os.binder_frozen_state_change_callback") @Nullable public java.util.concurrent.Executor getExecutor(); method @FlaggedApi("android.os.binder_frozen_state_change_callback") public int getFrozenCalleePolicy(); method @FlaggedApi("android.os.binder_frozen_state_change_callback") public int getMaxQueueSize(); method public Object getRegisteredCallbackCookie(int); Loading @@ -33905,6 +33906,7 @@ package android.os { @FlaggedApi("android.os.binder_frozen_state_change_callback") public static final class RemoteCallbackList.Builder<E extends android.os.IInterface> { ctor public RemoteCallbackList.Builder(int); method @NonNull public android.os.RemoteCallbackList<E> build(); method @NonNull public android.os.RemoteCallbackList.Builder setExecutor(@NonNull java.util.concurrent.Executor); method @NonNull public android.os.RemoteCallbackList.Builder setInterfaceDiedCallback(@NonNull android.os.RemoteCallbackList.Builder.InterfaceDiedCallback<E>); method @NonNull public android.os.RemoteCallbackList.Builder setMaxQueueSize(int); } core/java/android/os/BinderProxy.java +23 −11 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; Loading Loading @@ -651,28 +652,39 @@ public final class BinderProxy implements IBinder { private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags); /** * This list is to hold strong reference to the frozen state callbacks. The callbacks are only * weakly referenced by JNI so the strong references here are needed to keep the callbacks * around until the proxy is GC'ed. * This map is to hold strong reference to the frozen state callbacks. * * The callbacks are only weakly referenced by JNI so the strong references here are needed to * keep the callbacks around until the proxy is GC'ed. * * The key is the original callback passed into {@link #addFrozenStateChangeCallback}. The value * is the wrapped callback created in {@link #addFrozenStateChangeCallback} to dispatch the * calls on the desired executor. */ private List<FrozenStateChangeCallback> mFrozenStateChangeCallbacks = Collections.synchronizedList(new ArrayList<>()); private Map<FrozenStateChangeCallback, FrozenStateChangeCallback> mFrozenStateChangeCallbacks = Collections.synchronizedMap(new HashMap<>()); /** * See {@link IBinder#addFrozenStateChangeCallback(FrozenStateChangeCallback)} */ public void addFrozenStateChangeCallback(FrozenStateChangeCallback callback) public void addFrozenStateChangeCallback(Executor executor, FrozenStateChangeCallback callback) throws RemoteException { addFrozenStateChangeCallbackNative(callback); mFrozenStateChangeCallbacks.add(callback); FrozenStateChangeCallback wrappedCallback = (who, state) -> executor.execute(() -> callback.onFrozenStateChanged(who, state)); addFrozenStateChangeCallbackNative(wrappedCallback); mFrozenStateChangeCallbacks.put(callback, wrappedCallback); } /** * See {@link IBinder#removeFrozenStateChangeCallback} */ public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback) { mFrozenStateChangeCallbacks.remove(callback); return removeFrozenStateChangeCallbackNative(callback); public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback) throws IllegalArgumentException { FrozenStateChangeCallback wrappedCallback = mFrozenStateChangeCallbacks.remove(callback); if (wrappedCallback == null) { throw new IllegalArgumentException("callback not found"); } return removeFrozenStateChangeCallbackNative(wrappedCallback); } private native void addFrozenStateChangeCallbackNative(FrozenStateChangeCallback callback) Loading core/java/android/os/IBinder.java +38 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; Loading @@ -25,6 +26,7 @@ import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.Executor; /** * Base interface for a remotable object, the core part of a lightweight Loading Loading @@ -397,12 +399,31 @@ public interface IBinder { @interface State { } /** * Represents the frozen state of the remote process. * * While in this state, the remote process won't be able to receive and handle a * transaction. Therefore, any asynchronous transactions will be buffered and delivered when * the process is unfrozen, and any synchronous transactions will result in an error. * * Buffered transactions may be stale by the time that the process is unfrozen and handles * them. To avoid overwhelming the remote process with stale events or overflowing their * buffers, it's best to avoid sending binder transactions to a frozen process. */ int STATE_FROZEN = 0; /** * Represents the unfrozen state of the remote process. * * In this state, the process hosting the object can execute and is not restricted * by the freezer from using the CPU or responding to binder transactions. */ int STATE_UNFROZEN = 1; /** * Interface for receiving a callback when the process hosting an IBinder * has changed its frozen state. * * @param who The IBinder whose hosting process has changed state. * @param state The latest state. */ Loading @@ -427,15 +448,31 @@ public interface IBinder { * <p>You will only receive state change notifications for remote binders, as local binders by * definition can't be frozen without you being frozen too.</p> * * @param executor The executor on which to run the callback. * @param callback The callback used to deliver state change notifications. * * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support * this feature. */ @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK) default void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback) default void addFrozenStateChangeCallback( @NonNull @CallbackExecutor Executor executor, @NonNull FrozenStateChangeCallback callback) throws RemoteException { throw new UnsupportedOperationException(); } /** * Same as {@link #addFrozenStateChangeCallback(Executor, FrozenStateChangeCallback)} except * that callbacks are invoked on a binder thread. * * @hide */ default void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback) throws RemoteException { addFrozenStateChangeCallback(Runnable::run, callback); } /** * Unregister a {@link FrozenStateChangeCallback}. The callback will no longer be invoked when * the hosting process changes its frozen state. Loading core/java/android/os/RemoteCallbackList.java +41 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; Loading @@ -29,6 +30,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.Consumer; Loading Loading @@ -134,6 +136,7 @@ public class RemoteCallbackList<E extends IInterface> { private final @FrozenCalleePolicy int mFrozenCalleePolicy; private final int mMaxQueueSize; private final Executor mExecutor; private final class Interface implements IBinder.DeathRecipient, IBinder.FrozenStateChangeCallback { Loading Loading @@ -197,7 +200,7 @@ public class RemoteCallbackList<E extends IInterface> { void maybeSubscribeToFrozenCallback() throws RemoteException { if (mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) { try { mBinder.addFrozenStateChangeCallback(this); mBinder.addFrozenStateChangeCallback(mExecutor, this); } catch (UnsupportedOperationException e) { // The kernel does not support frozen notifications. In this case we want to // silently fall back to FROZEN_CALLEE_POLICY_UNSET. This is done by simply Loading Loading @@ -237,6 +240,7 @@ public class RemoteCallbackList<E extends IInterface> { private @FrozenCalleePolicy int mFrozenCalleePolicy; private int mMaxQueueSize = DEFAULT_MAX_QUEUE_SIZE; private InterfaceDiedCallback mInterfaceDiedCallback; private Executor mExecutor; /** * Creates a Builder for {@link RemoteCallbackList}. Loading Loading @@ -284,6 +288,18 @@ public class RemoteCallbackList<E extends IInterface> { return this; } /** * Sets the executor to be used when invoking callbacks asynchronously. * * This is only used when callbacks need to be invoked asynchronously, e.g. when the process * hosting a callback becomes unfrozen. Callbacks that can be invoked immediately run on the * same thread that calls {@link #broadcast} synchronously. */ public @NonNull Builder setExecutor(@NonNull @CallbackExecutor Executor executor) { mExecutor = executor; return this; } /** * For notifying when the process hosting a callback interface has died. * Loading @@ -308,15 +324,21 @@ public class RemoteCallbackList<E extends IInterface> { * @return The built {@link RemoteCallbackList} object. */ public @NonNull RemoteCallbackList<E> build() { Executor executor = mExecutor; if (executor == null && mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) { // TODO Throw an exception here once the existing API caller is updated to provide // an executor. executor = new HandlerExecutor(Handler.getMain()); } if (mInterfaceDiedCallback != null) { return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize) { return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize, executor) { @Override public void onCallbackDied(E deadInterface, Object cookie) { mInterfaceDiedCallback.onInterfaceDied(this, deadInterface, cookie); } }; } return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize); return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize, executor); } } Loading @@ -340,6 +362,16 @@ public class RemoteCallbackList<E extends IInterface> { return mMaxQueueSize; } /** * Returns the executor used when invoking callbacks asynchronously. * * @return The executor. */ @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK) public @Nullable Executor getExecutor() { return mExecutor; } /** * Creates a RemoteCallbackList with {@link #FROZEN_CALLEE_POLICY_UNSET}. This is equivalent to * <pre> Loading @@ -347,7 +379,7 @@ public class RemoteCallbackList<E extends IInterface> { * </pre> */ public RemoteCallbackList() { this(FROZEN_CALLEE_POLICY_UNSET, DEFAULT_MAX_QUEUE_SIZE); this(FROZEN_CALLEE_POLICY_UNSET, DEFAULT_MAX_QUEUE_SIZE, null); } /** Loading @@ -362,10 +394,14 @@ public class RemoteCallbackList<E extends IInterface> { * recipient's process is frozen. Once the limit is reached, the oldest callbacks would be * dropped to keep the size under limit. Ignored except for * {@link #FROZEN_CALLEE_POLICY_ENQUEUE_ALL}. * * @param executor The executor used when invoking callbacks asynchronously. */ private RemoteCallbackList(@FrozenCalleePolicy int frozenCalleePolicy, int maxQueueSize) { private RemoteCallbackList(@FrozenCalleePolicy int frozenCalleePolicy, int maxQueueSize, @CallbackExecutor Executor executor) { mFrozenCalleePolicy = frozenCalleePolicy; mMaxQueueSize = maxQueueSize; mExecutor = executor; } /** Loading core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java +3 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.frameworks.coretests.bfscctestapp; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.RemoteException; Loading @@ -36,6 +38,7 @@ public class BfsccTestAppCmdService extends Service { @Override public void listenTo(IBinder binder) throws RemoteException { binder.addFrozenStateChangeCallback( new HandlerExecutor(Handler.getMain()), (IBinder who, int state) -> mNotifications.offer(state)); } Loading Loading
core/api/current.txt +3 −1 Original line number Diff line number Diff line Loading @@ -33261,7 +33261,7 @@ package android.os { } public interface IBinder { method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default void addFrozenStateChangeCallback(@NonNull android.os.IBinder.FrozenStateChangeCallback) throws android.os.RemoteException; method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default void addFrozenStateChangeCallback(@NonNull java.util.concurrent.Executor, @NonNull android.os.IBinder.FrozenStateChangeCallback) throws android.os.RemoteException; method public void dump(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException; method public void dumpAsync(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException; method @Nullable public String getInterfaceDescriptor() throws android.os.RemoteException; Loading Loading @@ -33885,6 +33885,7 @@ package android.os { method public void finishBroadcast(); method public Object getBroadcastCookie(int); method public E getBroadcastItem(int); method @FlaggedApi("android.os.binder_frozen_state_change_callback") @Nullable public java.util.concurrent.Executor getExecutor(); method @FlaggedApi("android.os.binder_frozen_state_change_callback") public int getFrozenCalleePolicy(); method @FlaggedApi("android.os.binder_frozen_state_change_callback") public int getMaxQueueSize(); method public Object getRegisteredCallbackCookie(int); Loading @@ -33905,6 +33906,7 @@ package android.os { @FlaggedApi("android.os.binder_frozen_state_change_callback") public static final class RemoteCallbackList.Builder<E extends android.os.IInterface> { ctor public RemoteCallbackList.Builder(int); method @NonNull public android.os.RemoteCallbackList<E> build(); method @NonNull public android.os.RemoteCallbackList.Builder setExecutor(@NonNull java.util.concurrent.Executor); method @NonNull public android.os.RemoteCallbackList.Builder setInterfaceDiedCallback(@NonNull android.os.RemoteCallbackList.Builder.InterfaceDiedCallback<E>); method @NonNull public android.os.RemoteCallbackList.Builder setMaxQueueSize(int); }
core/java/android/os/BinderProxy.java +23 −11 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; Loading Loading @@ -651,28 +652,39 @@ public final class BinderProxy implements IBinder { private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags); /** * This list is to hold strong reference to the frozen state callbacks. The callbacks are only * weakly referenced by JNI so the strong references here are needed to keep the callbacks * around until the proxy is GC'ed. * This map is to hold strong reference to the frozen state callbacks. * * The callbacks are only weakly referenced by JNI so the strong references here are needed to * keep the callbacks around until the proxy is GC'ed. * * The key is the original callback passed into {@link #addFrozenStateChangeCallback}. The value * is the wrapped callback created in {@link #addFrozenStateChangeCallback} to dispatch the * calls on the desired executor. */ private List<FrozenStateChangeCallback> mFrozenStateChangeCallbacks = Collections.synchronizedList(new ArrayList<>()); private Map<FrozenStateChangeCallback, FrozenStateChangeCallback> mFrozenStateChangeCallbacks = Collections.synchronizedMap(new HashMap<>()); /** * See {@link IBinder#addFrozenStateChangeCallback(FrozenStateChangeCallback)} */ public void addFrozenStateChangeCallback(FrozenStateChangeCallback callback) public void addFrozenStateChangeCallback(Executor executor, FrozenStateChangeCallback callback) throws RemoteException { addFrozenStateChangeCallbackNative(callback); mFrozenStateChangeCallbacks.add(callback); FrozenStateChangeCallback wrappedCallback = (who, state) -> executor.execute(() -> callback.onFrozenStateChanged(who, state)); addFrozenStateChangeCallbackNative(wrappedCallback); mFrozenStateChangeCallbacks.put(callback, wrappedCallback); } /** * See {@link IBinder#removeFrozenStateChangeCallback} */ public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback) { mFrozenStateChangeCallbacks.remove(callback); return removeFrozenStateChangeCallbackNative(callback); public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback) throws IllegalArgumentException { FrozenStateChangeCallback wrappedCallback = mFrozenStateChangeCallbacks.remove(callback); if (wrappedCallback == null) { throw new IllegalArgumentException("callback not found"); } return removeFrozenStateChangeCallbackNative(wrappedCallback); } private native void addFrozenStateChangeCallbackNative(FrozenStateChangeCallback callback) Loading
core/java/android/os/IBinder.java +38 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; Loading @@ -25,6 +26,7 @@ import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.Executor; /** * Base interface for a remotable object, the core part of a lightweight Loading Loading @@ -397,12 +399,31 @@ public interface IBinder { @interface State { } /** * Represents the frozen state of the remote process. * * While in this state, the remote process won't be able to receive and handle a * transaction. Therefore, any asynchronous transactions will be buffered and delivered when * the process is unfrozen, and any synchronous transactions will result in an error. * * Buffered transactions may be stale by the time that the process is unfrozen and handles * them. To avoid overwhelming the remote process with stale events or overflowing their * buffers, it's best to avoid sending binder transactions to a frozen process. */ int STATE_FROZEN = 0; /** * Represents the unfrozen state of the remote process. * * In this state, the process hosting the object can execute and is not restricted * by the freezer from using the CPU or responding to binder transactions. */ int STATE_UNFROZEN = 1; /** * Interface for receiving a callback when the process hosting an IBinder * has changed its frozen state. * * @param who The IBinder whose hosting process has changed state. * @param state The latest state. */ Loading @@ -427,15 +448,31 @@ public interface IBinder { * <p>You will only receive state change notifications for remote binders, as local binders by * definition can't be frozen without you being frozen too.</p> * * @param executor The executor on which to run the callback. * @param callback The callback used to deliver state change notifications. * * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support * this feature. */ @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK) default void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback) default void addFrozenStateChangeCallback( @NonNull @CallbackExecutor Executor executor, @NonNull FrozenStateChangeCallback callback) throws RemoteException { throw new UnsupportedOperationException(); } /** * Same as {@link #addFrozenStateChangeCallback(Executor, FrozenStateChangeCallback)} except * that callbacks are invoked on a binder thread. * * @hide */ default void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback) throws RemoteException { addFrozenStateChangeCallback(Runnable::run, callback); } /** * Unregister a {@link FrozenStateChangeCallback}. The callback will no longer be invoked when * the hosting process changes its frozen state. Loading
core/java/android/os/RemoteCallbackList.java +41 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; Loading @@ -29,6 +30,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.Consumer; Loading Loading @@ -134,6 +136,7 @@ public class RemoteCallbackList<E extends IInterface> { private final @FrozenCalleePolicy int mFrozenCalleePolicy; private final int mMaxQueueSize; private final Executor mExecutor; private final class Interface implements IBinder.DeathRecipient, IBinder.FrozenStateChangeCallback { Loading Loading @@ -197,7 +200,7 @@ public class RemoteCallbackList<E extends IInterface> { void maybeSubscribeToFrozenCallback() throws RemoteException { if (mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) { try { mBinder.addFrozenStateChangeCallback(this); mBinder.addFrozenStateChangeCallback(mExecutor, this); } catch (UnsupportedOperationException e) { // The kernel does not support frozen notifications. In this case we want to // silently fall back to FROZEN_CALLEE_POLICY_UNSET. This is done by simply Loading Loading @@ -237,6 +240,7 @@ public class RemoteCallbackList<E extends IInterface> { private @FrozenCalleePolicy int mFrozenCalleePolicy; private int mMaxQueueSize = DEFAULT_MAX_QUEUE_SIZE; private InterfaceDiedCallback mInterfaceDiedCallback; private Executor mExecutor; /** * Creates a Builder for {@link RemoteCallbackList}. Loading Loading @@ -284,6 +288,18 @@ public class RemoteCallbackList<E extends IInterface> { return this; } /** * Sets the executor to be used when invoking callbacks asynchronously. * * This is only used when callbacks need to be invoked asynchronously, e.g. when the process * hosting a callback becomes unfrozen. Callbacks that can be invoked immediately run on the * same thread that calls {@link #broadcast} synchronously. */ public @NonNull Builder setExecutor(@NonNull @CallbackExecutor Executor executor) { mExecutor = executor; return this; } /** * For notifying when the process hosting a callback interface has died. * Loading @@ -308,15 +324,21 @@ public class RemoteCallbackList<E extends IInterface> { * @return The built {@link RemoteCallbackList} object. */ public @NonNull RemoteCallbackList<E> build() { Executor executor = mExecutor; if (executor == null && mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) { // TODO Throw an exception here once the existing API caller is updated to provide // an executor. executor = new HandlerExecutor(Handler.getMain()); } if (mInterfaceDiedCallback != null) { return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize) { return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize, executor) { @Override public void onCallbackDied(E deadInterface, Object cookie) { mInterfaceDiedCallback.onInterfaceDied(this, deadInterface, cookie); } }; } return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize); return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize, executor); } } Loading @@ -340,6 +362,16 @@ public class RemoteCallbackList<E extends IInterface> { return mMaxQueueSize; } /** * Returns the executor used when invoking callbacks asynchronously. * * @return The executor. */ @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK) public @Nullable Executor getExecutor() { return mExecutor; } /** * Creates a RemoteCallbackList with {@link #FROZEN_CALLEE_POLICY_UNSET}. This is equivalent to * <pre> Loading @@ -347,7 +379,7 @@ public class RemoteCallbackList<E extends IInterface> { * </pre> */ public RemoteCallbackList() { this(FROZEN_CALLEE_POLICY_UNSET, DEFAULT_MAX_QUEUE_SIZE); this(FROZEN_CALLEE_POLICY_UNSET, DEFAULT_MAX_QUEUE_SIZE, null); } /** Loading @@ -362,10 +394,14 @@ public class RemoteCallbackList<E extends IInterface> { * recipient's process is frozen. Once the limit is reached, the oldest callbacks would be * dropped to keep the size under limit. Ignored except for * {@link #FROZEN_CALLEE_POLICY_ENQUEUE_ALL}. * * @param executor The executor used when invoking callbacks asynchronously. */ private RemoteCallbackList(@FrozenCalleePolicy int frozenCalleePolicy, int maxQueueSize) { private RemoteCallbackList(@FrozenCalleePolicy int frozenCalleePolicy, int maxQueueSize, @CallbackExecutor Executor executor) { mFrozenCalleePolicy = frozenCalleePolicy; mMaxQueueSize = maxQueueSize; mExecutor = executor; } /** Loading
core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java +3 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.frameworks.coretests.bfscctestapp; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.RemoteException; Loading @@ -36,6 +38,7 @@ public class BfsccTestAppCmdService extends Service { @Override public void listenTo(IBinder binder) throws RemoteException { binder.addFrozenStateChangeCallback( new HandlerExecutor(Handler.getMain()), (IBinder who, int state) -> mNotifications.offer(state)); } Loading