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

Commit 9526ea6c authored by Arthur Ishiguro's avatar Arthur Ishiguro
Browse files

Implements ContextHubEndpointBroker open/closeEndpointSession

Bug: 378487799
Flag: android.chre.flags.offload_implementation
Test: make services
Change-Id: I5d5fc99be65c89931a3f5b107302d898fb26e551
parent e5c25297
Loading
Loading
Loading
Loading
+28 −7
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.hardware.contexthub.HubServiceInfo;
import android.hardware.contexthub.IContextHubEndpoint;
import android.hardware.contexthub.IContextHubEndpointCallback;
import android.hardware.location.IContextHubTransactionCallback;
import android.os.RemoteException;
import android.util.Log;

/**
 * A class that represents a broker for the endpoint registered by the client app. This class
@@ -72,21 +74,40 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub {
    }

    @Override
    public int openSession(HubEndpointInfo destination, HubServiceInfo serviceInfo) {
        // TODO(b/378487799): Implement this
        return 0;
    public int openSession(HubEndpointInfo destination, HubServiceInfo serviceInfo)
            throws RemoteException {
        ContextHubServiceUtil.checkPermissions(mContext);
        int sessionId = mEndpointManager.reserveSessionId();
        EndpointInfo halEndpointInfo = ContextHubServiceUtil.convertHalEndpointInfo(destination);
        try {
            mContextHubProxy.openEndpointSession(
                    sessionId,
                    halEndpointInfo.id,
                    mHalEndpointInfo.id,
                    serviceInfo == null ? null : serviceInfo.getServiceDescriptor());
        } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) {
            Log.e(TAG, "Exception while calling HAL openEndpointSession", e);
            mEndpointManager.returnSessionId(sessionId);
            throw e;
        }

    @Override
    public void closeSession(int sessionId, int reason) {
        // TODO(b/378487799): Implement this
        return sessionId;
    }

    @Override
    public void closeSession(int sessionId, int reason) throws RemoteException {
        ContextHubServiceUtil.checkPermissions(mContext);
        try {
            mContextHubProxy.closeEndpointSession(sessionId, (byte) reason);
        } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) {
            Log.e(TAG, "Exception while calling HAL closeEndpointSession", e);
            throw e;
        }
    }

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

    }

    @Override
+100 −1
Original line number Diff line number Diff line
@@ -22,11 +22,15 @@ import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.IContextHubEndpoint;
import android.hardware.contexthub.IContextHubEndpointCallback;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
@@ -40,6 +44,12 @@ import java.util.concurrent.ConcurrentHashMap;
    /** The hub ID of the Context Hub Service. */
    private static final long SERVICE_HUB_ID = 0x416e64726f696400L;

    /** The range of session IDs to use for endpoints */
    private static final int SERVICE_SESSION_RANGE = 1024;

    /** The length of the array that should be returned by HAL requestSessionIdRange */
    private static final int SERVICE_SESSION_RANGE_LENGTH = 2;

    /** The context of the service. */
    private final Context mContext;

