Change Sim Call Managers to use default dialer app instead.

Bug: 21499476
Change-Id: I60505ac1699f287656434b55d81aa61d4ae4ce14
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index f2e97bb..79489e0 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -35,6 +35,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.telecom.ConnectionService;
+import android.telecom.DefaultDialerManager;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.CarrierConfigManager;
@@ -264,43 +265,18 @@
                 SubscriptionManager.getDefaultSmsSubId();
     }
 
-    public void setSimCallManager(PhoneAccountHandle callManager) {
-        if (callManager != null) {
-            // TODO: Do we really want to return for *any* user?
-            PhoneAccount callManagerAccount = getPhoneAccount(callManager);
-            if (callManagerAccount == null) {
-                Log.d(this, "setSimCallManager: Nonexistent call manager: %s", callManager);
-                return;
-            } else if (!callManagerAccount.hasCapabilities(
-                    PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) {
-                Log.d(this, "setSimCallManager: Not a call manager: %s", callManagerAccount);
-                return;
-            }
-        } else {
-            callManager = NO_ACCOUNT_SELECTED;
-        }
-        mState.simCallManager = callManager;
-
-        write();
-        fireSimCallManagerChanged();
-    }
-
     /**
-     * @return The {@link PhoneAccount}s which are visible to {@link #mCurrentUserHandle}.
+     * Returns the {@link PhoneAccountHandle} corresponding to the currently active SIM Call
+     * Manager. SIM Call Manager returned corresponds to the following priority order:
+     * 1. If a SIM Call Manager {@link PhoneAccount} is registered for the same package as the
+     * default dialer, then that one is returned.
+     * 2. If there is a SIM Call Manager {@link PhoneAccount} registered which matches the
+     * carrier configuration's default, then that one is returned.
+     * 3. Otherwise, we return null.
      */
     public PhoneAccountHandle getSimCallManager() {
-        // If the "None" account was selected, return null (symmetry with setSimCallManager).
-        if (NO_ACCOUNT_SELECTED.equals(mState.simCallManager)) {
-            return null;
-        }
-
-        PhoneAccount account = getPhoneAccountCheckCallingUser(mState.simCallManager);
-
-        // Return the registered sim call manager iff it still exists (we keep a sticky
-        // setting to survive account deletion and re-addition)
-        if (account != null && !resolveComponent(mState.simCallManager).isEmpty()) {
-            return mState.simCallManager;
-        }
+        // Get the default dialer in case it has a connection manager associated with it.
+        String dialerPackage = DefaultDialerManager.getDefaultDialerApplication(mContext);
 
         // Check carrier config.
         String defaultSimCallManager = null;
@@ -312,34 +288,40 @@
                     CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING);
         }
 
