Implement VisualVoicemailService cascading.

This CL determines which VisualVoicemailService should be active.
The order is:

1. Current default dialer
The dialer might disable itself when a carrier VVM package is
installed.

2. The carrier packages
Designated with CarrierConfig using KEY_CARRIER_VVM_PACKAGE_NAME_STRING.
This value is used before solely to disable the system client.
KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY should be added to allow
multiple clients.

3. The system package.
A device specific package override-able with
R.string.system_visual_voicemail_client

4. The system dialer.

Bug: 34132028
Bug: 32414216
Change-Id: Ifa6d0bbb3033a14757ab99226f28aca245848c0f
Merged-in: Ifa6d0bbb3033a14757ab99226f28aca245848c0f
Fixes: 34132028
Test: manual test using the dialer and the system package.
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 130e9a8..81de9d7 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -94,10 +94,10 @@
 import com.android.internal.util.HexDump;
 import com.android.phone.settings.VisualVoicemailSettingsUtil;
 import com.android.phone.settings.VoicemailNotificationSettingsUtil;
+import com.android.phone.vvm.RemoteVvmTaskManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -2069,7 +2069,7 @@
     public void sendVisualVoicemailSmsForSubscriber(String callingPackage, int subId,
             String number, int port, String text, PendingIntent sentIntent) {
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
-        enforceDefaultDialer(callingPackage);
+        enforceVisualVoicemailPackage(callingPackage, subId);
         enforceSendSmsPermission();
         // Make the calls as the phone process.
         final long identity = Binder.clearCallingIdentity();
@@ -3432,14 +3432,16 @@
     }
 
     /**
-     * Make sure called from the default dialer
+     * Make sure called from the package in charge of visual voicemail.
      *
-     * @throws SecurityException if the caller is not the default dialer
+     * @throws SecurityException if the caller is not the visual voicemail package.
      */
