Merge "Don't link with mediametrics headers symlinks:"
diff --git a/src/java/android/net/sip/ISipService.aidl b/src/java/android/net/sip/ISipService.aidl
index 84750c7..f88ed6c 100644
--- a/src/java/android/net/sip/ISipService.aidl
+++ b/src/java/android/net/sip/ISipService.aidl
@@ -39,5 +39,5 @@
             in ISipSessionListener listener, String opPackageName);
     ISipSession getPendingSession(String callId, String opPackageName);
 
-    SipProfile[] getListOfProfiles(String opPackageName);
+    List<SipProfile> getListOfProfiles(String opPackageName);
 }
diff --git a/src/java/android/net/sip/SipAudioCall.java b/src/java/android/net/sip/SipAudioCall.java
index f1eb35b..a1a5ae8 100644
--- a/src/java/android/net/sip/SipAudioCall.java
+++ b/src/java/android/net/sip/SipAudioCall.java
@@ -16,6 +16,8 @@
 
 package android.net.sip;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.media.AudioManager;
 import android.net.rtp.AudioCodec;
@@ -27,6 +29,7 @@
 import android.os.Message;
 import android.telephony.Rlog;
 import android.text.TextUtils;
+
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -191,6 +194,7 @@
 
     private int mErrorCode = SipErrorCode.NO_ERROR;
     private String mErrorMessage;
+    private final Object mLock;
 
     /**
      * Creates a call object with the local SIP profile.
@@ -201,6 +205,7 @@
         mContext = context;
         mLocalProfile = localProfile;
         mWm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mLock = new Object();
     }
 
     /**
@@ -265,7 +270,7 @@
      * @return true if the call is established
      */
     public boolean isInCall() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mInCall;
         }
     }
@@ -276,7 +281,7 @@
      * @return true if the call is on hold
      */
     public boolean isOnHold() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mHold;
         }
     }
@@ -309,7 +314,7 @@
      * @return the local SIP profile
      */
     public SipProfile getLocalProfile() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mLocalProfile;
         }
     }
