From bc28ea71c553a3c0b53a36b9c80c913a9d7c62bd Mon Sep 17 00:00:00 2001 From: wangqi Date: Mon, 2 Apr 2018 16:23:00 -0700 Subject: Implement dialog for responding RTT request. Bug: 67596257 Test: manual PiperOrigin-RevId: 191365412 Change-Id: Ida741a837d6495c0d5f51b748f4d6c09a1beafec --- java/com/android/incallui/InCallActivity.java | 8 ++ java/com/android/incallui/InCallPresenter.java | 7 + .../android/incallui/RttRequestDialogFragment.java | 149 +++++++++++++++++++++ java/com/android/incallui/call/CallList.java | 13 ++ java/com/android/incallui/call/DialerCall.java | 8 ++ .../android/incallui/call/DialerCallListener.java | 2 + .../res/layout/frag_rtt_request_dialog.xml | 75 +++++++++++ java/com/android/incallui/res/values/strings.xml | 15 +++ .../incallui/rtt/impl/res/values/strings.xml | 2 +- 9 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 java/com/android/incallui/RttRequestDialogFragment.java create mode 100644 java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java index 1ba3683f0..65ef323fe 100644 --- a/java/com/android/incallui/InCallActivity.java +++ b/java/com/android/incallui/InCallActivity.java @@ -35,6 +35,7 @@ import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; +import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -1221,6 +1222,12 @@ public class InCallActivity extends TransactionSafeFragmentActivity fragment.show(getSupportFragmentManager(), Tags.INTERNATIONAL_CALL_ON_WIFI); } + public void showDialogForRttRequest(DialerCall call, int rttRequestId) { + LogUtil.enterBlock("InCallActivity.showDialogForRttRequest"); + DialogFragment fragment = RttRequestDialogFragment.newInstance(call.getId(), rttRequestId); + fragment.show(getSupportFragmentManager(), Tags.RTT_REQUEST_DIALOG); + } + @Override public void onMultiWindowModeChanged(boolean isInMultiWindowMode) { super.onMultiWindowModeChanged(isInMultiWindowMode); @@ -1763,6 +1770,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity static final String RTT_CALL_SCREEN = "tag_rtt_call_screen"; static final String POST_CHAR_DIALOG_FRAGMENT = "tag_post_char_dialog_fragment"; static final String SPEAK_EASY_SCREEN = "tag_speak_easy_screen"; + static final String RTT_REQUEST_DIALOG = "tag_rtt_request_dialog"; } private static final class ConfigNames { diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java index e11b376c1..6300dac75 100644 --- a/java/com/android/incallui/InCallPresenter.java +++ b/java/com/android/incallui/InCallPresenter.java @@ -893,6 +893,13 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud } } + @Override + public void onUpgradeToRtt(DialerCall call, int rttRequestId) { + if (inCallActivity != null) { + inCallActivity.showDialogForRttRequest(call, rttRequestId); + } + } + @Override public void onSessionModificationStateChange(DialerCall call) { int newState = call.getVideoTech().getSessionModificationState(); diff --git a/java/com/android/incallui/RttRequestDialogFragment.java b/java/com/android/incallui/RttRequestDialogFragment.java new file mode 100644 index 000000000..fa9b0e5db --- /dev/null +++ b/java/com/android/incallui/RttRequestDialogFragment.java @@ -0,0 +1,149 @@ +/* + * 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; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.telephony.PhoneNumberUtils; +import android.text.BidiFormatter; +import android.text.TextDirectionHeuristics; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; +import com.android.contacts.common.util.ContactDisplayUtils; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.incallui.ContactInfoCache.ContactCacheEntry; +import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback; +import com.android.incallui.call.CallList; +import com.android.incallui.call.DialerCall; +import java.lang.ref.WeakReference; + +/** Dialog that shown to user when receiving RTT request mid call. */ +public class RttRequestDialogFragment extends DialogFragment { + + /** + * Returns a new instance of {@link RttRequestDialogFragment} with the given callback. + * + *

Prefer this method over the default constructor. + */ + public static RttRequestDialogFragment newInstance(String callId, int rttRequestId) { + RttRequestDialogFragment fragment = new RttRequestDialogFragment(); + Bundle args = new Bundle(); + args.putString(ARG_CALL_ID, Assert.isNotNull(callId)); + args.putInt(ARG_RTT_REQUEST_ID, rttRequestId); + fragment.setArguments(args); + return fragment; + } + + /** Key in the arguments bundle for call id. */ + private static final String ARG_CALL_ID = "call_id"; + + private static final String ARG_RTT_REQUEST_ID = "rtt_request_id"; + + private TextView detailsTextView; + + @NonNull + @Override + public Dialog onCreateDialog(Bundle bundle) { + super.onCreateDialog(bundle); + LogUtil.enterBlock("RttRequestDialogFragment.onCreateDialog"); + + View dialogView = View.inflate(getActivity(), R.layout.frag_rtt_request_dialog, null); + detailsTextView = dialogView.findViewById(R.id.details); + + ContactInfoCache cache = ContactInfoCache.getInstance(getContext()); + DialerCall dialerCall = + CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID)); + cache.findInfo(dialerCall, false, new ContactLookupCallback(this)); + + dialogView + .findViewById(R.id.rtt_button_decline_request) + .setOnClickListener(v -> onNegativeButtonClick()); + dialogView + .findViewById(R.id.rtt_button_accept_request) + .setOnClickListener(v -> onPositiveButtonClick()); + + AlertDialog alertDialog = + new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme) + .setCancelable(false) + .setView(dialogView) + .setTitle(R.string.rtt_request_dialog_title) + .create(); + + alertDialog.setCanceledOnTouchOutside(false); + return alertDialog; + } + + private void onPositiveButtonClick() { + LogUtil.enterBlock("RttRequestDialogFragment.onPositiveButtonClick"); + + DialerCall call = CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID)); + call.respondToRttRequest(true, getArguments().getInt(ARG_RTT_REQUEST_ID)); + dismiss(); + } + + private void onNegativeButtonClick() { + LogUtil.enterBlock("RttRequestDialogFragment.onNegativeButtonClick"); + + DialerCall call = CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID)); + call.respondToRttRequest(false, getArguments().getInt(ARG_RTT_REQUEST_ID)); + dismiss(); + } + + private void setNameOrNumber(CharSequence nameOrNumber) { + detailsTextView.setText(getString(R.string.rtt_request_dialog_details, nameOrNumber)); + } + + private static class ContactLookupCallback implements ContactInfoCacheCallback { + private final WeakReference rttRequestDialogFragmentWeakReference; + + private ContactLookupCallback(RttRequestDialogFragment rttRequestDialogFragment) { + rttRequestDialogFragmentWeakReference = new WeakReference<>(rttRequestDialogFragment); + } + + @Override + public void onContactInfoComplete(String callId, ContactCacheEntry entry) { + RttRequestDialogFragment fragment = rttRequestDialogFragmentWeakReference.get(); + if (fragment != null) { + fragment.setNameOrNumber(getNameOrNumber(entry, fragment.getContext())); + } + } + + private CharSequence getNameOrNumber(ContactCacheEntry entry, Context context) { + String preferredName = + ContactDisplayUtils.getPreferredDisplayName( + entry.namePrimary, + entry.nameAlternative, + ContactsPreferencesFactory.newContactsPreferences(context)); + if (TextUtils.isEmpty(preferredName)) { + return TextUtils.isEmpty(entry.number) + ? null + : PhoneNumberUtils.createTtsSpannable( + BidiFormatter.getInstance().unicodeWrap(entry.number, TextDirectionHeuristics.LTR)); + } + return preferredName; + } + + @Override + public void onImageLoadComplete(String callId, ContactCacheEntry entry) {} + } +} diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java index 01f3b9d29..eccdceeca 100644 --- a/java/com/android/incallui/call/CallList.java +++ b/java/com/android/incallui/call/CallList.java @@ -784,6 +784,12 @@ public class CallList implements DialerCallDelegate { */ void onUpgradeToVideo(DialerCall call); + /** + * Called when a new RTT call request comes in This is the only method that gets called for RTT + * requests. + */ + default void onUpgradeToRtt(DialerCall call, int rttRequestId) {} + /** Called when the session modification state of a call changes. */ void onSessionModificationStateChange(DialerCall call); @@ -854,6 +860,13 @@ public class CallList implements DialerCallDelegate { @Override public void onDialerCallLastForwardedNumberChange() {} + @Override + public void onDialerCallUpgradeToRtt(int rttRequestId) { + for (Listener listener : listeners) { + listener.onUpgradeToRtt(call, rttRequestId); + } + } + @Override public void onDialerCallUpgradeToVideo() { for (Listener listener : listeners) { diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java index e08c926d8..35f9481c5 100644 --- a/java/com/android/incallui/call/DialerCall.java +++ b/java/com/android/incallui/call/DialerCall.java @@ -282,6 +282,9 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa @Override public void onRttRequest(Call call, int id) { LogUtil.v("TelecomCallCallback.onRttRequest", "id=%d", id); + for (DialerCallListener listener : listeners) { + listener.onDialerCallUpgradeToRtt(id); + } } @Override @@ -1033,6 +1036,11 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa getTelecomCall().sendRttRequest(); } + @TargetApi(28) + public void respondToRttRequest(boolean accept, int rttRequestId) { + getTelecomCall().respondToRttRequest(rttRequestId, accept); + } + public boolean hasReceivedVideoUpgradeRequest() { return VideoUtils.hasReceivedVideoUpgradeRequest(getVideoTech().getSessionModificationState()); } diff --git a/java/com/android/incallui/call/DialerCallListener.java b/java/com/android/incallui/call/DialerCallListener.java index 5d24a4d4b..37c30d30c 100644 --- a/java/com/android/incallui/call/DialerCallListener.java +++ b/java/com/android/incallui/call/DialerCallListener.java @@ -29,6 +29,8 @@ public interface DialerCallListener { void onDialerCallUpgradeToVideo(); + default void onDialerCallUpgradeToRtt(int rttRequestId) {} + void onDialerCallSessionModificationStateChange(); void onWiFiToLteHandover(); diff --git a/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml b/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml new file mode 100644 index 000000000..c6d9e991d --- /dev/null +++ b/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml @@ -0,0 +1,75 @@ + + + + + + + + + + +