Protect STHelper from calls after detach

Now that we expose detach to upper layers, we should ensure that
calling a method on a detached STHelper strongly errors.

Fixes: 277390523
Bug: 272147641
Test: atest AlwaysOnHotwordDetectorTest#isSessionInvalid_afterDetach
Change-Id: I32cf30d711e27debed0d643a9627663830e2ccf6
This commit is contained in:
Atneya Nair
2023-04-05 11:19:40 -07:00
parent d05c02efe2
commit 14de650038

View File

@@ -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());