From b9b64d3935bb05169afb23375ebe38fb846e78c8 Mon Sep 17 00:00:00 2001 From: twyen Date: Fri, 23 Mar 2018 10:50:16 -0700 Subject: Implement wifi emergency calling warning The warning is shown when there is no service, and the carrier requires the message to be shown because they cannot make emergency call over wifi. Bug: 68030294 Test: Unit tests, integration tests. PiperOrigin-RevId: 190241868 Change-Id: Ia6b838ac1e8e62ad6b40d97c1cf1a970491c1e6f --- .../dialer/dialpadview/DialpadFragment.java | 97 +++++++++++++++++++++- .../android/dialer/dialpadview/DialpadView.java | 6 ++ .../res/layout/dialpad_view_unthemed.xml | 61 ++++++++------ .../dialer/dialpadview/res/values/strings.xml | 6 +- 4 files changed, 142 insertions(+), 28 deletions(-) (limited to 'java') diff --git a/java/com/android/dialer/dialpadview/DialpadFragment.java b/java/com/android/dialer/dialpadview/DialpadFragment.java index 833b91f59..6f8d677e8 100644 --- a/java/com/android/dialer/dialpadview/DialpadFragment.java +++ b/java/com/android/dialer/dialpadview/DialpadFragment.java @@ -16,6 +16,7 @@ package com.android.dialer.dialpadview; +import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; @@ -34,6 +35,8 @@ import android.graphics.BitmapFactory; import android.media.AudioManager; import android.media.ToneGenerator; import android.net.Uri; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Trace; import android.provider.Contacts.People; @@ -48,6 +51,7 @@ import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telephony.PhoneNumberFormattingTextWatcher; import android.telephony.PhoneNumberUtils; +import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.text.Editable; import android.text.Selection; @@ -75,6 +79,7 @@ import android.widget.TextView; import com.android.contacts.common.dialog.CallSubjectDialog; import com.android.contacts.common.util.StopWatch; import com.android.dialer.animation.AnimUtils; +import com.android.dialer.animation.AnimUtils.AnimationCallback; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.common.Assert; @@ -141,7 +146,18 @@ public class DialpadFragment extends Fragment private static final String PREF_DIGITS_FILLED_BY_INTENT = "pref_digits_filled_by_intent"; private static final String PREF_IS_DIALPAD_SLIDE_OUT = "pref_is_dialpad_slide_out"; + /** + * Hidden key in carrier config to determine if no emergency call over wifi warning is required. + * + *

"Time delay (in ms) after which we show the notification for emergency calls, while the + * device is registered over WFC. Default value is -1, which indicates that this notification is + * not pertinent for a particular carrier. We've added a delay to prevent false positives." + */ + @VisibleForTesting + static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT = "emergency_notification_delay_int"; + private static Optional currentCountryIsoForTesting = Optional.absent(); + private static Boolean showEmergencyCallWarningForTest = null; private final Object toneGeneratorLock = new Object(); /** Set of dialpad keys that are currently being pressed */ @@ -303,6 +319,7 @@ public class DialpadFragment extends Fragment activity.invalidateOptionsMenu(); updateMenuOverflowButton(wasEmptyBeforeTextChange); } + updateDialpadHint(); } // DTMF Tones do not need to be played here any longer - @@ -439,6 +456,73 @@ public class DialpadFragment extends Fragment return fragmentView; } + /** + * The dialpad hint is a TextView overlaid above the digit EditText. {@link EditText#setHint(int)} + * is not used because the digits has auto resize and makes setting the size of the hint + * difficult. + */ + private void updateDialpadHint() { + TextView hint = dialpadView.getDigitsHint(); + if (!TextUtils.isEmpty(digits.getText())) { + hint.setVisibility(View.GONE); + return; + } + + if (shouldShowEmergencyCallWarning(getContext())) { + hint.setText(getContext().getString(R.string.dialpad_hint_emergency_calling_not_available)); + hint.setVisibility(View.VISIBLE); + return; + } + hint.setVisibility(View.GONE); + } + + /** + * Only show the "emergency call not available" warning when on wifi call and carrier requires it. + * + *

