summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Matthew Sedam <matthewsedam@google.com> 2022-10-06 21:10:28 +0000
committer Matthew Sedam <matthewsedam@google.com> 2022-11-01 18:04:27 +0000
commit6fbfc19179161aebd922943bc2fb6de3a400be03 (patch)
tree624f10430a9d10e5e2f8fd4d85db21ce1ebb2392
parent96ca88699717e2ca88365fb421cffe4de0b90739 (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.java39
-rw-r--r--services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java197
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;
}