Do not restrict downloads to WiFi networks.

Bug 21900337.

Change-Id: I82991b492ea4c02a28a1ccc898d6f12741f1b793
main
Dan Zivkovic 2015-06-17 12:53:55 -07:00
parent 764a18cd92
commit 02c28453fc
7 changed files with 23 additions and 134 deletions

View File

@ -1,38 +0,0 @@
/*
* Copyright (C) 2013 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.compat;
import android.app.DownloadManager;
import java.lang.reflect.Method;
public final class DownloadManagerCompatUtils {
// DownloadManager.Request#setAllowedOverMetered() has been introduced
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
private static final Method METHOD_setAllowedOverMetered = CompatUtils.getMethod(
DownloadManager.Request.class, "setAllowedOverMetered", boolean.class);
public static DownloadManager.Request setAllowedOverMetered(
final DownloadManager.Request request, final boolean allowOverMetered) {
return (DownloadManager.Request)CompatUtils.invoke(request,
request /* default return value */, METHOD_setAllowedOverMetered, allowOverMetered);
}
public static final boolean hasSetAllowedOverMetered() {
return null != METHOD_setAllowedOverMetered;
}
}

View File

@ -25,7 +25,6 @@ import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.android.inputmethod.compat.DownloadManagerCompatUtils;
import com.android.inputmethod.latin.BinaryDictionaryFileDumper; import com.android.inputmethod.latin.BinaryDictionaryFileDumper;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.common.LocaleUtils; import com.android.inputmethod.latin.common.LocaleUtils;
@ -86,7 +85,7 @@ public final class ActionBatch {
* Execute this action NOW. * Execute this action NOW.
* @param context the context to get system services, resources, databases * @param context the context to get system services, resources, databases
*/ */
public void execute(final Context context); void execute(final Context context);
} }
/** /**
@ -98,13 +97,10 @@ public final class ActionBatch {
private final String mClientId; private final String mClientId;
// The data to download. May not be null. // The data to download. May not be null.
final WordListMetadata mWordList; final WordListMetadata mWordList;
final boolean mForceStartNow; public StartDownloadAction(final String clientId, final WordListMetadata wordList) {
public StartDownloadAction(final String clientId,
final WordListMetadata wordList, final boolean forceStartNow) {
DebugLogUtils.l("New download action for client ", clientId, " : ", wordList); DebugLogUtils.l("New download action for client ", clientId, " : ", wordList);
mClientId = clientId; mClientId = clientId;
mWordList = wordList; mWordList = wordList;
mForceStartNow = forceStartNow;
} }
@Override @Override
@ -143,28 +139,7 @@ public final class ActionBatch {
final Request request = new Request(uri); final Request request = new Request(uri);
final Resources res = context.getResources(); final Resources res = context.getResources();
if (!mForceStartNow) { request.setAllowedNetworkTypes(Request.NETWORK_WIFI | Request.NETWORK_MOBILE);
if (DownloadManagerCompatUtils.hasSetAllowedOverMetered()) {
final boolean allowOverMetered;
switch (UpdateHandler.getDownloadOverMeteredSetting(context)) {
case UpdateHandler.DOWNLOAD_OVER_METERED_DISALLOWED:
// User said no: don't allow.
allowOverMetered = false;
break;
case UpdateHandler.DOWNLOAD_OVER_METERED_ALLOWED:
// User said yes: allow.
allowOverMetered = true;
break;
default: // UpdateHandler.DOWNLOAD_OVER_METERED_SETTING_UNKNOWN
// Don't know: use the default value from configuration.
allowOverMetered = res.getBoolean(R.bool.allow_over_metered);
}
DownloadManagerCompatUtils.setAllowedOverMetered(request, allowOverMetered);
} else {
request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
}
request.setAllowedOverRoaming(res.getBoolean(R.bool.allow_over_roaming));
} // if mForceStartNow, then allow all network types and roaming, which is the default.
request.setTitle(mWordList.mDescription); request.setTitle(mWordList.mDescription);
request.setNotificationVisibility( request.setNotificationVisibility(
res.getBoolean(R.bool.display_notification_for_auto_update) res.getBoolean(R.bool.display_notification_for_auto_update)

View File

@ -22,8 +22,6 @@ import android.content.SharedPreferences;
public final class CommonPreferences { public final class CommonPreferences {
private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs"; private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs";
public static final String PREF_FORCE_DOWNLOAD_DICT = "pref_key_force_download_dict";
public static SharedPreferences getCommonPreferences(final Context context) { public static SharedPreferences getCommonPreferences(final Context context) {
return context.getSharedPreferences(COMMON_PREFERENCES_NAME, 0); return context.getSharedPreferences(COMMON_PREFERENCES_NAME, 0);
} }
@ -39,14 +37,4 @@ public final class CommonPreferences {
editor.putBoolean(id, false); editor.putBoolean(id, false);
editor.apply(); editor.apply();
} }
public static boolean isForceDownloadDict(Context context) {
return getCommonPreferences(context).getBoolean(PREF_FORCE_DOWNLOAD_DICT, false);
}
public static void setForceDownloadDict(Context context, boolean forceDownload) {
SharedPreferences.Editor editor = getCommonPreferences(context).edit();
editor.putBoolean(PREF_FORCE_DOWNLOAD_DICT, forceDownload);
editor.apply();
}
} }

View File

@ -192,27 +192,22 @@ public final class DictionaryService extends Service {
} }
static void dispatchBroadcast(final Context context, final Intent intent) { static void dispatchBroadcast(final Context context, final Intent intent) {
if (DATE_CHANGED_INTENT_ACTION.equals(intent.getAction())) { final String action = intent.getAction();
// Do not force download dictionaries on date change updates. if (DATE_CHANGED_INTENT_ACTION.equals(action)) {
CommonPreferences.setForceDownloadDict(context, false);
// This happens when the date of the device changes. This normally happens // This happens when the date of the device changes. This normally happens
// at midnight local time, but it may happen if the user changes the date // at midnight local time, but it may happen if the user changes the date
// by hand or something similar happens. // by hand or something similar happens.
checkTimeAndMaybeSetupUpdateAlarm(context); checkTimeAndMaybeSetupUpdateAlarm(context);
} else if (DictionaryPackConstants.UPDATE_NOW_INTENT_ACTION.equals(intent.getAction())) { } else if (DictionaryPackConstants.UPDATE_NOW_INTENT_ACTION.equals(action)) {
// Intent to trigger an update now. // Intent to trigger an update now.
UpdateHandler.tryUpdate(context, CommonPreferences.isForceDownloadDict(context)); UpdateHandler.tryUpdate(context);
} else if (DictionaryPackConstants.INIT_AND_UPDATE_NOW_INTENT_ACTION.equals( } else if (DictionaryPackConstants.INIT_AND_UPDATE_NOW_INTENT_ACTION.equals(action)) {
intent.getAction())) {
// Enable force download of dictionaries irrespective of wifi or metered connection.
CommonPreferences.setForceDownloadDict(context, true);
// Initialize the client Db. // Initialize the client Db.
final String mClientId = context.getString(R.string.dictionary_pack_client_id); final String mClientId = context.getString(R.string.dictionary_pack_client_id);
BinaryDictionaryFileDumper.initializeClientRecordHelper(context, mClientId); BinaryDictionaryFileDumper.initializeClientRecordHelper(context, mClientId);
// Updates the metadata and the download the dictionaries. // Updates the metadata and the download the dictionaries.
UpdateHandler.tryUpdate(context, true); UpdateHandler.tryUpdate(context);
} else { } else {
UpdateHandler.downloadFinished(context, intent); UpdateHandler.downloadFinished(context, intent);
} }
@ -263,7 +258,7 @@ public final class DictionaryService extends Service {
*/ */
public static void updateNowIfNotUpdatedInAVeryLongTime(final Context context) { public static void updateNowIfNotUpdatedInAVeryLongTime(final Context context) {
if (!isLastUpdateAtLeastThisOld(context, VERY_LONG_TIME_MILLIS)) return; if (!isLastUpdateAtLeastThisOld(context, VERY_LONG_TIME_MILLIS)) return;
UpdateHandler.tryUpdate(context, CommonPreferences.isForceDownloadDict(context)); UpdateHandler.tryUpdate(context);
} }
/** /**

View File

@ -384,7 +384,7 @@ public final class DictionarySettingsFragment extends PreferenceFragment
// We call tryUpdate(), which returns whether we could successfully start an update. // We call tryUpdate(), which returns whether we could successfully start an update.
// If we couldn't, we'll never receive the end callback, so we stop the loading // If we couldn't, we'll never receive the end callback, so we stop the loading
// animation and return to the previous screen. // animation and return to the previous screen.
if (!UpdateHandler.tryUpdate(activity, true)) { if (!UpdateHandler.tryUpdate(activity)) {
stopLoadingAnimation(); stopLoadingAnimation();
} }
} }

View File

@ -266,8 +266,6 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
*/ */
@Override @Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
// Allow automatic download of dictionaries on upgrading the database.
CommonPreferences.setForceDownloadDict(mContext, true);
if (METADATA_DATABASE_INITIAL_VERSION == oldVersion if (METADATA_DATABASE_INITIAL_VERSION == oldVersion
&& METADATA_DATABASE_VERSION_WITH_CLIENTID <= newVersion && METADATA_DATABASE_VERSION_WITH_CLIENTID <= newVersion
&& CURRENT_METADATA_DATABASE_VERSION >= newVersion) { && CURRENT_METADATA_DATABASE_VERSION >= newVersion) {

View File

@ -36,7 +36,6 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.android.inputmethod.compat.ConnectivityManagerCompatUtils; import com.android.inputmethod.compat.ConnectivityManagerCompatUtils;
import com.android.inputmethod.compat.DownloadManagerCompatUtils;
import com.android.inputmethod.compat.NotificationCompatUtils; import com.android.inputmethod.compat.NotificationCompatUtils;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.common.LocaleUtils; import com.android.inputmethod.latin.common.LocaleUtils;
@ -106,9 +105,9 @@ public final class UpdateHandler {
* This is chiefly used by the dictionary manager UI. * This is chiefly used by the dictionary manager UI.
*/ */
public interface UpdateEventListener { public interface UpdateEventListener {
public void downloadedMetadata(boolean succeeded); void downloadedMetadata(boolean succeeded);
public void wordListDownloadFinished(String wordListId, boolean succeeded); void wordListDownloadFinished(String wordListId, boolean succeeded);
public void updateCycleCompleted(); void updateCycleCompleted();
} }
/** /**
@ -179,10 +178,9 @@ public final class UpdateHandler {
/** /**
* Download latest metadata from the server through DownloadManager for all known clients * Download latest metadata from the server through DownloadManager for all known clients
* @param context The context for retrieving resources * @param context The context for retrieving resources
* @param updateNow Whether we should update NOW, or respect bandwidth policies
* @return true if an update successfully started, false otherwise. * @return true if an update successfully started, false otherwise.
*/ */
public static boolean tryUpdate(final Context context, final boolean updateNow) { public static boolean tryUpdate(final Context context) {
// TODO: loop through all clients instead of only doing the default one. // TODO: loop through all clients instead of only doing the default one.
final TreeSet<String> uris = new TreeSet<>(); final TreeSet<String> uris = new TreeSet<>();
final Cursor cursor = MetadataDbHelper.queryClientIds(context); final Cursor cursor = MetadataDbHelper.queryClientIds(context);
@ -208,7 +206,7 @@ public final class UpdateHandler {
// it should have been rejected at the time of client registration; if there // it should have been rejected at the time of client registration; if there
// is a bug and it happens anyway, doing nothing is the right thing to do. // is a bug and it happens anyway, doing nothing is the right thing to do.
// For more information, {@see DictionaryProvider#insert(Uri, ContentValues)}. // For more information, {@see DictionaryProvider#insert(Uri, ContentValues)}.
updateClientsWithMetadataUri(context, updateNow, metadataUri); updateClientsWithMetadataUri(context, metadataUri);
started = true; started = true;
} }
} }
@ -219,11 +217,10 @@ public final class UpdateHandler {
* Download latest metadata from the server through DownloadManager for all relevant clients * Download latest metadata from the server through DownloadManager for all relevant clients
* *
* @param context The context for retrieving resources * @param context The context for retrieving resources
* @param updateNow Whether we should update NOW, or respect bandwidth policies
* @param metadataUri The client to update * @param metadataUri The client to update
*/ */
private static void updateClientsWithMetadataUri(final Context context, private static void updateClientsWithMetadataUri(
final boolean updateNow, final String metadataUri) { final Context context, final String metadataUri) {
PrivateLog.log("Update for metadata URI " + DebugLogUtils.s(metadataUri)); PrivateLog.log("Update for metadata URI " + DebugLogUtils.s(metadataUri));
// 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
@ -234,19 +231,7 @@ public final class UpdateHandler {
DebugLogUtils.l("Request =", metadataRequest); DebugLogUtils.l("Request =", metadataRequest);
final Resources res = context.getResources(); final Resources res = context.getResources();
// By default, download over roaming is allowed and all network types are allowed too. metadataRequest.setAllowedNetworkTypes(Request.NETWORK_WIFI | Request.NETWORK_MOBILE);
if (!updateNow) {
final boolean allowedOverMetered = res.getBoolean(R.bool.allow_over_metered);
// If we don't have to update NOW, then only do it over non-metered connections.
if (DownloadManagerCompatUtils.hasSetAllowedOverMetered()) {
DownloadManagerCompatUtils.setAllowedOverMetered(metadataRequest,
allowedOverMetered);
} else if (!allowedOverMetered) {
metadataRequest.setAllowedNetworkTypes(Request.NETWORK_WIFI);
}
metadataRequest.setAllowedOverRoaming(res.getBoolean(R.bool.allow_over_roaming));
}
metadataRequest.setTitle(res.getString(R.string.download_description)); metadataRequest.setTitle(res.getString(R.string.download_description));
// Do not show the notification when downloading the metadata. // Do not show the notification when downloading the metadata.
metadataRequest.setNotificationVisibility(Request.VISIBILITY_HIDDEN); metadataRequest.setNotificationVisibility(Request.VISIBILITY_HIDDEN);
@ -448,8 +433,6 @@ public final class UpdateHandler {
// download, so we are pretty sure it's alive. It's theoretically possible that it's // download, so we are pretty sure it's alive. It's theoretically possible that it's
// disabled right inbetween the firing of the intent and the control reaching here. // disabled right inbetween the firing of the intent and the control reaching here.
boolean dictionaryDownloaded = false;
for (final DownloadRecord record : recordList) { for (final DownloadRecord record : recordList) {
// downloadSuccessful is not final because we may still have exceptions from now on // downloadSuccessful is not final because we may still have exceptions from now on
boolean downloadSuccessful = false; boolean downloadSuccessful = false;
@ -464,15 +447,9 @@ public final class UpdateHandler {
final SQLiteDatabase db = MetadataDbHelper.getDb(context, record.mClientId); final SQLiteDatabase db = MetadataDbHelper.getDb(context, record.mClientId);
publishUpdateWordListCompleted(context, downloadSuccessful, fileId, publishUpdateWordListCompleted(context, downloadSuccessful, fileId,
db, record.mAttributes, record.mClientId); db, record.mAttributes, record.mClientId);
dictionaryDownloaded = true;
} }
} }
} }
if (dictionaryDownloaded) {
// Disable the force download after downloading the dictionaries.
CommonPreferences.setForceDownloadDict(context, false);
}
// Now that we're done using it, we can remove this download from DLManager // Now that we're done using it, we can remove this download from DLManager
manager.remove(fileId); manager.remove(fileId);
} }
@ -829,8 +806,7 @@ public final class UpdateHandler {
actions.add(new ActionBatch.MakeAvailableAction(clientId, newInfo)); actions.add(new ActionBatch.MakeAvailableAction(clientId, newInfo));
if (status == MetadataDbHelper.STATUS_INSTALLED if (status == MetadataDbHelper.STATUS_INSTALLED
|| status == MetadataDbHelper.STATUS_DISABLED) { || status == MetadataDbHelper.STATUS_DISABLED) {
actions.add(new ActionBatch.StartDownloadAction( actions.add(new ActionBatch.StartDownloadAction(clientId, newInfo));
clientId, newInfo, CommonPreferences.isForceDownloadDict(context)));
} else { } else {
// Pass true to ForgetAction: this is indeed an update to a non-installed // Pass true to ForgetAction: this is indeed an update to a non-installed
// word list, so activate status == AVAILABLE check // word list, so activate status == AVAILABLE check
@ -984,9 +960,7 @@ public final class UpdateHandler {
// auto-installed once to get auto-installed again, and that's what we want. // auto-installed once to get auto-installed again, and that's what we want.
final ActionBatch actions = new ActionBatch(); final ActionBatch actions = new ActionBatch();
actions.add(new ActionBatch.StartDownloadAction( actions.add(new ActionBatch.StartDownloadAction(
clientId, clientId, WordListMetadata.createFromContentValues(installCandidate)));
WordListMetadata.createFromContentValues(installCandidate),
CommonPreferences.isForceDownloadDict(context)));
final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN); final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN);
// We are in a content provider: we can't do any UI at all. We have to defer the displaying // We are in a content provider: we can't do any UI at all. We have to defer the displaying
// itself to the service. Also, we only display this when the user does not have a // itself to the service. Also, we only display this when the user does not have a
@ -1032,9 +1006,7 @@ public final class UpdateHandler {
|| MetadataDbHelper.STATUS_DELETING == status) { || MetadataDbHelper.STATUS_DELETING == status) {
actions.add(new ActionBatch.EnableAction(clientId, wordListMetaData)); actions.add(new ActionBatch.EnableAction(clientId, wordListMetaData));
} else if (MetadataDbHelper.STATUS_AVAILABLE == status) { } else if (MetadataDbHelper.STATUS_AVAILABLE == status) {
boolean forceDownloadDict = CommonPreferences.isForceDownloadDict(context); actions.add(new ActionBatch.StartDownloadAction(clientId, wordListMetaData));
actions.add(new ActionBatch.StartDownloadAction(clientId, wordListMetaData,
forceDownloadDict || allowDownloadOnMeteredData));
} else { } else {
Log.e(TAG, "Unexpected state of the word list for markAsUsed : " + status); Log.e(TAG, "Unexpected state of the word list for markAsUsed : " + status);
} }
@ -1149,8 +1121,7 @@ public final class UpdateHandler {
} }
final ActionBatch actions = new ActionBatch(); final ActionBatch actions = new ActionBatch();
actions.add(new ActionBatch.StartDownloadAction( actions.add(new ActionBatch.StartDownloadAction(clientId, wordListMetaData));
clientId, wordListMetaData, CommonPreferences.isForceDownloadDict(context)));
actions.execute(context, new LogProblemReporter(TAG)); actions.execute(context, new LogProblemReporter(TAG));
} else { } else {
if (DEBUG) { if (DEBUG) {