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

Commit 8bcb06a1 authored by Atneya Nair's avatar Atneya Nair Committed by Android (Google) Code Review
Browse files

Merge changes from topic "detach_cut" into udc-dev

* changes:
  [hotword] detach session when detector is destroyed
  Protect STHelper from calls after detach
parents 9b198254 7040c129
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -1334,13 +1334,7 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
    @Override
    public void destroy() {
        synchronized (mLock) {
            if (mAvailability == STATE_KEYPHRASE_ENROLLED) {
                try {
                    stopRecognition();
                } catch (Exception e) {
                    Log.i(TAG, "failed to stopRecognition in destroy", e);
                }
            }
            detachSessionLocked();

            mAvailability = STATE_INVALID;
            mIsAvailabilityOverriddenByTestApi = false;
@@ -1349,6 +1343,17 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
        super.destroy();
    }

    private void detachSessionLocked() {
        try {
            if (DBG) Slog.d(TAG, "detachSessionLocked() " + mSoundTriggerSession);
            if (mSoundTriggerSession != null) {
                mSoundTriggerSession.detach();
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     */
+5 −0
Original line number Diff line number Diff line
@@ -94,4 +94,9 @@ interface IVoiceInteractionSoundTriggerSession {
     */
    @nullable SoundTrigger.ModelParamRange queryParameter(int keyphraseId,
            in ModelParams modelParam);
    /**
     * Invalidates the sound trigger session and clears any associated resources. Subsequent calls
     * to this object will throw IllegalStateException.
     */
    void detach();
}
+6 −0
Original line number Diff line number Diff line
@@ -141,6 +141,12 @@ public interface SoundTriggerInternal {
        ModelParamRange queryParameter(int keyphraseId,
                @ModelParams int modelParam);

        /**
         * Invalidates the sound trigger session and clears any associated resources. Subsequent
         * calls to this object will throw IllegalStateException.
         */
        void detach();

        /**
         * Unloads (and stops if running) the given keyphraseId
         */
+70 −24
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;

import java.io.FileDescriptor;
@@ -129,6 +130,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
    private final Function<SoundTrigger.StatusListener, SoundTriggerModule> mModuleProvider;
    private final Supplier<List<ModuleProperties>> mModulePropertiesProvider;

    @GuardedBy("mLock")
    private boolean mIsDetached = false;

    SoundTriggerHelper(Context context,
            @NonNull Function<SoundTrigger.StatusListener, SoundTriggerModule> moduleProvider,
            int moduleId,
@@ -184,7 +188,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
     * recognition.
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int startGenericRecognition(UUID modelId, GenericSoundModel soundModel,
    public int startGenericRecognition(UUID modelId, GenericSoundModel soundModel,
            IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
            boolean runInBatterySaverMode) {
        MetricsLogger.count(mContext, "sth_start_recognition", 1);
@@ -195,6 +199,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
        }

        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            ModelData modelData = getOrCreateGenericModelDataLocked(modelId);
            if (modelData == null) {
                Slog.w(TAG, "Irrecoverable error occurred, check UUID / sound model data.");
@@ -214,7 +221,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
     * @param callback The callback for the recognition events related to the given keyphrase.
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int startKeyphraseRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
    public int startKeyphraseRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
            IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
            boolean runInBatterySaverMode) {
        synchronized (mLock) {
@@ -223,6 +230,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
                return STATUS_ERROR;
            }

            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }

            if (DBG) {
                Slog.d(TAG, "startKeyphraseRecognition for keyphraseId=" + keyphraseId
                        + " soundModel=" + soundModel + ", callback=" + callback.asBinder()
@@ -311,7 +322,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
     * for the recognition.
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int startRecognition(SoundModel soundModel, ModelData modelData,
    private int startRecognition(SoundModel soundModel, ModelData modelData,
            IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
            int keyphraseId, boolean runInBatterySaverMode) {
        synchronized (mLock) {
@@ -385,7 +396,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
     *
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int stopGenericRecognition(UUID modelId, IRecognitionStatusCallback callback) {
    public int stopGenericRecognition(UUID modelId, IRecognitionStatusCallback callback) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_stop_recognition", 1);
            if (callback == null || modelId == null) {
@@ -393,7 +404,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
                        modelId);
                return STATUS_ERROR;
            }

            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            ModelData modelData = mModelDataMap.get(modelId);
            if (modelData == null || !modelData.isGenericModel()) {
                Slog.w(TAG, "Attempting stopRecognition on invalid model with id:" + modelId);
@@ -418,7 +431,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
     *
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int stopKeyphraseRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
    public int stopKeyphraseRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_stop_recognition", 1);
            if (callback == null) {
@@ -426,7 +439,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
                        keyphraseId);
                return STATUS_ERROR;
            }

            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
            if (modelData == null || !modelData.isKeyphraseModel()) {
                Slog.w(TAG, "No model exists for given keyphrase Id " + keyphraseId);
@@ -538,6 +553,11 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
    }

    public ModuleProperties getModuleProperties() {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
        }
        for (ModuleProperties moduleProperties : mModulePropertiesProvider.get()) {
            if (moduleProperties.getId() == mModuleId) {
                return moduleProperties;
@@ -547,7 +567,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
        return null;
    }

    int unloadKeyphraseSoundModel(int keyphraseId) {
    public int unloadKeyphraseSoundModel(int keyphraseId) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1);
            ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
@@ -555,7 +575,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
                    || !modelData.isKeyphraseModel()) {
                return STATUS_ERROR;
            }

            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            // Stop recognition if it's the current one.
            modelData.setRequested(false);
            int status = updateRecognitionLocked(modelData, false);
@@ -574,12 +596,15 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
        }
    }

    int unloadGenericSoundModel(UUID modelId) {
    public int unloadGenericSoundModel(UUID modelId) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_unload_generic_sound_model", 1);
            if (modelId == null || mModule == null) {
                return STATUS_ERROR;
            }
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            ModelData modelData = mModelDataMap.get(modelId);
            if (modelData == null || !modelData.isGenericModel()) {
                Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" +
@@ -615,19 +640,25 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
        }
    }

    boolean isRecognitionRequested(UUID modelId) {
    public boolean isRecognitionRequested(UUID modelId) {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            ModelData modelData = mModelDataMap.get(modelId);
            return modelData != null && modelData.isRequested();
        }
    }

    int getGenericModelState(UUID modelId) {
    public int getGenericModelState(UUID modelId) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_get_generic_model_state", 1);
            if (modelId == null || mModule == null) {
                return STATUS_ERROR;
            }
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            ModelData modelData = mModelDataMap.get(modelId);
            if (modelData == null || !modelData.isGenericModel()) {
                Slog.w(TAG, "GetGenericModelState error: Invalid generic model id:" +
@@ -647,19 +678,20 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
        }
    }

    int getKeyphraseModelState(UUID modelId) {
        Slog.w(TAG, "GetKeyphraseModelState error: Not implemented");
        return STATUS_ERROR;
    }

    int setParameter(UUID modelId, @ModelParams int modelParam, int value) {
    public int setParameter(UUID modelId, @ModelParams int modelParam, int value) {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            return setParameterLocked(mModelDataMap.get(modelId), modelParam, value);
        }
    }

    int setKeyphraseParameter(int keyphraseId, @ModelParams int modelParam, int value) {
    public int setKeyphraseParameter(int keyphraseId, @ModelParams int modelParam, int value) {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            return setParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam, value);
        }
    }
@@ -678,14 +710,20 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
        return mModule.setParameter(modelData.getHandle(), modelParam, value);
    }

    int getParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
    public int getParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            return getParameterLocked(mModelDataMap.get(modelId), modelParam);
        }
    }

    int getKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
    public int getKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            return getParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam);
        }
    }
@@ -707,15 +745,21 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
    }

    @Nullable
    ModelParamRange queryParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
    public ModelParamRange queryParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            return queryParameterLocked(mModelDataMap.get(modelId), modelParam);
        }
    }

    @Nullable
    ModelParamRange queryKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
    public ModelParamRange queryKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
        synchronized (mLock) {
            if (mIsDetached) {
                throw new IllegalStateException("SoundTriggerHelper has been detached");
            }
            return queryParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam);
        }
    }
