diff options
4 files changed, 266 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubHalEndpointCallback.java b/services/core/java/com/android/server/location/contexthub/ContextHubHalEndpointCallback.java new file mode 100644 index 000000000000..c05f7a0c0e00 --- /dev/null +++ b/services/core/java/com/android/server/location/contexthub/ContextHubHalEndpointCallback.java @@ -0,0 +1,93 @@ +/* + * 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; + } +} diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java index 88a7d08415dc..dd7e4dd69a80 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -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,8 +758,10 @@ public class ContextHubService extends IContextHubService.Stub { @Override public List<HubEndpointInfo> findEndpoints(long endpointId) { super.findEndpoints_enforcePermission(); - // TODO(b/375487784): connect this with mHubInfoRegistry - return Collections.emptyList(); + if (mHubInfoRegistry == null) { + return Collections.emptyList(); + } + return mHubInfoRegistry.findEndpoints(endpointId); } /** diff --git a/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java b/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java index 68de9dbda2e1..4d1000f3e0e5 100644 --- a/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java +++ b/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java @@ -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(); } - mHubsInfo = hubInfos; + + 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(); } + } diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java index 6656a6fe9eb4..9b729eb11eed 100644 --- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java +++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java @@ -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; } |