@@ -320,7 +325,7 @@
      * @return the peer's SIP profile
      */
     public SipProfile getPeerProfile() {
-        synchronized (this) {
+        synchronized (mLock) {
             return (mSipSession == null) ? null : mSipSession.getPeerProfile();
         }
     }
@@ -332,7 +337,7 @@
      * @return the session state
      */
     public int getState() {
-        synchronized (this) {
+        synchronized (mLock) {
             if (mSipSession == null) return SipSession.State.READY_TO_CALL;
             return mSipSession.getState();
         }
@@ -346,7 +351,7 @@
      * @hide
      */
     public SipSession getSipSession() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mSipSession;
         }
     }
@@ -404,7 +409,7 @@
             public void onRinging(SipSession session,
                     SipProfile peerProfile, String sessionDescription) {
                 // this callback is triggered only for reinvite.
-                synchronized (SipAudioCall.this) {
+                synchronized (mLock) {
                     if ((mSipSession == null) || !mInCall
                             || !session.getCallId().equals(
                                     mSipSession.getCallId())) {
@@ -568,7 +573,7 @@
                 loge("onError():", t);
             }
         }
-        synchronized (this) {
+        synchronized (mLock) {
             if ((errorCode == SipErrorCode.DATA_CONNECTION_LOST)
                     || !isInCall()) {
                 close(true);
@@ -591,7 +596,7 @@
             throw new SipException("VOIP API is not supported");
         }
 
-        synchronized (this) {
+        synchronized (mLock) {
             mSipSession = session;
             mPeerSd = sessionDescription;
             if (DBG) log("attachCall(): " + mPeerSd);
@@ -626,7 +631,7 @@
             throw new SipException("VOIP API is not supported");
         }
 
-        synchronized (this) {
+        synchronized (mLock) {
             mSipSession = sipSession;
             try {
                 mAudioStream = new AudioStream(InetAddress.getByName(
@@ -647,7 +652,7 @@
      */
     public void endCall() throws SipException {
         if (DBG) log("endCall: mSipSession" + mSipSession);
-        synchronized (this) {
+        synchronized (mLock) {
             stopCall(RELEASE_SOCKET);
             mInCall = false;
 
@@ -670,7 +675,7 @@
      */
     public void holdCall(int timeout) throws SipException {
         if (DBG) log("holdCall: mSipSession" + mSipSession + " timeout=" + timeout);
-        synchronized (this) {
+        synchronized (mLock) {
             if (mHold) return;
             if (mSipSession == null) {
                 loge("holdCall:");
@@ -695,7 +700,7 @@
      */
     public void answerCall(int timeout) throws SipException {
         if (DBG) log("answerCall: mSipSession" + mSipSession + " timeout=" + timeout);
-        synchronized (this) {
+        synchronized (mLock) {
             if (mSipSession == null) {
                 throw new SipException("No call to answer");
             }
@@ -724,7 +729,7 @@
      */
     public void continueCall(int timeout) throws SipException {
         if (DBG) log("continueCall: mSipSession" + mSipSession + " timeout=" + timeout);
-        synchronized (this) {
+        synchronized (mLock) {
             if (!mHold) return;
             mSipSession.changeCall(createContinueOffer().encode(), timeout);
             mHold = false;
@@ -854,7 +859,7 @@
 
     /** Toggles mute. */
     public void toggleMute() {
-        synchronized (this) {
+        synchronized (mLock) {
             mMuted = !mMuted;
             setAudioGroupMode();
         }
@@ -866,7 +871,7 @@
      * @return true if the call is muted
      */
     public boolean isMuted() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mMuted;
         }
     }
@@ -879,7 +884,7 @@
      * @param speakerMode set true to enable speaker mode; false to disable
      */
     public void setSpeakerMode(boolean speakerMode) {
-        synchronized (this) {
+        synchronized (mLock) {
             ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
                     .setSpeakerphoneOn(speakerMode);
             setAudioGroupMode();
@@ -915,7 +920,7 @@
      * @param result the result message to send when done
      */
     public void sendDtmf(int code, Message result) {
-        synchronized (this) {
+        synchronized (mLock) {
             AudioGroup audioGroup = getAudioGroup();
             if ((audioGroup != null) && (mSipSession != null)
                     && (SipSession.State.IN_CALL == getState())) {
@@ -938,7 +943,7 @@
      * @hide
      */
     public AudioStream getAudioStream() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mAudioStream;
         }
     }
@@ -955,10 +960,9 @@
      * @return the {@link AudioGroup} object or null if the RTP stream has not
      *      yet been set up
      * @see #getAudioStream
-     * @hide
      */
-    public AudioGroup getAudioGroup() {
-        synchronized (this) {
+    public @Nullable AudioGroup getAudioGroup() {
+        synchronized (mLock) {
             if (mAudioGroup != null) return mAudioGroup;
             return ((mAudioStream == null) ? null : mAudioStream.getGroup());
         }
@@ -974,10 +978,9 @@
      * settings of the first object (that merges others) override others'.
      *
      * @see #getAudioStream
-     * @hide
      */
-    public void setAudioGroup(AudioGroup group) {
-        synchronized (this) {
+    public void setAudioGroup(@NonNull AudioGroup group) {
+        synchronized (mLock) {
             if (DBG) log("setAudioGroup: group=" + group);
             if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
                 mAudioStream.join(group);
diff --git a/src/java/android/net/sip/SipManager.java b/src/java/android/net/sip/SipManager.java
index 0cb1feb..43b816b 100644
--- a/src/java/android/net/sip/SipManager.java
+++ b/src/java/android/net/sip/SipManager.java
@@ -16,6 +16,8 @@
 
 package android.net.sip;
 
+import android.annotation.NonNull;
+import android.annotation.SdkConstant;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -26,6 +28,8 @@
 import android.telephony.Rlog;
 
 import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Provides APIs for SIP tasks, such as initiating SIP connections, and provides access to related
@@ -81,19 +85,19 @@
     public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
 
     /**
-     * Action to broadcast when SipService is up.
-     * Internal use only.
-     * @hide
+     * Intent action sent when the SipManager becomes available.
      */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SIP_SERVICE_UP =
-            "android.net.sip.SIP_SERVICE_UP";
+            "android.net.sip.action.SIP_SERVICE_UP";
+
     /**
-     * Action string for the incoming call intent for the Phone app.
-     * Internal use only.
-     * @hide
+     * Intent action sent when there is a new incoming SIP call.
      */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SIP_INCOMING_CALL =
-            "com.android.phone.SIP_INCOMING_CALL";
+            "android.net.sip.action.SIP_INCOMING_CALL";
+
     /**
      * Action string for the add-phone intent.
      * Internal use only.
@@ -101,23 +105,28 @@
      */
     public static final String ACTION_SIP_ADD_PHONE =
             "com.android.phone.SIP_ADD_PHONE";
-    /**
-     * Action string for the remove-phone intent.
-     * Internal use only.
-     * @hide
-     */
-    public static final String ACTION_SIP_REMOVE_PHONE =
-            "com.android.phone.SIP_REMOVE_PHONE";
 
     /**
-     * Action string for the SIP call option configuration changed intent.
-     * This is used to communicate  change to the SIP call option, triggering re-registration of
-     * the SIP phone accounts.
-     * Internal use only.
-     * @hide
+     * Intent action sent when a SIP profile has been removed.
      */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SIP_REMOVE_PROFILE =
+            "android.net.sip.action.SIP_REMOVE_PROFILE";
+
+    /**
+     * Intent action sent when the SIP accounts or other configuration has changed.
+     * This should trigger a re-registration of the SIP PhoneAccounts.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SIP_CALL_OPTION_CHANGED =
-            "com.android.phone.SIP_CALL_OPTION_CHANGED";
+            "android.net.sip.action.SIP_CALL_OPTION_CHANGED";
+
+    /**
+     * Intent action used by Telephony to start the SIP service after about.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_START_SIP =
+            "android.net.sip.action.START_SIP";
 
     /**
      * Part of the ACTION_SIP_ADD_PHONE and ACTION_SIP_REMOVE_PHONE intents.
@@ -601,14 +610,13 @@
     /**
      * Gets the list of profiles hosted by the SIP service. The user information
      * (username, password and display name) are crossed out.
-     * @hide
      */
-    public SipProfile[] getListOfProfiles() throws SipException {
+    public @NonNull List<SipProfile> getListOfProfiles() throws SipException {
         try {
             checkSipServiceConnection();
             return mSipService.getListOfProfiles(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return new SipProfile[0];
+            return new ArrayList<>();
         }
     }
 
diff --git a/src/java/android/net/sip/SipProfile.java b/src/java/android/net/sip/SipProfile.java
index 0ef754c..98069c0 100644
--- a/src/java/android/net/sip/SipProfile.java
+++ b/src/java/android/net/sip/SipProfile.java
@@ -480,7 +480,6 @@
 
     /**
      * Sets the calling process's Uid in the sip service.
-     * @hide
      */
     public void setCallingUid(int uid) {
         mCallingUid = uid;
@@ -488,7 +487,8 @@
 
     /**
      * Gets the calling process's Uid in the sip settings.
-     * @hide
+     *
+     * @return the calling process's Uid in the sip settings.
      */
     public int getCallingUid() {
         return mCallingUid;
diff --git a/src/java/com/android/server/sip/SipService.java b/src/java/com/android/server/sip/SipService.java
index e691d35..15f3cec 100644
--- a/src/java/com/android/server/sip/SipService.java
+++ b/src/java/com/android/server/sip/SipService.java
@@ -52,6 +52,7 @@
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executor;
 
@@ -128,18 +129,18 @@
     }
 
     @Override
-    public synchronized SipProfile[] getListOfProfiles(String opPackageName) {
+    public synchronized List<SipProfile> getListOfProfiles(String opPackageName) {
         if (!canUseSip(opPackageName, "getListOfProfiles")) {
-            return new SipProfile[0];
+            return new ArrayList<>();
         }
         boolean isCallerRadio = isCallerRadio();
-        ArrayList<SipProfile> profiles = new ArrayList<SipProfile>();
+        ArrayList<SipProfile> profiles = new ArrayList<>();
         for (SipSessionGroupExt group : mSipGroups.values()) {
             if (isCallerRadio || isCallerCreator(group)) {
                 profiles.add(group.getLocalProfile());
             }
         }
-        return profiles.toArray(new SipProfile[profiles.size()]);
+        return profiles;
     }
 
     @Override
@@ -350,7 +351,7 @@
 
     private void notifyProfileRemoved(SipProfile localProfile) {
         if (DBG) log("notify: profile removed: " + localProfile);
-        Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE);
+        Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PROFILE);
         intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
         mContext.sendBroadcast(intent);
         if (mSipGroups.size() == 0) {