aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
blob: 562580d413a4e0c8f25444843765b435aedd3cb1 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
 * 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.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(Context context, int fallbackResId) {
        final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId);
        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 private method of getting a private dictionaries, as implemented by the
     *   PrivateBinaryDictionaryGetter class.
     * If that fails:
     * - 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 first to query a private package signed the same way for private files.
        final List<AssetFileAddress> privateFiles =
                PrivateBinaryDictionaryGetter.getDictionaryFiles(locale, context);
        if (null != privateFiles) {
            return privateFiles;
        } else {
            try {
                // If that was no-go, try to find a publicly exported dictionary.
                return BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Unable to create dictionary file from provider for locale "
                        + locale.toString() + ": falling back to internal dictionary");
                return Arrays.asList(loadFallbackResource(context, fallbackResId));
            } catch (IOException e) {
                Log.e(TAG, "Unable to read source data for locale "
                        + locale.toString() + ": falling back to internal dictionary");
                return Arrays.asList(loadFallbackResource(context, fallbackResId));
            }
        }
    }
}