diff --git a/Android.bp b/Android.bp index 9127966fffc40..0ac41c06167cf 100644 --- a/Android.bp +++ b/Android.bp @@ -238,6 +238,7 @@ java_library { "android.hardware.contexthub-V1.0-java", "android.hardware.contexthub-V1.1-java", "android.hardware.contexthub-V1.2-java", + "android.hardware.contexthub-V1-java", "android.hardware.gnss-V1.0-java", "android.hardware.gnss-V2.1-java", "android.hardware.health-V1.0-java-constants", diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java index 6d56d2d459221..51045a4b6d665 100644 --- a/core/java/android/hardware/location/ContextHubInfo.java +++ b/core/java/android/hardware/location/ContextHubInfo.java @@ -79,6 +79,29 @@ public class ContextHubInfo implements Parcelable { mSupportedSensors = new int[0]; mMemoryRegions = new MemoryRegion[0]; } + /** + * @hide + */ + public ContextHubInfo(android.hardware.contexthub.ContextHubInfo contextHub) { + mId = contextHub.id; + mName = contextHub.name; + mVendor = contextHub.vendor; + mToolchain = contextHub.toolchain; + mPlatformVersion = 0; + mToolchainVersion = 0; + mPeakMips = contextHub.peakMips; + mStoppedPowerDrawMw = 0; + mSleepPowerDrawMw = 0; + mPeakPowerDrawMw = 0; + mMaxPacketLengthBytes = contextHub.maxSupportedMessageLengthBytes; + mChrePlatformId = contextHub.chrePlatformId; + mChreApiMajorVersion = contextHub.chreApiMajorVersion; + mChreApiMinorVersion = contextHub.chreApiMinorVersion; + mChrePatchVersion = (short) contextHub.chrePatchVersion; + + mSupportedSensors = new int[0]; + mMemoryRegions = new MemoryRegion[0]; + } /** * returns the maximum number of bytes that can be sent per message to the hub 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 27a78dd17d276..a491eb753d361 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -359,7 +359,10 @@ public class ContextHubService extends IContextHubService.Stub { * @return the IContextHubWrapper interface */ private IContextHubWrapper getContextHubWrapper() { - IContextHubWrapper wrapper = IContextHubWrapper.maybeConnectTo1_2(); + IContextHubWrapper wrapper = IContextHubWrapper.maybeConnectToAidl(); + if (wrapper == null) { + wrapper = IContextHubWrapper.maybeConnectTo1_2(); + } if (wrapper == null) { wrapper = IContextHubWrapper.maybeConnectTo1_1(); } diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java index df6cc0517964c..1de749bd5b9d1 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java @@ -33,6 +33,7 @@ import android.hardware.location.NanoAppState; import android.util.Log; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -44,6 +45,11 @@ import java.util.List; private static final String TAG = "ContextHubServiceUtil"; private static final String CONTEXT_HUB_PERMISSION = Manifest.permission.ACCESS_CONTEXT_HUB; + /** + * A host endpoint that is reserved to identify a broadcasted message. + */ + private static final char HOST_ENDPOINT_BROADCAST = 0xFFFF; + /** * Creates a ConcurrentHashMap of the Context Hub ID to the ContextHubInfo object given an * ArrayList of HIDL ContextHub objects. @@ -110,11 +116,11 @@ import java.util.List; } /** - * Generates the Context Hub HAL's NanoAppBinary object from the client-facing + * Generates the Context Hub HAL's HIDL NanoAppBinary object from the client-facing * android.hardware.location.NanoAppBinary object. * * @param nanoAppBinary the client-facing NanoAppBinary object - * @return the Context Hub HAL's NanoAppBinary object + * @return the Context Hub HAL's HIDL NanoAppBinary object */ /* package */ static android.hardware.contexthub.V1_0.NanoAppBinary createHidlNanoAppBinary( @@ -141,6 +147,29 @@ import java.util.List; return hidlNanoAppBinary; } + /** + * Generates the Context Hub HAL's AIDL NanoAppBinary object from the client-facing + * android.hardware.location.NanoAppBinary object. + * + * @param nanoAppBinary the client-facing NanoAppBinary object + * @return the Context Hub HAL's AIDL NanoAppBinary object + */ + /* package */ + static android.hardware.contexthub.NanoappBinary createAidlNanoAppBinary( + NanoAppBinary nanoAppBinary) { + android.hardware.contexthub.NanoappBinary aidlNanoAppBinary = + new android.hardware.contexthub.NanoappBinary(); + + aidlNanoAppBinary.nanoappId = nanoAppBinary.getNanoAppId(); + aidlNanoAppBinary.nanoappVersion = nanoAppBinary.getNanoAppVersion(); + aidlNanoAppBinary.flags = nanoAppBinary.getFlags(); + aidlNanoAppBinary.targetChreApiMajorVersion = nanoAppBinary.getTargetChreApiMajorVersion(); + aidlNanoAppBinary.targetChreApiMinorVersion = nanoAppBinary.getTargetChreApiMinorVersion(); + aidlNanoAppBinary.customBinary = nanoAppBinary.getBinaryNoHeader(); + + return aidlNanoAppBinary; + } + /** * Generates a client-facing NanoAppState array from a HAL HubAppInfo array. * @@ -154,7 +183,26 @@ import java.util.List; for (HubAppInfo appInfo : nanoAppInfoList) { nanoAppStateList.add( new NanoAppState(appInfo.info_1_0.appId, appInfo.info_1_0.version, - appInfo.info_1_0.enabled, appInfo.permissions)); + appInfo.info_1_0.enabled, appInfo.permissions)); + } + + return nanoAppStateList; + } + + /** + * Generates a client-facing NanoAppState array from a AIDL NanoappInfo array. + * + * @param nanoAppInfoList the array of NanoappInfo objects + * @return the corresponding array of NanoAppState objects + */ + /* package */ + static List createNanoAppStateList( + android.hardware.contexthub.NanoappInfo[] nanoAppInfoList) { + ArrayList nanoAppStateList = new ArrayList<>(); + for (android.hardware.contexthub.NanoappInfo appInfo : nanoAppInfoList) { + nanoAppStateList.add( + new NanoAppState(appInfo.nanoappId, appInfo.nanoappVersion, + appInfo.enabled, new ArrayList<>(Arrays.asList(appInfo.permissions)))); } return nanoAppStateList; @@ -179,6 +227,29 @@ import java.util.List; return hidlMessage; } + /** + * Creates an AIDL ContextHubMessage object to send to a nanoapp. + * + * @param hostEndPoint the ID of the client sending the message + * @param message the client-facing NanoAppMessage object describing the message + * @return the AIDL ContextHubMessage object + */ + /* package */ + static android.hardware.contexthub.ContextHubMessage createAidlContextHubMessage( + short hostEndPoint, NanoAppMessage message) { + android.hardware.contexthub.ContextHubMessage aidlMessage = + new android.hardware.contexthub.ContextHubMessage(); + + aidlMessage.nanoappId = message.getNanoAppId(); + aidlMessage.hostEndPoint = (char) hostEndPoint; + aidlMessage.messageType = message.getMessageType(); + aidlMessage.messageBody = message.getMessageBody(); + // This explicit definition is required to avoid erroneous behavior at the binder. + aidlMessage.permissions = new String[0]; + + return aidlMessage; + } + /** * Creates a client-facing NanoAppMessage object to send to a client. * @@ -194,6 +265,20 @@ import java.util.List; message.hostEndPoint == HostEndPoint.BROADCAST); } + /** + * Creates a client-facing NanoAppMessage object to send to a client. + * + * @param message the AIDL ContextHubMessage object from a nanoapp + * @return the NanoAppMessage object + */ + /* package */ + static NanoAppMessage createNanoAppMessage( + android.hardware.contexthub.ContextHubMessage message) { + return NanoAppMessage.createMessageFromNanoApp( + message.nanoappId, message.messageType, message.messageBody, + message.hostEndPoint == HOST_ENDPOINT_BROADCAST); + } + /** * Checks for location hardware permissions. * @@ -274,4 +359,21 @@ import java.util.List; return ContextHubService.CONTEXT_HUB_EVENT_UNKNOWN; } } + + /** + * Converts an AIDL AsyncEventType to the corresponding ContextHubService.CONTEXT_HUB_EVENT_*. + * + * @param aidlEventType The AsyncEventType value. + * @return The converted event type. + */ + /* package */ + static int toContextHubEventFromAidl(int aidlEventType) { + switch (aidlEventType) { + case android.hardware.contexthub.AsyncEventType.RESTARTED: + return ContextHubService.CONTEXT_HUB_EVENT_RESTARTED; + default: + Log.e(TAG, "toContextHubEventFromAidl: Unknown event type: " + aidlEventType); + return ContextHubService.CONTEXT_HUB_EVENT_UNKNOWN; + } + } } 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 d733db0097268..6c70d9deff45a 100644 --- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java +++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java @@ -30,13 +30,17 @@ import android.hardware.location.NanoAppBinary; import android.hardware.location.NanoAppMessage; import android.hardware.location.NanoAppState; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import android.util.Pair; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; +import java.util.Set; /** * @hide @@ -140,6 +144,29 @@ public abstract class IContextHubWrapper { return (proxy == null) ? null : new ContextHubWrapperV1_2(proxy); } + /** + * Attempts to connect to the Contexthub HAL AIDL service, if it exists. + * + * @return A valid IContextHubWrapper if the connection was successful, null otherwise. + */ + @Nullable + public static IContextHubWrapper maybeConnectToAidl() { + android.hardware.contexthub.IContextHub proxy = null; + final String aidlServiceName = + android.hardware.contexthub.IContextHub.class.getCanonicalName() + "/default"; + if (ServiceManager.isDeclared(aidlServiceName)) { + proxy = android.hardware.contexthub.IContextHub.Stub.asInterface( + ServiceManager.waitForService(aidlServiceName)); + if (proxy == null) { + Log.e(TAG, "Context Hub AIDL service was declared but was not found"); + } + } else { + Log.d(TAG, "Context Hub AIDL service is not declared"); + } + + return (proxy == null) ? null : new ContextHubWrapperAidl(proxy); + } + /** * Calls the appropriate getHubs function depending on the HAL version. */ @@ -258,6 +285,137 @@ public abstract class IContextHubWrapper { public abstract void registerCallback(int contextHubId, @NonNull ICallback callback) throws RemoteException; + private static class ContextHubWrapperAidl extends IContextHubWrapper { + private android.hardware.contexthub.IContextHub mHub; + + private ICallback mCallback = null; + + private ContextHubAidlCallback mAidlCallback = new ContextHubAidlCallback(); + + private class ContextHubAidlCallback extends + android.hardware.contexthub.IContextHubCallback.Stub { + public void handleNanoappInfo(android.hardware.contexthub.NanoappInfo[] appInfo) { + List nanoAppStateList = + ContextHubServiceUtil.createNanoAppStateList(appInfo); + mCallback.handleNanoappInfo(nanoAppStateList); + } + + public void handleContextHubMessage(android.hardware.contexthub.ContextHubMessage msg, + String[] msgContentPerms) { + mCallback.handleNanoappMessage( + (short) msg.hostEndPoint, + ContextHubServiceUtil.createNanoAppMessage(msg), + new ArrayList<>(Arrays.asList(msg.permissions)), + new ArrayList<>(Arrays.asList(msgContentPerms))); + } + + public void handleContextHubAsyncEvent(int evt) { + mCallback.handleContextHubEvent( + ContextHubServiceUtil.toContextHubEventFromAidl(evt)); + } + + public void handleTransactionResult(int transactionId, boolean success) { + mCallback.handleTransactionResult(transactionId, success); + } + } + + ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub) { + mHub = hub; + } + + public Pair, List> getHubs() throws RemoteException { + Set supportedPermissions = new HashSet<>(); + ArrayList hubInfoList = new ArrayList<>(); + for (android.hardware.contexthub.ContextHubInfo hub : mHub.getContextHubs()) { + hubInfoList.add(new ContextHubInfo(hub)); + for (String permission : hub.supportedPermissions) { + supportedPermissions.add(permission); + } + } + return new Pair(hubInfoList, new ArrayList(supportedPermissions)); + } + + // TODO(b/194285834): Implement settings logic + public boolean supportsLocationSettingNotifications() { + return false; + } + + public boolean supportsWifiSettingNotifications() { + return false; + } + + public boolean supportsAirplaneModeSettingNotifications() { + return false; + } + + public boolean supportsMicrophoneDisableSettingNotifications() { + return false; + } + + public void onLocationSettingChanged(boolean enabled) { + } + + public void onWifiSettingChanged(boolean enabled) { + } + + public void onAirplaneModeSettingChanged(boolean enabled) { + } + + public void onMicrophoneDisableSettingChanged(boolean enabled) { + } + + @ContextHubTransaction.Result + public int sendMessageToContextHub( + short hostEndpointId, int contextHubId, NanoAppMessage message) + throws RemoteException { + return toTransactionResult(mHub.sendMessageToHub(contextHubId, + ContextHubServiceUtil.createAidlContextHubMessage(hostEndpointId, message))); + } + + @ContextHubTransaction.Result + public int loadNanoapp(int contextHubId, NanoAppBinary binary, + int transactionId) throws RemoteException { + android.hardware.contexthub.NanoappBinary aidlNanoAppBinary = + ContextHubServiceUtil.createAidlNanoAppBinary(binary); + return toTransactionResult( + mHub.loadNanoapp(contextHubId, aidlNanoAppBinary, transactionId)); + } + + @ContextHubTransaction.Result + public int unloadNanoapp(int contextHubId, long nanoappId, int transactionId) + throws RemoteException { + return toTransactionResult(mHub.unloadNanoapp(contextHubId, nanoappId, transactionId)); + } + + @ContextHubTransaction.Result + public int enableNanoapp(int contextHubId, long nanoappId, int transactionId) + throws RemoteException { + return toTransactionResult(mHub.enableNanoapp(contextHubId, nanoappId, transactionId)); + } + + @ContextHubTransaction.Result + public int disableNanoapp(int contextHubId, long nanoappId, int transactionId) + throws RemoteException { + return toTransactionResult(mHub.disableNanoapp(contextHubId, nanoappId, transactionId)); + } + + @ContextHubTransaction.Result + public int queryNanoapps(int contextHubId) throws RemoteException { + return toTransactionResult(mHub.queryNanoapps(contextHubId)); + } + + public void registerCallback(int contextHubId, ICallback callback) throws RemoteException { + mCallback = callback; + mHub.registerCallback(contextHubId, mAidlCallback); + } + + @ContextHubTransaction.Result + private int toTransactionResult(boolean success) { + return success ? ContextHubTransaction.RESULT_SUCCESS + : ContextHubTransaction.RESULT_FAILED_UNKNOWN; + } + } + /** * An abstract call that defines methods common to all HIDL IContextHubWrappers. */