Add supported URI scheme to PhoneAccounts. (3/4)

1. Modify TelephonyConnectionService to register voidemail URI scheme.
2. Modify SipConnectionService to register 'tel' URI scheme in addition
to 'sip', should the user have chosen to use sip for all calls.
3. Modify SipBroadcastReceiver to listen to ACTION_SIP_CALL_OPTION_CHANGED
intent, triggering a rebuild of the SIP PhoneAccounts.
4. Fixed bug where all incoming SIP calls show as Unknown number.

Bug: 17140110
Bug: 17326799
Change-Id: I11d25c2cd98d02b80919d95ae9af077edb179fe0
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 66821ee..45c1e82 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -490,6 +490,7 @@
                 <action android:name="com.android.phone.SIP_INCOMING_CALL" />
                 <action android:name="com.android.phone.SIP_ADD_PHONE" />
                 <action android:name="com.android.phone.SIP_REMOVE_PHONE" />
+                <action android:name="com.android.phone.SIP_CALL_OPTION_CHANGED" />
             </intent-filter>
         </receiver>
 
diff --git a/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
index 8aca613..f830f67 100644
--- a/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
+++ b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
@@ -22,6 +22,7 @@
 import android.net.sip.SipException;
 import android.net.sip.SipManager;
 import android.net.sip.SipProfile;
+import android.provider.Settings;
 import android.telecomm.PhoneAccount;
 import android.telecomm.PhoneAccountHandle;
 import android.telecomm.TelecommManager;
@@ -65,16 +66,25 @@
         }
 
         private PhoneAccount createPhoneAccount(Context context) {
+            boolean useSipForPstnCalls = useSipForPstnCalls(context);
+
             PhoneAccountHandle accountHandle =
                     SipUtil.createAccountHandle(context, mProfile.getUriString());
-            return PhoneAccount.builder()
+
+            PhoneAccount.Builder builder = PhoneAccount.builder()
                     .withAccountHandle(accountHandle)
                     .withCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                     .withHandle(Uri.parse(mProfile.getUriString()))
                     .withLabel(mProfile.getDisplayName())
                     .withShortDescription(mProfile.getDisplayName())
                     .withIconResId(R.drawable.ic_dialer_sip_black_24dp)
-                    .build();
+                    .withSupportedUriScheme(PhoneAccount.SCHEME_SIP);
+
+            if (useSipForPstnCalls) {
+                builder.withSupportedUriScheme(PhoneAccount.SCHEME_TEL);
+            }
+
+            return builder.build();
         }
     }
 
@@ -144,6 +154,7 @@
     private void registerAccountForProfile(
             SipProfile profile, SipManager sipManager, Context context) {
         AccountEntry entry = new AccountEntry(profile);
+
         if (entry.register(sipManager, context)) {
             mAccounts.add(entry);
         }
@@ -160,6 +171,16 @@
         }
     }
 
+    /**
+     * Determines if the user has chosen to use SIP for PSTN calls as well as SIP calls.
+     * @param context The context.
+     * @return {@code True} if SIP should be used for PSTN calls.
+     */
+    private boolean useSipForPstnCalls(Context context) {
+        final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
+        return sipSharedPreferences.getSipCallOption().equals(Settings.System.SIP_ALWAYS);
+    }
+
     private void log(String message) {
         Log.d(SipUtil.LOG_TAG, PREFIX + message);
     }
