RttChatbot.java revision aeece4ec4184b76e0ac2e8a012af05638ad866f6
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 17package com.android.server.telecom.testapps; 18 19import android.content.Context; 20import android.os.Handler; 21import android.os.HandlerThread; 22import android.os.Looper; 23import android.os.Message; 24import android.os.ParcelFileDescriptor; 25import android.telecom.Connection; 26import android.telecom.Log; 27 28import java.io.FileInputStream; 29import java.io.FileOutputStream; 30import java.io.IOException; 31import java.io.InputStreamReader; 32import java.io.OutputStreamWriter; 33import java.util.Random; 34 35public class RttChatbot { 36 private static final String LOG_TAG = RttChatbot.class.getSimpleName(); 37 private static final long PER_CHARACTER_DELAY_MS = 100; 38 private static final long MSG_WAIT_DELAY_MS = 3999; 39 private static final double ONE_LINER_FREQUENCY = 0.1; 40 private static final String REPLY_PREFIX = "You said: "; 41 42 private static final int BEGIN_SEND_REPLY_MESSAGE = 1; 43 private static final int SEND_CHARACTER = 2; 44 private static final int APPEND_TO_INPUT_BUFFER = 3; 45 46 private final Connection.RttTextStream mRttTextStream; 47 private final Random mRandom = new Random(); 48 private final String[] mOneLiners; 49 private Handler mHandler; 50 private HandlerThread mSenderThread; 51 private Thread mReceiverThread; 52 53 private final class ReplyHandler extends Handler { 54 private StringBuilder mInputSoFar; 55 56 public ReplyHandler(Looper looper) { 57 super(looper); 58 } 59 60 @Override 61 public void handleMessage(Message msg) { 62 switch (msg.what) { 63 case BEGIN_SEND_REPLY_MESSAGE: 64 removeMessages(SEND_CHARACTER); 65 sendReplyMessage(); 66 break; 67 case SEND_CHARACTER: 68 try { 69 mRttTextStream.write((String) msg.obj); 70 } catch (IOException e) { 71 } 72 break; 73 case APPEND_TO_INPUT_BUFFER: 74 removeMessages(BEGIN_SEND_REPLY_MESSAGE); 75 sendEmptyMessageDelayed(BEGIN_SEND_REPLY_MESSAGE, MSG_WAIT_DELAY_MS); 76 String toAppend = (String) msg.obj; 77 if (mInputSoFar == null) { 78 mInputSoFar = new StringBuilder(toAppend); 79 } else { 80 mInputSoFar.append(toAppend); 81 } 82 Log.d(LOG_TAG, "Got %s to append, total text now %s", 83 toAppend, mInputSoFar.toString()); 84 break; 85 } 86 } 87 88 private void sendReplyMessage() { 89 String messageToSend; 90 if (mRandom.nextDouble() < ONE_LINER_FREQUENCY) { 91 messageToSend = mOneLiners[mRandom.nextInt(mOneLiners.length)]; 92 } else { 93 messageToSend = REPLY_PREFIX + mInputSoFar.toString(); 94 } 95 mInputSoFar = null; 96 Log.i(LOG_TAG, "Begin send reply message: %s", messageToSend); 97 int[] charsToSend = messageToSend.codePoints().toArray(); 98 for (int i = 0; i < charsToSend.length; i++) { 99 Message msg = obtainMessage(SEND_CHARACTER, 100 new String(new int[] {charsToSend[i]}, 0, 1)); 101 sendMessageDelayed(msg, PER_CHARACTER_DELAY_MS * i); 102 } 103 } 104 } 105 106 public RttChatbot(Context context, Connection.RttTextStream textStream) { 107 mOneLiners = context.getResources().getStringArray(R.array.rtt_reply_one_liners); 108 mRttTextStream = textStream; 109 } 110 111 public void start() { 112 Log.i(LOG_TAG, "Starting RTT chatbot."); 113 HandlerThread ht = new HandlerThread("RttChatbotSender"); 114 ht.start(); 115 mSenderThread = ht; 116 mHandler = new ReplyHandler(ht.getLooper()); 117 mReceiverThread = new Thread(() -> { 118 while (true) { 119 String charsReceived = mRttTextStream.read(); 120 if (charsReceived == null) { 121 if (Thread.currentThread().isInterrupted()) { 122 Log.w(LOG_TAG, "Thread interrupted"); 123 break; 124 } 125 Log.w(LOG_TAG, "Stream closed"); 126 break; 127 } 128 if (charsReceived.length() == 0) { 129 continue; 130 } 131 mHandler.obtainMessage(APPEND_TO_INPUT_BUFFER, charsReceived) 132 .sendToTarget(); 133 } 134 }, "RttChatbotReceiver"); 135 mReceiverThread.start(); 136 } 137 138 public void stop() { 139 if (mSenderThread != null && mSenderThread.isAlive()) { 140 mSenderThread.quit(); 141 } 142 if (mReceiverThread != null && mReceiverThread.isAlive()) { 143 mReceiverThread.interrupt(); 144 } 145 } 146} 147