-        if (!TextUtils.isEmpty(defaultSimCallManager)) {
-            ComponentName componentName = ComponentName.unflattenFromString(defaultSimCallManager);
-            if (componentName == null) {
-                return null;
-            }
+        ComponentName systemSimCallManagerComponent = TextUtils.isEmpty(defaultSimCallManager) ?
+                null : ComponentName.unflattenFromString(defaultSimCallManager);
 
-            // Make sure that the component can be resolved.
-            List<ResolveInfo> resolveInfos = resolveComponent(componentName, null);
-            if (resolveInfos.isEmpty()) {
-                resolveInfos = resolveComponent(componentName, Binder.getCallingUserHandle());
-            }
+        PhoneAccountHandle dialerSimCallManager = null;
+        PhoneAccountHandle systemSimCallManager = null;
 
-            if (!resolveInfos.isEmpty()) {
-                // See if there is registered PhoneAccount by this component.
-                List<PhoneAccountHandle> handles = getPhoneAccountHandles(0, null, null, true);
-                for (PhoneAccountHandle handle : handles) {
-                    if (componentName.equals(handle.getComponentName())) {
-                        return handle;
-                    }
+        if (!TextUtils.isEmpty(dialerPackage) || systemSimCallManagerComponent != null) {
+            // loop through and look for any connection manager in the same package.
+            List<PhoneAccountHandle> allSimCallManagers = getPhoneAccountHandles(
+                    PhoneAccount.CAPABILITY_CONNECTION_MANAGER, null, null,
+                    true /* includeDisabledAccounts */);
+            for (PhoneAccountHandle accountHandle : allSimCallManagers) {
+                ComponentName component = accountHandle.getComponentName();
+
+                // Store the system connection manager if found
+                if (systemSimCallManager == null
+                        && Objects.equals(component, systemSimCallManagerComponent)
+                        && !resolveComponent(accountHandle).isEmpty()) {
+                    systemSimCallManager = accountHandle;
+
+                // Store the dialer connection manager if found
+                } else if (dialerSimCallManager == null
+                        && Objects.equals(component.getPackageName(), dialerPackage)
+                        && !resolveComponent(accountHandle).isEmpty()) {
+                    dialerSimCallManager = accountHandle;
                 }
-                Log.d(this, "%s does not have a PhoneAccount; not using as default", componentName);
-            } else {
-                Log.d(this, "%s could not be resolved; not using as default", componentName);
             }
-        } else {
-            Log.v(this, "No default connection manager specified");
         }
 
+        PhoneAccountHandle retval = dialerSimCallManager != null ?
+                dialerSimCallManager : systemSimCallManager;
+
+        Log.i(this, "SimCallManager queried, returning: %s", retval);
+
         return null;
     }
 
@@ -495,15 +477,6 @@
         return getPhoneAccountHandles(0, null, packageName, false);
     }
 
-    /**
-     * Retrieves a list of all phone account handles with the connection manager capability.
-     *
-     * @return The phone account handles.
-     */
-    public List<PhoneAccountHandle> getConnectionManagerPhoneAccounts() {
-        return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CONNECTION_MANAGER, null, null, true);
-    }
-
     // TODO: Should we implement an artificial limit for # of accounts associated with a single
     // ComponentName?
     public void registerPhoneAccount(PhoneAccount account) {
@@ -801,12 +774,6 @@
         public PhoneAccountHandle defaultOutgoing = null;
 
         /**
-         * A {@code PhoneAccount} having {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} which
-         * manages and optimizes a user's PSTN SIM connections.
-         */
-        public PhoneAccountHandle simCallManager;
-
-        /**
          * The complete list of {@code PhoneAccount}s known to the Telecom subsystem.
          */
         public final List<PhoneAccount> accounts = new ArrayList<>();
@@ -827,8 +794,7 @@
             pw.println("xmlVersion: " + mState.versionNumber);
             pw.println("defaultOutgoing: " + (mState.defaultOutgoing == null ? "none" :
                     mState.defaultOutgoing));
-            pw.println("simCallManager: " + (mState.simCallManager == null ? "none" :
-                    mState.simCallManager));
+            pw.println("simCallManager: " + getSimCallManager());
             pw.println("phoneAccounts:");
             pw.increaseIndent();
             for (PhoneAccount phoneAccount : mState.accounts) {
@@ -1058,7 +1024,6 @@
             new XmlSerialization<State>() {
         private static final String CLASS_STATE = "phone_account_registrar_state";
         private static final String DEFAULT_OUTGOING = "default_outgoing";
-        private static final String SIM_CALL_MANAGER = "sim_call_manager";
         private static final String ACCOUNTS = "accounts";
         private static final String VERSION = "version";
 
@@ -1075,12 +1040,6 @@
                     serializer.endTag(null, DEFAULT_OUTGOING);
                 }
 
-                if (o.simCallManager != null) {
-                    serializer.startTag(null, SIM_CALL_MANAGER);
-                    sPhoneAccountHandleXml.writeToXml(o.simCallManager, serializer, context);
-                    serializer.endTag(null, SIM_CALL_MANAGER);
-                }
-
                 serializer.startTag(null, ACCOUNTS);
                 for (PhoneAccount m : o.accounts) {
                     sPhoneAccountXml.writeToXml(m, serializer, context);
@@ -1107,17 +1066,6 @@
                         parser.nextTag();
                         s.defaultOutgoing = sPhoneAccountHandleXml.readFromXml(parser,
                                 s.versionNumber, context);
-                    } else if (parser.getName().equals(SIM_CALL_MANAGER)) {
-                        parser.nextTag();
-                        s.simCallManager = sPhoneAccountHandleXml.readFromXml(parser,
-                                s.versionNumber, context);
-                        if (s.simCallManager.getUserHandle() == null) {
-                            // This should never happen, but handle the upgrade case.
-                            s.simCallManager = new PhoneAccountHandle(
-                                    s.simCallManager.getComponentName(),
-                                    s.simCallManager.getId(),
-                                    Process.myUserHandle());
-                        }
                     } else if (parser.getName().equals(ACCOUNTS)) {
                         int accountsDepth = parser.getDepth();
                         while (XmlUtils.nextElementWithin(parser, accountsDepth)) {
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 5d20956..17f18b1 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -257,7 +257,17 @@
         public PhoneAccountHandle getSimCallManager() {
             synchronized (mLock) {
                 try {
-                    PhoneAccountHandle accountHandle = mPhoneAccountRegistrar.getSimCallManager();
+                    PhoneAccountHandle accountHandle = null;
+
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        accountHandle = mPhoneAccountRegistrar.getSimCallManager();
+                    } finally {
+                        // We restore early so that isVisibleToCaller invocation below uses the
+                        // right user context.
+                        Binder.restoreCallingIdentity(token);
+                    }
+
                     if (!isVisibleToCaller(accountHandle)) {
                         Log.d(this, "%s is not visible for the calling user [gsCM]", accountHandle);
                         return null;
@@ -271,41 +281,6 @@
         }
 
         @Override
-        public void setSimCallManager(PhoneAccountHandle accountHandle) {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                try {
-                    mPhoneAccountRegistrar.setSimCallManager(accountHandle);
-                } catch (Exception e) {
-                    Log.e(this, e, "setSimCallManager");
-                    throw e;
-                }
-            }
-        }
-
-        @Override
-        public List<PhoneAccountHandle> getSimCallManagers(String callingPackage) {
-            synchronized (mLock) {
-                if (!canReadPhoneState(callingPackage, "getSimCallManagers")) {
-                    return Collections.emptyList();
-                }
-
-                long token = Binder.clearCallingIdentity();
-                try {
-                    // TODO: Does this isVisible check actually work considering we are clearing
-                    // the calling identity?
-                    return filterForAccountsVisibleToCaller(
-                            mPhoneAccountRegistrar.getConnectionManagerPhoneAccounts());
-                } catch (Exception e) {
-                    Log.e(this, e, "getSimCallManagers");
-                    throw e;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            }
-        }
-
-        @Override
         public void registerPhoneAccount(PhoneAccount account) {
             synchronized (mLock) {
                 if (!mContext.getApplicationContext().getResources().getBoolean(
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index aa4a8e6..f815fed 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -141,42 +141,7 @@
     }
 
     public void testSimCallManager() throws Exception {
-        mComponentContextFixture.addConnectionService(
-                makeQuickConnectionServiceComponentName(),
-                Mockito.mock(IConnectionService.class));
-
-        PhoneAccountHandle simManager = makeQuickAccountHandle("sim_mgr");
-        PhoneAccount simManagerAccount = new PhoneAccount.Builder(simManager, "sim_mgr")
-                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER
-                        | PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
-                .build();
-        registerAndEnableAccount(simManagerAccount);
-        assertNull(mRegistrar.getSimCallManager());
-
-        // Test the basic case
-        mRegistrar.setSimCallManager(simManager);
-        assertEquals(simManager, mRegistrar.getSimCallManager());
-
-        // Make sure clearing it works, too
-        mRegistrar.unregisterPhoneAccount(simManager);
-        assertNull(mRegistrar.getSimCallManager());
-
-        // Re-registering it makes the setting come back
-        registerAndEnableAccount(simManagerAccount);
-        assertEquals(simManager, mRegistrar.getSimCallManager());
-
-        // Make sure that the manager has CAPABILITY_CONNECTION_MANAGER
-        PhoneAccountHandle simManagerImposter = makeQuickAccountHandle("imposter");
-        PhoneAccount simManagerImposterAccount =
-                new PhoneAccount.Builder(simManagerImposter, "imposter")
-                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
-                .build();
-        mRegistrar.registerPhoneAccount(simManagerImposterAccount);
-
-        mRegistrar.setSimCallManager(null);
-        assertNull(mRegistrar.getSimCallManager());
-        mRegistrar.setSimCallManager(simManagerImposter);
-        assertNull(mRegistrar.getSimCallManager());
+        // TODO
     }
 
     public void testDefaultOutgoing() throws Exception {
@@ -374,7 +339,6 @@
     private static void assertStateEquals(
             PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) {
         assertPhoneAccountHandleEquals(a.defaultOutgoing, b.defaultOutgoing);
-        assertPhoneAccountHandleEquals(a.simCallManager, b.simCallManager);
         assertEquals(a.accounts.size(), b.accounts.size());
         for (int i = 0; i < a.accounts.size(); i++) {
             assertPhoneAccountEquals(a.accounts.get(i), b.accounts.get(i));
@@ -387,7 +351,6 @@
         s.accounts.add(makeQuickAccount("id1", 1));
         s.accounts.add(makeQuickAccount("id2", 2));
         s.defaultOutgoing = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0");
-        s.simCallManager = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id1");
         return s;
     }
 }