summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/com/android/dialer/simulator/impl/RttChatBot.java1
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConnection.java29
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorRttCall.java12
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java2
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java14
-rw-r--r--java/com/android/incallui/InCallActivity.java3
-rw-r--r--java/com/android/incallui/RttCallPresenter.java131
-rw-r--r--java/com/android/incallui/call/DialerCall.java9
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatAdapter.java12
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatFragment.java21
-rw-r--r--java/com/android/incallui/rtt/protocol/RttCallScreen.java2
-rw-r--r--java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java6
12 files changed, 218 insertions, 24 deletions
diff --git a/java/com/android/dialer/simulator/impl/RttChatBot.java b/java/com/android/dialer/simulator/impl/RttChatBot.java
index 5a7769f3e..b2860e387 100644
--- a/java/com/android/dialer/simulator/impl/RttChatBot.java
+++ b/java/com/android/dialer/simulator/impl/RttChatBot.java
@@ -97,7 +97,6 @@ public class RttChatBot {
break;
case SEND_MESSAGE:
String message = (String) msg.obj;
- LogUtil.w("test", "type: %s, to stream: %s", message, rttTextStream);
try {
rttTextStream.write(message);
} catch (IOException e) {
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConnection.java b/java/com/android/dialer/simulator/impl/SimulatorConnection.java
index c832a5051..3aa3296ea 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorConnection.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorConnection.java
@@ -16,9 +16,12 @@
package com.android.dialer.simulator.impl;
+import android.annotation.TargetApi;
import android.content.Context;
import android.support.annotation.NonNull;
+import android.support.v4.os.BuildCompat;
import android.telecom.Connection;
+import android.telecom.Connection.RttTextStream;
import android.telecom.ConnectionRequest;
import android.telecom.VideoProfile;
import com.android.dialer.common.Assert;
@@ -31,11 +34,14 @@ import java.util.ArrayList;
import java.util.List;
/** Represents a single phone call on the device. */
+@TargetApi(28)
public final class SimulatorConnection extends Connection {
private final List<Listener> listeners = new ArrayList<>();
private final List<Event> events = new ArrayList<>();
private final SimulatorConnectionsBank simulatorConnectionsBank;
private int currentState = STATE_NEW;
+ private RttTextStream rttTextStream;
+ private RttChatBot rttChatBot;
SimulatorConnection(@NonNull Context context, @NonNull ConnectionRequest request) {
Assert.isNotNull(context);
@@ -54,6 +60,9 @@ public final class SimulatorConnection extends Connection {
getConnectionCapabilities() | CAPABILITY_SEPARATE_FROM_CONFERENCE);
}
}
+ if (BuildCompat.isAtLeastP()) {
+ rttTextStream = request.getRttTextStream();
+ }
setVideoProvider(new SimulatorVideoProvider(context, this));
simulatorConnectionsBank = SimulatorComponent.get(context).getSimulatorConnectionsBank();
}
@@ -66,6 +75,10 @@ public final class SimulatorConnection extends Connection {
listeners.remove(Assert.isNotNull(listener));
}
+ RttTextStream getRttTextStream() {
+ return rttTextStream;
+ }
+
@NonNull
public List<Event> getEvents() {
return events;
@@ -101,6 +114,11 @@ public final class SimulatorConnection extends Connection {
LogUtil.enterBlock("SimulatorConnection.onDisconnect");
simulatorConnectionsBank.remove(this);
onEvent(new Event(Event.DISCONNECT));
+ rttTextStream = null;
+ if (rttChatBot != null) {
+ rttChatBot.stop();
+ rttChatBot = null;
+ }
}
@Override
@@ -124,12 +142,21 @@ public final class SimulatorConnection extends Connection {
@Override
public void onStartRtt(@NonNull RttTextStream rttTextStream) {
LogUtil.enterBlock("SimulatorConnection.onStartRtt");
+ if (this.rttTextStream != null || rttChatBot != null) {
+ LogUtil.e("SimulatorConnection.onStartRtt", "rttTextStream or rttChatBot is not null!");
+ }
+ this.rttTextStream = rttTextStream;
+ rttChatBot = new RttChatBot(rttTextStream);
+ rttChatBot.start();
onEvent(new Event(Event.START_RTT));
}
@Override
public void onStopRtt() {
LogUtil.enterBlock("SimulatorConnection.onStopRtt");
+ rttChatBot.stop();
+ rttChatBot = null;
+ rttTextStream = null;
onEvent(new Event(Event.STOP_RTT));
}
@@ -159,6 +186,4 @@ public final class SimulatorConnection extends Connection {
public interface Listener {
void onEvent(@NonNull SimulatorConnection connection, @NonNull Event event);
}
-
-
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorRttCall.java b/java/com/android/dialer/simulator/impl/SimulatorRttCall.java
index 7b0066719..352b9e4ef 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorRttCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorRttCall.java
@@ -34,6 +34,7 @@ final class SimulatorRttCall
@NonNull private final Context context;
@Nullable private String connectionTag;
+ private RttChatBot rttChatBot;
static ActionProvider getActionProvider(@NonNull Context context) {
return new SimulatorSubMenu(context)
@@ -112,24 +113,29 @@ final class SimulatorRttCall
switch (event.type) {
case Event.NONE:
throw Assert.createIllegalStateFailException();
- case Event.ANSWER:
- connection.setActive();
- break;
case Event.REJECT:
connection.setDisconnected(new DisconnectCause(DisconnectCause.REJECTED));
break;
case Event.HOLD:
connection.setOnHold();
break;
+ case Event.ANSWER:
case Event.UNHOLD:
connection.setActive();
break;
case Event.DISCONNECT:
+ rttChatBot.stop();
connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
break;
case Event.SESSION_MODIFY_REQUEST:
ThreadUtil.postDelayedOnUiThread(() -> connection.handleSessionModifyRequest(event), 2000);
break;
+ case Event.STATE_CHANGE:
+ if (Connection.stateToString(Connection.STATE_ACTIVE).equals(event.data2)) {
+ rttChatBot = new RttChatBot(connection.getRttTextStream());
+ rttChatBot.start();
+ }
+ break;
default:
LogUtil.i("SimulatorRttCall.onEvent", "unexpected event: " + event.type);
break;
diff --git a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
index d51e06816..c56afb21f 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
@@ -115,7 +115,7 @@ public class SimulatorSimCallManager {
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
callType == CALL_TYPE_VIDEO
? getVideoProviderHandle(context)
- : getSystemPhoneAccountHandle(context));
+ : getSimCallManagerHandle(context));
if (callType == CALL_TYPE_RTT) {
outgoingCallExtras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true);
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
index d4c7ee458..e59cddd51 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
@@ -22,6 +22,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.telecom.Connection;
+import android.telecom.Connection.RttModifyStatus;
import android.telecom.DisconnectCause;
import android.view.ActionProvider;
import com.android.dialer.common.Assert;
@@ -223,15 +224,13 @@ final class SimulatorVoiceCall
switch (event.type) {
case Event.NONE:
throw Assert.createIllegalStateFailException();
- case Event.ANSWER:
- connection.setActive();
- break;
case Event.REJECT:
connection.setDisconnected(new DisconnectCause(DisconnectCause.REJECTED));
break;
case Event.HOLD:
connection.setOnHold();
break;
+ case Event.ANSWER:
case Event.UNHOLD:
connection.setActive();
break;
@@ -244,6 +243,15 @@ final class SimulatorVoiceCall
case Event.SESSION_MODIFY_REQUEST:
ThreadUtil.postDelayedOnUiThread(() -> connection.handleSessionModifyRequest(event), 2000);
break;
+ case Event.START_RTT:
+ // TODO(wangqi): Add random accept/decline.
+ boolean accept = true;
+ if (accept) {
+ connection.sendRttInitiationSuccess();
+ } else {
+ connection.sendRttInitiationFailure(RttModifyStatus.SESSION_MODIFY_REQUEST_FAIL);
+ }
+ break;
default:
LogUtil.i("SimulatorVoiceCall.onEvent", "unexpected event: " + event.type);
break;
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index 67f5cfe4f..3fc7f6c76 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -182,6 +182,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
didShowAnswerScreen = bundle.getBoolean(KeysForSavedInstance.DID_SHOW_ANSWER_SCREEN);
didShowInCallScreen = bundle.getBoolean(KeysForSavedInstance.DID_SHOW_IN_CALL_SCREEN);
didShowVideoCallScreen = bundle.getBoolean(KeysForSavedInstance.DID_SHOW_VIDEO_CALL_SCREEN);
+ didShowRttCallScreen = bundle.getBoolean(KeysForSavedInstance.DID_SHOW_RTT_CALL_SCREEN);
}
setWindowFlags();
@@ -387,6 +388,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
out.putBoolean(KeysForSavedInstance.DID_SHOW_ANSWER_SCREEN, didShowAnswerScreen);
out.putBoolean(KeysForSavedInstance.DID_SHOW_IN_CALL_SCREEN, didShowInCallScreen);
out.putBoolean(KeysForSavedInstance.DID_SHOW_VIDEO_CALL_SCREEN, didShowVideoCallScreen);
+ out.putBoolean(KeysForSavedInstance.DID_SHOW_RTT_CALL_SCREEN, didShowRttCallScreen);
super.onSaveInstanceState(out);
isVisible = false;
@@ -1593,6 +1595,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
static final String DID_SHOW_ANSWER_SCREEN = "did_show_answer_screen";
static final String DID_SHOW_IN_CALL_SCREEN = "did_show_in_call_screen";
static final String DID_SHOW_VIDEO_CALL_SCREEN = "did_show_video_call_screen";
+ static final String DID_SHOW_RTT_CALL_SCREEN = "did_show_rtt_call_screen";
}
/** Request codes for pending intents. */
diff --git a/java/com/android/incallui/RttCallPresenter.java b/java/com/android/incallui/RttCallPresenter.java
index b90d56b36..939c9d00b 100644
--- a/java/com/android/incallui/RttCallPresenter.java
+++ b/java/com/android/incallui/RttCallPresenter.java
@@ -16,28 +16,145 @@
package com.android.incallui;
-import android.content.Context;
+import android.annotation.TargetApi;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.telecom.Call.RttCall;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.incallui.InCallPresenter.InCallState;
+import com.android.incallui.InCallPresenter.InCallStateListener;
+import com.android.incallui.call.CallList;
+import com.android.incallui.call.DialerCall;
import com.android.incallui.rtt.protocol.RttCallScreen;
import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
+import java.io.IOException;
/**
* Logic related to the {@link RttCallScreen} and for managing changes to the RTT calling surfaces
* based on other user interface events and incoming events.
*/
-public class RttCallPresenter implements RttCallScreenDelegate {
+@TargetApi(28)
+public class RttCallPresenter implements RttCallScreenDelegate, InCallStateListener {
- private Context appContext;
private RttCallScreen rttCallScreen;
+ private RttCall rttCall;
+ private HandlerThread handlerThread;
+ private RemoteMessageHandler remoteMessageHandler;
@Override
- public void initRttCallScreenDelegate(Context context, RttCallScreen rttCallScreen) {
- this.appContext = context.getApplicationContext();
+ public void initRttCallScreenDelegate(RttCallScreen rttCallScreen) {
this.rttCallScreen = rttCallScreen;
}
@Override
- public void onRttCallScreenUiReady() {}
+ public void onLocalMessage(String message) {
+ if (rttCall == null) {
+ LogUtil.w("RttCallPresenter.onLocalMessage", "Rtt Call is not started yet");
+ return;
+ }
+ remoteMessageHandler.writeMessage(message);
+ }
+
+ @Override
+ public void onRttCallScreenUiReady() {
+ LogUtil.enterBlock("RttCallPresenter.onRttCallScreenUiReady");
+ InCallPresenter.getInstance().addListener(this);
+ startListenOnRemoteMessage();
+ }
+
+ @Override
+ public void onRttCallScreenUiUnready() {
+ LogUtil.enterBlock("RttCallPresenter.onRttCallScreenUiUnready");
+ InCallPresenter.getInstance().removeListener(this);
+ stopListenOnRemoteMessage();
+ }
@Override
- public void onRttCallScreenUiUnready() {}
+ public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
+ LogUtil.enterBlock("RttCallPresenter.onStateChange");
+ if (newState == InCallState.INCALL) {
+ startListenOnRemoteMessage();
+ }
+ }
+
+ private void startListenOnRemoteMessage() {
+ DialerCall call = CallList.getInstance().getActiveCall();
+ if (call == null) {
+ LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "call is active yet");
+ return;
+ }
+ rttCall = call.getRttCall();
+ if (rttCall == null) {
+ LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "RTT Call is not started yet");
+ return;
+ }
+ if (handlerThread != null && handlerThread.isAlive()) {
+ LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "already running");
+ return;
+ }
+ handlerThread = new HandlerThread("RttCallRemoteMessageHandler");
+ handlerThread.start();
+ remoteMessageHandler =
+ new RemoteMessageHandler(handlerThread.getLooper(), rttCall, rttCallScreen);
+ remoteMessageHandler.start();
+ }
+
+ private void stopListenOnRemoteMessage() {
+ if (handlerThread != null && handlerThread.isAlive()) {
+ handlerThread.quit();
+ }
+ }
+
+ private static class RemoteMessageHandler extends Handler {
+ private static final int START = 1;
+ private static final int READ_MESSAGE = 2;
+ private static final int WRITE_MESSAGE = 3;
+
+ private final RttCall rttCall;
+ private final RttCallScreen rttCallScreen;
+
+ RemoteMessageHandler(Looper looper, RttCall rttCall, RttCallScreen rttCallScreen) {
+ super(looper);
+ this.rttCall = rttCall;
+ this.rttCallScreen = rttCallScreen;
+ }
+
+ @Override
+ public void handleMessage(android.os.Message msg) {
+ switch (msg.what) {
+ case START:
+ sendEmptyMessage(READ_MESSAGE);
+ break;
+ case READ_MESSAGE:
+ try {
+ final String message = rttCall.readImmediately();
+ if (message != null) {
+ ThreadUtil.postOnUiThread(() -> rttCallScreen.onRemoteMessage(message));
+ }
+ } catch (IOException e) {
+ LogUtil.e("RttCallPresenter.RemoteMessageHandler.handleMessage", "read message", e);
+ }
+ sendEmptyMessageDelayed(READ_MESSAGE, 200);
+ break;
+ case WRITE_MESSAGE:
+ try {
+ rttCall.write((String) msg.obj);
+ } catch (IOException e) {
+ LogUtil.e("RttCallPresenter.RemoteMessageHandler.handleMessage", "write message", e);
+ }
+ break;
+ default: // fall out
+ }
+ }
+
+ void start() {
+ sendEmptyMessage(START);
+ }
+
+ void writeMessage(String message) {
+ sendMessage(obtainMessage(WRITE_MESSAGE, message));
+ }
+ }
}
diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java
index 378806183..90a01401c 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -939,6 +939,14 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
}
}
+ @TargetApi(28)
+ public RttCall getRttCall() {
+ if (!isRttCall()) {
+ return null;
+ }
+ return getTelecomCall().getRttCall();
+ }
+
public boolean hasReceivedVideoUpgradeRequest() {
return VideoUtils.hasReceivedVideoUpgradeRequest(getVideoTech().getSessionModificationState());
}
@@ -948,7 +956,6 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
}
public boolean hasSentRttUpgradeRequest() {
- // TODO(wangqi): Implement this.
return false;
}
diff --git a/java/com/android/incallui/rtt/impl/RttChatAdapter.java b/java/com/android/incallui/rtt/impl/RttChatAdapter.java
index 1ea7f31b1..69837188a 100644
--- a/java/com/android/incallui/rtt/impl/RttChatAdapter.java
+++ b/java/com/android/incallui/rtt/impl/RttChatAdapter.java
@@ -110,7 +110,17 @@ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolde
notifyItemInserted(lastIndexOfLocalMessage);
} else {
rttChatMessage.append(newMessage);
- notifyItemChanged(lastIndexOfLocalMessage);
+ // Clear empty message bubble.
+ if (TextUtils.isEmpty(rttChatMessage.getContent())) {
+ rttMessages.remove(lastIndexOfLocalMessage);
+ notifyItemRemoved(lastIndexOfLocalMessage);
+ if (lastIndexOfRemoteMessage > lastIndexOfLocalMessage) {
+ lastIndexOfRemoteMessage -= 1;
+ }
+ lastIndexOfLocalMessage = -1;
+ } else {
+ notifyItemChanged(lastIndexOfLocalMessage);
+ }
}
}
diff --git a/java/com/android/incallui/rtt/impl/RttChatFragment.java b/java/com/android/incallui/rtt/impl/RttChatFragment.java
index c7ee2ff67..ba99b2bf6 100644
--- a/java/com/android/incallui/rtt/impl/RttChatFragment.java
+++ b/java/com/android/incallui/rtt/impl/RttChatFragment.java
@@ -132,7 +132,7 @@ public class RttChatFragment extends Fragment
FragmentUtils.getParentUnsafe(this, RttCallScreenDelegateFactory.class)
.newRttCallScreenDelegate(this);
- rttCallScreenDelegate.initRttCallScreenDelegate(getContext(), this);
+ rttCallScreenDelegate.initRttCallScreenDelegate(this);
inCallScreenDelegate.onInCallScreenDelegateInit(this);
inCallScreenDelegate.onInCallScreenReady();
@@ -193,7 +193,24 @@ public class RttChatFragment extends Fragment
if (isClearingInput) {
return;
}
- adapter.addLocalMessage(RttChatMessage.getChangedString(s, start, before, count));
+ String messageToAppend = RttChatMessage.getChangedString(s, start, before, count);
+ if (!TextUtils.isEmpty(messageToAppend)) {
+ adapter.addLocalMessage(messageToAppend);
+ rttCallScreenDelegate.onLocalMessage(messageToAppend);
+ }
+ }
+
+ @Override
+ public void onRemoteMessage(String message) {
+ adapter.addRemoteMessage(message);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ LogUtil.enterBlock("RttChatFragment.onDestroyView");
+ inCallButtonUiDelegate.onInCallButtonUiUnready();
+ inCallScreenDelegate.onInCallScreenUnready();
}
@Override
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreen.java b/java/com/android/incallui/rtt/protocol/RttCallScreen.java
index afacbae48..916dfb84d 100644
--- a/java/com/android/incallui/rtt/protocol/RttCallScreen.java
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreen.java
@@ -25,6 +25,8 @@ public interface RttCallScreen {
void onRttScreenStop();
+ void onRemoteMessage(String message);
+
Fragment getRttCallScreenFragment();
String getCallId();
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
index e29c43d70..8c484a844 100644
--- a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
@@ -16,14 +16,14 @@
package com.android.incallui.rtt.protocol;
-import android.content.Context;
-
/** Callbacks from the module out to the container. */
public interface RttCallScreenDelegate {
- void initRttCallScreenDelegate(Context context, RttCallScreen rttCallScreen);
+ void initRttCallScreenDelegate(RttCallScreen rttCallScreen);
void onRttCallScreenUiReady();
void onRttCallScreenUiUnready();
+
+ void onLocalMessage(String message);
}