Improve the architecture to support multiple dictionaries.

This change enables the interface to get multiple dictionaries from a
dictionary pack. It only implements it to the end in the case of the
proprietary method, as the open method needs still some working out,
and the "inside the package" method does not need it.

This change goes together with Iaa95bf36, and breaks the build
without it.

Bug: 1752028

Change-Id: I3ccfd696e8ef083ef9c074e1c3e4bb0bf2fcfd23
main
Jean Chalard 2011-04-27 23:13:11 +09:00
parent 3bf6fbb6b8
commit d8f52a4f18
5 changed files with 46 additions and 30 deletions

View File

@ -28,6 +28,8 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
/**
@ -79,27 +81,32 @@ public class BinaryDictionaryFileDumper {
}
/**
* Queries a content provider for dictionary data for some locale and returns it as a file name.
* Queries a content provider for dictionary data for some locale and returns the file addresses
*
* This will query a content provider for dictionary data for a given locale, and return
* the name of a file suitable to be mmap'ed. It will copy it to local storage if needed.
* It should also check the dictionary version to avoid unnecessary copies but this is
* the addresses of a file set the members of which are suitable to be mmap'ed. It will copy
* them to local storage if needed.
* It should also check the dictionary versions to avoid unnecessary copies but this is
* still in TODO state.
* This will make the data from the content provider the cached dictionary for this locale,
* overwriting any previous cached data.
* @returns the name of the file, or null if no data could be obtained.
* @returns the addresses of the files, or null if no data could be obtained.
* @throw FileNotFoundException if the provider returns non-existent data.
* @throw IOException if the provider-returned data could not be read.
*/
public static String getDictionaryFileFromContentProvider(Locale locale, Context context)
throws FileNotFoundException, IOException {
public static List<AssetFileAddress> getDictSetFromContentProvider(Locale locale,
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;
return copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context));
final String fileName =
copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context));
return Arrays.asList(AssetFileAddress.makeFromFileName(fileName));
}
/**

View File

@ -22,6 +22,8 @@ import android.util.Log;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
/**
@ -52,13 +54,13 @@ class BinaryDictionaryGetter {
}
/**
* Returns a file address for a given locale, trying relevant methods in order.
* Returns a list of file addresses for a given locale, trying relevant methods in order.
*
* Tries to get a binary dictionary from various sources, in order:
* - Uses a private method of getting a private dictionary, as implemented by the
* 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, as per the protocol described
* - 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.
@ -66,27 +68,25 @@ class BinaryDictionaryGetter {
* - Returns null.
* @return The address of a valid file, or null.
*/
public static AssetFileAddress getDictionaryFile(Locale locale, Context context,
public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context,
int fallbackResId) {
// Try first to query a private file signed the same way.
final AssetFileAddress privateFile =
PrivateBinaryDictionaryGetter.getDictionaryFile(locale, context);
if (null != privateFile) {
return privateFile;
// 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.
final String fileName = BinaryDictionaryFileDumper.
getDictionaryFileFromContentProvider(locale, context);
return AssetFileAddress.makeFromFileName(fileName);
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 loadFallbackResource(context, fallbackResId);
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 loadFallbackResource(context, fallbackResId);
return Arrays.asList(loadFallbackResource(context, fallbackResId));
}
}
}

View File

@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@ -34,6 +35,10 @@ public class DictionaryCollection extends Dictionary {
mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries);
}
public DictionaryCollection(Collection<Dictionary> dictionaries) {
mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries);
}
@Override
public void getWords(final WordComposer composer, final WordCallback callback) {
for (final Dictionary dict : mDictionaries)

View File

@ -18,11 +18,12 @@ package com.android.inputmethod.latin;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.Log;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
/**
@ -50,11 +51,14 @@ public class DictionaryFactory {
return new DictionaryCollection(createBinaryDictionary(context, fallbackResId));
}
final AssetFileAddress dictFile = BinaryDictionaryGetter.getDictionaryFile(locale,
context, fallbackResId);
if (null == dictFile) return null;
return new DictionaryCollection(new BinaryDictionary(context,
dictFile.mFilename, dictFile.mOffset, dictFile.mLength, null));
final List<Dictionary> dictList = new LinkedList<Dictionary>();
for (final AssetFileAddress f : BinaryDictionaryGetter.getDictionaryFiles(locale,
context, fallbackResId)) {
dictList.add(new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null));
}
if (null == dictList) return null;
return new DictionaryCollection(dictList);
}
/**
@ -66,7 +70,6 @@ public class DictionaryFactory {
protected static BinaryDictionary createBinaryDictionary(Context context, int resId) {
AssetFileDescriptor afd = null;
try {
// TODO: IMPORTANT: Do not create a dictionary from a placeholder.
afd = context.getResources().openRawResourceFd(resId);
if (afd == null) {
Log.e(TAG, "Found the resource but it is compressed. resId=" + resId);

View File

@ -18,11 +18,12 @@ package com.android.inputmethod.latin;
import android.content.Context;
import java.util.List;
import java.util.Locale;
class PrivateBinaryDictionaryGetter {
private PrivateBinaryDictionaryGetter() {}
public static AssetFileAddress getDictionaryFile(Locale locale, Context context) {
public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context) {
return null;
}
}