Implement getting data files with protocol v2
This also does it for deleting them Bug: 8167342 Bug: 6789534 Change-Id: I1823f98508881f109a667146d3608003f87aa4cbmain
parent
4beaab2a88
commit
d4cbc4fd07
|
@ -74,6 +74,8 @@ public final class BinaryDictionaryFileDumper {
|
||||||
|
|
||||||
// The path fragment to append after the client ID for dictionary info requests.
|
// The path fragment to append after the client ID for dictionary info requests.
|
||||||
private static final String QUERY_PATH_DICT_INFO = "dict";
|
private static final String QUERY_PATH_DICT_INFO = "dict";
|
||||||
|
// The path fragment to append after the client ID for dictionary datafile requests.
|
||||||
|
private static final String QUERY_PATH_DATAFILE = "datafile";
|
||||||
// The path fragment to append after the client ID for updating the metadata URI.
|
// The path fragment to append after the client ID for updating the metadata URI.
|
||||||
private static final String QUERY_PATH_METADATA = "metadata";
|
private static final String QUERY_PATH_METADATA = "metadata";
|
||||||
private static final String INSERT_METADATA_CLIENT_ID_COLUMN = "clientid";
|
private static final String INSERT_METADATA_CLIENT_ID_COLUMN = "clientid";
|
||||||
|
@ -156,7 +158,7 @@ public final class BinaryDictionaryFileDumper {
|
||||||
c.close();
|
c.close();
|
||||||
return Collections.<WordListInfo>emptyList();
|
return Collections.<WordListInfo>emptyList();
|
||||||
}
|
}
|
||||||
final List<WordListInfo> list = CollectionUtils.newArrayList();
|
final ArrayList<WordListInfo> list = CollectionUtils.newArrayList();
|
||||||
do {
|
do {
|
||||||
final String wordListId = c.getString(0);
|
final String wordListId = c.getString(0);
|
||||||
final String wordListLocale = c.getString(1);
|
final String wordListLocale = c.getString(1);
|
||||||
|
@ -186,13 +188,18 @@ public final class BinaryDictionaryFileDumper {
|
||||||
/**
|
/**
|
||||||
* Helper method to encapsulate exception handling.
|
* Helper method to encapsulate exception handling.
|
||||||
*/
|
*/
|
||||||
private static AssetFileDescriptor openAssetFileDescriptor(final ContentResolver resolver,
|
private static AssetFileDescriptor openAssetFileDescriptor(
|
||||||
final Uri uri) {
|
final ContentProviderClient providerClient, final Uri uri) {
|
||||||
try {
|
try {
|
||||||
return resolver.openAssetFileDescriptor(uri, "r");
|
return providerClient.openAssetFile(uri, "r");
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// I don't want to log the word list URI here for security concerns
|
// I don't want to log the word list URI here for security concerns. The exception
|
||||||
Log.e(TAG, "Could not find a word list from the dictionary provider.");
|
// contains the name of the file, so let's not pass it to Log.e here.
|
||||||
|
Log.e(TAG, "Could not find a word list from the dictionary provider."
|
||||||
|
/* intentionally don't pass the exception (see comment above) */);
|
||||||
|
return null;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Can't communicate with the dictionary pack", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,9 +209,8 @@ public final class BinaryDictionaryFileDumper {
|
||||||
* to the cache file name designated by its id and locale, overwriting it if already present
|
* to the cache file name designated by its id and locale, overwriting it if already present
|
||||||
* and creating it (and its containing directory) if necessary.
|
* and creating it (and its containing directory) if necessary.
|
||||||
*/
|
*/
|
||||||
private static AssetFileAddress cacheWordList(final String id, final String locale,
|
private static AssetFileAddress cacheWordList(final String wordlistId, final String locale,
|
||||||
final ContentResolver resolver, final Context context) {
|
final ContentProviderClient providerClient, final Context context) {
|
||||||
|
|
||||||
final int COMPRESSED_CRYPTED_COMPRESSED = 0;
|
final int COMPRESSED_CRYPTED_COMPRESSED = 0;
|
||||||
final int CRYPTED_COMPRESSED = 1;
|
final int CRYPTED_COMPRESSED = 1;
|
||||||
final int COMPRESSED_CRYPTED = 2;
|
final int COMPRESSED_CRYPTED = 2;
|
||||||
|
@ -214,11 +220,20 @@ public final class BinaryDictionaryFileDumper {
|
||||||
final int MODE_MIN = COMPRESSED_CRYPTED_COMPRESSED;
|
final int MODE_MIN = COMPRESSED_CRYPTED_COMPRESSED;
|
||||||
final int MODE_MAX = NONE;
|
final int MODE_MAX = NONE;
|
||||||
|
|
||||||
final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id);
|
final String clientId = context.getString(R.string.dictionary_pack_client_id);
|
||||||
final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context);
|
final Uri.Builder wordListUriBuilder;
|
||||||
|
try {
|
||||||
|
wordListUriBuilder = getContentUriBuilderForType(clientId,
|
||||||
|
providerClient, QUERY_PATH_DATAFILE, wordlistId /* extraPath */);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Can't communicate with the dictionary pack", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final String finalFileName =
|
||||||
|
DictionaryInfoUtils.getCacheFileName(wordlistId, locale, context);
|
||||||
String tempFileName;
|
String tempFileName;
|
||||||
try {
|
try {
|
||||||
tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
|
tempFileName = BinaryDictionaryGetter.getTempFileName(wordlistId, context);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Can't open the temporary file", e);
|
Log.e(TAG, "Can't open the temporary file", e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -236,7 +251,7 @@ public final class BinaryDictionaryFileDumper {
|
||||||
final Uri wordListUri = wordListUriBuilder.build();
|
final Uri wordListUri = wordListUriBuilder.build();
|
||||||
try {
|
try {
|
||||||
// Open input.
|
// Open input.
|
||||||
afd = openAssetFileDescriptor(resolver, wordListUri);
|
afd = openAssetFileDescriptor(providerClient, wordListUri);
|
||||||
// If we can't open it at all, don't even try a number of times.
|
// If we can't open it at all, don't even try a number of times.
|
||||||
if (null == afd) return null;
|
if (null == afd) return null;
|
||||||
originalSourceStream = afd.createInputStream();
|
originalSourceStream = afd.createInputStream();
|
||||||
|
@ -284,10 +299,10 @@ public final class BinaryDictionaryFileDumper {
|
||||||
}
|
}
|
||||||
wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
|
wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
|
||||||
QUERY_PARAMETER_SUCCESS);
|
QUERY_PARAMETER_SUCCESS);
|
||||||
if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) {
|
if (0 >= providerClient.delete(wordListUriBuilder.build(), null, null)) {
|
||||||
Log.e(TAG, "Could not have the dictionary pack delete a word list");
|
Log.e(TAG, "Could not have the dictionary pack delete a word list");
|
||||||
}
|
}
|
||||||
BinaryDictionaryGetter.removeFilesWithIdExcept(context, id, finalFile);
|
BinaryDictionaryGetter.removeFilesWithIdExcept(context, wordlistId, finalFile);
|
||||||
// Success! Close files (through the finally{} clause) and return.
|
// Success! Close files (through the finally{} clause) and return.
|
||||||
return AssetFileAddress.makeFromFileName(finalFileName);
|
return AssetFileAddress.makeFromFileName(finalFileName);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -327,8 +342,12 @@ public final class BinaryDictionaryFileDumper {
|
||||||
// as invalid.
|
// as invalid.
|
||||||
wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
|
wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
|
||||||
QUERY_PARAMETER_FAILURE);
|
QUERY_PARAMETER_FAILURE);
|
||||||
if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) {
|
try {
|
||||||
Log.e(TAG, "In addition, we were unable to delete it.");
|
if (0 >= providerClient.delete(wordListUriBuilder.build(), null, null)) {
|
||||||
|
Log.e(TAG, "In addition, we were unable to delete it.");
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "In addition, communication with the dictionary provider was cut", e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -345,17 +364,27 @@ public final class BinaryDictionaryFileDumper {
|
||||||
*/
|
*/
|
||||||
public static List<AssetFileAddress> cacheWordListsFromContentProvider(final Locale locale,
|
public static List<AssetFileAddress> cacheWordListsFromContentProvider(final Locale locale,
|
||||||
final Context context, final boolean hasDefaultWordList) {
|
final Context context, final boolean hasDefaultWordList) {
|
||||||
final ContentResolver resolver = context.getContentResolver();
|
final ContentProviderClient providerClient = context.getContentResolver().
|
||||||
final List<WordListInfo> idList = getWordListWordListInfos(locale, context,
|
acquireContentProviderClient(getProviderUriBuilder("").build());
|
||||||
hasDefaultWordList);
|
if (null == providerClient) {
|
||||||
final List<AssetFileAddress> fileAddressList = CollectionUtils.newArrayList();
|
Log.e(TAG, "Can't establish communication with the dictionary provider");
|
||||||
for (WordListInfo id : idList) {
|
return CollectionUtils.newArrayList();
|
||||||
final AssetFileAddress afd = cacheWordList(id.mId, id.mLocale, resolver, context);
|
}
|
||||||
if (null != afd) {
|
try {
|
||||||
fileAddressList.add(afd);
|
final List<WordListInfo> idList = getWordListWordListInfos(locale, context,
|
||||||
}
|
hasDefaultWordList);
|
||||||
|
final ArrayList<AssetFileAddress> fileAddressList = CollectionUtils.newArrayList();
|
||||||
|
for (WordListInfo id : idList) {
|
||||||
|
final AssetFileAddress afd =
|
||||||
|
cacheWordList(id.mId, id.mLocale, providerClient, context);
|
||||||
|
if (null != afd) {
|
||||||
|
fileAddressList.add(afd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileAddressList;
|
||||||
|
} finally {
|
||||||
|
providerClient.release();
|
||||||
}
|
}
|
||||||
return fileAddressList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue