diff options
| author | 2021-07-22 07:47:46 +0000 | |
|---|---|---|
| committer | 2021-07-22 07:47:46 +0000 | |
| commit | 43993b70c481a588d417565a9b15d3a3c80d1445 (patch) | |
| tree | 6afd9d1df970d471cc202a145de619656b3e2d12 | |
| parent | c630f87976d8e53436827b8f806f7fcbd2c03577 (diff) | |
| parent | 0896e161b3786ea175261b0b63b5eedf30e44425 (diff) | |
Merge "RESTRICT AUTOMERGE Restart recognition when failing to deliver event" into sc-dev
2 files changed, 45 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java index c1f8240f4018..9999aff3aa91 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java @@ -133,13 +133,8 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware * Throws a {@link SecurityException} iff the originator has permission to receive data. */ void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) { - // TODO(b/186164881): remove - // START TEMP HACK - enforcePermissionForPreflight(mContext, identity, RECORD_AUDIO); - int hotwordOp = AppOpsManager.strOpToOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD); - mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(hotwordOp, identity.uid, - identity.packageName, identity.attributionTag, reason); - // END TEMP HACK + enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO, + reason); enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD, reason); } @@ -167,8 +162,8 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware /** * Throws a {@link SecurityException} if originator permanently doesn't have the given - * permission, or a {@link ServiceSpecificException} with a {@link - * Status#TEMPORARY_PERMISSION_DENIED} if caller originator doesn't have the given permission. + * permission. + * Soft (temporary) denials are considered OK for preflight purposes. * * @param context A {@link Context}, used for permission checks. * @param identity The identity to check. @@ -180,15 +175,12 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware permission); switch (status) { case PermissionChecker.PERMISSION_GRANTED: + case PermissionChecker.PERMISSION_SOFT_DENIED: return; case PermissionChecker.PERMISSION_HARD_DENIED: throw new SecurityException( String.format("Failed to obtain permission %s for identity %s", permission, ObjectPrinter.print(identity, true, 16))); - case PermissionChecker.PERMISSION_SOFT_DENIED: - throw new ServiceSpecificException(Status.TEMPORARY_PERMISSION_DENIED, - String.format("Failed to obtain permission %s for identity %s", permission, - ObjectPrinter.print(identity, true, 16))); default: throw new RuntimeException("Unexpected perimission check result."); } diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java index 95a30c7f0278..458eae916d20 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java @@ -318,6 +318,8 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware */ private Map<Integer, ModelParameterRange> parameterSupport = new HashMap<>(); + private RecognitionConfig mConfig; + /** * Check that the given parameter is known to be supported for this model. * @@ -369,6 +371,14 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware void setActivityState(Activity activity) { mActivityState.set(activity.ordinal()); } + + void setRecognitionConfig(@NonNull RecognitionConfig config) { + mConfig = config; + } + + RecognitionConfig getRecognitionConfig() { + return mConfig; + } } /** @@ -502,6 +512,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware // Normally, we would set the state after the operation succeeds. However, since // the activity state may be reset outside of the lock, we set it here first, // and reset it in case of exception. + modelState.setRecognitionConfig(config); modelState.setActivityState(ModelState.Activity.ACTIVE); mDelegate.startRecognition(modelHandle, config); } catch (Exception e) { @@ -542,6 +553,27 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware } } + private void restartIfIntercepted(int modelHandle) { + synchronized (SoundTriggerMiddlewareValidation.this) { + // State validation. + if (mState == ModuleStatus.DETACHED) { + return; + } + ModelState modelState = mLoadedModels.get(modelHandle); + if (modelState == null + || modelState.getActivityState() != ModelState.Activity.INTERCEPTED) { + return; + } + try { + mDelegate.startRecognition(modelHandle, modelState.getRecognitionConfig()); + modelState.setActivityState(ModelState.Activity.ACTIVE); + Log.i(TAG, "Restarted intercepted model " + modelHandle); + } catch (Exception e) { + Log.i(TAG, "Failed to restart intercepted model " + modelHandle, e); + } + } + } + @Override public void forceRecognitionEvent(int modelHandle) { // Input validation (always valid). @@ -753,6 +785,10 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware Log.e(TAG, "Client callback exception.", e); if (event.status != RecognitionStatus.FORCED) { modelState.setActivityState(ModelState.Activity.INTERCEPTED); + // If we failed to deliver an actual event to the client, they would never + // know to restart it whenever circumstances change. Thus, we restart it + // here. We do this from a separate thread to avoid any race conditions. + new Thread(() -> restartIfIntercepted(modelHandle)).start(); } } } @@ -780,6 +816,10 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware Log.e(TAG, "Client callback exception.", e); if (event.common.status != RecognitionStatus.FORCED) { modelState.setActivityState(ModelState.Activity.INTERCEPTED); + // If we failed to deliver an actual event to the client, they would never + // know to restart it whenever circumstances change. Thus, we restart it + // here. We do this from a separate thread to avoid any race conditions. + new Thread(() -> restartIfIntercepted(modelHandle)).start(); } } } |