blob: f26da7f9e5f158ca705cc7da52baf2a96d5ba524 [file]
/*
* Copyright (C) 2021 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.android.managedprovisioning.common;
import static android.content.res.Configuration.UI_MODE_NIGHT_MASK;
import static android.content.res.Configuration.UI_MODE_NIGHT_YES;
import static com.android.managedprovisioning.provisioning.Constants.FLAG_ENABLE_LIGHT_DARK_MODE;
import static com.google.android.setupdesign.util.ThemeHelper.trySetDynamicColor;
import static java.util.Objects.requireNonNull;
import android.content.Context;
import android.content.Intent;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.webkit.WebSettings;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.webkit.WebSettingsCompat;
import androidx.webkit.WebViewFeature;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieComposition;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.R;
import com.google.android.setupdesign.util.ThemeResolver;
/**
* Helper with utility methods to manage the ManagedProvisioning theme and night mode.
*/
public class ThemeHelper {
private static final String SYSTEM_PROPERTY_SETUPWIZARD_THEME =
SystemProperties.get("setupwizard.theme");
private final NightModeChecker mNightModeChecker;
private final SetupWizardBridge mSetupWizardBridge;
private final AnimationDynamicColorsHelper mAnimationDynamicColorsHelper;
public ThemeHelper(NightModeChecker nightModeChecker, SetupWizardBridge setupWizardBridge) {
mNightModeChecker = requireNonNull(nightModeChecker);
mSetupWizardBridge = requireNonNull(setupWizardBridge);
// TODO(b/190182035): Tidy up tests after adding dependency injection support
mAnimationDynamicColorsHelper = new AnimationDynamicColorsHelper();
}
/**
* Infers the correct theme resource id.
*/
public int inferThemeResId(Context context, Intent intent) {
requireNonNull(context);
requireNonNull(intent);
String themeName = getDefaultThemeName(context, intent);
int defaultTheme = mSetupWizardBridge.isSetupWizardDayNightEnabled(context)
? R.style.SudThemeGlifV4_DayNight
: R.style.SudThemeGlifV4_Light;
return mSetupWizardBridge
.resolveTheme(defaultTheme, themeName, shouldSuppressDayNight(context));
}
/**
* Sets up theme-specific colors. Must be called after {@link
* #inferThemeResId(Context, Intent)}.
*/
public void setupDynamicColors(Context context) {
requireNonNull(context);
trySetDynamicColor(context);
}
/**
* Returns the appropriate day or night mode, depending on the setup wizard flags.
*
* @return {@link AppCompatDelegate#MODE_NIGHT_YES} or {@link AppCompatDelegate#MODE_NIGHT_NO}
*/
public int getDefaultNightMode(Context context, Intent intent) {
requireNonNull(context);
if (TextUtils.isEmpty(getProvidedTheme(intent))) {
return isSystemNightMode(context)
? AppCompatDelegate.MODE_NIGHT_YES
: AppCompatDelegate.MODE_NIGHT_NO;
}
if (shouldSuppressDayNight(context)) {
return AppCompatDelegate.MODE_NIGHT_NO;
}
if (isSystemNightMode(context)) {
return AppCompatDelegate.MODE_NIGHT_YES;
}
return AppCompatDelegate.MODE_NIGHT_NO;
}
/**
* Forces the web pages shown by the {@link android.webkit.WebView} which has the
* supplied {@code webSettings} to have the appropriate day/night mode depending
* on the app theme.
*/
public void applyWebSettingsDayNight(Context context, WebSettings webSettings, Intent intent) {
requireNonNull(context);
requireNonNull(webSettings);
if (!WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
return;
}
WebSettingsCompat.setForceDark(webSettings, getForceDarkMode(context, intent));
}
/**
* Updates the relevant animation with theme-specific colors.
* <p>If the supplied {@link LottieAnimationView} does not have a loaded {@link
* LottieComposition}, it asynchronously waits for it to load and then applies the colors.
*/
public void setupAnimationDynamicColors(
Context context, LottieAnimationView lottieAnimationView, Intent intent) {
mAnimationDynamicColorsHelper.setupAnimationDynamicColors(
new LottieAnimationWrapper(lottieAnimationView),
getDefaultNightMode(context, intent));
}
private int getForceDarkMode(Context context, Intent intent) {
if (getDefaultNightMode(context, intent) == AppCompatDelegate.MODE_NIGHT_YES) {
return WebSettingsCompat.FORCE_DARK_ON;
} else {
return WebSettingsCompat.FORCE_DARK_OFF;
}
}
private boolean shouldSuppressDayNight(Context context) {
if (!FLAG_ENABLE_LIGHT_DARK_MODE) {
return true;
}
return !mSetupWizardBridge.isSetupWizardDayNightEnabled(context);
}
private boolean isSystemNightMode(Context context) {
return mNightModeChecker.isSystemNightMode(context);
}
private String getDefaultThemeName(Context context, Intent intent) {
String theme = getProvidedTheme(intent);
if (TextUtils.isEmpty(theme)) {
if (isSystemNightMode(context)) {
theme = com.google.android.setupdesign.util.ThemeHelper.THEME_GLIF_V4;
} else {
theme = com.google.android.setupdesign.util.ThemeHelper.THEME_GLIF_V4_LIGHT;
}
}
return theme;
}
private String getProvidedTheme(Intent intent) {
String theme = intent.getStringExtra(WizardManagerHelper.EXTRA_THEME);
if (TextUtils.isEmpty(theme)) {
return mSetupWizardBridge.getSystemPropertySetupWizardTheme();
}
return theme;
}
interface SetupWizardBridge {
boolean isSetupWizardDayNightEnabled(Context context);
String getSystemPropertySetupWizardTheme();
int resolveTheme(int defaultTheme, String themeName, boolean suppressDayNight);
}
interface NightModeChecker {
boolean isSystemNightMode(Context context);
}
/**
* Default implementation of {@link NightModeChecker}.
*/
public static class DefaultNightModeChecker implements NightModeChecker {
@Override
public boolean isSystemNightMode(Context context) {
return (context.getResources().getConfiguration().uiMode & UI_MODE_NIGHT_MASK)
== UI_MODE_NIGHT_YES;
}
}
/**
* Default implementation of {@link SetupWizardBridge}.
*/
public static class DefaultSetupWizardBridge implements SetupWizardBridge {
@Override
public boolean isSetupWizardDayNightEnabled(Context context) {
return com.google.android.setupdesign.util.ThemeHelper
.isSetupWizardDayNightEnabled(context);
}
@Override
public String getSystemPropertySetupWizardTheme() {
return SYSTEM_PROPERTY_SETUPWIZARD_THEME;
}
@Override
public int resolveTheme(int defaultTheme, String themeName, boolean suppressDayNight) {
ThemeResolver themeResolver = new ThemeResolver.Builder(ThemeResolver.getDefault())
.setDefaultTheme(defaultTheme)
.setUseDayNight(true)
.build();
return themeResolver.resolve(
themeName,
suppressDayNight);
}
}
}