diff options
author | Dianne Hackborn <hackbod@google.com> | 2014-05-05 18:32:03 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-05-05 18:32:03 +0000 |
commit | 2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c (patch) | |
tree | 53d2582eeae05101cf059b065c31e46e6f89807b /services | |
parent | f593c9d728529cc2a58d48b4dd6535a237f5b26a (diff) | |
parent | c03c9167c2d9a1e22fb2b176b00a0524177fb037 (diff) | |
download | frameworks_base-2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c.zip frameworks_base-2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c.tar.gz frameworks_base-2059bce9d6ce3848b23f3c41aa4feb63fbfc2e6c.tar.bz2 |
Merge "Further work on voice interaction services."
Diffstat (limited to 'services')
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); + } } } |