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

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

Implements ContextHubService.registerEndpoint

Bug: 378487799
Flag: android.chre.flags.offload_implementation
Test: make services
Change-Id: I5983ca2d4f996c50f6b76a1852571825526f227c
parent c0bf94ea
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1267,6 +1267,9 @@ public final class ContextHubManager {
     * registration succeeds, the endpoint can receive notifications through the provided callback.
     *
     * @param hubEndpoint {@link HubEndpoint} object created by {@link HubEndpoint.Builder}
     * @throws IllegalStateException if the registration failed, for example if too many endpoints
     *     are registered at the service
     * @throws UnsupportedOperationException if endpoint registration is not supported
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+108 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.location.contexthub;

import android.content.Context;
import android.hardware.contexthub.EndpointInfo;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.HubMessage;
import android.hardware.contexthub.HubServiceInfo;
import android.hardware.contexthub.IContextHubEndpoint;
import android.hardware.contexthub.IContextHubEndpointCallback;
import android.hardware.location.IContextHubTransactionCallback;

/**
 * A class that represents a broker for the endpoint registered by the client app. This class
 * manages direct IContextHubEndpoint/IContextHubEndpointCallback API/callback calls.
 *
 * @hide
 */
public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub {
    private static final String TAG = "ContextHubEndpointBroker";

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

    /** The proxy to talk to the Context Hub HAL. */
    private final IContextHubWrapper mContextHubProxy;

    /** The manager that registered this endpoint. */
    private final ContextHubEndpointManager mEndpointManager;

    /** Metadata about this endpoint (app-facing container). */
    private final HubEndpointInfo mEndpointInfo;

    /** Metadata about this endpoint (HAL-facing container). */
    private final EndpointInfo mHalEndpointInfo;

    /** The remote callback interface for this endpoint. */
    private final IContextHubEndpointCallback mContextHubEndpointCallback;

    /* package */ ContextHubEndpointBroker(
            Context context,
            IContextHubWrapper contextHubProxy,
            ContextHubEndpointManager endpointManager,
            EndpointInfo halEndpointInfo,
            IContextHubEndpointCallback callback) {
        mContext = context;
        mContextHubProxy = contextHubProxy;
        mEndpointManager = endpointManager;
        mEndpointInfo = new HubEndpointInfo(halEndpointInfo);
        mHalEndpointInfo = halEndpointInfo;
        mContextHubEndpointCallback = callback;
    }

    @Override
    public HubEndpointInfo getAssignedHubEndpointInfo() {
        return mEndpointInfo;
    }

    @Override
    public int openSession(HubEndpointInfo destination, HubServiceInfo serviceInfo) {
        // TODO(b/378487799): Implement this
        return 0;
    }

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

    }

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

    }

    @Override
    public void unregister() {
        // TODO(b/378487799): Implement this

    }

    @Override
    public void sendMessage(
            int sessionId, HubMessage message, IContextHubTransactionCallback callback) {
        // TODO(b/381102453): Implement this
    }

    @Override
    public void sendMessageDeliveryStatus(int sessionId, int messageSeqNumber, byte errorCode) {
        // TODO(b/381102453): Implement this
    }
}
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.location.contexthub;

import android.content.Context;
import android.hardware.contexthub.EndpointInfo;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.IContextHubEndpoint;
import android.hardware.contexthub.IContextHubEndpointCallback;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A class that manages registration/unregistration of clients and manages messages to/from clients.
 *
 * @hide
 */
