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
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 @@
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 @@
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 @@
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 @@
// 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.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.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 @@
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 @@
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 @@
}
@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 @@
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.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 @@
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.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 @@
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 @@
}
}
- 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 @@
}
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 @@
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 @@
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) {