Do not re-download the unused dictionaries.

Does the following
1. Uses dictionaries from the files/ directory while populating the
   entries into the pendingUpdates table. So that a download happens only
   if the metadata.json says so.
2. Delete an unusable dictionaries from the files/ directory.

Bug: 20142708
Change-Id: Ibd738793585c39735868e324b8ad682dff0eba34
main
Mohammadinamul Sheik 2015-04-15 11:12:40 -07:00
parent bf732e7001
commit 3a5de64110
3 changed files with 91 additions and 23 deletions

View File

@ -377,7 +377,8 @@ public final class ActionBatch {
final ContentValues values = MetadataDbHelper.makeContentValues(0, final ContentValues values = MetadataDbHelper.makeContentValues(0,
MetadataDbHelper.TYPE_BULK, MetadataDbHelper.STATUS_INSTALLED, MetadataDbHelper.TYPE_BULK, MetadataDbHelper.STATUS_INSTALLED,
mWordList.mId, mWordList.mLocale, mWordList.mDescription, mWordList.mId, mWordList.mLocale, mWordList.mDescription,
"", mWordList.mRemoteFilename, mWordList.mLastUpdate, TextUtils.isEmpty(mWordList.mLocalFilename) ? "" : mWordList.mLocalFilename,
mWordList.mRemoteFilename, mWordList.mLastUpdate,
mWordList.mRawChecksum, mWordList.mChecksum, mWordList.mRetryCount, mWordList.mRawChecksum, mWordList.mChecksum, mWordList.mRetryCount,
mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion); mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
PrivateLog.log("Insert 'preinstalled' record for " + mWordList.mDescription PrivateLog.log("Insert 'preinstalled' record for " + mWordList.mDescription

View File

@ -95,6 +95,8 @@ public final class UpdateHandler {
// Name of the category for the main dictionary // Name of the category for the main dictionary
public static final String MAIN_DICTIONARY_CATEGORY = "main"; public static final String MAIN_DICTIONARY_CATEGORY = "main";
public static final String TEMP_DICT_FILE_SUB = "___";
// The id for the "dictionary available" notification. // The id for the "dictionary available" notification.
static final int DICT_AVAILABLE_NOTIFICATION_ID = 1; static final int DICT_AVAILABLE_NOTIFICATION_ID = 1;
@ -743,7 +745,7 @@ public final class UpdateHandler {
throws IOException { throws IOException {
DebugLogUtils.l("Entering openTempFileOutput"); DebugLogUtils.l("Entering openTempFileOutput");
final File dir = context.getFilesDir(); final File dir = context.getFilesDir();
final File f = File.createTempFile(locale + "___", DICT_FILE_SUFFIX, dir); final File f = File.createTempFile(locale + TEMP_DICT_FILE_SUB, DICT_FILE_SUFFIX, dir);
DebugLogUtils.l("File name is", f.getName()); DebugLogUtils.l("File name is", f.getName());
return f.getName(); return f.getName();
} }

View File

@ -25,6 +25,7 @@ import android.util.Log;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.dictionarypack.UpdateHandler;
import com.android.inputmethod.latin.AssetFileAddress; import com.android.inputmethod.latin.AssetFileAddress;
import com.android.inputmethod.latin.BinaryDictionaryGetter; import com.android.inputmethod.latin.BinaryDictionaryGetter;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
@ -36,6 +37,7 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import java.io.File; import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -58,6 +60,8 @@ public class DictionaryInfoUtils {
// 6 digits - unicode is limited to 21 bits // 6 digits - unicode is limited to 21 bits
private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6; private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6;
private static final String TEMP_DICT_FILE_SUB = UpdateHandler.TEMP_DICT_FILE_SUB;
public static class DictionaryInfo { public static class DictionaryInfo {
private static final String LOCALE_COLUMN = "locale"; private static final String LOCALE_COLUMN = "locale";
private static final String WORDLISTID_COLUMN = "id"; private static final String WORDLISTID_COLUMN = "id";
@ -66,22 +70,24 @@ public class DictionaryInfoUtils {
private static final String DATE_COLUMN = "date"; private static final String DATE_COLUMN = "date";
private static final String FILESIZE_COLUMN = "filesize"; private static final String FILESIZE_COLUMN = "filesize";
private static final String VERSION_COLUMN = "version"; private static final String VERSION_COLUMN = "version";
@Nonnull
public final String mId; @Nonnull public final String mId;
@Nonnull @Nonnull public final Locale mLocale;
public final Locale mLocale; @Nullable public final String mDescription;
@Nullable @Nullable public final String mFilename;
public final String mDescription; public final long mFilesize;
public final AssetFileAddress mFileAddress; public final long mModifiedTimeMillis;
public final int mVersion; public final int mVersion;
public DictionaryInfo(@Nonnull final String id, @Nonnull final Locale locale, public DictionaryInfo(@Nonnull String id, @Nonnull Locale locale,
@Nullable final String description, @Nullable final AssetFileAddress fileAddress, @Nullable String description, @Nullable String filename,
final int version) { long filesize, long modifiedTimeMillis, int version) {
mId = id; mId = id;
mLocale = locale; mLocale = locale;
mDescription = description; mDescription = description;
mFileAddress = fileAddress; mFilename = filename;
mFilesize = filesize;
mModifiedTimeMillis = modifiedTimeMillis;
mVersion = version; mVersion = version;
} }
@ -90,12 +96,9 @@ public class DictionaryInfoUtils {
values.put(WORDLISTID_COLUMN, mId); values.put(WORDLISTID_COLUMN, mId);
values.put(LOCALE_COLUMN, mLocale.toString()); values.put(LOCALE_COLUMN, mLocale.toString());
values.put(DESCRIPTION_COLUMN, mDescription); values.put(DESCRIPTION_COLUMN, mDescription);
values.put(LOCAL_FILENAME_COLUMN, values.put(LOCAL_FILENAME_COLUMN, mFilename != null ? mFilename : "");
mFileAddress != null ? mFileAddress.mFilename : ""); values.put(DATE_COLUMN, TimeUnit.MILLISECONDS.toSeconds(mModifiedTimeMillis));
values.put(DATE_COLUMN, TimeUnit.MILLISECONDS.toSeconds( values.put(FILESIZE_COLUMN, mFilesize);
mFileAddress != null ? new File(mFileAddress.mFilename).lastModified() : 0));
values.put(FILESIZE_COLUMN,
mFileAddress != null ? mFileAddress.mLength : 0);
values.put(VERSION_COLUMN, mVersion); values.put(VERSION_COLUMN, mVersion);
return values; return values;
} }
@ -185,6 +188,17 @@ public class DictionaryInfoUtils {
return new File(DictionaryInfoUtils.getWordListCacheDirectory(context)).listFiles(); return new File(DictionaryInfoUtils.getWordListCacheDirectory(context)).listFiles();
} }
@Nullable
public static File[] getUnusedDictionaryList(final Context context) {
return context.getFilesDir().listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
return !TextUtils.isEmpty(filename) && filename.endsWith(".dict")
&& filename.contains(TEMP_DICT_FILE_SUB);
}
});
}
/** /**
* Returns the category for a given file name. * Returns the category for a given file name.
* *
@ -342,12 +356,44 @@ public class DictionaryInfoUtils {
* @return information of the specified dictionary. * @return information of the specified dictionary.
*/ */
private static DictionaryInfo createDictionaryInfoFromFileAddress( private static DictionaryInfo createDictionaryInfoFromFileAddress(
final AssetFileAddress fileAddress, Locale locale) { @Nonnull final AssetFileAddress fileAddress, final Locale locale) {
final String id = getMainDictId(locale); final String id = getMainDictId(locale);
final int version = DictionaryHeaderUtils.getContentVersion(fileAddress); final int version = DictionaryHeaderUtils.getContentVersion(fileAddress);
final String description = SubtypeLocaleUtils final String description = SubtypeLocaleUtils
.getSubtypeLocaleDisplayName(locale.toString()); .getSubtypeLocaleDisplayName(locale.toString());
return new DictionaryInfo(id, locale, description, fileAddress, version); // Do not store the filename on db as it will try to move the filename from db to the
// cached directory. If the filename is already in cached directory, this is not
// necessary.
final String filenameToStoreOnDb = null;
return new DictionaryInfo(id, locale, description, filenameToStoreOnDb,
fileAddress.mLength, new File(fileAddress.mFilename).lastModified(), version);
}
/**
* Returns the information of the dictionary for the given {@link AssetFileAddress}.
* If the file is corrupted or a pre-fava file, then the file gets deleted and the null
* value is returned.
*/
@Nullable
private static DictionaryInfo createDictionaryInfoForUnCachedFile(
@Nonnull final AssetFileAddress fileAddress, final Locale locale) {
final String id = getMainDictId(locale);
final int version = DictionaryHeaderUtils.getContentVersion(fileAddress);
if (version == -1) {
// Purge the pre-fava/corrupted unused dictionaires.
fileAddress.deleteUnderlyingFile();
return null;
}
final String description = SubtypeLocaleUtils
.getSubtypeLocaleDisplayName(locale.toString());
final File unCachedFile = new File(fileAddress.mFilename);
// Store just the filename and not the full path.
final String filenameToStoreOnDb = unCachedFile.getName();
return new DictionaryInfo(id, locale, description, filenameToStoreOnDb, fileAddress.mLength,
unCachedFile.lastModified(), version);
} }
/** /**
@ -358,7 +404,7 @@ public class DictionaryInfoUtils {
final int version = -1; final int version = -1;
final String description = SubtypeLocaleUtils final String description = SubtypeLocaleUtils
.getSubtypeLocaleDisplayName(locale.toString()); .getSubtypeLocaleDisplayName(locale.toString());
return new DictionaryInfo(id, locale, description, null, version); return new DictionaryInfo(id, locale, description, null, 0L, 0L, version);
} }
private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList, private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList,
@ -380,7 +426,7 @@ public class DictionaryInfoUtils {
final Context context) { final Context context) {
final ArrayList<DictionaryInfo> dictList = new ArrayList<>(); final ArrayList<DictionaryInfo> dictList = new ArrayList<>();
// Retrieve downloaded dictionaries // Retrieve downloaded dictionaries from cached directories
final File[] directoryList = getCachedDirectoryList(context); final File[] directoryList = getCachedDirectoryList(context);
if (null != directoryList) { if (null != directoryList) {
for (final File directory : directoryList) { for (final File directory : directoryList) {
@ -407,6 +453,25 @@ public class DictionaryInfoUtils {
} }
} }
// Retrieve downloaded dictionaries from the unused dictionaries.
File[] unusedDictionaryList = getUnusedDictionaryList(context);
if (unusedDictionaryList != null) {
for (File dictionaryFile : unusedDictionaryList) {
String fileName = dictionaryFile.getName();
int index = fileName.indexOf(TEMP_DICT_FILE_SUB);
if (index == -1) {
continue;
}
String locale = fileName.substring(0, index);
DictionaryInfo dictionaryInfo = createDictionaryInfoForUnCachedFile(
AssetFileAddress.makeFromFile(dictionaryFile),
LocaleUtils.constructLocaleFromString(locale));
if (dictionaryInfo != null) {
addOrUpdateDictInfo(dictList, dictionaryInfo);
}
}
}
// Retrieve files from assets // Retrieve files from assets
final Resources resources = context.getResources(); final Resources resources = context.getResources();
final AssetManager assets = resources.getAssets(); final AssetManager assets = resources.getAssets();