Skip to content

Commit 57dd737

Browse files
author
Dianne Hackborn
committed
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
1 parent e827c25 commit 57dd737

10 files changed

Lines changed: 337 additions & 6 deletions

File tree

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28809,6 +28809,7 @@ package android.service.voice {
2880928809
ctor public VoiceInteractionSession(android.content.Context);
2881028810
ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
2881128811
method public void closeSystemDialogs();
28812+
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
2881228813
method public void finish();
2881328814
method public android.content.Context getContext();
2881428815
method public int getDisabledShowContext();

api/system-current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30961,6 +30961,7 @@ package android.service.voice {
3096130961
ctor public VoiceInteractionSession(android.content.Context);
3096230962
ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
3096330963
method public void closeSystemDialogs();
30964+
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
3096430965
method public void finish();
3096530966
method public android.content.Context getContext();
3096630967
method public int getDisabledShowContext();

core/java/android/app/Activity.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1864,7 +1864,10 @@ NonConfigurationInstances retainNonConfigurationInstances() {
18641864
nci.children = children;
18651865
nci.fragments = fragments;
18661866
nci.loaders = loaders;
1867-
nci.voiceInteractor = mVoiceInteractor;
1867+
if (mVoiceInteractor != null) {
1868+
mVoiceInteractor.retainInstance();
1869+
nci.voiceInteractor = mVoiceInteractor;
1870+
}
18681871
return nci;
18691872
}
18701873

@@ -5547,6 +5550,9 @@ void dumpInner(String prefix, FileDescriptor fd, PrintWriter writer, String[] ar
55475550

55485551
mFragments.dumpLoaders(innerPrefix, fd, writer, args);
55495552
mFragments.getFragmentManager().dump(innerPrefix, fd, writer, args);
5553+
if (mVoiceInteractor != null) {
5554+
mVoiceInteractor.dump(innerPrefix, fd, writer, args);
5555+
}
55505556

55515557
if (getWindow() != null &&
55525558
getWindow().peekDecorView() != null &&

core/java/android/app/VoiceInteractor.java

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,16 @@
2727
import android.os.Parcelable;
2828
import android.os.RemoteException;
2929
import android.util.ArrayMap;
30+
import android.util.DebugUtils;
3031
import android.util.Log;
3132
import com.android.internal.app.IVoiceInteractor;
3233
import com.android.internal.app.IVoiceInteractorCallback;
3334
import com.android.internal.app.IVoiceInteractorRequest;
3435
import com.android.internal.os.HandlerCaller;
3536
import com.android.internal.os.SomeArgs;
3637

38+
import java.io.FileDescriptor;
39+
import java.io.PrintWriter;
3740
import java.util.ArrayList;
3841

3942
/**
@@ -68,6 +71,7 @@ public final class VoiceInteractor {
6871

6972
Context mContext;
7073
Activity mActivity;
74+
boolean mRetaining;
7175

7276
final HandlerCaller mHandlerCaller;
7377
final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
@@ -272,6 +276,29 @@ public void onAttached(Activity activity) {
272276
public void onDetached() {
273277
}
274278

279+
@Override
280+
public String toString() {
281+
StringBuilder sb = new StringBuilder(128);
282+
DebugUtils.buildShortClassTag(this, sb);
283+
sb.append(" ");
284+
sb.append(getRequestTypeName());
285+
sb.append(" name=");
286+
sb.append(mName);
287+
sb.append('}');
288+
return sb.toString();
289+
}
290+
291+
void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
292+
writer.print(prefix); writer.print("mRequestInterface=");
293+
writer.println(mRequestInterface.asBinder());
294+
writer.print(prefix); writer.print("mActivity="); writer.println(mActivity);
295+
writer.print(prefix); writer.print("mName="); writer.println(mName);
296+
}
297+
298+
String getRequestTypeName() {
299+
return "Request";
300+
}
301+
275302
void clear() {
276303
mRequestInterface = null;
277304
mContext = null;
@@ -333,6 +360,18 @@ public ConfirmationRequest(CharSequence prompt, Bundle extras) {
333360
public void onConfirmationResult(boolean confirmed, Bundle result) {
334361
}
335362

363+
void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
364+
super.dump(prefix, fd, writer, args);
365+
writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
366+
if (mExtras != null) {
367+
writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
368+
}
369+
}
370+
371+
String getRequestTypeName() {
372+
return "Confirmation";
373+
}
374+
336375
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
337376
IVoiceInteractorCallback callback) throws RemoteException {
338377
return interactor.startConfirmation(packageName, callback, mPrompt, mExtras);
@@ -515,6 +554,38 @@ public PickOptionRequest(CharSequence prompt, Option[] options, Bundle extras) {
515554
public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
516555
}
517556

557+
void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
558+
super.dump(prefix, fd, writer, args);
559+
writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
560+
if (mOptions != null) {
561+
writer.print(prefix); writer.println("Options:");
562+
for (int i=0; i<mOptions.length; i++) {
563+
Option op = mOptions[i];
564+
writer.print(prefix); writer.print(" #"); writer.print(i); writer.println(":");
565+
writer.print(prefix); writer.print(" mLabel="); writer.println(op.mLabel);
566+
writer.print(prefix); writer.print(" mIndex="); writer.println(op.mIndex);
567+
if (op.mSynonyms != null && op.mSynonyms.size() > 0) {
568+
writer.print(prefix); writer.println(" Synonyms:");
569+
for (int j=0; j<op.mSynonyms.size(); j++) {
570+
writer.print(prefix); writer.print(" #"); writer.print(j);
571+
writer.print(": "); writer.println(op.mSynonyms.get(j));
572+
}
573+
}
574+
if (op.mExtras != null) {
575+
writer.print(prefix); writer.print(" mExtras=");
576+
writer.println(op.mExtras);
577+
}
578+
}
579+
}
580+
if (mExtras != null) {
581+
writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
582+
}
583+
}
584+
585+
String getRequestTypeName() {
586+
return "PickOption";
587+
}
588+
518589
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
519590
IVoiceInteractorCallback callback) throws RemoteException {
520591
return interactor.startPickOption(packageName, callback, mPrompt, mOptions, mExtras);
@@ -560,6 +631,18 @@ public CompleteVoiceRequest(CharSequence message, Bundle extras) {
560631
public void onCompleteResult(Bundle result) {
561632
}
562633

634+
void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
635+
super.dump(prefix, fd, writer, args);
636+
writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
637+
if (mExtras != null) {
638+
writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
639+
}
640+
}
641+
642+
String getRequestTypeName() {
643+
return "CompleteVoice";
644+
}
645+
563646
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
564647
IVoiceInteractorCallback callback) throws RemoteException {
565648
return interactor.startCompleteVoice(packageName, callback, mPrompt, mExtras);
@@ -607,6 +690,18 @@ public AbortVoiceRequest(CharSequence message, Bundle extras) {
607690
public void onAbortResult(Bundle result) {
608691
}
609692

693+
void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
694+
super.dump(prefix, fd, writer, args);
695+
writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
696+
if (mExtras != null) {
697+
writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
698+
}
699+
}
700+
701+
String getRequestTypeName() {
702+
return "AbortVoice";
703+
}
704+
610705
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
611706
IVoiceInteractorCallback callback) throws RemoteException {
612707
return interactor.startAbortVoice(packageName, callback, mPrompt, mExtras);
@@ -650,6 +745,18 @@ public CommandRequest(String command, Bundle args) {
650745
public void onCommandResult(boolean isCompleted, Bundle result) {
651746
}
652747

748+
void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
749+
super.dump(prefix, fd, writer, args);
750+
writer.print(prefix); writer.print("mCommand="); writer.println(mCommand);
751+
if (mArgs != null) {
752+
writer.print(prefix); writer.print("mArgs="); writer.println(mArgs);
753+
}
754+
}
755+
756+
String getRequestTypeName() {
757+
return "Command";
758+
}
759+
653760
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
654761
IVoiceInteractorCallback callback) throws RemoteException {
655762
return interactor.startCommand(packageName, callback, mCommand, mArgs);
@@ -721,6 +828,30 @@ public CharSequence getVisualPrompt() {
721828
return mVisualPrompt;
722829
}
723830

831+
@Override
832+
public String toString() {
833+
StringBuilder sb = new StringBuilder(128);
834+
DebugUtils.buildShortClassTag(this, sb);
835+
if (mVisualPrompt != null && mVoicePrompts != null && mVoicePrompts.length == 1
836+
&& mVisualPrompt.equals(mVoicePrompts[0])) {
837+
sb.append(" ");
838+
sb.append(mVisualPrompt);
839+
} else {
840+
if (mVisualPrompt != null) {
841+
sb.append(" visual="); sb.append(mVisualPrompt);
842+
}
843+
if (mVoicePrompts != null) {
844+
sb.append(", voice=");
845+
for (int i=0; i<mVoicePrompts.length; i++) {
846+
if (i > 0) sb.append(" | ");
847+
sb.append(mVoicePrompts[i]);
848+
}
849+
}
850+
}
851+
sb.append('}');
852+
return sb.toString();
853+
}
854+
724855
/** Constructor to support Parcelable behavior. */
725856
Prompt(Parcel in) {
726857
mVoicePrompts = in.readCharSequenceArray();
@@ -773,14 +904,15 @@ private ArrayList<Request> makeRequestList() {
773904
if (N < 1) {
774905
return null;
775906
}
776-
ArrayList<Request> list = new ArrayList<Request>(N);
907+
ArrayList<Request> list = new ArrayList<>(N);
777908
for (int i=0; i<N; i++) {
778909
list.add(mActiveRequests.valueAt(i));
779910
}
780911
return list;
781912
}
782913

783914
void attachActivity(Activity activity) {
915+
mRetaining = false;
784916
if (mActivity == activity) {
785917
return;
786918
}
@@ -797,6 +929,10 @@ void attachActivity(Activity activity) {
797929
}
798930
}
799931

932+
void retainInstance() {
933+
mRetaining = true;
934+
}
935+
800936
void detachActivity() {
801937
ArrayList<Request> reqs = makeRequestList();
802938
if (reqs != null) {
@@ -807,6 +943,16 @@ void detachActivity() {
807943
req.mContext = null;
808944
}
809945
}
946+
if (!mRetaining) {
947+
reqs = makeRequestList();
948+
if (reqs != null) {
949+
for (int i=0; i<reqs.size(); i++) {
950+
Request req = reqs.get(i);
951+
req.cancel();
952+
}
953+
}
954+
mActiveRequests.clear();
955+
}
810956
mContext = null;
811957
mActivity = null;
812958
}
@@ -902,4 +1048,22 @@ public boolean[] supportsCommands(String[] commands) {
9021048
throw new RuntimeException("Voice interactor has died", e);
9031049
}
9041050
}
1051+
1052+
void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
1053+
String innerPrefix = prefix + " ";
1054+
if (mActiveRequests.size() > 0) {
1055+
writer.print(prefix); writer.println("Active voice requests:");
1056+
for (int i=0; i<mActiveRequests.size(); i++) {
1057+
Request req = mActiveRequests.valueAt(i);
1058+
writer.print(prefix); writer.print(" #"); writer.print(i);
1059+
writer.print(": ");
1060+
writer.println(req);
1061+
req.dump(innerPrefix, fd, writer, args);
1062+
}
1063+
}
1064+
writer.print(prefix); writer.println("VoiceInteractor misc state:");
1065+
writer.print(prefix); writer.print(" mInteractor=");
1066+
writer.println(mInteractor.asBinder());
1067+
writer.print(prefix); writer.print(" mActivity="); writer.println(mActivity);
1068+
}
9051069
}

0 commit comments

Comments
 (0)