summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2014-05-05 18:32:03 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-05-05 18:32:03 +0000
commit2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c (patch)
tree53d2582eeae05101cf059b065c31e46e6f89807b /services
parentf593c9d728529cc2a58d48b4dd6535a237f5b26a (diff)
parentc03c9167c2d9a1e22fb2b176b00a0524177fb037 (diff)
downloadframeworks_base-2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c.zip
frameworks_base-2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c.tar.gz
frameworks_base-2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c.tar.bz2
Merge "Further work on voice interaction services."
Diffstat (limited to 'services')
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java2
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java20
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java4
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java86
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java103
5 files changed, 169 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index f506eab..7c3f288 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -480,7 +480,7 @@ final class ActivityRecord {
void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
if (task != null && task.removeActivity(this)) {
if (task != newTask) {
- task.stack.removeTask(task);
+ task.stack.removeTask(task, false);
} else {
Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
(newTask == null ? null : newTask.stack));
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d5ab277..ee39b67 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2841,7 +2841,7 @@ final class ActivityStack {
if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
mStackSupervisor.moveHomeToTop();
}
- removeTask(task);
+ removeTask(task, false);
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
@@ -3717,7 +3717,7 @@ final class ActivityStack {
return starting;
}
- void removeTask(TaskRecord task) {
+ void removeTask(TaskRecord task, boolean moving) {
mStackSupervisor.endLockTaskModeIfTaskEnding(task);
mWindowManager.removeTask(task.taskId);
final ActivityRecord r = mResumedActivity;
@@ -3731,9 +3731,13 @@ final class ActivityStack {
mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
}
mTaskHistory.remove(task);
- if (task.voiceInteractor != null) {
+ if (!moving && task.voiceSession != null) {
// This task was a voice interaction, so it should not remain on the
// recent tasks list.
+ try {
+ task.voiceSession.taskFinished(task.intent, task.taskId);
+ } catch (RemoteException e) {
+ }
mService.mRecentTasks.remove(task);
}
@@ -3753,7 +3757,7 @@ final class ActivityStack {
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
boolean toTop) {
TaskRecord task = new TaskRecord(taskId, info, intent, voiceSession, voiceInteractor);
- addTask(task, toTop);
+ addTask(task, toTop, false);
return task;
}
@@ -3761,13 +3765,19 @@ final class ActivityStack {
return new ArrayList<TaskRecord>(mTaskHistory);
}
- void addTask(final TaskRecord task, final boolean toTop) {
+ void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
task.stack = this;
if (toTop) {
insertTaskAtTop(task);
} else {
mTaskHistory.add(0, task);
}
+ if (!moving && task.voiceSession != null) {
+ try {
+ task.voiceSession.taskStarted(task.intent, task.taskId);
+ } catch (RemoteException e) {
+ }
+ }
}
public int getStackId() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9107cb6..8829b5f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2237,8 +2237,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
- task.stack.removeTask(task);
- stack.addTask(task, toTop);
+ task.stack.removeTask(task, true);
+ stack.addTask(task, toTop, true);
mWindowManager.addTask(taskId, stackId, toTop);
resumeTopActivitiesLocked();
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 045c0f6..16afc8f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -28,6 +28,8 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionService;
@@ -88,6 +90,21 @@ public class VoiceInteractionManagerService extends SystemService {
private boolean mSafeMode;
private int mCurUser;
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (RuntimeException e) {
+ // The activity manager only throws security exceptions, so let's
+ // log all others.
+ if (!(e instanceof SecurityException)) {
+ Slog.wtf(TAG, "VoiceInteractionManagerService Crash", e);
+ }
+ throw e;
+ }
+ }
+
public void systemRunning(boolean safeMode) {
mSafeMode = safeMode;
@@ -97,18 +114,18 @@ public class VoiceInteractionManagerService extends SystemService {
synchronized (this) {
mCurUser = ActivityManager.getCurrentUser();
- switchImplementationIfNeededLocked();
+ switchImplementationIfNeededLocked(false);
}
}
public void switchUser(int userHandle) {
synchronized (this) {
mCurUser = userHandle;
- switchImplementationIfNeededLocked();
+ switchImplementationIfNeededLocked(false);
}
}
- void switchImplementationIfNeededLocked() {
+ void switchImplementationIfNeededLocked(boolean force) {
if (!mSafeMode) {
String curService = Settings.Secure.getStringForUser(
mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
@@ -121,7 +138,7 @@ public class VoiceInteractionManagerService extends SystemService {
serviceComponent = null;
}
}
- if (mImpl == null || mImpl.mUser != mCurUser
+ if (force || mImpl == null || mImpl.mUser != mCurUser
|| !mImpl.mComponent.equals(serviceComponent)) {
if (mImpl != null) {
mImpl.shutdownLocked();
@@ -138,10 +155,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public void startVoiceActivity(Intent intent, String resolvedType,
- IVoiceInteractionService service, Bundle args) {
+ public void startSession(IVoiceInteractionService service, Bundle args) {
synchronized (this) {
- if (mImpl == null || service.asBinder() != mImpl.mService.asBinder()) {
+ if (mImpl == null || mImpl.mService == null
+ || service.asBinder() != mImpl.mService.asBinder()) {
throw new SecurityException(
"Caller is not the current voice interaction service");
}
@@ -149,8 +166,7 @@ public class VoiceInteractionManagerService extends SystemService {
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- mImpl.startVoiceActivityLocked(callingPid, callingUid,
- intent, resolvedType, args);
+ mImpl.startSessionLocked(callingPid, callingUid, args);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -158,12 +174,12 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public int deliverNewSession(IBinder token, IVoiceInteractionSession session,
+ public boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
IVoiceInteractor interactor) {
synchronized (this) {
if (mImpl == null) {
- Slog.w(TAG, "deliverNewSession without running voice interaction service");
- return ActivityManager.START_CANCELED;
+ throw new SecurityException(
+ "deliverNewSession without running voice interaction service");
}
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
@@ -175,7 +191,43 @@ public class VoiceInteractionManagerService extends SystemService {
Binder.restoreCallingIdentity(caller);
}
}
+ }
+ @Override
+ public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) {
+ synchronized (this) {
+ if (mImpl == null) {
+ Slog.w(TAG, "startVoiceActivity without running voice interaction service");
+ return ActivityManager.START_CANCELED;
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mImpl.startVoiceActivityLocked(callingPid, callingUid, token,
+ intent, resolvedType);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+ }
+
+ @Override
+ public void finish(IBinder token) {
+ synchronized (this) {
+ if (mImpl == null) {
+ Slog.w(TAG, "finish without running voice interaction service");
+ return;
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mImpl.finishLocked(callingPid, callingUid, token);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
}
@Override
@@ -207,7 +259,7 @@ public class VoiceInteractionManagerService extends SystemService {
@Override public void onChange(boolean selfChange) {
synchronized (VoiceInteractionManagerServiceStub.this) {
- switchImplementationIfNeededLocked();
+ switchImplementationIfNeededLocked(false);
}
}
}
@@ -220,27 +272,25 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public void onHandleUserStop(Intent intent, int userHandle) {
- super.onHandleUserStop(intent, userHandle);
}
@Override
public void onPackageDisappeared(String packageName, int reason) {
- super.onPackageDisappeared(packageName, reason);
}
@Override
public void onPackageAppeared(String packageName, int reason) {
- super.onPackageAppeared(packageName, reason);
+ if (mImpl != null && packageName.equals(mImpl.mComponent.getPackageName())) {
+ switchImplementationIfNeededLocked(true);
+ }
}
@Override
public void onPackageModified(String packageName) {
- super.onPackageModified(packageName);
}
@Override
public void onSomePackagesChanged() {
- super.onSomePackagesChanged();
}
};
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 6bbd1c1..9b6daad 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -19,9 +19,11 @@ package com.android.server.voiceinteraction;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
@@ -30,6 +32,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
@@ -37,6 +40,8 @@ import android.service.voice.IVoiceInteractionSessionService;
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionServiceInfo;
import android.util.Slog;
+import android.view.IWindowManager;
+import android.view.WindowManager;
import com.android.internal.app.IVoiceInteractor;
import java.io.FileDescriptor;
@@ -55,11 +60,28 @@ class VoiceInteractionManagerServiceImpl {
final IActivityManager mAm;
final VoiceInteractionServiceInfo mInfo;
final ComponentName mSessionComponentName;
+ final IWindowManager mIWindowManager;
boolean mBound = false;
IVoiceInteractionService mService;
SessionConnection mActiveSession;
+ final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ synchronized (mLock) {
+ if (mActiveSession != null && mActiveSession.mSession != null) {
+ try {
+ mActiveSession.mSession.closeSystemDialogs();
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+ }
+ };
+
final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -76,23 +98,26 @@ class VoiceInteractionManagerServiceImpl {
final class SessionConnection implements ServiceConnection {
final IBinder mToken = new Binder();
- final Intent mIntent;
- final String mResolvedType;
final Bundle mArgs;
boolean mBound;
IVoiceInteractionSessionService mService;
IVoiceInteractionSession mSession;
IVoiceInteractor mInteractor;
- SessionConnection(Intent intent, String resolvedType, Bundle args) {
- mIntent = intent;
- mResolvedType = resolvedType;
+ SessionConnection(Bundle args) {
mArgs = args;
Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
serviceIntent.setComponent(mSessionComponentName);
mBound = mContext.bindServiceAsUser(serviceIntent, this,
Context.BIND_AUTO_CREATE, new UserHandle(mUser));
- if (!mBound) {
+ if (mBound) {
+ try {
+ mIWindowManager.addWindowToken(mToken,
+ WindowManager.LayoutParams.TYPE_INPUT_METHOD);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed adding window token", e);
+ }
+ } else {
Slog.w(TAG, "Failed binding to voice interaction session service " + mComponent);
}
}
@@ -105,7 +130,7 @@ class VoiceInteractionManagerServiceImpl {
try {
mService.newSession(mToken, mArgs);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed making new session", e);
+ Slog.w(TAG, "Failed adding window token", e);
}
}
}
@@ -118,7 +143,19 @@ class VoiceInteractionManagerServiceImpl {
public void cancel() {
if (mBound) {
+ if (mSession != null) {
+ try {
+ mSession.destroy();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Voice interation session already dead");
+ }
+ }
mContext.unbindService(this);
+ try {
+ mIWindowManager.removeWindowToken(mToken);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed removing window token", e);
+ }
mBound = false;
mService = null;
mSession = null;
@@ -128,8 +165,6 @@ class VoiceInteractionManagerServiceImpl {
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
- pw.print(prefix); pw.print("mIntent="); pw.println(mIntent);
- pw.print(" mResolvedType="); pw.println(mResolvedType);
pw.print(prefix); pw.print("mArgs="); pw.println(mArgs);
pw.print(prefix); pw.print("mBound="); pw.println(mBound);
if (mBound) {
@@ -155,6 +190,7 @@ class VoiceInteractionManagerServiceImpl {
Slog.w(TAG, "Voice interaction service not found: " + service);
mInfo = null;
mSessionComponentName = null;
+ mIWindowManager = null;
mValid = false;
return;
}
@@ -162,43 +198,67 @@ class VoiceInteractionManagerServiceImpl {
if (mInfo.getParseError() != null) {
Slog.w(TAG, "Bad voice interaction service: " + mInfo.getParseError());
mSessionComponentName = null;
+ mIWindowManager = null;
mValid = false;
return;
}
mValid = true;
mSessionComponentName = new ComponentName(service.getPackageName(),
mInfo.getSessionService());
+ mIWindowManager = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ mContext.registerReceiver(mBroadcastReceiver, filter, null, handler);
}
- public void startVoiceActivityLocked(int callingPid, int callingUid, Intent intent,
- String resolvedType, Bundle args) {
+ public void startSessionLocked(int callingPid, int callingUid, Bundle args) {
if (mActiveSession != null) {
mActiveSession.cancel();
mActiveSession = null;
}
- mActiveSession = new SessionConnection(intent, resolvedType, args);
- intent.addCategory(Intent.CATEGORY_VOICE);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ mActiveSession = new SessionConnection(args);
}
- public int deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
+ public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
IVoiceInteractionSession session, IVoiceInteractor interactor) {
+ if (mActiveSession == null || token != mActiveSession.mToken) {
+ Slog.w(TAG, "deliverNewSession does not match active session");
+ return false;
+ }
+ mActiveSession.mSession = session;
+ mActiveSession.mInteractor = interactor;
+ return true;
+ }
+
+ public int startVoiceActivityLocked(int callingPid, int callingUid, IBinder token,
+ Intent intent, String resolvedType) {
try {
if (mActiveSession == null || token != mActiveSession.mToken) {
- Slog.w(TAG, "deliverNewSession does not match active session");
+ Slog.w(TAG, "startVoiceActivity does not match active session");
return ActivityManager.START_CANCELED;
}
- mActiveSession.mSession = session;
- mActiveSession.mInteractor = interactor;
+ intent = new Intent(intent);
+ intent.addCategory(Intent.CATEGORY_VOICE);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
return mAm.startVoiceActivity(mComponent.getPackageName(), callingPid, callingUid,
- mActiveSession.mIntent, mActiveSession.mResolvedType,
- mActiveSession.mSession, mActiveSession.mInteractor,
+ intent, resolvedType, mActiveSession.mSession, mActiveSession.mInteractor,
0, null, null, null, mUser);
} catch (RemoteException e) {
throw new IllegalStateException("Unexpected remote error", e);
}
}
+
+ public void finishLocked(int callingPid, int callingUid, IBinder token) {
+ if (mActiveSession == null || token != mActiveSession.mToken) {
+ Slog.w(TAG, "finish does not match active session");
+ return;
+ }
+ mActiveSession.cancel();
+ mActiveSession = null;
+ }
+
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!mValid) {
pw.print(" NOT VALID: ");
@@ -234,5 +294,8 @@ class VoiceInteractionManagerServiceImpl {
mContext.unbindService(mConnection);
mBound = false;
}
+ if (mValid) {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ }
}
}