/* package */ class ContextHubEndpointManager {
    private static final String TAG = "ContextHubEndpointManager";

    /** The hub ID of the Context Hub Service. */
    private static final long SERVICE_HUB_ID = 0x416e64726f696400L;

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

    /** The proxy to talk to the Context Hub. */
    private final IContextHubWrapper mContextHubProxy;

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

    /** Variables for managing endpoint ID creation */
    private final Object mEndpointLock = new Object();

    @GuardedBy("mEndpointLock")
    private long mNextEndpointId = 0;

    /* package */ ContextHubEndpointManager(Context context, IContextHubWrapper contextHubProxy) {
        mContext = context;
        mContextHubProxy = contextHubProxy;
    }

    /**
     * Registers a new endpoint with the service.
     *
     * @param pendingEndpointInfo the object describing the endpoint being registered
     * @param callback the callback interface of the endpoint to register
     * @return the endpoint interface
     * @throws IllegalStateException if max number of endpoints have already registered
     */
    /* package */ IContextHubEndpoint registerEndpoint(
            HubEndpointInfo pendingEndpointInfo, IContextHubEndpointCallback callback)
            throws RemoteException {
        ContextHubEndpointBroker broker;
        long endpointId = getNewEndpointId();
        EndpointInfo halEndpointInfo =
                ContextHubServiceUtil.createHalEndpointInfo(
                        pendingEndpointInfo, endpointId, SERVICE_HUB_ID);
        try {
            mContextHubProxy.registerEndpoint(halEndpointInfo);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException while calling HAL registerEndpoint", e);
            throw e;
        }
        broker =
                new ContextHubEndpointBroker(
                        mContext,
                        mContextHubProxy,
                        this /* endpointManager */,
                        halEndpointInfo,
                        callback);
        mEndpointMap.put(endpointId, broker);

        // TODO(b/378487799): Add death recipient

        Log.d(TAG, "Registered endpoint with ID = " + endpointId);
        return IContextHubEndpoint.Stub.asInterface(broker);
    }

    /**
     * @return an available endpoint ID
     */
    private long getNewEndpointId() {
        synchronized (mEndpointLock) {
            if (mNextEndpointId == Long.MAX_VALUE) {
                throw new IllegalStateException("Too many endpoints connected");
            }
            return mNextEndpointId++;
        }
    }
}
+11 −2
Original line number Diff line number Diff line
@@ -155,6 +155,9 @@ public class ContextHubService extends IContextHubService.Stub {
    // The manager for sending messages to/from clients
    private ContextHubClientManager mClientManager;

    // Manages endpoint and its sessions between apps and HAL
    private ContextHubEndpointManager mEndpointManager;

    // The default client for old API clients
    private Map<Integer, IContextHubClient> mDefaultClientMap;

@@ -330,14 +333,17 @@ public class ContextHubService extends IContextHubService.Stub {
            HubInfoRegistry registry;
            try {
                registry = new HubInfoRegistry(mContextHubWrapper);
                mEndpointManager = new ContextHubEndpointManager(mContext, mContextHubWrapper);
                Log.i(TAG, "Enabling generic offload API");
            } catch (UnsupportedOperationException e) {
                mEndpointManager = null;
                registry = null;
                Log.w(TAG, "Generic offload API not supported, disabling");
            }
            mHubInfoRegistry = registry;
        } else {
            mHubInfoRegistry = null;
            mEndpointManager = null;
            Log.i(TAG, "Disabling generic offload API");
        }

@@ -790,8 +796,11 @@ public class ContextHubService extends IContextHubService.Stub {
            HubEndpointInfo pendingHubEndpointInfo, IContextHubEndpointCallback callback)
            throws RemoteException {
        super.registerEndpoint_enforcePermission();
        // TODO(b/375487784): Implement this
        return null;
        if (mEndpointManager == null) {
            Log.e(TAG, "ContextHubService.registerEndpoint: endpoint manager failed to initialize");
            throw new UnsupportedOperationException("Endpoint registration is not supported");
        }
        return mEndpointManager.registerEndpoint(pendingHubEndpointInfo, callback);
    }

    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+50 −0
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package com.android.server.location.contexthub;

import android.Manifest;
import android.content.Context;
import android.hardware.contexthub.EndpointInfo;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.HubServiceInfo;
import android.hardware.contexthub.V1_0.AsyncEventType;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.HostEndPoint;
@@ -415,4 +418,51 @@ import java.util.List;
    static String formatDateFromTimestamp(long timeStampInMs) {
        return DATE_FORMATTER.format(Instant.ofEpochMilli(timeStampInMs));
    }

    /**
     * Converts a context hub HAL EndpointInfo object based on the provided HubEndpointInfo.
     *
     * @param info the HubEndpointInfo object
     * @return the equivalent EndpointInfo object
     */
    /* package */
    static EndpointInfo convertHalEndpointInfo(HubEndpointInfo info) {
        return createHalEndpointInfo(
                info, info.getIdentifier().getEndpoint(), info.getIdentifier().getHub());
    }

    /**
     * Creates a context hub HAL EndpointInfo object based on the provided HubEndpointInfo. As
     * opposed to convertHalEndpointInfo, this method can be used to overwrite/specify the endpoint
     * and hub ID.
     *
     * @param info the HubEndpointInfo object
     * @param endpointId the endpoint ID of this object
     * @param hubId the hub ID of this object
     * @return the equivalent EndpointInfo object
     */
    /* package */
    static EndpointInfo createHalEndpointInfo(HubEndpointInfo info, long endpointId, long hubId) {
        EndpointInfo outputInfo = new EndpointInfo();
        outputInfo.id = new android.hardware.contexthub.EndpointId();
        outputInfo.id.id = endpointId;
        outputInfo.id.hubId = hubId;
        outputInfo.name = info.getName();
        outputInfo.version = info.getVersion();
        outputInfo.tag = info.getTag();
        Collection<String> permissions = info.getRequiredPermissions();
        outputInfo.requiredPermissions = permissions.toArray(new String[permissions.size()]);
        Collection<HubServiceInfo> services = info.getServiceInfoCollection();
        outputInfo.services = new android.hardware.contexthub.Service[services.size()];
        int i = 0;
        for (HubServiceInfo service : services) {
            outputInfo.services[i] = new android.hardware.contexthub.Service();
            outputInfo.services[i].format = service.getFormat();
            outputInfo.services[i].serviceDescriptor = service.getServiceDescriptor();
            outputInfo.services[i].majorVersion = service.getMajorVersion();
            outputInfo.services[i].minorVersion = service.getMinorVersion();
            i++;
        }
        return outputInfo;
    }
}
Loading