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