Merge "Allow test numbers to be dialed from APM and wait for IN_SERVICE"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9f9269e..f68b72e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -194,6 +194,7 @@
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+    <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
 
     <application android:name="PhoneApp"
             android:persistent="true"
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index e251516..d080b31 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -135,6 +135,7 @@
 import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.euicc.EuiccConnector;
+import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.uicc.IccIoResult;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.telephony.uicc.SIMRecords;
@@ -1103,6 +1104,7 @@
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
                     request.result = (ar.exception == null);
+                    updateModemStateMetrics();
                     notifyRequester(request);
                     break;
                 default:
@@ -6521,7 +6523,7 @@
 
     /**
      * Get whether reboot is required or not after making changes to modem configurations.
-     * Return value defaults to false
+     * Return value defaults to true
      */
     @Override
     public boolean isRebootRequiredForModemConfigChange() {
@@ -6534,4 +6536,10 @@
         }
     }
 
+    private void updateModemStateMetrics() {
+        TelephonyMetrics metrics = TelephonyMetrics.getInstance();
+        // TODO: check the state for each modem if the api is ready.
+        metrics.updateEnabledModemBitmap((1 << TelephonyManager.from(mApp).getPhoneCount()) - 1);
+    }
+
 }
diff --git a/src/com/android/services/telephony/ConferenceParticipantConnection.java b/src/com/android/services/telephony/ConferenceParticipantConnection.java
index 82baa92..1f330f9 100644
--- a/src/com/android/services/telephony/ConferenceParticipantConnection.java
+++ b/src/com/android/services/telephony/ConferenceParticipantConnection.java
@@ -33,11 +33,6 @@
  * Represents a participant in a conference call.
  */
 public class ConferenceParticipantConnection extends Connection {
-    /**
-     * RFC5767 states that a SIP URI with an unknown number should use an address of
-     * {@code anonymous@anonymous.invalid}.  E.g. the host name is anonymous.invalid.
-     */
-    private static final String ANONYMOUS_INVALID_HOST = "anonymous.invalid";
 
     /**
      * The user entity URI For the conference participant.
@@ -65,7 +60,7 @@
 
         mParentConnection = parentConnection;
 
-        int presentation = getParticipantPresentation(participant);
+        int presentation = participant.getParticipantPresentation();
         Uri address;
         if (presentation != PhoneConstants.PRESENTATION_ALLOWED) {
             address = null;
@@ -161,53 +156,7 @@
         setConnectionCapabilities(capabilities);
     }
 
-    /**
-     * Determines the number presentation for a conference participant.  Per RFC5767, if the host
-     * name contains {@code anonymous.invalid} we can assume that there is no valid caller ID
-     * information for the caller, otherwise we'll assume that the URI can be shown.
-     *
-     * @param participant The conference participant.
-     * @return The number presentation.
-     */
-    private int getParticipantPresentation(ConferenceParticipant participant) {
-        Uri address = participant.getHandle();
-        if (address == null) {
-            return PhoneConstants.PRESENTATION_RESTRICTED;
-        }
 
-        String number = address.getSchemeSpecificPart();
-        // If no number, bail early and set restricted presentation.
-        if (TextUtils.isEmpty(number)) {
-            return PhoneConstants.PRESENTATION_RESTRICTED;
-        }
-        // Per RFC3261, the host name portion can also potentially include extra information:
-        // E.g. sip:anonymous1@anonymous.invalid;legid=1
-        // In this case, hostName will be anonymous.invalid and there is an extra parameter for
-        // legid=1.
-        // Parameters are optional, and the address (e.g. test@test.com) will always be the first
-        // part, with any parameters coming afterwards.
-        String hostParts[] = number.split("[;]");
-        String addressPart = hostParts[0];
-
-        // Get the number portion from the address part.
-        // This will typically be formatted similar to: 6505551212@test.com
-        String numberParts[] = addressPart.split("[@]");
-
-        // If we can't parse the host name out of the URI, then there is probably other data
-        // present, and is likely a valid SIP URI.
-        if (numberParts.length != 2) {
-            return PhoneConstants.PRESENTATION_ALLOWED;
-        }
-        String hostName = numberParts[1];
-
-        // If the hostname portion of the SIP URI is the invalid host string, presentation is
-        // restricted.
-        if (hostName.equals(ANONYMOUS_INVALID_HOST)) {
-            return PhoneConstants.PRESENTATION_RESTRICTED;
-        }
-
-        return PhoneConstants.PRESENTATION_ALLOWED;
-    }
 
     /**
      * Attempts to build a tel: style URI from a conference participant.
@@ -311,6 +260,10 @@
         sb.append(Log.pii(mParentConnection.getAddress()));
         sb.append(" state:");
         sb.append(Connection.stateToString(getState()));
+        sb.append(" connectTime:");
+        sb.append(getConnectTimeMillis());
+        sb.append(" connectElapsedTime:");
+        sb.append(getConnectElapsedTimeMillis());
         sb.append("]");
 
         return sb.toString();
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index d5af25b..c992c74 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -33,7 +33,6 @@
 import android.telecom.VideoProfile;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
-import android.util.FeatureFlagUtils;
 import android.util.Pair;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -47,7 +46,6 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -542,6 +540,8 @@
     @Override
     public void onConnectionAdded(android.telecom.Connection connection) {
         // No-op
+        Log.d(this, "connection added: " + connection
+                + ", time: " + connection.getConnectTimeMillis());
     }
 
     @Override
@@ -884,7 +884,7 @@
             // Remove the participant from Telecom.  It'll get picked up in a future CEP update
             // again anyways.
             entry.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED,
-                    "EMULATING_SINGLE_CALL"));
+                    DisconnectCause.REASON_EMULATING_SINGLE_CALL));
             entry.removeConnectionListener(mParticipantListener);
             mTelephonyConnectionService.removeConnection(entry);
             removeConnection(entry);
@@ -919,8 +919,13 @@
         ConferenceParticipantConnection connection = new ConferenceParticipantConnection(
                 parent.getOriginalConnection(), participant);
         connection.addConnectionListener(mParticipantListener);
-        connection.setConnectTimeMillis(parent.getConnectTimeMillis());
-
+        if (participant.getConnectTime() == 0) {
+            connection.setConnectTimeMillis(parent.getConnectTimeMillis());
+            connection.setConnectionStartElapsedRealTime(parent.getConnectElapsedTimeMillis());
+        } else {
+            connection.setConnectTimeMillis(participant.getConnectTime());
+            connection.setConnectionStartElapsedRealTime(participant.getConnectElapsedTime());
+        }
         Log.i(this, "createConferenceParticipantConnection: participant=%s, connection=%s",
                 participant, connection);
 
@@ -1083,6 +1088,7 @@
                 c.updateState();
                 // Copy the connect time from the conferenceHost
                 c.setConnectTimeMillis(mConferenceHost.getConnectTimeMillis());
+                c.setConnectionStartElapsedRealTime(mConferenceHost.getConnectElapsedTimeMillis());
                 mTelephonyConnectionService.addExistingConnection(phoneAccountHandle, c);
                 mTelephonyConnectionService.addConnectionToConferenceController(c);
             } // CDMA case not applicable for SRVCC