diff options
author | Dianne Hackborn <hackbod@google.com> | 2015-02-26 18:59:56 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-02-26 18:59:57 +0000 |
commit | 93ec05ca470453cc0505d2e387a7f4e3a2fe07d8 (patch) | |
tree | 9f1d0b458bc95900f7216a2e0fd53c817ae78eee /services | |
parent | d849518369846cffdf75679fe70712fe89a573ad (diff) | |
parent | ffeecb1bfb9b71f4b62c9ef1fbf7b58a7a63f655 (diff) | |
download | frameworks_base-93ec05ca470453cc0505d2e387a7f4e3a2fe07d8.zip frameworks_base-93ec05ca470453cc0505d2e387a7f4e3a2fe07d8.tar.gz frameworks_base-93ec05ca470453cc0505d2e387a7f4e3a2fe07d8.tar.bz2 |
Merge "Rework voice interaction session lifecycle."
Diffstat (limited to 'services')
3 files changed, 342 insertions, 139 deletions
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index fd990d7..6b8c49c 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -385,7 +385,7 @@ public class VoiceInteractionManagerService extends SystemService { } @Override - public void startSession(IVoiceInteractionService service, Bundle args, int flags) { + public void showSession(IVoiceInteractionService service, Bundle args, int flags) { synchronized (this) { if (mImpl == null || mImpl.mService == null || service.asBinder() != mImpl.mService.asBinder()) { @@ -396,7 +396,7 @@ public class VoiceInteractionManagerService extends SystemService { final int callingUid = Binder.getCallingUid(); final long caller = Binder.clearCallingIdentity(); try { - mImpl.startSessionLocked(callingPid, callingUid, args, flags); + mImpl.showSessionLocked(callingPid, callingUid, args, flags); } finally { Binder.restoreCallingIdentity(caller); } @@ -424,6 +424,42 @@ public class VoiceInteractionManagerService extends SystemService { } @Override + public boolean showSessionFromSession(IBinder token, Bundle sessionArgs, int flags) { + synchronized (this) { + if (mImpl == null) { + Slog.w(TAG, "showSessionFromSession without running voice interaction service"); + return false; + } + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); + final long caller = Binder.clearCallingIdentity(); + try { + return mImpl.showSessionLocked(callingPid, callingUid, sessionArgs, flags); + } finally { + Binder.restoreCallingIdentity(caller); + } + } + } + + @Override + public boolean hideSessionFromSession(IBinder token) { + synchronized (this) { + if (mImpl == null) { + Slog.w(TAG, "hideSessionFromSession without running voice interaction service"); + return false; + } + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); + final long caller = Binder.clearCallingIdentity(); + try { + return mImpl.hideSessionLocked(callingPid, callingUid); + } finally { + Binder.restoreCallingIdentity(caller); + } + } + } + + @Override public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) { synchronized (this) { if (mImpl == null) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index e80f702..9e92867 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -26,7 +26,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; -import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -35,20 +34,17 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; -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 com.android.internal.os.IResultReceiver; import java.io.FileDescriptor; import java.io.PrintWriter; -class VoiceInteractionManagerServiceImpl { +class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConnection.Callback { final static String TAG = "VoiceInteractionServiceManager"; final boolean mValid; @@ -65,7 +61,7 @@ class VoiceInteractionManagerServiceImpl { boolean mBound = false; IVoiceInteractionService mService; - SessionConnection mActiveSession; + VoiceInteractionSessionConnection mActiveSession; final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -101,124 +97,6 @@ class VoiceInteractionManagerServiceImpl { } }; - final class SessionConnection implements ServiceConnection { - final IBinder mToken = new Binder(); - final Bundle mArgs; - final int mFlags; - boolean mBound; - IVoiceInteractionSessionService mService; - IVoiceInteractionSession mSession; - IVoiceInteractor mInteractor; - boolean mHaveAssistData; - Bundle mAssistData; - - final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() { - @Override - public void send(int resultCode, Bundle resultData) throws RemoteException { - synchronized (mLock) { - mHaveAssistData = true; - mAssistData = resultData; - if (mSession != null) { - try { - mSession.handleAssist(resultData); - } catch (RemoteException e) { - } - } - } - } - }; - - SessionConnection(Bundle args, int flags) { - mArgs = args; - mFlags = flags; - Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE); - serviceIntent.setComponent(mSessionComponentName); - mBound = mContext.bindServiceAsUser(serviceIntent, this, - Context.BIND_AUTO_CREATE, new UserHandle(mUser)); - if (mBound) { - try { - mIWindowManager.addWindowToken(mToken, - WindowManager.LayoutParams.TYPE_VOICE_INTERACTION); - } catch (RemoteException e) { - Slog.w(TAG, "Failed adding window token", e); - } - if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) { - try { - mAm.requestAssistContextExtras(0, mAssistReceiver); - } catch (RemoteException e) { - } - } else { - mHaveAssistData = true; - } - } else { - Slog.w(TAG, "Failed binding to voice interaction session service " + mComponent); - } - } - - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - synchronized (mLock) { - mService = IVoiceInteractionSessionService.Stub.asInterface(service); - if (mActiveSession == this) { - try { - mService.newSession(mToken, mArgs, mFlags); - } catch (RemoteException e) { - Slog.w(TAG, "Failed adding window token", e); - } - } - } - } - - @Override - public void onServiceDisconnected(ComponentName name) { - mService = null; - } - - public void cancel() { - if (mBound) { - if (mSession != null) { - try { - mSession.destroy(); - } catch (RemoteException e) { - Slog.w(TAG, "Voice interation session already dead"); - } - } - if (mSession != null) { - try { - mAm.finishVoiceTask(mSession); - } catch (RemoteException e) { - } - } - mContext.unbindService(this); - try { - mIWindowManager.removeWindowToken(mToken); - } catch (RemoteException e) { - Slog.w(TAG, "Failed removing window token", e); - } - mBound = false; - mService = null; - mSession = null; - mInteractor = null; - } - } - - public void dump(String prefix, PrintWriter pw) { - pw.print(prefix); pw.print("mToken="); pw.println(mToken); - pw.print(prefix); pw.print("mArgs="); pw.println(mArgs); - pw.print(prefix); pw.print("mFlags=0x"); pw.println(Integer.toHexString(mFlags)); - pw.print(prefix); pw.print("mBound="); pw.println(mBound); - if (mBound) { - pw.print(prefix); pw.print("mService="); pw.println(mService); - pw.print(prefix); pw.print("mSession="); pw.println(mSession); - pw.print(prefix); pw.print("mInteractor="); pw.println(mInteractor); - } - pw.print(prefix); pw.print("mHaveAssistData="); pw.println(mHaveAssistData); - if (mHaveAssistData) { - pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData); - } - } - }; - VoiceInteractionManagerServiceImpl(Context context, Handler handler, Object lock, int userHandle, ComponentName service) { mContext = context; @@ -256,12 +134,16 @@ class VoiceInteractionManagerServiceImpl { mContext.registerReceiver(mBroadcastReceiver, filter, null, handler); } - public void startSessionLocked(int callingPid, int callingUid, Bundle args, int flags) { - if (mActiveSession != null) { - mActiveSession.cancel(); - mActiveSession = null; + public boolean showSessionLocked(int callingPid, int callingUid, Bundle args, int flags) { + if (mActiveSession == null) { + mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName, + mUser, mContext, this, callingPid, callingUid); } - mActiveSession = new SessionConnection(args, flags); + return mActiveSession.showLocked(args, flags); + } + + public boolean hideSessionLocked(int callingPid, int callingUid) { + return mActiveSession.hideLocked(); } public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token, @@ -270,14 +152,7 @@ class VoiceInteractionManagerServiceImpl { Slog.w(TAG, "deliverNewSession does not match active session"); return false; } - mActiveSession.mSession = session; - mActiveSession.mInteractor = interactor; - if (mActiveSession.mHaveAssistData) { - try { - session.handleAssist(mActiveSession.mAssistData); - } catch (RemoteException e) { - } - } + mActiveSession.deliverNewSessionLocked(session, interactor); return true; } @@ -367,4 +242,11 @@ class VoiceInteractionManagerServiceImpl { Slog.w(TAG, "RemoteException while calling soundModelsChanged", e); } } + + @Override + public void sessionConnectionGone(VoiceInteractionSessionConnection connection) { + synchronized (mLock) { + finishLocked(connection.mCallingPid, connection.mCallingUid, connection.mToken); + } + } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java new file mode 100644 index 0000000..e2b47c3 --- /dev/null +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2015 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 com.android.server.voiceinteraction; + +import android.app.ActivityManagerNative; +import android.app.IActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.service.voice.IVoiceInteractionSession; +import android.service.voice.IVoiceInteractionSessionService; +import android.service.voice.VoiceInteractionService; +import android.util.Slog; +import android.view.IWindowManager; +import android.view.WindowManager; +import com.android.internal.app.IVoiceInteractor; +import com.android.internal.os.IResultReceiver; + +import java.io.PrintWriter; + +final class VoiceInteractionSessionConnection implements ServiceConnection { + final static String TAG = "VoiceInteractionServiceManager"; + + final IBinder mToken = new Binder(); + final Object mLock; + final ComponentName mSessionComponentName; + final Intent mBindIntent; + final int mUser; + final Context mContext; + final Callback mCallback; + final int mCallingPid; + final int mCallingUid; + final IActivityManager mAm; + final IWindowManager mIWindowManager; + boolean mShown; + Bundle mShowArgs; + int mShowFlags; + boolean mBound; + boolean mFullyBound; + boolean mCanceled; + IVoiceInteractionSessionService mService; + IVoiceInteractionSession mSession; + IVoiceInteractor mInteractor; + boolean mHaveAssistData; + Bundle mAssistData; + + public interface Callback { + public void sessionConnectionGone(VoiceInteractionSessionConnection connection); + } + + final ServiceConnection mFullConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + } + @Override + public void onServiceDisconnected(ComponentName name) { + } + }; + + final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() { + @Override + public void send(int resultCode, Bundle resultData) throws RemoteException { + synchronized (mLock) { + if (mShown) { + if (mSession != null) { + try { + mSession.handleAssist(resultData); + } catch (RemoteException e) { + } + } else { + mHaveAssistData = true; + mAssistData = resultData; + } + } + } + } + }; + + public VoiceInteractionSessionConnection(Object lock, ComponentName component, int user, + Context context, Callback callback, int callingPid, int callingUid) { + mLock = lock; + mSessionComponentName = component; + mUser = user; + mContext = context; + mCallback = callback; + mCallingPid = callingPid; + mCallingUid = callingUid; + mAm = ActivityManagerNative.getDefault(); + mIWindowManager = IWindowManager.Stub.asInterface( + ServiceManager.getService(Context.WINDOW_SERVICE)); + mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE); + mBindIntent.setComponent(mSessionComponentName); + mBound = mContext.bindServiceAsUser(mBindIntent, this, + Context.BIND_AUTO_CREATE|Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser)); + if (mBound) { + try { + mIWindowManager.addWindowToken(mToken, + WindowManager.LayoutParams.TYPE_VOICE_INTERACTION); + } catch (RemoteException e) { + Slog.w(TAG, "Failed adding window token", e); + } + } else { + Slog.w(TAG, "Failed binding to voice interaction session service " + + mSessionComponentName); + } + } + + public boolean showLocked(Bundle args, int flags) { + if (mBound) { + if (!mFullyBound) { + mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection, + Context.BIND_AUTO_CREATE|Context.BIND_TREAT_LIKE_ACTIVITY, + new UserHandle(mUser)); + } + mShown = true; + mShowArgs = args; + mShowFlags = flags; + if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) { + try { + mAm.requestAssistContextExtras(0, mAssistReceiver); + } catch (RemoteException e) { + } + } else { + mHaveAssistData = false; + mAssistData = null; + } + if (mSession != null) { + try { + mSession.show(mShowArgs, mShowFlags); + mShowArgs = null; + mShowFlags = 0; + } catch (RemoteException e) { + } + if (mHaveAssistData) { + try { + mSession.handleAssist(mAssistData); + mAssistData = null; + mHaveAssistData = false; + } catch (RemoteException e) { + } + } + } + return true; + } + return false; + } + + public boolean hideLocked() { + if (mBound) { + if (mShown) { + mShown = false; + mShowArgs = null; + mShowFlags = 0; + mHaveAssistData = false; + mAssistData = null; + if (mSession != null) { + try { + mSession.hide(); + } catch (RemoteException e) { + } + } + } + if (mFullyBound) { + mContext.unbindService(mFullConnection); + mFullyBound = false; + } + return true; + } + return false; + } + + public boolean deliverNewSessionLocked(IVoiceInteractionSession session, + IVoiceInteractor interactor) { + mSession = session; + mInteractor = interactor; + if (mShown) { + try { + session.show(mShowArgs, mShowFlags); + mShowArgs = null; + mShowFlags = 0; + } catch (RemoteException e) { + } + if (mHaveAssistData) { + try { + session.handleAssist(mAssistData); + mAssistData = null; + mHaveAssistData = false; + } catch (RemoteException e) { + } + } + } + return true; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized (mLock) { + mService = IVoiceInteractionSessionService.Stub.asInterface(service); + if (!mCanceled) { + try { + mService.newSession(mToken, mShowArgs, mShowFlags); + } catch (RemoteException e) { + Slog.w(TAG, "Failed adding window token", e); + } + } + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + mCallback.sessionConnectionGone(this); + mService = null; + } + + public void cancel() { + mCanceled = true; + if (mBound) { + if (mSession != null) { + try { + mSession.destroy(); + } catch (RemoteException e) { + Slog.w(TAG, "Voice interation session already dead"); + } + } + if (mSession != null) { + try { + mAm.finishVoiceTask(mSession); + } catch (RemoteException e) { + } + } + mContext.unbindService(this); + try { + mIWindowManager.removeWindowToken(mToken); + } catch (RemoteException e) { + Slog.w(TAG, "Failed removing window token", e); + } + mBound = false; + mService = null; + mSession = null; + mInteractor = null; + } + if (mFullyBound) { + mContext.unbindService(mFullConnection); + mFullyBound = false; + } + } + + public void dump(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("mToken="); pw.println(mToken); + pw.print(prefix); pw.print("mShown="); pw.println(mShown); + pw.print(prefix); pw.print("mShowArgs="); pw.println(mShowArgs); + pw.print(prefix); pw.print("mShowFlags=0x"); pw.println(Integer.toHexString(mShowFlags)); + pw.print(prefix); pw.print("mBound="); pw.println(mBound); + if (mBound) { + pw.print(prefix); pw.print("mService="); pw.println(mService); + pw.print(prefix); pw.print("mSession="); pw.println(mSession); + pw.print(prefix); pw.print("mInteractor="); pw.println(mInteractor); + } + pw.print(prefix); pw.print("mHaveAssistData="); pw.println(mHaveAssistData); + if (mHaveAssistData) { + pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData); + } + } +}; |