summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorim Jaggi <jjaggi@google.com>2015-04-01 11:18:57 -0700
committerJorim Jaggi <jjaggi@google.com>2015-04-03 11:12:03 -0700
commit225d3b5449d29b43e619d8538d024305f6e81ba9 (patch)
tree1b51b10b43df82fe733b89989b6fd765469f78a0
parent25e12abc5b8a4aa83cfa150094fd145b777e6e03 (diff)
downloadframeworks_base-225d3b5449d29b43e619d8538d024305f6e81ba9.zip
frameworks_base-225d3b5449d29b43e619d8538d024305f6e81ba9.tar.gz
frameworks_base-225d3b5449d29b43e619d8538d024305f6e81ba9.tar.bz2
Add more internal API's for assist
- When starting a voice interaction session from SysUI, a callback can be passed to know when voice interaction has successfully started - Add a new window type for the voice interaction starting window, which resides behind the voice interaction layer. - SystemUI now also inspects the voice interaction service to get the logo asset for the starting window. - Make VoiceInteractionSession window fullscreen, to accomodate for the visuals. Change-Id: If8c3c445e8b39841f48e8d153e6d1ba81e447286
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/service/voice/IVoiceInteractionSession.aidl4
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java42
-rw-r--r--core/java/android/view/WindowManager.java7
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl11
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl22
-rw-r--r--packages/SystemUI/src/com/android/systemui/SearchPanelView.java39
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java21
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java26
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java6
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java57
11 files changed, 199 insertions, 37 deletions
diff --git a/Android.mk b/Android.mk
index f7f3652..f9ac712 100644
--- a/Android.mk
+++ b/Android.mk
@@ -267,6 +267,7 @@ LOCAL_SRC_FILES += \
core/java/com/android/internal/app/IBatteryStats.aidl \
core/java/com/android/internal/app/IProcessStats.aidl \
core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \
+ core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl \
core/java/com/android/internal/app/IVoiceInteractor.aidl \
core/java/com/android/internal/app/IVoiceInteractorCallback.aidl \
core/java/com/android/internal/app/IVoiceInteractorRequest.aidl \
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index 4f4b2d5..7c90261 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -20,11 +20,13 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
+
/**
* @hide
*/
oneway interface IVoiceInteractionSession {
- void show(in Bundle sessionArgs, int flags);
+ void show(in Bundle sessionArgs, int flags, IVoiceInteractionSessionShowCallback showCallback);
void hide();
void handleAssist(in Bundle assistData);
void handleScreenshot(in Bitmap screenshot);
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 3245f55..bb985b4 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -43,6 +43,7 @@ import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.IVoiceInteractorCallback;
import com.android.internal.app.IVoiceInteractorRequest;
@@ -163,9 +164,10 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() {
@Override
- public void show(Bundle sessionArgs, int flags) {
- mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_SHOW,
- flags, sessionArgs));
+ public void show(Bundle sessionArgs, int flags,
+ IVoiceInteractionSessionShowCallback showCallback) {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(MSG_SHOW,
+ flags, sessionArgs, showCallback));
}
@Override
@@ -412,9 +414,12 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
onHandleScreenshot((Bitmap) msg.obj);
break;
case MSG_SHOW:
- if (DEBUG) Log.d(TAG, "doShow: args=" + msg.obj
- + " flags=" + msg.arg1);
- doShow((Bundle) msg.obj, msg.arg1);
+ args = (SomeArgs)msg.obj;
+ if (DEBUG) Log.d(TAG, "doShow: args=" + args.arg1
+ + " flags=" + msg.arg1
+ + " showCallback=" + args.arg2);
+ doShow((Bundle) args.arg1, msg.arg1,
+ (IVoiceInteractionSessionShowCallback) args.arg2);
break;
case MSG_HIDE:
if (DEBUG) Log.d(TAG, "doHide");
@@ -523,7 +528,7 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
onCreate(args, startFlags);
}
- void doShow(Bundle args, int flags) {
+ void doShow(Bundle args, int flags, final IVoiceInteractionSessionShowCallback showCallback) {
if (DEBUG) Log.v(TAG, "Showing window: mWindowAdded=" + mWindowAdded
+ " mWindowVisible=" + mWindowVisible);
@@ -548,6 +553,22 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
mWindowVisible = true;
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);
+ }
+ return true;
+ }
+ });
+ }
} finally {
mWindowWasVisible = true;
mInShowWindow = false;
@@ -582,7 +603,8 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
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_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
mWindow.setContentView(mRootView);
mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
@@ -716,7 +738,9 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
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);
+ mWindow.getWindow().addFlags(
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
initViews();
mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
mWindow.setToken(mToken);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 66dae7b..54d78f3 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -223,6 +223,7 @@ public interface WindowManager extends ViewManager {
@ViewDebug.IntToString(from = TYPE_MAGNIFICATION_OVERLAY, to = "TYPE_MAGNIFICATION_OVERLAY"),
@ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"),
+ @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
})
public int type;
@@ -549,6 +550,12 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32;
/**
+ * Window type: Starting window for voice interaction layer.
+ * @hide
+ */
+ public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 144dca4..d328eaf 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -16,9 +16,11 @@
package com.android.internal.app;
+import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
@@ -87,10 +89,17 @@ interface IVoiceInteractionManagerService {
boolean isServiceActive();
/**
+ * @return the component name for the currently active voice interaction service
+ */
+ ComponentName getActiveServiceComponentName();
+
+ /**
* Shows the session for the currently active service. Used to start a new session from system
* affordances.
+ *
+ * @param showCallback callback to be notified when the session was shown
*/
- void showSessionForActiveService();
+ void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback);
/**
* Indicates whether there is a voice session running (but not necessarily showing).
diff --git a/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl b/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl
new file mode 100644
index 0000000..15fa89b
--- /dev/null
+++ b/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.internal.app;
+
+oneway interface IVoiceInteractionSessionShowCallback {
+ void onFailed();
+ void onShown();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index f0e6c43..d6f9f6d 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -122,7 +122,8 @@ public class SearchPanelView extends FrameLayout implements StatusBarPanel {
private void startVoiceInteractor() {
try {
- mVoiceInteractionManagerService.showSessionForActiveService();
+ // TODO: Pass show callback
+ mVoiceInteractionManagerService.showSessionForActiveService(null /* showCallback */);
} catch (RemoteException e) {
Log.w(TAG, "Failed to call showSessionForActiveService", e);
}
@@ -137,6 +138,15 @@ public class SearchPanelView extends FrameLayout implements StatusBarPanel {
}
}
+ private ComponentName getVoiceInteractorComponentName() {
+ try {
+ return mVoiceInteractionManagerService.getActiveServiceComponentName();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
+ return null;
+ }
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -152,25 +162,38 @@ public class SearchPanelView extends FrameLayout implements StatusBarPanel {
private void maybeSwapSearchIcon() {
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
.getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
- if (intent != null) {
- ComponentName component = intent.getComponent();
- replaceDrawable(mLogo, component, ASSIST_ICON_METADATA_NAME);
+ ComponentName component = null;
+ boolean isService = false;
+ if (isVoiceInteractorActive()) {
+ component = getVoiceInteractorComponentName();
+ isService = true;
+ } else if (intent != null) {
+ component = intent.getComponent();
+ }
+ if (component != null) {
+ replaceDrawable(mLogo, component, ASSIST_ICON_METADATA_NAME,
+ isService);
} else {
mLogo.setImageDrawable(null);
}
}
- public void replaceDrawable(ImageView v, ComponentName component, String name) {
+ public void replaceDrawable(ImageView v, ComponentName component, String name,
+ boolean isService) {
if (component != null) {
try {
PackageManager packageManager = mContext.getPackageManager();
// Look for the search icon specified in the activity meta-data
- Bundle metaData = packageManager.getActivityInfo(
- component, PackageManager.GET_META_DATA).metaData;
+ Bundle metaData = isService
+ ? packageManager.getServiceInfo(
+ component, PackageManager.GET_META_DATA).metaData
+ : packageManager.getActivityInfo(
+ component, PackageManager.GET_META_DATA).metaData;
if (metaData != null) {
int iconResId = metaData.getInt(name);
if (iconResId != 0) {
- Resources res = packageManager.getResourcesForActivity(component);
+ Resources res = packageManager.getResourcesForApplication(
+ component.getPackageName());
v.setImageDrawable(res.getDrawable(iconResId));
return;
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 958caea..cfea86f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1922,6 +1922,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_PHONE:
return 3;
case TYPE_SEARCH_BAR:
+ case TYPE_VOICE_INTERACTION_STARTING:
return 4;
case TYPE_VOICE_INTERACTION:
// voice interaction layer is almost immediately above apps.
@@ -2270,16 +2271,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
case TYPE_NAVIGATION_BAR_PANEL:
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.STATUS_BAR_SERVICE,
- "PhoneWindowManager");
- break;
case TYPE_STATUS_BAR_PANEL:
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.STATUS_BAR_SERVICE,
- "PhoneWindowManager");
- break;
case TYPE_STATUS_BAR_SUB_PANEL:
+ case TYPE_VOICE_INTERACTION_STARTING:
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.STATUS_BAR_SERVICE,
"PhoneWindowManager");
@@ -3657,7 +3651,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.bottom = df.bottom = of.bottom = cf.bottom
= mOverscanScreenTop + mOverscanScreenHeight;
}
- } else if (attrs.type == TYPE_INPUT_METHOD || attrs.type == TYPE_VOICE_INTERACTION) {
+ } else if (attrs.type == TYPE_INPUT_METHOD) {
pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
@@ -3668,6 +3662,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// IM dock windows always go to the bottom of the screen.
attrs.gravity = Gravity.BOTTOM;
mDockLayer = win.getSurfaceLayer();
+ } else if (attrs.type == TYPE_VOICE_INTERACTION) {
+ pf.left = df.left = of.left = cf.left = vf.left = mUnrestrictedScreenLeft;
+ pf.top = df.top = of.top = mUnrestrictedScreenTop;
+ pf.right = df.right = of.right = cf.right = vf.right = mUnrestrictedScreenLeft
+ + mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
+ + mUnrestrictedScreenHeight;
+ cf.bottom = vf.bottom = mStableBottom;
+ cf.top = vf.top = mStableTop;
} else if (win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
pf.left = df.left = of.left = mUnrestrictedScreenLeft;
pf.top = df.top = of.top = mUnrestrictedScreenTop;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index d8b9140..1203735 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -26,6 +26,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
@@ -50,6 +51,7 @@ import android.text.TextUtils;
import android.util.Slog;
import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
@@ -396,7 +398,8 @@ public class VoiceInteractionManagerService extends SystemService {
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- mImpl.showSessionLocked(callingPid, callingUid, args, flags);
+ mImpl.showSessionLocked(callingPid, callingUid, args, flags,
+ null /* showCallback */);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -434,7 +437,8 @@ public class VoiceInteractionManagerService extends SystemService {
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- return mImpl.showSessionLocked(callingPid, callingUid, sessionArgs, flags);
+ return mImpl.showSessionLocked(callingPid, callingUid, sessionArgs, flags,
+ null /* showCallback */);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -720,7 +724,20 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public void showSessionForActiveService() {
+ public ComponentName getActiveServiceComponentName() {
+ synchronized (this) {
+ if (mContext.checkCallingPermission(
+ Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold the permission "
+ + Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+ }
+ return mImpl != null ? mImpl.mComponent : null;
+ }
+ }
+
+ @Override
+ public void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback) {
synchronized (this) {
if (mContext.checkCallingPermission(
Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE)
@@ -740,7 +757,8 @@ public class VoiceInteractionManagerService extends SystemService {
mImpl.showSessionLocked(callingPid, callingUid, new Bundle() /* sessionArgs */,
VoiceInteractionService.START_SOURCE_SYSTEM
| VoiceInteractionService.START_WITH_ASSIST
- | VoiceInteractionService.START_WITH_SCREENSHOT);
+ | VoiceInteractionService.START_WITH_SCREENSHOT,
+ showCallback);
} finally {
Binder.restoreCallingIdentity(caller);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 5a91b88..1aa0d0b 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -39,6 +39,7 @@ import android.service.voice.VoiceInteractionServiceInfo;
import android.util.Slog;
import android.view.IWindowManager;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import java.io.FileDescriptor;
@@ -134,12 +135,13 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mContext.registerReceiver(mBroadcastReceiver, filter, null, handler);
}
- public boolean showSessionLocked(int callingPid, int callingUid, Bundle args, int flags) {
+ public boolean showSessionLocked(int callingPid, int callingUid, Bundle args, int flags,
+ IVoiceInteractionSessionShowCallback showCallback) {
if (mActiveSession == null) {
mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName,
mUser, mContext, this, callingPid, callingUid);
}
- return mActiveSession.showLocked(args, flags);
+ return mActiveSession.showLocked(args, flags, showCallback);
}
public boolean hideSessionLocked(int callingPid, int callingUid) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 7a379c2..73c7363 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -41,10 +41,12 @@ import android.util.Slog;
import android.view.IWindowManager;
import android.view.WindowManager;
import com.android.internal.app.IAssistScreenshotReceiver;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
import java.io.PrintWriter;
+import java.util.ArrayList;
final class VoiceInteractionSessionConnection implements ServiceConnection {
final static String TAG = "VoiceInteractionServiceManager";
@@ -74,6 +76,26 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
Bundle mAssistData;
boolean mHaveScreenshot;
Bitmap mScreenshot;
+ ArrayList<IVoiceInteractionSessionShowCallback> mPendingShowCallbacks = new ArrayList<>();
+
+ IVoiceInteractionSessionShowCallback mShowCallback =
+ new IVoiceInteractionSessionShowCallback.Stub() {
+ @Override
+ public void onFailed() throws RemoteException {
+ synchronized (mLock) {
+ notifyPendingShowCallbacksFailedLocked();
+ }
+ }
+
+ @Override
+ public void onShown() throws RemoteException {
+ synchronized (mLock) {
+ // TODO: Figure out whether this is good enough or whether we need to hook into
+ // Window manager to actually wait for the window to be drawn.
+ notifyPendingShowCallbacksShownLocked();
+ }
+ }
+ };
public interface Callback {
public void sessionConnectionGone(VoiceInteractionSessionConnection connection);
@@ -151,7 +173,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
}
}
- public boolean showLocked(Bundle args, int flags) {
+ public boolean showLocked(Bundle args, int flags,
+ IVoiceInteractionSessionShowCallback showCallback) {
if (mBound) {
if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@@ -182,15 +205,23 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
}
if (mSession != null) {
try {
- mSession.show(mShowArgs, mShowFlags);
+ mSession.show(mShowArgs, mShowFlags, showCallback);
mShowArgs = null;
mShowFlags = 0;
} catch (RemoteException e) {
}
deliverSessionDataLocked();
+ } else if (showCallback != null) {
+ mPendingShowCallbacks.add(showCallback);
}
return true;
}
+ if (showCallback != null) {
+ try {
+ showCallback.onFailed();
+ } catch (RemoteException e) {
+ }
+ }
return false;
}
@@ -320,7 +351,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mInteractor = interactor;
if (mShown) {
try {
- session.show(mShowArgs, mShowFlags);
+ session.show(mShowArgs, mShowFlags, mShowCallback);
mShowArgs = null;
mShowFlags = 0;
} catch (RemoteException e) {
@@ -330,6 +361,26 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
return true;
}
+ private void notifyPendingShowCallbacksShownLocked() {
+ for (int i = 0; i < mPendingShowCallbacks.size(); i++) {
+ try {
+ mPendingShowCallbacks.get(i).onShown();
+ } catch (RemoteException e) {
+ }
+ }
+ mPendingShowCallbacks.clear();
+ }
+
+ private void notifyPendingShowCallbacksFailedLocked() {
+ for (int i = 0; i < mPendingShowCallbacks.size(); i++) {
+ try {
+ mPendingShowCallbacks.get(i).onFailed();
+ } catch (RemoteException e) {
+ }
+ }
+ mPendingShowCallbacks.clear();
+ }
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {