From 57dd737443a174379eb638450e4888500d8e4a23 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 27 Jul 2015 18:11:14 -0700 Subject: Work on issue #21516866: Implement voice interaction in ResolverActivity The main change here is to not allow the dialog to go in to its "focus on the last app the user selected" when running in voice interaction mode, instead just always giving a simple list. This also fixes some problems with cleaning up active commands when an activity finishes and not forcing the current session to go away when the screen is turned off. Also added some debug help, having activity print the state of the voice interactor. Change-Id: Ifebee9c74d78398a730a280bb4970f47789dadf5 --- api/current.txt | 1 + api/system-current.txt | 1 + core/java/android/app/Activity.java | 8 +- core/java/android/app/VoiceInteractor.java | 166 ++++++++++++++++++++- .../service/voice/VoiceInteractionSession.java | 117 +++++++++++++++ .../voice/VoiceInteractionSessionService.java | 13 ++ .../com/android/internal/app/ResolverActivity.java | 9 +- .../com/android/server/dreams/DreamController.java | 4 +- .../VoiceInteractionManagerServiceImpl.java | 2 +- .../voiceinteraction/MainInteractionSession.java | 22 +++ 10 files changed, 337 insertions(+), 6 deletions(-) diff --git a/api/current.txt b/api/current.txt index 16c1880d9d22..b86e5d41f07c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28809,6 +28809,7 @@ package android.service.voice { ctor public VoiceInteractionSession(android.content.Context); ctor public VoiceInteractionSession(android.content.Context, android.os.Handler); method public void closeSystemDialogs(); + method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public void finish(); method public android.content.Context getContext(); method public int getDisabledShowContext(); diff --git a/api/system-current.txt b/api/system-current.txt index 7c473a98257c..b1642068fe55 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -30961,6 +30961,7 @@ package android.service.voice { ctor public VoiceInteractionSession(android.content.Context); ctor public VoiceInteractionSession(android.content.Context, android.os.Handler); method public void closeSystemDialogs(); + method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public void finish(); method public android.content.Context getContext(); method public int getDisabledShowContext(); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e49acfae7bed..bdea6088c529 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1864,7 +1864,10 @@ public class Activity extends ContextThemeWrapper nci.children = children; nci.fragments = fragments; nci.loaders = loaders; - nci.voiceInteractor = mVoiceInteractor; + if (mVoiceInteractor != null) { + mVoiceInteractor.retainInstance(); + nci.voiceInteractor = mVoiceInteractor; + } return nci; } @@ -5547,6 +5550,9 @@ public class Activity extends ContextThemeWrapper mFragments.dumpLoaders(innerPrefix, fd, writer, args); mFragments.getFragmentManager().dump(innerPrefix, fd, writer, args); + if (mVoiceInteractor != null) { + mVoiceInteractor.dump(innerPrefix, fd, writer, args); + } if (getWindow() != null && getWindow().peekDecorView() != null && diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java index bf7458c0c245..823c4271adf2 100644 --- a/core/java/android/app/VoiceInteractor.java +++ b/core/java/android/app/VoiceInteractor.java @@ -27,6 +27,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.util.ArrayMap; +import android.util.DebugUtils; import android.util.Log; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.IVoiceInteractorCallback; @@ -34,6 +35,8 @@ import com.android.internal.app.IVoiceInteractorRequest; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.ArrayList; /** @@ -68,6 +71,7 @@ public final class VoiceInteractor { Context mContext; Activity mActivity; + boolean mRetaining; final HandlerCaller mHandlerCaller; final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() { @@ -272,6 +276,29 @@ public final class VoiceInteractor { public void onDetached() { } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(128); + DebugUtils.buildShortClassTag(this, sb); + sb.append(" "); + sb.append(getRequestTypeName()); + sb.append(" name="); + sb.append(mName); + sb.append('}'); + return sb.toString(); + } + + void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + writer.print(prefix); writer.print("mRequestInterface="); + writer.println(mRequestInterface.asBinder()); + writer.print(prefix); writer.print("mActivity="); writer.println(mActivity); + writer.print(prefix); writer.print("mName="); writer.println(mName); + } + + String getRequestTypeName() { + return "Request"; + } + void clear() { mRequestInterface = null; mContext = null; @@ -333,6 +360,18 @@ public final class VoiceInteractor { public void onConfirmationResult(boolean confirmed, Bundle result) { } + void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + super.dump(prefix, fd, writer, args); + writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt); + if (mExtras != null) { + writer.print(prefix); writer.print("mExtras="); writer.println(mExtras); + } + } + + String getRequestTypeName() { + return "Confirmation"; + } + IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName, IVoiceInteractorCallback callback) throws RemoteException { return interactor.startConfirmation(packageName, callback, mPrompt, mExtras); @@ -515,6 +554,38 @@ public final class VoiceInteractor { public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) { } + void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + super.dump(prefix, fd, writer, args); + writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt); + if (mOptions != null) { + writer.print(prefix); writer.println("Options:"); + for (int i=0; i list = new ArrayList(N); + ArrayList list = new ArrayList<>(N); for (int i=0; i reqs = makeRequestList(); if (reqs != null) { @@ -807,6 +943,16 @@ public final class VoiceInteractor { req.mContext = null; } } + if (!mRetaining) { + reqs = makeRequestList(); + if (reqs != null) { + for (int i=0; i 0) { + writer.print(prefix); writer.println("Active voice requests:"); + for (int i=0; i payloadIntents, Intent[] initialIntents, List rList, boolean alwaysUseOption) { + // The last argument of createAdapter is whether to do special handling + // of the last used choice to highlight it in the list. We need to always + // turn this off when running under voice interaction, since it results in + // a more complicated UI that the current voice interaction flow is not able + // to handle. mAdapter = createAdapter(this, payloadIntents, initialIntents, rList, - mLaunchedFromUid, alwaysUseOption); + mLaunchedFromUid, alwaysUseOption && !isVoiceInteraction()); final int layoutId; if (mAdapter.hasFilteredItem()) { diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java index 81056757fb0a..206cc8a256d8 100644 --- a/services/core/java/com/android/server/dreams/DreamController.java +++ b/services/core/java/com/android/server/dreams/DreamController.java @@ -65,7 +65,7 @@ final class DreamController { private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - private final Intent mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + private final Intent mCloseNotificationShadeIntent; private DreamRecord mCurrentDream; @@ -92,6 +92,8 @@ final class DreamController { mHandler = handler; mListener = listener; mIWindowManager = WindowManagerGlobal.getWindowManagerService(); + mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + mCloseNotificationShadeIntent.putExtra("reason", "dream"); } public void dump(PrintWriter pw) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index a4facc1cb4f9..28520be8b7dc 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -72,7 +72,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne public void onReceive(Context context, Intent intent) { if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { String reason = intent.getStringExtra("reason"); - if (!CLOSE_REASON_VOICE_INTERACTION.equals(reason)) { + if (!CLOSE_REASON_VOICE_INTERACTION.equals(reason) && !"dream".equals(reason)) { synchronized (mLock) { if (mActiveSession != null && mActiveSession.mSession != null) { try { diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java index c0a67c189881..6e3694b345e9 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java @@ -72,6 +72,7 @@ public class MainInteractionSession extends VoiceInteractionSession VoiceInteractor.PickOptionRequest.Option[] mPendingOptions; CharSequence mPendingPrompt; Request mPendingRequest; + int mCurrentTask = -1; MainInteractionSession(Context context) { super(context); @@ -313,6 +314,27 @@ public class MainInteractionSession extends VoiceInteractionSession } } + @Override + public void onTaskStarted(Intent intent, int taskId) { + super.onTaskStarted(intent, taskId); + mCurrentTask = taskId; + } + + @Override + public void onTaskFinished(Intent intent, int taskId) { + super.onTaskFinished(intent, taskId); + if (mCurrentTask == taskId) { + mCurrentTask = -1; + } + } + + @Override + public void onLockscreenShown() { + if (mCurrentTask < 0) { + hide(); + } + } + @Override public boolean[] onGetSupportedCommands(String[] commands) { boolean[] res = new boolean[commands.length]; -- cgit v1.2.3-59-g8ed1b