am f7a7a636: am b0a17400: Merge "Add Service API to perform Hotword recognition" into klp-dev

* commit 'f7a7a636f6a38b8de9a54911152ec5858e344db6':
  Add Service API to perform Hotword recognition
This commit is contained in:
Sandeep Siddhartha
2013-08-27 10:29:52 -07:00
committed by Android Git Automerger
6 changed files with 836 additions and 0 deletions

View File

@@ -195,6 +195,8 @@ LOCAL_SRC_FILES += \
core/java/android/view/IWindowSession.aidl \
core/java/android/speech/IRecognitionListener.aidl \
core/java/android/speech/IRecognitionService.aidl \
core/java/android/speech/hotword/IHotwordRecognitionListener.aidl \
core/java/android/speech/hotword/IHotwordRecognitionService.aidl \
core/java/android/speech/tts/ITextToSpeechCallback.aidl \
core/java/android/speech/tts/ITextToSpeechService.aidl \
core/java/com/android/internal/app/IAppOpsCallback.aidl \

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.speech.hotword;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
/**
* Used for receiving notifications from the HotwordRecognitionService when the
* hotword recognition related events occur.
* All the callbacks are executed on the application main thread.
* {@hide}
*/
public interface HotwordRecognitionListener {
/**
* Called when the service starts listening for hotword.
*/
void onHotwordRecognitionStarted();
/**
* Called when the service stops listening for hotword.
*/
void onHotwordRecognitionStopped();
/**
* Called on an event of interest to the client.
*
* @param eventType the event type.
* @param eventBundle a Bundle containing the hotword event(s).
*/
void onHotwordEvent(int eventType, Bundle eventBundle);
/**
* Called back when hotword is detected.
* The action tells the client what action to take, post hotword-detection.
*/
void onHotwordRecognized(PendingIntent intent);
/**
* Called when the HotwordRecognitionService encounters an error.
*
* @param errorCode the error code describing the error that was encountered.
*/
void onHotwordError(int errorCode);
}

View File

