Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a0bc1ef authored by Yu-Ting Tseng's avatar Yu-Ting Tseng
Browse files

Add InterfaceDiedCallback to RemoteCallbackList

Some of the existing uses of RemoteCallbackList extend the class to
override onCallbackDied. However with the Builder pattern it is no
longer possible to do so.

This change offers an alternative that works with the Builder pattern. A
new Builder API setInterfaceDiedCallback() is added to allow the caller
to provide custom death handling logic.

Flag: android.os.binder_frozen_state_change_callback
Change-Id: Ib777d9920d8332a09a6da3601ad3bab071fb9cba
Test: atest --instant android.os.cts.RemoteCallbackListTest
Bug: 361157077
API-Coverage-Bug: 372923111
parent feaf5240
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -33998,9 +33998,14 @@ 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 setInterfaceDiedCallback(@NonNull android.os.RemoteCallbackList.Builder.InterfaceDiedCallback<E>);
    method @NonNull public android.os.RemoteCallbackList.Builder setMaxQueueSize(int);
  }
  @FlaggedApi("android.os.binder_frozen_state_change_callback") public static interface RemoteCallbackList.Builder.InterfaceDiedCallback<E extends android.os.IInterface> {
    method public void onInterfaceDied(@NonNull android.os.RemoteCallbackList<E>, E, @Nullable Object);
  }
  public class RemoteException extends android.util.AndroidException {
    ctor public RemoteException();
    ctor public RemoteException(String);
+2 −0
Original line number Diff line number Diff line
@@ -395,6 +395,8 @@ KotlinOperator: android.graphics.Matrix44#set(int, int, float):
    Method can be invoked with an indexing operator from Kotlin: `set` (this is usually desirable; just make sure it makes sense for this type of object)


MissingGetterMatchingBuilder: android.os.RemoteCallbackList.Builder#setInterfaceDiedCallback(android.os.RemoteCallbackList.Builder.InterfaceDiedCallback<E>):
    android.os.RemoteCallbackList does not declare a `getInterfaceDiedCallback()` method matching method android.os.RemoteCallbackList.Builder.setInterfaceDiedCallback(android.os.RemoteCallbackList.Builder.InterfaceDiedCallback<E>)
RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
    Method 'getAccountsByTypeAndFeatures' documentation mentions permissions without declaring @RequiresPermission
RequiresPermission: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+37 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.os;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Slog;
@@ -223,6 +224,7 @@ public class RemoteCallbackList<E extends IInterface> {
    public static final class Builder<E extends IInterface> {
        private @FrozenCalleePolicy int mFrozenCalleePolicy;
        private int mMaxQueueSize = DEFAULT_MAX_QUEUE_SIZE;
        private InterfaceDiedCallback mInterfaceDiedCallback;

        /**
         * Creates a Builder for {@link RemoteCallbackList}.
@@ -261,12 +263,47 @@ public class RemoteCallbackList<E extends IInterface> {
            return this;
        }

        /**
         * Sets the callback to be invoked when an interface dies.
         */
        public @NonNull Builder setInterfaceDiedCallback(
                @NonNull InterfaceDiedCallback<E> callback) {
            mInterfaceDiedCallback = callback;
            return this;
        }

        /**
         * For notifying when the process hosting a callback interface has died.
         *
         * @param <E> The remote callback interface type.
         */
        @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK)
        public interface InterfaceDiedCallback<E extends IInterface> {
            /**
             * Invoked when a callback interface has died.
             *
             * @param remoteCallbackList the list that the interface was registered with.
             * @param deadInterface the interface that has died.
             * @param cookie the cookie specified on interface registration.
             */
            void onInterfaceDied(@NonNull RemoteCallbackList<E> remoteCallbackList,
                    E deadInterface, @Nullable Object cookie);
        }

        /**
         * Builds and returns a {@link RemoteCallbackList}.
         *
         * @return The built {@link RemoteCallbackList} object.
         */
        public @NonNull RemoteCallbackList<E> build() {
            if (mInterfaceDiedCallback != null) {
                return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize) {
                    @Override
                    public void onCallbackDied(E deadInterface, Object cookie) {
                        mInterfaceDiedCallback.onInterfaceDied(this, deadInterface, cookie);
                    }
                };
            }
            return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize);
        }
    }