Move the taskviews initiation after root task view

- Moved the creation of background, appgrid and full taskviews after
  root task view becomes ready.
- Made some cleanup in terms of the timing of some of the initiation
  calls
- Added more logging for easier debuging
- Added a couple of missing fields to the default theme.
- fixed an issue were the background surface would leak from behind the
  task views during animation

Bug: 274801802
Fix: 272099148
Test: Manual
Change-Id: I26a8b67a182806baef03099c7c99432f04230783
diff --git a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/homeactivities/CarUiPortraitHomeScreen.java b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/homeactivities/CarUiPortraitHomeScreen.java
index 9a24390..e6e903f 100644
--- a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/homeactivities/CarUiPortraitHomeScreen.java
+++ b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/homeactivities/CarUiPortraitHomeScreen.java
@@ -77,6 +77,8 @@
 import com.android.car.portraitlauncher.panel.TaskViewPanel;
 
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -138,7 +140,8 @@
     // All the TaskViews & corresponding helper instance variables.
     private CarTaskView mBackgroundTaskView;
     private CarTaskView mFullScreenTaskView;
-    private boolean mIsRootTaskViewReady;
+    private boolean mIsBackgroundTaskViewReady;
+    private boolean mIsFullScreenTaskViewReady;
     private int mNavBarHeight;
     private boolean mIsSUWInProgress;
     private TaskCategoryManager mTaskCategoryManager;
@@ -156,6 +159,9 @@
      */
     private final Messenger mMessenger = new Messenger(new IncomingHandler());
 
