1 /* 2 * Copyright (C) 2017 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 android.telephony.embms.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 24 import android.content.BroadcastReceiver; 25 import android.content.ContentResolver; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.net.Uri; 30 import android.os.Bundle; 31 import android.os.Handler; 32 import android.telephony.MbmsDownloadSession; 33 import android.telephony.cts.embmstestapp.CtsDownloadService; 34 import android.telephony.mbms.DownloadRequest; 35 import android.telephony.mbms.MbmsDownloadReceiver; 36 import android.telephony.mbms.UriPathPair; 37 import android.telephony.mbms.vendor.VendorUtils; 38 39 import java.io.File; 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.Objects; 43 import java.util.concurrent.BlockingQueue; 44 import java.util.concurrent.LinkedBlockingQueue; 45 import java.util.concurrent.TimeUnit; 46 import java.util.stream.Collectors; 47 import org.junit.After; 48 import org.junit.Before; 49 import org.junit.Test; 50 51 public class MbmsDownloadReceiverTest extends MbmsDownloadTestBase { 52 private static final String CTS_BROADCAST_PERMISSION = 53 "android.telephony.embms.cts.permission.TEST_BROADCAST"; 54 private static final String TEST_SERVICE_ID = "service_id"; 55 56 public static final String APP_INTENT_ACTION = 57 "android.telephony.embms.cts.ACTION_TEST_DOWNLOAD_COMPLETE"; 58 59 public static class AppIntentCapture { 60 private final BlockingQueue<Intent> mReceivedIntent = new LinkedBlockingQueue<>(); 61 private final BroadcastReceiver mAppIntentReceiver = new BroadcastReceiver() { 62 @Override 63 public void onReceive(Context context, Intent intent) { 64 mReceivedIntent.add(intent); 65 } 66 }; 67 private Context mContext; 68 AppIntentCapture(Context context, Handler handler)69 public AppIntentCapture(Context context, Handler handler) { 70 mContext = context; 71 IntentFilter filter = new IntentFilter(APP_INTENT_ACTION); 72 mContext.registerReceiver(mAppIntentReceiver, filter, null, handler); 73 } 74 getIntent()75 public Intent getIntent() { 76 return getIntent(true); 77 } 78 getIntent(boolean unregister)79 public Intent getIntent(boolean unregister) { 80 try { 81 Intent result = mReceivedIntent.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 82 if (unregister) { 83 mContext.unregisterReceiver(mAppIntentReceiver); 84 } 85 return result; 86 } catch (InterruptedException e) { 87 fail("test was interrupted"); 88 return null; 89 } 90 } 91 getIntents(int numExpected)92 public List<Intent> getIntents(int numExpected) { 93 ArrayList<Intent> result = new ArrayList<>(numExpected); 94 for (int i = 0; i < numExpected; i++) { 95 result.add(getIntent(false)); 96 } 97 mContext.unregisterReceiver(mAppIntentReceiver); 98 return result; 99 } 100 } 101 102 private MbmsDownloadReceiver mReceiver; 103 private File tempFileRootDir; 104 private String tempFileRootDirPath; 105 private DownloadRequest testDownloadRequest; 106 107 @Before setUp()108 public void setUp() throws Exception { 109 super.setUp(); 110 testDownloadRequest = downloadRequestTemplate 111 .setAppIntent(new Intent(APP_INTENT_ACTION)) 112 .build(); 113 mReceiver = new MbmsDownloadReceiver(); 114 IntentFilter filter = new IntentFilter(); 115 filter.addAction(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL); 116 filter.addAction(VendorUtils.ACTION_CLEANUP); 117 filter.addAction(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 118 mContext.registerReceiver(mReceiver, filter); 119 tempFileRootDir = new File(mContext.getFilesDir(), "CtsTestDir"); 120 tempFileRootDir.mkdir(); 121 tempFileRootDirPath = tempFileRootDir.getCanonicalPath(); 122 try { 123 mDownloadSession.setTempFileRootDirectory(tempFileRootDir); 124 } catch (IllegalStateException e) { 125 tearDown(); 126 throw e; 127 } 128 } 129 130 @After tearDown()131 public void tearDown() throws Exception { 132 recursiveDelete(tempFileRootDir); 133 tempFileRootDir = null; 134 super.tearDown(); 135 } 136 137 @Test testMalformedIntents()138 public void testMalformedIntents() throws Exception { 139 Intent downloadCompleteIntent = new Intent(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL); 140 sendBroadcastAndValidate(downloadCompleteIntent, 141 MbmsDownloadReceiver.RESULT_MALFORMED_INTENT); 142 143 Intent fdRequestIntent = new Intent(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 144 sendBroadcastAndValidate(fdRequestIntent, 145 MbmsDownloadReceiver.RESULT_MALFORMED_INTENT); 146 147 Intent cleanupIntent = new Intent(VendorUtils.ACTION_CLEANUP); 148 sendBroadcastAndValidate(cleanupIntent, 149 MbmsDownloadReceiver.RESULT_MALFORMED_INTENT); 150 } 151 152 @Test testBadTempFileDirectory()153 public void testBadTempFileDirectory() throws Exception { 154 Intent cleanupIntent = new Intent(VendorUtils.ACTION_CLEANUP); 155 populateIntentWithCommonFields(cleanupIntent); 156 cleanupIntent.putParcelableArrayListExtra(VendorUtils.EXTRA_TEMP_FILES_IN_USE, 157 new ArrayList<>(0)); 158 cleanupIntent.putExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT, "this is not a directory path"); 159 sendBroadcastAndValidate(cleanupIntent, 160 MbmsDownloadReceiver.RESULT_BAD_TEMP_FILE_ROOT); 161 } 162 163 @Test testDownloadFailureIntent()164 public void testDownloadFailureIntent() throws Exception { 165 Intent intentForReceiverTest = new Intent(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL); 166 populateIntentWithCommonFields(intentForReceiverTest); 167 intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, 168 MbmsDownloadSession.RESULT_CANCELLED); 169 intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST, 170 testDownloadRequest); 171 172 AppIntentCapture intentCaptor = new AppIntentCapture(mContext, mHandler); 173 174 sendBroadcastAndValidate(intentForReceiverTest, MbmsDownloadReceiver.RESULT_OK); 175 Intent receivedIntent = intentCaptor.getIntent(); 176 177 assertEquals(MbmsDownloadSession.RESULT_CANCELLED, 178 receivedIntent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, -1)); 179 180 assertEquals(testDownloadRequest, 181 receivedIntent.getParcelableExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST)); 182 } 183 184 @Test testBadDownloadToken()185 public void testBadDownloadToken() { 186 // Set up a perfectly valid download completion intent, and expect it to fail because the 187 // download token hasn't been written. 188 Intent intentForReceiverTest = new Intent(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL); 189 populateIntentWithCommonFields(intentForReceiverTest); 190 intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, 191 MbmsDownloadSession.RESULT_SUCCESSFUL); 192 intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST, 193 testDownloadRequest); 194 intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO, 195 CtsDownloadService.FILE_INFO_1); 196 intentForReceiverTest.putExtra(VendorUtils.EXTRA_FINAL_URI, 197 Uri.fromFile(new File(new File(tempFileRootDir, TEST_SERVICE_ID), "file1"))); 198 199 sendBroadcastAndValidate(intentForReceiverTest, 200 MbmsDownloadReceiver.RESULT_MALFORMED_INTENT); 201 } 202 203 @Test testRequestNoFileDescriptors()204 public void testRequestNoFileDescriptors() throws Exception { 205 Intent fdRequestIntent = new Intent(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 206 populateIntentWithCommonFields(fdRequestIntent); 207 208 Bundle b = sendBroadcastAndValidate(fdRequestIntent, MbmsDownloadReceiver.RESULT_OK); 209 assertTrue(b == null || b.isEmpty()); 210 } 211 212 @Test testRequestNewFileDescriptors()213 public void testRequestNewFileDescriptors() throws Exception { 214 Intent fdRequestIntent = new Intent(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 215 populateIntentWithCommonFields(fdRequestIntent); 216 fdRequestIntent.putExtra(VendorUtils.EXTRA_FD_COUNT, 5); 217 218 Bundle result = sendBroadcastAndValidate(fdRequestIntent, MbmsDownloadReceiver.RESULT_OK); 219 List<UriPathPair> freeUris = result.getParcelableArrayList(VendorUtils.EXTRA_FREE_URI_LIST); 220 assertNotNull(freeUris); 221 assertEquals(5, freeUris.size()); 222 for (UriPathPair pathPair : freeUris) { 223 assertEquals(ContentResolver.SCHEME_CONTENT, pathPair.getContentUri().getScheme()); 224 assertEquals(ContentResolver.SCHEME_FILE, pathPair.getFilePathUri().getScheme()); 225 } 226 } 227 228 @Test testRequestRefreshedFileDescriptors()229 public void testRequestRefreshedFileDescriptors() throws Exception { 230 // Set up a few temp files that we can request again 231 Intent fdRequestIntent = new Intent(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 232 populateIntentWithCommonFields(fdRequestIntent); 233 fdRequestIntent.putExtra(VendorUtils.EXTRA_FD_COUNT, 2); 234 235 Bundle result = sendBroadcastAndValidate(fdRequestIntent, MbmsDownloadReceiver.RESULT_OK); 236 List<UriPathPair> freeUris = result.getParcelableArrayList(VendorUtils.EXTRA_FREE_URI_LIST); 237 238 Intent fdRefreshIntent = new Intent(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 239 populateIntentWithCommonFields(fdRefreshIntent); 240 fdRefreshIntent.putParcelableArrayListExtra(VendorUtils.EXTRA_PAUSED_LIST, 241 new ArrayList<>(freeUris.stream().map(UriPathPair::getFilePathUri) 242 .collect(Collectors.toList()))); 243 Bundle result2 = sendBroadcastAndValidate(fdRefreshIntent, MbmsDownloadReceiver.RESULT_OK); 244 List<UriPathPair> refreshUris = 245 result2.getParcelableArrayList(VendorUtils.EXTRA_PAUSED_URI_LIST); 246 assertEquals(freeUris.size(), refreshUris.size()); 247 for (UriPathPair pathPair : refreshUris) { 248 assertTrue(freeUris.stream() 249 .anyMatch((originalPair) -> 250 originalPair.getFilePathUri().equals(pathPair.getFilePathUri()))); 251 } 252 } 253 sendBroadcastAndValidate(Intent intent, int expectedCode)254 private Bundle sendBroadcastAndValidate(Intent intent, int expectedCode) { 255 BlockingQueue<Bundle> receivedExtras = new LinkedBlockingQueue<>(); 256 BlockingQueue<Integer> receivedCode = new LinkedBlockingQueue<>(); 257 mContext.sendOrderedBroadcast(intent, CTS_BROADCAST_PERMISSION, 258 new BroadcastReceiver() { 259 @Override 260 public void onReceive(Context context, Intent intent) { 261 receivedExtras.add(getResultExtras(true)); 262 receivedCode.add(getResultCode()); 263 } 264 }, mHandler, -1, null, null); 265 266 try { 267 assertEquals(expectedCode, 268 (int) receivedCode.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS)); 269 return receivedExtras.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 270 } catch (InterruptedException e) { 271 fail("Test interrupted"); 272 return null; 273 } 274 } 275 bundleEquals(Bundle a, Bundle b)276 private boolean bundleEquals(Bundle a, Bundle b) { 277 if (a == null && b == null) { 278 return true; 279 } 280 if (a == null || b == null) { 281 return false; 282 } 283 for (String aKey : a.keySet()) { 284 if (!Objects.equals(a.get(aKey), b.get(aKey))) { 285 return false; 286 } 287 } 288 289 for (String bKey : b.keySet()) { 290 if (!Objects.equals(b.get(bKey), a.get(bKey))) { 291 return false; 292 } 293 } 294 295 return true; 296 } 297 populateIntentWithCommonFields(Intent intent)298 private void populateIntentWithCommonFields(Intent intent) { 299 intent.putExtra(VendorUtils.EXTRA_SERVICE_ID, TEST_SERVICE_ID); 300 intent.putExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT, tempFileRootDirPath); 301 } 302 303 } 304