diff options
11 files changed, 145 insertions, 228 deletions
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java index 186b01f1..4007e761 100644 --- a/src/com/android/providers/downloads/DownloadProvider.java +++ b/src/com/android/providers/downloads/DownloadProvider.java @@ -247,7 +247,7 @@ public final class DownloadProvider extends ContentProvider { @Override public boolean onCreate() { if (mSystemFacade == null) { - mSystemFacade = new RealSystemFacade(); + mSystemFacade = new RealSystemFacade(getContext()); } mOpenHelper = new DatabaseHelper(getContext()); diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java index e8f10e7d..0b4a12da 100644 --- a/src/com/android/providers/downloads/DownloadReceiver.java +++ b/src/com/android/providers/downloads/DownloadReceiver.java @@ -38,7 +38,13 @@ import java.io.File; */ public class DownloadReceiver extends BroadcastReceiver { + SystemFacade mSystemFacade = null; + public void onReceive(Context context, Intent intent) { + if (mSystemFacade == null) { + mSystemFacade = new RealSystemFacade(context); + } + if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { if (Constants.LOGVV) { Log.v(Constants.TAG, "Receiver onBoot"); @@ -52,7 +58,7 @@ public class DownloadReceiver extends BroadcastReceiver { intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); if (info != null && info.isConnected()) { if (Constants.LOGX) { - if (Helpers.isNetworkAvailable(context)) { + if (Helpers.isNetworkAvailable(mSystemFacade)) { Log.i(Constants.TAG, "Broadcast: Network Up"); } else { Log.i(Constants.TAG, "Broadcast: Network Up, Actually Down"); @@ -61,7 +67,7 @@ public class DownloadReceiver extends BroadcastReceiver { context.startService(new Intent(context, DownloadService.class)); } else { if (Constants.LOGX) { - if (Helpers.isNetworkAvailable(context)) { + if (Helpers.isNetworkAvailable(mSystemFacade)) { Log.i(Constants.TAG, "Broadcast: Network Down, Actually Up"); } else { Log.i(Constants.TAG, "Broadcast: Network Down"); diff --git a/src/com/android/providers/downloads/DownloadService.java b/src/com/android/providers/downloads/DownloadService.java index 2e713fbf..b5cb2d45 100644 --- a/src/com/android/providers/downloads/DownloadService.java +++ b/src/com/android/providers/downloads/DownloadService.java @@ -16,9 +16,6 @@ package com.android.providers.downloads; -import com.google.android.collect.Lists; -import com.google.common.annotations.VisibleForTesting; - import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; @@ -45,11 +42,13 @@ import android.provider.Downloads; import android.util.Config; import android.util.Log; +import com.google.android.collect.Lists; +import com.google.common.annotations.VisibleForTesting; + import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; -import java.util.List; /** @@ -205,7 +204,7 @@ public class DownloadService extends Service { } if (mSystemFacade == null) { - mSystemFacade = new RealSystemFacade(); + mSystemFacade = new RealSystemFacade(this); } mDownloads = Lists.newArrayList(); @@ -311,8 +310,8 @@ public class DownloadService extends Service { } mPendingUpdate = false; } - boolean networkAvailable = Helpers.isNetworkAvailable(DownloadService.this); - boolean networkRoaming = Helpers.isNetworkRoaming(DownloadService.this); + boolean networkAvailable = Helpers.isNetworkAvailable(mSystemFacade); + boolean networkRoaming = Helpers.isNetworkRoaming(mSystemFacade); long now = mSystemFacade.currentTimeMillis(); Cursor cursor = getContentResolver().query(Downloads.Impl.CONTENT_URI, diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java index 8188eaae..e7763e4e 100644 --- a/src/com/android/providers/downloads/DownloadThread.java +++ b/src/com/android/providers/downloads/DownloadThread.java @@ -211,13 +211,13 @@ http_request_loop: break http_request_loop; } catch (IOException ex) { if (Constants.LOGX) { - if (Helpers.isNetworkAvailable(mContext)) { + if (Helpers.isNetworkAvailable(mSystemFacade)) { Log.i(Constants.TAG, "Execute Failed " + mInfo.mId + ", Net Up"); } else { Log.i(Constants.TAG, "Execute Failed " + mInfo.mId + ", Net Down"); } } - if (!Helpers.isNetworkAvailable(mContext)) { + if (!Helpers.isNetworkAvailable(mSystemFacade)) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; @@ -446,13 +446,13 @@ http_request_loop: entityStream = response.getEntity().getContent(); } catch (IOException ex) { if (Constants.LOGX) { - if (Helpers.isNetworkAvailable(mContext)) { + if (Helpers.isNetworkAvailable(mSystemFacade)) { Log.i(Constants.TAG, "Get Failed " + mInfo.mId + ", Net Up"); } else { Log.i(Constants.TAG, "Get Failed " + mInfo.mId + ", Net Down"); } } - if (!Helpers.isNetworkAvailable(mContext)) { + if (!Helpers.isNetworkAvailable(mSystemFacade)) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; @@ -479,7 +479,7 @@ http_request_loop: bytesRead = entityStream.read(data); } catch (IOException ex) { if (Constants.LOGX) { - if (Helpers.isNetworkAvailable(mContext)) { + if (Helpers.isNetworkAvailable(mSystemFacade)) { Log.i(Constants.TAG, "Read Failed " + mInfo.mId + ", Net Up"); } else { Log.i(Constants.TAG, "Read Failed " + mInfo.mId + ", Net Down"); @@ -501,7 +501,7 @@ http_request_loop: "can't resume interrupted download with no ETag"); } finalStatus = Downloads.Impl.STATUS_PRECONDITION_FAILED; - } else if (!Helpers.isNetworkAvailable(mContext)) { + } else if (!Helpers.isNetworkAvailable(mSystemFacade)) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; @@ -538,7 +538,7 @@ http_request_loop: mInfo.mId); } finalStatus = Downloads.Impl.STATUS_LENGTH_REQUIRED; - } else if (!Helpers.isNetworkAvailable(mContext)) { + } else if (!Helpers.isNetworkAvailable(mSystemFacade)) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; diff --git a/src/com/android/providers/downloads/Helpers.java b/src/com/android/providers/downloads/Helpers.java index 2705a7cb..4a0f860b 100644 --- a/src/com/android/providers/downloads/Helpers.java +++ b/src/com/android/providers/downloads/Helpers.java @@ -514,58 +514,15 @@ public class Helpers { /** * Returns whether the network is available */ - public static boolean isNetworkAvailable(Context context) { - ConnectivityManager connectivity = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivity == null) { - Log.w(Constants.TAG, "couldn't get connectivity manager"); - } else { - NetworkInfo[] info = connectivity.getAllNetworkInfo(); - if (info != null) { - for (int i = 0; i < info.length; i++) { - if (info[i].getState() == NetworkInfo.State.CONNECTED) { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is available"); - } - return true; - } - } - } - } - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is not available"); - } - return false; + public static boolean isNetworkAvailable(SystemFacade system) { + return !system.getConnectedNetworkTypes().isEmpty(); } /** * Returns whether the network is roaming */ - public static boolean isNetworkRoaming(Context context) { - ConnectivityManager connectivity = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivity == null) { - Log.w(Constants.TAG, "couldn't get connectivity manager"); - } else { - NetworkInfo info = connectivity.getActiveNetworkInfo(); - if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE) { - if (TelephonyManager.getDefault().isNetworkRoaming()) { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is roaming"); - } - return true; - } else { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is not roaming"); - } - } - } else { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "not using mobile network"); - } - } - } - return false; + public static boolean isNetworkRoaming(SystemFacade system) { + return system.isNetworkRoaming(); } /** diff --git a/src/com/android/providers/downloads/RealSystemFacade.java b/src/com/android/providers/downloads/RealSystemFacade.java index 88f10d8c..41ca6b6e 100644 --- a/src/com/android/providers/downloads/RealSystemFacade.java +++ b/src/com/android/providers/downloads/RealSystemFacade.java @@ -1,7 +1,65 @@ package com.android.providers.downloads; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.telephony.TelephonyManager; +import android.util.Log; + +import java.util.BitSet; + class RealSystemFacade implements SystemFacade { + private Context mContext; + + public RealSystemFacade(Context context) { + mContext = context; + } + public long currentTimeMillis() { return System.currentTimeMillis(); } + + public BitSet getConnectedNetworkTypes() { + BitSet connectedTypes = new BitSet(); + + ConnectivityManager connectivity = + (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity == null) { + Log.w(Constants.TAG, "couldn't get connectivity manager"); + return connectedTypes; + } + + NetworkInfo[] infos = connectivity.getAllNetworkInfo(); + if (infos != null) { + for (NetworkInfo info : infos) { + if (info.getState() == NetworkInfo.State.CONNECTED) { + connectedTypes.set(info.getType()); + } + } + } + + if (Constants.LOGVV) { + boolean isConnected = !connectedTypes.isEmpty(); + Log.v(Constants.TAG, "network is " + (isConnected ? "" : "not ") + "available"); + } + return connectedTypes; + } + + public boolean isNetworkRoaming() { + ConnectivityManager connectivity = + (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity == null) { + Log.w(Constants.TAG, "couldn't get connectivity manager"); + return false; + } + + NetworkInfo info = connectivity.getActiveNetworkInfo(); + boolean isMobile = (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE); + boolean isRoaming = isMobile && TelephonyManager.getDefault().isNetworkRoaming(); + if (Constants.LOGVV) { + Log.v(Constants.TAG, "network is mobile: " + isMobile); + Log.v(Constants.TAG, "network is roaming: " + isRoaming); + } + return isMobile && isRoaming; + } } diff --git a/src/com/android/providers/downloads/SystemFacade.java b/src/com/android/providers/downloads/SystemFacade.java index 4498877d..e16e6a06 100644 --- a/src/com/android/providers/downloads/SystemFacade.java +++ b/src/com/android/providers/downloads/SystemFacade.java @@ -1,6 +1,21 @@ package com.android.providers.downloads; +import java.util.BitSet; + interface SystemFacade { + /** + * @see System#currentTimeMillis() + */ public long currentTimeMillis(); + + /** + * @return Network types (as in ConnectivityManager.TYPE_*) of all connected networks. + */ + public BitSet getConnectedNetworkTypes(); + + /** + * @see android.telephony.TelephonyManager#isNetworkRoaming + */ + public boolean isNetworkRoaming(); } diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java index 06dd52af..326d9fff 100644 --- a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java @@ -21,7 +21,6 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; -import android.net.ConnectivityManager; import android.provider.Downloads; import android.test.MoreAsserts; import android.test.RenamingDelegatingContext; @@ -77,7 +76,6 @@ public abstract class AbstractDownloadManagerFunctionalTest extends private ContentResolver mResolver; boolean mHasServiceBeenStarted = false; - FakeIConnectivityManager mFakeIConnectivityManager; public TestContext(Context realContext) { super(realContext, FILENAME_PREFIX); @@ -86,7 +84,6 @@ public abstract class AbstractDownloadManagerFunctionalTest extends Context.NOTIFICATION_SERVICE, Context.POWER_SERVICE, })); - mFakeIConnectivityManager = new FakeIConnectivityManager(); } public void setResolver(ContentResolver resolver) { @@ -107,9 +104,6 @@ public abstract class AbstractDownloadManagerFunctionalTest extends */ @Override public Object getSystemService(String name) { - if (name.equals(Context.CONNECTIVITY_SERVICE)) { - return new ConnectivityManager(mFakeIConnectivityManager); - } if (mAllowedSystemServices.contains(name)) { return mRealContext.getSystemService(name); } diff --git a/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java index 7de90de5..3cd9cf58 100644 --- a/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java @@ -18,7 +18,7 @@ package com.android.providers.downloads; import android.content.ContentValues; import android.database.Cursor; -import android.net.NetworkInfo; +import android.net.ConnectivityManager; import android.net.Uri; import android.os.Environment; import android.provider.Downloads; @@ -102,12 +102,35 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti Uri downloadUri = requestDownload("/path"); // without connectivity, download immediately pauses - mTestContext.mFakeIConnectivityManager.setNetworkState(NetworkInfo.State.DISCONNECTED); + mSystemFacade.mActiveNetworkType = null; startService(null); - super.waitForDownloadToStop(getStatusReader(downloadUri), Downloads.STATUS_RUNNING_PAUSED); + waitForDownloadToStop(getStatusReader(downloadUri), Downloads.STATUS_RUNNING_PAUSED); // connecting should start the download - mTestContext.mFakeIConnectivityManager.setNetworkState(NetworkInfo.State.CONNECTED); + mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI; + runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS); + } + + public void testRoaming() throws Exception { + mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE; + mSystemFacade.mIsRoaming = true; + + // for a normal download, roaming is fine + enqueueResponse(HTTP_OK, FILE_CONTENT); + Uri downloadUri = requestDownload("/path"); + startService(null); + runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS); + + // when roaming is disallowed, the download should pause... + downloadUri = requestDownload("/path"); + updateDownload(downloadUri, Downloads.COLUMN_DESTINATION, + Integer.toString(Downloads.DESTINATION_CACHE_PARTITION_NOROAMING)); + startService(null); + waitForDownloadToStop(getStatusReader(downloadUri), Downloads.STATUS_RUNNING_PAUSED); + + // ...and pick up when we're off roaming + enqueueResponse(HTTP_OK, FILE_CONTENT); + mSystemFacade.mIsRoaming = false; runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS); } diff --git a/tests/src/com/android/providers/downloads/FakeIConnectivityManager.java b/tests/src/com/android/providers/downloads/FakeIConnectivityManager.java deleted file mode 100644 index 424411f8..00000000 --- a/tests/src/com/android/providers/downloads/FakeIConnectivityManager.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2010 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.providers.downloads; - -import android.net.ConnectivityManager; -import android.net.IConnectivityManager; -import android.net.NetworkInfo; -import android.net.NetworkInfo.State; -import android.os.IBinder; -import android.os.RemoteException; - -class FakeIConnectivityManager implements IConnectivityManager { - private static class MockNetworkInfo extends NetworkInfo { - private State mState; - - @SuppressWarnings("deprecation") - public MockNetworkInfo(State state) { - super(0); - mState = state; - } - - @Override - public State getState() { - return mState; - } - - @Override - public int getType() { - return ConnectivityManager.TYPE_MOBILE; - } - } - - private State mCurrentState = State.CONNECTED; - - public void setNetworkState(State state) { - mCurrentState = state; - } - - public IBinder asBinder() { - throw new UnsupportedOperationException(); - } - - public NetworkInfo getActiveNetworkInfo() throws RemoteException { - return new MockNetworkInfo(mCurrentState); - } - - public NetworkInfo[] getAllNetworkInfo() throws RemoteException { - return new NetworkInfo[] {getActiveNetworkInfo()}; - } - - public boolean getBackgroundDataSetting() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public int getLastTetherError(String iface) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public boolean getMobileDataEnabled() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public NetworkInfo getNetworkInfo(int networkType) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public int getNetworkPreference() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public String[] getTetherableIfaces() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public String[] getTetherableUsbRegexs() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public String[] getTetherableWifiRegexs() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public String[] getTetheredIfaces() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public String[] getTetheringErroredIfaces() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public boolean isTetheringSupported() throws RemoteException { - throw new UnsupportedOperationException(); - } - - public void requestNetworkTransitionWakelock(String forWhom) { - throw new UnsupportedOperationException(); - } - - public boolean requestRouteToHost(int networkType, int hostAddress) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public void setBackgroundDataSetting(boolean allowBackgroundData) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public void setMobileDataEnabled(boolean enabled) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public void setNetworkPreference(int pref) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public boolean setRadio(int networkType, boolean turnOn) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public boolean setRadios(boolean onOff) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public int startUsingNetworkFeature(int networkType, String feature, IBinder binder) - throws RemoteException { - throw new UnsupportedOperationException(); - } - - public int stopUsingNetworkFeature(int networkType, String feature) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public int tether(String iface) throws RemoteException { - throw new UnsupportedOperationException(); - } - - public int untether(String iface) throws RemoteException { - throw new UnsupportedOperationException(); - } -} diff --git a/tests/src/com/android/providers/downloads/FakeSystemFacade.java b/tests/src/com/android/providers/downloads/FakeSystemFacade.java index b75e663a..c48f815d 100644 --- a/tests/src/com/android/providers/downloads/FakeSystemFacade.java +++ b/tests/src/com/android/providers/downloads/FakeSystemFacade.java @@ -1,7 +1,13 @@ package com.android.providers.downloads; +import android.net.ConnectivityManager; + +import java.util.BitSet; + public class FakeSystemFacade implements SystemFacade { - private long mTimeMillis = 0; + long mTimeMillis = 0; + Integer mActiveNetworkType = ConnectivityManager.TYPE_WIFI; + boolean mIsRoaming = false; void incrementTimeMillis(long delta) { mTimeMillis += delta; @@ -10,4 +16,16 @@ public class FakeSystemFacade implements SystemFacade { public long currentTimeMillis() { return mTimeMillis; } + + public BitSet getConnectedNetworkTypes() { + BitSet connectedTypes = new BitSet(); + if (mActiveNetworkType != null) { + connectedTypes.set(mActiveNetworkType); + } + return connectedTypes; + } + + public boolean isNetworkRoaming() { + return mIsRoaming; + } } |