diff options
author | Nicholas Ambur <nambur@google.com> | 2020-02-19 18:11:30 -0800 |
---|---|---|
committer | Nicholas Ambur <nambur@google.com> | 2020-02-25 01:20:05 +0000 |
commit | 1ec50c8f2f547df3677f3fab2ee1c39ee4209063 (patch) | |
tree | a839de82aeb8cbbca7a1ea6de18534c0da77c3e9 /services/voiceinteraction | |
parent | 56d9d677e8a0f1dedce778f1ec28a590bcc56fdb (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')
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() { |