+    /** Holds any messages fired before service connection is establish. */
+    private final List<Message> mMessageCache = new ArrayList<>();
+
     private CarUiPortraitDriveStateController mCarUiPortraitDriveStateController;
 
     /**
@@ -179,6 +185,10 @@
                 // so there is no need to do anything here.
                 Log.w(TAG, "can't connect to CarUiPortraitService: ", e);
             }
+            for (Message msg : mMessageCache) {
+                notifySystemUI(msg);
+            }
+            mMessageCache.clear();
         }
 
         public void onServiceDisconnected(ComponentName className) {
@@ -193,9 +203,14 @@
         public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
                 throws RemoteException {
             logIfDebuggable("On task moved to front, task = " + taskInfo);
-            if (!mIsRootTaskViewReady) {
-                logIfDebuggable("Root Task View is not ready yet. Caching the task");
-                cacheTask(taskInfo);
+            if (!mRootTaskViewPanel.isReady()) {
+                logIfDebuggable("Root Task View is not ready yet.");
+                if (!TaskCategoryManager.isHomeIntent(taskInfo)
+                        && !mTaskCategoryManager.isBackgroundApp(taskInfo)
+                        && !mTaskCategoryManager.isAppGridActivity(taskInfo)) {
+
+                    cacheTask(taskInfo);
+                }
                 return;
             }
 
@@ -322,6 +337,7 @@
                     return;
                 }
 
+                logIfDebuggable("Control Bar layout changed!");
                 updateTaskViewInsets();
                 updateBackgroundTaskViewInsets();
                 updateObscuredTouchRegion();
@@ -391,24 +407,6 @@
             mTaskViewManager = new TaskViewManager(this, getMainThreadHandler());
         }
 
-        ViewGroup backgroundAppArea = findViewById(R.id.background_app_area);
-        if (backgroundAppArea != null) {
-            setUpBackgroundTaskView(backgroundAppArea);
-        }
-
-        if (mAppGridTaskViewPanel != null) {
-            setUpAppGridTaskView();
-        }
-
-        if (mRootTaskViewPanel != null) {
-            setUpRootTaskView();
-        }
-
-        ViewGroup fullscreenContainer = findViewById(R.id.fullscreen_container);
-        if (fullscreenContainer != null) {
-            setUpFullScreenTaskView(fullscreenContainer);
-        }
-
         mCarUiPortraitDriveStateController = new CarUiPortraitDriveStateController(
                 getApplicationContext());
 
@@ -416,6 +414,8 @@
 
         initializeCards();
         doBindService();
+
+        setUpRootTaskView();
     }
 
     @Override
@@ -517,12 +517,7 @@
     }
 
     private void cacheTask(ActivityManager.RunningTaskInfo taskInfo) {
-        if (TaskCategoryManager.isHomeIntent(taskInfo)
-                || mTaskCategoryManager.isBackgroundApp(taskInfo)
-                || mTaskCategoryManager.isAppGridActivity(taskInfo)) {
-            logIfDebuggable("Skip as task is a home intent or background app " + taskInfo);
-            return;
-        }
+        logIfDebuggable("Caching the task: " + taskInfo);
         if (mTaskInfoCache.cancelTask(taskInfo)) {
             boolean cached = mTaskInfoCache.cacheTask(taskInfo);
             logIfDebuggable("Task " + taskInfo + " is cached = " + cached);
@@ -617,7 +612,8 @@
         }
     }
 
-    private void setUpBackgroundTaskView(ViewGroup parent) {
+    private void setUpBackgroundTaskView() {
+        ViewGroup parent = findViewById(R.id.background_app_area);
         mTaskViewManager.createControlledCarTaskView(getMainExecutor(),
                 ControlledCarTaskViewConfig.builder()
                         .setActivityIntent(CarLauncherUtils.getMapsIntent(getApplicationContext()))
@@ -626,7 +622,7 @@
                 new ControlledCarTaskViewCallbacks() {
                     @Override
                     public void onTaskViewCreated(CarTaskView taskView) {
-                        taskView.setTag("Background");
+                        logIfDebuggable("Background Task View is created");
                         taskView.setZOrderOnTop(false);
                         mBackgroundTaskView = taskView;
                         parent.addView(mBackgroundTaskView);
@@ -634,6 +630,9 @@
 
                     @Override
                     public void onTaskViewReady() {
+                        logIfDebuggable("Background Task View is ready");
+                        mIsBackgroundTaskViewReady = true;
+                        onTaskViewReadinessUpdated();
                         updateBackgroundTaskViewInsets();
                     }
                 }
@@ -651,6 +650,7 @@
     }
 
     private void setUpAppGridTaskView() {
+        mAppGridTaskViewPanel.setTag("AppGridPanel");
         mTaskViewManager.createControlledCarTaskView(getMainExecutor(),
                 ControlledCarTaskViewConfig.builder()
                         .setActivityIntent(CarLauncherUtils.getAppsGridIntent())
@@ -665,7 +665,9 @@
 
                     @Override
                     public void onTaskViewReady() {
-                        updateBackgroundTaskViewInsets();
+                        logIfDebuggable("App grid Task View is ready");
+                        mAppGridTaskViewPanel.setReady(true);
+                        onTaskViewReadinessUpdated();
                     }
                 }
         );
@@ -694,35 +696,63 @@
         });
     }
 
+    private boolean isAllTaskViewsReady() {
+        return mRootTaskViewPanel.isReady() && mAppGridTaskViewPanel.isReady()
+                && mIsBackgroundTaskViewReady && mIsFullScreenTaskViewReady;
+    }
+
+    private void onTaskViewReadinessUpdated() {
+        if (!isAllTaskViewsReady()) {
+            return;
+        }
+        logIfDebuggable("All task views are ready");
+        updateObscuredTouchRegion();
+        updateBackgroundTaskViewInsets();
+        notifySystemUI(MSG_FG_TASK_VIEW_READY, boolToInt(true));
+        Rect controlBarBounds = new Rect();
+        mControlBarView.getBoundsOnScreen(controlBarBounds);
+        boolean isControlBarVisible = mControlBarView.getVisibility() == View.VISIBLE;
+        logIfDebuggable("Control bar:"
+                + "( visible: " + isControlBarVisible
+                + ", bounds:" + controlBarBounds
+                + ")");
+    }
+
     private void setUpRootTaskView() {
+        mRootTaskViewPanel.setTag("RootPanel");
         mRootTaskViewPanel.setTaskViewBackgroundColor(Color.BLACK);
         mRootTaskViewPanel.setOnStateChangeListener(new TaskViewPanel.OnStateChangeListener() {
             @Override
             public void onStateChangeStart(TaskViewPanel.State oldState,
                     TaskViewPanel.State newState, boolean animated) {
-                boolean isSystemBarHidden = newState.isFullScreen();
-                if (isSystemBarHidden) {
+                boolean isFullScreen = newState.isFullScreen();
+                if (isFullScreen) {
                     setHomeScreenBottomMargin(mIsSUWInProgress ? 0 : mNavBarHeight);
+                    if (!mIsSUWInProgress) {
+                        notifySystemUI(MSG_HIDE_SYSTEM_BAR_FOR_IMMERSIVE, boolToInt(isFullScreen));
+                    }
                 } else {
-                    setHomeScreenBottomMargin(mNavBarHeight);
                     setControlBarVisibility(/* isVisible= */ true, animated);
                 }
