Merge changes from topic "enrollment-app-permission" into rvc-dev

* changes:
  fix enrollment application permission check
  add KEYPHRASE_ENROLLMENT_APPLICATION permission
This commit is contained in:
Nicholas Ambur
2020-03-21 00:39:35 +00:00
committed by Android (Google) Code Review
3 changed files with 34 additions and 60 deletions

View File

@@ -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.
@@ -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.
*/
@@ -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(
@@ -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 "
@@ -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 + "]";
}
}

View File

@@ -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 -->

View File

@@ -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;
@@ -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;
@@ -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);
}
@@ -224,7 +223,6 @@ public class VoiceInteractionManagerService extends SystemService {
class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {
VoiceInteractionManagerServiceImpl mImpl;
KeyphraseEnrollmentInfo mEnrollmentApplicationInfo;
private boolean mSafeMode;
private int mCurUser;
@@ -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);
@@ -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)");
@@ -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);
}
}
@@ -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() {
@@ -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(