Adds Package check and TestApps test for PhoneAccount

1) Adds a check to ensure that a ConnectionService
is setting a PhoneAccount from the same Package name.

2) Adds TestApp test that switches PhoneAccount.

Bug: 27059146
Test: TestApp send intent to switch PhoneAccount
Change-Id: I5ac7dd8859d747b3aaaf5370af26a10225f8d6c2
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index e59c75d..8a0e881 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -834,6 +834,11 @@
         @Override
         public void onPhoneAccountChanged(String callId, PhoneAccountHandle pHandle,
                 Session.Info sessionInfo) throws RemoteException {
+            // Check that the Calling Package matches PhoneAccountHandle's Component Package
+            if (pHandle != null) {
+                mAppOpsManager.checkPackage(Binder.getCallingUid(),
+                        pHandle.getComponentName().getPackageName());
+            }
             Log.startSession(sessionInfo, "CSW.oPAC");
             long token = Binder.clearCallingIdentity();
             try {
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index 75d467a..675df78 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -46,6 +46,13 @@
             </intent-filter>
         </service>
 
+        <receiver android:name=".TestConnectionServiceReceiver">
+            <intent-filter>
+                <action android:name="android.server.telecom.testapps.ACTION_SWITCH_PHONE_ACCOUNT"/>
+                <action android:name="android.server.telecom.testapps.ACTION_SWITCH_PHONE_ACCOUNT_WRONG"/>
+            </intent-filter>
+        </receiver>
+
         <service android:name="com.android.server.telecom.testapps.TestConnectionManager"
                  android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" >
             <intent-filter>
@@ -72,6 +79,8 @@
             </intent-filter>
         </receiver>
 
+
+
         <activity android:name="com.android.server.telecom.testapps.TestInCallUI"
                 android:process="com.android.server.telecom.testapps.TestInCallService"
                 android:label="@string/inCallUiAppLabel"
diff --git a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
index ba58655..758ae4f 100644
--- a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
+++ b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
@@ -35,7 +35,9 @@
 import android.widget.Toast;
 
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Class used to create, update and cancel the notification used to display and update call state
@@ -44,11 +46,16 @@
 public class CallServiceNotifier {
     private static final CallServiceNotifier INSTANCE = new CallServiceNotifier();
 
-    static final String CALL_PROVIDER_ID = "testapps_TestConnectionService_CALL_PROVIDER_ID";
-    static final String SIM_SUBSCRIPTION_ID = "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID";
-    static final String CONNECTION_MANAGER_ID =
+    public static final String CALL_PROVIDER_ID = "testapps_TestConnectionService_CALL_PROVIDER_ID";
+    public static final String SIM_SUBSCRIPTION_ID =
+            "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID";
+    public static final String SIM_SUBSCRIPTION_ID2 =
+            "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID2";
+    public static final String CONNECTION_MANAGER_ID =
             "testapps_TestConnectionService_CONNECTION_MANAGER_ID";
 
+    private Map<String, PhoneAccountHandle> mPhoneAccountMap = new HashMap<>();
+
     /**
      * Static notification IDs.
      */
@@ -110,10 +117,11 @@
         testBundle.putString("EXTRA_STR1", "Hello");
         testBundle.putString("EXTRA_STR2", "There");
 
+        PhoneAccountHandle handle1 = new PhoneAccountHandle(
+                new ComponentName(context, TestConnectionService.class), CALL_PROVIDER_ID);
+        mPhoneAccountMap.put(CALL_PROVIDER_ID, handle1);
         telecomManager.registerPhoneAccount(PhoneAccount.builder(
-                new PhoneAccountHandle(
-                        new ComponentName(context, TestConnectionService.class),
-                        CALL_PROVIDER_ID),
+                handle1,
                 "TelecomTestApp Call Provider")
                 .setAddress(Uri.parse("tel:555-TEST"))
                 .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
@@ -130,10 +138,11 @@
                 .setExtras(testBundle)
                 .build());
 
+        PhoneAccountHandle handle2 = new PhoneAccountHandle(
+                new ComponentName(context, TestConnectionService.class), SIM_SUBSCRIPTION_ID);
+        mPhoneAccountMap.put(SIM_SUBSCRIPTION_ID, handle2);
         telecomManager.registerPhoneAccount(PhoneAccount.builder(
-                new PhoneAccountHandle(
-                        new ComponentName(context, TestConnectionService.class),
-                        SIM_SUBSCRIPTION_ID),
+                handle2,
                 "TelecomTestApp SIM Subscription")
                 .setAddress(Uri.parse("tel:555-TSIM"))
                 .setSubscriptionAddress(Uri.parse("tel:555-TSIM"))
@@ -149,11 +158,31 @@
                 .setShortDescription("a short description for the sim subscription")
                 .build());
 
+        PhoneAccountHandle handle3 = new PhoneAccountHandle(
+                new ComponentName(context, TestConnectionService.class), SIM_SUBSCRIPTION_ID2);
+        mPhoneAccountMap.put(SIM_SUBSCRIPTION_ID2, handle3);
         telecomManager.registerPhoneAccount(PhoneAccount.builder(
-                        new PhoneAccountHandle(
-                                new ComponentName(context, TestConnectionManager.class),
-                                CONNECTION_MANAGER_ID),
-                        "TelecomTestApp CONNECTION MANAGER")
+                handle3,
+                "TelecomTestApp SIM Subscription 2")
+                .setAddress(Uri.parse("tel:555-TSI2"))
+                .setSubscriptionAddress(Uri.parse("tel:555-TSI2"))
+                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
+                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
+                        PhoneAccount.CAPABILITY_VIDEO_CALLING |
+                        PhoneAccount.CAPABILITY_RTT |
+                        PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)
+                .setIcon(Icon.createWithResource(
+                        context.getResources(), R.drawable.stat_sys_phone_call))
+                .setHighlightColor(Color.CYAN)
+                .setShortDescription("a short description for the sim subscription")
+                .build());
+
+        PhoneAccountHandle handle4 = new PhoneAccountHandle(
+                new ComponentName(context, TestConnectionManager.class), CONNECTION_MANAGER_ID);
+        mPhoneAccountMap.put(CONNECTION_MANAGER_ID, handle4);
+        telecomManager.registerPhoneAccount(PhoneAccount.builder(
+                handle4,
+                "TelecomTestApp CONNECTION MANAGER")
                 .setAddress(Uri.parse("tel:555-CMGR"))
                 .setSubscriptionAddress(Uri.parse("tel:555-CMGR"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
@@ -164,6 +193,10 @@
                 .build());
     }
 
+    public PhoneAccountHandle getPhoneAccountHandle(String id) {
+        return mPhoneAccountMap.get(id);
+    }
+
     /**
      * Displays all phone accounts registered with telecom.
      */
diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
index ac239b9..52dcadb 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -43,6 +43,8 @@
 import java.util.List;
 import java.util.Random;
 
+import static com.android.server.telecom.testapps.CallServiceNotifier.SIM_SUBSCRIPTION_ID2;
+
 /**
  * Service which provides fake calls to test the ConnectionService interface.
  * TODO: Rename all classes in the directory to Dummy* (e.g., DummyConnectionService).
@@ -56,6 +58,9 @@
     public static final String EXTRA_HANDLE = "extra_handle";
 
     private static final String LOG_TAG = TestConnectionService.class.getSimpleName();
+
+    private static TestConnectionService INSTANCE;
+
     /**
      * Random number generator used to generate phone numbers.
      */
@@ -332,6 +337,11 @@
     private MediaPlayer mMediaPlayer;
 
     @Override
+    public void onCreate() {
+        INSTANCE = this;
+    }
+
+    @Override
     public boolean onUnbind(Intent intent) {
         log("onUnbind");
         mMediaPlayer = null;
@@ -479,6 +489,36 @@
         }
     }
 
+    public static TestConnectionService getInstance() {
+        return INSTANCE;
+    }
+
+    public void switchPhoneAccount() {
+        if (!mCalls.isEmpty()) {
+            TestConnection c = mCalls.get(0);
+            c.notifyPhoneAccountChanged(CallServiceNotifier.getInstance()
+                    .getPhoneAccountHandle(SIM_SUBSCRIPTION_ID2));
+        } else {
+            Log.i(this, "Couldn't switch PhoneAccount, call is null!");
+        }
+    }
+    public void switchPhoneAccountWrong() {
+        PhoneAccountHandle pah = new PhoneAccountHandle(
+                new ComponentName("com.android.phone",
+                "com.android.services.telephony.TelephonyConnectionService"), "TEST");
+        if (!mCalls.isEmpty()) {
+            TestConnection c = mCalls.get(0);
+            try {
+                c.notifyPhoneAccountChanged(pah);
+            } catch (SecurityException e) {
+                Toast.makeText(getApplicationContext(), "SwitchPhoneAccount: Pass",
+                        Toast.LENGTH_SHORT).show();
+            }
+        } else {
+            Log.i(this, "Couldn't switch PhoneAccount, call is null!");
+        }
+    }
+
     private void addVideoProvider(TestConnection connection) {
         TestVideoProvider testVideoCallProvider =
                 new TestVideoProvider(getApplicationContext(), connection);
diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionServiceReceiver.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionServiceReceiver.java
new file mode 100644
index 0000000..aaa5e2c
--- /dev/null
+++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionServiceReceiver.java
@@ -0,0 +1,58 @@
+/*
+ * 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.server.telecom.testapps;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class TestConnectionServiceReceiver extends BroadcastReceiver {
+    private static final String TAG = "TestConnectionServiceBR";
+
+    // Switches the PhoneAccount to the second test SIM account.
+    public static final String INTENT_SWITCH_PHONE_ACCOUNT =
+            "android.server.telecom.testapps.ACTION_SWITCH_PHONE_ACCOUNT";
+
+    // Creates a PhoneAccount that is incorrect and should create a SecurityException
+    public static final String INTENT_SWITCH_PHONE_ACCOUNT_WRONG =
+            "android.server.telecom.testapps.ACTION_SWITCH_PHONE_ACCOUNT_WRONG";
+
+    /**
+     * Handles broadcasts directed at the {@link TestInCallServiceImpl}.
+     *
+     * @param context The Context in which the receiver is running.
+     * @param intent  The Intent being received.
+     */
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+        Log.v(TAG, "onReceive: " + action);
+
+        TestConnectionService cs = TestConnectionService.getInstance();
+        if (cs == null) {
+            Log.i(TAG, "null TestConnectionService");
+            return;
+        }
+
+        if (INTENT_SWITCH_PHONE_ACCOUNT.equals(action)) {
+            cs.switchPhoneAccount();
+        } else if (INTENT_SWITCH_PHONE_ACCOUNT_WRONG.equals(action)) {
+            cs.switchPhoneAccountWrong();
+        }
+    }
+}