BinaryDictionaryGetter.java revision 44861474fbea784f12fe86bc56d30d5d9be4ad81
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.inputmethod.latin;
18
19import android.content.Context;
20import android.content.res.AssetFileDescriptor;
21import android.util.Log;
22
23import java.io.FileNotFoundException;
24import java.io.IOException;
25import java.util.Arrays;
26import java.util.List;
27import java.util.Locale;
28
29/**
30 * Helper class to get the address of a mmap'able dictionary file.
31 */
32class BinaryDictionaryGetter {
33
34    /**
35     * Used for Log actions from this class
36     */
37    private static final String TAG = BinaryDictionaryGetter.class.getSimpleName();
38
39    // Prevents this from being instantiated
40    private BinaryDictionaryGetter() {}
41
42    /**
43     * Returns a file address from a resource, or null if it cannot be opened.
44     */
45    private static AssetFileAddress loadFallbackResource(Context context, int fallbackResId) {
46        final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId);
47        if (afd == null) {
48            Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId="
49                    + fallbackResId);
50            return null;
51        }
52        return AssetFileAddress.makeFromFileNameAndOffset(
53                context.getApplicationInfo().sourceDir, afd.getStartOffset(), afd.getLength());
54    }
55
56    /**
57     * Returns a list of file addresses for a given locale, trying relevant methods in order.
58     *
59     * Tries to get binary dictionaries from various sources, in order:
60     * - Uses a private method of getting a private dictionaries, as implemented by the
61     *   PrivateBinaryDictionaryGetter class.
62     * If that fails:
63     * - Uses a content provider to get a public dictionary set, as per the protocol described
64     *   in BinaryDictionaryFileDumper.
65     * If that fails:
66     * - Gets a file name from the fallback resource passed as an argument.
67     * If that fails:
68     * - Returns null.
69     * @return The address of a valid file, or null.
70     */
71    public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context,
72            int fallbackResId) {
73        // Try first to query a private package signed the same way for private files.
74        final List<AssetFileAddress> privateFiles =
75                PrivateBinaryDictionaryGetter.getDictionaryFiles(locale, context);
76        if (null != privateFiles) {
77            return privateFiles;
78        } else {
79            try {
80                // If that was no-go, try to find a publicly exported dictionary.
81                List<AssetFileAddress> listFromContentProvider =
82                        BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
83                if (null != listFromContentProvider) {
84                    return listFromContentProvider;
85                }
86                // If the list is null, fall through and return the fallback
87            } catch (FileNotFoundException e) {
88                Log.e(TAG, "Unable to create dictionary file from provider for locale "
89                        + locale.toString() + ": falling back to internal dictionary");
90            } catch (IOException e) {
91                Log.e(TAG, "Unable to read source data for locale "
92                        + locale.toString() + ": falling back to internal dictionary");
93            }
94            final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId);
95            if (null == fallbackAsset) return null;
96            return Arrays.asList(fallbackAsset);
97        }
98    }
99}
100