summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/DownloadThread.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers/downloads/DownloadThread.java')
-rw-r--r--src/com/android/providers/downloads/DownloadThread.java86
1 files changed, 67 insertions, 19 deletions
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index 7ddfe959..75d4ca32 100644
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -16,14 +16,15 @@
package com.android.providers.downloads;
-import org.apache.http.conn.params.ConnRouteParams;
+import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import android.content.ContentValues;
import android.content.Context;
-import android.content.Intent;
-import android.net.http.AndroidHttpClient;
+import android.net.INetworkPolicyListener;
+import android.net.NetworkPolicyManager;
import android.net.Proxy;
import android.net.TrafficStats;
+import android.net.http.AndroidHttpClient;
import android.os.FileUtils;
import android.os.PowerManager;
import android.os.Process;
@@ -35,6 +36,7 @@ import android.util.Pair;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.params.ConnRouteParams;
import java.io.File;
import java.io.FileNotFoundException;
@@ -57,6 +59,8 @@ public class DownloadThread extends Thread {
private final StorageManager mStorageManager;
private DrmConvertSession mDrmConvertSession;
+ private volatile boolean mPolicyDirty;
+
public DownloadThread(Context context, SystemFacade systemFacade, DownloadInfo info,
StorageManager storageManager) {
mContext = context;
@@ -133,11 +137,16 @@ public class DownloadThread extends Thread {
int finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;
String errorMsg = null;
+ final NetworkPolicyManager netPolicy = NetworkPolicyManager.getSystemService(mContext);
+ final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
try {
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG);
wakeLock.acquire();
+ // while performing download, register for rules updates
+ netPolicy.registerListener(mPolicyListener);
+
if (Constants.LOGV) {
Log.v(Constants.TAG, "initiating download for " + mInfo.mUri);
}
@@ -203,6 +212,8 @@ public class DownloadThread extends Thread {
state.mNewUri, state.mMimeType, errorMsg);
DownloadHandler.getInstance().dequeueDownload(mInfo.mId);
+ netPolicy.unregisterListener(mPolicyListener);
+
if (wakeLock != null) {
wakeLock.release();
wakeLock = null;
@@ -242,6 +253,9 @@ public class DownloadThread extends Thread {
* Check if current connectivity is valid for this request.
*/
private void checkConnectivity() throws StopRequestException {
+ // checking connectivity will apply current policy
+ mPolicyDirty = false;
+
int networkUsable = mInfo.checkCanUseNetwork();
if (networkUsable != DownloadInfo.NETWORK_OK) {
int status = Downloads.Impl.STATUS_WAITING_FOR_NETWORK;
@@ -251,6 +265,8 @@ public class DownloadThread extends Thread {
} else if (networkUsable == DownloadInfo.NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE) {
status = Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
mInfo.notifyPauseDueToSize(false);
+ } else if (networkUsable == DownloadInfo.NETWORK_BLOCKED) {
+ status = Downloads.Impl.STATUS_BLOCKED;
}
throw new StopRequestException(status,
mInfo.getLogMessageForNetworkError(networkUsable));
@@ -262,8 +278,9 @@ public class DownloadThread extends Thread {
* @param data buffer to use to read data
* @param entityStream stream for reading the HTTP response entity
*/
- private void transferData(State state, InnerState innerState, byte[] data,
- InputStream entityStream) throws StopRequestException {
+ private void transferData(
+ State state, InnerState innerState, byte[] data, InputStream entityStream)
+ throws StopRequestException {
for (;;) {
int bytesRead = readFromResponse(state, innerState, data, entityStream);
if (bytesRead == -1) { // success, end of stream already reached
@@ -364,12 +381,17 @@ public class DownloadThread extends Thread {
private void checkPausedOrCanceled(State state) throws StopRequestException {
synchronized (mInfo) {
if (mInfo.mControl == Downloads.Impl.CONTROL_PAUSED) {
- throw new StopRequestException(Downloads.Impl.STATUS_PAUSED_BY_APP,
- "download paused by owner");
+ throw new StopRequestException(
+ Downloads.Impl.STATUS_PAUSED_BY_APP, "download paused by owner");
+ }
+ if (mInfo.mStatus == Downloads.Impl.STATUS_CANCELED) {
+ throw new StopRequestException(Downloads.Impl.STATUS_CANCELED, "download canceled");
}
}
- if (mInfo.mStatus == Downloads.Impl.STATUS_CANCELED) {
- throw new StopRequestException(Downloads.Impl.STATUS_CANCELED, "download canceled");
+
+ // if policy has been changed, trigger connectivity check
+ if (mPolicyDirty) {
+ checkConnectivity();
}
}
@@ -471,7 +493,7 @@ public class DownloadThread extends Thread {
try {
return entityStream.read(data);
} catch (IOException ex) {
- logNetworkState();
+ logNetworkState(mInfo.mUid);
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, innerState.mBytesSoFar);
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);
@@ -496,16 +518,16 @@ public class DownloadThread extends Thread {
try {
return response.getEntity().getContent();
} catch (IOException ex) {
- logNetworkState();
+ logNetworkState(mInfo.mUid);
throw new StopRequestException(getFinalStatusForHttpError(state),
"while getting entity: " + ex.toString(), ex);
}
}
- private void logNetworkState() {
+ private void logNetworkState(int uid) {
if (Constants.LOGX) {
Log.i(Constants.TAG,
- "Net " + (Helpers.isNetworkAvailable(mSystemFacade) ? "Up" : "Down"));
+ "Net " + (Helpers.isNetworkAvailable(mSystemFacade, uid) ? "Up" : "Down"));
}
}
@@ -766,7 +788,7 @@ public class DownloadThread extends Thread {
throw new StopRequestException(Downloads.Impl.STATUS_HTTP_DATA_ERROR,
"while trying to execute request: " + ex.toString(), ex);
} catch (IOException ex) {
- logNetworkState();
+ logNetworkState(mInfo.mUid);
throw new StopRequestException(getFinalStatusForHttpError(state),
"while trying to execute request: " + ex.toString(), ex);
}
@@ -775,10 +797,15 @@ public class DownloadThread extends Thread {
private int getFinalStatusForHttpError(State state) {
int networkUsable = mInfo.checkCanUseNetwork();
if (networkUsable != DownloadInfo.NETWORK_OK) {
- return (networkUsable == DownloadInfo.NETWORK_UNUSABLE_DUE_TO_SIZE ||
- networkUsable == DownloadInfo.NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE)
- ? Downloads.Impl.STATUS_QUEUED_FOR_WIFI
- : Downloads.Impl.STATUS_WAITING_FOR_NETWORK;
+ switch (networkUsable) {
+ case DownloadInfo.NETWORK_UNUSABLE_DUE_TO_SIZE:
+ case DownloadInfo.NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE:
+ return Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
+ case DownloadInfo.NETWORK_BLOCKED:
+ return Downloads.Impl.STATUS_BLOCKED;
+ default:
+ return Downloads.Impl.STATUS_WAITING_FOR_NETWORK;
+ }
} else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
state.mCountRetry = true;
return Downloads.Impl.STATUS_WAITING_TO_RETRY;
@@ -938,4 +965,25 @@ public class DownloadThread extends Thread {
return null;
}
}
+
+ private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+ @Override
+ public void onUidRulesChanged(int uid, int uidRules) {
+ // only someone like NPMS should only be calling us
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, Constants.TAG);
+
+ if (uid == mInfo.mUid) {
+ mPolicyDirty = true;
+ }
+ }
+
+ @Override
+ public void onMeteredIfacesChanged(String[] meteredIfaces) {
+ // only someone like NPMS should only be calling us
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, Constants.TAG);
+
+ mPolicyDirty = true;
+ }
+ };
+
}