Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import static org.robolectric.shadows.util.DataSource.toDataSource;
      4 
      5 import android.content.Context;
      6 import android.graphics.Bitmap;
      7 import android.media.MediaMetadataRetriever;
      8 import android.net.Uri;
      9 import java.io.FileDescriptor;
     10 import java.util.HashMap;
     11 import java.util.Map;
     12 import org.robolectric.annotation.Implementation;
     13 import org.robolectric.annotation.Implements;
     14 import org.robolectric.annotation.Resetter;
     15 import org.robolectric.shadows.util.DataSource;
     16 
     17 @Implements(MediaMetadataRetriever.class)
     18 public class ShadowMediaMetadataRetriever {
     19   private DataSource dataSource;
     20   private static final Map<DataSource, Map<Integer, String>> metadata = new HashMap<>();
     21   private static final Map<DataSource, Map<Long, Bitmap>> frames = new HashMap<>();
     22   private static final Map<DataSource, RuntimeException> exceptions = new HashMap<>();
     23 
     24   public void setDataSource(DataSource dataSource) {
     25     RuntimeException e = exceptions.get(dataSource);
     26     if (e != null) {
     27       e.fillInStackTrace();
     28       throw e;
     29     }
     30     this.dataSource = dataSource;
     31   }
     32 
     33   @Implementation
     34   protected void setDataSource(String path) {
     35     setDataSource(toDataSource(path));
     36   }
     37 
     38   @Implementation
     39   protected void setDataSource(Context context, Uri uri) {
     40     setDataSource(toDataSource(context, uri));
     41   }
     42 
     43   @Implementation
     44   protected void setDataSource(String uri, Map<String, String> headers) {
     45     setDataSource(toDataSource(uri, headers));
     46   }
     47 
     48   @Implementation
     49   protected void setDataSource(FileDescriptor fd, long offset, long length) {
     50     setDataSource(toDataSource(fd, offset, length));
     51   }
     52 
     53   @Implementation
     54   protected String extractMetadata(int keyCode) {
     55     if (metadata.containsKey(dataSource)) {
     56       return metadata.get(dataSource).get(keyCode);
     57     }
     58     return null;
     59   }
     60 
     61   @Implementation
     62   protected Bitmap getFrameAtTime(long timeUs, int option) {
     63     return (frames.containsKey(dataSource) ?
     64             frames.get(dataSource).get(timeUs) : null);
     65   }
     66 
     67   /**
     68    * Configures an exception to be thrown when {@link #setDataSource}
     69    * is called for the given data source.
     70    *
     71    * @param ds the data source that will trigger an exception
     72    * @param e the exception to trigger, or <tt>null</tt> to
     73    * avoid throwing an exception.
     74    */
     75   public static void addException(DataSource ds, RuntimeException e) {
     76     exceptions.put(ds, e);
     77   }
     78 
     79   public static void addMetadata(DataSource ds, int keyCode, String value) {
     80     if (!metadata.containsKey(ds)) {
     81       metadata.put(ds, new HashMap<Integer, String>());
     82     }
     83     metadata.get(ds).put(keyCode, value);
     84   }
     85 
     86   /**
     87    * Adds the given keyCode/value pair for the given data source.
     88    * Uses <tt>path</tt> to call {@link org.robolectric.shadows.util.DataSource#toDataSource(String)} and
     89    * then calls {@link #addMetadata(DataSource, int, String)}. This
     90    * method is retained mostly for backwards compatibility;
     91    * you can call {@link #addMetadata(DataSource, int, String)} directly.
     92    *
     93    * @param path the path to the data source whose metadata is being set.
     94    * @param keyCode the keyCode for the metadata being set, as used by {@link MediaMetadataRetriever#extractMetadata(int)}.
     95    * @param value the value for the specified metadata.
     96    */
     97   public static void addMetadata(String path, int keyCode, String value) {
     98     addMetadata(toDataSource(path), keyCode, value);
     99   }
    100 
    101   public static void addFrame(DataSource ds, long time, Bitmap bitmap) {
    102     if (!frames.containsKey(ds)) {
    103       frames.put(ds, new HashMap<Long, Bitmap>());
    104     }
    105     frames.get(ds).put(time, bitmap);
    106   }
    107 
    108   /**
    109    * Adds the given bitmap at the given time for the given data source.
    110    * Uses <tt>path</tt> to call {@link org.robolectric.shadows.util.DataSource#toDataSource(String)} and
    111    * then calls {@link #addFrame(DataSource, long, Bitmap)}. This
    112    * method is retained mostly for backwards compatibility;
    113    * you can call {@link #addFrame(DataSource, long, Bitmap)} directly.
    114    *
    115    * @param path the path to the data source.
    116    * @param time the playback time at which the specified bitmap
    117    * should be retrieved.
    118    * @param bitmap the bitmap to retrieve.
    119    */
    120   public static void addFrame(String path, long time, Bitmap bitmap) {
    121     addFrame(toDataSource(path), time, bitmap);
    122   }
    123 
    124   /**
    125    * Adds the given bitmap at the given time for the given data source.
    126    * Uses <tt>path</tt> to call {@link org.robolectric.shadows.util.DataSource#toDataSource(Context, Uri)} and
    127    * then calls {@link #addFrame(DataSource, long, Bitmap)}. This
    128    * method is retained mostly for backwards compatibility;
    129    * you can call {@link #addFrame(DataSource, long, Bitmap)} directly.
    130    *
    131    * @param context the Context object to match on the data source.
    132    * @param uri the Uri of the data source.
    133    * @param time the playback time at which the specified bitmap
    134    * should be retrieved.
    135    * @param bitmap the bitmap to retrieve.
    136    */
    137   public static void addFrame(Context context, Uri uri, long time, Bitmap bitmap) {
    138     addFrame(toDataSource(context, uri), time, bitmap);
    139   }
    140 
    141   /**
    142    * Adds the given bitmap at the given time for the given data source.
    143    * Uses <tt>path</tt> to call {@link org.robolectric.shadows.util.DataSource#toDataSource(String, Map)} and
    144    * then calls {@link #addFrame(DataSource, long, Bitmap)}. This
    145    * method is retained mostly for backwards compatibility;
    146    * you can call {@link #addFrame(DataSource, long, Bitmap)} directly.
    147    *
    148    * @param uri the Uri of the data source.
    149    * @param headers the headers to use when requesting the specified uri.
    150    * @param time the playback time at which the specified bitmap
    151    * should be retrieved.
    152    * @param bitmap the bitmap to retrieve.
    153    */
    154   public static void addFrame(String uri, Map<String, String> headers, long time, Bitmap bitmap) {
    155     addFrame(toDataSource(uri, headers), time, bitmap);
    156   }
    157 
    158   /**
    159    * Adds the given bitmap at the given time for the given data source.
    160    * Uses <tt>path</tt> to call {@link org.robolectric.shadows.util.DataSource#toDataSource(FileDescriptor)} and
    161    * then calls {@link #addFrame(DataSource, long, Bitmap)}. This
    162    * method is retained mostly for backwards compatibility;
    163    * you can call {@link #addFrame(DataSource, long, Bitmap)} directly.
    164    *
    165    * @param fd file descriptor of the data source.
    166    * @param time the playback time at which the specified bitmap
    167    * should be retrieved.
    168    * @param bitmap the bitmap to retrieve.
    169    */
    170   public static void addFrame(FileDescriptor fd, long time, Bitmap bitmap) {
    171     addFrame(toDataSource(fd), time, bitmap);
    172   }
    173 
    174   /**
    175    * Adds the given bitmap at the given time for the given data source.
    176    * Uses <tt>path</tt> to call {@link org.robolectric.shadows.util.DataSource#toDataSource(FileDescriptor, long, long)} and
    177    * then calls {@link #addFrame(DataSource, long, Bitmap)}. This
    178    * method is retained mostly for backwards compatibility;
    179    * you can call {@link #addFrame(DataSource, long, Bitmap)} directly.
    180    *
    181    * @param fd file descriptor of the data source.
    182    * @param offset the byte offset within the specified file from which to start reading the data.
    183    * @param length the number of bytes to read from the file.
    184    * @param time the playback time at which the specified bitmap
    185    * should be retrieved.
    186    * @param bitmap the bitmap to retrieve.
    187    */
    188   public static void addFrame(FileDescriptor fd, long offset, long length,
    189                               long time, Bitmap bitmap) {
    190     addFrame(toDataSource(fd, offset, length), time, bitmap);
    191   }
    192 
    193   @Resetter
    194   public static void reset() {
    195     metadata.clear();
    196     frames.clear();
    197     exceptions.clear();
    198   }
    199 }
    200