-
-                if (!mIsSUWInProgress) {
-                    notifySystemUI(MSG_HIDE_SYSTEM_BAR_FOR_IMMERSIVE, boolToInt(isSystemBarHidden));
-                }
             }
 
             @Override
             public void onStateChangeEnd(TaskViewPanel.State oldState,
                     TaskViewPanel.State newState, boolean animated) {
                 updateObscuredTouchRegion();
-
                 updateBackgroundTaskViewInsets();
 
                 // Hide the control bar after the animation if in full screen.
                 if (newState.isFullScreen()) {
                     setControlBarVisibility(/* isVisible= */ false, animated);
+                } else {
+                    // Adjust the bottom margin to count for the nav bar.
+                    setHomeScreenBottomMargin(mNavBarHeight);
+                    // Show the nav bar if not showing Setup Wizard
+                    if (!mIsSUWInProgress) {
+                        notifySystemUI(MSG_HIDE_SYSTEM_BAR_FOR_IMMERSIVE,
+                                boolToInt(newState.isFullScreen()));
+                    }
                 }
 
                 // Hide the app grid task view behind the root task view.
@@ -739,24 +769,27 @@
                 new LaunchRootCarTaskViewCallbacks() {
                     @Override
                     public void onTaskViewCreated(CarTaskView taskView) {
+                        logIfDebuggable("Root Task View is created");
                         taskView.setZOrderMediaOverlay(true);
                         mRootTaskViewPanel.setTaskView(taskView);
                     }
 
                     @Override
                     public void onTaskViewReady() {
-                        mIsRootTaskViewReady = true;
+                        logIfDebuggable("Root Task View is ready");
+                        mRootTaskViewPanel.setReady(true);
                         mTaskInfoCache.startCachedTasks();
-                        logIfDebuggable("Foreground Task View is ready");
-                        notifySystemUI(MSG_FG_TASK_VIEW_READY, boolToInt(true));
-                        // Launch the blank activity in the root task view to make sure we do not
-                        // present a dialog on top of empty space.
-                        startActivity(BlankActivity.createIntent(getApplicationContext()));
+                        onTaskViewReadinessUpdated();
+
+                        setUpBackgroundTaskView();
+                        setUpAppGridTaskView();
+                        setUpFullScreenTaskView();
                     }
                 });
     }
 
