Allow escrow to check components automatically

Bug: 169281141
Test: Manual
Change-Id: I7a5ee60e132d41d38a1474df930ab5e3f9105acb
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CheckCarUiComponents.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CheckCarUiComponents.java
index b4fd358..bd8462d 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CheckCarUiComponents.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CheckCarUiComponents.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
+import android.os.Handler;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -30,6 +31,7 @@
 
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.car.ui.R;
 import com.android.car.ui.utils.CarUiUtils;
 
 /**
@@ -39,45 +41,29 @@
  * To check if the activity is using the CarUI components properly, navigate to the activity and
  * run: adb shell am broadcast -a com.android.car.ui.intent.CHECK_CAR_UI_COMPONENTS. Filter
  * the logs with "CheckCarUiComponents". This is ONLY available for debug and eng builds.
+ *
+ * Other than using the adb command you can also set a boolean resource
+ * "car_ui_escrow_check_components_automatically" to true. This will generate the logs 2 seconds
+ * after launching any activity.
  */
 class CheckCarUiComponents implements Application.ActivityLifecycleCallbacks {
     private static final String TAG = CheckCarUiComponents.class.getSimpleName();
     private static final String INTENT_FILTER = "com.android.car.ui.intent.CHECK_CAR_UI_COMPONENTS";
+    private static final String NO_CAR_UI_RV = "CarUiRecyclerView not used:";
+    private static final String NO_CAR_UI_TOOLBAR = "CarUiToolbar is not used: ";
+    private static final String NO_CAR_UI_TOOLBAR_BL = "CarUiBaseLayoutToolbar is not used: ";
+    private static final String NO_CAR_UI_PREFERENCE = "CarUiPreference is not used: ";
+    private static final String NO_LIST_ITEM =
+            "CarUiListItem are not used within CarUiRecyclerView: ";
     private View mRootView;
     private boolean mIsScreenVisible;
 
+    private Handler mHandler = new Handler();
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (!mIsScreenVisible) {
-                return;
-            }
-
-            CarUiComponents carUiComponents = new CarUiComponents();
-            checkForCarUiComponents(mRootView, carUiComponents);
-            if (carUiComponents.mIsUsingCarUiRecyclerView
-                    && !carUiComponents.mIsCarUiRecyclerViewUsingListItem) {
-                Log.e(TAG, "CarUiListItem are not used within CarUiRecyclerView: ");
-                showToast(context, "CarUiListItem are not used within CarUiRecyclerView");
-            }
-            if (carUiComponents.mIsUsingAndroidXRecyclerView) {
-                Log.e(TAG, "CarUiRecyclerView not used: ");
-                showToast(context, "CarUiRecycler is not used");
-            }
-            if (!carUiComponents.mIsUsingCarUiToolbar) {
-                Log.e(TAG, "CarUiToolbar is not used: ");
-                showToast(context, "CarUiToolbar is not used");
-            }
-            if (!carUiComponents.mIsUsingCarUiBaseLayoutToolbar
-                    && carUiComponents.mIsUsingCarUiToolbar) {
-                Log.e(TAG, "CarUiBaseLayoutToolbar is not used: ");
-                showToast(context, "CarUiBaseLayoutToolbar is not used");
-            }
-            if (carUiComponents.mIsUsingCarUiRecyclerViewForPreference
-                    && !carUiComponents.mIsUsingCarUiPreference) {
-                Log.e(TAG, "CarUiPreference is not used: ");
-                showToast(context, "CarUiPreference is not used");
-            }
+            checkForComponents(context, true);
         }
     };
 
@@ -97,8 +83,17 @@
 
     @Override
     public void onActivityResumed(Activity activity) {
+    }
+
+    @Override
+    public void onActivityPostResumed(Activity activity) {
         mRootView = activity.getWindow().getDecorView().getRootView();
         mIsScreenVisible = true;
+        if (checkComponentsForAllActivities(activity)) {
+            // post a message after 2 seconds delay. This is an arbitrary number so that activity
+            // is ready with all its views rendered by this time.
+            mHandler.postDelayed(() -> checkForComponents(activity, false), 2000);
+        }
     }
 
     @Override
@@ -108,6 +103,7 @@
 
     @Override
     public void onActivityStopped(Activity activity) {
+        mHandler.removeCallbacksAndMessages(null);
     }
 
     @Override
@@ -122,6 +118,43 @@
         }
     }
 
+    private boolean checkComponentsForAllActivities(Context context) {
+        return context.getResources().getBoolean(
+                R.bool.car_ui_escrow_check_components_automatically);
+    }
+
+    private void checkForComponents(Context context, boolean showToast) {
+        if (!mIsScreenVisible) {
+            return;
+        }
+
+        CarUiComponents carUiComponents = new CarUiComponents();
+        checkForCarUiComponents(mRootView, carUiComponents);
+        if (carUiComponents.mIsUsingCarUiRecyclerView
+                && !carUiComponents.mIsCarUiRecyclerViewUsingListItem) {
+            Log.d(TAG, NO_LIST_ITEM);
+            mayShowToast(context, NO_LIST_ITEM, showToast);
+        }
+        if (carUiComponents.mIsUsingAndroidXRecyclerView) {
+            Log.d(TAG, NO_CAR_UI_RV);
+            mayShowToast(context, NO_CAR_UI_RV, showToast);
+        }
+        if (!carUiComponents.mIsUsingCarUiToolbar) {
+            Log.d(TAG, NO_CAR_UI_TOOLBAR);
+            mayShowToast(context, NO_CAR_UI_TOOLBAR, showToast);
+        }
+        if (!carUiComponents.mIsUsingCarUiBaseLayoutToolbar
+                && carUiComponents.mIsUsingCarUiToolbar) {
+            Log.d(TAG, NO_CAR_UI_TOOLBAR_BL);
+            mayShowToast(context, NO_CAR_UI_TOOLBAR_BL, showToast);
+        }
+        if (carUiComponents.mIsUsingCarUiRecyclerViewForPreference
+                && !carUiComponents.mIsUsingCarUiPreference) {
+            Log.d(TAG, NO_CAR_UI_PREFERENCE);
+            mayShowToast(context, NO_CAR_UI_PREFERENCE, showToast);
+        }
+    }
+
     private void checkForCarUiComponents(View v, CarUiComponents carUiComponents) {
         viewHasChildMatching(v, view -> {
             if (isCarUiRecyclerView(view)) {
@@ -194,7 +227,10 @@
         return view.getClass() == RecyclerView.class;
     }
 
-    private static void showToast(Context context, String message) {
+    private static void mayShowToast(Context context, String message, boolean show) {
+        if (!show) {
+            return;
+        }
         Toast.makeText(context, message, Toast.LENGTH_LONG).show();
     }
 
diff --git a/car-ui-lib/car-ui-lib/src/main/res-overlayable/values/overlayable.xml b/car-ui-lib/car-ui-lib/src/main/res-overlayable/values/overlayable.xml
index 824d2f6..eb3244e 100644
--- a/car-ui-lib/car-ui-lib/src/main/res-overlayable/values/overlayable.xml
+++ b/car-ui-lib/car-ui-lib/src/main/res-overlayable/values/overlayable.xml
@@ -72,6 +72,7 @@
       <item type="attr" name="title"/>
       <item type="bool" name="car_ui_enable_focus_area_background_highlight"/>
       <item type="bool" name="car_ui_enable_focus_area_foreground_highlight"/>
+      <item type="bool" name="car_ui_escrow_check_components_automatically"/>
       <item type="bool" name="car_ui_list_item_single_line_title"/>
       <item type="bool" name="car_ui_preference_list_show_full_screen"/>
       <item type="bool" name="car_ui_preference_show_chevron"/>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/bools.xml b/car-ui-lib/car-ui-lib/src/main/res/values/bools.xml
index b18a802..67efdca 100644
--- a/car-ui-lib/car-ui-lib/src/main/res/values/bools.xml
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/bools.xml
@@ -60,4 +60,7 @@
     <bool name="car_ui_focus_area_default_focus_overrides_history">true</bool>
     <!-- Whether to clear FocusArea history when the user rotates the rotary controller. -->
     <bool name="car_ui_clear_focus_area_history_when_rotating">true</bool>
+
+    <!--  Whether to log the escrow components check automatically for all the activities or not.  -->
+    <bool name="car_ui_escrow_check_components_automatically">false</bool>
 </resources>
diff --git a/car-ui-lib/tests/apitest/current.xml b/car-ui-lib/tests/apitest/current.xml
index 0509f3f..b2c79b7 100644
--- a/car-ui-lib/tests/apitest/current.xml
+++ b/car-ui-lib/tests/apitest/current.xml
@@ -8,6 +8,7 @@
   <public type="bool" name="car_ui_clear_focus_area_history_when_rotating"/>
   <public type="bool" name="car_ui_enable_focus_area_background_highlight"/>
   <public type="bool" name="car_ui_enable_focus_area_foreground_highlight"/>
+  <public type="bool" name="car_ui_escrow_check_components_automatically"/>
   <public type="bool" name="car_ui_focus_area_default_focus_overrides_history"/>
   <public type="bool" name="car_ui_list_item_single_line_title"/>
   <public type="bool" name="car_ui_preference_list_show_full_screen"/>
@@ -246,7 +247,6 @@
   <public type="id" name="checkbox_widget"/>
   <public type="id" name="container"/>
   <public type="id" name="content_icon"/>
-  <public type="id" name="text_container"/>
   <public type="id" name="icon"/>
   <public type="id" name="icon_container"/>
   <public type="id" name="list"/>
@@ -265,6 +265,7 @@
   <public type="id" name="spinner"/>
   <public type="id" name="supplemental_icon"/>
   <public type="id" name="switch_widget"/>
+  <public type="id" name="text_container"/>
   <public type="id" name="textbox"/>
   <public type="id" name="title"/>
   <public type="id" name="title_template"/>