Loading core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ package android { field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY"; field public static final String MANAGE_SMARTSPACE = "android.permission.MANAGE_SMARTSPACE"; field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER"; field public static final String MANAGE_SPEECH_RECOGNITION = "android.permission.MANAGE_SPEECH_RECOGNITION"; field public static final String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS"; field public static final String MANAGE_TEST_NETWORKS = "android.permission.MANAGE_TEST_NETWORKS"; field public static final String MANAGE_TIME_AND_ZONE_DETECTION = "android.permission.MANAGE_TIME_AND_ZONE_DETECTION"; Loading core/api/test-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -2125,6 +2125,14 @@ package android.service.watchdog { } package android.speech { public class SpeechRecognizer { method public void setTemporaryOnDeviceRecognizer(@Nullable android.content.ComponentName); } } package android.telecom { public static class Call.Details { Loading core/java/android/speech/IRecognitionServiceManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,6 @@ oneway interface IRecognitionServiceManager { in IBinder clientToken, boolean onDevice, in IRecognitionServiceManagerCallback callback); void setTemporaryComponent(in ComponentName componentName); } core/java/android/speech/SpeechRecognizer.java +94 −27 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package android.speech; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading @@ -35,6 +37,8 @@ import android.util.Log; import android.util.Slog; import java.util.List; import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; /** * This class provides access to the speech recognition service. This service allows access to the Loading @@ -52,7 +56,7 @@ import java.util.List; */ public class SpeechRecognizer { /** DEBUG value to enable verbose debug prints */ private final static boolean DBG = false; private static final boolean DBG = false; /** Log messages identifier */ private static final String TAG = "SpeechRecognizer"; Loading Loading @@ -113,10 +117,11 @@ public class SpeechRecognizer { public static final int ERROR_SERVER_DISCONNECTED = 11; /** action codes */ private final static int MSG_START = 1; private final static int MSG_STOP = 2; private final static int MSG_CANCEL = 3; private final static int MSG_CHANGE_LISTENER = 4; private static final int MSG_START = 1; private static final int MSG_STOP = 2; private static final int MSG_CANCEL = 3; private static final int MSG_CHANGE_LISTENER = 4; private static final int MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT = 5; /** The actual RecognitionService endpoint */ private IRecognitionService mService; Loading @@ -134,6 +139,7 @@ public class SpeechRecognizer { /** Handler that will execute the main tasks */ private Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { Loading @@ -149,10 +155,19 @@ public class SpeechRecognizer { case MSG_CHANGE_LISTENER: handleChangeListener((RecognitionListener) msg.obj); break; case MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT: handleSetTemporaryComponent((ComponentName) msg.obj); break; } } }; /** * Temporary queue, saving the messages until the connection will be established, afterwards, * only mHandler will receive the messages */ private final Queue<Message> mPendingTasks = new LinkedBlockingQueue<>(); /** The Listener that will receive all the callbacks */ private final InternalListener mListener = new InternalListener(); Loading Loading @@ -287,11 +302,9 @@ public class SpeechRecognizer { if (mService == null) { // First time connection: first establish a connection, then dispatch #startListening. connectToSystemService( () -> putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent))); } else { putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent)); connectToSystemService(); } putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent)); } /** Loading Loading @@ -336,6 +349,22 @@ public class SpeechRecognizer { putMessage(Message.obtain(mHandler, MSG_CANCEL)); } /** * Sets a temporary component to power on-device speech recognizer. * * <p>This is only expected to be called in tests, system would reject calls from client apps. * * @param componentName name of the component to set temporary replace speech recognizer. {@code * null} value resets the recognizer to default. * * @hide */ @TestApi public void setTemporaryOnDeviceRecognizer(@Nullable ComponentName componentName) { mHandler.sendMessage( Message.obtain(mHandler, MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT, componentName)); } private static void checkIsCalledFromMainThread() { if (Looper.myLooper() != Looper.getMainLooper()) { throw new RuntimeException( Loading @@ -344,8 +373,12 @@ public class SpeechRecognizer { } private void putMessage(Message msg) { if (mService == null) { mPendingTasks.offer(msg); } else { mHandler.sendMessage(msg); } } /** sends the actual message to the service */ private void handleStartListening(Intent recognizerIntent) { Loading Loading @@ -395,6 +428,22 @@ public class SpeechRecognizer { } } private void handleSetTemporaryComponent(ComponentName componentName) { if (DBG) { Log.d(TAG, "handleSetTemporaryComponent, componentName=" + componentName); } if (!maybeInitializeManagerService()) { return; } try { mManagerService.setTemporaryComponent(componentName); } catch (final RemoteException e) { e.rethrowFromSystemServer(); } } private boolean checkOpenConnection() { if (mService != null) { return true; Loading Loading @@ -422,16 +471,13 @@ public class SpeechRecognizer { } mService = null; mPendingTasks.clear(); mListener.mInternalListener = null; } /** Establishes a connection to system server proxy and initializes the session. */ private void connectToSystemService(Runnable onSuccess) { mManagerService = IRecognitionServiceManager.Stub.asInterface( ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE)); if (mManagerService == null) { mListener.onError(ERROR_CLIENT); private void connectToSystemService() { if (!maybeInitializeManagerService()) { return; } Loading @@ -450,13 +496,19 @@ public class SpeechRecognizer { new IRecognitionServiceManagerCallback.Stub(){ @Override public void onSuccess(IRecognitionService service) throws RemoteException { if (DBG) { Log.i(TAG, "Connected to speech recognition service"); } mService = service; onSuccess.run(); while (!mPendingTasks.isEmpty()) { mHandler.sendMessage(mPendingTasks.poll()); } } @Override public void onError(int errorCode) throws RemoteException { Log.e(TAG, "Bind to system recognition service failed"); Log.e(TAG, "Bind to system recognition service failed with error " + errorCode); mListener.onError(errorCode); } }); Loading @@ -465,6 +517,21 @@ public class SpeechRecognizer { } } private boolean maybeInitializeManagerService() { if (mManagerService != null) { return true; } mManagerService = IRecognitionServiceManager.Stub.asInterface( ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE)); if (mManagerService == null && mListener != null) { mListener.onError(ERROR_CLIENT); return false; } return true; } /** * Returns the component name to be used for establishing a connection, based on the parameters * used during initialization. Loading Loading @@ -505,15 +572,15 @@ public class SpeechRecognizer { private static class InternalListener extends IRecognitionListener.Stub { private RecognitionListener mInternalListener; private final static int MSG_BEGINNING_OF_SPEECH = 1; private final static int MSG_BUFFER_RECEIVED = 2; private final static int MSG_END_OF_SPEECH = 3; private final static int MSG_ERROR = 4; private final static int MSG_READY_FOR_SPEECH = 5; private final static int MSG_RESULTS = 6; private final static int MSG_PARTIAL_RESULTS = 7; private final static int MSG_RMS_CHANGED = 8; private final static int MSG_ON_EVENT = 9; private static final int MSG_BEGINNING_OF_SPEECH = 1; private static final int MSG_BUFFER_RECEIVED = 2; private static final int MSG_END_OF_SPEECH = 3; private static final int MSG_ERROR = 4; private static final int MSG_READY_FOR_SPEECH = 5; private static final int MSG_RESULTS = 6; private static final int MSG_PARTIAL_RESULTS = 7; private static final int MSG_RMS_CHANGED = 8; private static final int MSG_ON_EVENT = 9; private final Handler mInternalHandler = new Handler(Looper.getMainLooper()) { @Override Loading core/res/AndroidManifest.xml +7 −2 Original line number Diff line number Diff line Loading @@ -5259,6 +5259,11 @@ <permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to manage speech recognition service. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.MANAGE_SPEECH_RECOGNITION" android:protectionLevel="signature" /> <!-- @SystemApi Allows an application to manage the content suggestions service. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" Loading Loading
core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ package android { field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY"; field public static final String MANAGE_SMARTSPACE = "android.permission.MANAGE_SMARTSPACE"; field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER"; field public static final String MANAGE_SPEECH_RECOGNITION = "android.permission.MANAGE_SPEECH_RECOGNITION"; field public static final String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS"; field public static final String MANAGE_TEST_NETWORKS = "android.permission.MANAGE_TEST_NETWORKS"; field public static final String MANAGE_TIME_AND_ZONE_DETECTION = "android.permission.MANAGE_TIME_AND_ZONE_DETECTION"; Loading
core/api/test-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -2125,6 +2125,14 @@ package android.service.watchdog { } package android.speech { public class SpeechRecognizer { method public void setTemporaryOnDeviceRecognizer(@Nullable android.content.ComponentName); } } package android.telecom { public static class Call.Details { Loading
core/java/android/speech/IRecognitionServiceManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,6 @@ oneway interface IRecognitionServiceManager { in IBinder clientToken, boolean onDevice, in IRecognitionServiceManagerCallback callback); void setTemporaryComponent(in ComponentName componentName); }
core/java/android/speech/SpeechRecognizer.java +94 −27 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package android.speech; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading @@ -35,6 +37,8 @@ import android.util.Log; import android.util.Slog; import java.util.List; import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; /** * This class provides access to the speech recognition service. This service allows access to the Loading @@ -52,7 +56,7 @@ import java.util.List; */ public class SpeechRecognizer { /** DEBUG value to enable verbose debug prints */ private final static boolean DBG = false; private static final boolean DBG = false; /** Log messages identifier */ private static final String TAG = "SpeechRecognizer"; Loading Loading @@ -113,10 +117,11 @@ public class SpeechRecognizer { public static final int ERROR_SERVER_DISCONNECTED = 11; /** action codes */ private final static int MSG_START = 1; private final static int MSG_STOP = 2; private final static int MSG_CANCEL = 3; private final static int MSG_CHANGE_LISTENER = 4; private static final int MSG_START = 1; private static final int MSG_STOP = 2; private static final int MSG_CANCEL = 3; private static final int MSG_CHANGE_LISTENER = 4; private static final int MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT = 5; /** The actual RecognitionService endpoint */ private IRecognitionService mService; Loading @@ -134,6 +139,7 @@ public class SpeechRecognizer { /** Handler that will execute the main tasks */ private Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { Loading @@ -149,10 +155,19 @@ public class SpeechRecognizer { case MSG_CHANGE_LISTENER: handleChangeListener((RecognitionListener) msg.obj); break; case MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT: handleSetTemporaryComponent((ComponentName) msg.obj); break; } } }; /** * Temporary queue, saving the messages until the connection will be established, afterwards, * only mHandler will receive the messages */ private final Queue<Message> mPendingTasks = new LinkedBlockingQueue<>(); /** The Listener that will receive all the callbacks */ private final InternalListener mListener = new InternalListener(); Loading Loading @@ -287,11 +302,9 @@ public class SpeechRecognizer { if (mService == null) { // First time connection: first establish a connection, then dispatch #startListening. connectToSystemService( () -> putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent))); } else { putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent)); connectToSystemService(); } putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent)); } /** Loading Loading @@ -336,6 +349,22 @@ public class SpeechRecognizer { putMessage(Message.obtain(mHandler, MSG_CANCEL)); } /** * Sets a temporary component to power on-device speech recognizer. * * <p>This is only expected to be called in tests, system would reject calls from client apps. * * @param componentName name of the component to set temporary replace speech recognizer. {@code * null} value resets the recognizer to default. * * @hide */ @TestApi public void setTemporaryOnDeviceRecognizer(@Nullable ComponentName componentName) { mHandler.sendMessage( Message.obtain(mHandler, MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT, componentName)); } private static void checkIsCalledFromMainThread() { if (Looper.myLooper() != Looper.getMainLooper()) { throw new RuntimeException( Loading @@ -344,8 +373,12 @@ public class SpeechRecognizer { } private void putMessage(Message msg) { if (mService == null) { mPendingTasks.offer(msg); } else { mHandler.sendMessage(msg); } } /** sends the actual message to the service */ private void handleStartListening(Intent recognizerIntent) { Loading Loading @@ -395,6 +428,22 @@ public class SpeechRecognizer { } } private void handleSetTemporaryComponent(ComponentName componentName) { if (DBG) { Log.d(TAG, "handleSetTemporaryComponent, componentName=" + componentName); } if (!maybeInitializeManagerService()) { return; } try { mManagerService.setTemporaryComponent(componentName); } catch (final RemoteException e) { e.rethrowFromSystemServer(); } } private boolean checkOpenConnection() { if (mService != null) { return true; Loading Loading @@ -422,16 +471,13 @@ public class SpeechRecognizer { } mService = null; mPendingTasks.clear(); mListener.mInternalListener = null; } /** Establishes a connection to system server proxy and initializes the session. */ private void connectToSystemService(Runnable onSuccess) { mManagerService = IRecognitionServiceManager.Stub.asInterface( ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE)); if (mManagerService == null) { mListener.onError(ERROR_CLIENT); private void connectToSystemService() { if (!maybeInitializeManagerService()) { return; } Loading @@ -450,13 +496,19 @@ public class SpeechRecognizer { new IRecognitionServiceManagerCallback.Stub(){ @Override public void onSuccess(IRecognitionService service) throws RemoteException { if (DBG) { Log.i(TAG, "Connected to speech recognition service"); } mService = service; onSuccess.run(); while (!mPendingTasks.isEmpty()) { mHandler.sendMessage(mPendingTasks.poll()); } } @Override public void onError(int errorCode) throws RemoteException { Log.e(TAG, "Bind to system recognition service failed"); Log.e(TAG, "Bind to system recognition service failed with error " + errorCode); mListener.onError(errorCode); } }); Loading @@ -465,6 +517,21 @@ public class SpeechRecognizer { } } private boolean maybeInitializeManagerService() { if (mManagerService != null) { return true; } mManagerService = IRecognitionServiceManager.Stub.asInterface( ServiceManager.getService(Context.SPEECH_RECOGNITION_SERVICE)); if (mManagerService == null && mListener != null) { mListener.onError(ERROR_CLIENT); return false; } return true; } /** * Returns the component name to be used for establishing a connection, based on the parameters * used during initialization. Loading Loading @@ -505,15 +572,15 @@ public class SpeechRecognizer { private static class InternalListener extends IRecognitionListener.Stub { private RecognitionListener mInternalListener; private final static int MSG_BEGINNING_OF_SPEECH = 1; private final static int MSG_BUFFER_RECEIVED = 2; private final static int MSG_END_OF_SPEECH = 3; private final static int MSG_ERROR = 4; private final static int MSG_READY_FOR_SPEECH = 5; private final static int MSG_RESULTS = 6; private final static int MSG_PARTIAL_RESULTS = 7; private final static int MSG_RMS_CHANGED = 8; private final static int MSG_ON_EVENT = 9; private static final int MSG_BEGINNING_OF_SPEECH = 1; private static final int MSG_BUFFER_RECEIVED = 2; private static final int MSG_END_OF_SPEECH = 3; private static final int MSG_ERROR = 4; private static final int MSG_READY_FOR_SPEECH = 5; private static final int MSG_RESULTS = 6; private static final int MSG_PARTIAL_RESULTS = 7; private static final int MSG_RMS_CHANGED = 8; private static final int MSG_ON_EVENT = 9; private final Handler mInternalHandler = new Handler(Looper.getMainLooper()) { @Override Loading
core/res/AndroidManifest.xml +7 −2 Original line number Diff line number Diff line Loading @@ -5259,6 +5259,11 @@ <permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to manage speech recognition service. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.MANAGE_SPEECH_RECOGNITION" android:protectionLevel="signature" /> <!-- @SystemApi Allows an application to manage the content suggestions service. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" Loading