Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import android.app.DownloadManager;
      4 import android.database.Cursor;
      5 import android.net.Uri;
      6 import android.util.Pair;
      7 import java.util.ArrayList;
      8 import java.util.List;
      9 import java.util.Map;
     10 import java.util.TreeMap;
     11 import org.robolectric.Shadows;
     12 import org.robolectric.annotation.Implementation;
     13 import org.robolectric.annotation.Implements;
     14 import org.robolectric.annotation.RealObject;
     15 import org.robolectric.fakes.BaseCursor;
     16 import org.robolectric.util.ReflectionHelpers;
     17 
     18 @Implements(DownloadManager.class)
     19 public class ShadowDownloadManager {
     20 
     21   private long queueCounter = -1; // First request starts at 0 just like in the real DownloadManager
     22   private Map<Long, DownloadManager.Request> requestMap = new TreeMap<>();
     23 
     24   @Implementation
     25   public long enqueue(DownloadManager.Request request) {
     26     queueCounter++;
     27     requestMap.put(queueCounter, request);
     28     return queueCounter;
     29   }
     30 
     31   @Implementation
     32   public int remove(long... ids) {
     33     int removeCount = 0;
     34     for (long id : ids) {
     35       if (requestMap.remove(id) != null) {
     36         removeCount++;
     37       }
     38     }
     39     return removeCount;
     40   }
     41 
     42   @Implementation
     43   public Cursor query(DownloadManager.Query query) {
     44     ResultCursor result = new ResultCursor();
     45     ShadowQuery shadow = Shadows.shadowOf(query);
     46     long[] ids = shadow.getIds();
     47 
     48     if (ids != null) {
     49       for (long id : ids) {
     50         DownloadManager.Request request = requestMap.get(id);
     51         if (request != null) {
     52           result.requests.add(request);
     53         }
     54       }
     55     } else {
     56       result.requests.addAll(requestMap.values());
     57     }
     58     return result;
     59   }
     60 
     61   public DownloadManager.Request getRequest(long id) {
     62     return requestMap.get(id);
     63   }
     64 
     65   public int getRequestCount() {
     66     return requestMap.size();
     67   }
     68 
     69   @Implements(DownloadManager.Request.class)
     70   public static class ShadowRequest {
     71     @RealObject DownloadManager.Request realObject;
     72 
     73     private int status;
     74 
     75     public int getStatus() {
     76       return this.status;
     77     }
     78 
     79     public void setStatus(int status) {
     80       this.status = status;
     81     }
     82 
     83     public Uri getUri() {
     84       return getFieldReflectively("mUri", realObject, Uri.class);
     85     }
     86 
     87     public Uri getDestination() {
     88       return getFieldReflectively("mDestinationUri", realObject, Uri.class);
     89     }
     90 
     91     public CharSequence getTitle() {
     92       return getFieldReflectively("mTitle", realObject, CharSequence.class);
     93     }
     94 
     95     public CharSequence getDescription() {
     96       return getFieldReflectively("mDescription", realObject, CharSequence.class);
     97     }
     98 
     99     public CharSequence getMimeType() {
    100       return getFieldReflectively("mMimeType", realObject, CharSequence.class);
    101     }
    102 
    103     public int getNotificationVisibility() {
    104       return getFieldReflectively("mNotificationVisibility", realObject, Integer.class);
    105     }
    106 
    107     public int getAllowedNetworkTypes() {
    108       return getFieldReflectively("mAllowedNetworkTypes", realObject, Integer.class);
    109     }
    110 
    111     public boolean getAllowedOverRoaming() {
    112       return getFieldReflectively("mRoamingAllowed", realObject, Boolean.class);
    113     }
    114 
    115     public boolean getAllowedOverMetered() {
    116       return getFieldReflectively("mMeteredAllowed", realObject, Boolean.class);
    117     }
    118 
    119     public boolean getVisibleInDownloadsUi() {
    120       return getFieldReflectively("mIsVisibleInDownloadsUi", realObject, Boolean.class);
    121     }
    122 
    123     public List<Pair<String, String>> getRequestHeaders() {
    124       return getFieldReflectively("mRequestHeaders", realObject, List.class);
    125     }
    126   }
    127 
    128   @Implements(DownloadManager.Query.class)
    129   public static class ShadowQuery {
    130     @RealObject DownloadManager.Query realObject;
    131 
    132     public long[] getIds() {
    133       return getFieldReflectively("mIds", realObject, long[].class);
    134     }
    135   }
    136 
    137   private static class ResultCursor extends BaseCursor {
    138     private static final int COLUMN_INDEX_LOCAL_FILENAME = 0;
    139     private static final int COLUMN_INDEX_DESCRIPTION = 1;
    140     private static final int COLUMN_INDEX_REASON = 2;
    141     private static final int COLUMN_INDEX_STATUS = 3;
    142     private static final int COLUMN_INDEX_URI = 4;
    143     private static final int COLUMN_INDEX_LOCAL_URI = 5;
    144     private static final int COLUMN_INDEX_TITLE = 6;
    145 
    146     public List<DownloadManager.Request> requests = new ArrayList<>();
    147     private int positionIndex = -1;
    148     private boolean closed;
    149 
    150     @Override
    151     public int getCount() {
    152       checkClosed();
    153       return requests.size();
    154     }
    155 
    156     @Override
    157     public int getPosition() {
    158       return positionIndex;
    159     }
    160 
    161     @Override
    162     public boolean moveToFirst() {
    163       checkClosed();
    164       positionIndex = 0;
    165       return !requests.isEmpty();
    166     }
    167 
    168     @Override
    169     public boolean moveToNext() {
    170       checkClosed();
    171       positionIndex += 1;
    172       return positionIndex < requests.size();
    173     }
    174 
    175     @Override
    176     public int getColumnIndex(String columnName) {
    177       checkClosed();
    178 
    179       if (DownloadManager.COLUMN_LOCAL_FILENAME.equals(columnName)) {
    180         return COLUMN_INDEX_LOCAL_FILENAME;
    181 
    182       } else if (DownloadManager.COLUMN_DESCRIPTION.equals(columnName)) {
    183         return COLUMN_INDEX_DESCRIPTION;
    184 
    185       } else if (DownloadManager.COLUMN_REASON.equals(columnName)) {
    186         return COLUMN_INDEX_REASON;
    187 
    188       } else if (DownloadManager.COLUMN_STATUS.equals(columnName)) {
    189         return COLUMN_INDEX_STATUS;
    190 
    191       } else if (DownloadManager.COLUMN_URI.equals(columnName)) {
    192         return COLUMN_INDEX_URI;
    193 
    194       } else if (DownloadManager.COLUMN_LOCAL_URI.equals(columnName)) {
    195         return COLUMN_INDEX_LOCAL_URI;
    196 
    197       } else if (DownloadManager.COLUMN_TITLE.equals(columnName)) {
    198         return COLUMN_INDEX_TITLE;
    199       }
    200 
    201       return -1;
    202     }
    203 
    204     @Override
    205     public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
    206       checkClosed();
    207 
    208       int columnIndex = getColumnIndex(columnName);
    209       if (columnIndex == -1) {
    210         throw new IllegalArgumentException("Column not found.");
    211       }
    212       return columnIndex;
    213     }
    214 
    215     @Override
    216     public void close() {
    217       this.closed = true;
    218     }
    219 
    220     @Override
    221     public boolean isClosed() {
    222       return closed;
    223     }
    224 
    225     @Override
    226     public String getString(int columnIndex) {
    227       checkClosed();
    228       ShadowRequest request = Shadows.shadowOf(requests.get(positionIndex));
    229       switch (columnIndex) {
    230         case COLUMN_INDEX_LOCAL_FILENAME:
    231           return "local file name not implemented";
    232 
    233         case COLUMN_INDEX_REASON:
    234           return "reason not implemented";
    235 
    236         case COLUMN_INDEX_DESCRIPTION:
    237           return request.getDescription().toString();
    238 
    239         case COLUMN_INDEX_URI:
    240           return request.getUri().toString();
    241 
    242         case COLUMN_INDEX_LOCAL_URI:
    243           return request.getDestination().toString();
    244 
    245         case COLUMN_INDEX_TITLE:
    246           return request.getTitle().toString();
    247       }
    248 
    249       return "Unknown ColumnIndex " + columnIndex;
    250     }
    251 
    252     @Override
    253     public int getInt(int columnIndex) {
    254       checkClosed();
    255       ShadowRequest request = Shadows.shadowOf(requests.get(positionIndex));
    256       if (columnIndex == COLUMN_INDEX_STATUS) {
    257         return request.getStatus();
    258       }
    259       return 0;
    260     }
    261 
    262     private void checkClosed() {
    263       if (closed) {
    264         throw new IllegalStateException("Cursor is already closed.");
    265       }
    266     }
    267   }
    268 
    269   private static <T> T getFieldReflectively(String fieldName, Object object, Class<T> clazz) {
    270     return clazz.cast(ReflectionHelpers.getField(object, fieldName));
    271   }
    272 }
    273