Merge "Check if WFC enabled by platform when decide whether to show the WFC prompt."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ec2bfdf..76e49f6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -470,6 +470,9 @@
             Handler for EuiccManager's resolution intents. These are locked down so that only
             privileged processes can start them, which means we can trust the Intent used to start
             it (which contains a description of the next step to perform after resolution).
+
+            If modified, also change EuiccController#RESOLUTION_ACTIVITY_PACKAGE_NAME and
+            EuiccController#RESOLUTION_ACTIVITY_CLASS_NAME
         -->
         <activity android:name=".euicc.EuiccResolutionUiDispatcherActivity"
             android:exported="true"
@@ -669,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/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 62ff07c..1bd8609 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.
      */
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 73d6023..8790913 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -48,6 +48,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * Represents an IMS conference call.
@@ -834,9 +835,7 @@
      * @param conferenceHost The connection hosting the conference.
      */
     private void setConferenceHost(TelephonyConnection conferenceHost) {
-        if (Log.VERBOSE) {
-            Log.v(this, "setConferenceHost " + conferenceHost);
-        }
+        Log.i(this, "setConferenceHost " + conferenceHost);
 
         mConferenceHost = conferenceHost;
 
@@ -867,6 +866,16 @@
 
             mConferenceHostAddress = new Uri[hostAddresses.size()];
             mConferenceHostAddress = hostAddresses.toArray(mConferenceHostAddress);
+            Log.i(this, "setConferenceHost: temp log hosts are "
+                    + Arrays.stream(mConferenceHostAddress)
+                    .map(Uri::toString)
+                    .collect(Collectors.joining(", ")));
+
+            Log.i(this, "setConferenceHost: hosts are "
+                    + Arrays.stream(mConferenceHostAddress)
+                    .map(Uri::getSchemeSpecificPart)
+                    .map(ssp -> Rlog.pii(LOG_TAG, ssp))
+                    .collect(Collectors.joining(", ")));
 
             mIsUsingSimCallManager = mTelecomAccountRegistry.isUsingSimCallManager(
                     mConferenceHostPhoneAccountHandle);
@@ -1350,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 0c0cafa..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:
@@ -1574,12 +1577,13 @@
         boolean wasVideoCall = false;
         boolean isVowifiEnabled = false;
         if (phone instanceof ImsPhone) {
-            ImsPhone imsPhone = (ImsPhone) phone;
-            if (imsPhone.getForegroundCall() != null
-                    && imsPhone.getForegroundCall().getImsCall() != null) {
-                ImsCall call = imsPhone.getForegroundCall().getImsCall();
-                isCurrentVideoCall = call.isVideoCall();
-                wasVideoCall = call.wasVideoCall();
+            ImsPhoneCall foregroundCall = ((ImsPhone) phone).getForegroundCall();
+            if (foregroundCall != null) {
+                ImsCall call = foregroundCall.getImsCall();
+                if (call != null) {
+                    isCurrentVideoCall = call.isVideoCall();
+                    wasVideoCall = call.wasVideoCall();
+                }
             }
 
             isVowifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
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,