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