diff options
4 files changed, 166 insertions, 79 deletions
diff --git a/java/com/android/dialer/simulator/impl/RttChatBot.java b/java/com/android/dialer/simulator/impl/RttChatBot.java new file mode 100644 index 000000000..9c2989a07 --- /dev/null +++ b/java/com/android/dialer/simulator/impl/RttChatBot.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.simulator.impl; + +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.support.annotation.MainThread; +import android.telecom.Connection.RttTextStream; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.incallui.rtt.protocol.Constants; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** Chat bot to generate remote RTT chat messages. */ +public class RttChatBot { + + interface Callback { + void type(String text); + } + + private static final int START_SENDING = 1; + private static final int SEND_MESSAGE = 2; + + private static final String[] CANDIDATE_MESSAGES = + new String[] { + "To RTT or not to RTT, that is the question...", + "Making TTY great again!", + "I would be more comfortable with real \"Thyme\" chatting." + + " I don't know how to end this pun", + "お疲れ様でした", + "The FCC has mandated that I respond... I will do so begrudgingly", + "😂😂😂💯" + }; + + private final MessageHandler messageHandler; + private final HandlerThread handlerThread; + + RttChatBot(RttTextStream rttTextStream) { + handlerThread = new HandlerThread("RttChatBot"); + handlerThread.start(); + messageHandler = new MessageHandler(handlerThread.getLooper(), rttTextStream); + } + + @MainThread + public void start() { + Assert.isMainThread(); + LogUtil.enterBlock("RttChatBot.start"); + messageHandler.sendEmptyMessage(START_SENDING); + } + + @MainThread + public void stop() { + Assert.isMainThread(); + LogUtil.enterBlock("RttChatBot.stop"); + if (handlerThread != null && handlerThread.isAlive()) { + handlerThread.quit(); + } + } + + private static class MessageHandler extends Handler { + private final RttTextStream rttTextStream; + private final Random random = new Random(); + private final List<String> messageQueue = new ArrayList<>(); + private int currentTypingPosition = -1; + private String currentTypingMessage = null; + + MessageHandler(Looper looper, RttTextStream rttTextStream) { + super(looper); + this.rttTextStream = rttTextStream; + } + + @Override + public void handleMessage(android.os.Message msg) { + switch (msg.what) { + case START_SENDING: + sendMessage(obtainMessage(SEND_MESSAGE, nextTyping())); + 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) { + LogUtil.e("RttChatBot.MessageHandler", "write message", e); + } + if (Constants.BUBBLE_BREAKER.equals(message)) { + // Wait 1-11s between two messages. + sendMessageDelayed( + obtainMessage(SEND_MESSAGE, nextTyping()), 1000 * (1 + random.nextInt(10))); + } else { + // Wait up to 2s between typing. + sendMessageDelayed(obtainMessage(SEND_MESSAGE, nextTyping()), 200 * random.nextInt(10)); + } + break; + default: // fall out + } + } + + private String nextTyping() { + if (currentTypingPosition < 0 || currentTypingMessage == null) { + if (messageQueue.isEmpty()) { + String text = CANDIDATE_MESSAGES[random.nextInt(CANDIDATE_MESSAGES.length)]; + messageQueue.add(text); + } + currentTypingMessage = messageQueue.remove(0); + currentTypingPosition = 0; + } + if (currentTypingPosition < currentTypingMessage.length()) { + int size = random.nextInt(currentTypingMessage.length() - currentTypingPosition + 1); + String messageToType = + currentTypingMessage.substring(currentTypingPosition, currentTypingPosition + size); + currentTypingPosition = currentTypingPosition + size; + return messageToType; + } else { + currentTypingPosition = -1; + currentTypingMessage = null; + return Constants.BUBBLE_BREAKER; + } + } + } +} diff --git a/java/com/android/incallui/rtt/impl/RttChatAdapter.java b/java/com/android/incallui/rtt/impl/RttChatAdapter.java index 1db4c6bad..1ea7f31b1 100644 --- a/java/com/android/incallui/rtt/impl/RttChatAdapter.java +++ b/java/com/android/incallui/rtt/impl/RttChatAdapter.java @@ -17,19 +17,15 @@ package com.android.incallui.rtt.impl; import android.content.Context; -import android.support.annotation.MainThread; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; -import com.android.dialer.common.concurrent.ThreadUtil; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Random; /** Adapter class for holding RTT chat data. */ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolder> { @@ -42,13 +38,11 @@ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolde private final List<RttChatMessage> rttMessages = new ArrayList<>(); private int lastIndexOfLocalMessage = -1; private int lastIndexOfRemoteMessage = -1; - private final TypeBot typeBot; private final MessageListener messageListener; RttChatAdapter(Context context, MessageListener listener) { this.context = context; this.messageListener = listener; - typeBot = new TypeBot(text -> ThreadUtil.postOnUiThread(() -> addRemoteMessage(text))); } @Override @@ -133,7 +127,6 @@ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolde rttMessages.get(lastIndexOfLocalMessage).finish(); notifyItemChanged(lastIndexOfLocalMessage); lastIndexOfLocalMessage = -1; - startChatBot(); } void addRemoteMessage(String message) { @@ -146,73 +139,4 @@ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolde messageListener.newMessageAdded(); } } - - private void startChatBot() { - typeBot.scheduleMessage(); - } - - // TODO(wangqi): Move this out of this class once a bug is fixed. - private static class TypeBot { - interface Callback { - void type(String text); - } - - private static final String[] CANDIDATE_MESSAGES = - new String[] { - "To RTT or not to RTT, that is the question...", - "Making TTY great again!", - "I would be more comfortable with real \"Thyme\" chatting." - + " I don't know how to end this pun", - "お疲れ様でした", - "The FCC has mandated that I respond... I will do so begrudgingly", - "😂😂😂💯" - }; - private final Random random = new Random(); - private final Callback callback; - private final List<String> messageQueue = new ArrayList<>(); - private int currentTypingPosition = -1; - private String currentTypingMessage = null; - - TypeBot(Callback callback) { - this.callback = callback; - } - - @MainThread - public void scheduleMessage() { - Assert.isMainThread(); - if (random.nextDouble() < 0.5) { - return; - } - - String text = CANDIDATE_MESSAGES[random.nextInt(CANDIDATE_MESSAGES.length)]; - messageQueue.add(text); - typeMessage(); - } - - @MainThread - private void typeMessage() { - Assert.isMainThread(); - if (currentTypingPosition < 0 || currentTypingMessage == null) { - if (messageQueue.size() <= 0) { - return; - } - currentTypingMessage = messageQueue.remove(0); - currentTypingPosition = 0; - } - if (currentTypingPosition < currentTypingMessage.length()) { - int size = random.nextInt(currentTypingMessage.length() - currentTypingPosition + 1); - callback.type( - currentTypingMessage.substring(currentTypingPosition, currentTypingPosition + size)); - currentTypingPosition = currentTypingPosition + size; - // Wait up to 2s between typing. - ThreadUtil.postDelayedOnUiThread(this::typeMessage, 200 * random.nextInt(10)); - } else { - callback.type(RttChatMessage.BUBBLE_BREAKER); - currentTypingPosition = -1; - currentTypingMessage = null; - // Wait 1-11s between two messages. - ThreadUtil.postDelayedOnUiThread(this::typeMessage, 1000 * (1 + random.nextInt(10))); - } - } - } } diff --git a/java/com/android/incallui/rtt/impl/RttChatMessage.java b/java/com/android/incallui/rtt/impl/RttChatMessage.java index 85b045183..b36da77cc 100644 --- a/java/com/android/incallui/rtt/impl/RttChatMessage.java +++ b/java/com/android/incallui/rtt/impl/RttChatMessage.java @@ -19,6 +19,7 @@ package com.android.incallui.rtt.impl; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextWatcher; +import com.android.incallui.rtt.protocol.Constants; import com.google.common.base.Splitter; import java.util.ArrayList; import java.util.Iterator; @@ -27,8 +28,7 @@ import java.util.List; /** Message class that holds one RTT chat content. */ final class RttChatMessage { - static final String BUBBLE_BREAKER = "\n\n"; - private static final Splitter SPLITTER = Splitter.on(BUBBLE_BREAKER); + private static final Splitter SPLITTER = Splitter.on(Constants.BUBBLE_BREAKER); boolean isRemote; public boolean hasAvatar; @@ -108,7 +108,7 @@ final class RttChatMessage { firstMessage.isRemote = true; } firstMessage.append(firstMessageContent); - if (splitText.hasNext() || text.endsWith(BUBBLE_BREAKER)) { + if (splitText.hasNext() || text.endsWith(Constants.BUBBLE_BREAKER)) { firstMessage.finish(); } messageList.add(firstMessage); diff --git a/java/com/android/incallui/rtt/protocol/Constants.java b/java/com/android/incallui/rtt/protocol/Constants.java new file mode 100644 index 000000000..5806bbada --- /dev/null +++ b/java/com/android/incallui/rtt/protocol/Constants.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.incallui.rtt.protocol; + +/** Constants for RTT call. */ +public interface Constants { + + /** String used to break bubble, which means one RTT message is complete. */ + String BUBBLE_BREAKER = "\n\n"; +} |