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 org.junit.Assert.assertArrayEquals;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 
22 import android.app.DownloadManager;
23 import android.content.ContentResolver;
24 import android.content.Intent;
25 import android.content.IntentFilter;
26 import android.database.Cursor;
27 import android.net.Uri;
28 import android.os.Environment;
29 import android.os.FileUtils;
30 
31 import androidx.test.runner.AndroidJUnit4;
32 
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.FileOutputStream;
39 import java.io.InputStream;
40 import java.io.OutputStream;
41 
42 @RunWith(AndroidJUnit4.class)
43 public class DownloadManagerApi28Test extends DownloadManagerTestBase {
44 
45     @Test
testSetDestinationUri_publicDir()46     public void testSetDestinationUri_publicDir() throws Exception {
47         File publicLocation = new File(
48                 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
49                 "publicFile.bin");
50         deleteFromShell(publicLocation);
51 
52         final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
53         try {
54             IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
55             mContext.registerReceiver(receiver, intentFilter);
56 
57             DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
58             requestPublic.setDestinationUri(Uri.fromFile(publicLocation));
59             long id = mDownloadManager.enqueue(requestPublic);
60 
61             int allDownloads = getTotalNumberDownloads();
62             assertEquals(1, allDownloads);
63 
64             receiver.waitForDownloadComplete(SHORT_TIMEOUT, id);
65             assertSuccessfulDownload(id, publicLocation);
66 
67             assertRemoveDownload(id, 0);
68         } finally {
69             mContext.unregisterReceiver(receiver);
70         }
71     }
72 
73     @Test
testSetDestinationUri_sdcardPath()74     public void testSetDestinationUri_sdcardPath() throws Exception {
75         final File path = new File("/sdcard/publicFile.bin");
76         deleteFromShell(path);
77 
78         final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
79         try {
80             IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
81             mContext.registerReceiver(receiver, intentFilter);
82 
83             DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
84             requestPublic.setDestinationUri(Uri.fromFile(path));
85             long id = mDownloadManager.enqueue(requestPublic);
86 
87             int allDownloads = getTotalNumberDownloads();
88             assertEquals(1, allDownloads);
89 
90             receiver.waitForDownloadComplete(SHORT_TIMEOUT, id);
91             assertSuccessfulDownload(id, path);
92 
93             assertRemoveDownload(id, 0);
94         } finally {
95             mContext.unregisterReceiver(receiver);
96         }
97     }
98 
99     @Test
testDestinationInExternalPublicDir()100     public void testDestinationInExternalPublicDir() throws Exception {
101         File publicLocation = new File(
102                 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
103                 "publicFile.bin");
104         deleteFromShell(publicLocation);
105 
106         final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
107         try {
108             IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
109             mContext.registerReceiver(receiver, intentFilter);
110 
111             DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
112             requestPublic.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOCUMENTS,
113                     "publicFile.bin");
114             long id = mDownloadManager.enqueue(requestPublic);
115 
116             int allDownloads = getTotalNumberDownloads();
117             assertEquals(1, allDownloads);
118 
119             receiver.waitForDownloadComplete(SHORT_TIMEOUT, id);
120             assertSuccessfulDownload(id, publicLocation);
121 
122             assertRemoveDownload(id, 0);
123         } finally {
124             mContext.unregisterReceiver(receiver);
125         }
126     }
127 
128     @Test
testAddCompletedDownload_publicDirs()129     public void testAddCompletedDownload_publicDirs() throws Exception {
130         final String[] filePaths = new String[] {
131                 createFile(Environment.getExternalStoragePublicDirectory(
132                         Environment.DIRECTORY_DOWNLOADS), "file1.txt").getPath(),
133                 createFile(Environment.getExternalStoragePublicDirectory(
134                         Environment.DIRECTORY_DOCUMENTS), "file2.txt").getPath(),
135         };
136 
137         for (String path : filePaths) {
138             final String fileContents = "Test content:" + path + "_" + System.nanoTime();
139 
140             final File file = new File(path);
141             writeToFile(new File(path), fileContents);
142 
143             final long id = mDownloadManager.addCompletedDownload(file.getName(), "Test desc", true,
144                     "text/plain", path, fileContents.getBytes().length, true);
145             final String actualContents = readFromFile(mDownloadManager.openDownloadedFile(id));
146             assertEquals(fileContents, actualContents);
147 
148             final Uri downloadUri = mDownloadManager.getUriForDownloadedFile(id);
149             mContext.grantUriPermission("com.android.shell", downloadUri,
150                     Intent.FLAG_GRANT_READ_URI_PERMISSION);
151             final String rawFilePath = getRawFilePath(downloadUri);
152             final String rawFileContents = readFromRawFile(rawFilePath);
153             assertEquals(fileContents, rawFileContents);
154             assertRemoveDownload(id, 0);
155         }
156     }
157 
158 
159     @Test
testDownloadManager_mediaStoreEntry()160     public void testDownloadManager_mediaStoreEntry() throws Exception {
161         final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
162         try {
163             mContext.registerReceiver(receiver,
164                     new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
165 
166             final String fileName = "noiseandchirps.mp3";
167             final DownloadManager.Request request
168                     = new DownloadManager.Request(getAssetUrl(fileName));
169             final Uri[] downloadPathUris = new Uri[] {
170                     Uri.fromFile(new File(Environment.getExternalStoragePublicDirectory(
171                             Environment.DIRECTORY_DOWNLOADS), "testfile1.mp3")),
172                     Uri.parse("file:///sdcard/testfile2.mp3"),
173             };
174             for (Uri downloadLocation : downloadPathUris) {
175                 request.setDestinationUri(downloadLocation);
176                 final long downloadId = mDownloadManager.enqueue(request);
177                 receiver.waitForDownloadComplete(SHORT_TIMEOUT, downloadId);
178                 assertSuccessfulDownload(downloadId, new File(downloadLocation.getPath()));
179                 final Uri downloadUri = mDownloadManager.getUriForDownloadedFile(downloadId);
180                 final Uri mediaStoreUri = getMediaStoreUri(downloadUri);
181                 final ContentResolver contentResolver = mContext.getContentResolver();
182                 assertArrayEquals(hash(contentResolver.openInputStream(downloadUri)),
183                         hash(contentResolver.openInputStream(mediaStoreUri)));
184 
185                 // Delete entry in DownloadProvider and verify it's deleted from MediaProvider
186                 // as well.
187                 assertRemoveDownload(downloadId, 0);
188                 try (Cursor cursor = mContext.getContentResolver().query(
189                         mediaStoreUri, null, null, null)) {
190                     assertEquals(0, cursor.getCount());
191                 }
192             }
193         } finally {
194             mContext.unregisterReceiver(receiver);
195         }
196     }
197 
198     /**
199      * Add a file using DownloadManager.addCompleted and verify that the file has been added
200      * to MediaStore as well.
201      */
202     @Test
testAddCompletedDownload_mediaStoreEntry()203     public void testAddCompletedDownload_mediaStoreEntry() throws Exception {
204         final String assetName = "noiseandchirps.mp3";
205         final String[] downloadPath = new String[] {
206                 new File(Environment.getExternalStoragePublicDirectory(
207                         Environment.DIRECTORY_DOWNLOADS), "file1.mp3").getPath(),
208                 new File(Environment.getExternalStoragePublicDirectory(
209                         Environment.DIRECTORY_MUSIC), "file2.mp3").getPath(),
210                 "/sdcard/file3.mp3",
211         };
212         for (String downloadLocation : downloadPath) {
213             final File file = new File(Uri.parse(downloadLocation).getPath());
214             try (InputStream in = mContext.getAssets().open(assetName);
215                  OutputStream out = new FileOutputStream(file)) {
216                 FileUtils.copy(in, out);
217             }
218 
219             final long downloadId = mDownloadManager.addCompletedDownload(file.getName(),
220                     "Test desc", true,
221                     "audio/mp3", downloadLocation, file.length(), true);
222             assertTrue(downloadId >= 0);
223             final Uri downloadUri = mDownloadManager.getUriForDownloadedFile(downloadId);
224             final Uri mediaStoreUri = getMediaStoreUri(downloadUri);
225             assertArrayEquals(hash(new FileInputStream(file)),
226                     hash(mContext.getContentResolver().openInputStream(mediaStoreUri)));
227 
228             // Delete entry in DownloadProvider and verify it's deleted from MediaProvider as well.
229             assertRemoveDownload(downloadId, 0);
230             try (Cursor cursor = mContext.getContentResolver().query(
231                     mediaStoreUri, null, null, null)) {
232                 assertEquals(0, cursor.getCount());
233             }
234         }
235     }
236 }