blob: 0b750c9400a7c892bb248e5d61e00d57445e8cc6 [file] [log] [blame]
/*
* Copyright (C) 2015 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.setupdesign.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
import com.google.android.setupcompat.PartnerCustomizationLayout;
import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper;
import com.google.android.setupcompat.util.BuildCompatUtils;
import com.google.android.setupcompat.util.Logger;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.R;
import java.util.Objects;
/** The helper class holds the constant names of themes and util functions */
public final class ThemeHelper {
private static final Logger LOG = new Logger("ThemeHelper");
/**
* Passed in a setup wizard intent as {@link WizardManagerHelper#EXTRA_THEME}. This is the dark
* variant of the theme used in setup wizard for Nougat MR1.
*/
public static final String THEME_GLIF = "glif";
/**
* Passed in a setup wizard intent as {@link WizardManagerHelper#EXTRA_THEME}. This is the default
* theme used in setup wizard for Nougat MR1.
*/
public static final String THEME_GLIF_LIGHT = "glif_light";
/**
* Passed in a setup wizard intent as {@link WizardManagerHelper#EXTRA_THEME}. This is the dark
* variant of the theme used in setup wizard for O DR.
*/
public static final String THEME_GLIF_V2 = "glif_v2";
/**
* Passed in a setup wizard intent as {@link WizardManagerHelper#EXTRA_THEME}. This is the default
* theme used in setup wizard for O DR.
*/
public static final String THEME_GLIF_V2_LIGHT = "glif_v2_light";
/**
* Passed in a setup wizard intent as {@link WizardManagerHelper#EXTRA_THEME}. This is the dark
* variant of the theme used in setup wizard for P.
*/
public static final String THEME_GLIF_V3 = "glif_v3";
/**
* Passed in a setup wizard intent as {@link WizardManagerHelper#EXTRA_THEME}. This is the default
* theme used in setup wizard for P.
*/
public static final String THEME_GLIF_V3_LIGHT = "glif_v3_light";
/**
* Placeholder, not avirailed yet.
*/
public static final String THEME_GLIF_V4 = "glif_v4";
/**
* Placeholder, not avirailed yet.
*/
public static final String THEME_GLIF_V4_LIGHT = "glif_v4_light";
public static final String THEME_HOLO = "holo";
public static final String THEME_HOLO_LIGHT = "holo_light";
public static final String THEME_MATERIAL = "material";
public static final String THEME_MATERIAL_LIGHT = "material_light";
/**
* Checks the intent whether the extra indicates that the light theme should be used or not. If
* the theme is not specified in the intent, or the theme specified is unknown, the value def will
* be returned. Note that day-night themes are not taken into account by this method.
*
* @param intent The intent used to start the activity, which the theme extra will be read from.
* @param def The default value if the theme is not specified.
* @return True if the activity started by the given intent should use light theme.
*/
public static boolean isLightTheme(Intent intent, boolean def) {
final String theme = intent.getStringExtra(WizardManagerHelper.EXTRA_THEME);
return isLightTheme(theme, def);
}
/**
* Checks whether {@code theme} represents a light or dark theme. If the theme specified is
* unknown, the value def will be returned. Note that day-night themes are not taken into account
* by this method.
*
* @param theme The theme as specified from an intent sent from setup wizard.
* @param def The default value if the theme is not known.
* @return True if {@code theme} represents a light theme.
*/
public static boolean isLightTheme(String theme, boolean def) {
if (THEME_HOLO_LIGHT.equals(theme)
|| THEME_MATERIAL_LIGHT.equals(theme)
|| THEME_GLIF_LIGHT.equals(theme)
|| THEME_GLIF_V2_LIGHT.equals(theme)
|| THEME_GLIF_V3_LIGHT.equals(theme)
|| THEME_GLIF_V4_LIGHT.equals(theme)) {
return true;
} else if (THEME_HOLO.equals(theme)
|| THEME_MATERIAL.equals(theme)
|| THEME_GLIF.equals(theme)
|| THEME_GLIF_V2.equals(theme)
|| THEME_GLIF_V3.equals(theme)
|| THEME_GLIF_V4.equals(theme)) {
return false;
} else {
return def;
}
}
/**
* Reads the theme from the intent, and applies the theme to the activity as resolved by {@link
* ThemeResolver#getDefault()}.
*
* <p>If you require extra theme attributes, consider overriding {@link
* android.app.Activity#onApplyThemeResource} in your activity and call {@link
* android.content.res.Resources.Theme#applyStyle(int, boolean)} using your theme overlay.
*
* <pre>{@code
* protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
* super.onApplyThemeResource(theme, resid, first);
* theme.applyStyle(R.style.MyThemeOverlay, true);
* }
* }</pre>
*
* @param activity the activity to get the intent from and apply the resulting theme to.
*/
public static void applyTheme(Activity activity) {
ThemeResolver.getDefault().applyTheme(activity);
}
/**
* Checks whether SetupWizard supports the DayNight theme during setup flow; if it returns false,
* setup flow is always light theme.
*
* @return true if the SetupWizard is listening to system DayNight theme setting.
*/
public static boolean isSetupWizardDayNightEnabled(@NonNull Context context) {
return PartnerConfigHelper.isSetupWizardDayNightEnabled(context);
}
/**
* Returns true if the partner provider of SetupWizard is ready to support more partner configs.
*/
public static boolean shouldApplyExtendedPartnerConfig(@NonNull Context context) {
return PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context);
}
/**
* Returns {@code true} if the partner provider of SetupWizard is ready to support dynamic color.
*/
public static boolean isSetupWizardDynamicColorEnabled(@NonNull Context context) {
return PartnerConfigHelper.isSetupWizardDynamicColorEnabled(context);
}
/** Returns {@code true} if this {@code context} should apply dynamic color. */
public static boolean shouldApplyDynamicColor(@NonNull Context context) {
return shouldApplyExtendedPartnerConfig(context) && isSetupWizardDynamicColorEnabled(context);
}
/**
* Returns a theme resource id if the {@link com.google.android.setupdesign.GlifLayout} should
* apply dynamic color.
*
* <p>Otherwise returns {@code 0}.
*/
@StyleRes
public static int getDynamicColorTheme(@NonNull Context context) {
@StyleRes int resId = 0;
Activity activity;
try {
activity = PartnerCustomizationLayout.lookupActivityFromContext(context);
} catch (IllegalArgumentException ex) {
LOG.e(Objects.requireNonNull(ex.getMessage()));
return resId;
}
boolean isSetupFlow = WizardManagerHelper.isAnySetupWizard(activity.getIntent());
boolean isDayNightEnabled = isSetupWizardDayNightEnabled(context);
if (isSetupFlow) {
// return theme for inside setup flow
resId =
isDayNightEnabled
? R.style.SudDynamicColorThemeGlifV3_DayNight
: R.style.SudDynamicColorThemeGlifV3_Light;
} else {
// return theme for outside setup flow
resId =
isDayNightEnabled
? R.style.SudFullDynamicColorThemeGlifV3_DayNight
: R.style.SudFullDynamicColorThemeGlifV3_Light;
LOG.atInfo(
"Return "
+ (isDayNightEnabled
? "SudFullDynamicColorThemeGlifV3_DayNight"
: "SudFullDynamicColorThemeGlifV3_Light"));
}
LOG.atDebug(
"Gets the dynamic accentColor: [Light] "
+ colorIntToHex(context, R.color.sud_dynamic_color_accent_glif_v3_light)
+ ", "
+ (BuildCompatUtils.isAtLeastS()
? colorIntToHex(context, android.R.color.system_accent1_600)
: "n/a")
+ ", [Dark] "
+ colorIntToHex(context, R.color.sud_dynamic_color_accent_glif_v3_dark)
+ ", "
+ (BuildCompatUtils.isAtLeastS()
? colorIntToHex(context, android.R.color.system_accent1_100)
: "n/a"));
return resId;
}
/** Returns {@code true} if the dynamic color is set. */
public static boolean trySetDynamicColor(@NonNull Context context) {
if (!shouldApplyExtendedPartnerConfig(context)) {
LOG.w("SetupWizard does not supports the extended partner configs.");
return false;
}
if (!isSetupWizardDynamicColorEnabled(context)) {
LOG.w("SetupWizard does not support the dynamic color or supporting status unknown.");
return false;
}
Activity activity;
try {
activity = PartnerCustomizationLayout.lookupActivityFromContext(context);
} catch (IllegalArgumentException ex) {
LOG.e(Objects.requireNonNull(ex.getMessage()));
return false;
}
@StyleRes int resId = getDynamicColorTheme(context);
if (resId != 0) {
activity.setTheme(resId);
} else {
LOG.w("Error occurred on getting dynamic color theme.");
return false;
}
return true;
}
private static String colorIntToHex(Context context, int colorInt) {
return String.format("#%06X", (0xFFFFFF & context.getResources().getColor(colorInt)));
}
private ThemeHelper() {}
}