Merge Android 13 QPR1

Bug: 261731544
Merged-In: I62825661a5b260c3612420536e4d830341886a9c
Change-Id: If1fb5cf5baa3b35db7ddd9711faa75d3960a940e
diff --git a/main/java/com/google/android/setupcompat/template/FooterBarMixin.java b/main/java/com/google/android/setupcompat/template/FooterBarMixin.java
index 4d2a0c9..b77eacf 100644
--- a/main/java/com/google/android/setupcompat/template/FooterBarMixin.java
+++ b/main/java/com/google/android/setupcompat/template/FooterBarMixin.java
@@ -174,6 +174,8 @@
       TemplateLayout layout, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
     context = layout.getContext();
     footerStub = layout.findManagedViewById(R.id.suc_layout_footer);
+    FooterButtonStyleUtils.clearSavedDefaultTextColor();
+
     this.applyPartnerResources =
         layout instanceof PartnerCustomizationLayout
             && ((PartnerCustomizationLayout) layout).shouldApplyPartnerResource();
@@ -224,7 +226,6 @@
           /* isVisible= */ true, /* isUsingXml= */ true);
     }
 
-    FooterButtonStyleUtils.clearSavedDefaultTextColor();
   }
 
   protected boolean isFooterButtonAlignedEnd() {
@@ -581,10 +582,12 @@
   @CallSuper
   protected void onFooterButtonInflated(Button button, @ColorInt int defaultButtonBackgroundColor) {
     // Try to set default background
-    if (defaultButtonBackgroundColor != 0) {
-      FooterButtonStyleUtils.updateButtonBackground(button, defaultButtonBackgroundColor);
-    } else {
-      // TODO: get button background color from activity theme
+    if (!applyDynamicColor) {
+      if (defaultButtonBackgroundColor != 0) {
+        FooterButtonStyleUtils.updateButtonBackground(button, defaultButtonBackgroundColor);
+      } else {
+        // TODO: get button background color from activity theme
+      }
     }
     buttonContainer.addView(button);
     autoSetButtonBarVisibility();
diff --git a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
index 90de25e..f28cd6d 100644
--- a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
+++ b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
@@ -186,7 +186,8 @@
   }
 
   /**
-   * Checks whether an intent is running in the portal setup wizard flow.
+   * Checks whether an intent is running in the portal setup wizard flow. This API is supported
+   * since S.
    *
    * @param originalIntent The original intent that was used to start the step, usually via {@link
    *     Activity#getIntent()}.
@@ -230,8 +231,11 @@
   }
 
   /**
-   * Returns true if the intent passed in indicates that it is running in any setup wizard flow,
-   * including initial setup and deferred setup etc.
+   * Since Q, returns true if the intent passed in indicates that it is running in setup wizard
+   * flows, including initial, predeferred, deferred. Since S, it also supports portal setup.
+   *
+   * <p>Pre-Q, it is running in three setup wizard flows, including initial, predeferred, deferred
+   * setup.
    *
    * @param originalIntent The original intent that was used to start the step, usually via {@link
    *     Activity#getIntent()}.
diff --git a/main/java/com/google/android/setupcompat/view/ButtonBarLayout.java b/main/java/com/google/android/setupcompat/view/ButtonBarLayout.java
index 1157fae..1ef7b39 100644
--- a/main/java/com/google/android/setupcompat/view/ButtonBarLayout.java
+++ b/main/java/com/google/android/setupcompat/view/ButtonBarLayout.java
@@ -24,6 +24,9 @@
 import com.google.android.setupcompat.R;
 import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper;
 import com.google.android.setupcompat.template.FooterActionButton;
+import com.google.android.setupcompat.util.Logger;
+import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * An extension of LinearLayout that automatically switches to vertical orientation when it can't
@@ -33,6 +36,8 @@
  */
 public class ButtonBarLayout extends LinearLayout {
 
+  private static final Logger LOG = new Logger(ButtonBarLayout.class);
+
   private boolean stacked = false;
   private int originalPaddingLeft;
   private int originalPaddingRight;
@@ -82,6 +87,8 @@
       return;
     }
     this.stacked = stacked;
+    boolean isUnstack = false;
+    int primaryStyleButtonCount = 0;
     int childCount = getChildCount();
     for (int i = 0; i < childCount; i++) {
       View child = getChildAt(i);
@@ -94,16 +101,34 @@
         Float weight = (Float) child.getTag(R.id.suc_customization_original_weight);
         if (weight != null) {
           childParams.weight = weight;
+        } else {
+          // If the tag in the child is gone, it will be unstack and the child in the container will
+          // be disorder.
+          isUnstack = true;
+        }
+        if (isPrimaryButtonStyle(child)) {
+          primaryStyleButtonCount++;
         }
       }
       child.setLayoutParams(childParams);
     }
 
     setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
-
-    // Reverse the child order, so that the primary button is towards the top when vertical
-    for (int i = childCount - 1; i >= 0; i--) {
-      bringChildToFront(getChildAt(i));
+    if (isUnstack) {
+      LOG.w("Reorder the FooterActionButtons in the container");
+      ArrayList<View> childViewsInContainerInOrder =
+          getChildViewsInContainerInOrder(
+              childCount, /* isOnePrimaryButton= */ (primaryStyleButtonCount <= 1));
+      for (int i = 0; i < childCount; i++) {
+        View view = childViewsInContainerInOrder.get(i);
+        if (view != null) {
+          bringChildToFront(view);
+        }
+      }
+    } else {
+      for (int i = childCount - 1; i >= 0; i--) {
+        bringChildToFront(getChildAt(i));
+      }
     }
 
     if (stacked) {
@@ -122,6 +147,52 @@
     }
   }
 
+  private boolean isPrimaryButtonStyle(View child) {
+    return child instanceof FooterActionButton
+        && ((FooterActionButton) child).isPrimaryButtonStyle();
+  }
+
+  /**
+   * Return a array which store child views in the container and in the order (secondary button,
+   * space view, primary button), if only one primary button, the child views will replace null
+   * value in specific proper position, if there are two primary buttons, expected get the original
+   * child by the order (space view, secondary button, primary button), so insert the space view to
+   * the middle in the array.
+   */
+  private ArrayList<View> getChildViewsInContainerInOrder(
+      int childCount, boolean isOnePrimaryButton) {
+    int childViewsInContainerCount = 3;
+    int secondaryButtonIndex = 0;
+    int spaceViewIndex = 1;
+    int primaryButtonIndex = 2;
+
+    ArrayList<View> childFooterButtons = new ArrayList<>();
+
+    if (isOnePrimaryButton) {
+      childFooterButtons.addAll(Collections.nCopies(childViewsInContainerCount, null));
+    }
+
+    for (int i = 0; i < childCount; i++) {
+      View childAt = getChildAt(i);
+      if (isOnePrimaryButton) {
+        if (isPrimaryButtonStyle(childAt)) {
+          childFooterButtons.set(primaryButtonIndex, childAt);
+        } else if (!(childAt instanceof FooterActionButton)) {
+          childFooterButtons.set(spaceViewIndex, childAt);
+        } else {
+          childFooterButtons.set(secondaryButtonIndex, childAt);
+        }
+      } else {
+        if (!(childAt instanceof FooterActionButton)) {
+          childFooterButtons.add(spaceViewIndex, childAt);
+        } else {
+          childFooterButtons.add(getChildAt(i));
+        }
+      }
+    }
+    return childFooterButtons;
+  }
+
   private boolean isFooterButtonsEventlyWeighted(Context context) {
     int childCount = getChildCount();
     int primayButtonCount = 0;
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
index c9a1966..ea0dfd7 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
@@ -251,6 +251,20 @@
   CONFIG_DESCRIPTION_TEXT_MARGIN_BOTTOM(
       PartnerConfigKey.KEY_DESCRIPTION_TEXT_MARGIN_BOTTOM, ResourceType.DIMENSION),
 
+  // Font size of the account name
+  CONFIG_ACCOUNT_NAME_TEXT_SIZE(
+      PartnerConfigKey.KEY_ACCOUNT_NAME_TEXT_SIZE, ResourceType.DIMENSION),
+
+  // Font family of the account name
+  CONFIG_ACCOUNT_NAME_FONT_FAMILY(PartnerConfigKey.KEY_ACCOUNT_NAME_FONT_FAMILY, ResourceType.STRING),
+
+  // Margin end of the account avatar
+  CONFIG_ACCOUNT_AVATAR_MARGIN_END(
+      PartnerConfigKey.KEY_ACCOUNT_AVATAR_MARGIN_END, ResourceType.DIMENSION),
+
+  // Size of account avatar
+  CONFIG_ACCOUNT_AVATAR_SIZE(PartnerConfigKey.KEY_ACCOUNT_AVATAR_MAX_SIZE, ResourceType.DIMENSION),
+
   // Text size of the body content text
   CONFIG_CONTENT_TEXT_SIZE(PartnerConfigKey.KEY_CONTENT_TEXT_SIZE, ResourceType.DIMENSION),
 
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
index aca9a07..0db37ae 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
@@ -69,6 +69,9 @@
   @VisibleForTesting
   public static final String IS_NEUTRAL_BUTTON_STYLE_ENABLED_METHOD = "isNeutralButtonStyleEnabled";
 
+  @VisibleForTesting
+  public static final String GET_SUW_DEFAULT_THEME_STRING_METHOD = "suwDefaultThemeString";
+
   @VisibleForTesting public static final String SUW_PACKAGE_NAME = "com.google.android.setupwizard";
   @VisibleForTesting public static final String MATERIAL_YOU_RESOURCE_SUFFIX = "_material_you";
 
@@ -82,6 +85,8 @@
 
   @VisibleForTesting public static Bundle applyNeutralButtonStyleBundle = null;
 
+  @VisibleForTesting public static Bundle suwDefaultThemeBundle = null;
+
   private static PartnerConfigHelper instance = null;
 
   @VisibleForTesting Bundle resultBundle = null;
@@ -93,8 +98,7 @@
 
   private static int savedConfigUiMode;
 
-  @VisibleForTesting
-  public static int savedOrientation = Configuration.ORIENTATION_PORTRAIT;
+  @VisibleForTesting public static int savedOrientation = Configuration.ORIENTATION_PORTRAIT;
 
   /**
    * When testing related to fake PartnerConfigHelper instance, should sync the following saved
@@ -622,6 +626,7 @@
     applyMaterialYouConfigBundle = null;
     applyDynamicColorBundle = null;
     applyNeutralButtonStyleBundle = null;
+    suwDefaultThemeBundle = null;
   }
 
   /**
@@ -711,6 +716,34 @@
         && applyMaterialYouConfigBundle.getBoolean(IS_MATERIAL_YOU_STYLE_ENABLED_METHOD, false));
   }
 
+  /**
+   * Returns default glif theme name string from setupwizard, or if the setupwizard has not
+   * supported this api, return a null string.
+   */
+  @Nullable
+  public static String getSuwDefaultThemeString(@NonNull Context context) {
+    if (suwDefaultThemeBundle == null || suwDefaultThemeBundle.isEmpty()) {
+      try {
+        suwDefaultThemeBundle =
+            context
+                .getContentResolver()
+                .call(
+                    getContentUri(),
+                    GET_SUW_DEFAULT_THEME_STRING_METHOD,
+                    /* arg= */ null,
+                    /* extras= */ null);
+      } catch (IllegalArgumentException | SecurityException exception) {
+        Log.w(TAG, "SetupWizard default theme status unknown; return as null.");
+        suwDefaultThemeBundle = null;
+        return null;
+      }
+    }
+    if (suwDefaultThemeBundle == null || suwDefaultThemeBundle.isEmpty()) {
+      return null;
+    }
+    return suwDefaultThemeBundle.getString(GET_SUW_DEFAULT_THEME_STRING_METHOD);
+  }
+
   /** Returns true if the SetupWizard supports the dynamic color during setup flow. */
   public static boolean isSetupWizardDynamicColorEnabled(@NonNull Context context) {
     if (applyDynamicColorBundle == null) {
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
index 9554ff3..a5f9c3a 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
@@ -86,6 +86,10 @@
   PartnerConfigKey.KEY_DESCRIPTION_LINK_FONT_FAMILY,
   PartnerConfigKey.KEY_DESCRIPTION_TEXT_MARGIN_TOP,
   PartnerConfigKey.KEY_DESCRIPTION_TEXT_MARGIN_BOTTOM,
+  PartnerConfigKey.KEY_ACCOUNT_NAME_TEXT_SIZE,
+  PartnerConfigKey.KEY_ACCOUNT_NAME_FONT_FAMILY,
+  PartnerConfigKey.KEY_ACCOUNT_AVATAR_MARGIN_END,
+  PartnerConfigKey.KEY_ACCOUNT_AVATAR_MAX_SIZE,
   PartnerConfigKey.KEY_CONTENT_TEXT_SIZE,
   PartnerConfigKey.KEY_CONTENT_TEXT_COLOR,
   PartnerConfigKey.KEY_CONTENT_LINK_TEXT_COLOR,
@@ -338,6 +342,18 @@
   // Margin bottom of the header text
   String KEY_DESCRIPTION_TEXT_MARGIN_BOTTOM = "setup_design_description_text_margin_bottom";
 
+  // Font size of the account name
+  String KEY_ACCOUNT_NAME_TEXT_SIZE = "setup_design_account_name_text_size";
+
+  // Font family of the account name
+  String KEY_ACCOUNT_NAME_FONT_FAMILY = "setup_design_account_name_font_family";
+
+  // Margin end of the account avatar
+  String KEY_ACCOUNT_AVATAR_MARGIN_END = "setup_design_account_avatar_margin_end";
+
+  // Size of the account avatar
+  String KEY_ACCOUNT_AVATAR_MAX_SIZE = "setup_design_account_avatar_size";
+
   // Text size of the body content text
   String KEY_CONTENT_TEXT_SIZE = "setup_design_content_text_size";