@@ -0,0 +1,258 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.speech.hotword;
import android.annotation.SdkConstant;
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;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
/**
* This class provides a base class for hotword detection service implementations.
* This class should be extended only if you wish to implement a new hotword recognizer.
* {@hide}
*/
public abstract class HotwordRecognitionService extends Service {
/**
* The {@link Intent} that must be declared as handled by the service.
*/
@SdkConstant(SdkConstantType.SERVICE_ACTION)
public static final String SERVICE_INTERFACE =
"android.speech.hotword.HotwordRecognitionService";
/** Log messages identifier */
private static final String TAG = "HotwordRecognitionService";
/** Debugging flag */
// TODO: Turn off.
private static final boolean DBG = true;
private static final int MSG_START_RECOGNITION = 1;
private static final int MSG_STOP_RECOGNITION = 2;
/**
* The current callback of an application that invoked the
* {@link HotwordRecognitionService#onStartHotwordRecognition(Callback)} method
*/
private Callback mCurrentCallback = null;
// Handle the client dying.
private final IBinder.DeathRecipient mCallbackDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (DBG) Log.i(TAG, "HotwordRecognitionService listener died");
mCurrentCallback = null;
}
};
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_START_RECOGNITION:
dispatchStartRecognition((IHotwordRecognitionListener) msg.obj);
break;
case MSG_STOP_RECOGNITION:
dispatchStopRecognition((IHotwordRecognitionListener) msg.obj);
break;
}
}
};
/** Binder of the hotword recognition service */
private RecognitionServiceBinder mBinder = new RecognitionServiceBinder(this);
private void dispatchStartRecognition(IHotwordRecognitionListener listener) {
if (mCurrentCallback == null) {
if (DBG) Log.d(TAG, "created new mCurrentCallback, listener = " + listener.asBinder());
try {
listener.asBinder().linkToDeath(mCallbackDeathRecipient, 0);
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "listener died before linkToDeath()");
}
mCurrentCallback = new Callback(listener);
HotwordRecognitionService.this.onStartHotwordRecognition(mCurrentCallback);
} else {
try {
listener.onHotwordError(HotwordRecognizer.ERROR_RECOGNIZER_BUSY);
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "onError call from startRecognition failed");
}
if (DBG) Log.d(TAG, "concurrent startRecognition received - ignoring this call");
}
}
private void dispatchStopRecognition(IHotwordRecognitionListener listener) {
try {
if (mCurrentCallback == null) {
listener.onHotwordError(HotwordRecognizer.ERROR_CLIENT);
Log.w(TAG, "stopRecognition called with no preceding startRecognition - ignoring");
} else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
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 = null;
}
} catch (RemoteException e) { // occurs if onError fails
if (DBG) Log.d(TAG, "onError call from stopRecognition failed");
}
}
@Override
public IBinder onBind(final Intent intent) {
if (DBG) Log.d(TAG, "onBind, intent=" + intent);
return mBinder;
}
@Override
public void onDestroy() {
if (DBG) Log.d(TAG, "onDestroy");
if (mCurrentCallback != null) {
mCurrentCallback.mListener.asBinder().unlinkToDeath(mCallbackDeathRecipient, 0);
mCurrentCallback = null;
}
mBinder.clearReference();
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_INSUFFICIENT_PERMISSIONS);
} catch (RemoteException e) {
Log.e(TAG, "onHotwordError(ERROR_INSUFFICIENT_PERMISSIONS) message failed", e);
}
return false;
}
/**
* Notifies the service to start a recognition.
*
* @param callback that receives the callbacks from the service.
*/
public abstract void onStartHotwordRecognition(Callback callback);
/**
* Notifies the service to stop recognition.
*
* @param callback that receives the callbacks from the service.
*/
public abstract void onStopHotwordRecognition(Callback callback);
/** Binder of the hotword recognition service */
private static class RecognitionServiceBinder extends IHotwordRecognitionService.Stub {
private HotwordRecognitionService mInternalService;
public RecognitionServiceBinder(HotwordRecognitionService service) {
mInternalService = service;
}
public void startHotwordRecognition(IHotwordRecognitionListener listener) {
if (DBG) Log.d(TAG, "startRecognition called by: " + listener.asBinder());
if (mInternalService != null && mInternalService.checkPermissions(listener)) {
mInternalService.mHandler.sendMessage(
Message.obtain(mInternalService.mHandler, MSG_START_RECOGNITION, listener));
}
}
public void stopHotwordRecognition(IHotwordRecognitionListener listener) {
if (DBG) Log.d(TAG, "stopRecognition called by: " + listener.asBinder());
if (mInternalService != null) {
mInternalService.mHandler.sendMessage(
Message.obtain(mInternalService.mHandler, MSG_STOP_RECOGNITION, listener));
}
}
private void clearReference() {
mInternalService = null;
}
}
/**
* This class acts passes on the callbacks received from the Hotword service
* to the listener.
*/
public static class Callback {
private final IHotwordRecognitionListener mListener;
private Callback(IHotwordRecognitionListener listener) {
mListener = listener;
}
/**
* Called when the service starts listening for hotword.
*/
public void onHotwordRecognitionStarted() throws RemoteException {
mListener.onHotwordRecognitionStarted();
}
/**
* Called when the service starts listening for hotword.
*/
public void onHotwordRecognitionStopped() throws RemoteException {
mListener.onHotwordRecognitionStopped();
}
/**
* Called on an event of interest to the client.
*
* @param eventType the event type. Event types are defined in {@link HotwordRecognizer}.
* @param eventBundle a Bundle containing the hotword event(s).
*/
public void onHotwordEvent(int eventType, Bundle eventBundle) throws RemoteException {
mListener.onHotwordEvent(eventType, eventBundle);
}
/**
* Called back when hotword is detected.
* The action tells the client what action to take, post hotword-detection.
*/
public void onHotwordRecognized(PendingIntent intent) throws RemoteException {
mListener.onHotwordRecognized(intent);
}
/**
* Called when the HotwordRecognitionService encounters an error.
*
* @param errorCode the error code describing the error that was encountered.
* Error codes are defined in {@link HotwordRecognizer}.
*/
public void onError(int errorCode) throws RemoteException {
mListener.onHotwordError(errorCode);
}
}
}

View File

