Snap for 11526283 from 131aa921e4c30dc0ef04e36adc92004c89866ba5 to 24Q2-release
Change-Id: I4875a460870c17a0aa639ea26ce16377b905a947
diff --git a/main/java/com/google/android/setupcompat/util/ForceTwoPaneHelper.java b/main/java/com/google/android/setupcompat/util/ForceTwoPaneHelper.java
new file mode 100644
index 0000000..e69b890
--- /dev/null
+++ b/main/java/com/google/android/setupcompat/util/ForceTwoPaneHelper.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2024 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.setupcompat.util;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+import androidx.annotation.LayoutRes;
+import com.google.android.setupcompat.partnerconfig.PartnerConfig;
+import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper;
+
+/**
+ * A helper class to support force two pane feature on portrait orientation. This will inflate the
+ * layout from xml resource which concatenates with _two_pane suffix.
+ */
+public final class ForceTwoPaneHelper {
+
+ // Refer Support different screen sizes as guideline that any device that the width >= 600 will
+ // consider as large screen
+ // https://developer.android.com/guide/topics/large-screens/support-different-screen-sizes
+ private static final int DEFAULT_ADAPT_WINDOW_WIDTH = 600;
+
+ private static final Logger LOG = new Logger("ForceTwoPaneHelper");
+
+ /** A string to be a suffix of resource name which is associating to force two pane feature. */
+ public static final String FORCE_TWO_PANE_SUFFIX = "_two_pane";
+
+ /**
+ * Returns true to indicate the forced two pane feature is enabled, otherwise, returns false. This
+ * feature is supported from Sdk U while the feature enabled from SUW side.
+ */
+ public static boolean isForceTwoPaneEnable(Context context) {
+ return Build.VERSION.SDK_INT >= VERSION_CODES.UPSIDE_DOWN_CAKE
+ && PartnerConfigHelper.isForceTwoPaneEnabled(context);
+ }
+
+ /**
+ * Returns true if satisfied 1) enable force two-pane feature, 2) portrait mode, 3) width >=
+ * setup_compat_two_pane_adapt_window_width, forced to show in two-pane style, otherwise, returns
+ * false.
+ */
+ public static boolean shouldForceTwoPane(Context context) {
+ if (!isForceTwoPaneEnable(context)) {
+ return false;
+ }
+
+ if (context == null) {
+ return false;
+ }
+
+ WindowManager windowManager = context.getSystemService(WindowManager.class);
+ if (windowManager != null) {
+ WindowMetrics windowMetrics = windowManager.getCurrentWindowMetrics();
+ if (windowMetrics.getBounds().width() > windowMetrics.getBounds().height()) {
+ // Return false for portrait mode
+ return false;
+ }
+
+ int widthInDp = (int) (windowMetrics.getBounds().width() / windowMetrics.getDensity());
+ int adaptWindowWidth =
+ PartnerConfigHelper.get(context)
+ .getInteger(
+ context,
+ PartnerConfig.CONFIG_TWO_PANE_ADAPT_WINDOW_WIDTH,
+ DEFAULT_ADAPT_WINDOW_WIDTH);
+ return widthInDp >= adaptWindowWidth;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a layout which is picking up from the layout resources with _two_pane suffix. Fallback
+ * to origin resource id if the layout resource not available. For example, pass an
+ * glif_sud_template resource id and it will return glif_sud_template_two_pane resource id if it
+ * available.
+ */
+ @LayoutRes
+ @SuppressLint("DiscouragedApi")
+ public static int getForceTwoPaneStyleLayout(Context context, int template) {
+ if (!isForceTwoPaneEnable(context)) {
+ return template;
+ }
+
+ if (template == Resources.ID_NULL) {
+ return template;
+ }
+
+ try {
+ String layoutResName = context.getResources().getResourceEntryName(template);
+ int twoPaneLayoutId =
+ context
+ .getResources()
+ .getIdentifier(
+ layoutResName + FORCE_TWO_PANE_SUFFIX, "layout", context.getPackageName());
+ if (twoPaneLayoutId != Resources.ID_NULL) {
+ return twoPaneLayoutId;
+ }
+ } catch (NotFoundException ignore) {
+ LOG.w("Resource id 0x" + Integer.toHexString(template) + " is not found");
+ }
+
+ return template;
+ }
+
+ private ForceTwoPaneHelper() {}
+}
diff --git a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
index 19eea8a..1378c06 100644
--- a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
+++ b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java
@@ -35,12 +35,18 @@
/** Enum for notifying an Activity that what SetupWizard flow is */
public enum SuwLifeCycleEnum {
- UNKNOWN,
- INITIALIZATION,
- PREDEFERRED,
- DEFERRED,
- PORTAL,
- RESTORE_ANYTIME;
+ UNKNOWN(0),
+ INITIALIZATION(1),
+ PREDEFERRED(2),
+ DEFERRED(3),
+ PORTAL(4),
+ RESTORE_ANYTIME(5);
+
+ public final int value;
+
+ SuwLifeCycleEnum(int value) {
+ this.value = value;
+ }
}
/** Extra for notifying an Activity that what SetupWizard flow is. */
@@ -140,7 +146,7 @@
// The TikTok code in Restore doesn't let us put serializable extras into intents.
dstIntent.putExtra(
EXTRA_SUW_LIFECYCLE,
- srcIntent.getIntExtra(EXTRA_SUW_LIFECYCLE, SuwLifeCycleEnum.UNKNOWN.ordinal()));
+ srcIntent.getIntExtra(EXTRA_SUW_LIFECYCLE, SuwLifeCycleEnum.UNKNOWN.value));
dstIntent.putExtra(EXTRA_THEME, srcIntent.getStringExtra(EXTRA_THEME));
}
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
index efa3b7a..7ab946d 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
@@ -275,7 +275,8 @@
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),
+ CONFIG_ACCOUNT_NAME_FONT_FAMILY(
+ PartnerConfigKey.KEY_ACCOUNT_NAME_FONT_FAMILY, ResourceType.STRING),
// Margin end of the account avatar
CONFIG_ACCOUNT_AVATAR_MARGIN_END(
@@ -499,7 +500,11 @@
// The margin bottom of progress bar.
CONFIG_PROGRESS_BAR_MARGIN_BOTTOM(
- PartnerConfigKey.KEY_PROGRESS_BAR_MARGIN_BOTTOM, ResourceType.DIMENSION);
+ PartnerConfigKey.KEY_PROGRESS_BAR_MARGIN_BOTTOM, ResourceType.DIMENSION),
+
+ // The adapt window width to be part of determining two pane style condition
+ CONFIG_TWO_PANE_ADAPT_WINDOW_WIDTH(
+ PartnerConfigKey.KEY_TWO_PANE_ADAPT_WINDOW_WIDTH, ResourceType.INTEGER);
/** Resource type of the partner resources type. */
public enum ResourceType {
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
index e87d998..f027011 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
@@ -85,6 +85,9 @@
"isEmbeddedActivityOnePaneEnabled";
@VisibleForTesting
+ public static final String IS_FORCE_TWO_PANE_ENABLED_METHOD = "isForceTwoPaneEnabled";
+
+ @VisibleForTesting
public static final String GET_SUW_DEFAULT_THEME_STRING_METHOD = "suwDefaultThemeString";
@VisibleForTesting public static final String SUW_PACKAGE_NAME = "com.google.android.setupwizard";
@@ -125,6 +128,10 @@
@VisibleForTesting static Bundle applyTransitionBundle = null;
+ @SuppressWarnings("NonFinalStaticField")
+ @VisibleForTesting
+ public static Bundle applyForceTwoPaneBundle = null;
+
@VisibleForTesting public static int savedOrientation = Configuration.ORIENTATION_PORTRAIT;
/** The method name to get if transition settings is set from client. */
@@ -139,6 +146,9 @@
@VisibleForTesting public static int savedScreenWidth = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
+ /** A string to be a suffix of resource name which is associating to force two pane feature. */
+ @VisibleForTesting static final String FORCE_TWO_PANE_SUFFIX = "_two_pane";
+
public static synchronized PartnerConfigHelper get(@NonNull Context context) {
if (!isValidInstance(context)) {
instance = new PartnerConfigHelper(context);
@@ -593,6 +603,8 @@
if (BuildCompatUtils.isAtLeastU() && isActivityEmbedded(context)) {
resourceEntry = adjustEmbeddedActivityResourceEntryDefaultValue(context, resourceEntry);
+ } else if (BuildCompatUtils.isAtLeastU() && isForceTwoPaneEnabled(context)) {
+ resourceEntry = adjustForceTwoPaneResourceEntryDefaultValue(context, resourceEntry);
} else if (BuildCompatUtils.isAtLeastT() && shouldApplyMaterialYouStyle(context)) {
resourceEntry = adjustMaterialYouResourceEntryDefaultValue(context, resourceEntry);
}
@@ -730,6 +742,49 @@
return inputResourceEntry;
}
+ // Retrieve {@code resourceEntry} with _two_pane suffix resource from the partner resource,
+ // otherwise fallback to origin partner resource if two pane resource not available.
+ ResourceEntry adjustForceTwoPaneResourceEntryDefaultValue(
+ Context context, ResourceEntry resourceEntry) {
+ if (context == null) {
+ return resourceEntry;
+ }
+
+ try {
+ String resourceTypeName =
+ resourceEntry.getResources().getResourceTypeName(resourceEntry.getResourceId());
+ String forceTwoPaneResourceName =
+ resourceEntry.getResourceName().concat(FORCE_TWO_PANE_SUFFIX);
+ int twoPaneResourceId =
+ resourceEntry
+ .getResources()
+ .getIdentifier(
+ forceTwoPaneResourceName, resourceTypeName, resourceEntry.getPackageName());
+ if (twoPaneResourceId != Resources.ID_NULL) {
+ Log.i(TAG, "two pane resource=" + forceTwoPaneResourceName);
+ return new ResourceEntry(
+ resourceEntry.getPackageName(),
+ forceTwoPaneResourceName,
+ twoPaneResourceId,
+ resourceEntry.getResources());
+ } else {
+ // If resource id is not available from the Overlay package, try to get it from setup wizard
+ // package.
+ PackageManager packageManager = context.getPackageManager();
+ Resources resources = packageManager.getResourcesForApplication(SUW_PACKAGE_NAME);
+ twoPaneResourceId =
+ resources.getIdentifier(forceTwoPaneResourceName, resourceTypeName, SUW_PACKAGE_NAME);
+ if (twoPaneResourceId != 0) {
+ return new ResourceEntry(
+ SUW_PACKAGE_NAME, forceTwoPaneResourceName, twoPaneResourceId, resources);
+ }
+ }
+ } catch (NameNotFoundException | NotFoundException ignore) {
+ // fall through
+ }
+ return resourceEntry;
+ }
+
@VisibleForTesting
public static synchronized void resetInstance() {
instance = null;
@@ -742,6 +797,7 @@
applyEmbeddedActivityOnePaneBundle = null;
suwDefaultThemeBundle = null;
applyTransitionBundle = null;
+ applyForceTwoPaneBundle = null;
}
/**
@@ -982,8 +1038,7 @@
* than the client.
*/
public static boolean isGlifThemeControlledTransitionApplied(@NonNull Context context) {
- if (applyTransitionBundle == null
- || applyTransitionBundle.isEmpty()) {
+ if (applyTransitionBundle == null || applyTransitionBundle.isEmpty()) {
try {
applyTransitionBundle =
context
@@ -1000,14 +1055,34 @@
+ " as default value");
}
}
- if (applyTransitionBundle != null
- && !applyTransitionBundle.isEmpty()) {
- return applyTransitionBundle.getBoolean(
- APPLY_GLIF_THEME_CONTROLLED_TRANSITION_METHOD, true);
+ if (applyTransitionBundle != null && !applyTransitionBundle.isEmpty()) {
+ return applyTransitionBundle.getBoolean(APPLY_GLIF_THEME_CONTROLLED_TRANSITION_METHOD, true);
}
return true;
}
+ /** Returns a boolean indicate whether the force two pane feature enable or not. */
+ public static boolean isForceTwoPaneEnabled(@NonNull Context context) {
+ if (applyForceTwoPaneBundle == null || applyForceTwoPaneBundle.isEmpty()) {
+ try {
+ applyForceTwoPaneBundle =
+ context
+ .getContentResolver()
+ .call(
+ getContentUri(),
+ IS_FORCE_TWO_PANE_ENABLED_METHOD,
+ /* arg= */ null,
+ /* extras= */ null);
+ } catch (IllegalArgumentException | SecurityException exception) {
+ Log.w(TAG, "isForceTwoPaneEnabled status is unknown; return as false.");
+ }
+ }
+ if (applyForceTwoPaneBundle != null && !applyForceTwoPaneBundle.isEmpty()) {
+ return applyForceTwoPaneBundle.getBoolean(IS_FORCE_TWO_PANE_ENABLED_METHOD, false);
+ }
+ return false;
+ }
+
@VisibleForTesting
static Uri getContentUri() {
return new Uri.Builder()
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
index fb05a40..220054c 100644
--- a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
@@ -150,6 +150,7 @@
PartnerConfigKey.KEY_LOADING_LAYOUT_WAIT_FOR_ANIMATION_FINISHED,
PartnerConfigKey.KEY_PROGRESS_BAR_MARGIN_TOP,
PartnerConfigKey.KEY_PROGRESS_BAR_MARGIN_BOTTOM,
+ PartnerConfigKey.KEY_TWO_PANE_ADAPT_WINDOW_WIDTH,
})
// TODO: can be removed and always reference PartnerConfig.getResourceName()?
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
@@ -566,4 +567,7 @@
// A margin bottom of the content frame of progress bar.
String KEY_PROGRESS_BAR_MARGIN_BOTTOM = "setup_design_progress_bar_margin_bottom";
+
+ // A adapt window width to determine how large to show two panel.
+ String KEY_TWO_PANE_ADAPT_WINDOW_WIDTH = "setup_compat_two_pane_adapt_window_width";
}