Permission check for ConnectionService PhoneAccounts. (1/2)

Adding permission check which ocurrs when registering a PhoneAccount.
The permission ensures the ConnectionService for the PhoneAccount
has BIND_CONNECTION_SERVICE permission.
Removed lookupServices method in ConnectionServiceRepository,
which was unused.
Set TestConnectionService service permission to BIND_CONNECTION_SERVICE.

Bug: 16171070
Change-Id: I5475a1af9e63deef9ceb3a549425a8c3b5f7e175
diff --git a/src/com/android/telecomm/ConnectionServiceRepository.java b/src/com/android/telecomm/ConnectionServiceRepository.java
index ec2c90e..efd1ba4 100644
--- a/src/com/android/telecomm/ConnectionServiceRepository.java
+++ b/src/com/android/telecomm/ConnectionServiceRepository.java
@@ -38,21 +38,6 @@
     ConnectionServiceRepository() {
     }
 
-    Collection<ConnectionServiceWrapper> lookupServices() {
-        PackageManager packageManager = TelecommApp.getInstance().getPackageManager();
-        Intent intent = new Intent(ConnectionService.SERVICE_INTERFACE);
-        ArrayList<ConnectionServiceWrapper> services = new ArrayList<>();
-
-        for (ResolveInfo entry : packageManager.queryIntentServices(intent, 0)) {
-            ServiceInfo serviceInfo = entry.serviceInfo;
-            if (serviceInfo != null) {
-                services.add(getService(new ComponentName(
-                        serviceInfo.packageName, serviceInfo.name)));
-            }
-        }
-        return services;
-    }
-
     ConnectionServiceWrapper getService(ComponentName componentName) {
         ConnectionServiceWrapper service = mServiceCache.get(componentName);
         if (service == null) {
diff --git a/src/com/android/telecomm/CreateConnectionProcessor.java b/src/com/android/telecomm/CreateConnectionProcessor.java
index 3e6e544..aacb80b 100644
--- a/src/com/android/telecomm/CreateConnectionProcessor.java
+++ b/src/com/android/telecomm/CreateConnectionProcessor.java
@@ -107,9 +107,32 @@
 
     private void attemptNextPhoneAccount() {
         Log.v(this, "attemptNextPhoneAccount");
+        PhoneAccountRegistrar registrar = TelecommApp.getInstance().getPhoneAccountRegistrar();
+        CallAttemptRecord attempt = null;
+        if (mAttemptRecordIterator.hasNext()) {
+            attempt = mAttemptRecordIterator.next();
 
-        if (mResponse != null && mAttemptRecordIterator.hasNext()) {
-            CallAttemptRecord attempt = mAttemptRecordIterator.next();
+            if (!registrar.phoneAccountHasPermission(attempt.connectionManagerPhoneAccount)) {
+                Log.w(this,
+                        "Connection mgr does not have BIND_CONNECTION_SERVICE for attempt: %s",
+                        attempt);
+                attemptNextPhoneAccount();
+                return;
+            }
+
+            // If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it
+            // also has BIND_CONNECTION_SERVICE permission.
+            if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) &&
+                    !registrar.phoneAccountHasPermission(attempt.targetPhoneAccount)) {
+                Log.w(this,
+                        "Target PhoneAccount does not have BIND_CONNECTION_SERVICE for attempt: %s",
+                        attempt);
+                attemptNextPhoneAccount();
+                return;
+            }
+        }
+
+        if (mResponse != null && attempt != null) {
             Log.i(this, "Trying attempt %s", attempt);
             ConnectionServiceWrapper service =
                     mRepository.getService(
diff --git a/src/com/android/telecomm/PhoneAccountRegistrar.java b/src/com/android/telecomm/PhoneAccountRegistrar.java
index 71eb95b..f3a5a0b 100644
--- a/src/com/android/telecomm/PhoneAccountRegistrar.java
+++ b/src/com/android/telecomm/PhoneAccountRegistrar.java
@@ -16,9 +16,11 @@
 
 package com.android.telecomm;
 
+import android.Manifest;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.telecomm.ConnectionService;
 import android.telecomm.PhoneAccount;
 import android.telecomm.PhoneAccountHandle;
@@ -45,6 +47,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.SecurityException;
 import java.lang.String;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -231,6 +234,15 @@
     // TODO: Should we implement an artificial limit for # of accounts associated with a single
     // ComponentName?
     public void registerPhoneAccount(PhoneAccount account) {
+        // Enforce the requirement that a connection service for a phone account has the correct
+        // permission.
+        if (!phoneAccountHasPermission(account.getAccountHandle())) {
+            Log.w(this, "Phone account %s does not have BIND_CONNECTION_SERVICE permission.",
+                    account.getAccountHandle());
+            throw new SecurityException(
+                    "PhoneAccount connection service requires BIND_CONNECTION_SERVICE permission.");
+        }
+
         mState.accounts.add(account);
         // Search for duplicates and remove any that are found.
         for (int i = 0; i < mState.accounts.size() - 1; i++) {
@@ -311,6 +323,27 @@
         }
     }
 
+    /**
+     * Determines if the connection service specified by a {@link PhoneAccountHandle} has the
+     * {@link Manifest.permission#BIND_CONNECTION_SERVICE} permission.
+     *
+     * @param phoneAccountHandle The phone account to check.
+     * @return {@code True} if the phone account has permission.
+     */
+    public boolean phoneAccountHasPermission(PhoneAccountHandle phoneAccountHandle) {
+        PackageManager packageManager = TelecommApp.getInstance().getPackageManager();
+        try {
+            ServiceInfo serviceInfo = packageManager.getServiceInfo(
+                    phoneAccountHandle.getComponentName(), 0);
+
+            return serviceInfo.permission != null &&
+                    serviceInfo.permission.equals(Manifest.permission.BIND_CONNECTION_SERVICE);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(this, "Name not found %s", e);
+            return false;
+        }
+    }
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
 
     // TODO: Add a corresponding has(...) method to class PhoneAccount itself and remove this one
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index c17803f..d8877fb 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -29,13 +29,15 @@
 
         <!-- Miscellaneous telecomm app-related test activities. -->
 
-        <service android:name="com.android.telecomm.testapps.TestConnectionService">
+        <service android:name="com.android.telecomm.testapps.TestConnectionService"
+                 android:permission="android.permission.BIND_CONNECTION_SERVICE" >
             <intent-filter>
                 <action android:name="android.telecomm.ConnectionService" />
             </intent-filter>
         </service>
 
-        <service android:name="com.android.telecomm.testapps.TestConnectionManager">
+        <service android:name="com.android.telecomm.testapps.TestConnectionManager"
+                 android:permission="android.permission.BIND_CONNECTION_SERVICE" >
             <intent-filter>
                 <action android:name="android.telecomm.ConnectionService" />
             </intent-filter>