-    private void setUpFullScreenTaskView(ViewGroup parent) {
+    private void setUpFullScreenTaskView() {
+        ViewGroup parent = findViewById(R.id.fullscreen_container);
         mTaskViewManager.createSemiControlledTaskView(getMainExecutor(),
                 new SemiControlledCarTaskViewCallbacks() {
                     @Override
@@ -769,6 +802,7 @@
 
                     @Override
                     public void onTaskViewCreated(CarTaskView taskView) {
+                        logIfDebuggable("FullScreen Task View is created");
                         mFullScreenTaskView = taskView;
                         mFullScreenTaskView.setZOrderOnTop(true);
                         parent.addView(mFullScreenTaskView);
@@ -776,6 +810,9 @@
 
                     @Override
                     public void onTaskViewReady() {
+                        logIfDebuggable("FullScreen Task View is ready");
+                        mIsFullScreenTaskViewReady = true;
+                        onTaskViewReadinessUpdated();
                     }
                 });
     }
@@ -845,9 +882,16 @@
 
     private void notifySystemUI(int key, int value) {
         Message msg = Message.obtain(null, key, value, 0);
+        notifySystemUI(msg);
+    }
+
+    private void notifySystemUI(Message msg) {
         try {
             if (mService != null) {
                 mService.send(msg);
+            } else {
+                logIfDebuggable("Service is not connected yet! Caching the message:" + msg);
+                mMessageCache.add(msg);
             }
         } catch (RemoteException e) {
             throw new RuntimeException(e);
diff --git a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/TaskViewPanel.java b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/TaskViewPanel.java
index c422c2e..84f1b61 100644
--- a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/TaskViewPanel.java
+++ b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/TaskViewPanel.java
@@ -85,6 +85,12 @@
         public boolean isFullScreen() {
             return mIsFullScreen;
         }
+
+        /** The string representation of the state. Used for debugging */
+        public String toString() {
+            return "(visible: " + isVisible() + ", fullscreen: " + isFullScreen() + ", bounds: "
+                    + mBounds + ")";
+        }
     }
 
     /** Notifies the listener when the panel state changes. */
@@ -160,6 +166,9 @@
     /** The surface view showed on the back of the panel. */
     private BackgroundSurfaceView mBackgroundSurfaceView;
 
+    /** The flag indicating if the task view on the panel is ready. */
+    private boolean mIsReady;
+
     public TaskViewPanel(Context context) {
         this(context, null);
     }
@@ -249,7 +258,8 @@
     /** Transitions the panel into the close state using the fade-out animation. */
     public void fadeOutPanel() {
         PanelAnimator animator =
-                new FadeOutPanelAnimator(this, mTaskViewOverlay, mTaskView, mOpenState.mBounds);
+                new FadeOutPanelAnimator(this, mBackgroundSurfaceView, mTaskViewOverlay,
+                        mTaskView, mOpenState.mBounds);
         setActiveState(mCloseState, animator);
     }
 
@@ -288,9 +298,19 @@
 
     /** Updates the {@code TaskView} used in the panel. */
     public void setTaskView(CarTaskView taskView) {
-        logIfDebuggable("TaskView updated " + taskView);
         mTaskView = taskView;
         mTaskViewContainer.addView(mTaskView);
+        onParentDimensionChanged();
+    }
+
+    /** Updates the readiness state of the panel. */
+    public void setReady(boolean isReady) {
+        mIsReady = isReady;
+    }
+
+    /** Returns whether the panel is ready. */
+    public boolean isReady() {
+        return mIsReady;
     }
 
     /** Refreshes the panel according to the given {@code Theme}. */
@@ -302,7 +322,6 @@
         mBackgroundSurfaceView.refresh(theme);
     }
 
-
     /**
      * Updates the Obscured touch region of the panel.
      * This need to be called if there are areas that the task view should not receive a touch
@@ -375,7 +394,11 @@
         updateInsets(mActiveState.mInsets);
         recalculateBounds();
         updateBounds(mActiveState.mBounds);
-        post(() -> mTaskView.onLocationChanged());
+        post(() -> {
+            if (mTaskView != null) {
+                mTaskView.onLocationChanged();
+            }
+        });
     }
 
     /** Sets a fixed background color for the task view. */
@@ -393,11 +416,15 @@
         int parentWidth = ((ViewGroup) getParent()).getWidth();
         int parentHeight = ((ViewGroup) getParent()).getHeight();
 
-        Log.w(TAG, "onDimensionChanged: " + parentWidth + " " + parentHeight);
+        logIfDebuggable("onDimensionChanged: " + parentWidth + " " + parentHeight);
 
         recalculateBounds();
 
-        post(() -> mTaskView.onLocationChanged());
+        post(() -> {
+            if (mTaskView != null) {
+                mTaskView.onLocationChanged();
+            }
+        });
         updateBounds(mActiveState.mBounds);
     }
 
@@ -414,8 +441,9 @@
     }
 
     private void setActiveState(State toState, PanelAnimator animator) {
-        Log.w(TAG, "SetActiveState to " + toState.mBounds);
         State fromState = mActiveState;
+        logIfDebuggable("Panel( " + getTag() + ") active state changes from " + fromState
+                + " to " + toState);
 
         boolean animated = animator != null;
         onStateChangeStart(fromState, toState, animated);
@@ -456,9 +484,12 @@
         // to a visible state and only if the window bounds is not changed since the last visible
         // state.
         Rect taskViewBounds = getTaskViewBounds(mActiveState);
-        if (mActiveState.isVisible() && !taskViewBounds.equals(mTaskViewWindowBounds)) {
-            mTaskViewWindowBounds = taskViewBounds;
-            logIfDebuggable("TaskView bounds: " + mTaskViewWindowBounds);
+        if (!mActiveState.isVisible() || taskViewBounds.equals(mTaskViewWindowBounds)) {
+            return;
+        }
+        mTaskViewWindowBounds = taskViewBounds;
+        logIfDebuggable("TaskView bounds: " + mTaskViewWindowBounds);
+        if (mTaskView != null) {
             mTaskView.setWindowBounds(taskViewBounds);
         }
     }
diff --git a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FadeOutPanelAnimator.java b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FadeOutPanelAnimator.java
index 21f2f45..2b548d8 100644
--- a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FadeOutPanelAnimator.java
+++ b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FadeOutPanelAnimator.java
@@ -39,6 +39,7 @@
     private static final float FADE_OUT_ALPHA = 0;
     private static final float FADE_IN_ALPHA = 1;
 
+    private final View mBackground;
     private final View mOverlay;
     private final View mTaskView;
     private final Rect mBounds;
@@ -47,13 +48,16 @@
      * A {@code PanelAnimator} to animate the panel into the open state using the fade-in animation.
      *
      * @param panel The panel that should animate
-     * @param overlay The overlay view that covers the taskView. Used to visually fade out the task
-     *                view.
+     * @param background The view shown behind the {@code TaskView}.
+     * @param overlay The overlay view that covers the {@code TaskView}. Used to visually fade out
+     *                the {@code TaskView}.
      * @param taskView The task view of the panel.
      * @param toBounds The final bounds of the panel within its parent
      */
-    public FadeOutPanelAnimator(ViewGroup panel, View overlay, View taskView, Rect toBounds) {
+    public FadeOutPanelAnimator(ViewGroup panel, View background, View overlay, View taskView,
+            Rect toBounds) {
         super(panel);
+        mBackground = background;
         mOverlay = overlay;
         mTaskView = taskView;
         mBounds = toBounds;
@@ -62,6 +66,7 @@
     @Override
     public void animate(Runnable endAction) {
         updateBounds(mBounds);
+        mBackground.setVisibility(GONE);
         mOverlay.setVisibility(VISIBLE);
         mOverlay.setAlpha(FADE_OUT_ALPHA);
         // First fade in the overlay and then fade-out the whole panel.
@@ -70,6 +75,7 @@
                 .withEndAction(() -> {
                     mPanel.animate().alpha(FADE_OUT_ALPHA).setDuration(PANEL_FADE_OUT_DURATION)
                             .withEndAction(() -> {
+                                mBackground.setVisibility(VISIBLE);
                                 mOverlay.setVisibility(GONE);
                                 mTaskView.setVisibility(VISIBLE);
                                 mTaskView.setAlpha(FADE_IN_ALPHA);
diff --git a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FullScreenPanelAnimator.java b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FullScreenPanelAnimator.java
index 84c1292..2019a9c 100644
--- a/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FullScreenPanelAnimator.java
+++ b/car_product/car_ui_portrait/apps/CarUiPortraitLauncher/src/com/android/car/portraitlauncher/panel/animation/FullScreenPanelAnimator.java
@@ -59,6 +59,6 @@
         Animation animation = new BoundsAnimation(mPanel, mBounds, endAction);
         animation.setInterpolator(INTERPOLATOR);
         animation.setDuration(DURATION);
-        mPanel.startAnimation(animation);
+        mPanel.post(() -> mPanel.startAnimation(animation));
     }
 }
diff --git a/car_product/car_ui_portrait/rro/CarUIPortraitCommon/src/com/android/car/caruiportrait/common/service/CarUiPortraitService.java b/car_product/car_ui_portrait/rro/CarUIPortraitCommon/src/com/android/car/caruiportrait/common/service/CarUiPortraitService.java
index 96fadd6..8b3d839 100644
--- a/car_product/car_ui_portrait/rro/CarUIPortraitCommon/src/com/android/car/caruiportrait/common/service/CarUiPortraitService.java
+++ b/car_product/car_ui_portrait/rro/CarUIPortraitCommon/src/com/android/car/caruiportrait/common/service/CarUiPortraitService.java
@@ -26,6 +26,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import android.util.Log;
 
 import java.util.ArrayList;
 
@@ -116,6 +117,7 @@
     class IncomingHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
+            Log.d(TAG, "Received message: " + msg.what);
             switch (msg.what) {
                 case MSG_REGISTER_CLIENT:
                     mClients.add(msg.replyTo);
@@ -173,6 +175,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(REQUEST_FROM_SYSTEM_UI);
         registerReceiver(immersiveModeChangeReceiver, filter);
+        Log.d(TAG, "Portrait service is created");
     }
 
     @Override
diff --git a/car_product/car_ui_portrait/rro/android/res/values-port/themes_device_defaults.xml b/car_product/car_ui_portrait/rro/android/res/values-port/themes_device_defaults.xml
index e4aef32..9348f1c 100644
--- a/car_product/car_ui_portrait/rro/android/res/values-port/themes_device_defaults.xml
+++ b/car_product/car_ui_portrait/rro/android/res/values-port/themes_device_defaults.xml
@@ -41,6 +41,7 @@
         <item name="android:colorBackgroundFloating">@color/floating_background_color</item>
         <item name="android:statusBarColor">@android:color/transparent</item>
         <item name="android:colorButtonNormal">@color/btn_device_default</item>
+        <item name="android:colorAccent">@color/car_primary</item>
         <item name="android:colorActivatedHighlight">@color/car_control_highlight</item>
         <item name="android:colorBackground">@color/car_background</item>
         <item name="android:colorControlHighlight">@color/car_control_highlight</item>
@@ -48,6 +49,8 @@
         <item name="android:colorFocusedHighlight">@color/car_control_highlight</item>
         <item name="android:textColorPrimary">@color/car_on_background</item>
         <item name="android:textColorPrimaryInverse">@color/car_background</item>
+        <item name="android:textColorSecondary">@color/car_secondary</item>
+        <item name="android:textColorSecondaryInverse">@color/car_on_secondary</item>
 
         <item name="android:listDivider">@color/list_divider_color</item>
         <item name="android:alertDialogTheme">@android:style/Theme.DeviceDefault.Dialog.Alert</item>