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 androidx.test.InstrumentationRegistry.getContext; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 import static org.junit.Assume.assumeTrue; 26 27 import android.annotation.Nullable; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.ServiceConnection; 32 import android.net.Uri; 33 import android.os.Bundle; 34 import android.os.Handler; 35 import android.os.HandlerThread; 36 import android.os.IBinder; 37 import android.os.RemoteException; 38 import android.platform.test.flag.junit.CheckFlagsRule; 39 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 40 import android.telephony.MbmsDownloadSession; 41 import android.telephony.cts.embmstestapp.CtsDownloadService; 42 import android.telephony.cts.embmstestapp.ICtsDownloadMiddlewareControl; 43 import android.telephony.mbms.DownloadRequest; 44 import android.telephony.mbms.FileServiceInfo; 45 import android.telephony.mbms.MbmsDownloadSessionCallback; 46 import android.util.Log; 47 48 import com.android.internal.os.SomeArgs; 49 50 import org.junit.After; 51 import org.junit.Before; 52 import org.junit.Rule; 53 54 import java.io.File; 55 import java.util.List; 56 import java.util.concurrent.BlockingQueue; 57 import java.util.concurrent.CountDownLatch; 58 import java.util.concurrent.Executor; 59 import java.util.concurrent.LinkedBlockingQueue; 60 import java.util.concurrent.TimeUnit; 61 import java.util.stream.Collectors; 62 63 public class MbmsDownloadTestBase { 64 @Rule 65 public final CheckFlagsRule mCheckFlagsRule = 66 DeviceFlagsValueProvider.createCheckFlagsRule(); 67 68 protected static final int ASYNC_TIMEOUT = 10000; 69 70 protected static class TestCallback extends MbmsDownloadSessionCallback { 71 private final BlockingQueue<SomeArgs> mErrorCalls = new LinkedBlockingQueue<>(); 72 private final BlockingQueue<SomeArgs> mFileServicesUpdatedCalls = 73 new LinkedBlockingQueue<>(); 74 private final BlockingQueue<SomeArgs> mMiddlewareReadyCalls = new LinkedBlockingQueue<>(); 75 private int mNumErrorCalls = 0; 76 77 @Override onError(int errorCode, @Nullable String message)78 public void onError(int errorCode, @Nullable String message) { 79 mNumErrorCalls += 1; 80 SomeArgs args = SomeArgs.obtain(); 81 args.arg1 = errorCode; 82 args.arg2 = message; 83 mErrorCalls.add(args); 84 Log.i(MbmsDownloadTestBase.class.getSimpleName(), 85 "Got error: " + errorCode + ": " + message); 86 } 87 88 @Override onFileServicesUpdated(List<FileServiceInfo> services)89 public void onFileServicesUpdated(List<FileServiceInfo> services) { 90 SomeArgs args = SomeArgs.obtain(); 91 args.arg1 = services; 92 mFileServicesUpdatedCalls.add(args); 93 } 94 95 @Override onMiddlewareReady()96 public void onMiddlewareReady() { 97 mMiddlewareReadyCalls.add(SomeArgs.obtain()); 98 } 99 waitOnError()100 public SomeArgs waitOnError() { 101 try { 102 return mErrorCalls.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 103 } catch (InterruptedException e) { 104 return null; 105 } 106 } 107 waitOnMiddlewareReady()108 public boolean waitOnMiddlewareReady() { 109 try { 110 return mMiddlewareReadyCalls.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS) != null; 111 } catch (InterruptedException e) { 112 return false; 113 } 114 } 115 waitOnFileServicesUpdated()116 public SomeArgs waitOnFileServicesUpdated() { 117 try { 118 return mFileServicesUpdatedCalls.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 119 } catch (InterruptedException e) { 120 return null; 121 } 122 } 123 getNumErrorCalls()124 public int getNumErrorCalls() { 125 return mNumErrorCalls; 126 } 127 } 128 129 DownloadRequest.Builder downloadRequestTemplate; 130 Uri destinationDirectoryUri; 131 132 Context mContext; 133 HandlerThread mHandlerThread; 134 Handler mHandler; 135 Executor mCallbackExecutor; 136 ICtsDownloadMiddlewareControl mMiddlewareControl; 137 MbmsDownloadSession mDownloadSession; 138 TestCallback mCallback = new TestCallback(); 139 140 @Before setUp()141 public void setUp() throws Exception { 142 assumeTrue(MbmsUtil.hasMbmsFeature()); 143 144 mContext = getContext(); 145 mHandlerThread = new HandlerThread("EmbmsCtsTestWorker"); 146 mHandlerThread.start(); 147 mHandler = new Handler(mHandlerThread.getLooper()); 148 mCallbackExecutor = mHandler::post; 149 mCallback = new TestCallback(); 150 151 File destinationDirectory = new File(mContext.getFilesDir(), "downloads"); 152 destinationDirectory.mkdirs(); 153 destinationDirectoryUri = Uri.fromFile(destinationDirectory); 154 downloadRequestTemplate = new DownloadRequest.Builder( 155 CtsDownloadService.SOURCE_URI_1, destinationDirectoryUri) 156 .setServiceInfo(CtsDownloadService.FILE_SERVICE_INFO); 157 getControlBinder(); 158 setupDownloadSession(); 159 } 160 161 @After tearDown()162 public void tearDown() throws Exception { 163 if (!MbmsUtil.hasMbmsFeature()) { 164 return; 165 } 166 167 mHandlerThread.quit(); 168 mDownloadSession.close(); 169 mMiddlewareControl.reset(); 170 } 171 setupDownloadSession()172 private void setupDownloadSession() throws Exception { 173 mDownloadSession = MbmsDownloadSession.create( 174 mContext, mCallbackExecutor, mCallback); 175 assertNotNull(mDownloadSession); 176 assertTrue(mCallback.waitOnMiddlewareReady()); 177 assertEquals(0, mCallback.getNumErrorCalls()); 178 Bundle initializeCall = mMiddlewareControl.getDownloadSessionCalls().get(0); 179 assertEquals(CtsDownloadService.METHOD_INITIALIZE, 180 initializeCall.getString(CtsDownloadService.METHOD_NAME)); 181 } 182 getControlBinder()183 private void getControlBinder() throws InterruptedException { 184 Intent bindIntent = new Intent(CtsDownloadService.CONTROL_INTERFACE_ACTION); 185 bindIntent.setComponent(CtsDownloadService.CONTROL_INTERFACE_COMPONENT); 186 final CountDownLatch bindLatch = new CountDownLatch(1); 187 188 boolean success = mContext.bindService(bindIntent, new ServiceConnection() { 189 @Override 190 public void onServiceConnected(ComponentName name, IBinder service) { 191 mMiddlewareControl = ICtsDownloadMiddlewareControl.Stub.asInterface(service); 192 bindLatch.countDown(); 193 } 194 195 @Override 196 public void onServiceDisconnected(ComponentName name) { 197 mMiddlewareControl = null; 198 } 199 }, Context.BIND_AUTO_CREATE); 200 if (!success) { 201 fail("Failed to get control interface -- bind error"); 202 } 203 bindLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 204 } 205 getMiddlewareCalls(String methodName)206 protected List<Bundle> getMiddlewareCalls(String methodName) throws RemoteException { 207 return (mMiddlewareControl.getDownloadSessionCalls()).stream() 208 .filter((elem) -> elem.getString(CtsDownloadService.METHOD_NAME).equals(methodName)) 209 .collect(Collectors.toList()); 210 } 211 recursiveDelete(File f)212 protected static void recursiveDelete(File f) { 213 if (f != null) { 214 if (f.isDirectory()) { 215 for (File f1 : f.listFiles()) { 216 recursiveDelete(f1); 217 } 218 } 219 f.delete(); 220 } 221 } 222 }