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

Commit 5d73b6d7 authored by Christopher Tate's avatar Christopher Tate
Browse files

Introduce ServiceConnection#onNullBinding()

Historically, if a service returns null from onBind(), the binding app
gets no information about the outcome:  the ServiceConnection is never
invoked.  We now introduce a new connection callback, onNullBinding(),
for apps that need to detect this situation.  When the service rejects
the binding by returning null, the onNullBinding() callback in the
associated ServiceConnection is invoked instead of onServiceConnected().

onNullBinding() has an empty default implementation, so there is no
binary-compatibility impact of this new interface method.

Bug: 67377345
Test: atest android.app.cts.ServiceTest

Change-Id: I224512c118f7d6e5c1c2bb69eca1902882e73594
parent 2f919ef8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -10072,6 +10072,7 @@ package android.content {
  public abstract interface ServiceConnection {
    method public default void onBindingDied(android.content.ComponentName);
    method public default void onNullBinding(android.content.ComponentName);
    method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
    method public abstract void onServiceDisconnected(android.content.ComponentName);
  }
+4 −1
Original line number Diff line number Diff line
@@ -1646,9 +1646,12 @@ public final class LoadedApk {
            if (dead) {
                mConnection.onBindingDied(name);
            }
            // If there is a new service, it is now connected.
            // If there is a new viable service, it is now connected.
            if (service != null) {
                mConnection.onServiceConnected(name, service);
            } else {
                // The binding machinery worked, but the remote returned null from onBind().
                mConnection.onNullBinding(name);
            }
        }

+11 −4
Original line number Diff line number Diff line
@@ -2801,7 +2801,14 @@ public abstract class Context {
     * example, if this Context is an Activity that is stopped, the service will
     * not be required to continue running until the Activity is resumed.
     *
     * <p>This function will throw {@link SecurityException} if you do not
     * <p>If the service does not support binding, it may return {@code null} from
     * its {@link android.app.Service#onBind(Intent) onBind()} method.  If it does, then
     * the ServiceConnection's
     * {@link ServiceConnection#onNullBinding(ComponentName) onNullBinding()} method
     * will be invoked instead of
     * {@link ServiceConnection#onServiceConnected(ComponentName, IBinder) onServiceConnected()}.
     *
     * <p>This method will throw {@link SecurityException} if the calling app does not
     * have permission to bind to the given service.
     *
     * <p class="note">Note: this method <em>cannot be called from a
@@ -2827,8 +2834,8 @@ public abstract class Context {
     *          {@link #BIND_WAIVE_PRIORITY}.
     * @return If you have successfully bound to the service, {@code true} is returned;
     *         {@code false} is returned if the connection is not made so you will not
     *         receive the service object. However, you should still call
     *         {@link #unbindService} to release the connection.
     *         receive the service object. You should still call {@link #unbindService}
     *         to release the connection even if this method returned {@code false}.
     *
     * @throws SecurityException If the caller does not have permission to access the service
     * or the service can not be found.
+17 −0
Original line number Diff line number Diff line
@@ -63,4 +63,21 @@ public interface ServiceConnection {
     */
    default void onBindingDied(ComponentName name) {
    }

    /**
     * Called when the service being bound has returned {@code null} from its
     * {@link android.app.Service#onBind(Intent) onBind()} method.  This indicates
     * that the attempting service binding represented by this ServiceConnection
     * will never become usable.
     *
     * <p class="note">The app which requested the binding must still call
     * {@link Context#unbindService(ServiceConnection)} to release the tracking
     * resources associated with this ServiceConnection even if this callback was
     * invoked following {@link Context#bindService Context.bindService() bindService()}.
     *
     * @param name The concrete component name of the service whose binding
     *     has been rejected by the Service implementation.
     */
    default void onNullBinding(ComponentName name) {
    }
}