RESTRICT AUTOMERGE Restart recognition when failing to deliver event am: 7769bbdaaa
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15337429 Change-Id: Ia9240317af16ec9eadce4c94db2d8c8858391c6d
This commit is contained in:
@@ -133,13 +133,8 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
|
|||||||
* Throws a {@link SecurityException} iff the originator has permission to receive data.
|
* Throws a {@link SecurityException} iff the originator has permission to receive data.
|
||||||
*/
|
*/
|
||||||
void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
|
void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
|
||||||
// TODO(b/186164881): remove
|
enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO,
|
||||||
// START TEMP HACK
|
reason);
|
||||||
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, CAPTURE_AUDIO_HOTWORD,
|
enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
|
||||||
reason);
|
reason);
|
||||||
}
|
}
|
||||||
@@ -167,8 +162,8 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws a {@link SecurityException} if originator permanently doesn't have the given
|
* Throws a {@link SecurityException} if originator permanently doesn't have the given
|
||||||
* permission, or a {@link ServiceSpecificException} with a {@link
|
* permission.
|
||||||
* Status#TEMPORARY_PERMISSION_DENIED} if caller originator doesn't have the given permission.
|
* Soft (temporary) denials are considered OK for preflight purposes.
|
||||||
*
|
*
|
||||||
* @param context A {@link Context}, used for permission checks.
|
* @param context A {@link Context}, used for permission checks.
|
||||||
* @param identity The identity to check.
|
* @param identity The identity to check.
|
||||||
@@ -180,15 +175,12 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
|
|||||||
permission);
|
permission);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case PermissionChecker.PERMISSION_GRANTED:
|
case PermissionChecker.PERMISSION_GRANTED:
|
||||||
|
case PermissionChecker.PERMISSION_SOFT_DENIED:
|
||||||
return;
|
return;
|
||||||
case PermissionChecker.PERMISSION_HARD_DENIED:
|
case PermissionChecker.PERMISSION_HARD_DENIED:
|
||||||
throw new SecurityException(
|
throw new SecurityException(
|
||||||
String.format("Failed to obtain permission %s for identity %s", permission,
|
String.format("Failed to obtain permission %s for identity %s", permission,
|
||||||
ObjectPrinter.print(identity, true, 16)));
|
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:
|
default:
|
||||||
throw new RuntimeException("Unexpected perimission check result.");
|
throw new RuntimeException("Unexpected perimission check result.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -318,6 +318,8 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
|
|||||||
*/
|
*/
|
||||||
private Map<Integer, ModelParameterRange> parameterSupport = new HashMap<>();
|
private Map<Integer, ModelParameterRange> parameterSupport = new HashMap<>();
|
||||||
|
|
||||||
|
private RecognitionConfig mConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the given parameter is known to be supported for this model.
|
* 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) {
|
void setActivityState(Activity activity) {
|
||||||
mActivityState.set(activity.ordinal());
|
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
|
// 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,
|
// the activity state may be reset outside of the lock, we set it here first,
|
||||||
// and reset it in case of exception.
|
// and reset it in case of exception.
|
||||||
|
modelState.setRecognitionConfig(config);
|
||||||
modelState.setActivityState(ModelState.Activity.ACTIVE);
|
modelState.setActivityState(ModelState.Activity.ACTIVE);
|
||||||
mDelegate.startRecognition(modelHandle, config);
|
mDelegate.startRecognition(modelHandle, config);
|
||||||
} catch (Exception e) {
|
} 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
|
@Override
|
||||||
public void forceRecognitionEvent(int modelHandle) {
|
public void forceRecognitionEvent(int modelHandle) {
|
||||||
// Input validation (always valid).
|
// Input validation (always valid).
|
||||||
@@ -753,6 +785,10 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
|
|||||||
Log.e(TAG, "Client callback exception.", e);
|
Log.e(TAG, "Client callback exception.", e);
|
||||||
if (event.status != RecognitionStatus.FORCED) {
|
if (event.status != RecognitionStatus.FORCED) {
|
||||||
modelState.setActivityState(ModelState.Activity.INTERCEPTED);
|
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);
|
Log.e(TAG, "Client callback exception.", e);
|
||||||
if (event.common.status != RecognitionStatus.FORCED) {
|
if (event.common.status != RecognitionStatus.FORCED) {
|
||||||
modelState.setActivityState(ModelState.Activity.INTERCEPTED);
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user