internal method tested because the conditions cannot be setup in espresso, and the layout + * cannot be inflated in robolectric. + */ + @SuppressWarnings("missingPermission") + @TargetApi(VERSION_CODES.O) + @VisibleForTesting + static boolean shouldShowEmergencyCallWarning(Context context) { + if (showEmergencyCallWarningForTest != null) { + return showEmergencyCallWarningForTest; + } + if (VERSION.SDK_INT < VERSION_CODES.O) { + return false; + } + if (!PermissionsUtil.hasReadPhoneStatePermissions(context)) { + return false; + } + TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); + // A delay of -1 means wifi emergency call is available/the warning is not required. + if (telephonyManager.getCarrierConfig().getInt(KEY_EMERGENCY_NOTIFICATION_DELAY_INT, -1) + == -1) { + return false; + } + + // TelephonyManager.getVoiceNetworkType() Doesn't always return NETWORK_TYPE_IWLAN when on wifi. + // other wifi calling checks are hidden API. Emergency calling is not available without service + // regardless of the wifi state so this check is omitted. + + switch (telephonyManager.getServiceState().getState()) { + case ServiceState.STATE_OUT_OF_SERVICE: + case ServiceState.STATE_POWER_OFF: + return true; + case ServiceState.STATE_EMERGENCY_ONLY: + case ServiceState.STATE_IN_SERVICE: + return false; + default: + throw new AssertionError("unknown state " + telephonyManager.getServiceState().getState()); + } + } + + @VisibleForTesting + static void setShowEmergencyCallWarningForTest(Boolean value) { + showEmergencyCallWarningForTest = value; + } + @Override public void onAttach(Context context) { super.onAttach(context); @@ -732,6 +816,8 @@ public class DialpadFragment extends Fragment overflowMenuButton.setOnClickListener(this); overflowMenuButton.setVisibility(isDigitsEmpty() ? View.INVISIBLE : View.VISIBLE); + updateDialpadHint(); + if (firstLaunch) { // The onHiddenChanged callback does not get called the first time the fragment is // attached, so call it ourselves here. @@ -1392,7 +1478,16 @@ public class DialpadFragment extends Fragment if (transitionIn) { AnimUtils.fadeIn(overflowMenuButton, AnimUtils.DEFAULT_DURATION); } else { - AnimUtils.fadeOut(overflowMenuButton, AnimUtils.DEFAULT_DURATION); + AnimUtils.fadeOut( + overflowMenuButton, + AnimUtils.DEFAULT_DURATION, + new AnimationCallback() { + @Override + public void onAnimationEnd() { + // AnimUtils will set the visibility to GONE and cause the layout to move around. + overflowMenuButton.setVisibility(View.INVISIBLE); + } + }); } } diff --git a/java/com/android/dialer/dialpadview/DialpadView.java b/java/com/android/dialer/dialpadview/DialpadView.java index 58ba233bd..1bd8bad4f 100644 --- a/java/com/android/dialer/dialpadview/DialpadView.java +++ b/java/com/android/dialer/dialpadview/DialpadView.java @@ -82,6 +82,7 @@ public class DialpadView extends LinearLayout { private final int translateDistance; private EditText digits; + private TextView digitsHint; private ImageButton delete; private View overflowMenuButton; private ViewGroup rateContainer; @@ -134,6 +135,7 @@ public class DialpadView extends LinearLayout { setupKeypad(); digits = (EditText) findViewById(R.id.digits); + digitsHint = findViewById(R.id.digits_hint); delete = (ImageButton) findViewById(R.id.deleteButton); overflowMenuButton = findViewById(R.id.dialpad_overflow); rateContainer = (ViewGroup) findViewById(R.id.rate_container); @@ -311,6 +313,10 @@ public class DialpadView extends LinearLayout { return digits; } + public TextView getDigitsHint() { + return digitsHint; + } + public ImageButton getDeleteButton() { return delete; } diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml index 13c11f1ce..69d23a9b6 100644 --- a/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml +++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml @@ -13,9 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - + + + + - + diff --git a/java/com/android/dialer/dialpadview/res/values/strings.xml b/java/com/android/dialer/dialpadview/res/values/strings.xml index 51367b644..5d8d8e6a5 100644 --- a/java/com/android/dialer/dialpadview/res/values/strings.xml +++ b/java/com/android/dialer/dialpadview/res/values/strings.xml @@ -97,7 +97,11 @@ Ignored if empty. --> + + Emergency calling not available + - Can\'t call this number + Can\'t call this number -- cgit v1.2.3