Add buffer size checks to eliminate security vulnerability. am: 0fef164d3d

Change-Id: Ifb03c3496ac450201fc205708a66de4bc7db5a9c
diff --git a/Android.bp b/Android.bp
index 3dd8f09..7f2d193 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,8 +15,10 @@
 filegroup {
     name: "opt-net-voip-srcs",
     srcs: [
-        "src/java/android/net/**/*.java",
+        "src/java/**/*.java",
+        "src/java/**/I*.aidl",
     ],
+    path: "src/java",
 }
 
 filegroup {
@@ -29,14 +31,9 @@
 java_library {
     name: "voip-common",
     installable: true,
-    srcs: [
-        "src/java/**/*.java",
-        "src/java/**/I*.aidl",
+    srcs: [":opt-net-voip-srcs"],
+    static_libs: [
+        "nist-sip",
     ],
-    aidl: {
-        local_include_dirs: [
-            "src/java",
-        ],
-    },
     required: ["librtp_jni"],
 }
diff --git a/src/java/android/net/rtp/AudioGroup.java b/src/java/android/net/rtp/AudioGroup.java
index 15390d3..9d96006 100644
--- a/src/java/android/net/rtp/AudioGroup.java
+++ b/src/java/android/net/rtp/AudioGroup.java
@@ -16,7 +16,9 @@
 
 package android.net.rtp;
 
+import android.annotation.NonNull;
 import android.app.ActivityThread;
+import android.content.Context;
 import android.media.AudioManager;
 
 import java.util.HashMap;
@@ -96,14 +98,26 @@
     private int mMode = MODE_ON_HOLD;
 
     private long mNative;
+    private Context mContext;
     static {
         System.loadLibrary("rtp_jni");
     }
 
     /**
      * Creates an empty AudioGroup.
+     * @deprecated Replaced by {@link #AudioGroup(Context)}
      */
+    @Deprecated
     public AudioGroup() {
+        this(null);
+    }
+
+    /**
+     * Creates an empty AudioGroup.
+     * @param context Context used to get package name
+     */
+    public AudioGroup(@NonNull Context context) {
+        mContext = context;
         mStreams = new HashMap<AudioStream, Long>();
     }
 
@@ -153,7 +167,8 @@
                 long id = nativeAdd(stream.getMode(), stream.getSocket(),
                         stream.getRemoteAddress().getHostAddress(),
                         stream.getRemotePort(), codecSpec, stream.getDtmfType(),
-                        ActivityThread.currentOpPackageName());
+                        mContext != null ? mContext.getOpPackageName()
+                                : ActivityThread.currentOpPackageName());
                 mStreams.put(stream, id);
             } catch (NullPointerException e) {
                 throw new IllegalStateException(e);
diff --git a/src/java/android/net/sip/ISipService.aidl b/src/java/android/net/sip/ISipService.aidl
index 84750c7..adbf1cb 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> getProfiles(String opPackageName);
 }
diff --git a/src/java/android/net/sip/SipAudioCall.java b/src/java/android/net/sip/SipAudioCall.java
index ea943e9..363995c 100644
--- a/src/java/android/net/sip/SipAudioCall.java
+++ b/src/java/android/net/sip/SipAudioCall.java
@@ -16,6 +16,9 @@
 
 package android.net.sip;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.media.AudioManager;
 import android.net.rtp.AudioCodec;
@@ -27,6 +30,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 +195,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 +206,7 @@
         mContext = context;
         mLocalProfile = localProfile;
         mWm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mLock = new Object();
     }
 
     /**
@@ -265,7 +271,7 @@
      * @return true if the call is established
      */
     public boolean isInCall() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mInCall;
         }
     }
@@ -276,7 +282,7 @@
      * @return true if the call is on hold
      */
     public boolean isOnHold() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mHold;
         }
     }
@@ -309,7 +315,7 @@
      * @return the local SIP profile
      */
     public SipProfile getLocalProfile() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mLocalProfile;
         }
     }
@@ -320,7 +326,7 @@
      * @return the peer's SIP profile
      */
     public SipProfile getPeerProfile() {
-        synchronized (this) {
+        synchronized (mLock) {
             return (mSipSession == null) ? null : mSipSession.getPeerProfile();
         }
     }
@@ -332,7 +338,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 +352,7 @@
      * @hide
      */
     public SipSession getSipSession() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mSipSession;
         }
     }
@@ -404,7 +410,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 +574,7 @@
                 loge("onError():", t);
             }
         }
