Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 944681ed authored by Kohsuke Yatoh's avatar Kohsuke Yatoh Committed by Android (Google) Code Review
Browse files

Merge "Split lock in FontManagerService." into sc-dev

parents a5e22cf5 e2d2ccc9
Loading
Loading
Loading
Loading
+36 −24
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.graphics.fonts.FontFileUtil;
import android.graphics.fonts.FontManager;
import android.graphics.fonts.SystemFonts;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SharedMemory;
import android.os.ShellCallback;
@@ -67,13 +66,12 @@ public final class FontManagerService extends IFontManager.Stub {
    private static final String CRASH_MARKER_FILE = "/data/fonts/config/crash.txt";

    @Override
    public FontConfig getFontConfig() throws RemoteException {
    public FontConfig getFontConfig() {
        return getSystemFontConfig();
    }

    @Override
    public int updateFont(ParcelFileDescriptor fd, byte[] signature, int baseVersion)
            throws RemoteException {
    public int updateFont(ParcelFileDescriptor fd, byte[] signature, int baseVersion) {
        Objects.requireNonNull(fd);
        Objects.requireNonNull(signature);
        Preconditions.checkArgumentNonnegative(baseVersion);
@@ -183,14 +181,21 @@ public final class FontManagerService extends IFontManager.Stub {
    @NonNull
    private final Context mContext;

    @GuardedBy("FontManagerService.this")
    private final Object mUpdatableFontDirLock = new Object();

    @GuardedBy("mUpdatableFontDirLock")
    @NonNull
    private final FontCrashDetector mFontCrashDetector;

    @GuardedBy("mUpdatableFontDirLock")
    @Nullable
    private final UpdatableFontDir mUpdatableFontDir;

    @GuardedBy("FontManagerService.this")
    // mSerializedFontMapLock can be acquired while holding mUpdatableFontDirLock.
    // mUpdatableFontDirLock should not be newly acquired while holding mSerializedFontMapLock.
    private final Object mSerializedFontMapLock = new Object();

    @GuardedBy("mSerializedFontMapLock")
    @Nullable
    private SharedMemory mSerializedFontMap = null;

@@ -212,9 +217,9 @@ public final class FontManagerService extends IFontManager.Stub {
    }

    private void initialize() {
        synchronized (FontManagerService.this) {
        synchronized (mUpdatableFontDirLock) {
            if (mUpdatableFontDir == null) {
                mSerializedFontMap = buildNewSerializedFontMap();
                updateSerializedFontMap();
                return;
            }
            if (mFontCrashDetector.hasCrashed()) {
@@ -228,7 +233,7 @@ public final class FontManagerService extends IFontManager.Stub {
            }
            try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) {
                mUpdatableFontDir.loadFontFileMap();
                mSerializedFontMap = buildNewSerializedFontMap();
                updateSerializedFontMap();
            }
        }
    }
@@ -239,7 +244,7 @@ public final class FontManagerService extends IFontManager.Stub {
    }

    @Nullable /* package */ SharedMemory getCurrentFontMap() {
        synchronized (FontManagerService.this) {
        synchronized (mSerializedFontMapLock) {
            return mSerializedFontMap;
        }
    }
@@ -251,7 +256,7 @@ public final class FontManagerService extends IFontManager.Stub {
                    FontManager.RESULT_ERROR_FONT_UPDATER_DISABLED,
                    "The font updater is disabled.");
        }
        synchronized (FontManagerService.this) {
        synchronized (mUpdatableFontDirLock) {
            // baseVersion == -1 only happens from shell command. This is filtered and treated as
            // error from SystemApi call.
            if (baseVersion != -1 && mUpdatableFontDir.getConfigVersion() != baseVersion) {
@@ -261,7 +266,7 @@ public final class FontManagerService extends IFontManager.Stub {
            }
            try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) {
                mUpdatableFontDir.installFontFile(fd, pkcs7Signature);
                mSerializedFontMap = buildNewSerializedFontMap();
                updateSerializedFontMap();
            }
        }
    }
@@ -272,10 +277,10 @@ public final class FontManagerService extends IFontManager.Stub {
                    FontManager.RESULT_ERROR_FONT_UPDATER_DISABLED,
                    "The font updater is disabled.");
        }
        synchronized (FontManagerService.this) {
        synchronized (mUpdatableFontDirLock) {
            try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) {
                mUpdatableFontDir.clearUpdates();
                mSerializedFontMap = buildNewSerializedFontMap();
                updateSerializedFontMap();
            }
        }
    }
@@ -283,7 +288,8 @@ public final class FontManagerService extends IFontManager.Stub {
    /* package */ Map<String, File> getFontFileMap() {
        if (mUpdatableFontDir == null) {
            return Collections.emptyMap();
        } else {
        }
        synchronized (mUpdatableFontDirLock) {
            return mUpdatableFontDir.getFontFileMap();
        }
    }
@@ -301,7 +307,7 @@ public final class FontManagerService extends IFontManager.Stub {
            @Nullable FileDescriptor err,
            @NonNull String[] args,
            @Nullable ShellCallback callback,
            @NonNull ResultReceiver result) throws RemoteException {
            @NonNull ResultReceiver result) {
        new FontManagerShellCommand(this).exec(this, in, out, err, args, callback, result);
    }

@@ -309,24 +315,28 @@ public final class FontManagerService extends IFontManager.Stub {
     * Returns an active system font configuration.
     */
    public @NonNull FontConfig getSystemFontConfig() {
        if (mUpdatableFontDir != null) {
            return mUpdatableFontDir.getSystemFontConfig();
        } else {
        if (mUpdatableFontDir == null) {
            return SystemFonts.getSystemPreinstalledFontConfig();
        }
        synchronized (mUpdatableFontDirLock) {
            return mUpdatableFontDir.getSystemFontConfig();
        }
    }

    /**
     * Make new serialized font map data.
     * Makes new serialized font map data and updates mSerializedFontMap.
     */
    public @Nullable SharedMemory buildNewSerializedFontMap() {
    public void updateSerializedFontMap() {
        try {
            final FontConfig fontConfig = getSystemFontConfig();
            final Map<String, FontFamily[]> fallback = SystemFonts.buildSystemFallback(fontConfig);
            final Map<String, Typeface> typefaceMap =
                    SystemFonts.buildSystemTypefaces(fontConfig, fallback);

            return Typeface.serializeFontMap(typefaceMap);
            SharedMemory serializeFontMap = Typeface.serializeFontMap(typefaceMap);
            synchronized (mSerializedFontMapLock) {
                mSerializedFontMap = serializeFontMap;
            }
        } catch (IOException | ErrnoException e) {
            Slog.w(TAG, "Failed to serialize updatable font map. "
                    + "Retrying with system image fonts.", e);
@@ -338,11 +348,13 @@ public final class FontManagerService extends IFontManager.Stub {
            final Map<String, Typeface> typefaceMap =
                    SystemFonts.buildSystemTypefaces(fontConfig, fallback);

            return Typeface.serializeFontMap(typefaceMap);
            SharedMemory serializeFontMap = Typeface.serializeFontMap(typefaceMap);
            synchronized (mSerializedFontMapLock) {
                mSerializedFontMap = serializeFontMap;
            }
        } catch (IOException | ErrnoException e) {
            Slog.e(TAG, "Failed to serialize SystemServer system font map", e);
        }
        return null;
    }

}
+146 −158
Original line number Diff line number Diff line
@@ -29,8 +29,6 @@ import android.text.FontConfig;
import android.util.Base64;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;

import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
@@ -44,6 +42,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Manages set of updatable font files.
 *
 * <p>This class is not thread safe.
 */
final class UpdatableFontDir {

    private static final String TAG = "UpdatableFontDir";
@@ -113,11 +116,9 @@ final class UpdatableFontDir {
    private final File mConfigFile;
    private final File mTmpConfigFile;

    @GuardedBy("UpdatableFontDir.this")
    private final PersistentSystemFontConfig.Config mConfig =
            new PersistentSystemFontConfig.Config();

    @GuardedBy("UpdatableFontDir.this")
    private int mConfigVersion = 1;

    /**
@@ -125,7 +126,6 @@ final class UpdatableFontDir {
     * FontFileInfo}. All files in this map are validated, and have higher revision numbers than
     * corresponding font files in {@link #mPreinstalledFontDirs}.
     */
    @GuardedBy("UpdatableFontDir.this")
    private final Map<String, FontFileInfo> mFontFileInfoMap = new HashMap<>();

    UpdatableFontDir(File filesDir, List<File> preinstalledFontDirs, FontFileParser parser,
@@ -145,7 +145,6 @@ final class UpdatableFontDir {
    }

    /* package */ void loadFontFileMap() {
        synchronized (UpdatableFontDir.this) {
        boolean success = false;

        try (FileInputStream fis = new FileInputStream(mConfigFile)) {
@@ -163,7 +162,7 @@ final class UpdatableFontDir {
                File[] files = dir.listFiles();
                if (files == null || files.length != 1) return;
                FontFileInfo fontFileInfo = validateFontFile(files[0]);
                    addFileToMapIfNewerLocked(fontFileInfo, true /* deleteOldFile */);
                addFileToMapIfNewer(fontFileInfo, true /* deleteOldFile */);
            }
            success = true;
        } catch (Throwable t) {
@@ -178,10 +177,8 @@ final class UpdatableFontDir {
            }
        }
    }
    }

    /* package */ void clearUpdates() throws SystemFontException {
        synchronized (UpdatableFontDir.this) {
        mFontFileInfoMap.clear();
        FileUtils.deleteContents(mFilesDir);

@@ -196,7 +193,6 @@ final class UpdatableFontDir {
        }
        mConfigVersion++;
    }
    }

    /**
     * Installs a new font file, or updates an existing font file.
@@ -210,7 +206,6 @@ final class UpdatableFontDir {
     * @throws SystemFontException if error occurs.
     */
    void installFontFile(FileDescriptor fd, byte[] pkcs7Signature) throws SystemFontException {
        synchronized (UpdatableFontDir.this) {
        File newDir = getRandomDir(mFilesDir);
        if (!newDir.mkdir()) {
            throw new SystemFontException(
@@ -289,7 +284,7 @@ final class UpdatableFontDir {

            // Backup the mapping for rollback.
            HashMap<String, FontFileInfo> backup = new HashMap<>(mFontFileInfoMap);
                if (!addFileToMapIfNewerLocked(fontFileInfo, false)) {
            if (!addFileToMapIfNewer(fontFileInfo, false)) {
                throw new SystemFontException(
                        FontManager.RESULT_ERROR_DOWNGRADING,
                        "Downgrading font file is forbidden.");
@@ -316,7 +311,6 @@ final class UpdatableFontDir {
            }
        }
    }
    }

    /**
     * Given {@code parent}, returns {@code parent/~~[randomStr]}.
@@ -341,7 +335,7 @@ final class UpdatableFontDir {
     * higher than the currently used font file (either in {@link #mFontFileInfoMap} or {@link
     * #mPreinstalledFontDirs}).
     */
    private boolean addFileToMapIfNewerLocked(FontFileInfo fontFileInfo, boolean deleteOldFile) {
    private boolean addFileToMapIfNewer(FontFileInfo fontFileInfo, boolean deleteOldFile) {
        String name = fontFileInfo.getFile().getName();
        FontFileInfo existingInfo = mFontFileInfoMap.get(name);
        final boolean shouldAddToMap;
@@ -447,27 +441,21 @@ final class UpdatableFontDir {

    Map<String, File> getFontFileMap() {
        Map<String, File> map = new HashMap<>();
        synchronized (UpdatableFontDir.this) {
        for (Map.Entry<String, FontFileInfo> entry : mFontFileInfoMap.entrySet()) {
            map.put(entry.getKey(), entry.getValue().getFile());
        }
        }
        return map;
    }

    /* package */ FontConfig getSystemFontConfig() {
        synchronized (UpdatableFontDir.this) {
        return SystemFonts.getSystemFontConfig(
                getFontFileMap(),
                mConfig.lastModifiedDate,
                mConfigVersion
        );
    }
    }

    /* package */ int getConfigVersion() {
        synchronized (UpdatableFontDir.this) {
        return mConfigVersion;
    }
}
}