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.annotation.TargetApi; 20 import android.content.Context; 21 import android.support.annotation.NonNull; 22 import android.support.v4.os.BuildCompat; 23 import android.telecom.Connection; 24 import android.telecom.Connection.RttTextStream; 25 import android.telecom.ConnectionRequest; 26 import android.telecom.VideoProfile; 27 import com.android.dialer.common.Assert; 28 import com.android.dialer.common.LogUtil; 29 import com.android.dialer.simulator.Simulator; 30 import com.android.dialer.simulator.Simulator.Event; 31 import com.android.dialer.simulator.SimulatorComponent; 32 import com.android.dialer.simulator.SimulatorConnectionsBank; 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** Represents a single phone call on the device. */ 37 @TargetApi(28) 38 public final class SimulatorConnection extends Connection { 39 private final List<Listener> listeners = new ArrayList<>(); 40 private final List<Event> events = new ArrayList<>(); 41 private final SimulatorConnectionsBank simulatorConnectionsBank; 42 private int currentState = STATE_NEW; 43 private RttTextStream rttTextStream; 44 private RttChatBot rttChatBot; 45 SimulatorConnection(@onNull Context context, @NonNull ConnectionRequest request)46 SimulatorConnection(@NonNull Context context, @NonNull ConnectionRequest request) { 47 Assert.isNotNull(context); 48 Assert.isNotNull(request); 49 putExtras(request.getExtras()); 50 setConnectionCapabilities( 51 CAPABILITY_MUTE 52 | CAPABILITY_SUPPORT_HOLD 53 | CAPABILITY_HOLD 54 | CAPABILITY_CAN_UPGRADE_TO_VIDEO 55 | CAPABILITY_DISCONNECT_FROM_CONFERENCE); 56 57 if (request.getExtras() != null) { 58 if (!request.getExtras().getBoolean(Simulator.IS_VOLTE)) { 59 setConnectionCapabilities( 60 getConnectionCapabilities() | CAPABILITY_SEPARATE_FROM_CONFERENCE); 61 } 62 } 63 if (BuildCompat.isAtLeastP()) { 64 rttTextStream = request.getRttTextStream(); 65 } 66 setVideoProvider(new SimulatorVideoProvider(context, this)); 67 simulatorConnectionsBank = SimulatorComponent.get(context).getSimulatorConnectionsBank(); 68 } 69 addListener(@onNull Listener listener)70 public void addListener(@NonNull Listener listener) { 71 listeners.add(Assert.isNotNull(listener)); 72 } 73 removeListener(@onNull Listener listener)74 public void removeListener(@NonNull Listener listener) { 75 listeners.remove(Assert.isNotNull(listener)); 76 } 77 getRttTextStream()78 RttTextStream getRttTextStream() { 79 return rttTextStream; 80 } 81 82 @NonNull getEvents()83 public List<Event> getEvents() { 84 return events; 85 } 86 87 @Override onAnswer(int videoState)88 public void onAnswer(int videoState) { 89 LogUtil.enterBlock("SimulatorConnection.onAnswer"); 90 onEvent(new Event(Event.ANSWER, Integer.toString(videoState), null)); 91 } 92 93 @Override onReject()94 public void onReject() { 95 LogUtil.enterBlock("SimulatorConnection.onReject"); 96 simulatorConnectionsBank.remove(this); 97 onEvent(new Event(Event.REJECT)); 98 } 99 100 @Override onHold()101 public void onHold() { 102 LogUtil.enterBlock("SimulatorConnection.onHold"); 103 onEvent(new Event(Event.HOLD)); 104 } 105 106 @Override onUnhold()107 public void onUnhold() { 108 LogUtil.enterBlock("SimulatorConnection.onUnhold"); 109 onEvent(new Event(Event.UNHOLD)); 110 } 111 112 @Override onDisconnect()113 public void onDisconnect() { 114 LogUtil.enterBlock("SimulatorConnection.onDisconnect"); 115 simulatorConnectionsBank.remove(this); 116 onEvent(new Event(Event.DISCONNECT)); 117 rttTextStream = null; 118 if (rttChatBot != null) { 119 rttChatBot.stop(); 120 rttChatBot = null; 121 } 122 } 123 124 @Override onStateChanged(int newState)125 public void onStateChanged(int newState) { 126 LogUtil.i( 127 "SimulatorConnection.onStateChanged", 128 "%s -> %s", 129 stateToString(currentState), 130 stateToString(newState)); 131 int oldState = currentState; 132 currentState = newState; 133 onEvent(new Event(Event.STATE_CHANGE, stateToString(oldState), stateToString(newState))); 134 } 135 136 @Override onPlayDtmfTone(char c)137 public void onPlayDtmfTone(char c) { 138 LogUtil.enterBlock("SimulatorConnection.onPlayDtmfTone"); 139 onEvent(new Event(Event.DTMF, Character.toString(c), null)); 140 } 141 142 @Override onStartRtt(@onNull RttTextStream rttTextStream)143 public void onStartRtt(@NonNull RttTextStream rttTextStream) { 144 LogUtil.enterBlock("SimulatorConnection.onStartRtt"); 145 if (this.rttTextStream != null || rttChatBot != null) { 146 LogUtil.e("SimulatorConnection.onStartRtt", "rttTextStream or rttChatBot is not null!"); 147 } 148 this.rttTextStream = rttTextStream; 149 rttChatBot = new RttChatBot(rttTextStream); 150 rttChatBot.start(); 151 onEvent(new Event(Event.START_RTT)); 152 } 153 154 @Override onStopRtt()155 public void onStopRtt() { 156 LogUtil.enterBlock("SimulatorConnection.onStopRtt"); 157 rttChatBot.stop(); 158 rttChatBot = null; 159 rttTextStream = null; 160 onEvent(new Event(Event.STOP_RTT)); 161 } 162 163 @Override handleRttUpgradeResponse(RttTextStream rttTextStream)164 public void handleRttUpgradeResponse(RttTextStream rttTextStream) { 165 LogUtil.enterBlock("SimulatorConnection.handleRttUpgradeResponse"); 166 onEvent(new Event(Event.HANDLE_RTT_UPGRADE_RESPONSE)); 167 } 168 onEvent(@onNull Event event)169 void onEvent(@NonNull Event event) { 170 events.add(Assert.isNotNull(event)); 171 for (Listener listener : new ArrayList<>(listeners)) { 172 listener.onEvent(this, event); 173 } 174 } 175 handleSessionModifyRequest(@onNull Event event)176 void handleSessionModifyRequest(@NonNull Event event) { 177 VideoProfile fromProfile = new VideoProfile(Integer.parseInt(event.data1)); 178 VideoProfile toProfile = new VideoProfile(Integer.parseInt(event.data2)); 179 setVideoState(toProfile.getVideoState()); 180 getVideoProvider() 181 .receiveSessionModifyResponse( 182 Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS, fromProfile, toProfile); 183 } 184 185 /** Callback for when a new event arrives. */ 186 public interface Listener { onEvent(@onNull SimulatorConnection connection, @NonNull Event event)187 void onEvent(@NonNull SimulatorConnection connection, @NonNull Event event); 188 } 189 } 190