Loading core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java +0 −21 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; /** * Enrollment information about the different available keyphrases. Loading Loading @@ -119,11 +118,6 @@ public class KeyphraseEnrollmentInfo { */ private final KeyphraseMetadata[] mKeyphrases; /** * Set of UIDs associated with the detected enrollment applications. */ private final Set<Integer> mEnrollmentApplicationUids; /** * Map between KeyphraseMetadata and the package name of the enrollment app that provides it. */ Loading @@ -142,13 +136,11 @@ public class KeyphraseEnrollmentInfo { mParseError = "No enrollment applications found"; mKeyphrasePackageMap = Collections.<KeyphraseMetadata, String>emptyMap(); mKeyphrases = null; mEnrollmentApplicationUids = Collections.emptySet(); return; } List<String> parseErrors = new LinkedList<String>(); mKeyphrasePackageMap = new HashMap<KeyphraseMetadata, String>(); mEnrollmentApplicationUids = new ArraySet<>(); for (ResolveInfo ri : ris) { try { ApplicationInfo ai = pm.getApplicationInfo( Loading @@ -170,7 +162,6 @@ public class KeyphraseEnrollmentInfo { getKeyphraseMetadataFromApplicationInfo(pm, ai, parseErrors); if (metadata != null) { mKeyphrasePackageMap.put(metadata, ai.packageName); mEnrollmentApplicationUids.add(ai.uid); } } catch (PackageManager.NameNotFoundException e) { String error = "error parsing voice enrollment meta-data for " Loading Loading @@ -373,21 +364,9 @@ public class KeyphraseEnrollmentInfo { return null; } /** * Tests if the input UID matches a supported enrollment application. * * @param uid UID of the caller to test against. * @return Returns true if input uid matches the uid of a supported enrollment application. * False if not. */ public boolean isUidSupportedEnrollmentApplication(int uid) { return mEnrollmentApplicationUids.contains(uid); } @Override public String toString() { return "KeyphraseEnrollmentInfo [KeyphrasePackageMap=" + mKeyphrasePackageMap.toString() + ", enrollmentApplicationUids=" + mEnrollmentApplicationUids.toString() + ", ParseError=" + mParseError + "]"; } } core/res/AndroidManifest.xml +16 −3 Original line number Diff line number Diff line Loading @@ -3447,12 +3447,25 @@ <permission android:name="android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE" android:protectionLevel="signature" /> <!-- Must be required by hotword enrollment application, to ensure that only the system can interact with it. @hide <p>Not for use by third-party applications.</p> --> <!-- Must be required by a {@link android.service.voice.VoiceInteractionService} implementation to enroll its own sound models. This is a more restrictive permission than the higher-level permission KEYPHRASE_ENROLLMENT_APPLICATION. For the caller to enroll sound models with this permission, it must hold the permission and be the active VoiceInteractionService in the system. {@see Settings.Secure.VOICE_INTERACTION_SERVICE} @hide --> <permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES" android:protectionLevel="signature|privileged" /> <!-- Must be required by a keyphrase enrollment application, to enroll sound models. This is treated as a higher-level permission to MANAGE_VOICE_KEYPHRASES as a caller can enroll sound models at any time. This permission should be reserved for system enrollment applications detected by {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo} only. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.KEYPHRASE_ENROLLMENT_APPLICATION" android:protectionLevel="signature|privileged" /> <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider}, to ensure that only the system can bind to it. @hide --> Loading services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +18 −36 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.soundtrigger.IRecognitionStatusCallback; import android.hardware.soundtrigger.KeyphraseEnrollmentInfo; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.ModelParams; import android.hardware.soundtrigger.SoundTrigger; Loading Loading @@ -100,7 +99,7 @@ import java.util.concurrent.Executor; * SystemService that publishes an IVoiceInteractionManagerService. */ public class VoiceInteractionManagerService extends SystemService { static final String TAG = "VoiceInteractionManagerService"; static final String TAG = "VoiceInteractionManager"; static final boolean DEBUG = false; final Context mContext; Loading Loading @@ -172,17 +171,17 @@ public class VoiceInteractionManagerService extends SystemService { } @Override public void onStartUser(@NonNull UserInfo userInfo) { if (DEBUG_USER) Slog.d(TAG, "onStartUser(" + userInfo + ")"); public void onUserStarting(@NonNull TargetUser user) { if (DEBUG_USER) Slog.d(TAG, "onUserStarting(" + user + ")"); mServiceStub.initForUser(userInfo.id); mServiceStub.initForUser(user.getUserIdentifier()); } @Override public void onUnlockUser(@NonNull UserInfo userInfo) { if (DEBUG_USER) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); public void onUserUnlocking(@NonNull TargetUser user) { if (DEBUG_USER) Slog.d(TAG, "onUserUnlocking(" + user + ")"); mServiceStub.initForUser(userInfo.id); mServiceStub.initForUser(user.getUserIdentifier()); mServiceStub.switchImplementationIfNeeded(false); } Loading Loading @@ -224,7 +223,6 @@ public class VoiceInteractionManagerService extends SystemService { class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub { VoiceInteractionManagerServiceImpl mImpl; KeyphraseEnrollmentInfo mEnrollmentApplicationInfo; private boolean mSafeMode; private int mCurUser; Loading Loading @@ -449,15 +447,6 @@ public class VoiceInteractionManagerService extends SystemService { } } private void getOrCreateEnrollmentApplicationInfo() { synchronized (this) { if (mEnrollmentApplicationInfo == null) { mEnrollmentApplicationInfo = new KeyphraseEnrollmentInfo( mContext.getPackageManager()); } } } private void setCurrentUserLocked(@UserIdInt int userHandle) { mCurUser = userHandle; final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser); Loading Loading @@ -1391,11 +1380,6 @@ public class VoiceInteractionManagerService extends SystemService { pw.println(" mCurUserUnlocked: " + mCurUserUnlocked); pw.println(" mCurUserSupported: " + mCurUserSupported); dumpSupportedUsers(pw, " "); if (mEnrollmentApplicationInfo == null) { pw.println(" (No enrollment application info)"); } else { pw.println(" " + mEnrollmentApplicationInfo.toString()); } mDbHelper.dump(pw); if (mImpl == null) { pw.println(" (No active implementation)"); Loading Loading @@ -1425,9 +1409,13 @@ public class VoiceInteractionManagerService extends SystemService { } } private boolean isCallerHoldingPermission(String permission) { return mContext.checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; } private void enforceCallingPermission(String permission) { if (mContext.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { if (!isCallerHoldingPermission(permission)) { throw new SecurityException("Caller does not hold the permission " + permission); } } Loading @@ -1440,12 +1428,12 @@ public class VoiceInteractionManagerService extends SystemService { } 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"); if (isCallerHoldingPermission(Manifest.permission.KEYPHRASE_ENROLLMENT_APPLICATION)) { return; } enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES); enforceIsCurrentVoiceInteractionService(); } private boolean isCallerCurrentVoiceInteractionService() { Loading @@ -1453,12 +1441,6 @@ public class VoiceInteractionManagerService extends SystemService { && mImpl.mInfo.getServiceInfo().applicationInfo.uid == Binder.getCallingUid(); } private boolean isCallerTrustedEnrollmentApplication() { getOrCreateEnrollmentApplicationInfo(); return mEnrollmentApplicationInfo.isUidSupportedEnrollmentApplication( Binder.getCallingUid()); } private void setImplLocked(VoiceInteractionManagerServiceImpl impl) { mImpl = impl; mAtmInternal.notifyActiveVoiceInteractionServiceChanged( Loading Loading
core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java +0 −21 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; /** * Enrollment information about the different available keyphrases. Loading Loading @@ -119,11 +118,6 @@ public class KeyphraseEnrollmentInfo { */ private final KeyphraseMetadata[] mKeyphrases; /** * Set of UIDs associated with the detected enrollment applications. */ private final Set<Integer> mEnrollmentApplicationUids; /** * Map between KeyphraseMetadata and the package name of the enrollment app that provides it. */ Loading @@ -142,13 +136,11 @@ public class KeyphraseEnrollmentInfo { mParseError = "No enrollment applications found"; mKeyphrasePackageMap = Collections.<KeyphraseMetadata, String>emptyMap(); mKeyphrases = null; mEnrollmentApplicationUids = Collections.emptySet(); return; } List<String> parseErrors = new LinkedList<String>(); mKeyphrasePackageMap = new HashMap<KeyphraseMetadata, String>(); mEnrollmentApplicationUids = new ArraySet<>(); for (ResolveInfo ri : ris) { try { ApplicationInfo ai = pm.getApplicationInfo( Loading @@ -170,7 +162,6 @@ public class KeyphraseEnrollmentInfo { getKeyphraseMetadataFromApplicationInfo(pm, ai, parseErrors); if (metadata != null) { mKeyphrasePackageMap.put(metadata, ai.packageName); mEnrollmentApplicationUids.add(ai.uid); } } catch (PackageManager.NameNotFoundException e) { String error = "error parsing voice enrollment meta-data for " Loading Loading @@ -373,21 +364,9 @@ public class KeyphraseEnrollmentInfo { return null; } /** * Tests if the input UID matches a supported enrollment application. * * @param uid UID of the caller to test against. * @return Returns true if input uid matches the uid of a supported enrollment application. * False if not. */ public boolean isUidSupportedEnrollmentApplication(int uid) { return mEnrollmentApplicationUids.contains(uid); } @Override public String toString() { return "KeyphraseEnrollmentInfo [KeyphrasePackageMap=" + mKeyphrasePackageMap.toString() + ", enrollmentApplicationUids=" + mEnrollmentApplicationUids.toString() + ", ParseError=" + mParseError + "]"; } }
core/res/AndroidManifest.xml +16 −3 Original line number Diff line number Diff line Loading @@ -3447,12 +3447,25 @@ <permission android:name="android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE" android:protectionLevel="signature" /> <!-- Must be required by hotword enrollment application, to ensure that only the system can interact with it. @hide <p>Not for use by third-party applications.</p> --> <!-- Must be required by a {@link android.service.voice.VoiceInteractionService} implementation to enroll its own sound models. This is a more restrictive permission than the higher-level permission KEYPHRASE_ENROLLMENT_APPLICATION. For the caller to enroll sound models with this permission, it must hold the permission and be the active VoiceInteractionService in the system. {@see Settings.Secure.VOICE_INTERACTION_SERVICE} @hide --> <permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES" android:protectionLevel="signature|privileged" /> <!-- Must be required by a keyphrase enrollment application, to enroll sound models. This is treated as a higher-level permission to MANAGE_VOICE_KEYPHRASES as a caller can enroll sound models at any time. This permission should be reserved for system enrollment applications detected by {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo} only. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.KEYPHRASE_ENROLLMENT_APPLICATION" android:protectionLevel="signature|privileged" /> <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider}, to ensure that only the system can bind to it. @hide --> Loading
services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +18 −36 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.soundtrigger.IRecognitionStatusCallback; import android.hardware.soundtrigger.KeyphraseEnrollmentInfo; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.ModelParams; import android.hardware.soundtrigger.SoundTrigger; Loading Loading @@ -100,7 +99,7 @@ import java.util.concurrent.Executor; * SystemService that publishes an IVoiceInteractionManagerService. */ public class VoiceInteractionManagerService extends SystemService { static final String TAG = "VoiceInteractionManagerService"; static final String TAG = "VoiceInteractionManager"; static final boolean DEBUG = false; final Context mContext; Loading Loading @@ -172,17 +171,17 @@ public class VoiceInteractionManagerService extends SystemService { } @Override public void onStartUser(@NonNull UserInfo userInfo) { if (DEBUG_USER) Slog.d(TAG, "onStartUser(" + userInfo + ")"); public void onUserStarting(@NonNull TargetUser user) { if (DEBUG_USER) Slog.d(TAG, "onUserStarting(" + user + ")"); mServiceStub.initForUser(userInfo.id); mServiceStub.initForUser(user.getUserIdentifier()); } @Override public void onUnlockUser(@NonNull UserInfo userInfo) { if (DEBUG_USER) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); public void onUserUnlocking(@NonNull TargetUser user) { if (DEBUG_USER) Slog.d(TAG, "onUserUnlocking(" + user + ")"); mServiceStub.initForUser(userInfo.id); mServiceStub.initForUser(user.getUserIdentifier()); mServiceStub.switchImplementationIfNeeded(false); } Loading Loading @@ -224,7 +223,6 @@ public class VoiceInteractionManagerService extends SystemService { class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub { VoiceInteractionManagerServiceImpl mImpl; KeyphraseEnrollmentInfo mEnrollmentApplicationInfo; private boolean mSafeMode; private int mCurUser; Loading Loading @@ -449,15 +447,6 @@ public class VoiceInteractionManagerService extends SystemService { } } private void getOrCreateEnrollmentApplicationInfo() { synchronized (this) { if (mEnrollmentApplicationInfo == null) { mEnrollmentApplicationInfo = new KeyphraseEnrollmentInfo( mContext.getPackageManager()); } } } private void setCurrentUserLocked(@UserIdInt int userHandle) { mCurUser = userHandle; final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser); Loading Loading @@ -1391,11 +1380,6 @@ public class VoiceInteractionManagerService extends SystemService { pw.println(" mCurUserUnlocked: " + mCurUserUnlocked); pw.println(" mCurUserSupported: " + mCurUserSupported); dumpSupportedUsers(pw, " "); if (mEnrollmentApplicationInfo == null) { pw.println(" (No enrollment application info)"); } else { pw.println(" " + mEnrollmentApplicationInfo.toString()); } mDbHelper.dump(pw); if (mImpl == null) { pw.println(" (No active implementation)"); Loading Loading @@ -1425,9 +1409,13 @@ public class VoiceInteractionManagerService extends SystemService { } } private boolean isCallerHoldingPermission(String permission) { return mContext.checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; } private void enforceCallingPermission(String permission) { if (mContext.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { if (!isCallerHoldingPermission(permission)) { throw new SecurityException("Caller does not hold the permission " + permission); } } Loading @@ -1440,12 +1428,12 @@ public class VoiceInteractionManagerService extends SystemService { } 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"); if (isCallerHoldingPermission(Manifest.permission.KEYPHRASE_ENROLLMENT_APPLICATION)) { return; } enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES); enforceIsCurrentVoiceInteractionService(); } private boolean isCallerCurrentVoiceInteractionService() { Loading @@ -1453,12 +1441,6 @@ public class VoiceInteractionManagerService extends SystemService { && mImpl.mInfo.getServiceInfo().applicationInfo.uid == Binder.getCallingUid(); } private boolean isCallerTrustedEnrollmentApplication() { getOrCreateEnrollmentApplicationInfo(); return mEnrollmentApplicationInfo.isUidSupportedEnrollmentApplication( Binder.getCallingUid()); } private void setImplLocked(VoiceInteractionManagerServiceImpl impl) { mImpl = impl; mAtmInternal.notifyActiveVoiceInteractionServiceChanged( Loading