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

Commit daeed3cb authored by Arthur Ishiguro's avatar Arthur Ishiguro
Browse files

Modifies concurrency handling in ContextHubClientBroker

With PendingIntent, there will be multiple states in the class, so it
will be simpler to mark methods synchronized on the object.

Bug: 117612105
Test: Compile only
Change-Id: I60dfac3113508b9e251e33fd3c1c8f60378017f4
parent f95d6a17
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -31,8 +31,8 @@ interface IContextHubClient {
    void close();

    // Registers a PendingIntent with the client
    boolean registerIntent(in PendingIntent intent, long nanoAppId);
    boolean registerIntent(in PendingIntent pendingIntent, long nanoAppId);

    // Unregisters a PendingIntent from the client
    boolean unregisterIntent(in PendingIntent intent);
    boolean unregisterIntent(in PendingIntent pendingIntent);
}
+37 −25
Original line number Diff line number Diff line
@@ -30,8 +30,6 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * A class that acts as a broker for the ContextHubClient, which handles messaging and life-cycle
 * notification callbacks. This class implements the IContextHubClient object, and the implemented
@@ -69,14 +67,15 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
    private final short mHostEndPointId;

    /*
     * The remote callback interface for this client.
     * The remote callback interface for this client. This will be set to null whenever the
     * client connection is closed (either explicitly or via binder death).
     */
    private final IContextHubClientCallback mCallbackInterface;
    private IContextHubClientCallback mCallbackInterface = null;

    /*
     * false if the connection has been closed by the client, true otherwise.
     * True if the client is still registered with the Context Hub Service, false otherwise.
     */
    private final AtomicBoolean mConnectionOpen = new AtomicBoolean(true);
    private boolean mRegistered = true;

    /*
     * Internal interface used to invoke client callbacks.
@@ -102,9 +101,11 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     *
     * @throws RemoteException if the client has already died
     */
    /* package */ void attachDeathRecipient() throws RemoteException {
    /* package */ synchronized void attachDeathRecipient() throws RemoteException {
        if (mCallbackInterface != null) {
            mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */);
        }
    }

    /**
     * Sends from this client to a nanoapp.
@@ -118,9 +119,13 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
        ContextHubServiceUtil.checkPermissions(mContext);

        int result;
        if (mConnectionOpen.get()) {
            ContextHubMsg messageToNanoApp = ContextHubServiceUtil.createHidlContextHubMessage(
                    mHostEndPointId, message);
        IContextHubClientCallback callback = null;
        synchronized (this) {
            callback = mCallbackInterface;
        }
        if (callback != null) {
            ContextHubMsg messageToNanoApp =
                    ContextHubServiceUtil.createHidlContextHubMessage(mHostEndPointId, message);

            int contextHubId = mAttachedContextHubInfo.getId();
            try {
@@ -139,22 +144,22 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
    }

    /**
     * @param intent the intent to register
     * @param pendingIntent the intent to register
     * @param nanoAppId     the ID of the nanoapp to send events for
     * @return true on success, false otherwise
     */
    @Override
    public boolean registerIntent(PendingIntent intent, long nanoAppId) {
    public boolean registerIntent(PendingIntent pendingIntent, long nanoAppId) {
        // TODO: Implement this
        return false;
    }

    /**
     * @param intent the intent to unregister
     * @param pendingIntent the intent to unregister
     * @return true on success, false otherwise
     */
    @Override
    public boolean unregisterIntent(PendingIntent intent) {
    public boolean unregisterIntent(PendingIntent pendingIntent) {
        // TODO: Implement this
        return false;
    }
@@ -164,8 +169,15 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     */
    @Override
    public void close() {
        if (mConnectionOpen.getAndSet(false)) {
        synchronized (this) {
            if (mCallbackInterface != null) {
                mCallbackInterface.asBinder().unlinkToDeath(this, 0 /* flags */);
                mCallbackInterface = null;
            }
            if (mRegistered) {
                mClientManager.unregisterClient(mHostEndPointId);
                mRegistered = false;
            }
        }
    }

@@ -197,7 +209,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     * @param message the message that came from a nanoapp
     */
    /* package */ void sendMessageToClient(NanoAppMessage message) {
        invokeCallbackConcurrent(callback -> callback.onMessageFromNanoApp(message));
        invokeCallback(callback -> callback.onMessageFromNanoApp(message));
    }

    /**
@@ -206,7 +218,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     * @param nanoAppId the ID of the nanoapp that was loaded.
     */
    /* package */ void onNanoAppLoaded(long nanoAppId) {
        invokeCallbackConcurrent(callback -> callback.onNanoAppLoaded(nanoAppId));
        invokeCallback(callback -> callback.onNanoAppLoaded(nanoAppId));
    }

    /**
@@ -215,14 +227,14 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     * @param nanoAppId the ID of the nanoapp that was unloaded.
     */
    /* package */ void onNanoAppUnloaded(long nanoAppId) {
        invokeCallbackConcurrent(callback -> callback.onNanoAppUnloaded(nanoAppId));
        invokeCallback(callback -> callback.onNanoAppUnloaded(nanoAppId));
    }

    /**
     * Notifies the client of a hub reset event if the connection is open.
     */
    /* package */ void onHubReset() {
        invokeCallbackConcurrent(callback -> callback.onHubReset());
        invokeCallback(callback -> callback.onHubReset());
    }

    /**
@@ -232,7 +244,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     * @param abortCode the nanoapp specific abort code
     */
    /* package */ void onNanoAppAborted(long nanoAppId, int abortCode) {
        invokeCallbackConcurrent(callback -> callback.onNanoAppAborted(nanoAppId, abortCode));
        invokeCallback(callback -> callback.onNanoAppAborted(nanoAppId, abortCode));
    }

    /**
@@ -240,8 +252,8 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
     *
     * @param consumer the consumer specifying the callback to invoke
     */
    private void invokeCallbackConcurrent(CallbackConsumer consumer) {
        if (mConnectionOpen.get()) {
    private synchronized void invokeCallback(CallbackConsumer consumer) {
        if (mCallbackInterface != null) {
            try {
                consumer.accept(mCallbackInterface);
            } catch (RemoteException e) {