Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/java/android/app/ConfigurationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.HardwareRenderer;
import android.graphics.Typeface;
import android.inputmethodservice.InputMethodService;
import android.os.Build;
import android.os.LocaleList;
Expand Down Expand Up @@ -191,6 +192,7 @@ void handleConfigurationChanged(@Nullable Configuration config,

final Application app = mActivityThread.getApplication();
final Resources appResources = app.getResources();
Typeface.updateDefaultFont(appResources);
if (appResources.hasOverrideDisplayAdjustments()) {
// The value of Display#getRealSize will be adjusted by FixedRotationAdjustments,
// but Display#getSize refers to DisplayAdjustments#mConfiguration. So the rotated
Expand Down
3 changes: 3 additions & 0 deletions core/res/res/values/symbols.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4458,4 +4458,7 @@
<java-symbol type="integer" name="config_customizedMaxCachedProcesses" />

<java-symbol type="color" name="overview_background"/>

<!-- For dynamic default font styles -->
<java-symbol type="string" name="config_bodyFontFamily" />
</resources>
73 changes: 66 additions & 7 deletions graphics/java/android/graphics/Typeface.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import android.annotation.UiThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.FontStyle;
Expand Down Expand Up @@ -67,11 +68,13 @@
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -141,6 +144,8 @@ public class Typeface {
private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
private static final Object sDynamicCacheLock = new Object();

// For dynamic default font styles
private static final HashMap<String, Typeface> sSystemFontOverrides = new HashMap<>();

@GuardedBy("SYSTEM_FONT_MAP_LOCK")
static Typeface sDefaultTypeface;
Expand Down Expand Up @@ -884,7 +889,7 @@ public CustomFallbackBuilder(@NonNull FontFamily family) {
* @return The best matching typeface.
*/
public static Typeface create(String familyName, @Style int style) {
return create(getSystemDefaultTypeface(familyName), style);
return create(getSystemOverrideTypeface(familyName), style);
}

/**
Expand Down Expand Up @@ -1176,6 +1181,11 @@ private Typeface(long ni) {
mWeight = nativeGetWeight(ni);
}

private static Typeface getSystemOverrideTypeface(@NonNull String familyName) {
Typeface tf = sSystemFontOverrides.get(familyName);
return tf == null ? getSystemDefaultTypeface(familyName) : tf;
}

private static Typeface getSystemDefaultTypeface(@NonNull String familyName) {
Typeface tf = sSystemFontMap.get(familyName);
return tf == null ? Typeface.DEFAULT : tf;
Expand Down Expand Up @@ -1345,6 +1355,60 @@ public static void setSystemFontMap(@Nullable SharedMemory sharedMemory)
}
}

private static void setPublicDefaults(String familyName) {
synchronized (SYSTEM_FONT_MAP_LOCK) {
sDefaults = new Typeface[] {
DEFAULT,
DEFAULT_BOLD,
create(getSystemDefaultTypeface(familyName), Typeface.ITALIC),
create(getSystemDefaultTypeface(familyName), Typeface.BOLD_ITALIC),
};
}
}

private static void setFinalField(String fieldName, Typeface value) {
synchronized (SYSTEM_FONT_MAP_LOCK) {
try {
Field field = Typeface.class.getDeclaredField(fieldName);
// isAccessible bypasses final on ART
field.setAccessible(true);
field.set(null, value);
field.setAccessible(false);
} catch (NoSuchFieldException | IllegalAccessException e) {
Log.e(TAG, "Failed to set Typeface." + fieldName, e);
}
}
}

/** @hide */
public static void updateDefaultFont(Resources res) {
synchronized (SYSTEM_FONT_MAP_LOCK) {
String familyName = res.getString(com.android.internal.R.string.config_bodyFontFamily);
Typeface typeface = sSystemFontMap.get(familyName);
if (typeface == null) {
// This should never happen, but if the system font family name is invalid, just return
// instead of crashing the app.
return;
}

setDefault(typeface);

// Static typefaces in public API
setFinalField("DEFAULT", create(getSystemDefaultTypeface(familyName), 0));
setFinalField("DEFAULT_BOLD", create(getSystemDefaultTypeface(familyName), Typeface.BOLD));
setFinalField("SANS_SERIF", DEFAULT);

// For default aliases used in framework styles
sSystemFontOverrides.put("sans-serif", typeface);
sSystemFontOverrides.put("sans-serif-thin", create(typeface, 100, false));
sSystemFontOverrides.put("sans-serif-light", create(typeface, 300, false));
sSystemFontOverrides.put("sans-serif-medium", create(typeface, 500, false));
sSystemFontOverrides.put("sans-serif-black", create(typeface, 900, false));

setPublicDefaults(familyName);
}
}

/** @hide */
@VisibleForTesting
public static void setSystemFontMap(Map<String, Typeface> systemFontMap) {
Expand All @@ -1365,12 +1429,7 @@ public static void setSystemFontMap(Map<String, Typeface> systemFontMap) {
nativeForceSetStaticFinalField("SERIF", create("serif", 0));
nativeForceSetStaticFinalField("MONOSPACE", create("monospace", 0));

sDefaults = new Typeface[]{
DEFAULT,
DEFAULT_BOLD,
create((String) null, Typeface.ITALIC),
create((String) null, Typeface.BOLD_ITALIC),
};
setPublicDefaults(null);

// A list of generic families to be registered in native.
// https://www.w3.org/TR/css-fonts-4/#generic-font-families
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ public class ThemeOverlayApplier implements Dumpable {
private final String mLauncherPackage;
private final String mThemePickerPackage;

private boolean mIsBlackTheme;

public ThemeOverlayApplier(OverlayManager overlayManager,
Executor bgExecutor,
Executor mainExecutor,
Expand Down Expand Up @@ -235,6 +237,21 @@ public void applyCurrentUserOverlays(
});
}

public void setIsBlackTheme(boolean black) {
mIsBlackTheme = black;
}

public void applyBlackTheme(boolean enable) {
mBgExecutor.execute(() -> {
try {
mOverlayManager.setEnabled("com.android.system.theme.black",
enable, UserHandle.SYSTEM);
} catch (SecurityException | IllegalStateException e) {
Log.e(TAG, "setEnabled failed", e);
}
});
}

@VisibleForTesting
protected OverlayManagerTransaction.Builder getTransactionBuilder() {
return new OverlayManagerTransaction.Builder();
Expand All @@ -249,6 +266,10 @@ private void setEnabled(OverlayManagerTransaction.Builder transaction,
+ category + ": " + enabled);
}

if (OVERLAY_CATEGORY_SYSTEM_PALETTE.equals(category)) {
enabled = enabled && !mIsBlackTheme;
}

OverlayInfo overlayInfo = mOverlayManager.getOverlayInfo(identifier,
UserHandle.of(currentUser));
if (overlayInfo == null && !pendingCreation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public class ThemeOverlayController extends SystemUI implements Dumpable {
protected static final int NEUTRAL = 0;
protected static final int ACCENT = 1;

protected static String SYSTEM_BLACK_THEME = "system_black_theme";

private final ThemeOverlayApplier mThemeManager;
private final UserManager mUserManager;
private final BroadcastDispatcher mBroadcastDispatcher;
Expand Down Expand Up @@ -521,6 +523,11 @@ private void updateThemeOverlays() {
.map(key -> key + " -> " + categoryToPackage.get(key)).collect(
Collectors.joining(", ")));
}

boolean isBlackTheme = mSecureSettings.getInt(SYSTEM_BLACK_THEME, 0) == 1;

mThemeManager.setIsBlackTheme(isBlackTheme);

if (mNeedsOverlayCreation) {
mNeedsOverlayCreation = false;
mThemeManager.applyCurrentUserOverlays(categoryToPackage, new FabricatedOverlay[] {
Expand All @@ -530,6 +537,8 @@ private void updateThemeOverlays() {
mThemeManager.applyCurrentUserOverlays(categoryToPackage, null, currentUser,
managedProfiles);
}

mThemeManager.applyBlackTheme(isBlackTheme);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ class CustomThemeOverlayController @Inject constructor(

override fun start() {
tunerService.addTunable(this, PREF_COLOR_OVERRIDE, PREF_WHITE_LUMINANCE,
PREF_CHROMA_FACTOR, PREF_ACCURATE_SHADES, PREF_LINEAR_LIGHTNESS, PREF_CUSTOM_COLOR)
PREF_CHROMA_FACTOR, PREF_ACCURATE_SHADES,
PREF_LINEAR_LIGHTNESS, PREF_CUSTOM_COLOR, SYSTEM_BLACK_THEME)
super.start()
}

override fun onTuningChanged(key: String?, newValue: String?) {
key?.let {
if (it.contains(PREF_PREFIX)) {
customColor = Settings.Secure.getInt(mContext.contentResolver, PREF_CUSTOM_COLOR, 0) == 1
colorOverride = Settings.Secure.getInt(mContext.contentResolver,
PREF_COLOR_OVERRIDE, -1)
Expand All @@ -119,7 +119,6 @@ class CustomThemeOverlayController @Inject constructor(
linearLightness = Settings.Secure.getInt(mContext.contentResolver,
PREF_LINEAR_LIGHTNESS, 0) != 0
reevaluateSystemTheme(true /* forceReload */)
}
}
}

Expand Down