diff --git a/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java b/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
index 2adb61a..a113805 100644
--- a/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
+++ b/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
@@ -44,7 +44,8 @@
         SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance();
         if (action.equals(SipManager.ACTION_SIP_INCOMING_CALL)) {
             takeCall(context, intent);
-        } else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP)) {
+        } else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP) ||
+                action.equals(SipManager.ACTION_SIP_CALL_OPTION_CHANGED)) {
             sipAccountRegistry.setup(context);
         } else if (action.equals(SipManager.ACTION_SIP_ADD_PHONE)) {
             if (VERBOSE) log("SIP_ADD_PHONE " + intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
diff --git a/sip/src/com/android/services/telephony/sip/SipConnection.java b/sip/src/com/android/services/telephony/sip/SipConnection.java
index 2579159..534b27a 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnection.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnection.java
@@ -16,6 +16,7 @@
 
 package com.android.services.telephony.sip;
 
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
 import android.telecomm.AudioState;
@@ -26,8 +27,10 @@
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.sip.SipPhone;
+import com.android.phone.Constants;
 
 import java.util.List;
+import java.util.Objects;
 
 final class SipConnection extends Connection {
     private static final String PREFIX = "[SipConnection] ";
@@ -61,6 +64,7 @@
             getPhone().registerForPreciseCallStateChanged(mHandler, MSG_PRECISE_CALL_STATE_CHANGED,
                     null);
         }
+        updateHandle();
         setInitialized();
     }
 
@@ -268,6 +272,44 @@
         }
     }
 
+    /**
+     * Updates the handle on this connection based on the original connection.
+     */
+    private void updateHandle() {
+        if (mOriginalConnection != null) {
+            Uri handle = getHandleFromAddress(mOriginalConnection.getAddress());
+            int presentation = mOriginalConnection.getNumberPresentation();
+            if (!Objects.equals(handle, getHandle()) ||
+                    presentation != getHandlePresentation()) {
+                com.android.services.telephony.Log.v(this, "updateHandle, handle changed");
+                setHandle(handle, presentation);
+            }
+
+            String name = mOriginalConnection.getCnapName();
+            int namePresentation = mOriginalConnection.getCnapNamePresentation();
+            if (!Objects.equals(name, getCallerDisplayName()) ||
+                    namePresentation != getCallerDisplayNamePresentation()) {
+                com.android.services.telephony.Log
+                        .v(this, "updateHandle, caller display name changed");
+                setCallerDisplayName(name, namePresentation);
+            }
+        }
+    }
+
+    /**
+     * Determines the handle for an incoming number.
+     *
+     * @param address The incoming number.
+     * @return The Uri representing the number.
+     */
+    private static Uri getHandleFromAddress(String address) {
+        // Address can be null for blocked calls.
+        if (address == null) {
+            address = "";
+        }
+        return Uri.fromParts(Constants.SCHEME_SIP, address, null);
+    }
+
     private void close() {
         if (getPhone() != null) {
             getPhone().unregisterForPreciseCallStateChanged(mHandler);
diff --git a/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java b/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
index ff7a3c8..b5d1fc2 100644
--- a/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
+++ b/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
@@ -18,7 +18,9 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
 import android.content.SharedPreferences;
+import android.net.sip.SipManager;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
@@ -82,6 +84,12 @@
     public void setSipCallOption(String option) {
         Settings.System.putString(mContext.getContentResolver(),
                 Settings.System.SIP_CALL_OPTIONS, option);
+
+        // Notify SipAccountRegistry in the telephony layer that the configuration has changed.
+        // This causes the SIP PhoneAccounts to be re-registered.  This ensures the supported URI
+        // schemes for the SIP PhoneAccounts matches the new SIP_CALL_OPTIONS setting.
+        Intent intent = new Intent(SipManager.ACTION_SIP_CALL_OPTION_CHANGED);
+        mContext.sendBroadcast(intent);
     }
 
     public String getSipCallOption() {
diff --git a/src/com/android/services/telephony/TelecommAccountRegistry.java b/src/com/android/services/telephony/TelecommAccountRegistry.java
index c342e48..095073b 100644
--- a/src/com/android/services/telephony/TelecommAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecommAccountRegistry.java
@@ -104,6 +104,8 @@
                     .withIconResId(getPhoneAccountIcon(slotId))
                     .withLabel(label)
                     .withShortDescription(description)
+                    .withSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+                    .withSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
                     .build();
 
             // Register with Telecomm and put into the account entry.
@@ -131,6 +133,7 @@
     };
 
     private static final String TEL_SCHEME = "tel";
+    private static final String VOICEMAIL_SCHEME = "voicemail";
     private static TelecommAccountRegistry sInstance;
     private final Context mContext;
     private final TelecommManager mTelecommManager;