diff options
| author | 2022-10-06 21:10:28 +0000 | |
|---|---|---|
| committer | 2022-11-01 18:04:27 +0000 | |
| commit | 6fbfc19179161aebd922943bc2fb6de3a400be03 (patch) | |
| tree | 624f10430a9d10e5e2f8fd4d85db21ce1ebb2392 | |
| parent | 96ca88699717e2ca88365fb421cffe4de0b90739 (diff) | |
Add death recipient for Context Hub AIDL HAL
When the Context Hub AIDL HAL dies, we need to reconnect to the
binder interface and reset the Context Hub Service.
Bug: 246384988
Test: m && ./vendor/google/tools/flashall
Test: adb shell dumpsys contexthub # normal
Test: adb shell logcat | grep -iE 'CHRE|contexthub' # normal
Test: kill AIDL HAL process # Context Hub restarts
Test: Run CHQTS tests before and after AIDL HAL death
Test: Same tests passed
Change-Id: I86d4c87a3b8f6aa4c476fbc866432400ba7f4a3b
| -rw-r--r-- | services/core/java/com/android/server/location/contexthub/ContextHubService.java | 39 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java | 197 |
2 files changed, 208 insertions, 28 deletions
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 6232028bbabe..4eef147b40c5 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -207,6 +207,14 @@ public class ContextHubService extends IContextHubService.Stub { handleClientMessageCallback(mContextHubId, hostEndpointId, message, nanoappPermissions, messagePermissions); } + + @Override + public void handleServiceRestart() { + Log.i(TAG, "Starting Context Hub Service restart"); + initExistingCallbacks(); + resetSettings(); + Log.i(TAG, "Finished Context Hub Service restart"); + } } public ContextHubService(Context context, IContextHubWrapper contextHubWrapper) { @@ -381,6 +389,20 @@ public class ContextHubService extends IContextHubService.Stub { } /** + * Initializes existing callbacks with the mContextHubWrapper for every context hub + */ + private void initExistingCallbacks() { + for (int contextHubId : mContextHubIdToInfoMap.keySet()) { + try { + mContextHubWrapper.registerExistingCallback(contextHubId); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException while registering existing service callback for hub " + + "(ID = " + contextHubId + ")", e); + } + } + } + + /** * Handles the initialization of location settings notifications */ private void initLocationSettingNotifications() { @@ -508,6 +530,17 @@ public class ContextHubService extends IContextHubService.Stub { mContext.registerReceiver(btReceiver, filter); } + /** + * Resets the settings. Called when a context hub restarts or the AIDL HAL dies + */ + private void resetSettings() { + sendLocationSettingUpdate(); + sendWifiSettingUpdate(/* forceUpdate= */ true); + sendAirplaneModeSettingUpdate(); + sendMicrophoneDisableSettingUpdateForCurrentUser(); + sendBtSettingUpdate(/* forceUpdate= */ true); + } + @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver result) { @@ -841,11 +874,7 @@ public class ContextHubService extends IContextHubService.Stub { ContextHubEventLogger.getInstance().logContextHubRestart(contextHubId); - sendLocationSettingUpdate(); - sendWifiSettingUpdate(/* forceUpdate= */ true); - sendAirplaneModeSettingUpdate(); - sendMicrophoneDisableSettingUpdateForCurrentUser(); - sendBtSettingUpdate(/* forceUpdate= */ true); + resetSettings(); mTransactionManager.onHubReset(); queryNanoAppsInternal(contextHubId); 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 432b097afe83..48152b40aaf6 100644 --- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java +++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java @@ -32,6 +32,7 @@ import android.hardware.location.NanoAppMessage; import android.hardware.location.NanoAppState; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -92,6 +93,11 @@ public abstract class IContextHubWrapper { */ void handleNanoappMessage(short hostEndpointId, NanoAppMessage message, List<String> nanoappPermissions, List<String> messagePermissions); + + /** + * Handles a restart of the service + */ + void handleServiceRestart(); } /** @@ -170,12 +176,9 @@ public abstract class IContextHubWrapper { } /** - * Attempts to connect to the Contexthub HAL AIDL service, if it exists. - * - * @return A valid IContextHubWrapper if the connection was successful, null otherwise. + * Attempts to connect to the AIDL HAL and returns the proxy IContextHub. */ - @Nullable - public static IContextHubWrapper maybeConnectToAidl() { + public static android.hardware.contexthub.IContextHub maybeConnectToAidlGetProxy() { android.hardware.contexthub.IContextHub proxy = null; final String aidlServiceName = android.hardware.contexthub.IContextHub.class.getCanonicalName() + "/default"; @@ -188,8 +191,18 @@ public abstract class IContextHubWrapper { } else { Log.d(TAG, "Context Hub AIDL service is not declared"); } + return proxy; + } - return (proxy == null) ? null : new ContextHubWrapperAidl(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 = maybeConnectToAidlGetProxy(); + return proxy == null ? null : new ContextHubWrapperAidl(proxy); } /** @@ -354,12 +367,22 @@ public abstract class IContextHubWrapper { public abstract void registerCallback(int contextHubId, @NonNull ICallback callback) throws RemoteException; - private static class ContextHubWrapperAidl extends IContextHubWrapper { + /** + * Registers an existing callback with the Context Hub. + * + * @param contextHubId The ID of the Context Hub to register the callback with. + */ + public abstract void registerExistingCallback(int contextHubId) throws RemoteException; + + private static class ContextHubWrapperAidl extends IContextHubWrapper + implements IBinder.DeathRecipient { private android.hardware.contexthub.IContextHub mHub; private final Map<Integer, ContextHubAidlCallback> mAidlCallbackMap = new HashMap<>(); + private Runnable mHandleServiceRestartCallback = null; + // Use this thread in case where the execution requires to be on a service thread. // For instance, AppOpsManager.noteOp requires the UPDATE_APP_OPS_STATS permission. private HandlerThread mHandlerThread = @@ -419,17 +442,51 @@ public abstract class IContextHubWrapper { } ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub) { - mHub = hub; + setHub(hub); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); + linkWrapperToHubDeath(); + } + + private synchronized android.hardware.contexthub.IContextHub getHub() { + return mHub; + } + + private synchronized void setHub(android.hardware.contexthub.IContextHub hub) { + mHub = hub; + } + + @Override + public void binderDied() { + Log.i(TAG, "Context Hub AIDL HAL died"); + + setHub(maybeConnectToAidlGetProxy()); + if (getHub() == null) { + // TODO(b/256860015): Make this reconnection more robust + Log.e(TAG, "Could not reconnect to Context Hub AIDL HAL"); + return; + } + linkWrapperToHubDeath(); + + if (mHandleServiceRestartCallback != null) { + mHandleServiceRestartCallback.run(); + } else { + Log.e(TAG, "mHandleServiceRestartCallback is not set"); + } } public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return new Pair<List<ContextHubInfo>, List<String>>(new ArrayList<ContextHubInfo>(), + new ArrayList<String>()); + } + Set<String> supportedPermissions = new HashSet<>(); ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>(); - for (android.hardware.contexthub.ContextHubInfo hub : mHub.getContextHubs()) { - hubInfoList.add(new ContextHubInfo(hub)); - for (String permission : hub.supportedPermissions) { + for (android.hardware.contexthub.ContextHubInfo hubInfo : hub.getContextHubs()) { + hubInfoList.add(new ContextHubInfo(hubInfo)); + for (String permission : hubInfo.supportedPermissions) { supportedPermissions.add(permission); } } @@ -489,8 +546,13 @@ public abstract class IContextHubWrapper { @Override public void onHostEndpointConnected(HostEndpointInfo info) { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return; + } + try { - mHub.onHostEndpointConnected(info); + hub.onHostEndpointConnected(info); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Exception in onHostEndpointConnected" + e.getMessage()); } @@ -498,8 +560,13 @@ public abstract class IContextHubWrapper { @Override public void onHostEndpointDisconnected(short hostEndpointId) { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return; + } + try { - mHub.onHostEndpointDisconnected((char) hostEndpointId); + hub.onHostEndpointDisconnected((char) hostEndpointId); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Exception in onHostEndpointDisconnected" + e.getMessage()); } @@ -509,8 +576,13 @@ public abstract class IContextHubWrapper { public int sendMessageToContextHub( short hostEndpointId, int contextHubId, NanoAppMessage message) throws RemoteException { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; + } + try { - mHub.sendMessageToHub(contextHubId, + hub.sendMessageToHub(contextHubId, ContextHubServiceUtil.createAidlContextHubMessage(hostEndpointId, message)); return ContextHubTransaction.RESULT_SUCCESS; } catch (RemoteException | ServiceSpecificException e) { @@ -523,10 +595,15 @@ public abstract class IContextHubWrapper { @ContextHubTransaction.Result public int loadNanoapp(int contextHubId, NanoAppBinary binary, int transactionId) throws RemoteException { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; + } + android.hardware.contexthub.NanoappBinary aidlNanoAppBinary = ContextHubServiceUtil.createAidlNanoAppBinary(binary); try { - mHub.loadNanoapp(contextHubId, aidlNanoAppBinary, transactionId); + hub.loadNanoapp(contextHubId, aidlNanoAppBinary, transactionId); return ContextHubTransaction.RESULT_SUCCESS; } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { return ContextHubTransaction.RESULT_FAILED_UNKNOWN; @@ -538,8 +615,13 @@ public abstract class IContextHubWrapper { @ContextHubTransaction.Result public int unloadNanoapp(int contextHubId, long nanoappId, int transactionId) throws RemoteException { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; + } + try { - mHub.unloadNanoapp(contextHubId, nanoappId, transactionId); + hub.unloadNanoapp(contextHubId, nanoappId, transactionId); return ContextHubTransaction.RESULT_SUCCESS; } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { return ContextHubTransaction.RESULT_FAILED_UNKNOWN; @@ -551,8 +633,13 @@ public abstract class IContextHubWrapper { @ContextHubTransaction.Result public int enableNanoapp(int contextHubId, long nanoappId, int transactionId) throws RemoteException { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; + } + try { - mHub.enableNanoapp(contextHubId, nanoappId, transactionId); + hub.enableNanoapp(contextHubId, nanoappId, transactionId); return ContextHubTransaction.RESULT_SUCCESS; } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { return ContextHubTransaction.RESULT_FAILED_UNKNOWN; @@ -564,8 +651,13 @@ public abstract class IContextHubWrapper { @ContextHubTransaction.Result public int disableNanoapp(int contextHubId, long nanoappId, int transactionId) throws RemoteException { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; + } + try { - mHub.disableNanoapp(contextHubId, nanoappId, transactionId); + hub.disableNanoapp(contextHubId, nanoappId, transactionId); return ContextHubTransaction.RESULT_SUCCESS; } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { return ContextHubTransaction.RESULT_FAILED_UNKNOWN; @@ -576,8 +668,13 @@ public abstract class IContextHubWrapper { @ContextHubTransaction.Result public int queryNanoapps(int contextHubId) throws RemoteException { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS; + } + try { - mHub.queryNanoapps(contextHubId); + hub.queryNanoapps(contextHubId); return ContextHubTransaction.RESULT_SUCCESS; } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) { return ContextHubTransaction.RESULT_FAILED_UNKNOWN; @@ -586,22 +683,65 @@ public abstract class IContextHubWrapper { } } - public void registerCallback(int contextHubId, ICallback callback) throws RemoteException { - mAidlCallbackMap.put(contextHubId, new ContextHubAidlCallback(contextHubId, callback)); + public void registerExistingCallback(int contextHubId) { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return; + } + + ContextHubAidlCallback callback = mAidlCallbackMap.get(contextHubId); + if (callback == null) { + Log.e(TAG, "Could not find existing callback to register for context hub ID = " + + contextHubId); + return; + } + try { - mHub.registerCallback(contextHubId, mAidlCallbackMap.get(contextHubId)); + hub.registerCallback(contextHubId, callback); } catch (RemoteException | ServiceSpecificException | IllegalArgumentException e) { Log.e(TAG, "Exception while registering callback: " + e.getMessage()); } } + public void registerCallback(int contextHubId, ICallback callback) { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return; + } + + mHandleServiceRestartCallback = callback::handleServiceRestart; + mAidlCallbackMap.put(contextHubId, new ContextHubAidlCallback(contextHubId, callback)); + registerExistingCallback(contextHubId); + } + private void onSettingChanged(byte setting, boolean enabled) { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return; + } + try { - mHub.onSettingChanged(setting, enabled); + hub.onSettingChanged(setting, enabled); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Exception while sending setting update: " + e.getMessage()); } } + + /** + * Links the mHub death handler to this + */ + private void linkWrapperToHubDeath() { + android.hardware.contexthub.IContextHub hub = getHub(); + if (hub == null) { + return; + } + + try { + hub.asBinder().linkToDeath(this, 0); + } catch (RemoteException exception) { + Log.e(TAG, "Context Hub AIDL service death receipt could not be linked"); + } + } } /** @@ -729,6 +869,17 @@ public abstract class IContextHubWrapper { mHub.registerCallback(contextHubId, mHidlCallbackMap.get(contextHubId)); } + public void registerExistingCallback(int contextHubId) throws RemoteException { + ContextHubWrapperHidlCallback callback = mHidlCallbackMap.get(contextHubId); + if (callback == null) { + Log.e(TAG, "Could not find existing callback for context hub with ID = " + + contextHubId); + return; + } + + mHub.registerCallback(contextHubId, callback); + } + public boolean supportsBtSettingNotifications() { return false; } |