@@ -1115,12 +1159,14 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
     */
    public void detach() {
        synchronized (mLock) {
            if (mIsDetached) return;
            for (ModelData model : mModelDataMap.values()) {
                forceStopAndUnloadModelLocked(model, null);
            }
            mModelDataMap.clear();
            internalClearGlobalStateLocked();
            if (mModule != null) {
                mIsDetached = true;
                mModule.detach();
                mModule = null;
            }
@@ -1289,7 +1335,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
     * @param modelData Model data to be used for recognition
     * @return True if device state allows recognition to run, false if not.
     */
    boolean isRecognitionAllowedByPowerState(ModelData modelData) {
    private boolean isRecognitionAllowedByPowerState(ModelData modelData) {
        return mSoundTriggerPowerSaveMode == PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED
                || (mSoundTriggerPowerSaveMode == PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY
                && modelData.shouldRunInBatterySaverMode());
+5 −0
Original line number Diff line number Diff line
@@ -1662,6 +1662,11 @@ public class SoundTriggerService extends SystemService {
                return mSoundTriggerHelper.queryKeyphraseParameter(keyphraseId, modelParam);
            }

            @Override
            public void detach() {
                mSoundTriggerHelper.detach();
            }

            @Override
            public int unloadKeyphraseModel(int keyphraseId) {
                return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId);
Loading