-    private void enforceDefaultDialer(String callingPackage) {
-        TelecomManager telecomManager = mPhone.getContext().getSystemService(TelecomManager.class);
-        if (!callingPackage.equals(telecomManager.getDefaultDialerPackage())) {
-            throw new SecurityException("Caller not default dialer.");
+    private void enforceVisualVoicemailPackage(String callingPackage, int subId) {
+        String vvmPackage = RemoteVvmTaskManager.getRemotePackage(mPhone.getContext(), subId)
+                .getPackageName();
+        if (!callingPackage.equals(vvmPackage)) {
+            throw new SecurityException("Caller not current active visual voicemail package[" +
+                    vvmPackage + "]");
         }
     }
 
diff --git a/src/com/android/phone/VisualVoicemailSmsFilterConfig.java b/src/com/android/phone/VisualVoicemailSmsFilterConfig.java
index 2ffb477..db79e2b 100644
--- a/src/com/android/phone/VisualVoicemailSmsFilterConfig.java
+++ b/src/com/android/phone/VisualVoicemailSmsFilterConfig.java
@@ -64,7 +64,7 @@
 
     public static VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(
             Context context, int subId) {
-        ComponentName componentName = RemoteVvmTaskManager.getRemotePackage(context);
+        ComponentName componentName = RemoteVvmTaskManager.getRemotePackage(context, subId);
         String packageName;
         if (componentName == null) {
             packageName = DEFAULT_PACKAGE;
diff --git a/src/com/android/phone/vvm/RemoteVvmTaskManager.java b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
index ce6fce6..9236bd2 100644
--- a/src/com/android/phone/vvm/RemoteVvmTaskManager.java
+++ b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
@@ -29,16 +29,23 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Messenger;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
 import android.telephony.VisualVoicemailService;
 import android.telephony.VisualVoicemailSms;
+import android.text.TextUtils;
 
 import com.android.phone.Assert;
+import com.android.phone.R;
 import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
 
+import java.util.ArrayList;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Queue;
 
 /**
@@ -93,18 +100,39 @@
         context.startService(intent);
     }
 
-    public static boolean hasRemoteService(Context context) {
-        return getRemotePackage(context) != null;
+    public static boolean hasRemoteService(Context context, int subId) {
+        return getRemotePackage(context, subId) != null;
     }
 
-    public static ComponentName getRemotePackage(Context context) {
+    public static ComponentName getRemotePackage(Context context, int subId) {
+        Intent bindIntent = newBindIntent(context);
 
-        ResolveInfo info = context.getPackageManager()
-                .resolveService(newBindIntent(context), PackageManager.MATCH_ALL);
-        if (info == null) {
-            return null;
+        TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+        List<String> packages = new ArrayList<>();
+        packages.add(telecomManager.getDefaultDialerPackage());
+        PersistableBundle carrierConfig = context
+                .getSystemService(CarrierConfigManager.class).getConfigForSubId(subId);
+        packages.add(
+                carrierConfig.getString(CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING));
+        for (String packageName : carrierConfig
+                .getStringArray(CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY)) {
+            packages.add(packageName);
         }
-        return info.getComponentInfo().getComponentName();
+        packages.add(context.getResources().getString(R.string.system_visual_voicemail_client));
+        packages.add(telecomManager.getSystemDialerPackage());
+        for (String packageName : packages) {
+            if (TextUtils.isEmpty(packageName)) {
+                continue;
+            }
+            bindIntent.setPackage(packageName);
+            ResolveInfo info = context.getPackageManager()
+                    .resolveService(bindIntent, PackageManager.MATCH_ALL);
+            if (info != null) {
+                return info.getComponentInfo().getComponentName();
+            }
+
+        }
+        return null;
     }
 
     @Override
@@ -130,15 +158,27 @@
     public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
         Assert.isMainThread();
         mTaskReferenceCount++;
+
+        PhoneAccountHandle phoneAccountHandle = intent.getExtras()
+                .getParcelable(VisualVoicemailService.DATA_PHONE_ACCOUNT_HANDLE);
+        int subId = PhoneAccountHandleConverter.toSubId(phoneAccountHandle);
+        ComponentName remotePackage = getRemotePackage(this, subId);
+        if (remotePackage == null) {
+            VvmLog.i(TAG, "No service to handle " + intent.getAction() + ", ignoring");
+            checkReference();
+            return START_NOT_STICKY;
+        }
+
         switch (intent.getAction()) {
             case ACTION_START_CELL_SERVICE_CONNECTED:
-                send(VisualVoicemailService.MSG_ON_CELL_SERVICE_CONNECTED, intent.getExtras());
+                send(remotePackage, VisualVoicemailService.MSG_ON_CELL_SERVICE_CONNECTED,
+                        intent.getExtras());
                 break;
             case ACTION_START_SMS_RECEIVED:
-                send(VisualVoicemailService.MSG_ON_SMS_RECEIVED, intent.getExtras());
+                send(remotePackage, VisualVoicemailService.MSG_ON_SMS_RECEIVED, intent.getExtras());
                 break;
             case ACTION_START_SIM_REMOVED:
-                send(VisualVoicemailService.MSG_ON_SIM_REMOVED, intent.getExtras());
+                send(remotePackage, VisualVoicemailService.MSG_ON_SIM_REMOVED, intent.getExtras());
                 break;
             default:
                 Assert.fail("Unexpected action +" + intent.getAction());
@@ -217,7 +257,7 @@
         }
     }
 
-    private void send(int what, Bundle extras) {
+    private void send(ComponentName remotePackage,int what, Bundle extras) {
         Assert.isMainThread();
         Message message = Message.obtain();
         message.what = what;
@@ -229,12 +269,16 @@
 
         if (!mConnection.isConnected()) {
             Intent intent = newBindIntent(this);
-            intent.setComponent(getRemotePackage(this));
+            intent.setComponent(remotePackage);
+            VvmLog.i(TAG, "Binding to " + intent.getComponent());
             bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
         }
     }
 
     private void checkReference() {
+        if (mConnection == null) {
+            return;
+        }
         if (mTaskReferenceCount == 0) {
             unbindService(mConnection);
             mConnection = null;
@@ -244,8 +288,6 @@
     private static Intent newBindIntent(Context context) {
         Intent intent = new Intent();
         intent.setAction(VisualVoicemailService.SERVICE_INTERFACE);
-        TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
-        intent.setPackage(telecomManager.getDefaultDialerPackage());
         return intent;
     }
 }
diff --git a/src/com/android/phone/vvm/VvmSmsReceiver.java b/src/com/android/phone/vvm/VvmSmsReceiver.java
index 91e7933..feaa46b 100644
--- a/src/com/android/phone/vvm/VvmSmsReceiver.java
+++ b/src/com/android/phone/vvm/VvmSmsReceiver.java
@@ -20,10 +20,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.provider.VoicemailContract;
+import android.telephony.SubscriptionManager;
 import android.telephony.VisualVoicemailSms;
 
 import com.android.phone.vvm.omtp.VvmLog;
 import com.android.phone.vvm.omtp.sms.OmtpMessageReceiver;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
 
 /**
  * Receives the SMS filtered by {@link com.android.internal.telephony.VisualVoicemailSmsFilter} and
@@ -45,7 +47,13 @@
             return;
         }
 
-        if (RemoteVvmTaskManager.hasRemoteService(context)) {
+        int subId = PhoneAccountHandleConverter.toSubId(sms.getPhoneAccountHandle());
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            VvmLog.e(TAG, "Received message for invalid subId");
+            return;
+        }
+
+        if (RemoteVvmTaskManager.hasRemoteService(context, subId)) {
             VvmLog.i(TAG, "Sending SMS received event to remote service");
             RemoteVvmTaskManager.startSmsReceived(context, sms);
             return;
diff --git a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
index 0f93f01..fb8f02d 100644
--- a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
+++ b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
@@ -28,6 +28,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
@@ -56,7 +57,15 @@
             return;
         }
 
-        if (RemoteVvmTaskManager.hasRemoteService(context)) {
+        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            VvmLog.i(TAG, "Received SIM change for invalid subscription id.");
+            return;
+        }
+
+        if (RemoteVvmTaskManager.hasRemoteService(context, subId)) {
             return;
         }
 
@@ -69,13 +78,7 @@
                 }
                 break;
             case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
-                int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
-                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
 
-                if (!SubscriptionManager.isValidSubscriptionId(subId)) {
-                    VvmLog.i(TAG, "Received SIM change for invalid subscription id.");
-                    return;
-                }
 
                 TelephonyManager telephonyManager = context
                         .getSystemService(TelephonyManager.class);
diff --git a/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java b/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
index 21cce31..f725f96 100644
--- a/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
+++ b/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
@@ -22,6 +22,7 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telephony.SubscriptionManager;
+
 import com.android.phone.vvm.RemoteVvmTaskManager;
 import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
 
@@ -46,10 +47,6 @@
             return;
         }
 
-        if (RemoteVvmTaskManager.hasRemoteService(context)) {
-            return;
-        }
-
         VvmLog.v(TAG, "processing subId list");
         for (PhoneAccountHandle handle : TelecomManager.from(context)
                 .getCallCapablePhoneAccounts()) {
@@ -60,6 +57,10 @@
                 VvmLog.e(TAG, "phone account " + handle + " has invalid subId " + subId);
                 continue;
             }
+            if (RemoteVvmTaskManager.hasRemoteService(context, subId)) {
+                return;
+            }
+
             VvmLog.v(TAG, "processing subId " + subId);
             SimChangeReceiver.processSubId(context, subId);
         }
diff --git a/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java b/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
index 31c173d..75ffc71 100644
--- a/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
+++ b/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
@@ -20,6 +20,7 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
+
 import com.android.phone.PhoneUtils;
 import com.android.phone.VoicemailStatus;
 import com.android.phone.vvm.RemoteVvmTaskManager;
@@ -55,7 +56,7 @@
             return;
         }
 
-        if (RemoteVvmTaskManager.hasRemoteService(mContext)) {
+        if (RemoteVvmTaskManager.hasRemoteService(mContext, subId)) {
             return;
         }