Make CarLauncher multi-display CTS compatible.

CarLauncher has the logic to restart Maps in TaskView if it's crashed.
But this behavior hinders multi-display CTS because CTS's setup removes
all tasks but Home (CarLauncher), and it removes Maps too, so our logic
tries to restart Maps, and it creates unexpected superfluous Activity
state changes and the tests will be failed.

We changed the logic to restart Maps only when CarLauncher is focused.
The logic is safe for CTS, since most CTS doesn't give the focus to
Home explicitly.

This CL also sets setTaskAlwaysOnTop() on the Activity in TaskView and
cleans up some unused variables.

Test: atest MultiDisplayActivityLaunchTests
Test: atest MultiDisplayClientTests
Bug: 192122834
Bug: 192123204
Change-Id: Ie920e0ce78a3308e8cdc7aeeb5f2c4f600ecaa97
Merged-In: Ie920e0ce78a3308e8cdc7aeeb5f2c4f600ecaa97
diff --git a/src/com/android/car/carlauncher/CarLauncher.java b/src/com/android/car/carlauncher/CarLauncher.java
index 93e35c7..fdf8771 100644
--- a/src/com/android/car/carlauncher/CarLauncher.java
+++ b/src/com/android/car/carlauncher/CarLauncher.java
@@ -19,18 +19,16 @@
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
 import android.app.PendingIntent;
+import android.app.TaskStackListener;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.hardware.display.DisplayManager;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
 import android.util.Log;
 import android.view.Display;
 import android.view.ViewGroup;
@@ -48,7 +46,6 @@
 
 import java.net.URISyntaxException;
 import java.util.Set;
-import java.util.function.Consumer;
 
 /**
  * Basic Launcher for Android Automotive which demonstrates the use of {@link TaskView} to host
@@ -68,14 +65,13 @@
     private static final boolean DEBUG = false;
 
     private TaskViewManager mTaskViewManager;
-    private ActivityManager mActivityManager;
     private TaskView mTaskView;
     private boolean mTaskViewReady;
     // Tracking this to check if the task in TaskView has crashed in the background.
     private int mTaskViewTaskId = INVALID_TASK_ID;
     private boolean mIsResumed;
-    private DisplayManager mDisplayManager;
-    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+    private boolean mFocused;
+    private int mCarLauncherTaskId = INVALID_TASK_ID;
     private Set<HomeCardModule> mHomeCardModules;
 
     /** Set to {@code true} once we've logged that the Activity is fully drawn. */
@@ -107,7 +103,18 @@
         public void onTaskRemovalStarted(int taskId) {
             if (DEBUG) Log.d(TAG, "onTaskRemovalStarted: taskId=" + taskId);
             mTaskViewTaskId = INVALID_TASK_ID;
-            if (mIsResumed) {
+        }
+    };
+
+    private final TaskStackListener mTaskStackListener = new TaskStackListener() {
+        @Override
+        public void onTaskFocusChanged(int taskId, boolean focused) {
+            mFocused = taskId == mCarLauncherTaskId && focused;
+            if (DEBUG) {
+                Log.d(TAG, "onTaskFocusChanged: mFocused=" + mFocused
+                        + ", mTaskViewTaskId=" + mTaskViewTaskId);
+            }
+            if (mFocused && mTaskViewTaskId == INVALID_TASK_ID) {
                 startMapsInTaskView();
             }
         }
@@ -117,7 +124,9 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mActivityManager = getSystemService(ActivityManager.class);
+        mCarLauncherTaskId = getTaskId();
+        ActivityTaskManager.getInstance().registerTaskStackListener(mTaskStackListener);
+
         // Setting as trusted overlay to let touches pass through.
         getWindow().addPrivateFlags(PRIVATE_FLAG_TRUSTED_OVERLAY);
         // To pass touches to the underneath task.
@@ -156,14 +165,13 @@
         super.onResume();
         mIsResumed = true;
         maybeLogReady();
-        if (!mTaskViewReady) return;
-        if (mTaskViewTaskId == INVALID_TASK_ID) {
+        if (DEBUG) {
+            Log.d(TAG, "onResume: mFocused=" + mFocused + ", mTaskViewTaskId=" + mTaskViewTaskId);
+        }
+        if (mFocused && mTaskViewTaskId == INVALID_TASK_ID) {
             // If the task in TaskView is crashed during CarLauncher is background,
             // We'd like to restart it when CarLauncher becomes foreground.
             startMapsInTaskView();
-        } else {
-            // The task in TaskView should be in top to make it visible.
-            mActivityManager.moveTaskToFront(mTaskViewTaskId, /* flags= */ 0);
         }
     }
 
@@ -176,6 +184,7 @@
     @Override
     protected void onDestroy() {
         super.onDestroy();
+        ActivityTaskManager.getInstance().unregisterTaskStackListener(mTaskStackListener);
         if (mTaskView != null && mTaskViewReady) {
             mTaskView.release();
             mTaskView = null;
@@ -197,7 +206,10 @@
         }
         try {
             ActivityOptions options = ActivityOptions.makeCustomAnimation(this,
-                   /* enterResId= */ 0, /* exitResId= */ 0);
+                    /* enterResId= */ 0, /* exitResId= */ 0);
+            // To show the Activity in TaskView, the Activity should be above the host task in
+            // ActivityStack. This option only effects the host Activity is in resumed.
+            options.setTaskAlwaysOnTop(true);
             mTaskView.startActivity(
                     PendingIntent.getActivity(this, /* requestCode= */ 0, getMapsIntent(),
                             PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT),