[automerger skipped] Skip ab/6749736 in stage. am: db2c7c5552 -s ours am: f21c6d415f -s ours am: a66b5ed98f -s ours

am skip reason: Change-Id I164bb65835bac8d60cd5b9d21b698ed9cc611dc0 with SHA-1 501c2de16a is in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/external/setupcompat/+/12796112

Change-Id: I354392f29e88c6d3a9f7646e9e4a196fd640a724
diff --git a/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java b/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java
index fac4b39..896840c 100644
--- a/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java
+++ b/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java
@@ -132,15 +132,13 @@
   @Override
   protected void onBeforeTemplateInflated(AttributeSet attrs, int defStyleAttr) {
 
-    boolean isSetupFlow;
-
     // Sets default value to true since this timing
     // before PartnerCustomization members initialization
     usePartnerResourceAttr = true;
 
     activity = lookupActivityFromContext(getContext());
 
-    isSetupFlow = WizardManagerHelper.isAnySetupWizard(activity.getIntent());
+    boolean isSetupFlow = WizardManagerHelper.isAnySetupWizard(activity.getIntent());
 
     TypedArray a =
         getContext()
diff --git a/main/java/com/google/android/setupcompat/internal/FallbackThemeWrapper.java b/main/java/com/google/android/setupcompat/internal/FallbackThemeWrapper.java
index af17a62..574f614 100644
--- a/main/java/com/google/android/setupcompat/internal/FallbackThemeWrapper.java
+++ b/main/java/com/google/android/setupcompat/internal/FallbackThemeWrapper.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.content.res.Resources.Theme;
-import androidx.annotation.StyleRes;
 import android.view.ContextThemeWrapper;
+import androidx.annotation.StyleRes;
 
 /**
  * Same as {@link ContextThemeWrapper}, but the base context's theme attributes take precedence over
diff --git a/main/java/com/google/android/setupcompat/internal/PersistableBundles.java b/main/java/com/google/android/setupcompat/internal/PersistableBundles.java
index 1197645..f02265a 100644
--- a/main/java/com/google/android/setupcompat/internal/PersistableBundles.java
+++ b/main/java/com/google/android/setupcompat/internal/PersistableBundles.java
@@ -29,7 +29,7 @@
 import java.util.List;
 
 /** Contains utility methods related to {@link PersistableBundle}. */
-@TargetApi(VERSION_CODES.Q)
+@TargetApi(VERSION_CODES.LOLLIPOP_MR1)
 public final class PersistableBundles {
 
   /**
diff --git a/main/java/com/google/android/setupcompat/internal/SetupCompatServiceInvoker.java b/main/java/com/google/android/setupcompat/internal/SetupCompatServiceInvoker.java
index a1ca156..779cc8a 100644
--- a/main/java/com/google/android/setupcompat/internal/SetupCompatServiceInvoker.java
+++ b/main/java/com/google/android/setupcompat/internal/SetupCompatServiceInvoker.java
@@ -20,8 +20,8 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.RemoteException;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
+import androidx.annotation.VisibleForTesting;
 import com.google.android.setupcompat.ISetupCompatService;
 import com.google.android.setupcompat.logging.internal.SetupMetricsLoggingConstants.MetricType;
 import java.util.concurrent.ExecutorService;
@@ -68,7 +68,7 @@
       } else {
         Log.w(TAG, "logMetric failed since service reference is null. Are the permissions valid?");
       }
-    } catch (InterruptedException | TimeoutException | RemoteException e) {
+    } catch (InterruptedException | TimeoutException | RemoteException | IllegalStateException e) {
       Log.e(TAG, String.format("Exception occurred while trying to log metric = [%s]", args), e);
     }
   }
diff --git a/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java b/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java
index 2043a81..12c0a92 100644
--- a/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java
+++ b/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java
@@ -23,10 +23,10 @@
 import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.Looper;
+import android.util.Log;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import android.util.Log;
 import com.google.android.setupcompat.ISetupCompatService;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
diff --git a/main/java/com/google/android/setupcompat/internal/TemplateLayout.java b/main/java/com/google/android/setupcompat/internal/TemplateLayout.java
index 34179d6..25a3c5b 100644
--- a/main/java/com/google/android/setupcompat/internal/TemplateLayout.java
+++ b/main/java/com/google/android/setupcompat/internal/TemplateLayout.java
@@ -20,15 +20,15 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.os.Build.VERSION_CODES;
-import androidx.annotation.Keep;
-import androidx.annotation.LayoutRes;
-import androidx.annotation.StyleRes;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
+import androidx.annotation.Keep;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.StyleRes;
 import com.google.android.setupcompat.R;
 import com.google.android.setupcompat.template.Mixin;
 import java.util.HashMap;
diff --git a/main/java/com/google/android/setupcompat/logging/internal/PartnerCustomizedResourceListMetric.java b/main/java/com/google/android/setupcompat/logging/internal/PartnerCustomizedResourceListMetric.java
index 7d0b731..2aa1240 100644
--- a/main/java/com/google/android/setupcompat/logging/internal/PartnerCustomizedResourceListMetric.java
+++ b/main/java/com/google/android/setupcompat/logging/internal/PartnerCustomizedResourceListMetric.java
@@ -30,24 +30,28 @@
 @TargetApi(VERSION_CODES.Q)
 public class PartnerCustomizedResourceListMetric {
 
-  public static void logMetrics(Context context, String screenName, Bundle bundle) {
+  public static void logMetrics(Context context, String deviceDisplayName, Bundle bundle) {
     PersistableBundle logBundle =
-        buildLogBundleFromResourceConfigBundle(context.getPackageName(), bundle);
+        buildLogBundleFromResourceConfigBundle(context.getPackageName(), deviceDisplayName, bundle);
     if (!logBundle.isEmpty()) {
       SetupMetricsLogger.logCustomEvent(
           context,
-          CustomEvent.create(MetricKey.get("PartnerCustomizationResource", screenName), logBundle));
+          CustomEvent.create(
+              MetricKey.get("PartnerCustomizationResource", "NoScreenName"), logBundle));
     }
   }
 
   @VisibleForTesting
   public static PersistableBundle buildLogBundleFromResourceConfigBundle(
-      String defaultPackageName, Bundle resourceConfigBundle) {
+      String defaultPackageName, String deviceDisplayName, Bundle resourceConfigBundle) {
     PersistableBundle persistableBundle = new PersistableBundle();
+    persistableBundle.putString("deviceDisplayName", deviceDisplayName);
     for (String key : resourceConfigBundle.keySet()) {
       Bundle resourceExtra = resourceConfigBundle.getBundle(key);
       if (!resourceExtra.getString("packageName", defaultPackageName).equals(defaultPackageName)) {
         persistableBundle.putBoolean(resourceExtra.getString("resourceName", key), true);
+      } else {
+        persistableBundle.putBoolean(resourceExtra.getString("resourceName", key), false);
       }
     }
 
diff --git a/main/java/com/google/android/setupcompat/template/FooterActionButton.java b/main/java/com/google/android/setupcompat/template/FooterActionButton.java
index bb26d19..86a06d9 100644
--- a/main/java/com/google/android/setupcompat/template/FooterActionButton.java
+++ b/main/java/com/google/android/setupcompat/template/FooterActionButton.java
@@ -18,11 +18,11 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
-import androidx.annotation.Nullable;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.Button;
+import androidx.annotation.Nullable;
 
 /** Button that can react to touch when disabled. */
 public class FooterActionButton extends Button {
diff --git a/main/java/com/google/android/setupcompat/template/FooterBarMixin.java b/main/java/com/google/android/setupcompat/template/FooterBarMixin.java
index bc9e5c1..973b8f1 100644
--- a/main/java/com/google/android/setupcompat/template/FooterBarMixin.java
+++ b/main/java/com/google/android/setupcompat/template/FooterBarMixin.java
@@ -34,16 +34,6 @@
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.os.PersistableBundle;
-import androidx.annotation.AttrRes;
-import androidx.annotation.CallSuper;
-import androidx.annotation.ColorInt;
-import androidx.annotation.IdRes;
-import androidx.annotation.LayoutRes;
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StyleRes;
-import androidx.annotation.VisibleForTesting;
 import android.util.AttributeSet;
 import android.util.StateSet;
 import android.util.TypedValue;
@@ -54,6 +44,16 @@
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.LinearLayout.LayoutParams;
+import androidx.annotation.AttrRes;
+import androidx.annotation.CallSuper;
+import androidx.annotation.ColorInt;
+import androidx.annotation.IdRes;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StyleRes;
+import androidx.annotation.VisibleForTesting;
 import com.google.android.setupcompat.PartnerCustomizationLayout;
 import com.google.android.setupcompat.R;
 import com.google.android.setupcompat.internal.FooterButtonPartnerConfig;
diff --git a/main/java/com/google/android/setupcompat/template/FooterButton.java b/main/java/com/google/android/setupcompat/template/FooterButton.java
index 2fa8c7c..b23b1bb 100644
--- a/main/java/com/google/android/setupcompat/template/FooterButton.java
+++ b/main/java/com/google/android/setupcompat/template/FooterButton.java
@@ -23,14 +23,14 @@
 import android.content.res.TypedArray;
 import android.os.Build.VERSION_CODES;
 import android.os.PersistableBundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 import androidx.annotation.StyleRes;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.View.OnClickListener;
 import com.google.android.setupcompat.R;
 import com.google.android.setupcompat.logging.CustomEvent;
 import java.lang.annotation.Retention;
diff --git a/main/java/com/google/android/setupcompat/template/FooterButtonInflater.java b/main/java/com/google/android/setupcompat/template/FooterButtonInflater.java
index fe2538b..10aa052 100644
--- a/main/java/com/google/android/setupcompat/template/FooterButtonInflater.java
+++ b/main/java/com/google/android/setupcompat/template/FooterButtonInflater.java
@@ -19,10 +19,10 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
-import androidx.annotation.NonNull;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.InflateException;
+import androidx.annotation.NonNull;
 import java.io.IOException;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/main/java/com/google/android/setupcompat/template/StatusBarMixin.java b/main/java/com/google/android/setupcompat/template/StatusBarMixin.java
index 1bd6949..a818793 100644
--- a/main/java/com/google/android/setupcompat/template/StatusBarMixin.java
+++ b/main/java/com/google/android/setupcompat/template/StatusBarMixin.java
@@ -25,13 +25,13 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
-import androidx.annotation.AttrRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.Window;
 import android.widget.LinearLayout;
+import androidx.annotation.AttrRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import com.google.android.setupcompat.PartnerCustomizationLayout;
 import com.google.android.setupcompat.R;
 import com.google.android.setupcompat.partnerconfig.PartnerConfig;
diff --git a/main/java/com/google/android/setupcompat/template/SystemNavBarMixin.java b/main/java/com/google/android/setupcompat/template/SystemNavBarMixin.java
index e055d28..8050406 100644
--- a/main/java/com/google/android/setupcompat/template/SystemNavBarMixin.java
+++ b/main/java/com/google/android/setupcompat/template/SystemNavBarMixin.java
@@ -24,13 +24,13 @@
 import android.os.Build;
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.Window;
 import androidx.annotation.AttrRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.Window;
 import com.google.android.setupcompat.PartnerCustomizationLayout;
 import com.google.android.setupcompat.R;
 import com.google.android.setupcompat.internal.TemplateLayout;
@@ -83,6 +83,19 @@
       setLightSystemNavBar(
           a.getBoolean(
               R.styleable.SucSystemNavBarMixin_sucLightSystemNavBar, isLightSystemNavBar()));
+
+      // Support updating system navigation bar divider color from P.
+      if (VERSION.SDK_INT >= VERSION_CODES.P) {
+        // get fallback value from theme
+        int[] navBarDividerColorAttr = new int[] {android.R.attr.navigationBarDividerColor};
+        TypedArray typedArray =
+            templateLayout.getContext().obtainStyledAttributes(navBarDividerColorAttr);
+        int defaultColor = typedArray.getColor(/* index= */ 0, /* defValue= */ 0);
+        int sucSystemNavBarDividerColor =
+            a.getColor(R.styleable.SucSystemNavBarMixin_sucSystemNavBarDividerColor, defaultColor);
+        setSystemNavBarDividerColor(sucSystemNavBarDividerColor);
+        typedArray.recycle();
+      }
       a.recycle();
     }
   }
@@ -120,6 +133,7 @@
    *
    * @param isLight true means compatible with light theme, otherwise compatible with dark theme
    */
+
   public void setLightSystemNavBar(boolean isLight) {
     if (Build.VERSION.SDK_INT >= VERSION_CODES.O && windowOfActivity != null) {
       if (applyPartnerResources) {
@@ -158,6 +172,28 @@
   }
 
   /**
+   * Sets the divider color of navigation bar. The color will be overridden by partner resource if
+   * the activity is running in setup wizard flow.
+   *
+   * @param color the default divider color of navigation bar
+   */
+  public void setSystemNavBarDividerColor(int color) {
+    if (Build.VERSION.SDK_INT >= VERSION_CODES.P && windowOfActivity != null) {
+      if (applyPartnerResources) {
+        Context context = templateLayout.getContext();
+        // Do nothing if the old version partner provider did not contain the new config.
+        if (PartnerConfigHelper.get(context)
+            .isPartnerConfigAvailable(PartnerConfig.CONFIG_NAVIGATION_BAR_DIVIDER_COLOR)) {
+          color =
+              PartnerConfigHelper.get(context)
+                  .getColor(context, PartnerConfig.CONFIG_NAVIGATION_BAR_DIVIDER_COLOR);
+        }
+      }
+      windowOfActivity.setNavigationBarDividerColor(color);
+    }
+  }
+
+  /**
    * Hides the navigation bar, make the color of the status and navigation bars transparent, and
    * specify {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} flag so that the content is laid-out
    * behind the transparent status bar. This is commonly used with {@link
diff --git a/main/java/com/google/android/setupcompat/util/SystemBarHelper.java b/main/java/com/google/android/setupcompat/util/SystemBarHelper.java
index 75e5dd3..d61ff8b 100644
--- a/main/java/com/google/android/setupcompat/util/SystemBarHelper.java
+++ b/main/java/com/google/android/setupcompat/util/SystemBarHelper.java
@@ -24,13 +24,13 @@
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
 import android.os.Handler;
-import androidx.annotation.RequiresPermission;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowInsets;
 import android.view.WindowManager;
+import androidx.annotation.RequiresPermission;
 
 /**
  * A helper class to manage the system navigation bar and status bar. This will add various
diff --git a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
index bfe1dbb..96fedbc 100644
--- a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
+++ b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
@@ -34,7 +34,7 @@
  */
 public final class WizardManagerHelper {
 
-  private static final String ACTION_NEXT = "com.android.wizard.NEXT";
+  @VisibleForTesting public static final String ACTION_NEXT = "com.android.wizard.NEXT";
 
   // EXTRA_SCRIPT_URI and EXTRA_ACTION_ID are used in setup wizard in versions before M and are
   // kept for backwards compatibility.
@@ -43,10 +43,24 @@
 
   @VisibleForTesting static final String EXTRA_WIZARD_BUNDLE = "wizardBundle";
   private static final String EXTRA_RESULT_CODE = "com.android.setupwizard.ResultCode";
-  @VisibleForTesting public static final String EXTRA_IS_FIRST_RUN = "firstRun";
-  @VisibleForTesting static final String EXTRA_IS_DEFERRED_SETUP = "deferredSetup";
-  @VisibleForTesting static final String EXTRA_IS_PRE_DEFERRED_SETUP = "preDeferredSetup";
-  @VisibleForTesting public static final String EXTRA_IS_SETUP_FLOW = "isSetupFlow";
+
+  /** Extra for notifying an Activity that it is inside the first SetupWizard flow or not. */
+  public static final String EXTRA_IS_FIRST_RUN = "firstRun";
+
+  /** Extra for notifying an Activity that it is inside the Deferred SetupWizard flow or not. */
+  public static final String EXTRA_IS_DEFERRED_SETUP = "deferredSetup";
+
+  /** Extra for notifying an Activity that it is inside the "Pre-Deferred Setup" flow. */
+  public static final String EXTRA_IS_PRE_DEFERRED_SETUP = "preDeferredSetup";
+
+  /**
+   * Extra for notifying an Activity that it is inside the any setup flow.
+   *
+   * <p>Apps that target API levels below {@link android.os.Build.VERSION_CODES#Q} is able to
+   * determine whether Activity is inside the any setup flow by one of {@link #EXTRA_IS_FIRST_RUN},
+   * {@link #EXTRA_IS_DEFERRED_SETUP}, and {@link #EXTRA_IS_PRE_DEFERRED_SETUP} is true.
+   */
+  public static final String EXTRA_IS_SETUP_FLOW = "isSetupFlow";
 
   public static final String EXTRA_THEME = "theme";
   public static final String EXTRA_USE_IMMERSIVE_MODE = "useImmersiveMode";
diff --git a/main/res/values/attrs.xml b/main/res/values/attrs.xml
index 1a5342c..d075e81 100644
--- a/main/res/values/attrs.xml
+++ b/main/res/values/attrs.xml
@@ -52,6 +52,10 @@
              "android:windowTranslucentNavigation" should be set to false. -->
         <attr name="sucSystemNavBarBackgroundColor" format="color" />
         <attr name="sucLightSystemNavBar" format="boolean" />
+        <!-- The color for the system navigation bar divider. For this to take effect,
+             "android:windowDrawsSystemBarBackgrounds" should be set to true and
+             "android:windowTranslucentNavigation" should be set to false. -->
+        <attr name="sucSystemNavBarDividerColor" format="color" />
     </declare-styleable>
 
     <!-- FooterButton attributes -->
diff --git a/partnerconfig/AndroidManifest.xml b/partnerconfig/AndroidManifest.xml
index c95a4dd..43e2041 100644
--- a/partnerconfig/AndroidManifest.xml
+++ b/partnerconfig/AndroidManifest.xml
@@ -16,9 +16,16 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="com.google.android.setupcompat.partnerconfig">
 
-  <uses-sdk
-      android:minSdkVersion="14"
-      android:targetSdkVersion="28" />
+  <uses-sdk />
+
+  <!-- after SDK 30, package need to declare its visible packages. -->
+  <queries tools:node="merge">
+    <intent>
+      <action android:name="com.android.setupwizard.action.PARTNER_CUSTOMIZATION" />
+    </intent>
+    <provider android:authorities="com.google.android.setupwizard.partner" />
+  </queries>
 </manifest>
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
index 56256c9..f0baef3 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
@@ -30,6 +30,10 @@
   // Navigation bar background color
   CONFIG_NAVIGATION_BAR_BG_COLOR(PartnerConfigKey.KEY_NAVIGATION_BAR_BG_COLOR, ResourceType.COLOR),
 
+  // Navigation bar divider color
+  CONFIG_NAVIGATION_BAR_DIVIDER_COLOR(
+      PartnerConfigKey.KEY_NAVIGATION_BAR_DIVIDER_COLOR, ResourceType.COLOR),
+
   // Background color of the footer bar.
   CONFIG_FOOTER_BAR_BG_COLOR(PartnerConfigKey.KEY_FOOTER_BAR_BG_COLOR, ResourceType.COLOR),
 
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
index 7b9f65b..754f462 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
@@ -1,11 +1,11 @@
 /*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,22 +16,25 @@
 
 package com.google.android.setupcompat.partnerconfig;
 
+import android.app.UiModeManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
+import android.database.ContentObserver;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
 import androidx.annotation.ColorInt;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
 import com.google.android.setupcompat.partnerconfig.PartnerConfig.ResourceType;
 import java.util.EnumMap;
 
@@ -47,6 +50,11 @@
 
   @VisibleForTesting public static final String KEY_FALLBACK_CONFIG = "fallbackConfig";
 
+  @VisibleForTesting
+  public static final String IS_SUW_DAY_NIGHT_ENABLED_METHOD = "isSuwDayNightEnabled";
+
+  @VisibleForTesting static Bundle suwDayNightEnabledBundle = null;
+
   private static PartnerConfigHelper instance = null;
 
   @VisibleForTesting Bundle resultBundle = null;
@@ -54,6 +62,8 @@
   @VisibleForTesting
   final EnumMap<PartnerConfig, Object> partnerResourceCache = new EnumMap<>(PartnerConfig.class);
 
+  private static ContentObserver contentObserver;
+
   public static synchronized PartnerConfigHelper get(@NonNull Context context) {
     if (instance == null) {
       instance = new PartnerConfigHelper(context);
@@ -63,6 +73,8 @@
 
   private PartnerConfigHelper(Context context) {
     getPartnerConfigBundle(context);
+
+    registerContentObserver(context);
   }
 
   /**
@@ -75,12 +87,22 @@
   }
 
   /**
+   * Returns whether the given {@code resourceConfig} are available. This is true if setup wizard's
+   * content provider returns us a non-empty bundle, and this result bundle includes the given
+   * {@code resourceConfig} even if all the values are default, and none are customized by the
+   * overlay APK.
+   */
+  public boolean isPartnerConfigAvailable(PartnerConfig resourceConfig) {
+    return isAvailable() && resultBundle.containsKey(resourceConfig.getResourceName());
+  }
+
+  /**
    * Returns the color of given {@code resourceConfig}, or 0 if the given {@code resourceConfig} is
    * not found. If the {@code ResourceType} of the given {@code resourceConfig} is not color,
    * IllegalArgumentException will be thrown.
    *
    * @param context The context of client activity
-   * @param resourceConfig The {@code PartnerConfig} of target resource
+   * @param resourceConfig The {@link PartnerConfig} of target resource
    */
   @ColorInt
   public int getColor(@NonNull Context context, PartnerConfig resourceConfig) {
@@ -362,17 +384,14 @@
   private void getPartnerConfigBundle(Context context) {
     if (resultBundle == null || resultBundle.isEmpty()) {
       try {
-        Uri contentUri =
-            new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(SUW_AUTHORITY)
-                .appendPath(SUW_GET_PARTNER_CONFIG_METHOD)
-                .build();
         resultBundle =
             context
                 .getContentResolver()
                 .call(
-                    contentUri, SUW_GET_PARTNER_CONFIG_METHOD, /* arg= */ null, /* extras= */ null);
+                    getContentUri(),
+                    SUW_GET_PARTNER_CONFIG_METHOD,
+                    /* arg= */ null,
+                    /* extras= */ null);
         partnerResourceCache.clear();
       } catch (IllegalArgumentException | SecurityException exception) {
         Log.w(TAG, "Fail to get config from suw provider");
@@ -381,21 +400,88 @@
   }
 
   @Nullable
-  private ResourceEntry getResourceEntryFromKey(Context context, String resourceName) {
+  @VisibleForTesting
+  ResourceEntry getResourceEntryFromKey(Context context, String resourceName) {
     Bundle resourceEntryBundle = resultBundle.getBundle(resourceName);
     Bundle fallbackBundle = resultBundle.getBundle(KEY_FALLBACK_CONFIG);
     if (fallbackBundle != null) {
       resourceEntryBundle.putBundle(KEY_FALLBACK_CONFIG, fallbackBundle.getBundle(resourceName));
     }
-    return ResourceEntry.fromBundle(context, resourceEntryBundle);
+
+    return adjustResourceEntryDayNightMode(
+        context, ResourceEntry.fromBundle(context, resourceEntryBundle));
+  }
+
+  /**
+   * Force to day mode if setup wizard does not support day/night mode and current system is in
+   * night mode.
+   */
+  private static ResourceEntry adjustResourceEntryDayNightMode(
+      Context context, ResourceEntry resourceEntry) {
+    if (!isSetupWizardDayNightEnabled(context) && isNightMode(context)) {
+      if (resourceEntry == null) {
+        Log.w(TAG, "resourceEntry is null, skip to force day mode.");
+        return resourceEntry;
+      }
+      Resources resource = resourceEntry.getResources();
+      Configuration configuration = resource.getConfiguration();
+      configuration.uiMode =
+          Configuration.UI_MODE_NIGHT_NO
+              | (configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
+      resource.updateConfiguration(configuration, resource.getDisplayMetrics());
+    }
+
+    return resourceEntry;
+  }
+
+  private static boolean isNightMode(Context context) {
+    UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
+    return uiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES;
   }
 
   @VisibleForTesting
-  public static synchronized void resetForTesting() {
+  public static synchronized void resetInstance() {
     instance = null;
+    suwDayNightEnabledBundle = null;
   }
 
-  private TypedValue getTypedValueFromResource(Resources resource, int resId, int type) {
+  /**
+   * Checks whether SetupWizard supports the DayNight theme during setup flow; if return false setup
+   * flow should force to light theme.
+   *
+   * <p>Returns true if the setupwizard is listening to system DayNight theme setting.
+   */
+  public static boolean isSetupWizardDayNightEnabled(@NonNull Context context) {
+    if (suwDayNightEnabledBundle == null) {
+      try {
+        suwDayNightEnabledBundle =
+            context
+                .getContentResolver()
+                .call(
+                    getContentUri(),
+                    IS_SUW_DAY_NIGHT_ENABLED_METHOD,
+                    /* arg= */ null,
+                    /* extras= */ null);
+      } catch (IllegalArgumentException | SecurityException exception) {
+        Log.w(TAG, "SetupWizard DayNight supporting status unknown; return as false.");
+        suwDayNightEnabledBundle = null;
+        return false;
+      }
+    }
+
+    return (suwDayNightEnabledBundle != null
+        && suwDayNightEnabledBundle.getBoolean(IS_SUW_DAY_NIGHT_ENABLED_METHOD, false));
+  }
+
+  @VisibleForTesting
+  static Uri getContentUri() {
+    return new Uri.Builder()
+        .scheme(ContentResolver.SCHEME_CONTENT)
+        .authority(SUW_AUTHORITY)
+        .build();
+  }
+
+  private static TypedValue getTypedValueFromResource(Resources resource, int resId, int type) {
     TypedValue value = new TypedValue();
     resource.getValue(resId, value, true);
     if (value.type != type) {
@@ -409,8 +495,42 @@
     return value;
   }
 
-  private float getDimensionFromTypedValue(Context context, TypedValue value) {
+  private static float getDimensionFromTypedValue(Context context, TypedValue value) {
     DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
     return value.getDimension(displayMetrics);
   }
+
+  private static void registerContentObserver(Context context) {
+    if (isSetupWizardDayNightEnabled(context)) {
+      if (contentObserver != null) {
+        unregisterContentObserver(context);
+      }
+
+      Uri contentUri = getContentUri();
+      try {
+        contentObserver =
+            new ContentObserver(null) {
+              @Override
+              public void onChange(boolean selfChange) {
+                super.onChange(selfChange);
+                resetInstance();
+              }
+            };
+        context
+            .getContentResolver()
+            .registerContentObserver(contentUri, /* notifyForDescendants= */ true, contentObserver);
+      } catch (SecurityException | NullPointerException | IllegalArgumentException e) {
+        Log.w(TAG, "Failed to register content observer for " + contentUri + ": " + e);
+      }
+    }
+  }
+
+  private static void unregisterContentObserver(Context context) {
+    try {
+      context.getContentResolver().unregisterContentObserver(contentObserver);
+      contentObserver = null;
+    } catch (SecurityException | NullPointerException | IllegalArgumentException e) {
+      Log.w(TAG, "Failed to unregister content observer: " + e);
+    }
+  }
 }
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
index e5c5442..840472e 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
@@ -28,6 +28,7 @@
   PartnerConfigKey.KEY_LIGHT_STATUS_BAR,
   PartnerConfigKey.KEY_NAVIGATION_BAR_BG_COLOR,
   PartnerConfigKey.KEY_LIGHT_NAVIGATION_BAR,
+  PartnerConfigKey.KEY_NAVIGATION_BAR_DIVIDER_COLOR,
   PartnerConfigKey.KEY_FOOTER_BAR_BG_COLOR,
   PartnerConfigKey.KEY_FOOTER_BUTTON_FONT_FAMILY,
   PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_ADD_ANOTHER,
@@ -87,6 +88,9 @@
   // such that it is compatible with a light navigation bar background.
   String KEY_LIGHT_NAVIGATION_BAR = "setup_compat_light_navigation_bar";
 
+  // Navigation bar divider color
+  String KEY_NAVIGATION_BAR_DIVIDER_COLOR = "setup_compat_navigation_bar_divider_color";
+
   // Background color of the footer bar.
   String KEY_FOOTER_BAR_BG_COLOR = "setup_compat_footer_bar_bg_color";
 
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java
index 8f7c9d8..c8b8623 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java
@@ -23,10 +23,10 @@
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
+import android.util.Log;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import android.util.Log;
 
 /**
  * A potentially cross-package resource entry, which can then be retrieved using {@link