-        synchronized (this) {
+        synchronized (mLock) {
             if ((errorCode == SipErrorCode.DATA_CONNECTION_LOST)
                     || !isInCall()) {
                 close(true);
@@ -591,7 +597,7 @@
             throw new SipException("VOIP API is not supported");
         }
 
-        synchronized (this) {
+        synchronized (mLock) {
             mSipSession = session;
             mPeerSd = sessionDescription;
             if (DBG) log("attachCall(): " + mPeerSd);
@@ -626,7 +632,7 @@
             throw new SipException("VOIP API is not supported");
         }
 
-        synchronized (this) {
+        synchronized (mLock) {
             mSipSession = sipSession;
             try {
                 mAudioStream = new AudioStream(InetAddress.getByName(
@@ -647,7 +653,7 @@
      */
     public void endCall() throws SipException {
         if (DBG) log("endCall: mSipSession" + mSipSession);
-        synchronized (this) {
+        synchronized (mLock) {
             stopCall(RELEASE_SOCKET);
             mInCall = false;
 
@@ -670,7 +676,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 +701,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 +730,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 +860,7 @@
 
     /** Toggles mute. */
     public void toggleMute() {
-        synchronized (this) {
+        synchronized (mLock) {
             mMuted = !mMuted;
             setAudioGroupMode();
         }
@@ -866,7 +872,7 @@
      * @return true if the call is muted
      */
     public boolean isMuted() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mMuted;
         }
     }
@@ -879,7 +885,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 +921,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 +944,7 @@
      * @hide
      */
     public AudioStream getAudioStream() {
-        synchronized (this) {
+        synchronized (mLock) {
             return mAudioStream;
         }
     }
@@ -957,8 +963,9 @@
      * @see #getAudioStream
      * @hide
      */
-    public AudioGroup getAudioGroup() {
-        synchronized (this) {
+    @SystemApi
+    public @Nullable AudioGroup getAudioGroup() {
+        synchronized (mLock) {
             if (mAudioGroup != null) return mAudioGroup;
             return ((mAudioStream == null) ? null : mAudioStream.getGroup());
         }
@@ -976,8 +983,9 @@
      * @see #getAudioStream
      * @hide
      */
-    public void setAudioGroup(AudioGroup group) {
-        synchronized (this) {
+    @SystemApi
+    public void setAudioGroup(@NonNull AudioGroup group) {
+        synchronized (mLock) {
             if (DBG) log("setAudioGroup: group=" + group);
             if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
                 mAudioStream.join(group);
@@ -1081,7 +1089,7 @@
             // don't create an AudioGroup here; doing so will fail if
             // there's another AudioGroup out there that's active
         } else {
-            if (audioGroup == null) audioGroup = new AudioGroup();
+            if (audioGroup == null) audioGroup = new AudioGroup(mContext);
             stream.join(audioGroup);
         }
         setAudioGroupMode();
diff --git a/src/java/android/net/sip/SipManager.java b/src/java/android/net/sip/SipManager.java
index 0cb1feb..39f66de 100644
--- a/src/java/android/net/sip/SipManager.java
+++ b/src/java/android/net/sip/SipManager.java
@@ -16,6 +16,9 @@
 
 package android.net.sip;
 
+import android.annotation.NonNull;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -26,6 +29,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 +86,23 @@
     public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
 
     /**
-     * Action to broadcast when SipService is up.
-     * Internal use only.
+     * Intent action sent when the SipManager becomes available.
      * @hide
      */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    @SystemApi
     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.
+     * Intent action sent when there is a new incoming SIP call.
      * @hide
      */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    @SystemApi
     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 +110,34 @@
      */
     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.
+     * Intent action sent when a SIP profile has been removed.
      * @hide
      */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    @SystemApi
+    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.
+     * @hide
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    @SystemApi
     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.
+     * @hide
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    @SystemApi
+    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.
@@ -603,12 +623,13 @@
      * (username, password and display name) are crossed out.
      * @hide
      */
-    public SipProfile[] getListOfProfiles() throws SipException {
+    @SystemApi
+    public @NonNull List<SipProfile> getProfiles() throws SipException {
         try {
             checkSipServiceConnection();
-            return mSipService.getListOfProfiles(mContext.getOpPackageName());
+            return mSipService.getProfiles(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return new SipProfile[0];
+            throw new SipException(e.getMessage());
         }
     }
 
diff --git a/src/java/android/net/sip/SipProfile.java b/src/java/android/net/sip/SipProfile.java
index 0ef754c..14b0334 100644
--- a/src/java/android/net/sip/SipProfile.java
+++ b/src/java/android/net/sip/SipProfile.java
@@ -16,6 +16,7 @@
 
 package android.net.sip;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -480,7 +481,6 @@
 
     /**
      * Sets the calling process's Uid in the sip service.
-     * @hide
      */
     public void setCallingUid(int uid) {
         mCallingUid = uid;
@@ -488,8 +488,11 @@
 
     /**
      * Gets the calling process's Uid in the sip settings.
+     *
+     * @return the calling process's Uid in the sip settings.
      * @hide
      */
+    @SystemApi
     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 d14a8d6..7c6daf8 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,19 @@
     }
 
     @Override
-    public synchronized SipProfile[] getListOfProfiles(String opPackageName) {
-        if (!canUseSip(opPackageName, "getListOfProfiles")) {
-            return new SipProfile[0];
+    public synchronized List<SipProfile> getProfiles(String opPackageName) throws RemoteException {
+        if (!canUseSip(opPackageName, "getProfiles")) {
+            throw new RemoteException(String.format("Package %s cannot use Sip service",
+                    opPackageName));
         }
         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 +352,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) {
diff --git a/src/jni/rtp/Android.bp b/src/jni/rtp/Android.bp
index bdd5071..c938224 100644
--- a/src/jni/rtp/Android.bp
+++ b/src/jni/rtp/Android.bp
@@ -26,13 +26,18 @@
         "G711Codec.cpp",
         "GsmCodec.cpp",
     ],
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
-        "libnativehelper",
-        "libcutils",
-        "libutils",
-        "liblog",
         "libaudioclient",
+        "libaudiofoundation",
+        "libcutils",
+        "liblog",
+        "libnativehelper",
         "libstagefright_amrnb_common",
+        "libutils",
     ],
     static_libs: [
         "libgsm",
diff --git a/src/jni/rtp/AudioGroup.cpp b/src/jni/rtp/AudioGroup.cpp
index e01fbca..8bb543c 100644
--- a/src/jni/rtp/AudioGroup.cpp
+++ b/src/jni/rtp/AudioGroup.cpp
@@ -37,10 +37,8 @@
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 #include <utils/SystemClock.h>
-#include <media/AudioSystem.h>
 #include <media/AudioRecord.h>
 #include <media/AudioTrack.h>
-#include <media/mediarecorder.h>
 #include <media/AudioEffect.h>
 #include <system/audio_effects/effect_aec.h>
 #include <system/audio.h>