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

Commit 55e000f0 authored by Arthur Ishiguro's avatar Arthur Ishiguro
Browse files

Implements endpoint session callbacks

Bug: 378487799
Flag: android.chre.flags.offload_implementation
Test: make services

Change-Id: If79db8da9a63a7e502d214dbf2ce6e6b299b2249
parent a44cb2f8
Loading
Loading
Loading
Loading
+108 −15
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
@@ -60,6 +64,20 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
    /** True if this endpoint is registered with the service. */
    private AtomicBoolean mIsRegistered = new AtomicBoolean(true);

    private final Object mOpenSessionLock = new Object();

    /** The set of session IDs that are pending remote acceptance */
    @GuardedBy("mOpenSessionLock")
    private final Set<Integer> mPendingSessionIds = new HashSet<>();

    /** The set of session IDs that are actively enabled by this endpoint */
    @GuardedBy("mOpenSessionLock")
    private final Set<Integer> mActiveSessionIds = new HashSet<>();

    /** The set of session IDs that are actively enabled by the remote endpoint */
    @GuardedBy("mOpenSessionLock")
    private final Set<Integer> mActiveRemoteSessionIds = new HashSet<>();

    /* package */ ContextHubEndpointBroker(
            Context context,
            IContextHubWrapper contextHubProxy,
@@ -86,17 +104,25 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
        if (!mIsRegistered.get()) throw new IllegalStateException("Endpoint is not registered");
        int sessionId = mEndpointManager.reserveSessionId();
        EndpointInfo halEndpointInfo = ContextHubServiceUtil.convertHalEndpointInfo(destination);

        synchronized (mOpenSessionLock) {
            try {
                mPendingSessionIds.add(sessionId);
                mContextHubProxy.openEndpointSession(
                    sessionId, halEndpointInfo.id, mHalEndpointInfo.id, serviceDescriptor);
                        sessionId,
                        halEndpointInfo.id,
                        mHalEndpointInfo.id,
                        serviceDescriptor);
            } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) {
                Log.e(TAG, "Exception while calling HAL openEndpointSession", e);
                mPendingSessionIds.remove(sessionId);
                mEndpointManager.returnSessionId(sessionId);
                throw e;
            }

            return sessionId;
        }
    }

    @Override
    public void closeSession(int sessionId, int reason) throws RemoteException {
@@ -110,11 +136,6 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
        }
    }

    @Override
    public void openSessionRequestComplete(int sessionId) {
        // TODO(b/378487799): Implement this
    }

    @Override
    public void unregister() {
        ContextHubServiceUtil.checkPermissions(mContext);
@@ -124,10 +145,33 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException while calling HAL unregisterEndpoint", e);
        }
        // TODO(b/378487799): Release reserved session IDs
        synchronized (mOpenSessionLock) {
            for (int id : mPendingSessionIds) {
                mEndpointManager.returnSessionId(id);
            }
            for (int id : mActiveSessionIds) {
                mEndpointManager.returnSessionId(id);
            }
            mPendingSessionIds.clear();
            mActiveSessionIds.clear();
            mActiveRemoteSessionIds.clear();
        }
        mEndpointManager.unregisterEndpoint(mEndpointInfo.getIdentifier().getEndpoint());
    }

    @Override
    public void openSessionRequestComplete(int sessionId) {
        ContextHubServiceUtil.checkPermissions(mContext);
        synchronized (mOpenSessionLock) {
            try {
                mContextHubProxy.endpointSessionOpenComplete(sessionId);
                mActiveRemoteSessionIds.add(sessionId);
            } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) {
                Log.e(TAG, "Exception while calling endpointSessionOpenComplete", e);
            }
        }
    }

    @Override
    public void sendMessage(
            int sessionId, HubMessage message, IContextHubTransactionCallback callback) {
@@ -150,4 +194,53 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
            mContextHubEndpointCallback.asBinder().linkToDeath(this, 0 /* flags */);
        }
    }

    /* package */ void onEndpointSessionOpenRequest(
            int sessionId, HubEndpointInfo initiator, String serviceDescriptor) {
        if (mContextHubEndpointCallback != null) {
            try {
                mContextHubEndpointCallback.onSessionOpenRequest(
                        sessionId, initiator, serviceDescriptor);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException while calling onSessionOpenRequest", e);
            }
        }
    }

    /* package */ void onCloseEndpointSession(int sessionId, byte reason) {
        synchronized (mOpenSessionLock) {
            mPendingSessionIds.remove(sessionId);
            mActiveSessionIds.remove(sessionId);
            mActiveRemoteSessionIds.remove(sessionId);
        }
        if (mContextHubEndpointCallback != null) {
            try {
                mContextHubEndpointCallback.onSessionClosed(sessionId, reason);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException while calling onSessionClosed", e);
            }
        }
    }

    /* package */ void onEndpointSessionOpenComplete(int sessionId) {
        synchronized (mOpenSessionLock) {
            mPendingSessionIds.remove(sessionId);
            mActiveSessionIds.add(sessionId);
        }
        if (mContextHubEndpointCallback != null) {
            try {
                mContextHubEndpointCallback.onSessionOpenComplete(sessionId);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException while calling onSessionClosed", e);
            }
        }
    }

    /* package */ boolean hasSessionId(int sessionId) {
        synchronized (mOpenSessionLock) {
            return mPendingSessionIds.contains(sessionId)
                    || mActiveSessionIds.contains(sessionId)
                    || mActiveRemoteSessionIds.contains(sessionId);
        }
    }
}
+74 −2
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@ import java.util.concurrent.ConcurrentHashMap;
 *
 * @hide
 */
