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 17package androidx.media.test.client; 18 19import static org.junit.Assert.assertTrue; 20 21import android.os.Bundle; 22import android.os.Handler; 23import android.os.Looper; 24 25import androidx.core.util.ObjectsCompat; 26import androidx.media.DataSourceDesc; 27import androidx.media.MediaItem2; 28import androidx.media.MediaMetadata2; 29 30import java.io.FileDescriptor; 31import java.util.ArrayList; 32import java.util.List; 33import java.util.concurrent.CountDownLatch; 34import java.util.concurrent.TimeUnit; 35 36/** 37 * Utilities for tests. 38 */ 39public final class TestUtils { 40 private static final int WAIT_TIME_MS = 1000; 41 private static final int WAIT_SERVICE_TIME_MS = 5000; 42 43 // Temporaily commenting out, since we don't have the Mock services yet. 44// /** 45// * Finds the session with id in this test package. 46// * 47// * @param context 48// * @param id 49// * @return 50// */ 51// public static SessionToken2 getServiceToken(Context context, String id) { 52// switch (id) { 53// case MockMediaSessionService2.ID: 54// return new SessionToken2(context, new ComponentName( 55// context.getPackageName(), MockMediaSessionService2.class.getName())); 56// case MockMediaLibraryService2.ID: 57// return new SessionToken2(context, new ComponentName( 58// context.getPackageName(), MockMediaLibraryService2.class.getName())); 59// } 60// fail("Unknown id=" + id); 61// return null; 62// } 63 64 /** 65 * Compares contents of two bundles. 66 * 67 * @param a a bundle 68 * @param b another bundle 69 * @return {@code true} if two bundles are the same. {@code false} otherwise. This may be 70 * incorrect if any bundle contains a bundle. 71 */ 72 public static boolean equals(Bundle a, Bundle b) { 73 return contains(a, b) && contains(b, a); 74 } 75 76 /** 77 * Checks whether a Bundle contains another bundle. 78 * 79 * @param a a bundle 80 * @param b another bundle 81 * @return {@code true} if a contains b. {@code false} otherwise. This may be incorrect if any 82 * bundle contains a bundle. 83 */ 84 public static boolean contains(Bundle a, Bundle b) { 85 if (a == b) { 86 return true; 87 } 88 if (a == null || b == null) { 89 return b == null; 90 } 91 if (!a.keySet().containsAll(b.keySet())) { 92 return false; 93 } 94 for (String key : b.keySet()) { 95 if (!ObjectsCompat.equals(a.get(key), b.get(key))) { 96 return false; 97 } 98 } 99 return true; 100 } 101 102 /** 103 * Create a playlist for testing purpose 104 * <p> 105 * Caller's method name will be used for prefix of each media item's media id. 106 * 107 * @param size list size 108 * @return the newly created playlist 109 */ 110 public static List<MediaItem2> createPlaylist(int size) { 111 final List<MediaItem2> list = new ArrayList<>(); 112 String caller = Thread.currentThread().getStackTrace()[1].getMethodName(); 113 for (int i = 0; i < size; i++) { 114 list.add(new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE) 115 .setMediaId(caller + "_item_" + (size + 1)) 116 .setDataSourceDesc(createDSD()).build()); 117 } 118 return list; 119 } 120 121 /** 122 * Create a media item with the metadata for testing purpose. 123 * 124 * @return the newly created media item 125 * @see #createMetadata() 126 */ 127 public static MediaItem2 createMediaItemWithMetadata() { 128 return new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE) 129 .setMetadata(createMetadata()).setDataSourceDesc(createDSD()).build(); 130 } 131 132 /** 133 * Create a media metadata for testing purpose. 134 * <p> 135 * Caller's method name will be used for the media id. 136 * 137 * @return the newly created media item 138 */ 139 public static MediaMetadata2 createMetadata() { 140 String mediaId = Thread.currentThread().getStackTrace()[1].getMethodName(); 141 return new MediaMetadata2.Builder() 142 .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId).build(); 143 } 144 145 private static DataSourceDesc createDSD() { 146 return new DataSourceDesc.Builder().setDataSource(new FileDescriptor()).build(); 147 } 148 149 /** 150 * Create a bundle for testing purpose. 151 * 152 * @return the newly created bundle. 153 */ 154 public static Bundle createTestBundle() { 155 Bundle bundle = new Bundle(); 156 bundle.putString("test_key", "test_value"); 157 return bundle; 158 } 159 160 /** 161 * Handler that always waits until the Runnable finishes. 162 */ 163 public static class SyncHandler extends Handler { 164 public SyncHandler(Looper looper) { 165 super(looper); 166 } 167 168 public void postAndSync(final Runnable runnable) throws InterruptedException { 169 if (getLooper() == Looper.myLooper()) { 170 runnable.run(); 171 } else { 172 final CountDownLatch latch = new CountDownLatch(1); 173 post(new Runnable() { 174 @Override 175 public void run() { 176 runnable.run(); 177 latch.countDown(); 178 } 179 }); 180 assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS)); 181 } 182 } 183 } 184} 185