Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 671b9dbb authored by Ytai Ben-Tsvi's avatar Ytai Ben-Tsvi Committed by Automerger Merge Worker
Browse files

RESTRICT AUTOMERGE Restart recognition when failing to deliver event am: 0896e161

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15325120

Change-Id: I5662751b89ae496631c36a3092c9ad061eca3c5c
parents bab9e04c 0896e161
Loading
Loading
Loading
Loading
+5 −13
Original line number Diff line number Diff line
@@ -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.");
        }
+40 −0
Original line number Diff line number Diff line
@@ -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();
                    }
                }
            }