/* package */ class ContextHubEndpointManager {
/* package */ class ContextHubEndpointManager
        implements ContextHubHalEndpointCallback.IEndpointSessionCallback {
    private static final String TAG = "ContextHubEndpointManager";

    /** The hub ID of the Context Hub Service. */
@@ -56,6 +57,8 @@ import java.util.concurrent.ConcurrentHashMap;
    /** The proxy to talk to the Context Hub. */
    private final IContextHubWrapper mContextHubProxy;

    private final HubInfoRegistry mHubInfoRegistry;

    /** A map of endpoint IDs to brokers currently registered. */
    private final Map<Long, ContextHubEndpointBroker> mEndpointMap = new ConcurrentHashMap<>();

@@ -85,9 +88,11 @@ import java.util.concurrent.ConcurrentHashMap;
    /** Initialized to true if all initialization in the constructor succeeds. */
    private final boolean mSessionIdsValid;

    /* package */ ContextHubEndpointManager(Context context, IContextHubWrapper contextHubProxy) {
    /* package */ ContextHubEndpointManager(
            Context context, IContextHubWrapper contextHubProxy, HubInfoRegistry hubInfoRegistry) {
        mContext = context;
        mContextHubProxy = contextHubProxy;
        mHubInfoRegistry = hubInfoRegistry;
        int[] range = null;
        try {
            range = mContextHubProxy.requestSessionIdRange(SERVICE_SESSION_RANGE);
@@ -210,6 +215,70 @@ import java.util.concurrent.ConcurrentHashMap;
        mEndpointMap.remove(endpointId);
    }

    @Override
    public void onEndpointSessionOpenRequest(
            int sessionId,
            HubEndpointInfo.HubEndpointIdentifier destination,
            HubEndpointInfo.HubEndpointIdentifier initiator,
            String serviceDescriptor) {
        if (destination.getHub() != SERVICE_HUB_ID) {
            Log.e(
                    TAG,
                    "onEndpointSessionOpenRequest: invalid destination hub ID: "
                            + destination.getHub());
            return;
        }
        ContextHubEndpointBroker broker = mEndpointMap.get(destination.getEndpoint());
        if (broker == null) {
            Log.e(
                    TAG,
                    "onEndpointSessionOpenRequest: unknown destination endpoint ID: "
                            + destination.getEndpoint());
            return;
        }
        HubEndpointInfo initiatorInfo = mHubInfoRegistry.getEndpointInfo(initiator);
        if (initiatorInfo == null) {
            Log.e(
                    TAG,
                    "onEndpointSessionOpenRequest: unknown initiator endpoint ID: "
                            + initiator.getEndpoint());
            return;
        }
        broker.onEndpointSessionOpenRequest(sessionId, initiatorInfo, serviceDescriptor);
    }

    @Override
    public void onCloseEndpointSession(int sessionId, byte reason) {
        boolean callbackInvoked = false;
        for (ContextHubEndpointBroker broker : mEndpointMap.values()) {
            if (broker.hasSessionId(sessionId)) {
                broker.onCloseEndpointSession(sessionId, reason);
                callbackInvoked = true;
                break;
            }
        }

        if (!callbackInvoked) {
            Log.w(TAG, "onCloseEndpointSession: unknown session ID " + sessionId);
        }
    }

    @Override
    public void onEndpointSessionOpenComplete(int sessionId) {
        boolean callbackInvoked = false;
        for (ContextHubEndpointBroker broker : mEndpointMap.values()) {
            if (broker.hasSessionId(sessionId)) {
                broker.onEndpointSessionOpenComplete(sessionId);
                callbackInvoked = true;
                break;
            }
        }

        if (!callbackInvoked) {
            Log.w(TAG, "onEndpointSessionOpenComplete: unknown session ID " + sessionId);
        }
    }

    /** @return an available endpoint ID */
    private long getNewEndpointId() {
        synchronized (mEndpointLock) {
@@ -220,6 +289,9 @@ import java.util.concurrent.ConcurrentHashMap;
        }
    }

    /**
     * @return true if the provided session ID range is valid
     */
    private boolean isSessionIdRangeValid(int minId, int maxId) {
        return (minId <= maxId) && (minId >= 0) && (maxId >= 0);
    }
+34 −5
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.RemoteException;
public class ContextHubHalEndpointCallback
        extends android.hardware.contexthub.IEndpointCallback.Stub {
    private final IEndpointLifecycleCallback mEndpointLifecycleCallback;
    private final IEndpointSessionCallback mEndpointSessionCallback;

    /** Interface for listening for endpoint start and stop events. */
    public interface IEndpointLifecycleCallback {
@@ -36,8 +37,27 @@ public class ContextHubHalEndpointCallback
        void onEndpointStopped(HubEndpointInfo.HubEndpointIdentifier[] endpointIds, byte reason);
    }

    ContextHubHalEndpointCallback(IEndpointLifecycleCallback endpointLifecycleCallback) {
    /** Interface for listening for endpoint session events. */
    public interface IEndpointSessionCallback {
        /** Called when an endpoint session open is requested by the HAL. */
        void onEndpointSessionOpenRequest(
                int sessionId,
                HubEndpointInfo.HubEndpointIdentifier destinationId,
                HubEndpointInfo.HubEndpointIdentifier initiatorId,
                String serviceDescriptor);

        /** Called when a endpoint close session is completed. */
        void onCloseEndpointSession(int sessionId, byte reason);

        /** Called when a requested endpoint open session is completed */
        void onEndpointSessionOpenComplete(int sessionId);
    }

    ContextHubHalEndpointCallback(
            IEndpointLifecycleCallback endpointLifecycleCallback,
            IEndpointSessionCallback endpointSessionCallback) {
        mEndpointLifecycleCallback = endpointLifecycleCallback;
        mEndpointSessionCallback = endpointSessionCallback;
    }

    @Override
@@ -72,14 +92,23 @@ public class ContextHubHalEndpointCallback

    @Override
    public void onEndpointSessionOpenRequest(
            int i, EndpointId endpointId, EndpointId endpointId1, String s)
            throws RemoteException {}
            int i, EndpointId destination, EndpointId initiator, String s) throws RemoteException {
        HubEndpointInfo.HubEndpointIdentifier destinationId =
                new HubEndpointInfo.HubEndpointIdentifier(destination.hubId, destination.id);
        HubEndpointInfo.HubEndpointIdentifier initiatorId =
                new HubEndpointInfo.HubEndpointIdentifier(initiator.hubId, initiator.id);
        mEndpointSessionCallback.onEndpointSessionOpenRequest(i, destinationId, initiatorId, s);
    }

    @Override
    public void onCloseEndpointSession(int i, byte b) throws RemoteException {}
    public void onCloseEndpointSession(int i, byte b) throws RemoteException {
        mEndpointSessionCallback.onCloseEndpointSession(i, b);
    }

    @Override
    public void onEndpointSessionOpenComplete(int i) throws RemoteException {}
    public void onEndpointSessionOpenComplete(int i) throws RemoteException {
        mEndpointSessionCallback.onEndpointSessionOpenComplete(i);
    }

    @Override
    public int getInterfaceVersion() throws RemoteException {
+3 −2
Original line number Diff line number Diff line
@@ -333,7 +333,8 @@ public class ContextHubService extends IContextHubService.Stub {
            HubInfoRegistry registry;
            try {
                registry = new HubInfoRegistry(mContextHubWrapper);
                mEndpointManager = new ContextHubEndpointManager(mContext, mContextHubWrapper);
                mEndpointManager =
                        new ContextHubEndpointManager(mContext, mContextHubWrapper, registry);
                Log.i(TAG, "Enabling generic offload API");
            } catch (UnsupportedOperationException e) {
                mEndpointManager = null;
@@ -533,7 +534,7 @@ public class ContextHubService extends IContextHubService.Stub {
        }
        try {
            mContextHubWrapper.registerEndpointCallback(
                    new ContextHubHalEndpointCallback(mHubInfoRegistry));
                    new ContextHubHalEndpointCallback(mHubInfoRegistry, mEndpointManager));
        } catch (RemoteException | UnsupportedOperationException e) {
            Log.e(TAG, "Exception while registering IEndpointCallback", e);
        }
+6 −0
Original line number Diff line number Diff line
@@ -87,6 +87,12 @@ class HubInfoRegistry implements ContextHubHalEndpointCallback.IEndpointLifecycl
        }
    }

    public HubEndpointInfo getEndpointInfo(HubEndpointInfo.HubEndpointIdentifier id) {
        synchronized (mLock) {
            return mHubEndpointInfos.get(id);
        }
    }

    /** Invoked when HAL restarts */
    public void onHalRestart() {
        synchronized (mLock) {
Loading