Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5924dc4d authored by Wink Saville's avatar Wink Saville Committed by Android (Google) Code Review
Browse files

Merge "Delete frameworks/base/voip use voip-common from frameworks/opt/net/voip"

parents 4daf9b1b cbb2a2a2
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -219,10 +219,7 @@ LOCAL_SRC_FILES += \
	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
	wifi/java/android/net/wifi/IWifiManager.aidl \
	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
	voip/java/android/net/sip/ISipSession.aidl \
	voip/java/android/net/sip/ISipSessionListener.aidl \
	voip/java/android/net/sip/ISipService.aidl
	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
#


@@ -353,6 +350,8 @@ non_base_dirs := \
	../../external/apache-http/src/org/apache/http \
	../opt/telephony/src/java/android/telephony \
	../opt/telephony/src/java/android/telephony/gsm \
	../opt/net/voip/src/java/android/net/rtp \
	../opt/net/voip/src/java/android/net/sip

# These are relative to frameworks/base
dirs_to_check_apis := \
@@ -405,6 +404,7 @@ framework_docs_LOCAL_JAVA_LIBRARIES := \
			framework \
			mms-common \
			telephony-common \
			voip-common \

framework_docs_LOCAL_MODULE_CLASS := JAVA_LIBRARIES
framework_docs_LOCAL_DROIDDOC_HTML_DIR := docs/html
+5 −0
Original line number Diff line number Diff line
@@ -149,6 +149,11 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayMagnificationController.P)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayMagnificationMediator.java)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayMagnificationMediator.P)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/voip)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/librtp_jni_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/librtp_jni.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/librtp_jni.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/lib/librtp_jni.so)

# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+0 −146
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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 android.net.rtp;

import java.util.Arrays;

/**
 * This class defines a collection of audio codecs to be used with
 * {@link AudioStream}s. Their parameters are designed to be exchanged using
 * Session Description Protocol (SDP). Most of the values listed here can be
 * found in RFC 3551, while others are described in separated standards.
 *
 * <p>Few simple configurations are defined as public static instances for the
 * convenience of direct uses. More complicated ones could be obtained using
 * {@link #getCodec(int, String, String)}. For example, one can use the
 * following snippet to create a mode-1-only AMR codec.</p>
 * <pre>
 * AudioCodec codec = AudioCodec.getCodec(100, "AMR/8000", "mode-set=1");
 * </pre>
 *
 * @see AudioStream
 */
public class AudioCodec {
    /**
     * The RTP payload type of the encoding.
     */
    public final int type;

    /**
     * The encoding parameters to be used in the corresponding SDP attribute.
     */
    public final String rtpmap;

    /**
     * The format parameters to be used in the corresponding SDP attribute.
     */
    public final String fmtp;

    /**
     * G.711 u-law audio codec.
     */
    public static final AudioCodec PCMU = new AudioCodec(0, "PCMU/8000", null);

    /**
     * G.711 a-law audio codec.
     */
    public static final AudioCodec PCMA = new AudioCodec(8, "PCMA/8000", null);

    /**
     * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or
     * simply FR.
     */
    public static final AudioCodec GSM = new AudioCodec(3, "GSM/8000", null);

    /**
     * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or
     * simply EFR.
     */
    public static final AudioCodec GSM_EFR = new AudioCodec(96, "GSM-EFR/8000", null);

    /**
     * Adaptive Multi-Rate narrowband audio codec, also known as AMR or AMR-NB.
     * Currently CRC, robust sorting, and interleaving are not supported. See
     * more details about these features in RFC 4867.
     */
    public static final AudioCodec AMR = new AudioCodec(97, "AMR/8000", null);

    private static final AudioCodec[] sCodecs = {GSM_EFR, AMR, GSM, PCMU, PCMA};

    private AudioCodec(int type, String rtpmap, String fmtp) {
        this.type = type;
        this.rtpmap = rtpmap;
        this.fmtp = fmtp;
    }

    /**
     * Returns system supported audio codecs.
     */
    public static AudioCodec[] getCodecs() {
        return Arrays.copyOf(sCodecs, sCodecs.length);
    }

