1 /* 2 * Copyright (C) 2019 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.os.Handler; 33 import android.os.HandlerThread; 34 import android.os.IBinder; 35 import android.os.RemoteException; 36 import android.platform.test.flag.junit.CheckFlagsRule; 37 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 38 import android.telephony.MbmsGroupCallSession; 39 import android.telephony.cts.embmstestapp.CtsGroupCallService; 40 import android.telephony.cts.embmstestapp.ICtsGroupCallMiddlewareControl; 41 import android.telephony.mbms.MbmsGroupCallSessionCallback; 42 43 import org.junit.After; 44 import org.junit.Before; 45 import org.junit.Rule; 46 47 import java.util.List; 48 import java.util.concurrent.BlockingQueue; 49 import java.util.concurrent.CountDownLatch; 50 import java.util.concurrent.Executor; 51 import java.util.concurrent.LinkedBlockingQueue; 52 import java.util.concurrent.TimeUnit; 53 import java.util.stream.Collectors; 54 55 public class MbmsGroupCallTestBase { 56 @Rule 57 public final CheckFlagsRule mCheckFlagsRule = 58 DeviceFlagsValueProvider.createCheckFlagsRule(); 59 60 protected static final int ASYNC_TIMEOUT = 10000; 61 62 protected static class TestCallback implements MbmsGroupCallSessionCallback { 63 private final BlockingQueue<SomeArgs> mErrorCalls = new LinkedBlockingQueue<>(); 64 private final BlockingQueue<SomeArgs> mOnAvailableSaisUpdatedCalls = 65 new LinkedBlockingQueue<>(); 66 private final BlockingQueue<SomeArgs> mOnServiceInterfaceAvailableCalls = 67 new LinkedBlockingQueue<>(); 68 private final BlockingQueue<SomeArgs> mMiddlewareReadyCalls = new LinkedBlockingQueue<>(); 69 private int mNumErrorCalls = 0; 70 71 @Override onError(int errorCode, @Nullable String message)72 public void onError(int errorCode, @Nullable String message) { 73 MbmsGroupCallSessionCallback.super.onError(errorCode, message); 74 mNumErrorCalls += 1; 75 SomeArgs args = SomeArgs.obtain(); 76 args.arg1 = errorCode; 77 args.arg2 = message; 78 mErrorCalls.add(args); 79 } 80 81 @Override onMiddlewareReady()82 public void onMiddlewareReady() { 83 MbmsGroupCallSessionCallback.super.onMiddlewareReady(); 84 mMiddlewareReadyCalls.add(SomeArgs.obtain()); 85 } 86 87 @Override onAvailableSaisUpdated(List<Integer> currentSais, List<List<Integer>> availableSais)88 public void onAvailableSaisUpdated(List<Integer> currentSais, 89 List<List<Integer>> availableSais) { 90 MbmsGroupCallSessionCallback.super.onAvailableSaisUpdated(currentSais, availableSais); 91 SomeArgs args = SomeArgs.obtain(); 92 args.arg1 = currentSais; 93 args.arg2 = availableSais; 94 mOnAvailableSaisUpdatedCalls.add(args); 95 } 96 97 @Override onServiceInterfaceAvailable(String interfaceName, int index)98 public void onServiceInterfaceAvailable(String interfaceName, int index) { 99 MbmsGroupCallSessionCallback.super.onServiceInterfaceAvailable(interfaceName, index); 100 SomeArgs args = SomeArgs.obtain(); 101 args.arg1 = interfaceName; 102 args.arg2 = index; 103 mOnServiceInterfaceAvailableCalls.add(args); 104 } 105 waitOnError()106 public SomeArgs waitOnError() { 107 try { 108 return mErrorCalls.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 109 } catch (InterruptedException e) { 110 return null; 111 } 112 } 113 waitOnAvailableSaisUpdatedCalls()114 public SomeArgs waitOnAvailableSaisUpdatedCalls() { 115 try { 116 return mOnAvailableSaisUpdatedCalls.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 117 } catch (InterruptedException e) { 118 return null; 119 } 120 } 121 waitOnServiceInterfaceAvailableCalls()122 public SomeArgs waitOnServiceInterfaceAvailableCalls() { 123 try { 124 return mOnServiceInterfaceAvailableCalls.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 125 } catch (InterruptedException e) { 126 return null; 127 } 128 } 129 waitOnMiddlewareReady()130 public boolean waitOnMiddlewareReady() { 131 try { 132 return mMiddlewareReadyCalls.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS) != null; 133 } catch (InterruptedException e) { 134 return false; 135 } 136 } 137 getNumErrorCalls()138 public int getNumErrorCalls() { 139 return mNumErrorCalls; 140 } 141 } 142 143 Context mContext; 144 HandlerThread mHandlerThread; 145 Executor mCallbackExecutor; 146 ICtsGroupCallMiddlewareControl mMiddlewareControl; 147 MbmsGroupCallSession mGroupCallSession; 148 TestCallback mCallback = new TestCallback(); 149 150 @Before setUp()151 public void setUp() throws Exception { 152 assumeTrue(MbmsUtil.hasMbmsFeature()); 153 154 mContext = getContext(); 155 mHandlerThread = new HandlerThread("EmbmsCtsTestWorker"); 156 mHandlerThread.start(); 157 mCallbackExecutor = (new Handler(mHandlerThread.getLooper()))::post; 158 mCallback = new TestCallback(); 159 getControlBinder(); 160 setupGroupCallSession(); 161 } 162 163 @After tearDown()164 public void tearDown() throws Exception { 165 if (mHandlerThread != null) { 166 mHandlerThread.quit(); 167 mHandlerThread = null; 168 } 169 if (mGroupCallSession != null) { 170 mGroupCallSession.close(); 171 mGroupCallSession = null; 172 } 173 if (mMiddlewareControl != null) { 174 mMiddlewareControl.reset(); 175 mMiddlewareControl = null; 176 } 177 } 178 setupGroupCallSession()179 private void setupGroupCallSession() throws Exception { 180 mGroupCallSession = MbmsGroupCallSession.create( 181 mContext, mCallbackExecutor, mCallback); 182 assertNotNull(mGroupCallSession); 183 assertTrue(mCallback.waitOnMiddlewareReady()); 184 assertEquals(0, mCallback.getNumErrorCalls()); 185 List initializeCall = (List) mMiddlewareControl.getGroupCallSessionCalls().get(0); 186 assertEquals(CtsGroupCallService.METHOD_INITIALIZE, initializeCall.get(0)); 187 } 188 getControlBinder()189 private void getControlBinder() throws InterruptedException { 190 Intent bindIntent = new Intent(CtsGroupCallService.CONTROL_INTERFACE_ACTION); 191 bindIntent.setComponent(CtsGroupCallService.CONTROL_INTERFACE_COMPONENT); 192 final CountDownLatch bindLatch = new CountDownLatch(1); 193 194 boolean success = mContext.bindService(bindIntent, new ServiceConnection() { 195 @Override 196 public void onServiceConnected(ComponentName name, IBinder service) { 197 mMiddlewareControl = ICtsGroupCallMiddlewareControl.Stub.asInterface(service); 198 bindLatch.countDown(); 199 } 200 201 @Override 202 public void onServiceDisconnected(ComponentName name) { 203 mMiddlewareControl = null; 204 } 205 }, Context.BIND_AUTO_CREATE); 206 if (!success) { 207 fail("Failed to get control interface -- bind error"); 208 } 209 bindLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 210 } 211 getMiddlewareCalls(String methodName)212 protected List<List<Object>> getMiddlewareCalls(String methodName) throws RemoteException { 213 return ((List<List<Object>>) mMiddlewareControl.getGroupCallSessionCalls()).stream() 214 .filter((elem) -> elem.get(0).equals(methodName)) 215 .collect(Collectors.toList()); 216 } 217 }