Add focus outline to launcher

Fix: 310953377
Test: TBC
Flag: ACONFIG com.android.launcher3.enable_focus_outline Development
Change-Id: Ie395ec74c8a4a13a68539ca7ec6496481d96b860
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index af175ce..210cfd0 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -43,6 +43,13 @@
 }
 
 flag {
+    name: "enable_focus_outline"
+    namespace: "launcher"
+    description: "Enables focus states outline for launcher."
+    bug: "310953377"
+}
+
+flag {
     name: "enable_taskbar_no_recreate"
     namespace: "launcher"
     description: "Enables taskbar with no recreation from lifecycle changes of TaskbarActivityContext."
diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml
index 4093744..6af346e 100644
--- a/res/layout/folder_icon.xml
+++ b/res/layout/folder_icon.xml
@@ -19,7 +19,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:focusable="true" >
+    android:focusable="true"
+    android:defaultFocusHighlightEnabled="false">
     <com.android.launcher3.views.DoubleShadowBubbleTextView
         style="@style/BaseIcon.Workspace"
         android:id="@+id/folder_icon_name"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6c3b54c..53d7d0c 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -25,6 +25,7 @@
     <color name="uninstall_target_hover_tint">#FFF0592B</color>
 
     <color name="focused_background">#80c6c5c5</color>
+    <color name="focus_outline_color">@color/material_color_on_secondary_container</color>
 
     <color name="default_shadow_color_no_alpha">#FF000000</color>
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 242c439..7c0526b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -432,6 +432,9 @@
     <dimen name="split_instructions_bottom_margin_phone_portrait">60dp</dimen>
     <dimen name="split_instructions_start_margin_cancel">8dp</dimen>
 
+    <dimen name="focus_outline_radius">16dp</dimen>
+    <dimen name="focus_outline_stroke_width">3dp</dimen>
+
     <!-- Workspace grid visualization parameters -->
     <dimen name="grid_visualization_rounding_radius">16dp</dimen>
     <dimen name="grid_visualization_horizontal_cell_spacing">6dp</dimen>
diff --git a/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java b/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java
index 83003ff..1a7d797 100644
--- a/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java
+++ b/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java
@@ -20,6 +20,7 @@
 import android.view.View;
 import android.view.View.OnFocusChangeListener;
 
+import com.android.launcher3.Flags;
 import com.android.launcher3.R;
 
 /**
@@ -29,7 +30,8 @@
         implements OnFocusChangeListener {
 
     public FocusIndicatorHelper(View container) {
-        super(container, container.getResources().getColor(R.color.focused_background));
+        super(container, container.getResources().getColor(Flags.enableFocusOutline()
+                ? R.color.focus_outline_color : R.color.focused_background));
     }
 
     @Override
@@ -53,7 +55,18 @@
 
         @Override
         public void viewToRect(View v, Rect outRect) {
-            outRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
+            if (Flags.enableFocusOutline()) {
+                // Ensure the left and top would not be negative and drawn outside of canvas
+                outRect.set(Math.max(0, v.getLeft()), Math.max(0, v.getTop()), v.getRight(),
+                        v.getBottom());
+                // Stroke is drawn with half outside and half inside the view. Inset by half
+                // stroke width to move the whole stroke inside the view and avoid other views
+                // occluding it
+                int halfStrokeWidth = (int) mPaint.getStrokeWidth() / 2;
+                outRect.inset(halfStrokeWidth, halfStrokeWidth);
+            } else {
+                outRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
+            }
         }
     }
 }
diff --git a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
index 2dc8d81..8eb5c7d 100644
--- a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
+++ b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
@@ -29,6 +29,7 @@
 import android.util.FloatProperty;
 import android.view.View;
 
+import com.android.launcher3.Flags;
 import com.android.launcher3.R;
 
 /**
@@ -97,13 +98,22 @@
         mContainer = container;
 
         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mMaxAlpha = Color.alpha(color);
         mPaint.setColor(0xFF000000 | color);
+        if (Flags.enableFocusOutline()) {
+            mPaint.setStyle(Paint.Style.STROKE);
+            mPaint.setStrokeWidth(container.getResources().getDimensionPixelSize(
+                    R.dimen.focus_outline_stroke_width));
+            mRadius = container.getResources().getDimensionPixelSize(
+                    R.dimen.focus_outline_radius);
+        } else {
+            mPaint.setStyle(Paint.Style.FILL);
+            mRadius = container.getResources().getDimensionPixelSize(
+                    R.dimen.grid_visualization_rounding_radius);
+        }
+        mMaxAlpha = Color.alpha(color);
 
         setAlpha(0);
         mShift = 0;
-        mRadius = container.getResources().getDimensionPixelSize(
-                R.dimen.grid_visualization_rounding_radius);
     }
 
     protected void setAlpha(float alpha) {