@@ -55,9 +65,57 @@ import java.util.concurrent.ConcurrentHashMap;
    @GuardedBy("mEndpointLock")
    private long mNextEndpointId = 0;

    /** The minimum session ID reservable by endpoints (retrieved from HAL) */
    private final int mMinSessionId;

    /** The minimum session ID reservable by endpoints (retrieved from HAL) */
    private final int mMaxSessionId;

    /** Variables for managing session ID creation */
    private final Object mSessionIdLock = new Object();

    /** A set of session IDs that have been reserved by an endpoint. */
    @GuardedBy("mSessionIdLock")
    private final Set<Integer> mReservedSessionIds =
            Collections.newSetFromMap(new HashMap<Integer, Boolean>());

    @GuardedBy("mSessionIdLock")
    private int mNextSessionId = 0;

    /** Initialized to true if all initialization in the constructor succeeds. */
    private final boolean mSessionIdsValid;

    /* package */ ContextHubEndpointManager(Context context, IContextHubWrapper contextHubProxy) {
        mContext = context;
        mContextHubProxy = contextHubProxy;
        int[] range = null;
        try {
            range = mContextHubProxy.requestSessionIdRange(SERVICE_SESSION_RANGE);
            if (range != null && range.length < SERVICE_SESSION_RANGE_LENGTH) {
                Log.e(TAG, "Invalid session ID range: range array size = " + range.length);
                range = null;
            }
        } catch (RemoteException | IllegalArgumentException | ServiceSpecificException e) {
            Log.e(TAG, "Exception while calling HAL requestSessionIdRange", e);
        }

        if (range == null) {
            mMinSessionId = -1;
            mMaxSessionId = -1;
            mSessionIdsValid = false;
        } else {
            mMinSessionId = range[0];
            mMaxSessionId = range[1];
            if (!isSessionIdRangeValid(mMinSessionId, mMaxSessionId)) {
                Log.e(
                        TAG,
                        "Invalid session ID range: max=" + mMaxSessionId + " min=" + mMinSessionId);
                mSessionIdsValid = false;
            } else {
                mNextSessionId = mMinSessionId;
                mSessionIdsValid = true;
            }
        }
    }

    /**
@@ -71,6 +129,9 @@ import java.util.concurrent.ConcurrentHashMap;
    /* package */ IContextHubEndpoint registerEndpoint(
            HubEndpointInfo pendingEndpointInfo, IContextHubEndpointCallback callback)
            throws RemoteException {
        if (!mSessionIdsValid) {
            throw new IllegalStateException("ContextHubEndpointManager failed to initialize");
        }
        ContextHubEndpointBroker broker;
        long endpointId = getNewEndpointId();
        EndpointInfo halEndpointInfo =
@@ -98,8 +159,42 @@ import java.util.concurrent.ConcurrentHashMap;
    }

    /**
     * @return an available endpoint ID
     * Reserves an available session ID for an endpoint.
     *
     * @throws IllegalStateException if no session ID was available.
     * @return The reserved session ID.
     */
    /* package */ int reserveSessionId() {
        int id = -1;
        synchronized (mSessionIdLock) {
            final int maxCapacity = mMaxSessionId - mMinSessionId + 1;
            if (mReservedSessionIds.size() >= maxCapacity) {
                throw new IllegalStateException("Too many sessions reserved");
            }

            id = mNextSessionId;
            for (int i = mMinSessionId; i <= mMaxSessionId; i++) {
                if (!mReservedSessionIds.contains(id)) {
                    mNextSessionId = (id == mMaxSessionId) ? mMinSessionId : id + 1;
                    break;
                }

                id = (id == mMaxSessionId) ? mMinSessionId : id + 1;
            }

            mReservedSessionIds.add(id);
        }
        return id;
    }

    /** Returns a previously reserved session ID through {@link #reserveSessionId()}. */
    /* package */ void returnSessionId(int sessionId) {
        synchronized (mSessionIdLock) {
            mReservedSessionIds.remove(sessionId);
        }
    }

    /** @return an available endpoint ID */
    private long getNewEndpointId() {
        synchronized (mEndpointLock) {
            if (mNextEndpointId == Long.MAX_VALUE) {
@@ -108,4 +203,8 @@ import java.util.concurrent.ConcurrentHashMap;
            return mNextEndpointId++;
        }
    }

    private boolean isSessionIdRangeValid(int minId, int maxId) {
        return (minId <= maxId) && (minId >= 0) && (maxId >= 0);
    }
}
+46 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.location.contexthub;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.chre.flags.Flags;
import android.hardware.contexthub.EndpointId;
import android.hardware.contexthub.HostEndpointInfo;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.MessageDeliveryStatus;
@@ -243,6 +244,19 @@ public abstract class IContextHubWrapper {
    public void registerEndpoint(android.hardware.contexthub.EndpointInfo info)
            throws RemoteException {}

    /** Unregisters a previously registered endpoint */
    public int[] requestSessionIdRange(int size) throws RemoteException {
        return null;
    }

    /** Opens an endpoint session between two endpoints */
    public void openEndpointSession(
            int sessionId, EndpointId destination, EndpointId initiator, String serviceDescriptor)
            throws RemoteException {}

    /** Closes a previously opened endpoint */
    public void closeEndpointSession(int sessionId, byte reason) throws RemoteException {}

    /**
     * @return True if this version of the Contexthub HAL supports Location setting notifications.
     */
@@ -685,6 +699,38 @@ public abstract class IContextHubWrapper {
            hub.registerEndpoint(info);
        }

        @Override
        public int[] requestSessionIdRange(int size) throws RemoteException {
            android.hardware.contexthub.IContextHub hub = getHub();
            if (hub == null) {
                return null;
            }
            return hub.requestSessionIdRange(size);
        }

        @Override
        public void openEndpointSession(
                int sessionId,
                EndpointId destination,
                EndpointId initiator,
                String serviceDescriptor)
                throws RemoteException {
            android.hardware.contexthub.IContextHub hub = getHub();
            if (hub == null) {
                return;
            }
            hub.openEndpointSession(sessionId, destination, initiator, serviceDescriptor);
        }

        @Override
        public void closeEndpointSession(int sessionId, byte reason) throws RemoteException {
            android.hardware.contexthub.IContextHub hub = getHub();
            if (hub == null) {
                return;
            }
            hub.closeEndpointSession(sessionId, reason);
        }

        public boolean supportsLocationSettingNotifications() {
            return true;
        }