Home | History | Annotate | Download | only in testapps
      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.server.telecom.testapps;
     18 
     19 import android.content.Context;
     20 import android.os.Handler;
     21 import android.os.HandlerThread;
     22 import android.os.Looper;
     23 import android.os.Message;
     24 import android.os.ParcelFileDescriptor;
     25 import android.telecom.Connection;
     26 import android.telecom.Log;
     27 
     28 import java.io.FileInputStream;
     29 import java.io.FileOutputStream;
     30 import java.io.IOException;
     31 import java.io.InputStreamReader;
     32 import java.io.OutputStreamWriter;
     33 import java.util.Random;
     34 
     35 public 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;
    120                 try {
    121                     charsReceived = mRttTextStream.read();
    122                 } catch (IOException e) {
    123                     break;
    124                 }
    125                 if (charsReceived == null) {
    126                     if (Thread.currentThread().isInterrupted()) {
    127                         Log.w(LOG_TAG, "Thread interrupted");
    128                         break;
    129                     }
    130                     Log.w(LOG_TAG, "Stream closed");
    131                     break;
    132                 }
    133                 if (charsReceived.length() == 0) {
    134                     continue;
    135                 }
    136                 mHandler.obtainMessage(APPEND_TO_INPUT_BUFFER, charsReceived)
    137                         .sendToTarget();
    138             }
    139         }, "RttChatbotReceiver");
    140         mReceiverThread.start();
    141     }
    142 
    143     public void stop() {
    144         if (mSenderThread != null && mSenderThread.isAlive()) {
    145             mSenderThread.quit();
    146         }
    147         if (mReceiverThread != null && mReceiverThread.isAlive()) {
    148             mReceiverThread.interrupt();
    149         }
    150     }
    151 }
    152