1 /*
2  * Copyright 2020 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.bluetooth.avrcp;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import android.content.Context;
23 import android.content.pm.PackageManager;
24 import android.content.res.Resources;
25 import android.graphics.Bitmap;
26 import android.graphics.BitmapFactory;
27 
28 import androidx.test.InstrumentationRegistry;
29 import androidx.test.runner.AndroidJUnit4;
30 
31 import com.android.bluetooth.audio_util.Image;
32 import com.android.bluetooth.avrcpcontroller.BipEncoding;
33 import com.android.bluetooth.avrcpcontroller.BipImageDescriptor;
34 import com.android.bluetooth.avrcpcontroller.BipImageFormat;
35 import com.android.bluetooth.avrcpcontroller.BipImageProperties;
36 import com.android.bluetooth.avrcpcontroller.BipPixel;
37 
38 import org.junit.After;
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 
43 import java.io.ByteArrayInputStream;
44 import java.io.ByteArrayOutputStream;
45 import java.io.InputStream;
46 import java.util.Arrays;
47 
48 @RunWith(AndroidJUnit4.class)
49 public class CoverArtTest {
50     private Context mTargetContext;
51     private Resources mTestResources;
52 
53     private static final BipPixel PIXEL_THUMBNAIL = BipPixel.createFixed(200, 200);
54     private static final String IMAGE_HANDLE_1 = "0000001";
55 
56     private Bitmap m200by200Image = null;
57     private Bitmap m200by200ImageBlue = null;
58 
59     private Image mImage = null;
60     private Image mImage2 = null;
61 
62     @Before
setUp()63     public void setUp() throws Exception {
64         mTargetContext = InstrumentationRegistry.getTargetContext();
65         try {
66             mTestResources = mTargetContext.getPackageManager()
67                     .getResourcesForApplication("com.android.bluetooth.tests");
68         } catch (PackageManager.NameNotFoundException e) {
69             assertWithMessage("Setup Failure Unable to get resources" + e.toString()).fail();
70         }
71 
72         m200by200Image = loadImage(com.android.bluetooth.tests.R.raw.image_200_200);
73         m200by200ImageBlue = loadImage(com.android.bluetooth.tests.R.raw.image_200_200_blue);
74         mImage = new Image(null, m200by200Image);
75         mImage2 = new Image(null, m200by200ImageBlue);
76     }
77 
78     @After
tearDown()79     public void tearDown() throws Exception {
80         mImage2 = null;
81         mImage = null;
82         m200by200ImageBlue = null;
83         m200by200Image = null;
84         mTestResources = null;
85         mTargetContext = null;
86     }
87 
loadImage(int resId)88     private Bitmap loadImage(int resId) {
89         InputStream imageInputStream = mTestResources.openRawResource(resId);
90         return BitmapFactory.decodeStream(imageInputStream);
91     }
92 
toInputSteam(Bitmap bitmap)93     private InputStream toInputSteam(Bitmap bitmap) {
94         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
95         bitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream);
96         byte[] imageBytes = outputStream.toByteArray();
97         return new ByteArrayInputStream(imageBytes);
98     }
99 
toBitmap(byte[] imageBytes)100     private Bitmap toBitmap(byte[] imageBytes) {
101         ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
102         return BitmapFactory.decodeStream(inputStream);
103     }
104 
getDescriptor(int encoding, int width, int height)105     private BipImageDescriptor getDescriptor(int encoding, int width, int height) {
106         return new BipImageDescriptor.Builder()
107                 .setEncoding(encoding)
108                 .setFixedDimensions(width, height)
109                 .build();
110     }
111 
containsThumbnailFormat(BipImageProperties properties)112     private boolean containsThumbnailFormat(BipImageProperties properties) {
113         if (properties == null) return false;
114 
115         for (BipImageFormat format : properties.getNativeFormats()) {
116             BipEncoding encoding = format.getEncoding();
117             BipPixel pixel = format.getPixel();
118             if (encoding == null || pixel == null) continue;
119             if (encoding.getType() == BipEncoding.JPEG && PIXEL_THUMBNAIL.equals(pixel)) {
120                 return true;
121             }
122         }
123 
124         for (BipImageFormat format : properties.getVariantFormats()) {
125             BipEncoding encoding = format.getEncoding();
126             BipPixel pixel = format.getPixel();
127             if (encoding == null || pixel == null) continue;
128             if (encoding.getType() == BipEncoding.JPEG && PIXEL_THUMBNAIL.equals(pixel)) {
129                 return true;
130             }
131         }
132 
133         return false;
134     }
135 
isThumbnailFormat(Bitmap image)136     private boolean isThumbnailFormat(Bitmap image) {
137         if (image == null) return false;
138         return (200 == image.getHeight() && 200 == image.getWidth());
139     }
140 
141     /**
142      * Make sure you can create an image from an Image object
143      */
144     @Test
testCreateCoverArtFromImage()145     public void testCreateCoverArtFromImage() {
146         CoverArt artwork = new CoverArt(mImage);
147         assertThat(artwork.getImage()).isNotNull();
148     }
149 
150     /**
151      * Make sure you get an image hash from a valid image
152      */
153     @Test
testGetImageHash()154     public void testGetImageHash() {
155         CoverArt artwork = new CoverArt(mImage);
156         String hash = artwork.getImageHash();
157         assertThat(hash).isNotNull();
158     }
159 
160     /**
161      * Make sure you get the same image hash from several calls to the same object
162      */
163     @Test
testGetImageHashSameForMultipleCalls()164     public void testGetImageHashSameForMultipleCalls() {
165         CoverArt artwork = new CoverArt(mImage);
166         String hash = artwork.getImageHash();
167         assertThat(hash).isNotNull();
168         assertThat(artwork.getImageHash()).isEqualTo(hash); // extra call 1
169         assertThat(artwork.getImageHash()).isEqualTo(hash); // extra call 2
170     }
171 
172     /**
173      * Make sure you get the same image hash from separate objects created from the same image
174      */
175     @Test
testGetImageHashSameForSameImages()176     public void testGetImageHashSameForSameImages() {
177         CoverArt artwork = new CoverArt(mImage);
178         CoverArt artwork2 = new CoverArt(mImage);
179         String hash = artwork.getImageHash();
180         String hash2 = artwork2.getImageHash();
181 
182         assertThat(hash).isNotNull();
183         assertThat(hash2).isNotNull();
184         assertThat(hash).isEqualTo(hash2);
185     }
186 
187     /**
188      * Make sure you get different image hashes from separate objects created from different images
189      */
190     @Test
testGetImageHashDifferentForDifferentImages()191     public void testGetImageHashDifferentForDifferentImages() {
192         CoverArt artwork = new CoverArt(mImage);
193         CoverArt artwork2 = new CoverArt(mImage2);
194         String hash = artwork.getImageHash();
195         String hash2 = artwork2.getImageHash();
196 
197         assertThat(hash).isNotNull();
198         assertThat(hash2).isNotNull();
199         assertThat(hash).isNotEqualTo(hash2);
200     }
201 
202     /**
203      * Make sure you get an image when asking for the native image
204      */
205     @Test
testGetNativeImage()206     public void testGetNativeImage() {
207         CoverArt artwork = new CoverArt(mImage);
208         byte[] image = artwork.getImage();
209         assertThat(image).isNotNull();
210     }
211 
212     /**
213      * Make sure you getThumbnailImage returns an image as a 200 by 200 JPEG
214      */
215     @Test
testGetThumbnailImage()216     public void testGetThumbnailImage() {
217         CoverArt artwork = new CoverArt(mImage);
218         byte[] imageBytes = artwork.getThumbnail();
219         assertThat(imageBytes).isNotNull();
220         Bitmap image = toBitmap(imageBytes);
221         assertThat(isThumbnailFormat(image)).isTrue();
222     }
223 
224     /**
225      * Make sure you can set the image handle associated with this object
226      */
227     @Test
testGetAndSetImageHandle()228     public void testGetAndSetImageHandle() {
229         CoverArt artwork = new CoverArt(mImage);
230         assertThat(artwork.getImageHandle()).isNull();
231         artwork.setImageHandle(IMAGE_HANDLE_1);
232         assertThat(artwork.getImageHandle()).isEqualTo(IMAGE_HANDLE_1);
233     }
234 
235     /**
236      * Make sure a getImageProperties() yields a set of image properties. The thumbnail format
237      * MUST be contained in that set
238      */
239     @Test
testGetImageProperties()240     public void testGetImageProperties() {
241         CoverArt artwork = new CoverArt(mImage);
242         artwork.setImageHandle(IMAGE_HANDLE_1);
243         BipImageProperties properties = artwork.getImageProperties();
244         assertThat(properties).isNotNull();
245         assertThat(containsThumbnailFormat(properties)).isTrue();
246     }
247 
248     /**
249      * Make sure a getImage(<valid descriptor>) yield an image in the format you asked for
250      */
251     @Test
testGetImageWithValidDescriptor()252     public void testGetImageWithValidDescriptor() {
253         CoverArt artwork = new CoverArt(mImage);
254         BipImageDescriptor descriptor = getDescriptor(BipEncoding.JPEG, 200, 200);
255         byte[] image = artwork.getImage(descriptor);
256         assertThat(image).isNotNull();
257     }
258 
259     /**
260      * Make sure a getImage(<thumbnail descriptor>) yields the image in the thumbnail format
261      */
262     @Test
testGetImageWithThumbnailDescriptor()263     public void testGetImageWithThumbnailDescriptor() {
264         CoverArt artwork = new CoverArt(mImage);
265         BipImageDescriptor descriptor = getDescriptor(BipEncoding.JPEG, 200, 200);
266         byte[] imageBytes = artwork.getImage(descriptor);
267         assertThat(imageBytes).isNotNull();
268         Bitmap image = toBitmap(imageBytes);
269         assertThat(isThumbnailFormat(image)).isTrue();
270     }
271 
272     /**
273      * Make sure a getImage(<invalid descriptor>) yields a null
274      */
275     @Test
testGetImageWithInvalidDescriptor()276     public void testGetImageWithInvalidDescriptor() {
277         CoverArt artwork = new CoverArt(mImage);
278         BipImageDescriptor descriptor = getDescriptor(BipEncoding.BMP, 1200, 1200);
279         byte[] image = artwork.getImage(descriptor);
280         assertThat(image).isNull();
281     }
282 
283     /**
284      * Make sure a getImage(<null descriptor>) yields the native image
285      */
286     @Test
testGetImageWithoutDescriptor()287     public void testGetImageWithoutDescriptor() {
288         CoverArt artwork = new CoverArt(mImage);
289         byte[] image = artwork.getImage(null);
290         byte[] nativeImage = artwork.getImage();
291         assertThat(Arrays.equals(nativeImage, image)).isTrue();
292     }
293 
294     /**
295      * Make sure we can get a valid string representation of the CoverArt
296      */
297     @Test
testGetSize()298     public void testGetSize() {
299         CoverArt artwork = new CoverArt(mImage);
300         assertThat(artwork.size() > 0).isTrue();
301     }
302 
303     /**
304      * Make sure we can get a valid string representation of the CoverArt
305      */
306     @Test
testToString()307     public void testToString() {
308         CoverArt artwork = new CoverArt(mImage);
309         assertThat(artwork.toString()).isNotNull();
310     }
311 }
312