Update voice interaction layer for new UI design.

Can switch from a pure overlay at the top of the screen,
to interactive mode with the voice UI drawing at the bottom
and pushing its target activity up like an IME.

Add mechanism to get assist data to the voice interaction UI.

Add some basic visualization of the assist data, outlining
where on the screen we have text.

Add a test ACTION_ASSIST handler, which can propagate the
assist data it gets to the voice interaction session so
you can see what kind of data we are getting from different
apps.

Change-Id: I18312fe1601d7926d1fb96a817638d60f6263771
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c4718b8..511347e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -65,6 +65,7 @@
 import com.android.internal.app.ProcessStats;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.os.Zygote;
@@ -439,23 +440,28 @@
         public final Bundle extras;
         public final Intent intent;
         public final String hint;
+        public final IResultReceiver receiver;
         public final int userHandle;
         public boolean haveResult = false;
         public Bundle result = null;
         public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent,
-                String _hint, int _userHandle) {
+                String _hint, IResultReceiver _receiver, int _userHandle) {
             activity = _activity;
             extras = _extras;
             intent = _intent;
             hint = _hint;
+            receiver = _receiver;
             userHandle = _userHandle;
         }
         @Override
         public void run() {
             Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from " + activity);
-            synchronized (this) {
-                haveResult = true;
-                notifyAll();
+            synchronized (ActivityManagerService.this) {
+                synchronized (this) {
+                    haveResult = true;
+                    notifyAll();
+                }
+                pendingAssistExtrasTimedOutLocked(this);
             }
         }
     }
@@ -9980,8 +9986,9 @@
         return true;
     }
 
+    @Override
     public Bundle getAssistContextExtras(int requestType) {
-        PendingAssistExtras pae = enqueueAssistContext(requestType, null, null,
+        PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
                 UserHandle.getCallingUserId());
         if (pae == null) {
             return null;
@@ -9993,19 +10000,22 @@
                 } catch (InterruptedException e) {
                 }
             }
-            if (pae.result != null) {
-                pae.extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.result);
-            }
         }
         synchronized (this) {
+            buildAssistBundleLocked(pae, pae.result);
             mPendingAssistExtras.remove(pae);
             mHandler.removeCallbacks(pae);
         }
         return pae.extras;
     }
 
+    @Override
+    public void requestAssistContextExtras(int requestType, IResultReceiver receiver) {
+        enqueueAssistContext(requestType, null, null, receiver, UserHandle.getCallingUserId());
+    }
+
     private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
-            int userHandle) {
+            IResultReceiver receiver, int userHandle) {
         enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
                 "getAssistContextExtras()");
         PendingAssistExtras pae;
@@ -10025,7 +10035,7 @@
                 Slog.w(TAG, "getAssistContextExtras failed: request process same as " + activity);
                 return null;
             }
-            pae = new PendingAssistExtras(activity, extras, intent, hint, userHandle);
+            pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, userHandle);
             try {
                 activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
                         requestType);
@@ -10039,13 +10049,33 @@
         }
     }
 
+    void pendingAssistExtrasTimedOutLocked(PendingAssistExtras pae) {
+        mPendingAssistExtras.remove(pae);
+        if (pae.receiver != null) {
+            // Caller wants result sent back to them.
+            try {
+                pae.receiver.send(0, null);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    private void buildAssistBundleLocked(PendingAssistExtras pae, Bundle result) {
+        if (result != null) {
+            pae.extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, result);
+        }
+        if (pae.hint != null) {
+            pae.extras.putBoolean(pae.hint, true);
+        }
+    }
+
     public void reportAssistContextExtras(IBinder token, Bundle extras) {
         PendingAssistExtras pae = (PendingAssistExtras)token;
         synchronized (pae) {
             pae.result = extras;
             pae.haveResult = true;
             pae.notifyAll();
-            if (pae.intent == null) {
+            if (pae.intent == null && pae.receiver == null) {
                 // Caller is just waiting for the result.
                 return;
             }
@@ -10053,17 +10083,23 @@
 
         // We are now ready to launch the assist activity.
         synchronized (this) {
+            buildAssistBundleLocked(pae, extras);
             boolean exists = mPendingAssistExtras.remove(pae);
             mHandler.removeCallbacks(pae);
             if (!exists) {
                 // Timed out.
                 return;
             }
+            if (pae.receiver != null) {
+                // Caller wants result sent back to them.
+                try {
+                    pae.receiver.send(0, pae.extras);
+                } catch (RemoteException e) {
+                }
+                return;
+            }
         }
-        pae.intent.replaceExtras(extras);
-        if (pae.hint != null) {
-            pae.intent.putExtra(pae.hint, true);
-        }
+        pae.intent.replaceExtras(pae.extras);
         pae.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_SINGLE_TOP
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -10076,7 +10112,7 @@
     }
 
     public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle) {
-        return enqueueAssistContext(requestType, intent, hint, userHandle) != null;
+        return enqueueAssistContext(requestType, intent, hint, null, userHandle) != null;
     }
 
     public void registerProcessObserver(IProcessObserver observer) {
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 5b6f35b..af9f456 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -355,7 +355,7 @@
             if (mWindow != null) {
                 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
                 ipw.increaseIndent();
-                DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, 200);
+                DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, "", 200);
             }
         }
 
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index 9ca5fda..3f4eab9 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -153,7 +153,7 @@
     }
 
     @Override
