Home | History | Annotate | Download | only in cts
      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 
     73     public static CtsSelfManagedConnectionService getConnectionService() {
     74         return sConnectionService;
     75     }
     76 
     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
     87     public boolean onUnbind(Intent intent) {
     88         sBindingLock = new CountDownLatch(1);
     89         return super.onUnbind(intent);
     90     }
     91 
     92     @Override
     93     public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerAccount,
     94             final ConnectionRequest request) {
     95 
     96         return createSelfManagedConnection(request, false);
     97     }
     98 
     99     @Override
    100     public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
    101             ConnectionRequest request) {
    102 
    103         return createSelfManagedConnection(request, true);
    104     }
    105 
    106     @Override
    107     public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerHandle,
    108                                                  ConnectionRequest request) {
    109         mLocks[CREATE_INCOMING_CONNECTION_FAILED_LOCK].countDown();
    110     }
    111 
    112     @Override
    113     public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerHandle,
    114                                                  ConnectionRequest request) {
    115         mLocks[CREATE_OUTGOING_CONNECTION_FAILED_LOCK].countDown();
    116     }
    117 
    118     @Override
    119     public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
    120             ConnectionRequest request) {
    121         mOnCreateIncomingHandoverConnectionCounter.invoke(fromPhoneAccountHandle, request);
    122         return createSelfManagedConnection(request, true /* incoming */);
    123     }
    124 
    125     @Override
    126     public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
    127             ConnectionRequest request) {
    128         mOnCreateOutgoingHandoverConnectionCounter.invoke(fromPhoneAccountHandle, request);
    129         return createSelfManagedConnection(request, false /* incoming */);
    130     }
    131 
    132     @Override
    133     public void onHandoverFailed(ConnectionRequest request, int error) {
    134         mLocks[HANDOVER_FAILED_LOCK].countDown();
    135     }
    136 
    137 
    138     @Override
    139     public void onConnectionServiceFocusGained() {
    140         mLocks[FOCUS_GAINED_LOCK].countDown();
    141     }
    142 
    143     @Override
    144     public void onConnectionServiceFocusLost() {
    145         mLocks[FOCUS_LOST_LOCK].countDown();
    146         connectionServiceFocusReleased();
    147     }
    148 
    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 
    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 
    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      */
    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      */
    210     public static boolean waitForBinding() {
    211         return TestUtils.waitForLatchCountDown(sBindingLock);
    212     }
    213 
    214     public TestUtils.InvokeCounter getOnCreateIncomingHandoverConnectionCounter() {
    215         return mOnCreateIncomingHandoverConnectionCounter;
    216     }
    217 
    218     public TestUtils.InvokeCounter getOnCreateOutgoingHandoverConnectionCounter() {
    219         return mOnCreateOutgoingHandoverConnectionCounter;
    220     }
    221 }
    222