From fae8d60ee926e9f340392789119cf81655ad46e9 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 2 Aug 2011 19:13:44 +0900 Subject: [PATCH] Change the dictionary file passing schema to a list of ids The dictionary filename used to be passed directly to Latin IME. This change implements, on the part of Latin IME, the passing of them as an id that should then be passed through openAssetFileDescriptor. Bug: 5095140 Change-Id: I7d1e9d57c19f0645045368f68681680f238189fc --- .../latin/BinaryDictionaryFileDumper.java | 66 ++++++++++++++++--- .../latin/BinaryDictionaryGetter.java | 43 +++++------- 2 files changed, 72 insertions(+), 37 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 41b577cf3..1c7599442 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -20,8 +20,10 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; +import android.database.Cursor; import android.net.Uri; import android.text.TextUtils; +import android.util.Log; import java.io.File; import java.io.FileInputStream; @@ -29,7 +31,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; @@ -43,6 +46,8 @@ public class BinaryDictionaryFileDumper { */ static final int FILE_READ_BUFFER_SIZE = 1024; + private static final String DICTIONARY_PROJECTION[] = { "id" }; + // Prevents this class to be accidentally instantiated. private BinaryDictionaryFileDumper() { } @@ -75,12 +80,47 @@ public class BinaryDictionaryFileDumper { /** * Return for a given locale the provider URI to query to get the dictionary. */ + // TODO: remove this public static Uri getProviderUri(Locale locale) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath( locale.toString()).build(); } + /** + * Return for a given locale or dictionary id the provider URI to get the dictionary. + */ + private static Uri getProviderUri(String path) { + return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) + .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath( + path).build(); + } + + /** + * Queries a content provider for the list of dictionaries for a specific locale + * available to copy into Latin IME. + */ + private static List getDictIdList(final Locale locale, final Context context) { + final ContentResolver resolver = context.getContentResolver(); + final Uri dictionaryPackUri = getProviderUri(locale); + + final Cursor c = resolver.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null, null); + if (null == c) return Collections.emptyList(); + if (c.getCount() <= 0 || !c.moveToFirst()) { + c.close(); + return Collections.emptyList(); + } + + final List list = new ArrayList(); + do { + final String id = c.getString(0); + if (TextUtils.isEmpty(id)) continue; + list.add(id); + } while (c.moveToNext()); + c.close(); + return list; + } + /** * Queries a content provider for dictionary data for some locale and returns the file addresses * @@ -95,20 +135,26 @@ public class BinaryDictionaryFileDumper { * @throw FileNotFoundException if the provider returns non-existent data. * @throw IOException if the provider-returned data could not be read. */ - public static List getDictSetFromContentProvider(Locale locale, - Context context) throws FileNotFoundException, IOException { + public static List getDictSetFromContentProvider(final Locale locale, + final Context context) throws FileNotFoundException, IOException { // TODO: check whether the dictionary is the same or not and if it is, return the cached // file. // TODO: This should be able to read a number of files from the dictionary pack, copy // them all and return them. final ContentResolver resolver = context.getContentResolver(); - final Uri dictionaryPackUri = getProviderUri(locale); - final AssetFileDescriptor afd = resolver.openAssetFileDescriptor(dictionaryPackUri, "r"); - if (null == afd) return null; - final String fileName = - copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context)); - afd.close(); - return Arrays.asList(AssetFileAddress.makeFromFileName(fileName)); + final List idList = getDictIdList(locale, context); + final List fileAddressList = new ArrayList(); + for (String id : idList) { + final Uri dictionaryPackUri = getProviderUri(id); + final AssetFileDescriptor afd = + resolver.openAssetFileDescriptor(dictionaryPackUri, "r"); + if (null == afd) continue; + final String fileName = + copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context)); + afd.close(); + fileAddressList.add(AssetFileAddress.makeFromFileName(fileName)); + } + return fileAddressList; } /** diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 989a0e9a0..4b1c05adf 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -63,9 +63,6 @@ class BinaryDictionaryGetter { * 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: @@ -76,31 +73,23 @@ class BinaryDictionaryGetter { */ public static List getDictionaryFiles(Locale locale, Context context, int fallbackResId) { - // Try first to query a private package signed the same way for private files. - final List privateFiles = - PrivateBinaryDictionaryGetter.getDictionaryFiles(locale, context); - if (null != privateFiles) { - return privateFiles; - } else { - try { - // If that was no-go, try to find a publicly exported dictionary. - List 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"); + try { + List listFromContentProvider = + BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context); + if (null != listFromContentProvider) { + return listFromContentProvider; } - final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId, - locale); - if (null == fallbackAsset) return null; - return Arrays.asList(fallbackAsset); + // 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); } }