Merge "Fix comparison of SIM State values."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2c19a0f..76e49f6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -672,6 +672,7 @@
             android:name="com.android.phone.vvm.RemoteVvmTaskManager"
             android:exported="false"/>
         <service android:name="com.android.internal.telephony.CellularNetworkService"
+            android:exported="true"
             android:permission="android.permission.BIND_TELEPHONY_NETWORK_SERVICE" >
             <intent-filter>
                 <action android:name="android.telephony.NetworkService" />
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index 18fc534..38936ec 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -113,12 +113,18 @@
     public static boolean shouldPromoteWfc(Context context, int phoneId) {
         CarrierConfigManager cfgManager = (CarrierConfigManager) context
                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        if (cfgManager == null || !cfgManager.getConfigForSubId(getSubId(phoneId))
-                .getBoolean(CarrierConfigManager.KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL)) {
+
+        ImsManager imsManager = ImsManager.getInstance(context, phoneId);
+        if (!imsManager.isWfcEnabledByPlatform()) {
             return false;
         }
 
-        if (!getDefaultImsManagerInstance(context).isWfcProvisionedOnDevice()) {
+        if (!imsManager.isWfcProvisionedOnDevice()) {
+            return false;
+        }
+
+        if (cfgManager == null || !cfgManager.getConfigForSubId(getSubId(phoneId))
+                .getBoolean(CarrierConfigManager.KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL)) {
             return false;
         }
 
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 62ff07c..4f6be79 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -5004,6 +5004,22 @@
     }
 
     /**
+     * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
+     */
+    public void unregisterImsFeatureCallback(int slotId, int featureType,
+            IImsServiceFeatureCallback callback) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (mImsResolver == null) return;
+            mImsResolver.unregisterImsFeatureCallback(slotId, featureType, callback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Returns the {@link IImsRegistration} structure associated with the slotId and feature
      * specified or null if IMS is not supported on the slot specified.
      */
@@ -7374,15 +7390,10 @@
 
     @Override
     public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) {
-        try {
-            PackageManager pm = mApp.getPackageManager();
-            if (Binder.getCallingUid() != pm.getPackageUid(callingPackage, 0)) {
-                throw new SecurityException("Calling package " + callingPackage + " does not match "
-                        + "calling UID");
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new SecurityException("Invalid calling package. e=" + e);
-        }
+        // Verify that tha callingPackage belongs to the calling UID
+        mApp.getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
+
         boolean hasReadPermission = false;
         try {
             enforceReadPrivilegedPermission("getUiccCardsInfo");
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 00b1bc2..8790913 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -1359,9 +1359,12 @@
             }
 
             if (mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
-                Log.i(this,"handleOriginalConnectionChange : SRVCC to GSM");
                 GsmConnection c = new GsmConnection(originalConnection, getTelecomCallId(),
                         mConferenceHost.getCallDirection());
+                Log.i(this, "handleOriginalConnectionChange : SRVCC to GSM."
+                        + " Created new GsmConnection with objId=" + System.identityHashCode(c)
+                        + " and originalConnection objId="
+                        + System.identityHashCode(originalConnection));
                 // This is a newly created conference connection as a result of SRVCC
                 c.setConferenceSupported(true);
                 c.setTelephonyConnectionProperties(
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index d2dfab5..eb3f3a0 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -25,7 +25,6 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
-import com.android.telephony.Rlog;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.Call;
@@ -40,6 +39,7 @@
 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.phone.NumberVerificationManager;
 import com.android.phone.PhoneUtils;
+import com.android.telephony.Rlog;
 
 import java.util.Objects;
 
@@ -214,6 +214,9 @@
             Call call = connection.getCall();
             if (call != null && call.getState().isAlive()) {
                 addNewUnknownCall(connection);
+            } else {
+                Log.i(this, "Skipping new unknown connection because its call is null or dead."
+                        + " connection=" + connection);
             }
         }
     }
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index 95281b3..fd16d4b 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -260,6 +260,8 @@
                     }
 
                     mTelephonyConference = new TelephonyConference(phoneAccountHandle);
+                    Log.i(this, "Creating new TelephonyConference to hold conferenced connections."
+                            + " conference=" + mTelephonyConference);
                     for (Connection connection : conferencedConnections) {
                         Log.d(this, "Adding a connection to a conference call: %s %s",
                                 mTelephonyConference, connection);
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 983351f..5a2b384 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -152,15 +152,18 @@
                             mOriginalConnection.getAddress() != null &&
                             mOriginalConnection.getAddress().equals(connection.getAddress())) ||
                             connection.getState() == mOriginalConnection.getStateBeforeHandover())) {
-                            Log.d(TelephonyConnection.this,
-                                    "SettingOriginalConnection " + mOriginalConnection.toString()
-                                            + " with " + connection.toString());
+                            Log.d(TelephonyConnection.this, "Setting original connection after"
+                                    + " handover or redial, current original connection="
+                                    + mOriginalConnection.toString()
+                                    + ", new original connection="
+                                    + connection.toString());
                             setOriginalConnection(connection);
                             mWasImsConnection = false;
                         }
                     } else {
                         Log.w(TelephonyConnection.this,
-                                what + ": mOriginalConnection==null - invalid state (not cleaned up)");
+                                what + ": mOriginalConnection==null --"
+                                        + " invalid state (not cleaned up)");
                     }
                     break;
                 case MSG_RINGBACK_TONE:
