summaryrefslogtreecommitdiff
path: root/services/voiceinteraction
diff options
context:
space:
mode:
authorNicholas Ambur <nambur@google.com>2020-02-19 18:11:30 -0800
committerNicholas Ambur <nambur@google.com>2020-02-25 01:20:05 +0000
commit1ec50c8f2f547df3677f3fab2ee1c39ee4209063 (patch)
treea839de82aeb8cbbca7a1ea6de18534c0da77c3e9 /services/voiceinteraction
parent56d9d677e8a0f1dedce778f1ec28a590bcc56fdb (diff)
remove client token passing active VI service
Previous implementation relied on client to pass a token which the service used to verify if it was the active service. This is seen to be a security concern as there is no way to verify how the client obtained the token. Instead, a check is done to confirm the caller's UID matches the UID of the active service. In the case of voice model enrollment, KeyphraseEnrollmentInfo class is leveraged. A client is allowed to enroll if it is the active voice interaction service or if it is a voice model enrollment application bundled with the system image. All previous manifest permision checks still apply. Bug: 148159858 Test: gts-tradefed run gts-dev -m GtsAssistIntentTestCases -t \ com.google.android.assist.gts.KeyphraseModelManagerTest \ \#testShouldEnrollOnlyWhenActiveService Merged-In: Ie2c4653d365770a9123a22bc69822518b4ccc568 Change-Id: Ie2c4653d365770a9123a22bc69822518b4ccc568 (cherry picked from commit c6f4118f9e86f666817bc10a5dbae51d0dabacb8)
Diffstat (limited to 'services/voiceinteraction')
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java83
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java4
2 files changed, 50 insertions, 37 deletions
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 3c0e0af67969..0b24dd2fe15a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -60,7 +60,6 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.provider.Settings;
-import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.service.voice.VoiceInteractionService;
@@ -684,9 +683,9 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public void showSession(IVoiceInteractionService service, Bundle args, int flags) {
+ public void showSession(Bundle args, int flags) {
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
final long caller = Binder.clearCallingIdentity();
try {
@@ -928,12 +927,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
//----------------- Model management APIs --------------------------------//
- // TODO: add check to only allow active voice interaction service or keyphrase enrollment
- // application to manage voice models
@Override
public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
- enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
+ enforceCallerAllowedToEnrollVoiceModel();
if (bcp47Locale == null) {
throw new IllegalArgumentException("Illegal argument(s) in getKeyphraseSoundModel");
@@ -950,7 +947,7 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public int updateKeyphraseSoundModel(KeyphraseSoundModel model) {
- enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
+ enforceCallerAllowedToEnrollVoiceModel();
if (model == null) {
throw new IllegalArgumentException("Model must not be null");
}
@@ -975,7 +972,7 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public int deleteKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
- enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
+ enforceCallerAllowedToEnrollVoiceModel();
if (bcp47Locale == null) {
throw new IllegalArgumentException(
@@ -1008,10 +1005,9 @@ public class VoiceInteractionManagerService extends SystemService {
//----------------- SoundTrigger APIs --------------------------------//
@Override
- public boolean isEnrolledForKeyphrase(IVoiceInteractionService service, int keyphraseId,
- String bcp47Locale) {
+ public boolean isEnrolledForKeyphrase(int keyphraseId, String bcp47Locale) {
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
}
if (bcp47Locale == null) {
@@ -1030,10 +1026,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Nullable
- public KeyphraseMetadata getEnrolledKeyphraseMetadata(IVoiceInteractionService service,
- String keyphrase, String bcp47Locale) {
+ public KeyphraseMetadata getEnrolledKeyphraseMetadata(String keyphrase,
+ String bcp47Locale) {
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
}
if (bcp47Locale == null) {
@@ -1065,10 +1061,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
+ public ModuleProperties getDspModuleProperties() {
// Allow the call if this is the current voice interaction service.
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
final long caller = Binder.clearCallingIdentity();
try {
@@ -1080,12 +1076,11 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public int startRecognition(IVoiceInteractionService service, int keyphraseId,
- String bcp47Locale, IRecognitionStatusCallback callback,
- RecognitionConfig recognitionConfig) {
+ public int startRecognition(int keyphraseId, String bcp47Locale,
+ IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
// Allow the call if this is the current voice interaction service.
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
if (callback == null || recognitionConfig == null || bcp47Locale == null) {
throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
@@ -1117,11 +1112,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public int stopRecognition(IVoiceInteractionService service, int keyphraseId,
- IRecognitionStatusCallback callback) {
+ public int stopRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
// Allow the call if this is the current voice interaction service.
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
}
final long caller = Binder.clearCallingIdentity();
@@ -1133,11 +1127,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public int setParameter(IVoiceInteractionService service, int keyphraseId,
- @ModelParams int modelParam, int value) {
+ public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
// Allow the call if this is the current voice interaction service.
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
}
final long caller = Binder.clearCallingIdentity();
@@ -1149,11 +1142,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public int getParameter(IVoiceInteractionService service, int keyphraseId,
- @ModelParams int modelParam) {
+ public int getParameter(int keyphraseId, @ModelParams int modelParam) {
// Allow the call if this is the current voice interaction service.
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
}
final long caller = Binder.clearCallingIdentity();
@@ -1166,11 +1158,10 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
@Nullable
- public ModelParamRange queryParameter(IVoiceInteractionService service,
- int keyphraseId, @ModelParams int modelParam) {
+ public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
// Allow the call if this is the current voice interaction service.
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
}
final long caller = Binder.clearCallingIdentity();
@@ -1400,9 +1391,9 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public void setUiHints(IVoiceInteractionService service, Bundle hints) {
+ public void setUiHints(Bundle hints) {
synchronized (this) {
- enforceIsCurrentVoiceInteractionService(service);
+ enforceIsCurrentVoiceInteractionService();
final int size = mVoiceInteractionSessionListeners.beginBroadcast();
for (int i = 0; i < size; ++i) {
@@ -1425,14 +1416,32 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
- private void enforceIsCurrentVoiceInteractionService(IVoiceInteractionService service) {
- if (mImpl == null || mImpl.mService == null
- || service.asBinder() != mImpl.mService.asBinder()) {
+ private void enforceIsCurrentVoiceInteractionService() {
+ if (!isCallerCurrentVoiceInteractionService()) {
throw new
SecurityException("Caller is not the current voice interaction service");
}
}
+ private void enforceCallerAllowedToEnrollVoiceModel() {
+ enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
+ if (!isCallerCurrentVoiceInteractionService()
+ && !isCallerTrustedEnrollmentApplication()) {
+ throw new SecurityException("Caller is required to be the current voice interaction"
+ + " service or a system enrollment application to enroll voice models");
+ }
+ }
+
+ private boolean isCallerCurrentVoiceInteractionService() {
+ return mImpl != null
+ && mImpl.mInfo.getServiceInfo().applicationInfo.uid == Binder.getCallingUid();
+ }
+
+ private boolean isCallerTrustedEnrollmentApplication() {
+ return mImpl.mEnrollmentApplicationInfo.isUidSupportedEnrollmentApplication(
+ Binder.getCallingUid());
+ }
+
private void setImplLocked(VoiceInteractionManagerServiceImpl impl) {
mImpl = impl;
mAtmInternal.notifyActiveVoiceInteractionServiceChanged(
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index a62b03ca82e4..b813f87f335f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -36,6 +36,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -78,6 +79,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
final IActivityManager mAm;
final IActivityTaskManager mAtm;
final VoiceInteractionServiceInfo mInfo;
+ final KeyphraseEnrollmentInfo mEnrollmentApplicationInfo;
final ComponentName mSessionComponentName;
final IWindowManager mIWindowManager;
boolean mBound = false;
@@ -133,6 +135,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mComponent = service;
mAm = ActivityManager.getService();
mAtm = ActivityTaskManager.getService();
+ mEnrollmentApplicationInfo = new KeyphraseEnrollmentInfo(context.getPackageManager());
VoiceInteractionServiceInfo info;
try {
info = new VoiceInteractionServiceInfo(context.getPackageManager(), service, mUser);
@@ -403,6 +406,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
pw.println(" Active session:");
mActiveSession.dump(" ", pw);
}
+ pw.println(" " + mEnrollmentApplicationInfo.toString());
}
void startLocked() {