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