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