Fix multi-window assiststructure trashing

When multiple activities within the same process
try to handle requests for AssistStructure, the
singleton mLastAssistStructure tends to trash
the old structure when a second window's request
comes in.

This change passes in a sessionId so that the
cache is only cleared if the session id changes.

Bug: 28348867
Change-Id: I07efcd933db7e48aefd25a1c95493b71bbcffe4b
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6b62837..a4f404f 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2418,8 +2418,9 @@
             Bundle receiverExtras = data.readBundle();
             IBinder activityToken = data.readStrongBinder();
             boolean focused = data.readInt() == 1;
+            boolean newSessionId = data.readInt() == 1;
             boolean res = requestAssistContextExtras(requestType, receiver, receiverExtras,
-                    activityToken, focused);
+                    activityToken, focused, newSessionId);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -6104,7 +6105,7 @@
 
     public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
             Bundle receiverExtras,
-            IBinder activityToken, boolean focused) throws RemoteException {
+            IBinder activityToken, boolean focused, boolean newSessionId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -6113,6 +6114,7 @@
         data.writeBundle(receiverExtras);
         data.writeStrongBinder(activityToken);
         data.writeInt(focused ? 1 : 0);
+        data.writeInt(newSessionId ? 1 : 0);
         mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean res = reply.readInt() != 0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9383394..a39dbcb 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -206,7 +206,8 @@
     ActivityClientRecord mNewActivities = null;
     // Number of activities that are currently visible on-screen.
     int mNumVisibleActivities = 0;
-    WeakReference<AssistStructure> mLastAssistStructure;
+    ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
+    private int mLastSessionId;
     final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
     AppBindData mBoundApplication;
     Profiler mProfiler;
@@ -622,6 +623,7 @@
         IBinder activityToken;
         IBinder requestToken;
         int requestType;
+        int sessionId;
     }
 
     static final class ActivityConfigChangeData {
@@ -1183,11 +1185,12 @@
 
         @Override
         public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
-                int requestType) {
+                int requestType, int sessionId) {
             RequestAssistContextExtras cmd = new RequestAssistContextExtras();
             cmd.activityToken = activityToken;
             cmd.requestToken = requestToken;
             cmd.requestType = requestType;
+            cmd.sessionId = sessionId;
             sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
         }
 
@@ -1804,6 +1807,7 @@
     }
 
     private Configuration mMainThreadConfig = new Configuration();
+
     Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
             CompatibilityInfo compat) {
         if (config == null) {
@@ -2785,10 +2789,15 @@
     }
 
     public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
-        if (mLastAssistStructure != null) {
-            AssistStructure structure = mLastAssistStructure.get();
-            if (structure != null) {
-                structure.clearSendChannel();
+        if (mLastSessionId != cmd.sessionId) {
+            // Clear the existing structures
+            mLastSessionId = cmd.sessionId;
+            for (int i = mLastAssistStructures.size() - 1; i >= 0; i--) {
+                AssistStructure structure = mLastAssistStructures.get(i).get();
+                if (structure != null) {
+                    structure.clearSendChannel();
+                }
+                mLastAssistStructures.remove(i);
             }
         }
         Bundle data = new Bundle();
@@ -2820,7 +2829,7 @@
         if (structure == null) {
             structure = new AssistStructure();
         }
-        mLastAssistStructure = new WeakReference<>(structure);
+        mLastAssistStructures.add(new WeakReference<>(structure));
         IActivityManager mgr = ActivityManagerNative.getDefault();
         try {
             mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index ea86dd0..d6da3f4 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -621,7 +621,8 @@
             IBinder activityToken = data.readStrongBinder();
             IBinder requestToken = data.readStrongBinder();
             int requestType = data.readInt();
-            requestAssistContextExtras(activityToken, requestToken, requestType);
+            int sessionId = data.readInt();
+            requestAssistContextExtras(activityToken, requestToken, requestType, sessionId);
             reply.writeNoException();
             return true;
         }
@@ -1377,12 +1378,13 @@
 
     @Override
     public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
-            int requestType) throws RemoteException {
+            int requestType, int sessionId) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(activityToken);
         data.writeStrongBinder(requestToken);
         data.writeInt(requestType);
+        data.writeInt(sessionId);
         mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 849fcec..2fcad0d 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -524,7 +524,7 @@
 
     public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
             Bundle receiverExtras,
-            IBinder activityToken, boolean focused) throws RemoteException;
+            IBinder activityToken, boolean focused, boolean newSessionId) throws RemoteException;
 
     public void reportAssistContextExtras(IBinder token, Bundle extras,
             AssistStructure structure, AssistContent content, Uri referrer) throws RemoteException;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index a3b2638..559f69f 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -143,8 +143,8 @@
     void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void unstableProviderDied(IBinder provider) throws RemoteException;
