Loading services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java +14 −4 Original line number Diff line number Diff line Loading @@ -68,12 +68,14 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn private final ComponentName mComponentName; RemoteSpeechRecognitionService( Context context, ComponentName serviceName, int userId, int callingUid) { Context context, ComponentName serviceName, int userId, int callingUid, boolean isPrivileged) { super(context, new Intent(RecognitionService.SERVICE_INTERFACE).setComponent(serviceName), Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | Context.BIND_INCLUDE_CAPABILITIES, getBindingFlags(isPrivileged), userId, IRecognitionService.Stub::asInterface); Loading @@ -85,6 +87,14 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn } } private static int getBindingFlags(boolean isPrivileged) { int bindingFlags = Context.BIND_AUTO_CREATE; if (isPrivileged) { bindingFlags |= Context.BIND_INCLUDE_CAPABILITIES | Context.BIND_FOREGROUND_SERVICE; } return bindingFlags; } ComponentName getServiceComponentName() { return mComponentName; } Loading services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java +63 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.app.AppGlobals; import android.content.AttributionSource; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; Loading @@ -31,6 +32,7 @@ import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.permission.PermissionManager; import android.provider.Settings; import android.speech.IModelDownloadListener; import android.speech.IRecognitionListener; import android.speech.IRecognitionService; Loading Loading @@ -311,9 +313,22 @@ final class SpeechRecognitionManagerServiceImpl extends return null; } final boolean isPrivileged; if (serviceComponent == null) { isPrivileged = false; } else { // Only certain privileged recognition service can obtain process capabilities // from persistent process to hold while-in-use permission in the background. isPrivileged = checkPrivilege(serviceComponent); } RemoteSpeechRecognitionService service = new RemoteSpeechRecognitionService( getContext(), serviceComponent, getUserId(), callingUid); getContext(), serviceComponent, getUserId(), callingUid, isPrivileged); Set<RemoteSpeechRecognitionService> valuesByCaller = mRemoteServicesByUid.computeIfAbsent(callingUid, key -> new HashSet<>()); Loading @@ -328,6 +343,53 @@ final class SpeechRecognitionManagerServiceImpl extends } } /** * Checks if the given service component should have privileged binding flags when created. Only * a service component that matches with any of the following condition would be granted: * * <ul> * <li>A default recognition service component.</li> * <li>An on-device recognition service component.</li> * <li>A pre-installed recognition service component.</li> * </ul> */ @GuardedBy("mLock") private boolean checkPrivilege(@NonNull ComponentName serviceComponent) { final ComponentName defaultComponent = getDefaultRecognitionServiceComponent(); final ComponentName onDeviceComponent = getOnDeviceComponentNameLocked(); final boolean preinstalled = isPreinstalledApp(serviceComponent); return serviceComponent.equals(defaultComponent) || serviceComponent.equals(onDeviceComponent) || preinstalled; } private boolean isPreinstalledApp(@NonNull ComponentName serviceComponent) { PackageManager pm = getContext().getPackageManager(); if (pm == null) { return false; } try { ApplicationInfo info = pm.getApplicationInfoAsUser(serviceComponent.getPackageName(), PackageManager.MATCH_SYSTEM_ONLY, getUserId()); return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } catch (PackageManager.NameNotFoundException e) { return false; } } @Nullable private ComponentName getDefaultRecognitionServiceComponent() { String componentName = Settings.Secure.getStringForUser( getContext().getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE, getUserId()); if (componentName == null) { return null; } return ComponentName.unflattenFromString(componentName); } private boolean componentMapsToRecognitionService(@NonNull ComponentName serviceComponent) { List<ResolveInfo> resolveInfos; Loading Loading
services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java +14 −4 Original line number Diff line number Diff line Loading @@ -68,12 +68,14 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn private final ComponentName mComponentName; RemoteSpeechRecognitionService( Context context, ComponentName serviceName, int userId, int callingUid) { Context context, ComponentName serviceName, int userId, int callingUid, boolean isPrivileged) { super(context, new Intent(RecognitionService.SERVICE_INTERFACE).setComponent(serviceName), Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | Context.BIND_INCLUDE_CAPABILITIES, getBindingFlags(isPrivileged), userId, IRecognitionService.Stub::asInterface); Loading @@ -85,6 +87,14 @@ final class RemoteSpeechRecognitionService extends ServiceConnector.Impl<IRecogn } } private static int getBindingFlags(boolean isPrivileged) { int bindingFlags = Context.BIND_AUTO_CREATE; if (isPrivileged) { bindingFlags |= Context.BIND_INCLUDE_CAPABILITIES | Context.BIND_FOREGROUND_SERVICE; } return bindingFlags; } ComponentName getServiceComponentName() { return mComponentName; } Loading
services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java +63 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.app.AppGlobals; import android.content.AttributionSource; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; Loading @@ -31,6 +32,7 @@ import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.permission.PermissionManager; import android.provider.Settings; import android.speech.IModelDownloadListener; import android.speech.IRecognitionListener; import android.speech.IRecognitionService; Loading Loading @@ -311,9 +313,22 @@ final class SpeechRecognitionManagerServiceImpl extends return null; } final boolean isPrivileged; if (serviceComponent == null) { isPrivileged = false; } else { // Only certain privileged recognition service can obtain process capabilities // from persistent process to hold while-in-use permission in the background. isPrivileged = checkPrivilege(serviceComponent); } RemoteSpeechRecognitionService service = new RemoteSpeechRecognitionService( getContext(), serviceComponent, getUserId(), callingUid); getContext(), serviceComponent, getUserId(), callingUid, isPrivileged); Set<RemoteSpeechRecognitionService> valuesByCaller = mRemoteServicesByUid.computeIfAbsent(callingUid, key -> new HashSet<>()); Loading @@ -328,6 +343,53 @@ final class SpeechRecognitionManagerServiceImpl extends } } /** * Checks if the given service component should have privileged binding flags when created. Only * a service component that matches with any of the following condition would be granted: * * <ul> * <li>A default recognition service component.</li> * <li>An on-device recognition service component.</li> * <li>A pre-installed recognition service component.</li> * </ul> */ @GuardedBy("mLock") private boolean checkPrivilege(@NonNull ComponentName serviceComponent) { final ComponentName defaultComponent = getDefaultRecognitionServiceComponent(); final ComponentName onDeviceComponent = getOnDeviceComponentNameLocked(); final boolean preinstalled = isPreinstalledApp(serviceComponent); return serviceComponent.equals(defaultComponent) || serviceComponent.equals(onDeviceComponent) || preinstalled; } private boolean isPreinstalledApp(@NonNull ComponentName serviceComponent) { PackageManager pm = getContext().getPackageManager(); if (pm == null) { return false; } try { ApplicationInfo info = pm.getApplicationInfoAsUser(serviceComponent.getPackageName(), PackageManager.MATCH_SYSTEM_ONLY, getUserId()); return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } catch (PackageManager.NameNotFoundException e) { return false; } } @Nullable private ComponentName getDefaultRecognitionServiceComponent() { String componentName = Settings.Secure.getStringForUser( getContext().getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE, getUserId()); if (componentName == null) { return null; } return ComponentName.unflattenFromString(componentName); } private boolean componentMapsToRecognitionService(@NonNull ComponentName serviceComponent) { List<ResolveInfo> resolveInfos; Loading