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

Commit 144ace42 authored by Yifei Zhang's avatar Yifei Zhang
Browse files

contexthub: implement findEndpoints in service

- Create callback interface that tracks Endpoint start/stop events
- Maintains an internal cache of the endpoints information, refresh on
  HAL restart.

Test: build
Bug: 375487784
Flag: android.chre.flags.offload_api
Change-Id: I19c4132957b58e626ee7a5c9ba7b45bc13ff67c1
parent 17a02e66
Loading
Loading
Loading
Loading
+93 −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.hardware.contexthub.EndpointId;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.IEndpointCallback;
import android.hardware.contexthub.Message;
import android.hardware.contexthub.MessageDeliveryStatus;
import android.os.RemoteException;

/** IEndpointCallback implementation. */
public class ContextHubHalEndpointCallback
        extends android.hardware.contexthub.IEndpointCallback.Stub {
    private final IEndpointLifecycleCallback mEndpointLifecycleCallback;

    /** Interface for listening for endpoint start and stop events. */
    public interface IEndpointLifecycleCallback {
        /** Called when a batch of endpoints started. */
        void onEndpointStarted(HubEndpointInfo[] endpointInfos);

        /** Called when a batch of endpoints stopped. */
        void onEndpointStopped(HubEndpointInfo.HubEndpointIdentifier[] endpointIds, byte reason);
    }

    ContextHubHalEndpointCallback(IEndpointLifecycleCallback endpointLifecycleCallback) {
        mEndpointLifecycleCallback = endpointLifecycleCallback;
    }

    @Override
    public void onEndpointStarted(android.hardware.contexthub.EndpointInfo[] halEndpointInfos)
            throws RemoteException {
        if (halEndpointInfos.length == 0) {
            return;
        }
        HubEndpointInfo[] endpointInfos = new HubEndpointInfo[halEndpointInfos.length];
        for (int i = 0; i < halEndpointInfos.length; i++) {
            endpointInfos[i++] = new HubEndpointInfo(halEndpointInfos[i]);
        }
        mEndpointLifecycleCallback.onEndpointStarted(endpointInfos);
    }

    @Override
    public void onEndpointStopped(EndpointId[] halEndpointIds, byte reason) throws RemoteException {
        HubEndpointInfo.HubEndpointIdentifier[] endpointIds =
                new HubEndpointInfo.HubEndpointIdentifier[halEndpointIds.length];
        for (int i = 0; i < halEndpointIds.length; i++) {
            endpointIds[i] = new HubEndpointInfo.HubEndpointIdentifier(halEndpointIds[i]);
        }
        mEndpointLifecycleCallback.onEndpointStopped(endpointIds, reason);
    }

    @Override
    public void onMessageReceived(int i, Message message) throws RemoteException {}

    @Override
    public void onMessageDeliveryStatusReceived(int i, MessageDeliveryStatus messageDeliveryStatus)
            throws RemoteException {}

    @Override
    public void onEndpointSessionOpenRequest(
            int i, EndpointId endpointId, EndpointId endpointId1, String s)
            throws RemoteException {}

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

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

    @Override
    public int getInterfaceVersion() throws RemoteException {
        return IEndpointCallback.VERSION;
    }

    @Override
    public String getInterfaceHash() throws RemoteException {
        return IEndpointCallback.HASH;
    }
}
+18 −2
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ public class ContextHubService extends IContextHubService.Stub {
        public void handleServiceRestart() {
            Log.i(TAG, "Recovering from Context Hub HAL restart...");
            initExistingCallbacks();
            mHubInfoRegistry.onHalRestart();
            resetSettings();
            if (Flags.reconnectHostEndpointsAfterHalRestart()) {
                mClientManager.forEachClientOfHub(mContextHubId,
@@ -331,6 +332,7 @@ public class ContextHubService extends IContextHubService.Stub {
        }

        initDefaultClientMap();
        initEndpointCallback();

        initLocationSettingNotifications();
        initWifiSettingNotifications();
@@ -509,6 +511,18 @@ public class ContextHubService extends IContextHubService.Stub {
        mDefaultClientMap = Collections.unmodifiableMap(defaultClientMap);
    }

    private void initEndpointCallback() {
        if (mHubInfoRegistry == null) {
            return;
        }
        try {
            mContextHubWrapper.registerEndpointCallback(
                    new ContextHubHalEndpointCallback(mHubInfoRegistry));
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException while registering IEndpointCallback", e);
        }
    }

    /**
     * Initializes existing callbacks with the mContextHubWrapper for every context hub
     */
@@ -744,9 +758,11 @@ public class ContextHubService extends IContextHubService.Stub {
    @Override
    public List<HubEndpointInfo> findEndpoints(long endpointId) {
        super.findEndpoints_enforcePermission();
        // TODO(b/375487784): connect this with mHubInfoRegistry
        if (mHubInfoRegistry == null) {
            return Collections.emptyList();
        }
        return mHubInfoRegistry.findEndpoints(endpointId);
    }

    /**
     * Creates an internal load transaction callback to be used for old API clients
+106 −7
Original line number Diff line number Diff line
@@ -16,45 +16,144 @@

package com.android.server.location.contexthub;

import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.location.HubInfo;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class HubInfoRegistry {
class HubInfoRegistry implements ContextHubHalEndpointCallback.IEndpointLifecycleCallback {
    private static final String TAG = "HubInfoRegistry";
    private final Object mLock = new Object();

    private final IContextHubWrapper mContextHubWrapper;

    private final List<HubInfo> mHubsInfo;
    @GuardedBy("mLock")
    private List<HubInfo> mHubsInfo;

    @GuardedBy("mLock")
    private final ArrayMap<HubEndpointInfo.HubEndpointIdentifier, HubEndpointInfo>
            mHubEndpointInfos = new ArrayMap<>();

    HubInfoRegistry(IContextHubWrapper contextHubWrapper) {
        List<HubInfo> hubInfos;
        mContextHubWrapper = contextHubWrapper;
        refreshCachedHubs();
        refreshCachedEndpoints();
    }

    /** Retrieve the list of hubs available. */
    List<HubInfo> getHubs() {
        synchronized (mLock) {
            return mHubsInfo;
        }
    }

    private void refreshCachedHubs() {
        List<HubInfo> hubInfos;
        try {
            hubInfos = mContextHubWrapper.getHubs();
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException while getting Hub info", e);
            hubInfos = Collections.emptyList();
        }

        synchronized (mLock) {
            mHubsInfo = hubInfos;
        }
    }

    /** Retrieve the list of hubs available. */
    List<HubInfo> getHubs() {
        return mHubsInfo;
    private void refreshCachedEndpoints() {
        List<HubEndpointInfo> endpointInfos;
        try {
            endpointInfos = mContextHubWrapper.getEndpoints();
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException while getting Hub info", e);
            endpointInfos = Collections.emptyList();
        }

        synchronized (mLock) {
            mHubEndpointInfos.clear();
            for (HubEndpointInfo endpointInfo : endpointInfos) {
                mHubEndpointInfos.put(endpointInfo.getIdentifier(), endpointInfo);
            }
        }
    }

    /** Invoked when HAL restarts */
    public void onHalRestart() {
        synchronized (mLock) {
            refreshCachedHubs();
            refreshCachedEndpoints();
        }
    }

    @Override
    public void onEndpointStarted(HubEndpointInfo[] endpointInfos) {
        synchronized (mLock) {
            for (HubEndpointInfo endpointInfo : endpointInfos) {
                mHubEndpointInfos.remove(endpointInfo.getIdentifier());
                mHubEndpointInfos.put(endpointInfo.getIdentifier(), endpointInfo);
            }
        }
    }

    @Override
    public void onEndpointStopped(
            HubEndpointInfo.HubEndpointIdentifier[] endpointIds, byte reason) {
        synchronized (mLock) {
            for (HubEndpointInfo.HubEndpointIdentifier endpointId : endpointIds) {
                mHubEndpointInfos.remove(endpointId);
            }
        }
    }

    /** Return a list of {@link HubEndpointInfo} that represents endpoints with the matching id. */
    public List<HubEndpointInfo> findEndpoints(long endpointIdQuery) {
        List<HubEndpointInfo> searchResult = new ArrayList<>();
        synchronized (mLock) {
            for (HubEndpointInfo.HubEndpointIdentifier endpointId : mHubEndpointInfos.keySet()) {
                if (endpointId.getEndpoint() == endpointIdQuery) {
                    searchResult.add(mHubEndpointInfos.get(endpointId));
                }
            }
        }
        return searchResult;
    }

    void dump(IndentingPrintWriter ipw) {
        synchronized (mLock) {
            dumpLocked(ipw);
        }
    }

    @GuardedBy("mLock")
    private void dumpLocked(IndentingPrintWriter ipw) {
        ipw.println(TAG);

        ipw.increaseIndent();
        ipw.println("Hubs");
        for (HubInfo hubInfo : mHubsInfo) {
            ipw.println(hubInfo);
        }
        ipw.decreaseIndent();

        ipw.println();

        ipw.increaseIndent();
        ipw.println("Endpoints");
        for (HubEndpointInfo endpointInfo : mHubEndpointInfos.values()) {
            ipw.println(endpointInfo);
        }
        ipw.decreaseIndent();

        ipw.println();
    }

}
+49 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.chre.flags.Flags;
import android.hardware.contexthub.HostEndpointInfo;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.MessageDeliveryStatus;
import android.hardware.contexthub.NanSessionRequest;
import android.hardware.contexthub.V1_0.ContextHub;
@@ -229,6 +230,15 @@ public abstract class IContextHubWrapper {
        return Collections.emptyList();
    }

    /** Calls the appropriate getEndpoints function depending on the HAL version. */
    public List<HubEndpointInfo> getEndpoints() throws RemoteException {
        return Collections.emptyList();
    }

    /** Calls the appropriate registerEndpointCallback function depending on the HAL version. */
    public void registerEndpointCallback(android.hardware.contexthub.IEndpointCallback cb)
            throws RemoteException {}

    /**
     * @return True if this version of the Contexthub HAL supports Location setting notifications.
     */
@@ -622,6 +632,45 @@ public abstract class IContextHubWrapper {
            return retVal;
        }

        @Override
        public List<HubEndpointInfo> getEndpoints() throws RemoteException {
            android.hardware.contexthub.IContextHub hub = getHub();
            if (hub == null) {
                return Collections.emptyList();
            }

            List<HubEndpointInfo> retVal = new ArrayList<>();
            final List<android.hardware.contexthub.EndpointInfo> halEndpointInfos =
                    hub.getEndpoints();
            for (android.hardware.contexthub.EndpointInfo halEndpointInfo : halEndpointInfos) {
                /* HAL -> API Type conversion */
                final HubEndpointInfo endpointInfo = new HubEndpointInfo(halEndpointInfo);
                if (DEBUG) {
                    Log.i(TAG, "getEndpoints: endpointInfo=" + endpointInfo);
                }
                retVal.add(endpointInfo);
            }

            if (DEBUG) {
                Log.i(TAG, "getEndpoints: total count=" + retVal.size());
            }
            return retVal;
        }

        @Override
        public void registerEndpointCallback(android.hardware.contexthub.IEndpointCallback cb)
                throws RemoteException {
            android.hardware.contexthub.IContextHub hub = getHub();
            if (hub == null) {
                return;
            }

            if (DEBUG) {
                Log.i(TAG, "registerEndpointCallback: cb=" + cb);
            }
            hub.registerEndpointCallback(cb);
        }

        public boolean supportsLocationSettingNotifications() {
            return true;
        }