diff options
10 files changed, 224 insertions, 33 deletions
diff --git a/api/current.txt b/api/current.txt index df9ea35..ea33eaf 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28785,11 +28785,13 @@ package android.service.voice { public class VoiceInteractionService extends android.app.Service { ctor public VoiceInteractionService(); method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback); + method public int getDisabledShowContext(); method public static boolean isActiveService(android.content.Context, android.content.ComponentName); method public android.os.IBinder onBind(android.content.Intent); method public void onLaunchVoiceAssistFromKeyguard(); method public void onReady(); method public void onShutdown(); + method public void setDisabledShowContext(int); method public void showSession(android.os.Bundle, int); field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService"; field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction"; @@ -28801,6 +28803,7 @@ package android.service.voice { method public void closeSystemDialogs(); method public void finish(); method public android.content.Context getContext(); + method public int getDisabledShowContext(); method public android.view.LayoutInflater getLayoutInflater(); method public android.app.Dialog getWindow(); method public void hide(); @@ -28832,6 +28835,7 @@ package android.service.voice { method public void onTaskStarted(android.content.Intent, int); method public void onTrimMemory(int); method public void setContentView(android.view.View); + method public void setDisabledShowContext(int); method public void setKeepAwake(boolean); method public void setTheme(int); method public void show(android.os.Bundle, int); diff --git a/api/system-current.txt b/api/system-current.txt index eb1c431..cbb1bb2 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -30934,11 +30934,13 @@ package android.service.voice { public class VoiceInteractionService extends android.app.Service { ctor public VoiceInteractionService(); method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback); + method public int getDisabledShowContext(); method public static boolean isActiveService(android.content.Context, android.content.ComponentName); method public android.os.IBinder onBind(android.content.Intent); method public void onLaunchVoiceAssistFromKeyguard(); method public void onReady(); method public void onShutdown(); + method public void setDisabledShowContext(int); method public void showSession(android.os.Bundle, int); field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService"; field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction"; @@ -30950,6 +30952,7 @@ package android.service.voice { method public void closeSystemDialogs(); method public void finish(); method public android.content.Context getContext(); + method public int getDisabledShowContext(); method public android.view.LayoutInflater getLayoutInflater(); method public android.app.Dialog getWindow(); method public void hide(); @@ -30981,6 +30984,7 @@ package android.service.voice { method public void onTaskStarted(android.content.Intent, int); method public void onTrimMemory(int); method public void setContentView(android.view.View); + method public void setDisabledShowContext(int); method public void setKeepAwake(boolean); method public void setTheme(int); method public void show(android.os.Bundle, int); diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 549c93e..479c9e2 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -37,7 +37,6 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Locale; - /** * Top-level service of the current global voice interactor, which is providing * support for hotwording, the back-end of a {@link android.app.VoiceInteractor}, etc. @@ -154,11 +153,39 @@ public class VoiceInteractionService extends Service { } /** + * Set contextual options you would always like to have disabled when a session + * is shown. The flags may be any combination of + * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and + * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT + * VoiceInteractionSession.SHOW_WITH_SCREENSHOT}. + */ + public void setDisabledShowContext(int flags) { + try { + mSystemService.setDisabledShowContext(flags); + } catch (RemoteException e) { + } + } + + /** + * Return the value set by {@link #setDisabledShowContext}. + */ + public int getDisabledShowContext() { + try { + return mSystemService.getDisabledShowContext(); + } catch (RemoteException e) { + return 0; + } + } + + /** * Request that the associated {@link android.service.voice.VoiceInteractionSession} be * shown to the user, starting it if necessary. * @param args Arbitrary arguments that will be propagated to the session. * @param flags Indicates additional optional behavior that should be performed. May - * be {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} + * be any combination of + * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and + * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT + * VoiceInteractionSession.SHOW_WITH_SCREENSHOT} * to request that the system generate and deliver assist data on the current foreground * app as part of showing the session UI. */ diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index 5b87440..95f96e8 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -913,12 +913,38 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } /** + * Equivalent to {@link VoiceInteractionService#setDisabledShowContext + * VoiceInteractionService.setDisabledShowContext(int)}. + */ + public void setDisabledShowContext(int flags) { + try { + mSystemService.setDisabledShowContext(flags); + } catch (RemoteException e) { + } + } + + /** + * Equivalent to {@link VoiceInteractionService#getDisabledShowContext + * VoiceInteractionService.getDisabledShowContext}. + */ + public int getDisabledShowContext() { + try { + return mSystemService.getDisabledShowContext(); + } catch (RemoteException e) { + return 0; + } + } + + /** * Show the UI for this session. This asks the system to go through the process of showing * your UI, which will eventually culminate in {@link #onShow}. This is similar to calling * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}. * @param args Arbitrary arguments that will be propagated {@link #onShow}. * @param flags Indicates additional optional behavior that should be performed. May - * be {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} + * be any combination of + * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and + * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT + * VoiceInteractionSession.SHOW_WITH_SCREENSHOT} * to request that the system generate and deliver assist data on the current foreground * app as part of showing the session UI. */ diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 7f54f50..73ad981 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -37,6 +37,8 @@ interface IVoiceInteractionManagerService { void setKeepAwake(IBinder token, boolean keepAwake); void closeSystemDialogs(IBinder token); void finish(IBinder token); + void setDisabledShowContext(int flags); + int getDisabledShowContext(); /** * Gets the registered Sound model for keyphrase detection for the current user. diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 36478da..42f879c 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -578,6 +578,44 @@ public class VoiceInteractionManagerService extends SystemService { } } + @Override + public void setDisabledShowContext(int flags) { + synchronized (this) { + if (mImpl == null) { + Slog.w(TAG, "setDisabledShowContext without running voice interaction service"); + return; + } + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); + final long caller = Binder.clearCallingIdentity(); + try { + mImpl.setDisabledShowContextLocked(callingPid, callingUid, flags); + } finally { + Binder.restoreCallingIdentity(caller); + } + } + + } + + @Override + public int getDisabledShowContext() { + synchronized (this) { + if (mImpl == null) { + Slog.w(TAG, "getDisabledShowContext without running voice interaction service"); + return 0; + } + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); + final long caller = Binder.clearCallingIdentity(); + try { + return mImpl.getDisabledShowContextLocked(callingPid, callingUid); + } finally { + Binder.restoreCallingIdentity(caller); + } + } + + } + //----------------- Model management APIs --------------------------------// @Override diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index e5faf4d..7409f99 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -65,6 +65,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne IVoiceInteractionService mService; VoiceInteractionSessionConnection mActiveSession; + int mDisabledShowContext; final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -146,7 +147,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName, mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler); } - return mActiveSession.showLocked(args, flags, showCallback); + return mActiveSession.showLocked(args, flags, mDisabledShowContext, showCallback); } public boolean hideSessionLocked() { @@ -222,6 +223,24 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne mActiveSession = null; } + public void setDisabledShowContextLocked(int callingPid, int callingUid, int flags) { + int activeUid = mInfo.getServiceInfo().applicationInfo.uid; + if (callingUid != activeUid) { + throw new SecurityException("Calling uid " + callingUid + + " does not match active uid " + activeUid); + } + mDisabledShowContext = flags; + } + + public int getDisabledShowContextLocked(int callingPid, int callingUid) { + int activeUid = mInfo.getServiceInfo().applicationInfo.uid; + if (callingUid != activeUid) { + throw new SecurityException("Calling uid " + callingUid + + " does not match active uid " + activeUid); + } + return mDisabledShowContext; + } + public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) { if (!mValid) { pw.print(" NOT VALID: "); @@ -235,6 +254,10 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne pw.print(" mComponent="); pw.println(mComponent.flattenToShortString()); pw.print(" Session service="); pw.println(mInfo.getSessionService()); pw.print(" Settings activity="); pw.println(mInfo.getSettingsActivity()); + if (mDisabledShowContext != 0) { + pw.print(" mDisabledShowContext="); + pw.println(Integer.toHexString(mDisabledShowContext)); + } pw.print(" mBound="); pw.print(mBound); pw.print(" mService="); pw.println(mService); if (mActiveSession != null) { pw.println(" Active session:"); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index bd043ac..dfdd639 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -183,7 +183,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { } } - public boolean showLocked(Bundle args, int flags, + public boolean showLocked(Bundle args, int flags, int disabledContext, IVoiceInteractionSessionShowCallback showCallback) { if (mBound) { if (!mFullyBound) { @@ -200,15 +200,17 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { } boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0 - && isScreenCaptureAllowed; + && isScreenCaptureAllowed + && (disabledContext&VoiceInteractionSession.SHOW_WITH_ASSIST) == 0; boolean screenshotEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1, mUser) != 0 - && isScreenCaptureAllowed; + && isScreenCaptureAllowed + && (disabledContext&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0; mShowArgs = args; mShowFlags = flags; mHaveAssistData = false; boolean needDisclosure = false; - if ((flags& VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) { + if ((flags&VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) { if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid, mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED && structureEnabled) { @@ -226,7 +228,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mAssistData = null; } mHaveScreenshot = false; - if ((flags& VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) { + if ((flags&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) { if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_SCREENSHOT, mCallingUid, mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED && screenshotEnabled) { diff --git a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml index 610f30b..dc4e31b 100644 --- a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml +++ b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml @@ -31,33 +31,56 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> - <LinearLayout android:id="@+id/top_content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="top" - android:orientation="horizontal" - android:background="#ffffffff" - android:elevation="8dp" - > - <ImageView android:id="@+id/screenshot" - android:layout_width="wrap_content" - android:layout_height="46dp" - android:adjustViewBounds="true" /> - <View android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1" /> - <Button android:id="@+id/do_tree" - android:layout_width="wrap_content" + <LinearLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/tree" /> - <Button android:id="@+id/do_text" - android:layout_width="wrap_content" + android:layout_gravity="top" + android:orientation="vertical" + android:background="#ffffffff" + android:elevation="8dp" + > + <LinearLayout android:id="@+id/top_content" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/text" /> - <Button android:id="@+id/start" - android:layout_width="wrap_content" + android:orientation="horizontal" + > + <ImageView android:id="@+id/screenshot" + android:layout_width="wrap_content" + android:layout_height="46dp" + android:adjustViewBounds="true" /> + <View android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="1" /> + <CheckBox android:id="@+id/show_options" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + <Button android:id="@+id/do_tree" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/tree" /> + <Button android:id="@+id/do_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/text" /> + <Button android:id="@+id/start" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/start" /> + </LinearLayout> + <LinearLayout android:id="@+id/options" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/start" /> + android:orientation="vertical" + > + <CheckBox android:id="@+id/disallow_structure" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Disallow context" /> + <CheckBox android:id="@+id/disallow_screenshot" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Disallow screenshot" /> + </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/bottom_content" diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java index a6585ba..8796c9f 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java @@ -29,6 +29,7 @@ import android.service.voice.VoiceInteractionSession; import android.util.Log; import android.view.View; import android.widget.Button; +import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView; @@ -45,6 +46,10 @@ public class MainInteractionSession extends VoiceInteractionSession Button mTreeButton; Button mTextButton; Button mStartButton; + CheckBox mOptionsCheck; + View mOptionsContainer; + CheckBox mDisallowAssist; + CheckBox mDisallowScreenshot; ImageView mScreenshot; ImageView mFullScreenshot; Button mConfirmButton; @@ -122,15 +127,34 @@ public class MainInteractionSession extends VoiceInteractionSession mScreenshot = (ImageView)mContentView.findViewById(R.id.screenshot); mScreenshot.setOnClickListener(this); mFullScreenshot = (ImageView)mContentView.findViewById(R.id.full_screenshot); + mOptionsCheck = (CheckBox)mContentView.findViewById(R.id.show_options); + mOptionsCheck.setOnClickListener(this); + mOptionsContainer = mContentView.findViewById(R.id.options); + mDisallowAssist = (CheckBox)mContentView.findViewById(R.id.disallow_structure); + mDisallowAssist.setOnClickListener(this); + mDisallowScreenshot = (CheckBox)mContentView.findViewById(R.id.disallow_screenshot); + mDisallowScreenshot.setOnClickListener(this); mConfirmButton = (Button)mContentView.findViewById(R.id.confirm); mConfirmButton.setOnClickListener(this); mCompleteButton = (Button)mContentView.findViewById(R.id.complete); mCompleteButton.setOnClickListener(this); mAbortButton = (Button)mContentView.findViewById(R.id.abort); mAbortButton.setOnClickListener(this); + refreshOptions(); return mContentView; } + void refreshOptions() { + if (mOptionsCheck.isChecked()) { + mOptionsContainer.setVisibility(View.VISIBLE); + int flags = getDisabledShowContext(); + mDisallowAssist.setChecked((flags & SHOW_WITH_ASSIST) != 0); + mDisallowScreenshot.setChecked((flags & SHOW_WITH_SCREENSHOT) != 0); + } else { + mOptionsContainer.setVisibility(View.GONE); + } + } + public void onHandleAssist(Bundle assistBundle) { } @@ -202,6 +226,24 @@ public class MainInteractionSession extends VoiceInteractionSession if (mAssistVisualizer != null) { mAssistVisualizer.logText(); } + } else if (v == mOptionsCheck) { + refreshOptions(); + } else if (v == mDisallowAssist) { + int flags = getDisabledShowContext(); + if (mDisallowAssist.isChecked()) { + flags |= SHOW_WITH_ASSIST; + } else { + flags &= ~SHOW_WITH_ASSIST; + } + setDisabledShowContext(flags); + } else if (v == mDisallowScreenshot) { + int flags = getDisabledShowContext(); + if (mDisallowScreenshot.isChecked()) { + flags |= SHOW_WITH_SCREENSHOT; + } else { + flags &= ~SHOW_WITH_SCREENSHOT; + } + setDisabledShowContext(flags); } else if (v == mStartButton) { mState = STATE_LAUNCHING; updateState(); |