From 0a77c62a82503b38c484e0079648f0231dd85d53 Mon Sep 17 00:00:00 2001 From: Steve Howard Date: Wed, 21 Jul 2010 11:41:30 -0700 Subject: Public API support for broadcasts and connectivity control. * Three new DB fields, one indicating whether a download was initiated by the public API or not, two to hold connectivity control info. DB migration to add these fields and code in DownloadProvider.insert() to handle them. * Change broadcast intent code to match public API spec, for public API downloads only. (Legacy code can go away once existing clients are converted over to the new API.) * Introduce SystemFacade methods for sending broadcasts and checking package ownership; this facilitates new tests of broadcast code. * Change DownloadInfo.canUseNetwork() to obey new connectivity controls available in public API, but again, retain legacy behavior for downloads initiated directly through DownloadProvider * New test cases to cover the new behavior Also made a couple changes to reduce some test flakiness I was observing: * in tearDown(), wait for any running UpdateThread to complete * in PublicApiFunctionalTest.setUp(), if the test directory already exists, remove it rather than aborting DB changes for broadcast + roaming support Change-Id: I60f39fc133f678f3510880ea6eb9f639358914b4 --- .../AbstractDownloadManagerFunctionalTest.java | 14 ++++ .../providers/downloads/FakeSystemFacade.java | 16 +++++ .../downloads/PublicApiFunctionalTest.java | 84 ++++++++++++++++++++-- 3 files changed, 110 insertions(+), 4 deletions(-) (limited to 'tests/src') diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java index 92678fe3..7af98c17 100644 --- a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java @@ -148,10 +148,24 @@ public abstract class AbstractDownloadManagerFunctionalTest extends @Override protected void tearDown() throws Exception { + waitForUpdateThread(); cleanUpDownloads(); super.tearDown(); } + private void waitForUpdateThread() throws InterruptedException { + DownloadService service = getService(); + if (service == null) { + return; + } + + long startTimeMillis = System.currentTimeMillis(); + while (service.mUpdateThread != null + && System.currentTimeMillis() < startTimeMillis + 1000) { + Thread.sleep(50); + } + } + private boolean isDatabaseEmpty() { Cursor cursor = mResolver.query(Downloads.CONTENT_URI, null, null, null, null); try { diff --git a/tests/src/com/android/providers/downloads/FakeSystemFacade.java b/tests/src/com/android/providers/downloads/FakeSystemFacade.java index 4ff313ab..0f8a9801 100644 --- a/tests/src/com/android/providers/downloads/FakeSystemFacade.java +++ b/tests/src/com/android/providers/downloads/FakeSystemFacade.java @@ -1,12 +1,18 @@ package com.android.providers.downloads; +import android.content.Intent; +import android.content.pm.PackageManager.NameNotFoundException; import android.net.ConnectivityManager; +import java.util.ArrayList; +import java.util.List; + public class FakeSystemFacade implements SystemFacade { long mTimeMillis = 0; Integer mActiveNetworkType = ConnectivityManager.TYPE_WIFI; boolean mIsRoaming = false; Integer mMaxBytesOverMobile = null; + List mBroadcastsSent = new ArrayList(); void incrementTimeMillis(long delta) { mTimeMillis += delta; @@ -27,4 +33,14 @@ public class FakeSystemFacade implements SystemFacade { public Integer getMaxBytesOverMobile() { return mMaxBytesOverMobile ; } + + @Override + public void sendBroadcast(Intent intent) { + mBroadcastsSent.add(intent); + } + + @Override + public boolean userOwnsPackage(int uid, String pckg) throws NameNotFoundException { + return true; + } } diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java index b1ccc7ae..7982ef4a 100644 --- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java @@ -16,12 +16,14 @@ package com.android.providers.downloads; +import android.content.Intent; import android.database.Cursor; import android.net.ConnectivityManager; import android.net.DownloadManager; import android.net.Uri; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.provider.Downloads; import android.test.suitebuilder.annotation.LargeTest; import tests.http.MockResponse; import tests.http.RecordedRequest; @@ -34,6 +36,7 @@ import java.util.List; @LargeTest public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTest { + private static final String PACKAGE_NAME = "my.package.name"; private static final int HTTP_NOT_ACCEPTABLE = 406; private static final int HTTP_LENGTH_REQUIRED = 411; private static final String REQUEST_PATH = "/path"; @@ -102,13 +105,12 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe @Override protected void setUp() throws Exception { super.setUp(); - mManager = new DownloadManager(mResolver); + mManager = new DownloadManager(mResolver, PACKAGE_NAME); mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "download_manager_functional_test"); if (mTestDirectory.exists()) { - throw new RuntimeException( - "Test directory on external storage already exists, cannot run"); + mTestDirectory.delete(); } if (!mTestDirectory.mkdir()) { throw new RuntimeException("Couldn't create test directory: " @@ -328,7 +330,7 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe enqueueResponse(HTTP_OK, FILE_CONTENT); download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); } - + /** * Test for race conditions when the service is flooded with startService() calls while running * a download. @@ -394,6 +396,80 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS); startService(null); Thread.sleep(500); // TODO: eliminate this when we can run the service synchronously + // if the cancel didn't work, we should get an unexpected request to the HTTP server + } + + public void testDownloadCompleteBroadcast() throws Exception { + enqueueEmptyResponse(HTTP_OK); + Download download = enqueueRequest(getRequest()); + download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); + + long startTimeMillis = System.currentTimeMillis(); + while (mSystemFacade.mBroadcastsSent.isEmpty()) { + Thread.sleep(100); + if (System.currentTimeMillis() > startTimeMillis + 500) { + fail("Timed out waiting for broadcast intent"); + } + } + assertEquals(1, mSystemFacade.mBroadcastsSent.size()); + Intent broadcast = mSystemFacade.mBroadcastsSent.get(0); + assertEquals(DownloadManager.ACTION_DOWNLOAD_COMPLETE, broadcast.getAction()); + assertEquals(PACKAGE_NAME, broadcast.getPackage()); + long intentId = broadcast.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID); + assertEquals(download.mId, intentId); + } + + public void testNotificationClickedBroadcast() throws Exception { + Download download = enqueueRequest(getRequest().setShowNotification( + DownloadManager.Request.NOTIFICATION_WHEN_RUNNING)); + + DownloadReceiver receiver = new DownloadReceiver(); + receiver.mSystemFacade = mSystemFacade; + Intent intent = new Intent(Constants.ACTION_LIST); + intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + download.mId)); + receiver.onReceive(mContext, intent); + + assertEquals(1, mSystemFacade.mBroadcastsSent.size()); + Intent broadcast = mSystemFacade.mBroadcastsSent.get(0); + assertEquals(DownloadManager.ACTION_NOTIFICATION_CLICKED, broadcast.getAction()); + assertEquals(PACKAGE_NAME, broadcast.getPackage()); + } + + public void testAllowedNetworkTypes() throws Exception { + mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE; + + // by default, use any connection + enqueueEmptyResponse(HTTP_OK); + Download download = enqueueRequest(getRequest()); + download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); + + // restrict a download to wifi... + download = enqueueRequest(getRequest() + .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)); + startService(null); + waitForDownloadToStop(download, DownloadManager.STATUS_PAUSED); + // ...then enable wifi + mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI; + enqueueEmptyResponse(HTTP_OK); + download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); + } + + public void testRoaming() throws Exception { + mSystemFacade.mIsRoaming = true; + + // by default, allow roaming + enqueueEmptyResponse(HTTP_OK); + Download download = enqueueRequest(getRequest()); + download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); + + // disallow roaming for a download... + download = enqueueRequest(getRequest().setAllowedOverRoaming(false)); + startService(null); + waitForDownloadToStop(download, DownloadManager.STATUS_PAUSED); + // ...then turn off roaming + mSystemFacade.mIsRoaming = false; + enqueueEmptyResponse(HTTP_OK); + download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); } private void runSimpleFailureTest(int expectedErrorCode) throws Exception { -- cgit v1.2.3