From 59da805846034a4939b014f469d7383285c75aab Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 6 Feb 2017 17:42:41 -0800 Subject: [PATCH] Add new VoiceInteractionSession.setUiEnabled method This allows the session to turn off all of its UI. Use it in onCreate() to prevent the session from ever creating any of its UI. Switched the window creation and initialization to happen lazily to support this. Test: New test added to android.assist.cts.LifecycleTest Bug: 30999386 Change-Id: I8eacb3697c8ac9908c50b9577abea2d20597b016 --- api/current.txt | 2 + api/system-current.txt | 2 + api/test-current.txt | 2 + .../voice/VoiceInteractionSession.java | 138 +++++++++++++----- .../MainInteractionSession.java | 31 ++-- 5 files changed, 124 insertions(+), 51 deletions(-) diff --git a/api/current.txt b/api/current.txt index de5486907589b..d86748b3480c9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -36758,6 +36758,7 @@ package android.service.voice { method public boolean onKeyUp(int, android.view.KeyEvent); method public void onLockscreenShown(); method public void onLowMemory(); + method public void onPrepareShow(android.os.Bundle, int); method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest); method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest); method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest); @@ -36771,6 +36772,7 @@ package android.service.voice { method public void setDisabledShowContext(int); method public void setKeepAwake(boolean); method public void setTheme(int); + method public void setUiEnabled(boolean); method public void show(android.os.Bundle, int); method public void startVoiceActivity(android.content.Intent); field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10 diff --git a/api/system-current.txt b/api/system-current.txt index bdf06db863fc8..4b361d6f72fc3 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -39856,6 +39856,7 @@ package android.service.voice { method public boolean onKeyUp(int, android.view.KeyEvent); method public void onLockscreenShown(); method public void onLowMemory(); + method public void onPrepareShow(android.os.Bundle, int); method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest); method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest); method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest); @@ -39869,6 +39870,7 @@ package android.service.voice { method public void setDisabledShowContext(int); method public void setKeepAwake(boolean); method public void setTheme(int); + method public void setUiEnabled(boolean); method public void show(android.os.Bundle, int); method public void startVoiceActivity(android.content.Intent); field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10 diff --git a/api/test-current.txt b/api/test-current.txt index 0f6502b6daeda..3005e3222adfa 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -36893,6 +36893,7 @@ package android.service.voice { method public boolean onKeyUp(int, android.view.KeyEvent); method public void onLockscreenShown(); method public void onLowMemory(); + method public void onPrepareShow(android.os.Bundle, int); method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest); method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest); method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest); @@ -36906,6 +36907,7 @@ package android.service.voice { method public void setDisabledShowContext(int); method public void setKeepAwake(boolean); method public void setTheme(int); + method public void setUiEnabled(boolean); method public void show(android.os.Bundle, int); method public void startVoiceActivity(android.content.Intent); field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10 diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index e9bbc2de26cc3..ca736e346761e 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -135,6 +135,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall FrameLayout mContentFrame; SoftInputWindow mWindow; + boolean mUiEnabled = true; boolean mInitialized; boolean mWindowAdded; boolean mWindowVisible; @@ -1001,35 +1002,40 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall try { mInShowWindow = true; + onPrepareShow(args, flags); if (!mWindowVisible) { - if (!mWindowAdded) { - mWindowAdded = true; - View v = onCreateContentView(); - if (v != null) { - setContentView(v); - } - } + ensureWindowAdded(); } onShow(args, flags); if (!mWindowVisible) { mWindowVisible = true; - mWindow.show(); + if (mUiEnabled) { + mWindow.show(); + } } if (showCallback != null) { - mRootView.invalidate(); - mRootView.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - mRootView.getViewTreeObserver().removeOnPreDrawListener(this); - try { - showCallback.onShown(); - } catch (RemoteException e) { - Log.w(TAG, "Error calling onShown", e); + if (mUiEnabled) { + mRootView.invalidate(); + mRootView.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mRootView.getViewTreeObserver().removeOnPreDrawListener(this); + try { + showCallback.onShown(); + } catch (RemoteException e) { + Log.w(TAG, "Error calling onShown", e); + } + return true; } - return true; - } - }); + }); + } else { + try { + showCallback.onShown(); + } catch (RemoteException e) { + Log.w(TAG, "Error calling onShown", e); + } + } } } finally { mWindowWasVisible = true; @@ -1039,7 +1045,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall void doHide() { if (mWindowVisible) { - mWindow.hide(); + ensureWindowHidden(); mWindowVisible = false; onHide(); } @@ -1058,19 +1064,56 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } - void initViews() { + void ensureWindowCreated() { + if (mInitialized) { + return; + } + + if (!mUiEnabled) { + throw new IllegalStateException("setUiEnabled is false"); + } + mInitialized = true; + mInflater = (LayoutInflater)mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme, + mCallbacks, this, mDispatcherState, + WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true); + mWindow.getWindow().addFlags( + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | + WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); mThemeAttrs = mContext.obtainStyledAttributes(android.R.styleable.VoiceInteractionSession); mRootView = mInflater.inflate( com.android.internal.R.layout.voice_interaction_session, null); mRootView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); mWindow.setContentView(mRootView); mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer); mContentFrame = (FrameLayout)mRootView.findViewById(android.R.id.content); + + mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT); + mWindow.setToken(mToken); + } + + void ensureWindowAdded() { + if (mUiEnabled && !mWindowAdded) { + mWindowAdded = true; + ensureWindowCreated(); + View v = onCreateContentView(); + if (v != null) { + setContentView(v); + } + } + } + + void ensureWindowHidden() { + if (mWindow != null) { + mWindow.hide(); + } } /** @@ -1150,6 +1193,24 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } + /** + * Control whether the UI layer for this session is enabled. It is enabled by default. + * If set to false, you will not be able to provide a UI through {@link #onCreateContentView()}. + */ + public void setUiEnabled(boolean enabled) { + if (mUiEnabled != enabled) { + mUiEnabled = enabled; + if (mWindowVisible) { + if (enabled) { + ensureWindowAdded(); + mWindow.show(); + } else { + ensureWindowHidden(); + } + } + } + } + /** * You can call this to customize the theme used by your IME's window. * This must be set before {@link #onCreate}, so you @@ -1242,6 +1303,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * Convenience for inflating views. */ public LayoutInflater getLayoutInflater() { + ensureWindowCreated(); return mInflater; } @@ -1249,6 +1311,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * Retrieve the window being used to show the session's UI. */ public Dialog getWindow() { + ensureWindowCreated(); return mWindow; } @@ -1278,18 +1341,17 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall private void doOnCreate() { mTheme = mTheme != 0 ? mTheme : com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession; - mInflater = (LayoutInflater)mContext.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme, - mCallbacks, this, mDispatcherState, - WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true); - mWindow.getWindow().addFlags( - WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | - WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); - initViews(); - mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT); - mWindow.setToken(mToken); + } + + /** + * Called prior to {@link #onShow} before any UI setup has occurred. Not generally useful. + * + * @param args The arguments that were supplied to + * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}. + * @param showFlags The show flags originally provided to + * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}. + */ + public void onPrepareShow(Bundle args, int showFlags) { } /** @@ -1327,6 +1389,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } public void setContentView(View view) { + ensureWindowCreated(); mContentFrame.removeAllViews(); mContentFrame.addView(view, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, @@ -1623,7 +1686,8 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { writer.print(prefix); writer.print("mToken="); writer.println(mToken); writer.print(prefix); writer.print("mTheme=#"); writer.println(Integer.toHexString(mTheme)); - writer.print(prefix); writer.print("mInitialized="); writer.println(mInitialized); + writer.print(prefix); writer.print("mUiEnabled="); writer.println(mUiEnabled); + writer.print(" mInitialized="); writer.println(mInitialized); writer.print(prefix); writer.print("mWindowAdded="); writer.print(mWindowAdded); writer.print(" mWindowVisible="); writer.println(mWindowVisible); writer.print(prefix); writer.print("mWindowWasVisible="); writer.print(mWindowWasVisible); diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java index 5767f110f0a49..0401737924066 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java @@ -172,12 +172,10 @@ public class MainInteractionSession extends VoiceInteractionSession @Override public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) { mAssistStructure = structure; - if (mAssistStructure != null) { - if (mAssistVisualizer != null) { + if (mAssistVisualizer != null) { + if (mAssistStructure != null) { mAssistVisualizer.setAssistStructure(mAssistStructure); - } - } else { - if (mAssistVisualizer != null) { + } else { mAssistVisualizer.clearAssistData(); } } @@ -207,19 +205,24 @@ public class MainInteractionSession extends VoiceInteractionSession @Override public void onHandleScreenshot(Bitmap screenshot) { - if (screenshot != null) { - mScreenshot.setImageBitmap(screenshot); - mScreenshot.setAdjustViewBounds(true); - mScreenshot.setMaxWidth(screenshot.getWidth() / 3); - mScreenshot.setMaxHeight(screenshot.getHeight() / 3); - mFullScreenshot.setImageBitmap(screenshot); - } else { - mScreenshot.setImageDrawable(null); - mFullScreenshot.setImageDrawable(null); + if (mScreenshot != null) { + if (screenshot != null) { + mScreenshot.setImageBitmap(screenshot); + mScreenshot.setAdjustViewBounds(true); + mScreenshot.setMaxWidth(screenshot.getWidth() / 3); + mScreenshot.setMaxHeight(screenshot.getHeight() / 3); + mFullScreenshot.setImageBitmap(screenshot); + } else { + mScreenshot.setImageDrawable(null); + mFullScreenshot.setImageDrawable(null); + } } } void updateState() { + if (mTopContent == null) { + return; + } if (mState == STATE_IDLE) { mTopContent.setVisibility(View.VISIBLE); mBottomContent.setVisibility(View.GONE);