summaryrefslogtreecommitdiffstats
path: root/core/java/android/service
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2014-04-25 17:06:18 -0700
committerDianne Hackborn <hackbod@google.com>2014-04-28 10:54:15 -0700
commit18f0d357f9693fe787a3e3777d8fdf01357a6e3f (patch)
tree87ffa17a98fa81355a37e25b2c7fc649ffc4e9be /core/java/android/service
parent01c70711d5e4f1c3405bcd169be70605e92166f2 (diff)
downloadframeworks_base-18f0d357f9693fe787a3e3777d8fdf01357a6e3f.zip
frameworks_base-18f0d357f9693fe787a3e3777d8fdf01357a6e3f.tar.gz
frameworks_base-18f0d357f9693fe787a3e3777d8fdf01357a6e3f.tar.bz2
Rework some of the voice interaction APIs.
On the app side, requests are now composed by subclassing from various types of Request objects. On the service side, starting a voice interaction session involves starting another service that will then manage the session. This leads the service design much more to what we want, where the long-running main service is very tiny and all the heavy-weight transient session work is elsewhere in another process. Change-Id: I46c074c6fe27b6c1cf2583c6d216aed1de2f1143
Diffstat (limited to 'core/java/android/service')
-rw-r--r--core/java/android/service/voice/IVoiceInteractionSessionService.aidl28
-rw-r--r--core/java/android/service/voice/VoiceInteractionService.java8
-rw-r--r--core/java/android/service/voice/VoiceInteractionServiceInfo.java125
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java4
-rw-r--r--core/java/android/service/voice/VoiceInteractionSessionService.java82
5 files changed, 241 insertions, 6 deletions
diff --git a/core/java/android/service/voice/IVoiceInteractionSessionService.aidl b/core/java/android/service/voice/IVoiceInteractionSessionService.aidl
new file mode 100644
index 0000000..2519442
--- /dev/null
+++ b/core/java/android/service/voice/IVoiceInteractionSessionService.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 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.service.voice;
+
+import android.os.Bundle;
+
+import android.service.voice.IVoiceInteractionSession;
+
+/**
+ * @hide
+ */
+oneway interface IVoiceInteractionSessionService {
+ void newSession(IBinder token, in Bundle args);
+}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index ed93b74..d005890 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -21,6 +21,7 @@ import android.app.Instrumentation;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -50,12 +51,11 @@ public class VoiceInteractionService extends Service {
IVoiceInteractionManagerService mSystemService;
- public void startVoiceActivity(Intent intent, VoiceInteractionSession session) {
+ public void startVoiceActivity(Intent intent, Bundle sessionArgs) {
try {
- int res = mSystemService.startVoiceActivity(intent,
+ mSystemService.startVoiceActivity(intent,
intent.resolveType(getContentResolver()),
- mInterface, session.mSession, session.mInteractor);
- Instrumentation.checkStartActivityResult(res, intent);
+ mInterface, sessionArgs);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
new file mode 100644
index 0000000..a909ead
--- /dev/null
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2014 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.service.voice;
+
+import android.Manifest;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.speech.RecognitionService;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** @hide */
+public class VoiceInteractionServiceInfo {
+ static final String TAG = "VoiceInteractionServiceInfo";
+
+ private String mParseError;
+
+ private ServiceInfo mServiceInfo;
+ private String mSessionService;
+ private String mSettingsActivity;
+
+ public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
+ throws PackageManager.NameNotFoundException {
+ this(pm, pm.getServiceInfo(comp, PackageManager.GET_META_DATA));
+ }
+
+ public VoiceInteractionServiceInfo(PackageManager pm, ServiceInfo si) {
+ if (!Manifest.permission.BIND_VOICE_INTERACTION.equals(si.permission)) {
+ mParseError = "Service does not require permission "
+ + Manifest.permission.BIND_VOICE_INTERACTION;
+ return;
+ }
+
+ XmlResourceParser parser = null;
+ try {
+ parser = si.loadXmlMetaData(pm, VoiceInteractionService.SERVICE_META_DATA);
+ if (parser == null) {
+ mParseError = "No " + VoiceInteractionService.SERVICE_META_DATA
+ + " meta-data for " + si.packageName;
+ return;
+ }
+
+ Resources res = pm.getResourcesForApplication(si.applicationInfo);
+
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+
+ String nodeName = parser.getName();
+ if (!"voice-interaction-service".equals(nodeName)) {
+ mParseError = "Meta-data does not start with voice-interaction-service tag";
+ return;
+ }
+
+ TypedArray array = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.VoiceInteractionService);
+ mSessionService = array.getString(
+ com.android.internal.R.styleable.VoiceInteractionService_sessionService);
+ mSettingsActivity = array.getString(
+ com.android.internal.R.styleable.VoiceInteractionService_settingsActivity);
+ array.recycle();
+ if (mSessionService == null) {
+ mParseError = "No sessionService specified";
+ return;
+ }
+ } catch (XmlPullParserException e) {
+ mParseError = "Error parsing voice interation service meta-data: " + e;
+ Log.w(TAG, "error parsing voice interaction service meta-data", e);
+ return;
+ } catch (IOException e) {
+ mParseError = "Error parsing voice interation service meta-data: " + e;
+ Log.w(TAG, "error parsing voice interaction service meta-data", e);
+ return;
+ } catch (PackageManager.NameNotFoundException e) {
+ mParseError = "Error parsing voice interation service meta-data: " + e;
+ Log.w(TAG, "error parsing voice interaction service meta-data", e);
+ return;
+ } finally {
+ if (parser != null) parser.close();
+ }
+ mServiceInfo = si;
+ }
+
+ public String getParseError() {
+ return mParseError;
+ }
+
+ public ServiceInfo getServiceInfo() {
+ return mServiceInfo;
+ }
+
+ public String getSessionService() {
+ return mSessionService;
+ }
+
+ public String getSettingsActivity() {
+ return mSettingsActivity;
+ }
+}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 59544be..963b6b4 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -96,11 +96,11 @@ public abstract class VoiceInteractionSession {
}
}
- public void sendCommandResult(Bundle result) {
+ public void sendCommandResult(boolean complete, Bundle result) {
try {
if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface
+ " result=" + result);
- mCallback.deliverCommandResult(mInterface, result);
+ mCallback.deliverCommandResult(mInterface, complete, result);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java
new file mode 100644
index 0000000..40e5bba
--- /dev/null
+++ b/core/java/android/service/voice/VoiceInteractionSessionService.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2014 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.service.voice;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+public abstract class VoiceInteractionSessionService extends Service {
+
+ static final int MSG_NEW_SESSION = 1;
+
+ IVoiceInteractionManagerService mSystemService;
+
+ IVoiceInteractionSessionService mInterface = new IVoiceInteractionSessionService.Stub() {
+ public void newSession(IBinder token, Bundle args) {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(MSG_NEW_SESSION,
+ token, args));
+
+ }
+ };
+
+ HandlerCaller mHandlerCaller;
+ final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
+ @Override
+ public void executeMessage(Message msg) {
+ SomeArgs args = (SomeArgs)msg.obj;
+ switch (msg.what) {
+ case MSG_NEW_SESSION:
+ doNewSession((IBinder)args.arg1, (Bundle)args.arg2);
+ break;
+ }
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
+ ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+ mHandlerCaller = new HandlerCaller(this, Looper.myLooper(),
+ mHandlerCallerCallback, true);
+ }
+
+ public abstract VoiceInteractionSession onNewSession(Bundle args);
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mInterface.asBinder();
+ }
+
+ void doNewSession(IBinder token, Bundle args) {
+ VoiceInteractionSession session = onNewSession(args);
+ try {
+ mSystemService.deliverNewSession(token, session.mSession, session.mInteractor);
+ } catch (RemoteException e) {
+ }
+ }
+}