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