summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorSandeep Siddhartha <sansid@google.com>2014-07-20 12:22:56 -0700
committerSandeep Siddhartha <sansid@google.com>2014-07-20 16:53:09 -0700
commit110f569b47bc21fb38ec25b6110ee302ce137e06 (patch)
treeb596841dbf21aaf5d23e1d905cf2914f5f6d53e4 /services
parent8ca1fdc10b9afb831636ce00e48b9692476413c5 (diff)
downloadframeworks_base-110f569b47bc21fb38ec25b6110ee302ce137e06.zip
frameworks_base-110f569b47bc21fb38ec25b6110ee302ce137e06.tar.gz
frameworks_base-110f569b47bc21fb38ec25b6110ee302ce137e06.tar.bz2
Fix synchronization issues in AlwaysOnHotwordDetector
- Remove unnecessary recognition status from AlwaysOnHotwordDetector - Remove unnecessary recognition started callback from IRecognitionStatusCallback - Fix a bug around the fact that we weren't picking up enrollment at runtime because we were storing the availability at instantiation time. - Handle 0-length arrays in SoundTrigger classes while parceling/unparceling - Fix issue in SoundTrigger helper where we were not comparing binders for start/stop calls - Unload the previous model when starting a new recognition - Add more debug logging Change-Id: Icc56d7f3dd1ffa49a8cfeea49080e3ab4d342c32
Diffstat (limited to 'services')
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java37
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java42
2 files changed, 67 insertions, 12 deletions
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index eed2d44..50be1dc 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -24,6 +24,7 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Slog;
@@ -38,6 +39,7 @@ import java.util.UUID;
*/
public class DatabaseHelper extends SQLiteOpenHelper {
static final String TAG = "SoundModelDBHelper";
+ static final boolean DBG = false;
private static final String NAME = "sound_model.db";
private static final int VERSION = 2;
@@ -75,8 +77,11 @@ public class DatabaseHelper extends SQLiteOpenHelper {
+ SoundModelContract.KEY_TYPE + " INTEGER,"
+ SoundModelContract.KEY_DATA + " BLOB" + ")";
+ private final UserManager mUserManager;
+
public DatabaseHelper(Context context) {
super(context, NAME, null, VERSION);
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
}
@Override
@@ -175,8 +180,17 @@ public class DatabaseHelper extends SQLiteOpenHelper {
String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID));
byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
// Get all the keyphrases for this this sound model.
- models.add(new KeyphraseSoundModel(
- UUID.fromString(id), data, getKeyphrasesForSoundModel(db, id)));
+ // Validate the sound model.
+ if (id == null) {
+ Slog.w(TAG, "Ignoring sound model since it doesn't specify an ID");
+ continue;
+ }
+ KeyphraseSoundModel model = new KeyphraseSoundModel(
+ UUID.fromString(id), data, getKeyphrasesForSoundModel(db, id));
+ if (DBG) {
+ Slog.d(TAG, "Adding model: " + model);
+ }
+ models.add(model);
} while (c.moveToNext());
}
c.close();
@@ -200,6 +214,25 @@ public class DatabaseHelper extends SQLiteOpenHelper {
String locale = c.getString(c.getColumnIndex(KeyphraseContract.KEY_LOCALE));
String hintText = c.getString(c.getColumnIndex(KeyphraseContract.KEY_HINT_TEXT));
+ // Only add keyphrases meant for the current user.
+ if (users == null) {
+ // No users present in the keyphrase.
+ Slog.w(TAG, "Ignoring keyphrase since it doesn't specify users");
+ continue;
+ }
+ boolean isAvailableForCurrentUser = false;
+ int currentUser = mUserManager.getUserHandle();
+ for (int user : users) {
+ if (currentUser == user) {
+ isAvailableForCurrentUser = true;
+ break;
+ }
+ }
+ if (!isAvailableForCurrentUser) {
+ Slog.w(TAG, "Ignoring keyphrase since it's not for the current user");
+ continue;
+ }
+
keyphrases.add(new Keyphrase(id, modes, locale, hintText, users));
} while (c.moveToNext());
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
index 6842f7d..4430586 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
@@ -38,8 +38,9 @@ import java.util.ArrayList;
*/
public class SoundTriggerHelper implements SoundTrigger.StatusListener {
static final String TAG = "SoundTriggerHelper";
+ static final boolean DBG = false;
// TODO: Remove this.
- static final int TEMP_KEYPHRASE_ID = 1;
+ static final int TEMP_KEYPHRASE_ID = 100;
/**
* Return codes for {@link #startRecognition(int, KeyphraseSoundModel,
@@ -101,20 +102,32 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
KeyphraseSoundModel soundModel,
IRecognitionStatusCallback listener,
RecognitionConfig recognitionConfig) {
+ if (DBG) {
+ Slog.d(TAG, "startRecognition for keyphraseId=" + keyphraseId
+ + " soundModel=" + soundModel + ", listener=" + listener
+ + ", recognitionConfig=" + recognitionConfig);
+ Slog.d(TAG, "moduleProperties=" + moduleProperties);
+ Slog.d(TAG, "# of current listeners=" + mActiveListeners.size());
+ Slog.d(TAG, "mCurrentSoundModelHandle=" + mCurrentSoundModelHandle);
+ }
if (moduleProperties == null || mModule == null) {
Slog.w(TAG, "Attempting startRecognition without the capability");
return STATUS_ERROR;
}
+ if (mCurrentSoundModelHandle != INVALID_SOUND_MODEL_HANDLE) {
+ Slog.w(TAG, "Canceling previous recognition");
+ // TODO: Inspect the return codes here.
+ mModule.unloadSoundModel(mCurrentSoundModelHandle);
+ mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
+ }
+
+ // If the previous recognition was by a different listener,
+ // Notify them that it was stopped.
IRecognitionStatusCallback oldListener = mActiveListeners.get(keyphraseId);
- if (oldListener != null && oldListener != listener) {
- if (mCurrentSoundModelHandle != INVALID_SOUND_MODEL_HANDLE) {
- Slog.w(TAG, "Canceling previous recognition");
- // TODO: Inspect the return codes here.
- mModule.unloadSoundModel(mCurrentSoundModelHandle);
- }
+ if (oldListener != null && oldListener.asBinder() != listener.asBinder()) {
try {
- mActiveListeners.get(keyphraseId).onDetectionStopped();
+ oldListener.onDetectionStopped();
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onDetectionStopped");
}
@@ -159,17 +172,26 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
synchronized int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener) {
+ if (DBG) {
+ Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId
+ + ", listener=" + listener);
+ Slog.d(TAG, "# of current listeners = " + mActiveListeners.size());
+ }
+
if (moduleProperties == null || mModule == null) {
Slog.w(TAG, "Attempting stopRecognition without the capability");
return STATUS_ERROR;
}
IRecognitionStatusCallback currentListener = mActiveListeners.get(keyphraseId);
- if (currentListener == null) {
+ if (listener == null) {
+ Slog.w(TAG, "Attempting stopRecognition without a valid listener");
+ return STATUS_ERROR;
+ } if (currentListener == null) {
// startRecognition hasn't been called or it failed.
Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition");
return STATUS_ERROR;
- } else if (currentListener != listener) {
+ } else if (currentListener.asBinder() != listener.asBinder()) {
// TODO: Figure out if this should match the listener that was passed in during
// startRecognition, or should we allow a different listener to stop the recognition,
// in which case we don't need to pass in a listener here.