diff --git a/testapps/SmsManagerTestApp/AndroidManifest.xml b/testapps/SmsManagerTestApp/AndroidManifest.xml
index 57b7344..7dc717f 100644
--- a/testapps/SmsManagerTestApp/AndroidManifest.xml
+++ b/testapps/SmsManagerTestApp/AndroidManifest.xml
@@ -40,6 +40,62 @@
                 <data android:scheme="content"/>
             </intent-filter>
         </receiver>
+        <service android:name=".PersistentService"
+                 android:exported="false"
+                 android:process=":persistent"
+                 android:permission="android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE">
+            <intent-filter>
+                <action android:name="android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE" />
+            </intent-filter>
+        </service>
+
+        <!-- Stuff required to become the default messaging app defined below, doesn't actually do
+             anything useful for now. -->
+
+        <!-- Fake BroadcastReceiver that listens for incoming SMS messages -->
+        <receiver android:name=".SmsReceiver"
+                  android:permission="android.permission.BROADCAST_SMS">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.SMS_DELIVER" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Fake BroadcastReceiver that listens for incoming MMS messages -->
+        <receiver android:name=".MmsReceiver"
+                  android:permission="android.permission.BROADCAST_WAP_PUSH">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+                <data android:mimeType="application/vnd.wap.mms-message" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Fake Activity that allows the user to send new SMS/MMS messages -->
+        <activity android:name=".ComposeSmsActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.SEND" />
+                <action android:name="android.intent.action.SENDTO" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </activity>
+
+        <!-- Fake Service that delivers messages from the phone "quick response" -->
+        <service android:name=".HeadlessSmsSendService"
+                 android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
+                 android:exported="true" >
+            <intent-filter>
+                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </service>
 
     </application>
 </manifest>
diff --git a/testapps/SmsManagerTestApp/res/layout/activity_main.xml b/testapps/SmsManagerTestApp/res/layout/activity_main.xml
index 39fb6c6..185e0e2 100644
--- a/testapps/SmsManagerTestApp/res/layout/activity_main.xml
+++ b/testapps/SmsManagerTestApp/res/layout/activity_main.xml
@@ -63,5 +63,17 @@
             android:layout_height="wrap_content"
             android:paddingRight="4dp"
             android:text="@string/get_sub_for_result_button"/>
+        <Button
+            android:id="@+id/enable_persistent_service"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/enable_persistent_service"/>
+        <Button
+            android:id="@+id/disable_persistent_service"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/disable_persistent_service"/>
     </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml b/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
index d6497a3..c8b9f91 100644
--- a/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
+++ b/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
@@ -19,4 +19,6 @@
     <string name="send_text_button">Send Outgoing Text Now.</string>
     <string name="send_text_service_button">Send Outgoing Text after 5 sec.</string>
     <string name="get_sub_for_result_button">Ask user for sub id.</string>
