Home | History | Annotate | Download | only in downloadapp
      1 /*
      2  * Copyright (C) 2016 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 
     17 package com.android.functional.downloadapp;
     18 
     19 import android.app.AlarmManager;
     20 import android.app.DownloadManager;
     21 import android.app.DownloadManager.Query;
     22 import android.app.DownloadManager.Request;
     23 import android.content.ContentValues;
     24 import android.content.Context;
     25 import android.database.Cursor;
     26 import android.icu.util.Calendar;
     27 import android.net.Uri;
     28 import android.os.Environment;
     29 import android.support.test.launcherhelper.ILauncherStrategy;
     30 import android.support.test.launcherhelper.LauncherStrategyFactory;
     31 import android.support.test.uiautomator.By;
     32 import android.support.test.uiautomator.UiDevice;
     33 import android.support.test.uiautomator.UiObject2;
     34 import android.support.test.uiautomator.Until;
     35 import android.util.Log;
     36 
     37 import junit.framework.Assert;
     38 
     39 import java.util.ArrayList;
     40 import java.util.Hashtable;
     41 import java.util.List;
     42 import java.util.Random;
     43 
     44 public class DownloadAppTestHelper {
     45     private static DownloadAppTestHelper mInstance = null;
     46     public static final String[] FILE_TYPES = new String[] {
     47             "pdf", "jpg", "jpeg", "doc", "xls", "txt", "rtf", "ppt", "gif", "png"
     48     };
     49 
     50     public static final String PACKAGE_NAME = "com.android.documentsui";
     51     public static final String APP_NAME = "Downloads";
     52     public static final String TEST_TAG = "DownloadAppTest";
     53     public final int TIMEOUT = 500;
     54     public final int MIN_FILENAME_LEN = 4;
     55     private Context mContext = null;
     56     private UiDevice mDevice = null;
     57     private DownloadManager mDownloadMgr;
     58     private Hashtable<String, DlObjSizeTimePair> mDownloadedItems =
     59             new Hashtable<String, DlObjSizeTimePair>();
     60     public ILauncherStrategy mLauncherStrategy;
     61 
     62     private DownloadAppTestHelper(UiDevice device, Context context) {
     63         mDevice = device;
     64         mContext = context;
     65         mLauncherStrategy = LauncherStrategyFactory.getInstance(mDevice).getLauncherStrategy();
     66     }
     67 
     68     public static DownloadAppTestHelper getInstance(UiDevice device, Context context) {
     69         if (mInstance == null) {
     70             mInstance = new DownloadAppTestHelper(device, context);
     71         }
     72         return mInstance;
     73     }
     74 
     75     public DownloadManager getDLManager() {
     76         return (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
     77     }
     78 
     79     public void launchApp(String packageName, String appName) {
     80         if (!mDevice.hasObject(By.pkg(packageName).depth(0))) {
     81             mLauncherStrategy.launch(appName, packageName);
     82         }
     83     }
     84 
     85     /** sort items in Download app by name, size, time */
     86     public void sortByParam(String sortby) {
     87         UiObject2 sortMenu = mDevice
     88                 .wait(Until.findObject(By.res(PACKAGE_NAME, "menu_sort")), 200);
     89         if (sortMenu == null) {
     90             mDevice.wait(Until.findObject(By.desc("More options")), 200).click();
     91             sortMenu = mDevice.wait(Until.findObject(By.res("android:id/submenuarrow")), 200);
     92         }
     93         sortMenu.click();
     94         mDevice.wait(Until.findObject(By.text(String.format("By %s", sortby))), 200).click();
     95         mDevice.waitForIdle();
     96     }
     97 
     98     /** returns text list of items in Download app */
     99     public List<String> getDownloadItemNames() {
    100         List<UiObject2> itmesList = mDevice.wait(Until.findObjects(By.res("android:id/title")),
    101                 TIMEOUT);
    102         List<String> nameList = new ArrayList<String>();
    103         for (UiObject2 item : itmesList) {
    104             nameList.add(item.getText());
    105         }
    106         return nameList;
    107     }
    108 
    109     /** verifies items in DownloadApp UI are sorted by name */
    110     public Boolean verifySortedByName() {
    111         List<String> nameList = getDownloadItemNames();
    112         for (int i = 0; i < (nameList.size() - 1); ++i) {
    113             if (nameList.get(i).compareToIgnoreCase(nameList.get(i + 1)) > 0) {
    114                 return false;
    115             }
    116         }
    117         return true;
    118     }
    119 
    120     /** verifies items in DownloadApp UI are sorted by size */
    121     public Boolean verifySortedBySize() {
    122         List<String> nameList = getDownloadItemNames();
    123         for (int i = 0; i < (nameList.size() - 1); ++i) {
    124             DlObjSizeTimePair firstItem = mDownloadedItems.get(nameList.get(i));
    125             DlObjSizeTimePair secondItem = mDownloadedItems.get(nameList.get(i + 1));
    126             if (firstItem != null && secondItem != null
    127                     && firstItem.dlObjSize < secondItem.dlObjSize) {
    128                 return false;
    129             }
    130         }
    131         return true;
    132     }
    133 
    134     /** verifies items in DownloadApp UI are sorted by time */
    135     public Boolean verifySortedByTime() {
    136         List<String> nameList = getDownloadItemNames();
    137         for (int i = 0; i < (nameList.size() - 1); ++i) {
    138             DlObjSizeTimePair firstItem = mDownloadedItems.get(nameList.get(i));
    139             DlObjSizeTimePair secondItem = mDownloadedItems.get(nameList.get(i + 1));
    140             if (firstItem != null && secondItem != null
    141                     && firstItem.dlObjTimeInMilliSec < secondItem.dlObjTimeInMilliSec) {
    142                 return false;
    143             }
    144         }
    145         return true;
    146     }
    147 
    148     public void verifyDownloadViewType(UIViewType view) {
    149         int counter = 5;
    150         UiObject2 viewTypeObj = null;
    151         while ((viewTypeObj = mDevice.wait(
    152                 Until.findObject(By.res(String.format("%s:id/%s",
    153                         DownloadAppTestHelper.PACKAGE_NAME,view.toString()))),200)) == null
    154                         && counter-- > 0);
    155         Assert.assertNotNull(viewTypeObj);
    156     }
    157 
    158     /**
    159      * Create word of random assortment of lower/upper case letters
    160      */
    161     /** set system time to random n[0..29] days earlier */
    162     public long changeSystemTime(long timeToSet) {
    163         Calendar c = Calendar.getInstance();
    164         c.setTimeInMillis(timeToSet);
    165         AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
    166         am.setTime(c.getTimeInMillis());
    167         return c.getTimeInMillis();
    168     }
    169 
    170     /** add some content to download DB using DownloadManager.addCompletedDownload api */
    171     public void populateContentInDLApp(int count) {
    172         int totalDownloaded = getTotalNumberDownloads();
    173         if (totalDownloaded >= count) {
    174             return;
    175         }
    176         Random random = new Random();
    177         long currentTime = System.currentTimeMillis();
    178         for (int i = 0; i < (count - totalDownloaded); ++i) {
    179             String fileName = String.format("%s.%s",
    180                     DownloadAppTestHelper.randomWord(random.nextInt(8) + MIN_FILENAME_LEN),
    181                     DownloadAppTestHelper.FILE_TYPES[random.nextInt(FILE_TYPES.length)]);
    182             int size = random.nextInt(1000);
    183             // changing system time to simulate the usecase "downloaded items over a period of time"
    184             long timeInMiliSec = changeSystemTime(
    185                     System.currentTimeMillis() - random.nextInt(30 * 24) * (60 * 60 * 1000));
    186             long dlId = -1;
    187 
    188             dlId = getDLManager().addCompletedDownload(
    189                     fileName,
    190                     String.format("%s Desc",
    191                             DownloadAppTestHelper.randomWord(random.nextInt(8) + MIN_FILENAME_LEN)),
    192                     Boolean.FALSE,
    193                     DownloadAppTestHelper.FILE_TYPES[random.nextInt(FILE_TYPES.length)],
    194                     Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
    195                             .getAbsolutePath(),
    196                     size, Boolean.FALSE);
    197             Assert.assertFalse("Add to DonwloadDB has failed!", dlId == -1);
    198             Log.d(TEST_TAG, String.format("Adding Name = %s, size = %d, time = %d", fileName,
    199                     size, timeInMiliSec));
    200             mDownloadedItems.put(fileName, new DlObjSizeTimePair(size, timeInMiliSec));
    201         }
    202         changeSystemTime(currentTime);
    203     }
    204 
    205     /** add some content to download DB directly in hacky way to bypass addCompletedDownload Api*/
    206     public long addToDownloadContentDB(String title, String description,
    207             boolean isMediaScannerScannable, String mimeType, String path, long length,
    208             boolean showNotification) {
    209 
    210         boolean allowWrite = Boolean.FALSE;
    211         Uri uri = Uri.parse("http://blah-blah"); // just put something in url format
    212         Uri referer = null;
    213         Request request;
    214         request = new Request(uri);
    215         ContentValues values = new ContentValues();
    216         /**
    217          * a hacky way to insert into the Download DB direct bypassing the api with minimal data
    218          * Constants have been taken from
    219          * /platform/frameworks/base/+/master/core/java/android/provider/Downloads.java
    220          */
    221         values.put("title", title);
    222         values.put("description", description);
    223         values.put("mimetype", mimeType);
    224         values.put("is_public_api", true);
    225         values.put("scanned", isMediaScannerScannable);
    226         values.put("is_visible_in_downloads_ui", Boolean.TRUE);
    227         values.put("destination", 6); // 6: show the download item in app
    228         values.put("_data", path); // location to save the downloaded file
    229         values.put("status", 200); // 200 : STATUS_SUCCESS
    230         values.put("total_bytes", length);
    231         values.put("visibility", (showNotification)
    232                 ? Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION : Request.VISIBILITY_HIDDEN);
    233         Uri downloadUri = mContext.getContentResolver()
    234                 .insert(Uri.parse("content://downloads/my_downloads"), values);
    235         if (downloadUri == null) {
    236             return -1;
    237         }
    238         return Long.parseLong(downloadUri.getLastPathSegment());
    239     }
    240 
    241     /** remove downloads from download content db */
    242     public void removeContentInDLApp() {
    243         Cursor cursor = null;
    244         try {
    245             Query query = new Query();
    246             cursor = getDLManager().query(query);
    247             int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_ID);
    248             long[] removeIds = new long[cursor.getCount() - 1];
    249             Log.d(TEST_TAG, String.format("Remove Size is = %d", cursor.getCount()));
    250             for (int i = 0; i < (cursor.getCount() - 1); i++) {
    251                 cursor.moveToNext();
    252                 removeIds[i] = cursor.getLong(columnIndex);
    253             }
    254             if (removeIds.length > 0) {
    255                 Assert.assertEquals(removeIds.length, getDLManager().remove(removeIds));
    256             }
    257         } finally {
    258             if (cursor != null) {
    259                 cursor.close();
    260             }
    261         }
    262     }
    263 
    264     public int getTotalNumberDownloads() {
    265         Cursor cursor = null;
    266         try {
    267             Query query = new Query();
    268             cursor = getDLManager().query(query);
    269             return cursor.getCount();
    270         } finally {
    271             if (cursor != null) {
    272                 cursor.close();
    273             }
    274         }
    275     }
    276 
    277     public int getDownloadItemCountById(long[] downloadId) {
    278         Cursor cursor = null;
    279         int total = 0;
    280         try {
    281             Query query = new Query().setFilterById(downloadId);
    282             cursor = getDLManager().query(query);
    283             total = cursor.getCount();
    284         } finally {
    285             if (cursor != null) {
    286                 cursor.close();
    287             }
    288         }
    289 
    290         return total;
    291     }
    292 
    293     public static String randomWord(int length) {
    294         Random random = new Random();
    295         StringBuilder result = new StringBuilder();
    296         for (int j = 0; j < length; j++) {
    297             int base = random.nextInt(2) == 0 ? 'A' : 'a';
    298             result.append((char) (random.nextInt(26) + base));
    299         }
    300         return result.toString();
    301     }
    302 
    303     /**
    304      * Class to hold size and time info on downloaded items
    305      */
    306     class DlObjSizeTimePair {
    307         int dlObjSize;
    308         long dlObjTimeInMilliSec;
    309 
    310         public DlObjSizeTimePair(int size, long time) {
    311             this.dlObjSize = size;
    312             this.dlObjTimeInMilliSec = time;
    313         }
    314     }
    315 
    316     public enum UIViewType {
    317         LIST {
    318             public String toString() {
    319                 return "menu_list";
    320             }
    321         },
    322         GRID {
    323             public String toString() {
    324                 return "menu_grid";
    325             }
    326         }
    327     };
    328 }
    329