Loading core/java/android/speech/hotword/HotwordRecognitionService.java +4 −27 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.SdkConstant.SdkConstantType; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -113,8 +112,9 @@ public abstract class HotwordRecognitionService extends Service { listener.onHotwordError(HotwordRecognizer.ERROR_RECOGNIZER_BUSY); Log.w(TAG, "stopRecognition called by a different caller - ignoring"); } else { // the correct state HotwordRecognitionService.this.onStopHotwordRecognition(mCurrentCallback); mCurrentCallback.onHotwordRecognitionStopped(); mCurrentCallback = null; HotwordRecognitionService.this.onStopHotwordRecognition(); } } catch (RemoteException e) { // occurs if onError fails if (DBG) Log.d(TAG, "onError call from stopRecognition failed"); Loading @@ -138,27 +138,6 @@ public abstract class HotwordRecognitionService extends Service { super.onDestroy(); } /** * Checks whether the caller has sufficient permissions * * @param listener to send the error message to in case of error * @return {@code true} if the caller has enough permissions, {@code false} otherwise */ private boolean checkPermissions(IHotwordRecognitionListener listener) { if (DBG) Log.d(TAG, "checkPermissions"); if (checkCallingOrSelfPermission( android.Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) { return true; } try { Log.e(TAG, "Recognition service called without RECORD_AUDIO permissions"); listener.onHotwordError(HotwordRecognizer.ERROR_FAILED); } catch (RemoteException e) { Log.e(TAG, "onHotwordError(ERROR_INSUFFICIENT_PERMISSIONS) message failed", e); } return false; } /** * Notifies the service to start a recognition. * Loading @@ -168,10 +147,8 @@ public abstract class HotwordRecognitionService extends Service { /** * Notifies the service to stop recognition. * * @param callback that receives the callbacks from the service. */ public abstract void onStopHotwordRecognition(Callback callback); public abstract void onStopHotwordRecognition(); /** Binder of the hotword recognition service */ private static class RecognitionServiceBinder extends IHotwordRecognitionService.Stub { Loading @@ -183,7 +160,7 @@ public abstract class HotwordRecognitionService extends Service { public void startHotwordRecognition(IHotwordRecognitionListener listener) { if (DBG) Log.d(TAG, "startRecognition called by: " + listener.asBinder()); if (mInternalService != null && mInternalService.checkPermissions(listener)) { if (mInternalService != null) { mInternalService.mHandler.sendMessage( Message.obtain(mInternalService.mHandler, MSG_START_RECOGNITION, listener)); } Loading core/java/android/speech/hotword/HotwordRecognizer.java +46 −62 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -82,7 +84,6 @@ public class HotwordRecognizer { /** action codes */ private static final int MSG_START = 1; private static final int MSG_STOP = 2; private final static int MSG_CHANGE_LISTENER = 3; /** The underlying HotwordRecognitionService endpoint */ private IHotwordRecognitionService mService; Loading @@ -107,9 +108,6 @@ public class HotwordRecognizer { case MSG_STOP: handleStopRecognition(); break; case MSG_CHANGE_LISTENER: handleChangeListener((HotwordRecognitionListener) msg.obj); break; } } }; Loading Loading @@ -138,24 +136,38 @@ public class HotwordRecognizer { } /** * Factory method to create a new {@code HotwordRecognizer}. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} * should be called before dispatching any command to the created {@code HotwordRecognizer}, * otherwise no notifications will be received. * Factory method to create a new {@code HotwordRecognizer}. * * @param context in which to create {@code HotwordRecognizer} * @return a new {@code HotwordRecognizer} */ public static HotwordRecognizer createHotwordRecognizer(final Context context) { return createHotwordRecognizer(context, null); ComponentName serviceComponent = null; // Resolve to a default ComponentName. final List<ResolveInfo> list = context.getPackageManager().queryIntentServices( new Intent(HotwordRecognitionService.SERVICE_INTERFACE), 0); for (int i = 0; i < list.size(); i++) { final ResolveInfo ri = list.get(i); if (!ri.serviceInfo.enabled) { continue; } if ((ri.serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != PackageManager.MATCH_DEFAULT_ONLY) { serviceComponent = new ComponentName( ri.serviceInfo.packageName, ri.serviceInfo.name); break; } } // If all else fails, pick the first one. if (serviceComponent == null && !list.isEmpty()) { serviceComponent = new ComponentName( list.get(0).serviceInfo.packageName, list.get(0).serviceInfo.name); } return createHotwordRecognizer(context, serviceComponent); } /** * Factory method to create a new {@code HotwordRecognizer}. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} * should be called before dispatching any command to the created {@code HotwordRecognizer}, * otherwise no notifications will be received. * Factory method to create a new {@code HotwordRecognizer}. * * Use this version of the method to specify a specific service to direct this * {@link HotwordRecognizer} to. Normally you would not use this; use Loading @@ -177,40 +189,26 @@ public class HotwordRecognizer { } /** * Sets the listener that will receive all the callbacks. The previous unfinished commands will * be executed with the old listener, while any following command will be executed with the new * listener. * Starts recognizing hotword and sets the listener that will receive the callbacks. * * @param listener listener that will receive all the callbacks from the created * {@link HotwordRecognizer}, this must not be null. */ public void setRecognitionListener(HotwordRecognitionListener listener) { public void startRecognition(HotwordRecognitionListener listener) { checkIsCalledFromMainThread(); putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener)); if (mConnection == null) { // first time connection if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } /** * Starts recognizing hotword. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} should be called beforehand, * otherwise no notifications will be received. */ public void startRecognition() { checkIsCalledFromMainThread(); if (mConnection == null) { // first time connection mConnection = new Connection(); Intent serviceIntent = new Intent(HotwordRecognitionService.SERVICE_INTERFACE); mListener.mInternalListener = listener; if (mServiceComponent == null) { // TODO: Resolve the ComponentName here and use it. String serviceComponent = null; if (TextUtils.isEmpty(serviceComponent)) { Log.e(TAG, "no selected voice recognition service"); mListener.onHotwordError(ERROR_CLIENT); return; } serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent)); } else { serviceIntent.setComponent(mServiceComponent); } Loading @@ -222,17 +220,15 @@ public class HotwordRecognizer { mListener.onHotwordError(ERROR_CLIENT); return; } putMessage(Message.obtain(mHandler, MSG_START)); } else { mListener.onHotwordError(ERROR_SERVICE_ALREADY_STARTED); return; } putMessage(Message.obtain(mHandler, MSG_START)); } /** * Stops recognizing hotword. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} should be called beforehand, * otherwise no notifications will be received. * Stops recognizing hotword. */ public void stopRecognition() { checkIsCalledFromMainThread(); Loading @@ -245,19 +241,6 @@ public class HotwordRecognizer { mServiceComponent = serviceComponent; } /** * Destroys the {@code HotwordRecognizer} object. */ public void destroy() { if (mConnection != null) { mContext.unbindService(mConnection); } mPendingTasks.clear(); mService = null; mConnection = null; mListener.mInternalListener = null; } private void handleStartRecognition() { if (!checkOpenConnection()) { return; Loading @@ -271,26 +254,27 @@ public class HotwordRecognizer { } } private void handleStopRecognition() { if (!checkOpenConnection()) { return; } try { mService.stopHotwordRecognition(mListener); if (mConnection != null) { mContext.unbindService(mConnection); } if (DBG) Log.d(TAG, "service stopRecognition command succeeded"); } catch (final RemoteException e) { Log.e(TAG, "stopRecognition() failed", e); mListener.onHotwordError(ERROR_CLIENT); } finally { mPendingTasks.clear(); mService = null; mConnection = null; mListener.mInternalListener = null; } } /** changes the listener */ private void handleChangeListener(HotwordRecognitionListener listener) { if (DBG) Log.d(TAG, "handleChangeListener, listener=" + listener); mListener.mInternalListener = listener; } private boolean checkOpenConnection() { if (mService != null) { return true; Loading Loading
core/java/android/speech/hotword/HotwordRecognitionService.java +4 −27 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.SdkConstant.SdkConstantType; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -113,8 +112,9 @@ public abstract class HotwordRecognitionService extends Service { listener.onHotwordError(HotwordRecognizer.ERROR_RECOGNIZER_BUSY); Log.w(TAG, "stopRecognition called by a different caller - ignoring"); } else { // the correct state HotwordRecognitionService.this.onStopHotwordRecognition(mCurrentCallback); mCurrentCallback.onHotwordRecognitionStopped(); mCurrentCallback = null; HotwordRecognitionService.this.onStopHotwordRecognition(); } } catch (RemoteException e) { // occurs if onError fails if (DBG) Log.d(TAG, "onError call from stopRecognition failed"); Loading @@ -138,27 +138,6 @@ public abstract class HotwordRecognitionService extends Service { super.onDestroy(); } /** * Checks whether the caller has sufficient permissions * * @param listener to send the error message to in case of error * @return {@code true} if the caller has enough permissions, {@code false} otherwise */ private boolean checkPermissions(IHotwordRecognitionListener listener) { if (DBG) Log.d(TAG, "checkPermissions"); if (checkCallingOrSelfPermission( android.Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) { return true; } try { Log.e(TAG, "Recognition service called without RECORD_AUDIO permissions"); listener.onHotwordError(HotwordRecognizer.ERROR_FAILED); } catch (RemoteException e) { Log.e(TAG, "onHotwordError(ERROR_INSUFFICIENT_PERMISSIONS) message failed", e); } return false; } /** * Notifies the service to start a recognition. * Loading @@ -168,10 +147,8 @@ public abstract class HotwordRecognitionService extends Service { /** * Notifies the service to stop recognition. * * @param callback that receives the callbacks from the service. */ public abstract void onStopHotwordRecognition(Callback callback); public abstract void onStopHotwordRecognition(); /** Binder of the hotword recognition service */ private static class RecognitionServiceBinder extends IHotwordRecognitionService.Stub { Loading @@ -183,7 +160,7 @@ public abstract class HotwordRecognitionService extends Service { public void startHotwordRecognition(IHotwordRecognitionListener listener) { if (DBG) Log.d(TAG, "startRecognition called by: " + listener.asBinder()); if (mInternalService != null && mInternalService.checkPermissions(listener)) { if (mInternalService != null) { mInternalService.mHandler.sendMessage( Message.obtain(mInternalService.mHandler, MSG_START_RECOGNITION, listener)); } Loading
core/java/android/speech/hotword/HotwordRecognizer.java +46 −62 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -82,7 +84,6 @@ public class HotwordRecognizer { /** action codes */ private static final int MSG_START = 1; private static final int MSG_STOP = 2; private final static int MSG_CHANGE_LISTENER = 3; /** The underlying HotwordRecognitionService endpoint */ private IHotwordRecognitionService mService; Loading @@ -107,9 +108,6 @@ public class HotwordRecognizer { case MSG_STOP: handleStopRecognition(); break; case MSG_CHANGE_LISTENER: handleChangeListener((HotwordRecognitionListener) msg.obj); break; } } }; Loading Loading @@ -138,24 +136,38 @@ public class HotwordRecognizer { } /** * Factory method to create a new {@code HotwordRecognizer}. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} * should be called before dispatching any command to the created {@code HotwordRecognizer}, * otherwise no notifications will be received. * Factory method to create a new {@code HotwordRecognizer}. * * @param context in which to create {@code HotwordRecognizer} * @return a new {@code HotwordRecognizer} */ public static HotwordRecognizer createHotwordRecognizer(final Context context) { return createHotwordRecognizer(context, null); ComponentName serviceComponent = null; // Resolve to a default ComponentName. final List<ResolveInfo> list = context.getPackageManager().queryIntentServices( new Intent(HotwordRecognitionService.SERVICE_INTERFACE), 0); for (int i = 0; i < list.size(); i++) { final ResolveInfo ri = list.get(i); if (!ri.serviceInfo.enabled) { continue; } if ((ri.serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != PackageManager.MATCH_DEFAULT_ONLY) { serviceComponent = new ComponentName( ri.serviceInfo.packageName, ri.serviceInfo.name); break; } } // If all else fails, pick the first one. if (serviceComponent == null && !list.isEmpty()) { serviceComponent = new ComponentName( list.get(0).serviceInfo.packageName, list.get(0).serviceInfo.name); } return createHotwordRecognizer(context, serviceComponent); } /** * Factory method to create a new {@code HotwordRecognizer}. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} * should be called before dispatching any command to the created {@code HotwordRecognizer}, * otherwise no notifications will be received. * Factory method to create a new {@code HotwordRecognizer}. * * Use this version of the method to specify a specific service to direct this * {@link HotwordRecognizer} to. Normally you would not use this; use Loading @@ -177,40 +189,26 @@ public class HotwordRecognizer { } /** * Sets the listener that will receive all the callbacks. The previous unfinished commands will * be executed with the old listener, while any following command will be executed with the new * listener. * Starts recognizing hotword and sets the listener that will receive the callbacks. * * @param listener listener that will receive all the callbacks from the created * {@link HotwordRecognizer}, this must not be null. */ public void setRecognitionListener(HotwordRecognitionListener listener) { public void startRecognition(HotwordRecognitionListener listener) { checkIsCalledFromMainThread(); putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener)); if (mConnection == null) { // first time connection if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } /** * Starts recognizing hotword. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} should be called beforehand, * otherwise no notifications will be received. */ public void startRecognition() { checkIsCalledFromMainThread(); if (mConnection == null) { // first time connection mConnection = new Connection(); Intent serviceIntent = new Intent(HotwordRecognitionService.SERVICE_INTERFACE); mListener.mInternalListener = listener; if (mServiceComponent == null) { // TODO: Resolve the ComponentName here and use it. String serviceComponent = null; if (TextUtils.isEmpty(serviceComponent)) { Log.e(TAG, "no selected voice recognition service"); mListener.onHotwordError(ERROR_CLIENT); return; } serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent)); } else { serviceIntent.setComponent(mServiceComponent); } Loading @@ -222,17 +220,15 @@ public class HotwordRecognizer { mListener.onHotwordError(ERROR_CLIENT); return; } putMessage(Message.obtain(mHandler, MSG_START)); } else { mListener.onHotwordError(ERROR_SERVICE_ALREADY_STARTED); return; } putMessage(Message.obtain(mHandler, MSG_START)); } /** * Stops recognizing hotword. Please note that * {@link #setRecognitionListener(HotwordRecognitionListener)} should be called beforehand, * otherwise no notifications will be received. * Stops recognizing hotword. */ public void stopRecognition() { checkIsCalledFromMainThread(); Loading @@ -245,19 +241,6 @@ public class HotwordRecognizer { mServiceComponent = serviceComponent; } /** * Destroys the {@code HotwordRecognizer} object. */ public void destroy() { if (mConnection != null) { mContext.unbindService(mConnection); } mPendingTasks.clear(); mService = null; mConnection = null; mListener.mInternalListener = null; } private void handleStartRecognition() { if (!checkOpenConnection()) { return; Loading @@ -271,26 +254,27 @@ public class HotwordRecognizer { } } private void handleStopRecognition() { if (!checkOpenConnection()) { return; } try { mService.stopHotwordRecognition(mListener); if (mConnection != null) { mContext.unbindService(mConnection); } if (DBG) Log.d(TAG, "service stopRecognition command succeeded"); } catch (final RemoteException e) { Log.e(TAG, "stopRecognition() failed", e); mListener.onHotwordError(ERROR_CLIENT); } finally { mPendingTasks.clear(); mService = null; mConnection = null; mListener.mInternalListener = null; } } /** changes the listener */ private void handleChangeListener(HotwordRecognitionListener listener) { if (DBG) Log.d(TAG, "handleChangeListener, listener=" + listener); mListener.mInternalListener = listener; } private boolean checkOpenConnection() { if (mService != null) { return true; Loading