+    <string name="enable_persistent_service">Enable Persistent Service</string>
+    <string name="disable_persistent_service">Disable Persistent Service</string>
 </resources>
\ No newline at end of file
diff --git a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/PersistentService.java b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/PersistentService.java
new file mode 100644
index 0000000..16b7ecd
--- /dev/null
+++ b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/PersistentService.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 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.phone.testapps.smsmanagertestapp;
+
+import android.content.Intent;
+import android.service.carrier.CarrierMessagingClientService;
+import android.util.Log;
+
+/**
+ * A test persistent service that should be started by the framework when this app becomes the
+ * default SMS app and destroyed when it is removed. See {@link CarrierMessagingClientService} for
+ * more information.
+ */
+public class PersistentService extends CarrierMessagingClientService {
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.i("SmsTestApp", "onCreate");
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.i("SmsTestApp", "onDestroy");
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.i("SmsTestApp", "onUnbind");
+        return false;
+    }
+}
diff --git a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
index 75536f3..785fe3f 100644
--- a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
+++ b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
@@ -66,6 +66,10 @@
         findViewById(R.id.send_text_button_service)
                 .setOnClickListener(this::sendOutgoingSmsService);
         findViewById(R.id.get_sub_for_result_button).setOnClickListener(this::getSubIdForResult);
+        findViewById(R.id.enable_persistent_service)
+                .setOnClickListener(this::setPersistentServiceComponentEnabled);
+        findViewById(R.id.disable_persistent_service)
+                .setOnClickListener(this::setPersistentServiceComponentDisabled);
         mPhoneNumber = (EditText) findViewById(R.id.phone_number_text);
     }
 
@@ -183,6 +187,21 @@
         }
     }
 
+    private void setPersistentServiceComponentEnabled(View view) {
+        getPackageManager().setComponentEnabledSetting(
+                new ComponentName(this, PersistentService.class),
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+
+    private void setPersistentServiceComponentDisabled(View view) {
+        getPackageManager().setComponentEnabledSetting(
+                new ComponentName(this, PersistentService.class),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+
+
     private Intent getSendStatusIntent() {
         // Encode requestId in intent data
         return new Intent(SendStatusReceiver.MESSAGE_SENT_ACTION, null, this,
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
deleted file mode 100644
index 9f8de9e..0000000
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2020 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.phone;
-
-import static junit.framework.TestCase.fail;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.util.Log;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.TelephonyTestBase;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-@RunWith(AndroidJUnit4.class)
-public class PhoneInterfaceManagerTest extends TelephonyTestBase {
-
-    private static final String PRIVILEGED_PACKAGE_NAME = "test.package.name";
-
-    private static final String TAG = "PhoneInterfaceManagerTest";
-
-    private PhoneInterfaceManager mPhoneInterfaceManager;
-    private PhoneGlobals mMockPhoneGlobals;
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        mMockPhoneGlobals = mock(PhoneGlobals.class);
-        //PhoneGlobals phoneGlobals = new PhoneGlobals(mContext);
-        mPhoneInterfaceManager = new PhoneInterfaceManager(mMockPhoneGlobals);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    @Test
-    public void testGetUiccCardsInfoSecurity() {
-        // Set up mocks so that the supplied package UID does not equal the calling UID
-        PackageManager mockPackageManager = mock(PackageManager.class);
-        try {
-            doReturn(Binder.getCallingUid() + 1).when(mockPackageManager)
-                    .getPackageUid(eq(PRIVILEGED_PACKAGE_NAME), anyInt());
-        } catch (Exception e) {
-            Log.d(TAG, "testGetUiccCardsInfoSecurity unable to setup mocks");
-            fail();
-        }
-        doReturn(mockPackageManager).when(mContext).getPackageManager();
-        doReturn(mockPackageManager).when(mMockPhoneGlobals).getPackageManager();
-        try {
-            mPhoneInterfaceManager.getUiccCardsInfo(PRIVILEGED_PACKAGE_NAME);
-            fail();
-        } catch (SecurityException e) {
-            Log.d(TAG, "testGetUiccCardsInfoSecurity e = " + e);
-        }
-    }
-}