Merge "Detect invalid Call Forwarding numbers and replace" into oc-mr1-dev
am: 112e5ada3c

Change-Id: I029ddd57bfd0469a87911957f3a1082a1918e997
diff --git a/src/com/android/phone/CallForwardEditPreference.java b/src/com/android/phone/CallForwardEditPreference.java
index 2cd4abc..49c652b 100644
--- a/src/com/android/phone/CallForwardEditPreference.java
+++ b/src/com/android/phone/CallForwardEditPreference.java
@@ -13,6 +13,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 import android.text.BidiFormatter;
 import android.text.SpannableString;
 import android.text.TextDirectionHeuristics;
@@ -43,6 +44,8 @@
     private Phone mPhone;
     CallForwardInfo callForwardInfo;
     private TimeConsumingPreferenceListener mTcpListener;
+    // Should we replace CF queries containing an invalid number with "Voicemail"
+    private boolean mReplaceInvalidCFNumber = false;
 
     public CallForwardEditPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -64,9 +67,11 @@
         this(context, null);
     }
 
-    void init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone) {
+    void init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone,
+            boolean replaceInvalidCFNumber) {
         mPhone = phone;
         mTcpListener = listener;
+        mReplaceInvalidCFNumber = replaceInvalidCFNumber;
 
         if (!skipReading) {
             mPhone.getCallForwardingOption(reason,
@@ -144,6 +149,15 @@
     void handleCallForwardResult(CallForwardInfo cf) {
         callForwardInfo = cf;
         Log.d(LOG_TAG, "handleGetCFResponse done, callForwardInfo=" + callForwardInfo);
+        // In some cases, the network can send call forwarding URIs for voicemail that violate the
+        // 3gpp spec. This can cause us to receive "numbers" that are sequences of letters. In this
+        // case, we must detect these series of characters and replace them with "Voicemail".
+        // PhoneNumberUtils#formatNumber returns null if the number is not valid.
+        if (mReplaceInvalidCFNumber && (PhoneNumberUtils.formatNumber(callForwardInfo.number,
+                getCurrentCountryIso()) == null)) {
+            callForwardInfo.number = getContext().getString(R.string.voicemail);
+            Log.i(LOG_TAG, "handleGetCFResponse: Overridding CF number");
+        }
 
         setToggled(callForwardInfo.status == 1);
         setPhoneNumber(callForwardInfo.number);
@@ -172,6 +186,19 @@
 
     }
 
+    /**
+     * @return The ISO 3166-1 two letters country code of the country the user is in based on the
+     *      network location.
+     */
+    private String getCurrentCountryIso() {
+        final TelephonyManager telephonyManager =
+                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        if (telephonyManager == null) {
+            return "";
+        }
+        return telephonyManager.getNetworkCountryIso().toUpperCase();
+    }
+
     // Message protocol:
     // what: get vs. set
     // arg1: action -- register vs. disable
diff --git a/src/com/android/phone/GsmUmtsCallForwardOptions.java b/src/com/android/phone/GsmUmtsCallForwardOptions.java
index 15b9bf0..77cc6cc 100644
--- a/src/com/android/phone/GsmUmtsCallForwardOptions.java
+++ b/src/com/android/phone/GsmUmtsCallForwardOptions.java
@@ -10,6 +10,7 @@
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceScreen;
+import android.telephony.CarrierConfigManager;
 import android.util.Log;
 import android.view.MenuItem;
 
@@ -45,6 +46,7 @@
     private Bundle mIcicle;
     private Phone mPhone;
     private SubscriptionInfoHelper mSubscriptionInfoHelper;
+    private boolean mReplaceInvalidCFNumbers;
 
     @Override
     protected void onCreate(Bundle icicle) {
@@ -57,6 +59,13 @@
                 getActionBar(), getResources(), R.string.call_forwarding_settings_with_label);
         mPhone = mSubscriptionInfoHelper.getPhone();
 
+        CarrierConfigManager carrierConfig = (CarrierConfigManager)
+                getSystemService(CARRIER_CONFIG_SERVICE);
+        if (carrierConfig != null) {
+            mReplaceInvalidCFNumbers = carrierConfig.getConfig().getBoolean(
+                    CarrierConfigManager.KEY_CALL_FORWARDING_MAP_NON_NUMBER_TO_VOICEMAIL_BOOL);
+        }
+
         PreferenceScreen prefSet = getPreferenceScreen();
         mButtonCFU = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFU_KEY);
         mButtonCFB = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFB_KEY);
@@ -94,7 +103,7 @@
         if (mFirstResume) {
             if (mIcicle == null) {
                 Log.d(LOG_TAG, "start to init ");
-                mPreferences.get(mInitIndex).init(this, false, mPhone);
+                mPreferences.get(mInitIndex).init(this, false, mPhone, mReplaceInvalidCFNumbers);
             } else {
                 mInitIndex = mPreferences.size();
 
@@ -105,7 +114,7 @@
                     cf.number = bundle.getString(KEY_NUMBER);
                     cf.status = bundle.getInt(KEY_STATUS);
                     pref.handleCallForwardResult(cf);
-                    pref.init(this, true, mPhone);
+                    pref.init(this, true, mPhone, mReplaceInvalidCFNumbers);
                 }
             }
             mFirstResume = false;
@@ -132,7 +141,7 @@
     public void onFinished(Preference preference, boolean reading) {
         if (mInitIndex < mPreferences.size()-1 && !isFinishing()) {
             mInitIndex++;
-            mPreferences.get(mInitIndex).init(this, false, mPhone);
+            mPreferences.get(mInitIndex).init(this, false, mPhone, mReplaceInvalidCFNumbers);
         }
 
         super.onFinished(preference, reading);
diff --git a/tests/src/com/android/phone/tests/CallForwardInfoTest.java b/tests/src/com/android/phone/tests/CallForwardInfoTest.java
new file mode 100644
index 0000000..acf5955
--- /dev/null
+++ b/tests/src/com/android/phone/tests/CallForwardInfoTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.phone.tests;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.PhoneNumberUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Tests Related to CallForwardInfoTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class CallForwardInfoTest {
+
+    @Test
+    public void testCallForwardNumberResponses() {
+        // Test numbers in correct formats
+        assertNotNull(PhoneNumberUtils.formatNumber("+12345678900", Locale.US.getCountry()));
+        assertNotNull(PhoneNumberUtils.formatNumber("123-456-7890", Locale.US.getCountry()));
+        assertNotNull(PhoneNumberUtils.formatNumber("#123", Locale.US.getCountry()));
+        assertNotNull(PhoneNumberUtils.formatNumber("*12", Locale.US.getCountry()));
+        // Test invalid numbers
+        assertNull(PhoneNumberUtils.formatNumber("a", Locale.US.getCountry()));
+        assertNull(PhoneNumberUtils.formatNumber("a1", Locale.US.getCountry()));
+    }
+}