Skip to content
Snippets Groups Projects
BinaryDictionaryGetter.java 3.65 KiB
Newer Older
/*
 * Copyright (C) 2011 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.inputmethod.latin;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.util.Log;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
 * Helper class to get the address of a mmap'able dictionary file.
 */
class BinaryDictionaryGetter {

    /**
     * Used for Log actions from this class
     */
    private static final String TAG = BinaryDictionaryGetter.class.getSimpleName();

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

    /**
     * Returns a file address from a resource, or null if it cannot be opened.
     */
    private static AssetFileAddress loadFallbackResource(final Context context,
            final int fallbackResId, final Locale locale) {
        final Resources res = context.getResources();
        final Locale savedLocale = Utils.setSystemLocale(res, locale);
        final AssetFileDescriptor afd = res.openRawResourceFd(fallbackResId);
        Utils.setSystemLocale(res, savedLocale);

        if (afd == null) {
            Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId="
                    + fallbackResId);
            return null;
        }
        return AssetFileAddress.makeFromFileNameAndOffset(
                context.getApplicationInfo().sourceDir, afd.getStartOffset(), afd.getLength());
    }

    /**
     * Returns a list of file addresses for a given locale, trying relevant methods in order.
     * Tries to get binary dictionaries from various sources, in order:
     * - Uses a content provider to get a public dictionary set, as per the protocol described
     *   in BinaryDictionaryFileDumper.
     * If that fails:
     * - Gets a file name from the fallback resource passed as an argument.
     * If that fails:
     * - Returns null.
     * @return The address of a valid file, or null.
     */
    public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context,
            int fallbackResId) {
        try {
            List<AssetFileAddress> listFromContentProvider =
                    BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
            if (null != listFromContentProvider) {
                return listFromContentProvider;
            // If the list is null, fall through and return the fallback
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Unable to create dictionary file from provider for locale "
                    + locale.toString() + ": falling back to internal dictionary");
        } catch (IOException e) {
            Log.e(TAG, "Unable to read source data for locale "
                    + locale.toString() + ": falling back to internal dictionary");
        final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId,
                locale);
        if (null == fallbackAsset) return null;
        return Arrays.asList(fallbackAsset);