1 /*
2  * Copyright 2018 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 androidx.media;
18 
19 import android.content.res.AssetFileDescriptor;
20 import android.util.Log;
21 
22 import java.io.IOException;
23 import java.io.InputStream;
24 
25 /**
26  * A Media2DataSource that reads from a byte array for use in tests.
27  */
28 public class TestMedia2DataSource extends Media2DataSource {
29     private static final String TAG = "TestMedia2DataSource";
30 
31     private byte[] mData;
32 
33     private boolean mThrowFromReadAt;
34     private boolean mThrowFromGetSize;
35     private Integer mReturnFromReadAt;
36     private Long mReturnFromGetSize;
37     private boolean mIsClosed;
38 
39     // Read an asset fd into a new byte array data source. Closes afd.
fromAssetFd(AssetFileDescriptor afd)40     public static TestMedia2DataSource fromAssetFd(AssetFileDescriptor afd) throws IOException {
41         try {
42             InputStream in = afd.createInputStream();
43             final int size = (int) afd.getDeclaredLength();
44             byte[] data = new byte[(int) size];
45             int writeIndex = 0;
46             int numRead = 0;
47             do {
48                 numRead = in.read(data, writeIndex, size - writeIndex);
49                 writeIndex += numRead;
50             } while (numRead >= 0);
51             return new TestMedia2DataSource(data);
52         } finally {
53             afd.close();
54         }
55     }
56 
TestMedia2DataSource(byte[] data)57     public TestMedia2DataSource(byte[] data) {
58         mData = data;
59     }
60 
61     @Override
readAt(long position, byte[] buffer, int offset, int size)62     public synchronized int readAt(long position, byte[] buffer, int offset, int size)
63             throws IOException {
64         if (mThrowFromReadAt) {
65             throw new IOException("Test exception from readAt()");
66         }
67         if (mReturnFromReadAt != null) {
68             return mReturnFromReadAt;
69         }
70 
71         // Clamp reads past the end of the source.
72         if (position >= mData.length) {
73             return -1; // -1 indicates EOF
74         }
75         if (position + size > mData.length) {
76             size -= (position + size) - mData.length;
77         }
78         System.arraycopy(mData, (int) position, buffer, offset, size);
79         return size;
80     }
81 
82     @Override
getSize()83     public synchronized long getSize() throws IOException {
84         if (mThrowFromGetSize) {
85             throw new IOException("Test exception from getSize()");
86         }
87         if (mReturnFromGetSize != null) {
88             return mReturnFromGetSize;
89         }
90 
91         Log.v(TAG, "getSize: " + mData.length);
92         return mData.length;
93     }
94 
95     // Note: it's fine to keep using this data source after closing it.
96     @Override
close()97     public synchronized void close() {
98         Log.v(TAG, "close()");
99         mIsClosed = true;
100     }
101 
102     // Whether close() has been called.
isClosed()103     public synchronized boolean isClosed() {
104         return mIsClosed;
105     }
106 
throwFromReadAt()107     public void throwFromReadAt() {
108         mThrowFromReadAt = true;
109     }
110 
throwFromGetSize()111     public void throwFromGetSize() {
112         mThrowFromGetSize = true;
113     }
114 
returnFromReadAt(int numRead)115     public void returnFromReadAt(int numRead) {
116         mReturnFromReadAt = numRead;
117     }
118 
returnFromGetSize(long size)119     public void returnFromGetSize(long size) {
120         mReturnFromGetSize = size;
121     }
122 }
123 
124