    /**
     * Creates an AudioCodec according to the given configuration.
     *
     * @param type The payload type of the encoding defined in RTP/AVP.
     * @param rtpmap The encoding parameters specified in the corresponding SDP
     *     attribute, or null if it is not available.
     * @param fmtp The format parameters specified in the corresponding SDP
     *     attribute, or null if it is not available.
     * @return The configured AudioCodec or {@code null} if it is not supported.
     */
    public static AudioCodec getCodec(int type, String rtpmap, String fmtp) {
        if (type < 0 || type > 127) {
            return null;
        }

        AudioCodec hint = null;
        if (rtpmap != null) {
            String clue = rtpmap.trim().toUpperCase();
            for (AudioCodec codec : sCodecs) {
                if (clue.startsWith(codec.rtpmap)) {
                    String channels = clue.substring(codec.rtpmap.length());
                    if (channels.length() == 0 || channels.equals("/1")) {
                        hint = codec;
                    }
                    break;
                }
            }
        } else if (type < 96) {
            for (AudioCodec codec : sCodecs) {
                if (type == codec.type) {
                    hint = codec;
                    rtpmap = codec.rtpmap;
                    break;
                }
            }
        }

        if (hint == null) {
            return null;
        }
        if (hint == AMR && fmtp != null) {
            String clue = fmtp.toLowerCase();
            if (clue.contains("crc=1") || clue.contains("robust-sorting=1") ||
                    clue.contains("interleaving=")) {
                return null;
            }
        }
        return new AudioCodec(type, rtpmap, fmtp);
    }
}
+0 −206
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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 android.net.rtp;