@@ -0,0 +1,409 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.speech.hotword;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* This class provides access to the Hotword recognition service.
* This class's methods must be invoked on the main application thread.
* {@hide}
*/
public class HotwordRecognizer {
/** DEBUG value to enable verbose debug prints */
// TODO: Turn off.
private final static boolean DBG = true;
/** Log messages identifier */
private static final String TAG = "HotwordRecognizer";
/**
* Key used to retrieve a string to be displayed to the user passed to the
* {@link android.speech.hotword.HotwordRecognitionListener#onHotwordEvent(int, Bundle)} method.
*/
public static final String PROMPT_TEXT = "prompt_text";
/**
* Event type used to indicate to the user that the hotword service has changed
* its state.
*/
public static final int EVENT_TYPE_STATE_CHANGED = 1;
/** Audio recording error. */
public static final int ERROR_AUDIO = 1;
/** RecognitionService busy. */
public static final int ERROR_RECOGNIZER_BUSY = 2;
/** Insufficient permissions */
public static final int ERROR_INSUFFICIENT_PERMISSIONS = 3;
/** Client-side errors */
public static final int ERROR_CLIENT = 4;
/** The service timed out */
public static final int ERROR_TIMEOUT = 5;
/** The service received concurrent start calls */
public static final int WARNING_SERVICE_ALREADY_STARTED = 6;
/** 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;
/** The connection to the actual service */
private Connection mConnection;
/** Context with which the manager was created */
private final Context mContext;
/** Component to direct service intent to */
private final ComponentName mServiceComponent;
/** Handler that will execute the main tasks */
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_START:
handleStartRecognition();
break;
case MSG_STOP:
handleStopRecognition();
break;
case MSG_CHANGE_LISTENER:
handleChangeListener((HotwordRecognitionListener) 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 LinkedList<Message>();
/** The Listener that will receive all the callbacks */
private final InternalListener mListener = new InternalListener();
/**
* Checks whether a hotword recognition service is available on the system. If this method
* returns {@code false}, {@link HotwordRecognizer#createHotwordRecognizer(Context)} will
* fail.
*
* @param context with which {@code HotwordRecognizer} will be created
* @return {@code true} if recognition is available, {@code false} otherwise
*/
public static boolean isHotwordRecognitionAvailable(final Context context) {
final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
new Intent(HotwordRecognitionService.SERVICE_INTERFACE), 0);
return list != null && list.size() != 0;
}
/**
* 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.
*
* @param context in which to create {@code HotwordRecognizer}
* @return a new {@code HotwordRecognizer}
*/
public static HotwordRecognizer createHotwordRecognizer(final Context context) {
return createHotwordRecognizer(context, null);
}
/**
* 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.
*
* Use this version of the method to specify a specific service to direct this
* {@link HotwordRecognizer} to. Normally you would not use this; use
* {@link #createHotwordRecognizer(Context)} instead to use the system default recognition
* service.
*
* @param context in which to create {@code HotwordRecognizer}
* @param serviceComponent the {@link ComponentName} of a specific service to direct this
* {@code HotwordRecognizer} to
* @return a new {@code HotwordRecognizer}
*/
public static HotwordRecognizer createHotwordRecognizer(
final Context context, final ComponentName serviceComponent) {
if (context == null) {
throw new IllegalArgumentException("Context cannot be null)");
}
checkIsCalledFromMainThread();
return new HotwordRecognizer(context, serviceComponent);
}
/**
* 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.
*
* @param listener listener that will receive all the callbacks from the created
* {@link HotwordRecognizer}, this must not be null.
*/
public void setRecognitionListener(HotwordRecognitionListener listener) {
checkIsCalledFromMainThread();
putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener));
}
/**
* 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);
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);
}
if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) {
Log.e(TAG, "bind to recognition service failed");
mConnection = null;
mService = null;
mListener.onHotwordError(ERROR_CLIENT);
return;
}
} else {
mListener.onHotwordError(WARNING_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.
*/
public void stopRecognition() {
checkIsCalledFromMainThread();
putMessage(Message.obtain(mHandler, MSG_STOP));
}
// Private constructor.
private HotwordRecognizer(Context context, ComponentName serviceComponent) {
mContext = context;
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;
}
try {
mService.startHotwordRecognition(mListener);
if (DBG) Log.d(TAG, "service startRecognition command succeeded");
} catch (final RemoteException e) {
Log.e(TAG, "startRecognition() failed", e);
mListener.onHotwordError(ERROR_CLIENT);
}
}
private void handleStopRecognition() {
if (!checkOpenConnection()) {
return;
}
try {
mService.stopHotwordRecognition(mListener);
if (DBG) Log.d(TAG, "service stopRecognition command succeeded");
} catch (final RemoteException e) {
Log.e(TAG, "stopRecognition() failed", e);
mListener.onHotwordError(ERROR_CLIENT);
}
}
/** 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;
}
mListener.onHotwordError(ERROR_CLIENT);
Log.e(TAG, "not connected to the recognition service");
return false;
}
private static void checkIsCalledFromMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new RuntimeException(
"HotwordRecognizer should be used only from the application's main thread");
}
}
private void putMessage(Message msg) {
if (mService == null) {
mPendingTasks.offer(msg);
} else {
mHandler.sendMessage(msg);
}
}
/**
* Basic ServiceConnection that records the mService variable.
* Additionally, on creation it invokes
* {@link IHotwordRecognitionService#startHotwordRecognition(IHotwordRecognitionListener)}.
*/
private class Connection implements ServiceConnection {
public void onServiceConnected(final ComponentName name, final IBinder service) {
// always done on the application main thread, so no need to send message to mHandler
mService = IHotwordRecognitionService.Stub.asInterface(service);
if (DBG) Log.d(TAG, "onServiceConnected - Success");
while (!mPendingTasks.isEmpty()) {
mHandler.sendMessage(mPendingTasks.poll());
}
}
public void onServiceDisconnected(final ComponentName name) {
// always done on the application main thread, so no need to send message to mHandler
mService = null;
mConnection = null;
mPendingTasks.clear();
if (DBG) Log.d(TAG, "onServiceDisconnected - Success");
}
}
/**
* Internal wrapper of IHotwordRecognitionListener which will propagate the results to
* HotwordRecognitionListener.
*/
private class InternalListener extends IHotwordRecognitionListener.Stub {
private HotwordRecognitionListener mInternalListener;
private final static int MSG_ON_START = 1;
private final static int MSG_ON_STOP = 2;
private final static int MSG_ON_EVENT = 3;
private final static int MSG_ON_RECOGNIZED = 4;
private final static int MSG_ON_ERROR = 5;
private final Handler mInternalHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (mInternalListener == null) {
return;
}
switch (msg.what) {
case MSG_ON_START:
mInternalListener.onHotwordRecognitionStarted();
break;
case MSG_ON_STOP:
mInternalListener.onHotwordRecognitionStopped();
break;
case MSG_ON_EVENT:
mInternalListener.onHotwordEvent(msg.arg1, (Bundle) msg.obj);
break;
case MSG_ON_RECOGNIZED:
mInternalListener.onHotwordRecognized((PendingIntent) msg.obj);
break;
case MSG_ON_ERROR:
mInternalListener.onHotwordError((Integer) msg.obj);
break;
}
}
};
@Override
public void onHotwordRecognitionStarted() throws RemoteException {
Message.obtain(mInternalHandler, MSG_ON_START).sendToTarget();
}
@Override
public void onHotwordRecognitionStopped() throws RemoteException {
Message.obtain(mInternalHandler, MSG_ON_STOP).sendToTarget();
}
@Override
public void onHotwordEvent(final int eventType, final Bundle params) {
Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params)
.sendToTarget();
}
@Override
public void onHotwordRecognized(PendingIntent intent) throws RemoteException {
Message.obtain(mInternalHandler, MSG_ON_RECOGNIZED, intent)
.sendToTarget();
}
@Override
public void onHotwordError(final int error) {
Message.obtain(mInternalHandler, MSG_ON_ERROR, error).sendToTarget();
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.speech.hotword;
import android.app.PendingIntent;
import android.os.Bundle;
/**
* Listener for hotword detection events.
* This indicates when the hotword was detected, and also notifies the
* client of the intermediate events that may be used to show visual feedback
* to the user.
* {@hide}
*/
oneway interface IHotwordRecognitionListener {
/**
* Called when the service starts listening for hotword.
*/
void onHotwordRecognitionStarted();
/**
* Called when the service starts listening for hotword.
*/
void onHotwordRecognitionStopped();
/**
* Called on an event of interest to the client.
*
* @param eventType the event type.
* @param eventBundle a Bundle containing the hotword event(s).
*/
void onHotwordEvent(in int eventType, in Bundle eventBundle);
/**
* Called back when hotword is detected.
* The action tells the client what action to take, post hotword-detection.
*/
void onHotwordRecognized(in PendingIntent intent);
/**
* Called when the HotwordRecognitionService encounters an error.
*
* @param errorCode the error code describing the error that was encountered.
*/
void onHotwordError(in int errorCode);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.speech.hotword;
import android.speech.hotword.IHotwordRecognitionListener;
/**
* A service interface to Hotword recognition.
* Call startHotwordDetection with a listener when you want to begin detecting
* hotword;
* The service would automatically stop detection when hotword is detected;
* So it's a create-once use-once service.
* The service doesn't support nested calls to start detection and disallows them.
* {@hide}
*/
oneway interface IHotwordRecognitionService {
/**
* Start hotword recognition.
* The clients should rely on the callback to figure out if the detection was
* started.
*
* @param listener a listener to notify of hotword events.
*/
void startHotwordRecognition(in IHotwordRecognitionListener listener);
/**
* Stop hotword recognition.
* Stops the recognition only if it was started by the same caller.
*
* @param listener a listener to notify of hotword events.
*/
void stopHotwordRecognition(in IHotwordRecognitionListener listener);
}