-    public void dump(PrintWriter pw) {
+    public void dump(PrintWriter pw, String prefix) {
         pw.println("mWindowVisible=" + mWindowVisible);
         pw.println("mWindowX=" + mWindowX);
         pw.println("mWindowY=" + mWindowY);
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index c939861..f163555 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -123,7 +123,7 @@
             pw.println("mDisplayController:");
             final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
             ipw.increaseIndent();
-            DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200);
+            DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, "", 200);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java
index dbb59b2..31c1eea 100644
--- a/services/core/java/com/android/server/display/WifiDisplayController.java
+++ b/services/core/java/com/android/server/display/WifiDisplayController.java
@@ -209,7 +209,7 @@
     }
 
     @Override
-    public void dump(PrintWriter pw) {
+    public void dump(PrintWriter pw, String prefix) {
         pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
         pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
         pw.println("mWfdEnabled=" + mWfdEnabled);
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 4521c28..458928f 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -137,10 +137,10 @@
 
         DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
             @Override
-            public void dump(PrintWriter pw) {
+            public void dump(PrintWriter pw, String prefix) {
                 mController.dump(pw);
             }
-        }, pw, 200);
+        }, pw, "", 200);
     }
 
     private boolean isDreamingInternal() {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5bb193a..ff274b6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3554,7 +3554,7 @@
                 pf.bottom = df.bottom = of.bottom = cf.bottom
                         = mOverscanScreenTop + mOverscanScreenHeight;
             }
