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 com.android.dialer.simulator.impl;
18 
19 import android.content.Context;
20 import android.support.annotation.NonNull;
21 import android.support.annotation.Nullable;
22 import android.telecom.Connection;
23 import android.telecom.DisconnectCause;
24 import com.android.dialer.common.Assert;
25 import com.android.dialer.common.LogUtil;
26 import com.android.dialer.common.concurrent.ThreadUtil;
27 import com.android.dialer.simulator.Simulator;
28 import com.android.dialer.simulator.Simulator.Event;
29 
30 /** Entry point in the simulator to create voice calls. */
31 final class SimulatorRttCall
32     implements SimulatorConnectionService.Listener, SimulatorConnection.Listener {
33 
34   @NonNull private final Context context;
35   @Nullable private String connectionTag;
36   private RttChatBot rttChatBot;
37 
SimulatorRttCall(@onNull Context context)38   SimulatorRttCall(@NonNull Context context) {
39     this.context = Assert.isNotNull(context);
40     SimulatorConnectionService.addListener(this);
41     SimulatorConnectionService.addListener(
42         new SimulatorConferenceCreator(context, Simulator.CONFERENCE_TYPE_GSM));
43   }
44 
addNewIncomingCall(boolean isSpam)45   void addNewIncomingCall(boolean isSpam) {
46     String callerId =
47         isSpam
48             ? "+1-661-778-3020" /* Blacklisted custom spam number */
49             : "+44 (0) 20 7031 3000" /* Google London office */;
50     connectionTag =
51         SimulatorSimCallManager.addNewIncomingCall(
52             context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT);
53   }
54 
addNewOutgoingCall()55   void addNewOutgoingCall() {
56     String callerId = "+55-31-2128-6800"; // Brazil office.
57     connectionTag =
58         SimulatorSimCallManager.addNewOutgoingCall(
59             context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT);
60   }
61 
addNewEmergencyCall()62   void addNewEmergencyCall() {
63     String callerId = "911";
64     connectionTag =
65         SimulatorSimCallManager.addNewIncomingCall(
66             context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT);
67   }
68 
69   @Override
onNewOutgoingConnection(@onNull SimulatorConnection connection)70   public void onNewOutgoingConnection(@NonNull SimulatorConnection connection) {
71     if (isMyConnection(connection)) {
72       LogUtil.i("SimulatorRttCall.onNewOutgoingConnection", "connection created");
73       handleNewConnection(connection);
74 
75       // Telecom will force the connection to switch to Dialing when we return it. Wait until after
76       // we're returned it before changing call state.
77       ThreadUtil.postOnUiThread(connection::setActive);
78     }
79   }
80 
81   @Override
onNewIncomingConnection(@onNull SimulatorConnection connection)82   public void onNewIncomingConnection(@NonNull SimulatorConnection connection) {
83     if (isMyConnection(connection)) {
84       LogUtil.i("SimulatorRttCall.onNewIncomingConnection", "connection created");
85       handleNewConnection(connection);
86     }
87   }
88 
89   @Override
onConference( @onNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2)90   public void onConference(
91       @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2) {}
92 
handleNewConnection(@onNull SimulatorConnection connection)93   private void handleNewConnection(@NonNull SimulatorConnection connection) {
94     connection.addListener(this);
95     connection.setConnectionProperties(
96         connection.getConnectionProperties() | Connection.PROPERTY_IS_RTT);
97   }
98 
isMyConnection(@onNull Connection connection)99   private boolean isMyConnection(@NonNull Connection connection) {
100     return connection.getExtras().getBoolean(connectionTag);
101   }
102 
103   @Override
onEvent(@onNull SimulatorConnection connection, @NonNull Event event)104   public void onEvent(@NonNull SimulatorConnection connection, @NonNull Event event) {
105     switch (event.type) {
106       case Event.NONE:
107         throw Assert.createIllegalStateFailException();
108       case Event.REJECT:
109         connection.setDisconnected(new DisconnectCause(DisconnectCause.REJECTED));
110         break;
111       case Event.HOLD:
112         connection.setOnHold();
113         break;
114       case Event.ANSWER:
115       case Event.UNHOLD:
116         connection.setActive();
117         break;
118       case Event.DISCONNECT:
119         rttChatBot.stop();
120         connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
121         break;
122       case Event.SESSION_MODIFY_REQUEST:
123         ThreadUtil.postDelayedOnUiThread(() -> connection.handleSessionModifyRequest(event), 2000);
124         break;
125       case Event.STATE_CHANGE:
126         if (Connection.stateToString(Connection.STATE_ACTIVE).equals(event.data2)) {
127           rttChatBot = new RttChatBot(connection.getRttTextStream());
128           rttChatBot.start();
129         }
130         break;
131       default:
132         LogUtil.i("SimulatorRttCall.onEvent", "unexpected event: " + event.type);
133         break;
134     }
135   }
136 }
137