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