diff options
author | Hall Liu <hallliu@google.com> | 2017-02-22 19:05:07 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-02-22 19:05:07 +0000 |
commit | 86f417aa84995ffba44ea98b32d5ba4ee338aa6f (patch) | |
tree | 208bd848391e2ba05f658861be0c1f23684f51e8 /testapps | |
parent | 6dc6e969f2179e21402ad7ac1b453ea7273415aa (diff) | |
parent | 1d36154ab9ace2609131eb86a242513c20dc53d8 (diff) | |
download | android_packages_services_Telecomm-86f417aa84995ffba44ea98b32d5ba4ee338aa6f.tar.gz android_packages_services_Telecomm-86f417aa84995ffba44ea98b32d5ba4ee338aa6f.tar.bz2 android_packages_services_Telecomm-86f417aa84995ffba44ea98b32d5ba4ee338aa6f.zip |
Add support for RTT calls (part 1) am: dd68bc36a3 am: 399f7e50b0
am: 1d36154ab9
Change-Id: Id768015a354c9a3428b4c817507d058df6ea15f7
Diffstat (limited to 'testapps')
16 files changed, 578 insertions, 20 deletions
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml index 6c7202b9..2cdfc554 100644 --- a/testapps/AndroidManifest.xml +++ b/testapps/AndroidManifest.xml @@ -81,6 +81,16 @@ </intent-filter> </activity> + <activity android:name="com.android.server.telecom.testapps.TestRttActivity" + android:process="com.android.server.telecom.testapps.TestInCallService" + android:label="@string/rttUiLabel" + android:launchMode="singleInstance"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + <activity android:name="com.android.server.telecom.testapps.TestCallActivity" android:theme="@android:style/Theme.NoDisplay" android:label="@string/testCallActivityLabel"> @@ -105,6 +115,11 @@ <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="int" /> </intent-filter> + <intent-filter> + <action android:name="android.telecom.testapps.ACTION_RTT_CALL" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="tel" /> + </intent-filter> </activity> <receiver android:name="com.android.server.telecom.testapps.CallNotificationReceiver" diff --git a/testapps/res/layout/incall_screen.xml b/testapps/res/layout/incall_screen.xml index 6a891e7f..3ca87814 100644 --- a/testapps/res/layout/incall_screen.xml +++ b/testapps/res/layout/incall_screen.xml @@ -44,7 +44,16 @@ android:id="@+id/hold_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/holdButton" > - </Button> + android:text="@string/holdButton"/> + <Button + android:id="@+id/rtt_iface_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/rttIfaceButton"/> + <Button + android:id="@+id/answer_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/answerCallButton"/> </LinearLayout> </LinearLayout> diff --git a/testapps/res/layout/rtt_incall_screen.xml b/testapps/res/layout/rtt_incall_screen.xml new file mode 100644 index 00000000..e7cbac4a --- /dev/null +++ b/testapps/res/layout/rtt_incall_screen.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 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 + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView + android:id="@+id/received_messages_text" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="> " + android:lines="7" /> + <TextView + android:id="@+id/sent_messages_text" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="> " + android:lines="7" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <Button + android:id="@+id/end_rtt_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/endRttButton" /> + <Spinner + android:id="@+id/rtt_mode_selection_spinner" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + </LinearLayout> + + <EditText + android:id="@+id/rtt_typing_box" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:lines="1" + android:hint="Type here" /> +</LinearLayout>
\ No newline at end of file diff --git a/testapps/res/layout/testdialer_main.xml b/testapps/res/layout/testdialer_main.xml index 2c3e5e48..e6c56b74 100644 --- a/testapps/res/layout/testdialer_main.xml +++ b/testapps/res/layout/testdialer_main.xml @@ -44,4 +44,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/cancelMissedButton" /> + <CheckBox + android:id="@+id/call_with_rtt_checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/startCallWithRtt"/> </LinearLayout> diff --git a/testapps/res/values/donottranslate_strings.xml b/testapps/res/values/donottranslate_strings.xml index 74a3fd40..f24625e5 100644 --- a/testapps/res/values/donottranslate_strings.xml +++ b/testapps/res/values/donottranslate_strings.xml @@ -40,6 +40,14 @@ <string name="endCallButton">End Call</string> + <string name="answerCallButton">Answer</string> + + <string name="startCallWithRtt">Start call with RTT</string> + + <string name="rttIfaceButton">RTT</string> + + <string name="endRttButton">End RTT</string> + <string name="muteButton">Mute</string> <string name="holdButton">Hold</string> @@ -62,4 +70,22 @@ <string name="incomingCallNotPermitted">Incoming call not permitted.</string> <string name="incomingCallNotPermittedCS">Incoming call not permitted (CS Reported).</string> + + <string name="rttUiLabel">Test RTT UI</string> + + <string-array name="rtt_mode_array"> + <item>Full</item> + <item>HCO</item> + <item>VCO</item> + </string-array> + + <string-array name="rtt_reply_one_liners"> + <item>To RTT or not to RTT, that is the question...</item> + <item>Making TTY great again!</item> + <item>I would be more comfortable with real "Thyme" chatting. I don\'t know how to end + this pun</item> + <item>お疲れ様でした</item> + <item>The FCC has mandated that I respond... I will do so begrudgingly</item> + <item>😂😂😂💯</item> + </string-array> </resources> diff --git a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java index bea0e63e..85785d58 100644 --- a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java +++ b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java @@ -103,7 +103,8 @@ public class CallListAdapter extends BaseAdapter { state.setText(getStateString(call)); - Log.i(TAG, "Call found: " + handle.getSchemeSpecificPart() + ", " + durationMs); + Log.i(TAG, "Call found: " + ((handle == null) ? "null" : handle.getSchemeSpecificPart()) + + ", " + durationMs); return convertView; } diff --git a/testapps/src/com/android/server/telecom/testapps/CallNotificationReceiver.java b/testapps/src/com/android/server/telecom/testapps/CallNotificationReceiver.java index aee55148..8fd23780 100644 --- a/testapps/src/com/android/server/telecom/testapps/CallNotificationReceiver.java +++ b/testapps/src/com/android/server/telecom/testapps/CallNotificationReceiver.java @@ -51,6 +51,8 @@ public class CallNotificationReceiver extends BroadcastReceiver { "com.android.server.telecom.testapps.ACTION_TWO_WAY_VIDEO_CALL"; static final String ACTION_AUDIO_CALL = "com.android.server.telecom.testapps.ACTION_AUDIO_CALL"; + static final String ACTION_RTT_CALL = + "com.android.server.telecom.testapps.ACTION_RTT_CALL"; /** {@inheritDoc} */ @Override @@ -66,6 +68,8 @@ public class CallNotificationReceiver extends BroadcastReceiver { sendIncomingCallIntent(context, null, VideoProfile.STATE_RX_ENABLED); } else if (ACTION_TWO_WAY_VIDEO_CALL.equals(action)) { sendIncomingCallIntent(context, null, VideoProfile.STATE_BIDIRECTIONAL); + } else if (ACTION_RTT_CALL.equals(action)) { + sendIncomingRttCallIntent(context, null, VideoProfile.STATE_AUDIO_ONLY); } else if (ACTION_AUDIO_CALL.equals(action)) { sendIncomingCallIntent(context, null, VideoProfile.STATE_AUDIO_ONLY); } @@ -93,6 +97,23 @@ public class CallNotificationReceiver extends BroadcastReceiver { TelecomManager.from(context).addNewIncomingCall(phoneAccount, extras); } + public static void sendIncomingRttCallIntent(Context context, Uri handle, int videoState) { + PhoneAccountHandle phoneAccount = new PhoneAccountHandle( + new ComponentName(context, TestConnectionService.class), + CallServiceNotifier.SIM_SUBSCRIPTION_ID); + + // For the purposes of testing, indicate whether the incoming call is a video call by + // stashing an indicator in the EXTRA_INCOMING_CALL_EXTRAS. + Bundle extras = new Bundle(); + extras.putInt(TestConnectionService.EXTRA_START_VIDEO_STATE, videoState); + if (handle != null) { + extras.putParcelable(TestConnectionService.EXTRA_HANDLE, handle); + } + extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true); + + TelecomManager.from(context).addNewIncomingCall(phoneAccount, extras); + } + public static void addNewUnknownCall(Context context, Uri handle, Bundle extras) { Log.i(TAG, "Adding new unknown call with handle " + handle); PhoneAccountHandle phoneAccount = new PhoneAccountHandle( diff --git a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java index 9292273e..ba586553 100644 --- a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java +++ b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java @@ -119,6 +119,7 @@ public class CallServiceNotifier { .setSubscriptionAddress(Uri.parse("tel:555-TEST")) .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_VIDEO_CALLING | + PhoneAccount.CAPABILITY_RTT | PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE) .setIcon(Icon.createWithResource( context.getResources(), R.drawable.stat_sys_phone_call)) @@ -139,6 +140,7 @@ public class CallServiceNotifier { .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | PhoneAccount.CAPABILITY_VIDEO_CALLING | + PhoneAccount.CAPABILITY_RTT | PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE) .setIcon(Icon.createWithResource( context.getResources(), R.drawable.stat_sys_phone_call)) diff --git a/testapps/src/com/android/server/telecom/testapps/RttChatbot.java b/testapps/src/com/android/server/telecom/testapps/RttChatbot.java new file mode 100644 index 00000000..3b16bd44 --- /dev/null +++ b/testapps/src/com/android/server/telecom/testapps/RttChatbot.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2017 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.server.telecom.testapps; + +import android.content.Context; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.ParcelFileDescriptor; +import android.telecom.Connection; +import android.telecom.Log; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.Random; + +public class RttChatbot { + private static final String LOG_TAG = RttChatbot.class.getSimpleName(); + private static final long PER_CHARACTER_DELAY_MS = 100; + private static final long MSG_WAIT_DELAY_MS = 3999; + private static final double ONE_LINER_FREQUENCY = 0.1; + private static final String REPLY_PREFIX = "You said: "; + + private static final int BEGIN_SEND_REPLY_MESSAGE = 1; + private static final int SEND_CHARACTER = 2; + private static final int APPEND_TO_INPUT_BUFFER = 3; + + private final Connection.RttTextStream mRttTextStream; + private final Random mRandom = new Random(); + private final String[] mOneLiners; + private Handler mHandler; + + private final class ReplyHandler extends Handler { + private StringBuilder mInputSoFar; + + public ReplyHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case BEGIN_SEND_REPLY_MESSAGE: + removeMessages(SEND_CHARACTER); + sendReplyMessage(); + break; + case SEND_CHARACTER: + try { + mRttTextStream.write((String) msg.obj); + } catch (IOException e) { + } + break; + case APPEND_TO_INPUT_BUFFER: + removeMessages(BEGIN_SEND_REPLY_MESSAGE); + sendEmptyMessageDelayed(BEGIN_SEND_REPLY_MESSAGE, MSG_WAIT_DELAY_MS); + String toAppend = (String) msg.obj; + if (mInputSoFar == null) { + mInputSoFar = new StringBuilder(toAppend); + } else { + mInputSoFar.append(toAppend); + } + Log.d(LOG_TAG, "Got %s to append, total text now %s", + toAppend, mInputSoFar.toString()); + break; + } + } + + private void sendReplyMessage() { + String messageToSend; + if (mRandom.nextDouble() < ONE_LINER_FREQUENCY) { + messageToSend = mOneLiners[mRandom.nextInt(mOneLiners.length)]; + } else { + messageToSend = REPLY_PREFIX + mInputSoFar.toString(); + } + mInputSoFar = null; + Log.i(LOG_TAG, "Begin send reply message: %s", messageToSend); + int[] charsToSend = messageToSend.codePoints().toArray(); + for (int i = 0; i < charsToSend.length; i++) { + Message msg = obtainMessage(SEND_CHARACTER, + new String(new int[] {charsToSend[i]}, 0, 1)); + sendMessageDelayed(msg, PER_CHARACTER_DELAY_MS * i); + } + } + } + + public RttChatbot(Context context, Connection.RttTextStream textStream) { + mOneLiners = context.getResources().getStringArray(R.array.rtt_reply_one_liners); + mRttTextStream = textStream; + } + + public void start() { + Log.i(LOG_TAG, "Starting RTT chatbot."); + HandlerThread ht = new HandlerThread("RttChatbotSender"); + ht.start(); + mHandler = new ReplyHandler(ht.getLooper()); + Thread receiveThread = new Thread(() -> { + while (true) { + String charsReceived = mRttTextStream.read(); + if (charsReceived == null) { + if (Thread.currentThread().isInterrupted()) { + Log.w(LOG_TAG, "Thread interrupted"); + break; + } + Log.w(LOG_TAG, "Stream closed"); + break; + } + if (charsReceived.length() == 0) { + continue; + } + mHandler.obtainMessage(APPEND_TO_INPUT_BUFFER, charsReceived) + .sendToTarget(); + } + }, "RttChatbotReceiver"); + receiveThread.start(); + } +} diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java b/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java index 862ccf76..76f2058c 100644 --- a/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java +++ b/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java @@ -52,6 +52,9 @@ public class TestCallActivity extends Activity { public static final String ACTION_SEND_UPGRADE_REQUEST = "android.telecom.testapps.ACTION_SEND_UPGRADE_REQUEST"; + static final String ACTION_RTT_CALL = + "android.telecom.testapps.ACTION_RTT_CALL"; + @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -65,6 +68,9 @@ public class TestCallActivity extends Activity { CallNotificationReceiver.addNewUnknownCall(this, data, intent.getExtras()); } else if (ACTION_HANGUP_CALLS.equals(action)) { CallNotificationReceiver.hangupCalls(this); + } else if (ACTION_RTT_CALL.equals(action)) { + CallNotificationReceiver.sendIncomingRttCallIntent( + this, data, VideoProfile.STATE_AUDIO_ONLY); } else if (ACTION_SEND_UPGRADE_REQUEST.equals(action)) { CallNotificationReceiver.sendUpgradeRequest(this, data); } else { diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallList.java b/testapps/src/com/android/server/telecom/testapps/TestCallList.java index 391a5886..4419b17d 100644 --- a/testapps/src/com/android/server/telecom/testapps/TestCallList.java +++ b/testapps/src/com/android/server/telecom/testapps/TestCallList.java @@ -32,7 +32,7 @@ import java.util.Set; /** * Maintains a list of calls received via the {@link TestInCallServiceImpl}. */ -public class TestCallList extends Call.Listener { +public class TestCallList extends Call.Callback { public static abstract class Listener { public void onCallAdded(Call call) {} @@ -126,7 +126,7 @@ public class TestCallList extends Call.Listener { } Log.i(TAG, "addCall: " + call + " " + System.identityHashCode(this)); mCalls.add(call); - call.addListener(this); + call.registerCallback(this); for (Listener l : mListeners) { l.onCallAdded(call); @@ -140,7 +140,7 @@ public class TestCallList extends Call.Listener { } Log.i(TAG, "removeCall: " + call); mCalls.remove(call); - call.removeListener(this); + call.unregisterCallback(this); for (Listener l : mListeners) { l.onCallRemoved(call); @@ -214,4 +214,15 @@ public class TestCallList extends Call.Listener { } } } + + @Override + public void onRttStatusChanged(Call call, boolean enabled, Call.RttCall rttCall) { + Log.v(TAG, "onRttStatusChanged: call = " + call + " " + System.identityHashCode(this)); + + if (call != null) { + // Did you have another call? Well too bad, this class isn't gonna handle it. + mCalls.clear(); + mCalls.add(call); + } + } } diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java index 5b0cf637..c2d8852a 100644 --- a/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java +++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java @@ -135,6 +135,7 @@ public class TestConnectionManager extends ConnectionService { mRemote.registerCallback(mRemoteCallback); setState(mRemote.getState()); setVideoState(mRemote.getVideoState()); + setConnectionProperties(remote.getConnectionProperties()); } @Override diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java index 0150dbe5..6c070739 100644 --- a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java +++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java @@ -25,6 +25,7 @@ import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.os.ParcelFileDescriptor; import android.support.v4.content.LocalBroadcastManager; import android.telecom.Conference; import android.telecom.Connection; @@ -35,7 +36,7 @@ import android.telecom.ConnectionService; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telecom.VideoProfile; -import android.util.Log; +import android.telecom.Log; import android.widget.Toast; import com.android.server.telecom.testapps.R; @@ -57,6 +58,7 @@ public class TestConnectionService extends ConnectionService { public static final String EXTRA_HANDLE = "extra_handle"; + private static final String LOG_TAG = TestConnectionService.class.getSimpleName(); /** * Random number generator used to generate phone numbers. */ @@ -271,6 +273,8 @@ public class TestConnectionService extends ConnectionService { /** Used to play an audio tone during a call. */ private MediaPlayer mMediaPlayer; + // Used to provide text reply in an RTT call + private RttChatbot mRttChatbot; @Override public boolean onUnbind(Intent intent) { @@ -309,11 +313,22 @@ public class TestConnectionService extends ConnectionService { Toast.LENGTH_SHORT).show(); } + if (originalRequest.isRequestingRtt()) { + Log.i(LOG_TAG, "Is RTT call. Starting chatbot service."); + mRttChatbot = new RttChatbot(getApplicationContext(), + originalRequest.getRttTextStream()); + mRttChatbot.start(); + } + log("gateway package [" + gatewayPackage + "], original handle [" + originalHandle + "]"); final TestConnection connection = new TestConnection(false /* isIncoming */); setAddress(connection, handle); + if (originalRequest.isRequestingRtt()) { + connection.setConnectionProperties( + connection.getConnectionProperties() | Connection.PROPERTY_IS_RTT); + } // If the number starts with 555, then we handle it ourselves. If not, then we // use a remote connection service. @@ -377,6 +392,13 @@ public class TestConnectionService extends ConnectionService { connectionExtras.putString(Connection.EXTRA_CALL_SUBJECT, "This is a test of call subject lines."); } + + if (request.isRequestingRtt()) { + Log.i(LOG_TAG, "Is RTT call. Starting chatbot service."); + mRttChatbot = new RttChatbot(getApplicationContext(), request.getRttTextStream()); + mRttChatbot.start(); + } + connection.putExtras(connectionExtras); setAddress(connection, address); @@ -385,11 +407,6 @@ public class TestConnectionService extends ConnectionService { addCall(connection); - ConnectionRequest newRequest = new ConnectionRequest( - request.getAccountHandle(), - address, - request.getExtras(), - videoState); connection.setVideoState(videoState); return connection; } else { diff --git a/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java b/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java index 596d18d4..c7eccf72 100644 --- a/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java +++ b/testapps/src/com/android/server/telecom/testapps/TestDialerActivity.java @@ -12,15 +12,15 @@ import android.telecom.TelecomManager; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; +import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; -import com.android.server.telecom.testapps.R; - public class TestDialerActivity extends Activity { private static final int REQUEST_CODE_SET_DEFAULT_DIALER = 1; private EditText mNumberView; + private CheckBox mRttCheckbox; @Override protected void onCreate(Bundle savedInstanceState) { @@ -55,7 +55,8 @@ public class TestDialerActivity extends Activity { }); mNumberView = (EditText) findViewById(R.id.number); - updateEditTextWithNumber(); + mRttCheckbox = (CheckBox) findViewById(R.id.call_with_rtt_checkbox); + updateMutableUi(); } @Override @@ -72,13 +73,15 @@ public class TestDialerActivity extends Activity { @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); - updateEditTextWithNumber(); + updateMutableUi(); } - private void updateEditTextWithNumber() { + private void updateMutableUi() { Intent intent = getIntent(); if (intent != null) { mNumberView.setText(intent.getDataString()); + mRttCheckbox.setChecked( + intent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_RTT, false)); } } @@ -127,7 +130,10 @@ public class TestDialerActivity extends Activity { private Bundle createCallIntentExtras() { Bundle extras = new Bundle(); - extras.putString("com.android.server.telecom.testapps.CALL_EXTRAS", "Yorke was here"); + extras.putString("com.android.server.telecom.testapps.CALL_EXTRAS", "Hall was here"); + if (mRttCheckbox.isChecked()) { + extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true); + } Bundle intentExtras = new Bundle(); intentExtras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras); diff --git a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java index ce53709d..809036c8 100644 --- a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java +++ b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java @@ -17,9 +17,10 @@ package com.android.server.telecom.testapps; import android.app.Activity; -import android.graphics.Color; +import android.content.Intent; import android.os.Bundle; import android.telecom.Call; +import android.telecom.VideoProfile; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; @@ -46,7 +47,7 @@ public class TestInCallUI extends Activity { @Override public void onCallRemoved(Call call) { if (mCallList.size() == 0) { - Log.i("Santos", "Ending the incall UI"); + Log.i(TestInCallUI.class.getSimpleName(), "Ending the incall UI"); finish(); } } @@ -55,6 +56,8 @@ public class TestInCallUI extends Activity { View endCallButton = findViewById(R.id.end_call_button); View holdButton = findViewById(R.id.hold_button); View muteButton = findViewById(R.id.mute_button); + View rttIfaceButton = findViewById(R.id.rtt_iface_button); + View answerButton = findViewById(R.id.answer_button); endCallButton.setOnClickListener(new OnClickListener() { @Override @@ -83,9 +86,24 @@ public class TestInCallUI extends Activity { public void onClick(View view) { Call call = mCallList.getCall(0); if (call != null) { + } } }); + rttIfaceButton.setOnClickListener((view) -> { + Call call = mCallList.getCall(0); + if (call.isRttActive()) { + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setClass(this, TestRttActivity.class); + startActivity(intent); + } + }); + answerButton.setOnClickListener(view -> { + Call call = mCallList.getCall(0); + if (call.getState() == Call.STATE_RINGING) { + call.answer(VideoProfile.STATE_AUDIO_ONLY); + } + }); } /** ${inheritDoc} */ diff --git a/testapps/src/com/android/server/telecom/testapps/TestRttActivity.java b/testapps/src/com/android/server/telecom/testapps/TestRttActivity.java new file mode 100644 index 00000000..ce962b47 --- /dev/null +++ b/testapps/src/com/android/server/telecom/testapps/TestRttActivity.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2017 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.server.telecom.testapps; + +import android.app.Activity; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.telecom.Call; +import android.telecom.Log; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.TextView; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; + +public class TestRttActivity extends Activity { + private static final String LOG_TAG = TestRttActivity.class.getSimpleName(); + private static final long NEWLINE_DELAY_MILLIS = 3000; + + private static final int UPDATE_RECEIVED_TEXT = 1; + private static final int UPDATE_SENT_TEXT = 2; + private static final int RECEIVED_MESSAGE_GAP = 3; + private static final int SENT_MESSAGE_GAP = 4; + + private TextView mReceivedText; + private TextView mSentText; + private EditText mTypingBox; + + private TestCallList mCallList; + + private Handler mTextDisplayHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + String text; + switch (msg.what) { + case UPDATE_RECEIVED_TEXT: + text = (String) msg.obj; + mReceivedText.append(text); + break; + case UPDATE_SENT_TEXT: + text = (String) msg.obj; + mSentText.append(text); + break; + case RECEIVED_MESSAGE_GAP: + mReceivedText.append("\n> "); + break; + case SENT_MESSAGE_GAP: + mSentText.append("\n> "); + mTypingBox.setText(""); + break; + default: + Log.w(LOG_TAG, "Invalid message %d", msg.what); + } + } + }; + + private Thread mReceiveReader = new Thread() { + @Override + public void run() { + // outer loop + while (true) { + begin : + // sleep and wait if there are no calls + while (mCallList.size() > 0) { + Call.RttCall rttCall = mCallList.getCall(0).getRttCall(); + if (rttCall == null) { + break; + } + // inner read loop + while (true) { + String receivedText = rttCall.read(); + if (receivedText == null) { + if (Thread.currentThread().isInterrupted()) { + break begin; + } + break; + } + Log.d(LOG_TAG, "Received %s", receivedText); + mTextDisplayHandler.removeMessages(RECEIVED_MESSAGE_GAP); + mTextDisplayHandler.sendEmptyMessageDelayed(RECEIVED_MESSAGE_GAP, + NEWLINE_DELAY_MILLIS); + mTextDisplayHandler.obtainMessage(UPDATE_RECEIVED_TEXT, receivedText) + .sendToTarget(); + } + } + if (Thread.currentThread().isInterrupted()) { + break; + } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + break; + } + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.rtt_incall_screen); + + mReceivedText = (TextView) findViewById(R.id.received_messages_text); + mSentText = (TextView) findViewById(R.id.sent_messages_text); + mTypingBox = (EditText) findViewById(R.id.rtt_typing_box); + + Button endRttButton = (Button) findViewById(R.id.end_rtt_button); + Spinner rttModeSelector = (Spinner) findViewById(R.id.rtt_mode_selection_spinner); + + ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, + R.array.rtt_mode_array, android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + rttModeSelector.setAdapter(adapter); + + mCallList = TestCallList.getInstance(); + mCallList.addListener(new TestCallList.Listener() { + @Override + public void onCallRemoved(Call call) { + if (mCallList.size() == 0) { + Log.i(LOG_TAG, "Ending the RTT UI"); + finish(); + } + } + }); + + endRttButton.setOnClickListener((view) -> { + Call call = mCallList.getCall(0); + call.stopRtt(); + }); + + rttModeSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + CharSequence selection = (CharSequence) parent.getItemAtPosition(position); + Call.RttCall call = mCallList.getCall(0).getRttCall(); + switch (selection.toString()) { + case "Full": + call.setRttMode(Call.RttCall.RTT_MODE_FULL); + break; + case "HCO": + call.setRttMode(Call.RttCall.RTT_MODE_HCO); + break; + case "VCO": + call.setRttMode(Call.RttCall.RTT_MODE_VCO); + break; + default: + Log.w(LOG_TAG, "Bad name for rtt mode: %s", selection.toString()); + } + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + } + }); + + mTypingBox.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (count == 0 || count < before) { + // ignore deletions and clears + return; + } + // Only appending at the end is supported. + int numCharsInserted = count - before; + String toAppend = + s.subSequence(s.length() - numCharsInserted, s.length()).toString(); + + if (toAppend.isEmpty()) { + return; + } + try { + mCallList.getCall(0).getRttCall().write(toAppend); + } catch (IOException e) { + Log.w(LOG_TAG, "Exception sending text %s: %s", toAppend, e); + } + mTextDisplayHandler.removeMessages(SENT_MESSAGE_GAP); + mTextDisplayHandler.sendEmptyMessageDelayed(SENT_MESSAGE_GAP, NEWLINE_DELAY_MILLIS); + mTextDisplayHandler.obtainMessage(UPDATE_SENT_TEXT, toAppend).sendToTarget(); + } + + @Override + public void afterTextChanged(Editable s) { + } + }); + + } + + @Override + public void onStart() { + super.onStart(); + mReceiveReader.start(); + } + + @Override + public void onStop() { + super.onStop(); + mReceiveReader.interrupt(); + } + +} |