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:
committed by
Android (Google) Code Review
commit
aceabbf758
@@ -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 + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user