diff options
Diffstat (limited to 'main/java/com/google')
11 files changed, 141 insertions, 26 deletions
diff --git a/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java b/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java index 360a0a0..fac4b39 100644 --- a/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java +++ b/main/java/com/google/android/setupcompat/PartnerCustomizationLayout.java @@ -212,9 +212,7 @@ public class PartnerCustomizationLayout extends TemplateLayout { SetupMetricsLogger.logCustomEvent( getContext(), - CustomEvent.create( - MetricKey.get("SetupCompatMetrics", activity.getClass().getSimpleName()), - persistableBundle)); + CustomEvent.create(MetricKey.get("SetupCompatMetrics", activity), persistableBundle)); } } diff --git a/main/java/com/google/android/setupcompat/internal/FooterButtonPartnerConfig.java b/main/java/com/google/android/setupcompat/internal/FooterButtonPartnerConfig.java index 6a019fd..39b50cf 100644 --- a/main/java/com/google/android/setupcompat/internal/FooterButtonPartnerConfig.java +++ b/main/java/com/google/android/setupcompat/internal/FooterButtonPartnerConfig.java @@ -22,6 +22,8 @@ import com.google.android.setupcompat.template.FooterButton; /** Keep the partner configuration of a footer button. Used when the button is inflated. */ public class FooterButtonPartnerConfig { private final PartnerConfig buttonBackgroundConfig; + private final PartnerConfig buttonDisableAlphaConfig; + private final PartnerConfig buttonDisableBackgroundConfig; private final PartnerConfig buttonIconConfig; private final PartnerConfig buttonTextColorConfig; private final PartnerConfig buttonTextSizeConfig; @@ -33,6 +35,8 @@ public class FooterButtonPartnerConfig { private FooterButtonPartnerConfig( int partnerTheme, PartnerConfig buttonBackgroundConfig, + PartnerConfig buttonDisableAlphaConfig, + PartnerConfig buttonDisableBackgroundConfig, PartnerConfig buttonIconConfig, PartnerConfig buttonTextColorConfig, PartnerConfig buttonTextSizeConfig, @@ -45,6 +49,8 @@ public class FooterButtonPartnerConfig { this.buttonTextSizeConfig = buttonTextSizeConfig; this.buttonTextTypeFaceConfig = buttonTextTypeFaceConfig; this.buttonBackgroundConfig = buttonBackgroundConfig; + this.buttonDisableAlphaConfig = buttonDisableAlphaConfig; + this.buttonDisableBackgroundConfig = buttonDisableBackgroundConfig; this.buttonRadiusConfig = buttonRadiusConfig; this.buttonIconConfig = buttonIconConfig; this.buttonRippleColorAlphaConfig = buttonRippleColorAlphaConfig; @@ -58,6 +64,14 @@ public class FooterButtonPartnerConfig { return buttonBackgroundConfig; } + public PartnerConfig getButtonDisableAlphaConfig() { + return buttonDisableAlphaConfig; + } + + public PartnerConfig getButtonDisableBackgroundConfig() { + return buttonDisableBackgroundConfig; + } + public PartnerConfig getButtonIconConfig() { return buttonIconConfig; } @@ -86,6 +100,8 @@ public class FooterButtonPartnerConfig { public static class Builder { private final FooterButton footerButton; private PartnerConfig buttonBackgroundConfig = null; + private PartnerConfig buttonDisableAlphaConfig = null; + private PartnerConfig buttonDisableBackgroundConfig = null; private PartnerConfig buttonIconConfig = null; private PartnerConfig buttonTextColorConfig = null; private PartnerConfig buttonTextSizeConfig = null; @@ -105,6 +121,16 @@ public class FooterButtonPartnerConfig { return this; } + public Builder setButtonDisableAlphaConfig(PartnerConfig buttonDisableAlphaConfig) { + this.buttonDisableAlphaConfig = buttonDisableAlphaConfig; + return this; + } + + public Builder setButtonDisableBackgroundConfig(PartnerConfig buttonDisableBackgroundConfig) { + this.buttonDisableBackgroundConfig = buttonDisableBackgroundConfig; + return this; + } + public Builder setButtonIconConfig(PartnerConfig buttonIconConfig) { this.buttonIconConfig = buttonIconConfig; return this; @@ -144,6 +170,8 @@ public class FooterButtonPartnerConfig { return new FooterButtonPartnerConfig( partnerTheme, buttonBackgroundConfig, + buttonDisableAlphaConfig, + buttonDisableBackgroundConfig, buttonIconConfig, buttonTextColorConfig, buttonTextSizeConfig, diff --git a/main/java/com/google/android/setupcompat/internal/LifecycleFragment.java b/main/java/com/google/android/setupcompat/internal/LifecycleFragment.java index 269dd6d..d882c9d 100644 --- a/main/java/com/google/android/setupcompat/internal/LifecycleFragment.java +++ b/main/java/com/google/android/setupcompat/internal/LifecycleFragment.java @@ -24,7 +24,9 @@ import android.app.FragmentManager; import android.content.Context; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; +import android.os.PersistableBundle; import android.util.Log; +import com.google.android.setupcompat.logging.CustomEvent; import com.google.android.setupcompat.logging.MetricKey; import com.google.android.setupcompat.logging.SetupMetricsLogger; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -87,7 +89,7 @@ public class LifecycleFragment extends Fragment { @Override public void onAttach(Context context) { super.onAttach(context); - metricKey = MetricKey.get("ScreenDuration", getActivity().getClass().getSimpleName()); + metricKey = MetricKey.get("ScreenDuration", getActivity()); } @Override @@ -100,6 +102,7 @@ public class LifecycleFragment extends Fragment { public void onResume() { super.onResume(); startInNanos = ClockProvider.timeInNanos(); + logScreenResume(); } @Override @@ -107,4 +110,14 @@ public class LifecycleFragment extends Fragment { super.onPause(); durationInNanos += (ClockProvider.timeInNanos() - startInNanos); } + + private void logScreenResume() { + if (VERSION.SDK_INT >= VERSION_CODES.Q) { + PersistableBundle bundle = new PersistableBundle(); + bundle.putLong("onScreenResume", System.nanoTime()); + SetupMetricsLogger.logCustomEvent( + getActivity(), + CustomEvent.create(MetricKey.get("ScreenActivity", getActivity()), bundle)); + } + } } diff --git a/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java b/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java index 66503a7..2043a81 100644 --- a/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java +++ b/main/java/com/google/android/setupcompat/internal/SetupCompatServiceProvider.java @@ -169,7 +169,7 @@ public class SetupCompatServiceProvider { return serviceContext.state; } - private ServiceContext getCurrentServiceState() { + private synchronized ServiceContext getCurrentServiceState() { return serviceContext; } diff --git a/main/java/com/google/android/setupcompat/logging/CustomEvent.java b/main/java/com/google/android/setupcompat/logging/CustomEvent.java index 88ac05e..38c32fa 100644 --- a/main/java/com/google/android/setupcompat/logging/CustomEvent.java +++ b/main/java/com/google/android/setupcompat/logging/CustomEvent.java @@ -25,6 +25,7 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.google.android.setupcompat.internal.ClockProvider; import com.google.android.setupcompat.internal.PersistableBundles; @@ -201,6 +202,19 @@ public final class CustomEvent implements Parcelable { } } + /** + * Trims the string longer than {@code MAX_STR_LENGTH} character, only keep the first {@code + * MAX_STR_LENGTH} - 1 characters and attached … in the end. + */ + @NonNull + public static String trimsStringOverMaxLength(@NonNull String str) { + if (str.length() <= MAX_STR_LENGTH) { + return str; + } else { + return String.format("%s…", str.substring(0, MAX_STR_LENGTH - 1)); + } + } + @VisibleForTesting static final int MAX_STR_LENGTH = 50; @VisibleForTesting static final int MIN_BUNDLE_KEY_LENGTH = 3; } diff --git a/main/java/com/google/android/setupcompat/logging/MetricKey.java b/main/java/com/google/android/setupcompat/logging/MetricKey.java index 125dee9..cdfb7d7 100644 --- a/main/java/com/google/android/setupcompat/logging/MetricKey.java +++ b/main/java/com/google/android/setupcompat/logging/MetricKey.java @@ -18,6 +18,7 @@ package com.google.android.setupcompat.logging; import static com.google.android.setupcompat.internal.Validations.assertLengthInRange; +import android.app.Activity; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -40,6 +41,21 @@ public final class MetricKey implements Parcelable { /** * Creates a new instance of MetricKey. * + * @param name metric name to identify what we log + * @param activity activity of metric screen, uses to generate screenName + */ + public static MetricKey get(@NonNull String name, @NonNull Activity activity) { + String screenName = activity.getComponentName().getClassName(); + assertLengthInRange(name, "MetricKey.name", MIN_METRIC_KEY_LENGTH, MAX_METRIC_KEY_LENGTH); + Preconditions.checkArgument( + METRIC_KEY_PATTERN.matcher(name).matches(), + "Invalid MetricKey, only alpha numeric characters are allowed."); + return new MetricKey(name, screenName); + } + + /** + * Creates a new instance of MetricKey. + * * <p>NOTE: * * <ul> @@ -50,15 +66,21 @@ public final class MetricKey implements Parcelable { * </ul> */ public static MetricKey get(@NonNull String name, @NonNull String screenName) { + // We only checked the length of customized screen name, by the reason if the screenName match + // to the class name skip check it + if (!SCREEN_COMPONENTNAME_PATTERN.matcher(screenName).matches()) { + assertLengthInRange( + screenName, "MetricKey.screenName", MIN_SCREEN_NAME_LENGTH, MAX_SCREEN_NAME_LENGTH); + Preconditions.checkArgument( + SCREEN_NAME_PATTERN.matcher(screenName).matches(), + "Invalid ScreenName, only alpha numeric characters are allowed."); + } + assertLengthInRange(name, "MetricKey.name", MIN_METRIC_KEY_LENGTH, MAX_METRIC_KEY_LENGTH); - assertLengthInRange( - screenName, "MetricKey.screenName", MIN_SCREEN_NAME_LENGTH, MAX_SCREEN_NAME_LENGTH); Preconditions.checkArgument( METRIC_KEY_PATTERN.matcher(name).matches(), "Invalid MetricKey, only alpha numeric characters are allowed."); - Preconditions.checkArgument( - METRIC_KEY_PATTERN.matcher(screenName).matches(), - "Invalid MetricKey, only alpha numeric characters are allowed."); + return new MetricKey(name, screenName); } @@ -145,4 +167,7 @@ public final class MetricKey implements Parcelable { private static final int MAX_SCREEN_NAME_LENGTH = 50; private static final int MAX_METRIC_KEY_LENGTH = 30; private static final Pattern METRIC_KEY_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]+"); + private static final Pattern SCREEN_COMPONENTNAME_PATTERN = + Pattern.compile("^([a-z]+[.])+[A-Z][a-zA-Z0-9]+"); + private static final Pattern SCREEN_NAME_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]+"); } diff --git a/main/java/com/google/android/setupcompat/template/FooterBarMixin.java b/main/java/com/google/android/setupcompat/template/FooterBarMixin.java index 3c88791..bc9e5c1 100644 --- a/main/java/com/google/android/setupcompat/template/FooterBarMixin.java +++ b/main/java/com/google/android/setupcompat/template/FooterBarMixin.java @@ -303,6 +303,8 @@ public class FooterBarMixin implements Mixin { /* buttonBackgroundColorConfig= */ PartnerConfig .CONFIG_FOOTER_PRIMARY_BUTTON_BG_COLOR)) .setButtonBackgroundConfig(PartnerConfig.CONFIG_FOOTER_PRIMARY_BUTTON_BG_COLOR) + .setButtonDisableAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_ALPHA) + .setButtonDisableBackgroundConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_BG_COLOR) .setButtonIconConfig(getDrawablePartnerConfig(footerButton.getButtonType())) .setButtonRadiusConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RADIUS) .setButtonRippleColorAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RIPPLE_COLOR_ALPHA) @@ -357,6 +359,8 @@ public class FooterBarMixin implements Mixin { /* buttonBackgroundColorConfig= */ PartnerConfig .CONFIG_FOOTER_SECONDARY_BUTTON_BG_COLOR)) .setButtonBackgroundConfig(PartnerConfig.CONFIG_FOOTER_SECONDARY_BUTTON_BG_COLOR) + .setButtonDisableAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_ALPHA) + .setButtonDisableBackgroundConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_BG_COLOR) .setButtonIconConfig(getDrawablePartnerConfig(footerButton.getButtonType())) .setButtonRadiusConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RADIUS) .setButtonRippleColorAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RIPPLE_COLOR_ALPHA) @@ -428,14 +432,16 @@ public class FooterBarMixin implements Mixin { // TODO: Make sure customize attributes in theme can be applied during setup flow. // If sets background color to full transparent, the button changes to colored borderless ink // button style. - int color = PartnerConfigHelper.get(context).getColor(context, buttonBackgroundColorConfig); - if (applyPartnerResources && color == Color.TRANSPARENT) { - overrideTheme = R.style.SucPartnerCustomizationButton_Secondary; - } else if (applyPartnerResources && (color != Color.TRANSPARENT)) { - // TODO: remove the constrain (color != Color.WHITE), need to check all pages go - // well without customization. It should be fine since the default value of secondary bg color - // is set as transparent. - overrideTheme = R.style.SucPartnerCustomizationButton_Primary; + if (applyPartnerResources) { + int color = PartnerConfigHelper.get(context).getColor(context, buttonBackgroundColorConfig); + if (color == Color.TRANSPARENT) { + overrideTheme = R.style.SucPartnerCustomizationButton_Secondary; + } else if (color != Color.TRANSPARENT) { + // TODO: remove the constrain (color != Color.WHITE), need to check all pages + // go well without customization. It should be fine since the default value of secondary bg + // color is set as transparent. + overrideTheme = R.style.SucPartnerCustomizationButton_Primary; + } } return overrideTheme; } @@ -545,7 +551,10 @@ public class FooterBarMixin implements Mixin { updateButtonTypeFaceWithPartnerConfig( button, footerButtonPartnerConfig.getButtonTextTypeFaceConfig()); updateButtonBackgroundWithPartnerConfig( - button, footerButtonPartnerConfig.getButtonBackgroundConfig()); + button, + footerButtonPartnerConfig.getButtonBackgroundConfig(), + footerButtonPartnerConfig.getButtonDisableAlphaConfig(), + footerButtonPartnerConfig.getButtonDisableBackgroundConfig()); updateButtonRadiusWithPartnerConfig(button, footerButtonPartnerConfig.getButtonRadiusConfig()); updateButtonIconWithPartnerConfig(button, footerButtonPartnerConfig.getButtonIconConfig()); updateButtonRippleColorWithPartnerConfig(button, footerButtonPartnerConfig); @@ -586,25 +595,43 @@ public class FooterBarMixin implements Mixin { @TargetApi(VERSION_CODES.Q) private void updateButtonBackgroundWithPartnerConfig( - Button button, PartnerConfig buttonBackgroundConfig) { + Button button, + PartnerConfig buttonBackgroundConfig, + PartnerConfig buttonDisableAlphaConfig, + PartnerConfig buttonDisableBackgroundConfig) { Preconditions.checkArgument( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q, "Update button background only support on sdk Q or higher"); @ColorInt int color; + @ColorInt int disabledColor; + float disabledAlpha; int[] DISABLED_STATE_SET = {-android.R.attr.state_enabled}; int[] ENABLED_STATE_SET = {}; color = PartnerConfigHelper.get(context).getColor(context, buttonBackgroundConfig); + disabledAlpha = + PartnerConfigHelper.get(context).getFraction(context, buttonDisableAlphaConfig, 0f); + disabledColor = + PartnerConfigHelper.get(context).getColor(context, buttonDisableBackgroundConfig); if (color != Color.TRANSPARENT) { - TypedArray a = context.obtainStyledAttributes(new int[] {android.R.attr.disabledAlpha}); - float alpha = a.getFloat(0, DEFAULT_DISABLED_ALPHA); - a.recycle(); + if (disabledAlpha <= 0f) { + // if no partner resource, fallback to theme disable alpha + float alpha; + TypedArray a = context.obtainStyledAttributes(new int[] {android.R.attr.disabledAlpha}); + alpha = a.getFloat(0, DEFAULT_DISABLED_ALPHA); + a.recycle(); + disabledAlpha = alpha; + } + if (disabledColor == Color.TRANSPARENT) { + // if no partner resource, fallback to button background color + disabledColor = color; + } // Set text color for ripple. ColorStateList colorStateList = new ColorStateList( new int[][] {DISABLED_STATE_SET, ENABLED_STATE_SET}, - new int[] {convertRgbToArgb(color, alpha), color}); + new int[] {convertRgbToArgb(disabledColor, disabledAlpha), color}); // b/129482013: When a LayerDrawable is mutated, a new clone of its children drawables are // created, but without copying the state from the parent drawable. So even though the diff --git a/main/java/com/google/android/setupcompat/template/FooterButton.java b/main/java/com/google/android/setupcompat/template/FooterButton.java index a4d2c87..2fa8c7c 100644 --- a/main/java/com/google/android/setupcompat/template/FooterButton.java +++ b/main/java/com/google/android/setupcompat/template/FooterButton.java @@ -32,6 +32,7 @@ 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; /** @@ -285,7 +286,8 @@ public final class FooterButton implements OnClickListener { @TargetApi(VERSION_CODES.Q) public PersistableBundle getMetrics(String buttonName) { PersistableBundle bundle = new PersistableBundle(); - bundle.putString(buttonName + KEY_BUTTON_TEXT, getText().toString()); + bundle.putString( + buttonName + KEY_BUTTON_TEXT, CustomEvent.trimsStringOverMaxLength(getText().toString())); bundle.putString(buttonName + KEY_BUTTON_TYPE, getButtonTypeName()); bundle.putInt(buttonName + KEY_BUTTON_ON_CLICK_COUNT, clickCount); return bundle; diff --git a/main/java/com/google/android/setupcompat/util/ResultCodes.java b/main/java/com/google/android/setupcompat/util/ResultCodes.java index 3934b21..5fed731 100644 --- a/main/java/com/google/android/setupcompat/util/ResultCodes.java +++ b/main/java/com/google/android/setupcompat/util/ResultCodes.java @@ -24,6 +24,10 @@ public final class ResultCodes { public static final int RESULT_SKIP = RESULT_FIRST_USER; public static final int RESULT_RETRY = RESULT_FIRST_USER + 1; public static final int RESULT_ACTIVITY_NOT_FOUND = RESULT_FIRST_USER + 2; + public static final int RESULT_LIFECYCLE_NOT_MATCHED = RESULT_FIRST_USER + 3; + public static final int RESULT_FLOW_NOT_MATCHED = RESULT_FIRST_USER + 4; public static final int RESULT_FIRST_SETUP_USER = RESULT_FIRST_USER + 100; + + private ResultCodes() {} } diff --git a/main/java/com/google/android/setupcompat/util/SystemBarHelper.java b/main/java/com/google/android/setupcompat/util/SystemBarHelper.java index f336617..75e5dd3 100644 --- a/main/java/com/google/android/setupcompat/util/SystemBarHelper.java +++ b/main/java/com/google/android/setupcompat/util/SystemBarHelper.java @@ -347,4 +347,6 @@ public final class SystemBarHelper { void onDecorViewInstalled(View decorView); } + + private SystemBarHelper() {} } diff --git a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java index 36b7d38..bfe1dbb 100644 --- a/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java +++ b/main/java/com/google/android/setupcompat/util/WizardManagerHelper.java @@ -32,7 +32,7 @@ import java.util.Arrays; * shown inside the setup flow. This includes things like parsing extras passed by Wizard Manager, * and invoking Wizard Manager to start the next action. */ -public class WizardManagerHelper { +public final class WizardManagerHelper { private static final String ACTION_NEXT = "com.android.wizard.NEXT"; @@ -216,4 +216,6 @@ public class WizardManagerHelper { || isDeferredSetupWizard(originalIntent); } } + + private WizardManagerHelper() {} } |