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

Commit 13822d2b authored by Jean Chalard's avatar Jean Chalard
Browse files

Hack to skip reading an outdated binary file.

Bug: 7005813
Change-Id: Ie0d8d4b2d5eb147838ca23bdd5ec1cecd4f01151
parent 522e1266
Loading
Loading
Loading
Loading
+46 −3
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.inputmethod.latin;

import com.android.inputmethod.latin.makedict.BinaryDictInputOutput;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -23,6 +25,7 @@ import android.content.res.AssetFileDescriptor;
import android.util.Log;

import java.io.File;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
@@ -51,6 +54,9 @@ class BinaryDictionaryGetter {
    private static final String MAIN_DICTIONARY_CATEGORY = "main";
    public static final String ID_CATEGORY_SEPARATOR = ":";

    // The key considered to read the version attribute in a dictionary file.
    private static String VERSION_KEY = "version";

    // Prevents this from being instantiated
    private BinaryDictionaryGetter() {}

@@ -336,6 +342,42 @@ class BinaryDictionaryGetter {
        return MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
    }

    // ## HACK ## we prevent usage of a dictionary before version 18 for English only. The reason
    // for this is, since those do not include whitelist entries, the new code with an old version
    // of the dictionary would lose whitelist functionality.
    private static boolean hackCanUseDictionaryFile(final Locale locale, final File f) {
        // Only for English - other languages didn't have a whitelist, hence this
        // ad-hock ## HACK ##
        if (!Locale.ENGLISH.getLanguage().equals(locale.getLanguage())) return true;

        try {
            // Read the version of the file
            final RandomAccessFile raf = new RandomAccessFile(f, "r");
            final int magic = raf.readInt();
            if (magic != BinaryDictInputOutput.VERSION_2_MAGIC_NUMBER) {
                return false;
            }
            final int formatVersion = raf.readInt();
            final int headerSize = raf.readInt();
            final HashMap<String, String> options = new HashMap<String, String>();
            BinaryDictInputOutput.populateOptionsFromFile(raf, headerSize, options);
            final String version = options.get(VERSION_KEY);
            if (null == version) {
                // No version in the options : the format is unexpected
                return false;
            }
            // Version 18 is the first one to include the whitelist
            // Obviously this is a big ## HACK ##
            return Integer.parseInt(version) >= 18;
        } catch (java.io.FileNotFoundException e) {
            return false;
        } catch (java.io.IOException e) {
            return false;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * Returns a list of file addresses for a given locale, trying relevant methods in order.
     *
@@ -366,14 +408,15 @@ class BinaryDictionaryGetter {
        // cachedWordLists may not be null, see doc for getCachedDictionaryList
        for (final File f : cachedWordLists) {
            final String wordListId = getWordListIdFromFileName(f.getName());
            if (isMainWordListId(wordListId)) {
            final boolean canUse = f.canRead() && hackCanUseDictionaryFile(locale, f);
            if (canUse && isMainWordListId(wordListId)) {
                foundMainDict = true;
            }
            if (!dictPackSettings.isWordListActive(wordListId)) continue;
            if (f.canRead()) {
            if (canUse) {
                fileList.add(AssetFileAddress.makeFromFileName(f.getPath()));
            } else {
                Log.e(TAG, "Found a cached dictionary file but cannot read it");
                Log.e(TAG, "Found a cached dictionary file but cannot read or use it");
            }
        }

+17 −6
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ public class BinaryDictInputOutput {
     */

    private static final int VERSION_1_MAGIC_NUMBER = 0x78B1;
    private static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE;
    public static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE;
    private static final int MINIMUM_SUPPORTED_VERSION = 1;
    private static final int MAXIMUM_SUPPORTED_VERSION = 2;
    private static final int NOT_A_VERSION_NUMBER = -1;
@@ -1327,6 +1327,21 @@ public class BinaryDictInputOutput {
        return NOT_A_VERSION_NUMBER;
    }

    /**
     * Reads options from a file and populate a map with their contents.
     *
     * The file is read at the current file pointer, so the caller must take care the pointer
     * is in the right place before calling this.
     */
    public static void populateOptionsFromFile(final RandomAccessFile source, final long headerSize,
            final HashMap<String, String> options) throws IOException {
        while (source.getFilePointer() < headerSize) {
            final String key = CharEncoding.readString(source);
            final String value = CharEncoding.readString(source);
            options.put(key, value);
        }
    }

    /**
     * Reads a random access file and returns the memory representation of the dictionary.
     *
@@ -1358,11 +1373,7 @@ public class BinaryDictInputOutput {
        } else {
            headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16)
                    + (source.readUnsignedByte() << 8) + source.readUnsignedByte();
            while (source.getFilePointer() < headerSize) {
                final String key = CharEncoding.readString(source);
                final String value = CharEncoding.readString(source);
                options.put(key, value);
            }
            populateOptionsFromFile(source, headerSize, options);
            source.seek(headerSize);
        }