Fix a couple bugs with back button visibility

- Fix back button flickering when returning to NORMAL state instead of
  finishing a gesture to, say, ALL_APPS. This is achieved by posting
  changes to the back visibility on the UI thread (binder calls are
  posted on the background thread).
- Restore back button when touch service reconnects (in case we were
  forced into an app when launcher is force-stopped, for instance).

Change-Id: I3731ee43d66965ce7cd8cf026174aabfe2d5c56c
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 92b38fe..7bd4366 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -69,8 +69,8 @@
     }
 
     public static void onLauncherStateOrFocusChanged(Launcher launcher) {
-        OverviewInteractionState.setBackButtonVisible(launcher, !launcher.isInState(NORMAL)
-                || !launcher.hasWindowFocus());
+        OverviewInteractionState.setBackButtonVisible(launcher, launcher == null
+                || !launcher.isInState(NORMAL) || !launcher.hasWindowFocus());
     }
 
     public static Bitmap createFromRenderer(int width, int height, boolean forceSoftwareRenderer,
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 9be12bd..3c68281 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -18,9 +18,13 @@
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
 
 import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.launcher3.util.UiThreadHelper;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 
 /**
@@ -36,11 +40,35 @@
 public class OverviewInteractionState {
 
     private static final String TAG = "OverviewFlags";
+    private static final Handler sUiHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            updateOverviewInteractionFlag((Context) msg.obj, msg.what, msg.arg1 == 1);
+        }
+    };
+    private static final Handler sBackgroundHandler = new Handler(
+            UiThreadHelper.getBackgroundLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            ISystemUiProxy systemUiProxy = (ISystemUiProxy) msg.obj;
+            int flags = msg.what;
+            try {
+                systemUiProxy.setInteractionState(flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Unable to update overview interaction flags", e);
+            }
+        }
+    };
 
     private static int sFlags;
 
     public static void setBackButtonVisible(Context context, boolean visible) {
-        updateOverviewInteractionFlag(context, FLAG_HIDE_BACK_BUTTON, !visible);
+        updateFlagOnUi(context, FLAG_HIDE_BACK_BUTTON, !visible);
+    }
+
+    private static void updateFlagOnUi(Context context, int flag, boolean enabled) {
+        sUiHandler.removeMessages(flag);
+        sUiHandler.sendMessage(sUiHandler.obtainMessage(flag, enabled ? 1 : 0, 0, context));
     }
 
     private static void updateOverviewInteractionFlag(Context context, int flag, boolean enabled) {
@@ -55,10 +83,9 @@
             Log.w(TAG, "Unable to update overview interaction flags; not bound to service");
             return;
         }
-        try {
-            systemUiProxy.setInteractionState(sFlags);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Unable to update overview interaction flags", e);
+        // If we aren't already setting these flags, do so now on the background thread.
+        if (!sBackgroundHandler.hasMessages(sFlags)) {
+            sBackgroundHandler.sendMessage(sBackgroundHandler.obtainMessage(sFlags, systemUiProxy));
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 52cd60e..af6f8c8 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -48,6 +48,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.UiFactory;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -86,6 +87,9 @@
             mRecentsModel.setSystemUiProxy(mISystemUiProxy);
             RemoteRunnable.executeSafely(() -> mISystemUiProxy.setRecentsOnboardingText(
                     getResources().getString(R.string.recents_swipe_up_onboarding)));
+            Launcher launcher = (Launcher) LauncherAppState.getInstance(
+                    TouchInteractionService.this).getModel().getCallback();
+            UiFactory.onLauncherStateOrFocusChanged(launcher);
         }
 
         @Override