blob: 7dc462a2939f42b0c96260a4c57d6c7d1ae4dde3 [file] [log] [blame]
/*
* Copyright (C) 2012 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.cts.externalstorageapp;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPaths;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.app.DownloadManager.Request;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.text.format.DateUtils;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
/**
* Test external storage from an application that has no external storage
* permissions.
*/
public class ExternalStorageTest extends AndroidTestCase {
public void testPrimaryNoAccess() throws Exception {
assertDirNoAccess(Environment.getExternalStorageDirectory());
}
/**
* Verify that above our package directories we always have no access.
*/
public void testAllWalkingUpTreeNoAccess() throws Exception {
final List<File> paths = getAllPackageSpecificPaths(getContext());
final String packageName = getContext().getPackageName();
for (File path : paths) {
if (path == null) continue;
assertTrue(path.getAbsolutePath().contains(packageName));
// Walk up until we drop our package
while (path.getAbsolutePath().contains(packageName)) {
assertDirReadWriteAccess(path);
path = path.getParentFile();
}
// Keep walking up until we leave device
while (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState(path))) {
assertDirNoAccess(path);
path = path.getParentFile();
}
}
}
/**
* Verify that we can't download things outside package directory.
*/
public void testDownloadManager() throws Exception {
final DownloadManager dm = getContext().getSystemService(DownloadManager.class);
try {
final Uri source = Uri.parse("http://www.example.com");
final File target = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "meow");
dm.enqueue(new Request(source).setDestinationUri(Uri.fromFile(target)));
fail("Unexpected success writing outside package directory");
} catch (SecurityException expected) {
}
}
/**
* Verify that we can download things into our package directory.
*/
public void testDownloadManagerPackage() throws Exception {
final DownloadManager dm = getContext().getSystemService(DownloadManager.class);
final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
try {
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
mContext.registerReceiver(receiver, intentFilter);
final Uri source = Uri.parse("http://www.example.com");
final File target = new File(
getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "meow");
final long id = dm.enqueue(new Request(source).setDestinationUri(Uri.fromFile(target)));
receiver.waitForDownloadComplete(30 * DateUtils.SECOND_IN_MILLIS, id);
assertSuccessfulDownload(id, target);
} finally {
mContext.unregisterReceiver(receiver);
}
}
/**
* Shamelessly borrowed from DownloadManagerTest.java
*/
private static class DownloadCompleteReceiver extends BroadcastReceiver {
private HashSet<Long> mCompleteIds = new HashSet<>();
public DownloadCompleteReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mCompleteIds) {
mCompleteIds.add(intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1));
mCompleteIds.notifyAll();
}
}
private boolean isCompleteLocked(long... ids) {
for (long id : ids) {
if (!mCompleteIds.contains(id)) {
return false;
}
}
return true;
}
public void waitForDownloadComplete(long timeoutMillis, long... waitForIds)
throws InterruptedException {
if (waitForIds.length == 0) {
throw new IllegalArgumentException("Missing IDs to wait for");
}
final long startTime = SystemClock.elapsedRealtime();
do {
synchronized (mCompleteIds) {
mCompleteIds.wait(timeoutMillis);
if (isCompleteLocked(waitForIds)) return;
}
} while ((SystemClock.elapsedRealtime() - startTime) < timeoutMillis);
throw new InterruptedException("Timeout waiting for IDs " + Arrays.toString(waitForIds)
+ "; received " + mCompleteIds.toString()
+ ". Make sure you have WiFi or some other connectivity for this test.");
}
}
private void assertSuccessfulDownload(long id, File location) {
final DownloadManager dm = getContext().getSystemService(DownloadManager.class);
Cursor cursor = null;
try {
cursor = dm.query(new Query().setFilterById(id));
assertTrue(cursor.moveToNext());
assertEquals(DownloadManager.STATUS_SUCCESSFUL, cursor.getInt(
cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)));
assertEquals(Uri.fromFile(location).toString(),
cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
assertTrue(location.exists());
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}