/*
 * 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();
            }
        }
    }
}
