Clean up dictionary pack presence test.

This method is much cleaner and much more readable.

Change-Id: I8055c169ef7c4453ab45c463704bd56a6080da4f
This commit is contained in:
Jean Chalard 2013-02-12 17:59:36 -08:00
parent 69cc3cfe1f
commit a9df972780

View file

@ -23,6 +23,7 @@ import android.content.Context;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.RemoteException;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -94,23 +95,6 @@ public final class BinaryDictionaryFileDumper {
path); path);
} }
/**
* Finds out whether the dictionary pack is available on this device.
* @param context A context to get the content resolver.
* @return whether the dictionary pack is present or not.
*/
private static boolean isDictionaryPackPresent(final Context context) {
final ContentResolver cr = context.getContentResolver();
final ContentProviderClient client =
cr.acquireContentProviderClient(getProviderUriBuilder("").build());
if (client != null) {
client.release();
return true;
} else {
return false;
}
}
/** /**
* Queries a content provider for the list of word lists for a specific locale * Queries a content provider for the list of word lists for a specific locale
* available to copy into Latin IME. * available to copy into Latin IME.
@ -128,15 +112,14 @@ public final class BinaryDictionaryFileDumper {
} }
final Uri dictionaryPackUri = builder.build(); final Uri dictionaryPackUri = builder.build();
final ContentResolver resolver = context.getContentResolver(); final ContentProviderClient client = context.getContentResolver().
acquireContentProviderClient(getProviderUriBuilder("").build());
if (null == client) return Collections.<WordListInfo>emptyList();
try { try {
final Cursor c = resolver.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null, final Cursor c = client.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null,
null); null);
if (null == c) { if (null == c) {
if (isDictionaryPackPresent(context)) { reinitializeClientRecordInDictionaryContentProvider(context, client, clientId);
reinitializeClientRecordInDictionaryContentProvider(context, resolver,
clientId);
}
return Collections.<WordListInfo>emptyList(); return Collections.<WordListInfo>emptyList();
} }
if (c.getCount() <= 0 || !c.moveToFirst()) { if (c.getCount() <= 0 || !c.moveToFirst()) {
@ -152,21 +135,20 @@ public final class BinaryDictionaryFileDumper {
} while (c.moveToNext()); } while (c.moveToNext());
c.close(); c.close();
return list; return list;
} catch (IllegalArgumentException e) { } catch (RemoteException e) {
// Any method call on the content resolver may unexpectedly crash without notice // The documentation is unclear as to in which cases this may happen, but it probably
// if the content provider is not present (for example, while crypting a device). // happens when the content provider got suddenly killed because it crashed or because
// Testing seems to indicate that ContentResolver#query() merely returns null // the user disabled it through Settings.
// while ContentResolver#delete throws IllegalArgumentException but this is Log.e(TAG, "RemoteException: communication with the dictionary pack cut", e);
// undocumented, so all ContentResolver methods should be protected. A crash here is
// dangerous because crashing here would brick any encrypted device - we need the
// keyboard to be up and working to enter the password. So let's be as safe as possible.
Log.e(TAG, "IllegalArgumentException: the dictionary pack can't be contacted?", e);
return Collections.<WordListInfo>emptyList(); return Collections.<WordListInfo>emptyList();
} catch (Exception e) { } catch (Exception e) {
// Just in case we hit a problem in communication with the dictionary pack. // A crash here is dangerous because crashing here would brick any encrypted device -
// We don't want to die. // we need the keyboard to be up and working to enter the password, so we don't want
Log.e(TAG, "Exception communicating with the dictionary pack", e); // to die no matter what. So let's be as safe as possible.
Log.e(TAG, "Unexpected exception communicating with the dictionary pack", e);
return Collections.<WordListInfo>emptyList(); return Collections.<WordListInfo>emptyList();
} finally {
client.release();
} }
} }
@ -380,7 +362,7 @@ public final class BinaryDictionaryFileDumper {
} }
private static void reinitializeClientRecordInDictionaryContentProvider(final Context context, private static void reinitializeClientRecordInDictionaryContentProvider(final Context context,
final ContentResolver resolver, final String clientId) { final ContentProviderClient client, final String clientId) throws RemoteException {
final String metadataFileUri = context.getString(R.string.dictionary_pack_metadata_uri); final String metadataFileUri = context.getString(R.string.dictionary_pack_metadata_uri);
if (TextUtils.isEmpty(metadataFileUri)) return; if (TextUtils.isEmpty(metadataFileUri)) return;
// Tell the content provider to reset all information about this client id // Tell the content provider to reset all information about this client id
@ -388,12 +370,12 @@ public final class BinaryDictionaryFileDumper {
.appendPath(QUERY_PATH_METADATA) .appendPath(QUERY_PATH_METADATA)
.appendQueryParameter(QUERY_PARAMETER_PROTOCOL, QUERY_PARAMETER_PROTOCOL_VALUE) .appendQueryParameter(QUERY_PARAMETER_PROTOCOL, QUERY_PARAMETER_PROTOCOL_VALUE)
.build(); .build();
resolver.delete(metadataContentUri, null, null); client.delete(metadataContentUri, null, null);
// Update the metadata URI // Update the metadata URI
final ContentValues metadataValues = new ContentValues(); final ContentValues metadataValues = new ContentValues();
metadataValues.put(INSERT_METADATA_CLIENT_ID_COLUMN, clientId); metadataValues.put(INSERT_METADATA_CLIENT_ID_COLUMN, clientId);
metadataValues.put(INSERT_METADATA_METADATA_URI_COLUMN, metadataFileUri); metadataValues.put(INSERT_METADATA_METADATA_URI_COLUMN, metadataFileUri);
resolver.insert(metadataContentUri, metadataValues); client.insert(metadataContentUri, metadataValues);
// Update the dictionary list. // Update the dictionary list.
final Uri dictionaryContentUriBase = getProviderUriBuilder(clientId) final Uri dictionaryContentUriBase = getProviderUriBuilder(clientId)
@ -405,7 +387,7 @@ public final class BinaryDictionaryFileDumper {
final int length = dictionaryList.size(); final int length = dictionaryList.size();
for (int i = 0; i < length; ++i) { for (int i = 0; i < length; ++i) {
final DictionaryInfo info = dictionaryList.get(i); final DictionaryInfo info = dictionaryList.get(i);
resolver.insert(Uri.withAppendedPath(dictionaryContentUriBase, info.mId), client.insert(Uri.withAppendedPath(dictionaryContentUriBase, info.mId),
info.toContentValues()); info.toContentValues());
} }
} }