Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aceabbf7 authored by Nicholas Ambur's avatar Nicholas Ambur Committed by Android (Google) Code Review
Browse files

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

* changes:
  fix enrollment application permission check
  add KEYPHRASE_ENROLLMENT_APPLICATION permission
parents 68de49c9 64fb254c
Loading
Loading
Loading
Loading
+0 −21
Original line number Diff line number Diff line
@@ -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 + "]";
    }
}
+16 −3
Original line number Diff line number Diff line
@@ -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 -->
+18 −36
Original line number Diff line number Diff line
@@ -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(