Catch exceptions we can't do anything about.
This also abstracts away the "package deactivated" case for simpler and safer code. Bug: 11072561 Change-Id: Idaaf2ae8d8d5b2c4a15de641bbf2f8c5c7cc9410main
parent
4197c6f3ab
commit
a149731a67
|
@ -117,16 +117,11 @@ public final class ActionBatch {
|
||||||
final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
|
final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
|
||||||
mWordList.mId, mWordList.mVersion);
|
mWordList.mId, mWordList.mVersion);
|
||||||
final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
|
final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
|
||||||
final DownloadManager manager =
|
final DownloadManagerWrapper manager = new DownloadManagerWrapper(context);
|
||||||
(DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
if (MetadataDbHelper.STATUS_DOWNLOADING == status) {
|
if (MetadataDbHelper.STATUS_DOWNLOADING == status) {
|
||||||
// The word list is still downloading. Cancel the download and revert the
|
// The word list is still downloading. Cancel the download and revert the
|
||||||
// word list status to "available".
|
// word list status to "available".
|
||||||
if (null != manager) {
|
|
||||||
// DownloadManager is disabled (or not installed?). We can't cancel - there
|
|
||||||
// is nothing we can do. We still need to mark the entry as available.
|
|
||||||
manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
|
manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
|
||||||
}
|
|
||||||
MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
|
MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
|
||||||
} else if (MetadataDbHelper.STATUS_AVAILABLE != status) {
|
} else if (MetadataDbHelper.STATUS_AVAILABLE != status) {
|
||||||
// Should never happen
|
// Should never happen
|
||||||
|
@ -136,9 +131,6 @@ public final class ActionBatch {
|
||||||
// Download it.
|
// Download it.
|
||||||
DebugLogUtils.l("Upgrade word list, downloading", mWordList.mRemoteFilename);
|
DebugLogUtils.l("Upgrade word list, downloading", mWordList.mRemoteFilename);
|
||||||
|
|
||||||
// TODO: if DownloadManager is disabled or not installed, download by ourselves
|
|
||||||
if (null == manager) return;
|
|
||||||
|
|
||||||
// This is an upgraded word list: we should download it.
|
// This is an upgraded word list: we should download it.
|
||||||
// Adding a disambiguator to circumvent a bug in older versions of DownloadManager.
|
// Adding a disambiguator to circumvent a bug in older versions of DownloadManager.
|
||||||
// DownloadManager also stupidly cuts the extension to replace with its own that it
|
// DownloadManager also stupidly cuts the extension to replace with its own that it
|
||||||
|
@ -293,13 +285,8 @@ public final class ActionBatch {
|
||||||
}
|
}
|
||||||
// The word list is still downloading. Cancel the download and revert the
|
// The word list is still downloading. Cancel the download and revert the
|
||||||
// word list status to "available".
|
// word list status to "available".
|
||||||
final DownloadManager manager =
|
final DownloadManagerWrapper manager = new DownloadManagerWrapper(context);
|
||||||
(DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
if (null != manager) {
|
|
||||||
// If we can't cancel the download because DownloadManager is not available,
|
|
||||||
// we still need to mark the entry as available.
|
|
||||||
manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
|
manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
|
||||||
}
|
|
||||||
MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
|
MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,26 +107,22 @@ public class DictionaryDownloadProgressBar extends ProgressBar {
|
||||||
|
|
||||||
private class UpdaterThread extends Thread {
|
private class UpdaterThread extends Thread {
|
||||||
private final static int REPORT_PERIOD = 150; // how often to report progress, in ms
|
private final static int REPORT_PERIOD = 150; // how often to report progress, in ms
|
||||||
final DownloadManager mDownloadManager;
|
final DownloadManagerWrapper mDownloadManagerWrapper;
|
||||||
final int mId;
|
final int mId;
|
||||||
public UpdaterThread(final Context context, final int id) {
|
public UpdaterThread(final Context context, final int id) {
|
||||||
super();
|
super();
|
||||||
mDownloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
mDownloadManagerWrapper = new DownloadManagerWrapper(context);
|
||||||
mId = id;
|
mId = id;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
// It's almost impossible that mDownloadManager is null (it would mean it has been
|
|
||||||
// disabled between pressing the 'install' button and displaying the progress
|
|
||||||
// bar), but just in case.
|
|
||||||
if (null == mDownloadManager) return;
|
|
||||||
final UpdateHelper updateHelper = new UpdateHelper();
|
final UpdateHelper updateHelper = new UpdateHelper();
|
||||||
final Query query = new Query().setFilterById(mId);
|
final Query query = new Query().setFilterById(mId);
|
||||||
int lastProgress = 0;
|
int lastProgress = 0;
|
||||||
setIndeterminate(true);
|
setIndeterminate(true);
|
||||||
while (!isInterrupted()) {
|
while (!isInterrupted()) {
|
||||||
final Cursor cursor = mDownloadManager.query(query);
|
final Cursor cursor = mDownloadManagerWrapper.query(query);
|
||||||
if (null == cursor) {
|
if (null == cursor) {
|
||||||
// Can't contact DownloadManager: this should never happen.
|
// Can't contact DownloadManager: this should never happen.
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.dictionarypack;
|
||||||
|
|
||||||
|
import android.app.DownloadManager;
|
||||||
|
import android.app.DownloadManager.Query;
|
||||||
|
import android.app.DownloadManager.Request;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteException;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to help with calling DownloadManager methods.
|
||||||
|
*
|
||||||
|
* Mostly, the problem here is that most methods from DownloadManager may throw SQL exceptions if
|
||||||
|
* they can't open the database on disk. We want to avoid crashing in these cases but can't do
|
||||||
|
* much more, so this class insulates the callers from these. SQLiteException also inherit from
|
||||||
|
* RuntimeException so they are unchecked :(
|
||||||
|
* While we're at it, we also insulate callers from the cases where DownloadManager is disabled,
|
||||||
|
* and getSystemService returns null.
|
||||||
|
*/
|
||||||
|
public class DownloadManagerWrapper {
|
||||||
|
private final static String TAG = DownloadManagerWrapper.class.getSimpleName();
|
||||||
|
private final DownloadManager mDownloadManager;
|
||||||
|
|
||||||
|
public DownloadManagerWrapper(final Context context) {
|
||||||
|
this((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DownloadManagerWrapper(final DownloadManager downloadManager) {
|
||||||
|
mDownloadManager = downloadManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(final long... ids) {
|
||||||
|
try {
|
||||||
|
if (null != mDownloadManager) {
|
||||||
|
mDownloadManager.remove(ids);
|
||||||
|
}
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
// We couldn't remove the file from DownloadManager. Apparently, the database can't
|
||||||
|
// be opened. It may be a problem with file system corruption. In any case, there is
|
||||||
|
// not much we can do apart from avoiding crashing.
|
||||||
|
Log.e(TAG, "Can't remove files with ID " + ids + " from download manager", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParcelFileDescriptor openDownloadedFile(final long fileId) throws FileNotFoundException {
|
||||||
|
try {
|
||||||
|
if (null != mDownloadManager) {
|
||||||
|
return mDownloadManager.openDownloadedFile(fileId);
|
||||||
|
}
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(TAG, "Can't open downloaded file with ID " + fileId, e);
|
||||||
|
}
|
||||||
|
// We come here if mDownloadManager is null or if an exception was thrown.
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor query(final Query query) {
|
||||||
|
try {
|
||||||
|
if (null != mDownloadManager) {
|
||||||
|
return mDownloadManager.query(query);
|
||||||
|
}
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(TAG, "Can't query the download manager", e);
|
||||||
|
}
|
||||||
|
// We come here if mDownloadManager is null or if an exception was thrown.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long enqueue(final Request request) {
|
||||||
|
try {
|
||||||
|
if (null != mDownloadManager) {
|
||||||
|
return mDownloadManager.enqueue(request);
|
||||||
|
}
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(TAG, "Can't enqueue a request with the download manager", e);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -249,13 +249,7 @@ public final class UpdateHandler {
|
||||||
metadataRequest.setVisibleInDownloadsUi(
|
metadataRequest.setVisibleInDownloadsUi(
|
||||||
res.getBoolean(R.bool.metadata_downloads_visible_in_download_UI));
|
res.getBoolean(R.bool.metadata_downloads_visible_in_download_UI));
|
||||||
|
|
||||||
final DownloadManager manager =
|
final DownloadManagerWrapper manager = new DownloadManagerWrapper(context);
|
||||||
(DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
if (null == manager) {
|
|
||||||
// Download manager is not installed or disabled.
|
|
||||||
// TODO: fall back to self-managed download?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cancelUpdateWithDownloadManager(context, metadataUri, manager);
|
cancelUpdateWithDownloadManager(context, metadataUri, manager);
|
||||||
final long downloadId;
|
final long downloadId;
|
||||||
synchronized (sSharedIdProtector) {
|
synchronized (sSharedIdProtector) {
|
||||||
|
@ -278,10 +272,10 @@ public final class UpdateHandler {
|
||||||
*
|
*
|
||||||
* @param context the context to open the database on
|
* @param context the context to open the database on
|
||||||
* @param metadataUri the URI to cancel
|
* @param metadataUri the URI to cancel
|
||||||
* @param manager an instance of DownloadManager
|
* @param manager an wrapped instance of DownloadManager
|
||||||
*/
|
*/
|
||||||
private static void cancelUpdateWithDownloadManager(final Context context,
|
private static void cancelUpdateWithDownloadManager(final Context context,
|
||||||
final String metadataUri, final DownloadManager manager) {
|
final String metadataUri, final DownloadManagerWrapper manager) {
|
||||||
synchronized (sSharedIdProtector) {
|
synchronized (sSharedIdProtector) {
|
||||||
final long metadataDownloadId =
|
final long metadataDownloadId =
|
||||||
MetadataDbHelper.getMetadataDownloadIdForURI(context, metadataUri);
|
MetadataDbHelper.getMetadataDownloadIdForURI(context, metadataUri);
|
||||||
|
@ -306,10 +300,9 @@ public final class UpdateHandler {
|
||||||
* @param clientId the ID of the client we want to cancel the update of
|
* @param clientId the ID of the client we want to cancel the update of
|
||||||
*/
|
*/
|
||||||
public static void cancelUpdate(final Context context, final String clientId) {
|
public static void cancelUpdate(final Context context, final String clientId) {
|
||||||
final DownloadManager manager =
|
final DownloadManagerWrapper manager = new DownloadManagerWrapper(context);
|
||||||
(DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
final String metadataUri = MetadataDbHelper.getMetadataUriAsString(context, clientId);
|
final String metadataUri = MetadataDbHelper.getMetadataUriAsString(context, clientId);
|
||||||
if (null != manager) cancelUpdateWithDownloadManager(context, metadataUri, manager);
|
cancelUpdateWithDownloadManager(context, metadataUri, manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -323,15 +316,15 @@ public final class UpdateHandler {
|
||||||
* download request id, which is not known before submitting the request to the download
|
* download request id, which is not known before submitting the request to the download
|
||||||
* manager. Hence, it only updates the relevant line.
|
* manager. Hence, it only updates the relevant line.
|
||||||
*
|
*
|
||||||
* @param manager the download manager service to register the request with.
|
* @param manager a wrapped download manager service to register the request with.
|
||||||
* @param request the request to register.
|
* @param request the request to register.
|
||||||
* @param db the metadata database.
|
* @param db the metadata database.
|
||||||
* @param id the id of the word list.
|
* @param id the id of the word list.
|
||||||
* @param version the version of the word list.
|
* @param version the version of the word list.
|
||||||
* @return the download id returned by the download manager.
|
* @return the download id returned by the download manager.
|
||||||
*/
|
*/
|
||||||
public static long registerDownloadRequest(final DownloadManager manager, final Request request,
|
public static long registerDownloadRequest(final DownloadManagerWrapper manager,
|
||||||
final SQLiteDatabase db, final String id, final int version) {
|
final Request request, final SQLiteDatabase db, final String id, final int version) {
|
||||||
DebugLogUtils.l("RegisterDownloadRequest for word list id : ", id, ", version ", version);
|
DebugLogUtils.l("RegisterDownloadRequest for word list id : ", id, ", version ", version);
|
||||||
final long downloadId;
|
final long downloadId;
|
||||||
synchronized (sSharedIdProtector) {
|
synchronized (sSharedIdProtector) {
|
||||||
|
@ -345,8 +338,8 @@ public final class UpdateHandler {
|
||||||
/**
|
/**
|
||||||
* Retrieve information about a specific download from DownloadManager.
|
* Retrieve information about a specific download from DownloadManager.
|
||||||
*/
|
*/
|
||||||
private static CompletedDownloadInfo getCompletedDownloadInfo(final DownloadManager manager,
|
private static CompletedDownloadInfo getCompletedDownloadInfo(
|
||||||
final long downloadId) {
|
final DownloadManagerWrapper manager, final long downloadId) {
|
||||||
final Query query = new Query().setFilterById(downloadId);
|
final Query query = new Query().setFilterById(downloadId);
|
||||||
final Cursor cursor = manager.query(query);
|
final Cursor cursor = manager.query(query);
|
||||||
|
|
||||||
|
@ -425,8 +418,7 @@ public final class UpdateHandler {
|
||||||
DebugLogUtils.l("DownloadFinished with id", fileId);
|
DebugLogUtils.l("DownloadFinished with id", fileId);
|
||||||
if (NOT_AN_ID == fileId) return; // Spurious wake-up: ignore
|
if (NOT_AN_ID == fileId) return; // Spurious wake-up: ignore
|
||||||
|
|
||||||
final DownloadManager manager =
|
final DownloadManagerWrapper manager = new DownloadManagerWrapper(context);
|
||||||
(DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
final CompletedDownloadInfo downloadInfo = getCompletedDownloadInfo(manager, fileId);
|
final CompletedDownloadInfo downloadInfo = getCompletedDownloadInfo(manager, fileId);
|
||||||
|
|
||||||
final ArrayList<DownloadRecord> recordList =
|
final ArrayList<DownloadRecord> recordList =
|
||||||
|
@ -517,7 +509,7 @@ public final class UpdateHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean handleDownloadedFile(final Context context,
|
private static boolean handleDownloadedFile(final Context context,
|
||||||
final DownloadRecord downloadRecord, final DownloadManager manager,
|
final DownloadRecord downloadRecord, final DownloadManagerWrapper manager,
|
||||||
final long fileId) {
|
final long fileId) {
|
||||||
try {
|
try {
|
||||||
// {@link handleWordList(Context,InputStream,ContentValues)}.
|
// {@link handleWordList(Context,InputStream,ContentValues)}.
|
||||||
|
|
Loading…
Reference in New Issue