1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.app.cts; 17 18 import static com.android.compatibility.common.util.SystemUtil.runShellCommand; 19 20 import static com.google.common.truth.Truth.assertThat; 21 22 import static org.junit.Assert.assertArrayEquals; 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertTrue; 25 26 import android.app.DownloadManager; 27 import android.content.ContentResolver; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.database.Cursor; 31 import android.net.Uri; 32 import android.os.Environment; 33 import android.os.FileUtils; 34 35 import androidx.test.runner.AndroidJUnit4; 36 37 import org.junit.Assert; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import java.io.File; 42 import java.io.FileInputStream; 43 import java.io.FileOutputStream; 44 import java.io.InputStream; 45 import java.io.OutputStream; 46 47 @RunWith(AndroidJUnit4.class) 48 public class DownloadManagerApi28Test extends DownloadManagerTestBase { 49 50 @Test testSetDestinationUri_publicDir()51 public void testSetDestinationUri_publicDir() throws Exception { 52 File publicLocation = new File( 53 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), 54 "publicFile.bin"); 55 deleteFromShell(publicLocation); 56 57 final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(); 58 try { 59 IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 60 mContext.registerReceiver(receiver, intentFilter); 61 62 DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl()); 63 requestPublic.setDestinationUri(Uri.fromFile(publicLocation)); 64 long id = mDownloadManager.enqueue(requestPublic); 65 66 int allDownloads = getTotalNumberDownloads(); 67 assertEquals(1, allDownloads); 68 69 receiver.waitForDownloadComplete(SHORT_TIMEOUT, id); 70 assertSuccessfulDownload(id, publicLocation); 71 72 assertRemoveDownload(id, 0); 73 } finally { 74 mContext.unregisterReceiver(receiver); 75 } 76 } 77 78 @Test testSetDestinationUri_sdcardPath()79 public void testSetDestinationUri_sdcardPath() throws Exception { 80 final File path = new File("/sdcard/publicFile.bin"); 81 deleteFromShell(path); 82 83 final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(); 84 try { 85 IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 86 mContext.registerReceiver(receiver, intentFilter); 87 88 DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl()); 89 requestPublic.setDestinationUri(Uri.fromFile(path)); 90 long id = mDownloadManager.enqueue(requestPublic); 91 92 int allDownloads = getTotalNumberDownloads(); 93 assertEquals(1, allDownloads); 94 95 receiver.waitForDownloadComplete(SHORT_TIMEOUT, id); 96 assertSuccessfulDownload(id, path); 97 98 assertRemoveDownload(id, 0); 99 } finally { 100 mContext.unregisterReceiver(receiver); 101 } 102 } 103 104 @Test testSetDestinationUri_privateAppDir()105 public void testSetDestinationUri_privateAppDir() throws Exception { 106 // Make sure the private app directory exists 107 runShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770"); 108 final File path = new File("/sdcard/Android/data/com.android.shell/" 109 + TAG + System.currentTimeMillis()); 110 111 final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(); 112 try { 113 IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 114 mContext.registerReceiver(receiver, intentFilter); 115 116 DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl()); 117 requestPublic.setDestinationUri(Uri.fromFile(path)); 118 mDownloadManager.enqueue(requestPublic); 119 Assert.fail("Cannot download files into other app's private directories"); 120 } catch (SecurityException expected) { 121 } finally { 122 mContext.unregisterReceiver(receiver); 123 } 124 } 125 126 @Test testDestinationInExternalPublicDir()127 public void testDestinationInExternalPublicDir() throws Exception { 128 File publicLocation = new File( 129 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), 130 "publicFile.bin"); 131 deleteFromShell(publicLocation); 132 133 final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(); 134 try { 135 IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 136 mContext.registerReceiver(receiver, intentFilter); 137 138 DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl()); 139 requestPublic.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOCUMENTS, 140 "publicFile.bin"); 141 long id = mDownloadManager.enqueue(requestPublic); 142 143 int allDownloads = getTotalNumberDownloads(); 144 assertEquals(1, allDownloads); 145 146 receiver.waitForDownloadComplete(SHORT_TIMEOUT, id); 147 assertSuccessfulDownload(id, publicLocation); 148 149 assertRemoveDownload(id, 0); 150 } finally { 151 mContext.unregisterReceiver(receiver); 152 } 153 } 154 155 @Test testAddCompletedDownload_publicDirs()156 public void testAddCompletedDownload_publicDirs() throws Exception { 157 final String[] filePaths = new String[] { 158 createFile(Environment.getExternalStoragePublicDirectory( 159 Environment.DIRECTORY_DOWNLOADS), "file1.txt").getPath(), 160 createFile(Environment.getExternalStoragePublicDirectory( 161 Environment.DIRECTORY_DOCUMENTS), "file2.txt").getPath(), 162 "/sdcard/Download/file3.txt", 163 }; 164 165 for (String path : filePaths) { 166 final String fileContents = "Test content:" + path + "_" + System.nanoTime(); 167 168 final File file = new File(path); 169 writeToFile(new File(path), fileContents); 170 171 final long id = mDownloadManager.addCompletedDownload(file.getName(), "Test desc", true, 172 "text/plain", path, fileContents.getBytes().length, true); 173 final String actualContents = readFromFile(mDownloadManager.openDownloadedFile(id)); 174 assertEquals(fileContents, actualContents); 175 176 final Uri downloadUri = mDownloadManager.getUriForDownloadedFile(id); 177 mContext.grantUriPermission("com.android.shell", downloadUri, 178 Intent.FLAG_GRANT_READ_URI_PERMISSION); 179 final String rawFilePath = getRawFilePath(downloadUri); 180 final String rawFileContents = readFromRawFile(rawFilePath); 181 assertEquals(fileContents, rawFileContents); 182 assertRemoveDownload(id, 0); 183 } 184 } 185 186 187 @Test testDownloadManager_mediaStoreEntry()188 public void testDownloadManager_mediaStoreEntry() throws Exception { 189 final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(); 190 try { 191 mContext.registerReceiver(receiver, 192 new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 193 194 final String fileName = "noiseandchirps.mp3"; 195 final DownloadManager.Request request 196 = new DownloadManager.Request(getAssetUrl(fileName)); 197 final Uri[] downloadPathUris = new Uri[] { 198 Uri.fromFile(new File(Environment.getExternalStoragePublicDirectory( 199 Environment.DIRECTORY_DOWNLOADS), "testfile1.mp3")), 200 Uri.parse("file:///sdcard/testfile2.mp3"), 201 }; 202 for (Uri downloadLocation : downloadPathUris) { 203 request.setDestinationUri(downloadLocation); 204 final long downloadId = mDownloadManager.enqueue(request); 205 receiver.waitForDownloadComplete(SHORT_TIMEOUT, downloadId); 206 assertSuccessfulDownload(downloadId, new File(downloadLocation.getPath())); 207 final Uri downloadUri = mDownloadManager.getUriForDownloadedFile(downloadId); 208 final Uri mediaStoreUri = getMediaStoreUri(downloadUri); 209 final ContentResolver contentResolver = mContext.getContentResolver(); 210 assertArrayEquals(hash(contentResolver.openInputStream(downloadUri)), 211 hash(contentResolver.openInputStream(mediaStoreUri))); 212 213 // Delete entry in DownloadProvider and verify it's deleted from MediaProvider 214 // as well. 215 assertRemoveDownload(downloadId, 0); 216 try (Cursor cursor = mContext.getContentResolver().query( 217 mediaStoreUri, null, null, null)) { 218 assertEquals(0, cursor.getCount()); 219 } 220 } 221 } finally { 222 mContext.unregisterReceiver(receiver); 223 } 224 } 225 226 /** 227 * Add a file using DownloadManager.addCompleted and verify that the file has been added 228 * to MediaStore as well. 229 */ 230 @Test testAddCompletedDownload_mediaStoreEntry()231 public void testAddCompletedDownload_mediaStoreEntry() throws Exception { 232 final String assetName = "noiseandchirps.mp3"; 233 final String[] downloadPath = new String[] { 234 new File(Environment.getExternalStoragePublicDirectory( 235 Environment.DIRECTORY_DOWNLOADS), "file1.mp3").getPath(), 236 new File(Environment.getExternalStoragePublicDirectory( 237 Environment.DIRECTORY_MUSIC), "file2.mp3").getPath(), 238 "/sdcard/file3.mp3", 239 }; 240 for (String downloadLocation : downloadPath) { 241 final File file = new File(Uri.parse(downloadLocation).getPath()); 242 final File parentDir = file.getParentFile(); 243 if (!parentDir.exists()) { 244 parentDir.mkdirs(); 245 assertThat(parentDir.exists()).isTrue(); 246 } 247 try (InputStream in = mContext.getAssets().open(assetName); 248 OutputStream out = new FileOutputStream(file)) { 249 FileUtils.copy(in, out); 250 } 251 252 final long downloadId = mDownloadManager.addCompletedDownload(file.getName(), 253 "Test desc", true, 254 "audio/mp3", downloadLocation, file.length(), true); 255 assertTrue(downloadId >= 0); 256 final Uri downloadUri = mDownloadManager.getUriForDownloadedFile(downloadId); 257 final Uri mediaStoreUri = getMediaStoreUri(downloadUri); 258 assertArrayEquals(hash(new FileInputStream(file)), 259 hash(mContext.getContentResolver().openInputStream(mediaStoreUri))); 260 261 // Delete entry in DownloadProvider and verify it's deleted from MediaProvider as well. 262 assertRemoveDownload(downloadId, 0); 263 try (Cursor cursor = mContext.getContentResolver().query( 264 mediaStoreUri, null, null, null)) { 265 assertEquals(0, cursor.getCount()); 266 } 267 } 268 } 269 } 270