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.telecom.cts; 18 19 import android.content.Intent; 20 import android.os.Bundle; 21 import android.telecom.Connection; 22 import android.telecom.ConnectionRequest; 23 import android.telecom.ConnectionService; 24 import android.telecom.DisconnectCause; 25 import android.telecom.PhoneAccountHandle; 26 import android.telecom.TelecomManager; 27 import android.util.Log; 28 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.List; 32 import java.util.concurrent.CountDownLatch; 33 import java.util.concurrent.TimeUnit; 34 35 import static org.junit.Assert.assertTrue; 36 37 /** 38 * CTS test self-managed {@link ConnectionService} implementation. 39 */ 40 public class CtsSelfManagedConnectionService extends ConnectionService { 41 // Constants used to address into the mLocks array. 42 public static int CONNECTION_CREATED_LOCK = 0; 43 public static int CREATE_INCOMING_CONNECTION_FAILED_LOCK = 1; 44 public static int CREATE_OUTGOING_CONNECTION_FAILED_LOCK = 2; 45 public static int HANDOVER_FAILED_LOCK = 3; 46 public static int FOCUS_GAINED_LOCK = 4; 47 public static int FOCUS_LOST_LOCK = 5; 48 49 private static int NUM_LOCKS = FOCUS_LOST_LOCK + 1; 50 51 private static CtsSelfManagedConnectionService sConnectionService; 52 53 // Lock used to determine when binding to CS is complete. 54 private static CountDownLatch sBindingLock = new CountDownLatch(1); 55 56 private SelfManagedConnection.Listener mConnectionListener = 57 new SelfManagedConnection.Listener() { 58 @Override 59 void onDestroyed(SelfManagedConnection connection) { 60 mConnections.remove(connection); 61 } 62 }; 63 64 private CountDownLatch[] mLocks = new CountDownLatch[NUM_LOCKS]; 65 66 private Object mLock = new Object(); 67 private List<SelfManagedConnection> mConnections = new ArrayList<>(); 68 private TestUtils.InvokeCounter mOnCreateIncomingHandoverConnectionCounter = 69 new TestUtils.InvokeCounter("incomingHandoverConnection"); 70 private TestUtils.InvokeCounter mOnCreateOutgoingHandoverConnectionCounter = 71 new TestUtils.InvokeCounter("outgoingHandoverConnection"); 72 getConnectionService()73 public static CtsSelfManagedConnectionService getConnectionService() { 74 return sConnectionService; 75 } 76 CtsSelfManagedConnectionService()77 public CtsSelfManagedConnectionService() throws Exception { 78 super(); 79 sConnectionService = this; 80 Arrays.setAll(mLocks, i -> new CountDownLatch(1)); 81 82 // Inform anyone waiting on binding that we're bound. 83 sBindingLock.countDown(); 84 } 85 86 @Override onUnbind(Intent intent)87 public boolean onUnbind(Intent intent) { 88 sBindingLock = new CountDownLatch(1); 89 return super.onUnbind(intent); 90 } 91 92 @Override onCreateOutgoingConnection(PhoneAccountHandle connectionManagerAccount, final ConnectionRequest request)93 public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerAccount, 94 final ConnectionRequest request) { 95 96 return createSelfManagedConnection(request, false); 97 } 98 99 @Override onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)100 public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, 101 ConnectionRequest request) { 102 103 return createSelfManagedConnection(request, true); 104 } 105 106 @Override onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerHandle, ConnectionRequest request)107 public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerHandle, 108 ConnectionRequest request) { 109 mLocks[CREATE_INCOMING_CONNECTION_FAILED_LOCK].countDown(); 110 } 111 112 @Override onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerHandle, ConnectionRequest request)113 public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerHandle, 114 ConnectionRequest request) { 115 mLocks[CREATE_OUTGOING_CONNECTION_FAILED_LOCK].countDown(); 116 } 117 118 @Override onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle, ConnectionRequest request)119 public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle, 120 ConnectionRequest request) { 121 mOnCreateIncomingHandoverConnectionCounter.invoke(fromPhoneAccountHandle, request); 122 return createSelfManagedConnection(request, true /* incoming */); 123 } 124 125 @Override onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle, ConnectionRequest request)126 public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle, 127 ConnectionRequest request) { 128 mOnCreateOutgoingHandoverConnectionCounter.invoke(fromPhoneAccountHandle, request); 129 return createSelfManagedConnection(request, false /* incoming */); 130 } 131 132 @Override onHandoverFailed(ConnectionRequest request, int error)133 public void onHandoverFailed(ConnectionRequest request, int error) { 134 mLocks[HANDOVER_FAILED_LOCK].countDown(); 135 } 136 137 138 @Override onConnectionServiceFocusGained()139 public void onConnectionServiceFocusGained() { 140 mLocks[FOCUS_GAINED_LOCK].countDown(); 141 } 142 143 @Override onConnectionServiceFocusLost()144 public void onConnectionServiceFocusLost() { 145 mLocks[FOCUS_LOST_LOCK].countDown(); 146 connectionServiceFocusReleased(); 147 } 148 tearDown()149 public void tearDown() { 150 synchronized(mLock) { 151 if (mConnections != null && mConnections.size() > 0) { 152 mConnections.forEach(connection -> { 153 connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL)); 154 connection.destroy(); 155 } 156 ); 157 mConnections.clear(); 158 } 159 } 160 sBindingLock = new CountDownLatch(1); 161 } 162 createSelfManagedConnection(ConnectionRequest request, boolean isIncoming)163 private Connection createSelfManagedConnection(ConnectionRequest request, boolean isIncoming) { 164 SelfManagedConnection connection = new SelfManagedConnection(isIncoming, 165 mConnectionListener); 166 connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED); 167 connection.setConnectionCapabilities( 168 Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD); 169 connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED); 170 connection.setExtras(request.getExtras()); 171 172 Bundle moreExtras = new Bundle(); 173 moreExtras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, 174 request.getAccountHandle()); 175 connection.putExtras(moreExtras); 176 connection.setVideoState(request.getVideoState()); 177 178 if (!isIncoming) { 179 connection.setInitializing(); 180 } 181 synchronized(mLock) { 182 mConnections.add(connection); 183 } 184 mLocks[CONNECTION_CREATED_LOCK].countDown(); 185 return connection; 186 } 187 getConnections()188 public List<SelfManagedConnection> getConnections() { 189 synchronized(mLock) { 190 return new ArrayList<>(mConnections); 191 } 192 } 193 194 /** 195 * Waits on a lock for maximum of 5 seconds. 196 * 197 * @param lock one of the {@code *_LOCK} constants defined above. 198 * @return {@code true} if the lock was released within the time limit, {@code false} if the 199 * timeout expired without the lock being released. 200 */ waitForUpdate(int lock)201 public boolean waitForUpdate(int lock) { 202 mLocks[lock] = TestUtils.waitForLock(mLocks[lock]); 203 return mLocks[lock] != null; 204 } 205 206 /** 207 * Waits for the {@link ConnectionService} to be found. 208 * @return {@code true} if binding happened within the time limit, or {@code false} otherwise. 209 */ waitForBinding()210 public static boolean waitForBinding() { 211 return TestUtils.waitForLatchCountDown(sBindingLock); 212 } 213 getOnCreateIncomingHandoverConnectionCounter()214 public TestUtils.InvokeCounter getOnCreateIncomingHandoverConnectionCounter() { 215 return mOnCreateIncomingHandoverConnectionCounter; 216 } 217 getOnCreateOutgoingHandoverConnectionCounter()218 public TestUtils.InvokeCounter getOnCreateOutgoingHandoverConnectionCounter() { 219 return mOnCreateOutgoingHandoverConnectionCounter; 220 } 221 } 222