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

Commit 187ddde3 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
Test: atest --instant android.os.cts.RemoteCallbackListTest
Bug: 361157077
API-Coverage-Bug: 372923111
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5a0bc1ef9f697dbc973480b5aba4c07d420711a7)
Merged-In: Ib777d9920d8332a09a6da3601ad3bab071fb9cba
Change-Id: Ib777d9920d8332a09a6da3601ad3bab071fb9cba

Original patch:
 From 5a0bc1ef Mon Sep 17 00:00:00 2001
From: Yu-Ting Tseng <yutingtseng@google.com>
Date: Mon, 14 Oct 2024 14:13:43 -0700
Subject: [PATCH] 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 04f26a49
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -33905,9 +33905,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);
+8 −1
Original line number Diff line number Diff line
@@ -383,6 +383,10 @@ DeprecationMismatch: javax.microedition.khronos.egl.EGL10#eglCreatePixmapSurface
    Method javax.microedition.khronos.egl.EGL10.eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match


ExecutorRegistration: android.os.IBinder#addFrozenStateChangeCallback(android.os.IBinder.FrozenStateChangeCallback):
    Registration methods should have overload that accepts delivery Executor: `addFrozenStateChangeCallback`


InvalidNullabilityOverride: android.app.Notification.TvExtender#extend(android.app.Notification.Builder) parameter #0:
    Invalid nullability on parameter `builder` in method `extend`. Parameters of overrides cannot be NonNull if the super parameter is unannotated.
InvalidNullabilityOverride: android.media.midi.MidiUmpDeviceService#onBind(android.content.Intent) parameter #0:
@@ -395,6 +399,10 @@ 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):
@@ -1445,7 +1453,6 @@ UnflaggedApi: android.graphics.text.PositionedGlyphs#getItalicOverride(int):
    New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getItalicOverride(int)
UnflaggedApi: android.graphics.text.PositionedGlyphs#getWeightOverride(int):
    New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getWeightOverride(int)

UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_CAR:
    New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_CAR
UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_COMPUTER:
+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);
        }
    }