import android.media.AudioManager;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * An AudioGroup is an audio hub for the speaker, the microphone, and
 * {@link AudioStream}s. Each of these components can be logically turned on
 * or off by calling {@link #setMode(int)} or {@link RtpStream#setMode(int)}.
 * The AudioGroup will go through these components and process them one by one
 * within its execution loop. The loop consists of four steps. First, for each
 * AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its incoming
 * packets and stores in its buffer. Then, if the microphone is enabled,
 * processes the recorded audio and stores in its buffer. Third, if the speaker
 * is enabled, mixes all AudioStream buffers and plays back. Finally, for each
 * AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all other
 * buffers and sends back the encoded packets. An AudioGroup does nothing if
 * there is no AudioStream in it.
 *
 * <p>Few things must be noticed before using these classes. The performance is
 * highly related to the system load and the network bandwidth. Usually a
 * simpler {@link AudioCodec} costs fewer CPU cycles but requires more network
 * bandwidth, and vise versa. Using two AudioStreams at the same time doubles
 * not only the load but also the bandwidth. The condition varies from one
 * device to another, and developers should choose the right combination in
 * order to get the best result.</p>
 *
 * <p>It is sometimes useful to keep multiple AudioGroups at the same time. For
 * example, a Voice over IP (VoIP) application might want to put a conference
 * call on hold in order to make a new call but still allow people in the
 * conference call talking to each other. This can be done easily using two
 * AudioGroups, but there are some limitations. Since the speaker and the
 * microphone are globally shared resources, only one AudioGroup at a time is
 * allowed to run in a mode other than {@link #MODE_ON_HOLD}. The others will
 * be unable to acquire these resources and fail silently.</p>
 *
 * <p class="note">Using this class requires
 * {@link android.Manifest.permission#RECORD_AUDIO} permission. Developers
 * should set the audio mode to {@link AudioManager#MODE_IN_COMMUNICATION}
 * using {@link AudioManager#setMode(int)} and change it back when none of
 * the AudioGroups is in use.</p>
 *
 * @see AudioStream
 */
public class AudioGroup {
    /**
     * This mode is similar to {@link #MODE_NORMAL} except the speaker and
     * the microphone are both disabled.
     */
    public static final int MODE_ON_HOLD = 0;

    /**
     * This mode is similar to {@link #MODE_NORMAL} except the microphone is
     * disabled.
     */
    public static final int MODE_MUTED = 1;

    /**
     * This mode indicates that the speaker, the microphone, and all
     * {@link AudioStream}s in the group are enabled. First, the packets
     * received from the streams are decoded and mixed with the audio recorded
     * from the microphone. Then, the results are played back to the speaker,
     * encoded and sent back to each stream.
     */
    public static final int MODE_NORMAL = 2;

    /**
     * This mode is similar to {@link #MODE_NORMAL} except the echo suppression
     * is enabled. It should be only used when the speaker phone is on.
     */
    public static final int MODE_ECHO_SUPPRESSION = 3;

    private static final int MODE_LAST = 3;

    private final Map<AudioStream, Integer> mStreams;
    private int mMode = MODE_ON_HOLD;

    private int mNative;
    static {
        System.loadLibrary("rtp_jni");
    }

    /**
     * Creates an empty AudioGroup.
     */
    public AudioGroup() {
        mStreams = new HashMap<AudioStream, Integer>();
    }

    /**
     * Returns the {@link AudioStream}s in this group.
     */
    public AudioStream[] getStreams() {
        synchronized (this) {
            return mStreams.keySet().toArray(new AudioStream[mStreams.size()]);
        }
    }

    /**
     * Returns the current mode.
     */
    public int getMode() {
        return mMode;
    }

    /**
     * Changes the current mode. It must be one of {@link #MODE_ON_HOLD},
     * {@link #MODE_MUTED}, {@link #MODE_NORMAL}, and
     * {@link #MODE_ECHO_SUPPRESSION}.
     *
     * @param mode The mode to change to.
     * @throws IllegalArgumentException if the mode is invalid.
     */
    public void setMode(int mode) {
        if (mode < 0 || mode > MODE_LAST) {
            throw new IllegalArgumentException("Invalid mode");
        }
        synchronized (this) {
            nativeSetMode(mode);
            mMode = mode;
        }
    }

    private native void nativeSetMode(int mode);

    // Package-private method used by AudioStream.join().
    synchronized void add(AudioStream stream) {
        if (!mStreams.containsKey(stream)) {
            try {
                AudioCodec codec = stream.getCodec();
                String codecSpec = String.format(Locale.US, "%d %s %s", codec.type,
                        codec.rtpmap, codec.fmtp);
                int id = nativeAdd(stream.getMode(), stream.getSocket(),
                        stream.getRemoteAddress().getHostAddress(),
                        stream.getRemotePort(), codecSpec, stream.getDtmfType());
                mStreams.put(stream, id);
            } catch (NullPointerException e) {
                throw new IllegalStateException(e);
            }
        }
    }

    private native int nativeAdd(int mode, int socket, String remoteAddress,
            int remotePort, String codecSpec, int dtmfType);

    // Package-private method used by AudioStream.join().
    synchronized void remove(AudioStream stream) {
        Integer id = mStreams.remove(stream);
        if (id != null) {
            nativeRemove(id);
        }
    }

    private native void nativeRemove(int id);

    /**
     * Sends a DTMF digit to every {@link AudioStream} in this group. Currently
     * only event {@code 0} to {@code 15} are supported.
     *
     * @throws IllegalArgumentException if the event is invalid.
     */
    public void sendDtmf(int event) {
        if (event < 0 || event > 15) {
            throw new IllegalArgumentException("Invalid event");
        }
        synchronized (this) {
            nativeSendDtmf(event);
        }
    }

    private native void nativeSendDtmf(int event);

    /**
     * Removes every {@link AudioStream} in this group.
     */
    public void clear() {
        for (AudioStream stream : getStreams()) {
            stream.join(null);
        }
    }

    @Override
    protected void finalize() throws Throwable {
        nativeRemove(0);
        super.finalize();
    }
}
+0 −167
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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 android.net.rtp;

import java.net.InetAddress;
import java.net.SocketException;

/**
 * An AudioStream is a {@link RtpStream} which carrys audio payloads over
 * Real-time Transport Protocol (RTP). Two different classes are developed in
 * order to support various usages such as audio conferencing. An AudioStream
 * represents a remote endpoint which consists of a network mapping and a
 * configured {@link AudioCodec}. On the other side, An {@link AudioGroup}
 * represents a local endpoint which mixes all the AudioStreams and optionally
 * interacts with the speaker and the microphone at the same time. The simplest
 * usage includes one for each endpoints. For other combinations, developers
 * should be aware of the limitations described in {@link AudioGroup}.
 *
 * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most
 * of the setter methods are disabled. This is designed to ease the task of
 * managing native resources. One can always make an AudioStream leave its
 * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it
 * back after the modification is done.</p>
 *
 * <p class="note">Using this class requires
 * {@link android.Manifest.permission#INTERNET} permission.</p>
 *
 * @see RtpStream
 * @see AudioGroup
 */
public class AudioStream extends RtpStream {
    private AudioCodec mCodec;
    private int mDtmfType = -1;
    private AudioGroup mGroup;

    /**
     * Creates an AudioStream on the given local address. Note that the local
     * port is assigned automatically to conform with RFC 3550.
     *
     * @param address The network address of the local host to bind to.
     * @throws SocketException if the address cannot be bound or a problem
     *     occurs during binding.
     */
    public AudioStream(InetAddress address) throws SocketException {
        super(address);
    }

    /**
     * Returns {@code true} if the stream has already joined an
     * {@link AudioGroup}.
     */
    @Override
    public final boolean isBusy() {
        return mGroup != null;
    }

    /**
     * Returns the joined {@link AudioGroup}.
     */
    public AudioGroup getGroup() {
        return mGroup;
    }

    /**
     * Joins an {@link AudioGroup}. Each stream can join only one group at a
     * time. The group can be changed by passing a different one or removed
     * by calling this method with {@code null}.
     *
     * @param group The AudioGroup to join or {@code null} to leave.
     * @throws IllegalStateException if the stream is not properly configured.
     * @see AudioGroup
     */
    public void join(AudioGroup group) {
        synchronized (this) {
            if (mGroup == group) {
                return;
            }
            if (mGroup != null) {
                mGroup.remove(this);
                mGroup = null;
            }
            if (group != null) {
                group.add(this);
                mGroup = group;
            }
        }
    }

    /**
     * Returns the {@link AudioCodec}, or {@code null} if it is not set.
     *
     * @see #setCodec(AudioCodec)
     */
    public AudioCodec getCodec() {
        return mCodec;
    }

    /**
     * Sets the {@link AudioCodec}.
     *
     * @param codec The AudioCodec to be used.
     * @throws IllegalArgumentException if its type is used by DTMF.
     * @throws IllegalStateException if the stream is busy.
     */
    public void setCodec(AudioCodec codec) {
        if (isBusy()) {
            throw new IllegalStateException("Busy");
        }
        if (codec.type == mDtmfType) {
            throw new IllegalArgumentException("The type is used by DTMF");
        }
        mCodec = codec;
    }

    /**
     * Returns the RTP payload type for dual-tone multi-frequency (DTMF) digits,
     * or {@code -1} if it is not enabled.
     *
     * @see #setDtmfType(int)
     */
    public int getDtmfType() {
        return mDtmfType;
    }

    /**
     * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits.
     * The primary usage is to send digits to the remote gateway to perform
     * certain tasks, such as second-stage dialing. According to RFC 2833, the
     * RTP payload type for DTMF is assigned dynamically, so it must be in the
     * range of 96 and 127. One can use {@code -1} to disable DTMF and free up
     * the previous assigned type. This method cannot be called when the stream
     * already joined an {@link AudioGroup}.
     *
     * @param type The RTP payload type to be used or {@code -1} to disable it.
     * @throws IllegalArgumentException if the type is invalid or used by codec.
     * @throws IllegalStateException if the stream is busy.
     * @see AudioGroup#sendDtmf(int)
     */
    public void setDtmfType(int type) {
        if (isBusy()) {
            throw new IllegalStateException("Busy");
        }
        if (type != -1) {
            if (type < 96 || type > 127) {
                throw new IllegalArgumentException("Invalid type");
            }
            if (mCodec != null && type == mCodec.type) {
                throw new IllegalArgumentException("The type is used by codec");
            }
        }
        mDtmfType = type;
    }
}
Loading