-    void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, int requestType)
-            throws RemoteException;
+    void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, int requestType,
+            int sessionId) throws RemoteException;
     void scheduleTranslucentConversionComplete(IBinder token, boolean timeout)
             throws RemoteException;
     void scheduleOnNewActivityOptions(IBinder token, ActivityOptions options)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f52bda9..313ca9a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1513,6 +1513,10 @@
 
     PackageManagerInternal mPackageManagerInt;
 
+    // VoiceInteraction session ID that changes for each new request except when
+    // being called for multiwindow assist in a single session.
+    private int mViSessionId = 1000;
+
     final class KillHandler extends Handler {
         static final int KILL_PROCESS_GROUP_MSG = 4000;
 
@@ -11881,7 +11885,8 @@
     @Override
     public Bundle getAssistContextExtras(int requestType) {
         PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
-                null, null, true, UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
+                null, null, true /* focused */, true /* newSessionId */,
+                UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
         if (pae == null) {
             return null;
         }
@@ -11946,16 +11951,16 @@
     @Override
     public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
             Bundle receiverExtras,
-            IBinder activityToken, boolean focused) {
+            IBinder activityToken, boolean focused, boolean newSessionId) {
         return enqueueAssistContext(requestType, null, null, receiver, receiverExtras,
-                activityToken, focused,
+                activityToken, focused, newSessionId,
                 UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT)
                 != null;
     }
 
     private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
-            IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken, boolean focused,
-            int userHandle, Bundle args, long timeout) {
+            IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken,
+            boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout) {
         enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
                 "enqueueAssistContext()");
         synchronized (this) {
@@ -11995,9 +12000,13 @@
             extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
             pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
                     userHandle);
+            // Increment the sessionId if necessary
+            if (newSessionId) {
+                mViSessionId++;
+            }
             try {
                 activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
-                        requestType);
+                        requestType, mViSessionId);
                 mPendingAssistExtras.add(pae);
                 mUiHandler.postDelayed(pae, timeout);
             } catch (RemoteException e) {
@@ -12102,7 +12111,8 @@
 
     public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
             Bundle args) {
-        return enqueueAssistContext(requestType, intent, hint, null, null, null, true,
+        return enqueueAssistContext(requestType, intent, hint, null, null, null,
+                true /* focused */, true /* newSessionId */,
                 userHandle, args, PENDING_ASSIST_EXTRAS_TIMEOUT) != null;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d74e22e..243c887 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3341,14 +3341,12 @@
                         } catch (RemoteException re) {
                             // Ok
                         }
-                        // TODO: VI This is redundant in some cases
                         mService.finishRunningVoiceLocked();
                         break;
                     }
                 }
             }
         }
-        Slog.d(TAG, "ActivityStack.finishVoiceTask()");
 
         if (didOne) {
             mService.updateOomAdjLocked();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 855a5c4..0694911 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -260,7 +260,8 @@
                             receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i);
                             receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, count);
                             if (mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
-                                    mAssistReceiver, receiverExtras, topActivity, i == 0)) {
+                                    mAssistReceiver, receiverExtras, topActivity,
+                                    /* focused= */ i == 0, /* newSessionId= */ i == 0)) {
                                 needDisclosure = true;
                                 mPendingAssistDataCount++;
                             } else if (i == 0) {