-        } else  if (attrs.type == TYPE_INPUT_METHOD) {
+        } else  if (attrs.type == TYPE_INPUT_METHOD || attrs.type == TYPE_VOICE_INTERACTION) {
             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;
@@ -3936,7 +3936,7 @@
     }
 
     private void offsetInputMethodWindowLw(WindowState win) {
-        int top = win.getContentFrameLw().top;
+        int top = win.getDisplayFrameLw().top;
         top += win.getGivenContentInsetsLw().top;
         if (mContentBottom > top) {
             mContentBottom = top;
@@ -3955,36 +3955,10 @@
     }
 
     private void offsetVoiceInputWindowLw(WindowState win) {
-        final int gravity = win.getAttrs().gravity;
-        switch (gravity&((Gravity.AXIS_PULL_BEFORE|Gravity.AXIS_PULL_AFTER)
-                << Gravity.AXIS_X_SHIFT)) {
-            case Gravity.AXIS_PULL_BEFORE<<Gravity.AXIS_X_SHIFT: {
-                int right = win.getContentFrameLw().right - win.getGivenContentInsetsLw().right;
-                if (mVoiceContentLeft < right) {
-                    mVoiceContentLeft = right;
-                }
-            } break;
-            case Gravity.AXIS_PULL_AFTER<<Gravity.AXIS_X_SHIFT: {
-                int left = win.getContentFrameLw().left - win.getGivenContentInsetsLw().left;
-                if (mVoiceContentRight < left) {
-                    mVoiceContentRight = left;
-                }
-            } break;
-        }
-        switch (gravity&((Gravity.AXIS_PULL_BEFORE|Gravity.AXIS_PULL_AFTER)
-                << Gravity.AXIS_Y_SHIFT)) {
-            case Gravity.AXIS_PULL_BEFORE<<Gravity.AXIS_Y_SHIFT: {
-                int bottom = win.getContentFrameLw().bottom - win.getGivenContentInsetsLw().bottom;
-                if (mVoiceContentTop < bottom) {
-                    mVoiceContentTop = bottom;
-                }
-            } break;
-            case Gravity.AXIS_PULL_AFTER<<Gravity.AXIS_Y_SHIFT: {
-                int top = win.getContentFrameLw().top - win.getGivenContentInsetsLw().top;
-                if (mVoiceContentBottom < top) {
-                    mVoiceContentBottom = top;
-                }
-            } break;
+        int top = win.getDisplayFrameLw().top;
+        top += win.getGivenContentInsetsLw().top;
+        if (mVoiceContentBottom > top) {
+            mVoiceContentBottom = top;
         }
     }
 
@@ -6385,9 +6359,8 @@
         }
         if (mStatusBar != null) {
             pw.print(prefix); pw.print("mStatusBar=");
-                    pw.println(mStatusBar);
-            pw.print(prefix); pw.print("isStatusBarKeyguard=");
-                    pw.print(isStatusBarKeyguard());
+                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
+                    pw.println(isStatusBarKeyguard());
         }
         if (mNavigationBar != null) {
             pw.print(prefix); pw.print("mNavigationBar=");
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index c0d54e1..231a6bd 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1130,32 +1130,34 @@
     }
 
     @Override
-    public void dump(PrintWriter pw) {
-        pw.print(" " + this);
-        pw.print("  mAppTransitionState="); pw.println(appStateToString());
+    public void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.println(this);
+        pw.print(prefix); pw.print("mAppTransitionState="); pw.println(appStateToString());
         if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) {
-            pw.print("  mNextAppTransitionType="); pw.println(transitTypeToString());
+            pw.print(prefix); pw.print("mNextAppTransitionType=");
+                    pw.println(transitTypeToString());
         }
         switch (mNextAppTransitionType) {
             case NEXT_TRANSIT_TYPE_CUSTOM:
-                pw.print("  mNextAppTransitionPackage=");
+                pw.print(prefix); pw.print("mNextAppTransitionPackage=");
                         pw.println(mNextAppTransitionPackage);
-                pw.print("  mNextAppTransitionEnter=0x");
+                pw.print(prefix); pw.print("mNextAppTransitionEnter=0x");
                         pw.print(Integer.toHexString(mNextAppTransitionEnter));
                         pw.print(" mNextAppTransitionExit=0x");
                         pw.println(Integer.toHexString(mNextAppTransitionExit));
                 break;
             case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE:
-                pw.print("  mNextAppTransitionPackage=");
+                pw.print(prefix); pw.print("mNextAppTransitionPackage=");
                         pw.println(mNextAppTransitionPackage);
-                pw.print("  mNextAppTransitionInPlace=0x");
+                pw.print(prefix); pw.print("mNextAppTransitionInPlace=0x");
                         pw.print(Integer.toHexString(mNextAppTransitionInPlace));
                 break;
             case NEXT_TRANSIT_TYPE_SCALE_UP:
-                pw.print("  mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
+                pw.print(prefix); pw.print("mNextAppTransitionStartX=");
+                        pw.print(mNextAppTransitionStartX);
                         pw.print(" mNextAppTransitionStartY=");
                         pw.println(mNextAppTransitionStartY);
-                pw.print("  mNextAppTransitionStartWidth=");
+                pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
                         pw.print(mNextAppTransitionStartWidth);
                         pw.print(" mNextAppTransitionStartHeight=");
                         pw.println(mNextAppTransitionStartHeight);
@@ -1164,22 +1166,23 @@
             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
             case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
             case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
-                pw.print("  mNextAppTransitionThumbnail=");
+                pw.print(prefix); pw.print("mNextAppTransitionThumbnail=");
                         pw.print(mNextAppTransitionThumbnail);
                         pw.print(" mNextAppTransitionStartX=");
                         pw.print(mNextAppTransitionStartX);
                         pw.print(" mNextAppTransitionStartY=");
                         pw.println(mNextAppTransitionStartY);
-                        pw.print(" mNextAppTransitionStartWidth=");
+                pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
                         pw.print(mNextAppTransitionStartWidth);
                         pw.print(" mNextAppTransitionStartHeight=");
                         pw.println(mNextAppTransitionStartHeight);
-                pw.print("  mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
+                pw.print(prefix); pw.print("mNextAppTransitionScaleUp=");
+                        pw.println(mNextAppTransitionScaleUp);
                 break;
         }
         if (mNextAppTransitionCallback != null) {
-            pw.print("  mNextAppTransitionCallback=");
-            pw.println(mNextAppTransitionCallback);
+            pw.print(prefix); pw.print("mNextAppTransitionCallback=");
+                    pw.println(mNextAppTransitionCallback);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 02a4f4d..8e217b9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -11058,7 +11058,7 @@
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
             pw.println("  mLayoutToAnim:");
-            mAppTransition.dump(pw);
+            mAppTransition.dump(pw, "    ");
         }
     }