Merge "Add WiFi toggle prompts - framework"
diff --git a/api/current.txt b/api/current.txt
index 03e3f36..21fe3e2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -36363,6 +36363,7 @@
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+    field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 256; // 0x100
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
@@ -36864,8 +36865,12 @@
     method public int describeContents();
     method public boolean equals(java.lang.Object);
     method public int getAsuLevel();
+    method public int getCqi();
     method public int getDbm();
     method public int getLevel();
+    method public int getRsrp();
+    method public int getRsrq();
+    method public int getRssnr();
     method public int getTimingAdvance();
     method public int hashCode();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 057f1af..974db45 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -39267,6 +39267,7 @@
     field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+    field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 256; // 0x100
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
@@ -39799,8 +39800,12 @@
     method public int describeContents();
     method public boolean equals(java.lang.Object);
     method public int getAsuLevel();
+    method public int getCqi();
     method public int getDbm();
     method public int getLevel();
+    method public int getRsrp();
+    method public int getRsrq();
+    method public int getRssnr();
     method public int getTimingAdvance();
     method public int hashCode();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 85b5ab8..29de7a5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -36440,6 +36440,7 @@
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+    field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 256; // 0x100
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
@@ -36941,8 +36942,12 @@
     method public int describeContents();
     method public boolean equals(java.lang.Object);
     method public int getAsuLevel();
+    method public int getCqi();
     method public int getDbm();
     method public int getLevel();
+    method public int getRsrp();
+    method public int getRsrq();
+    method public int getRssnr();
     method public int getTimingAdvance();
     method public int hashCode();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 11c2735..4271e3f 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -601,10 +601,6 @@
      */
     public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
         if (!getLeAccess()) return null;
-        if (!isMultipleAdvertisementSupported() && !isPeripheralModeSupported()) {
-            Log.e(TAG, "Bluetooth LE advertising not supported");
-            return null;
-        }
         synchronized(mLock) {
             if (sBluetoothLeAdvertiser == null) {
                 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
@@ -1354,24 +1350,6 @@
     }
 
     /**
-     * Returns whether peripheral mode is supported.
-     *
-     * @hide
-     */
-    public boolean isPeripheralModeSupported() {
-        if (getState() != STATE_ON) return false;
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) return mService.isPeripheralModeSupported();
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get peripheral mode capability: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
      * Return true if offloaded filters are supported
      *
      * @return true if chipset supports on-chip filtering
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 96a1ae8..7c5458b 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -100,7 +100,6 @@
     boolean factoryReset();
 
     boolean isMultiAdvertisementSupported();
-    boolean isPeripheralModeSupported();
     boolean isOffloadedFilteringSupported();
     boolean isOffloadedScanBatchingSupported();
     boolean isActivityAndEnergyReportingSupported();
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 26f2dea..5d27662 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -111,12 +111,6 @@
             if (callback == null) {
                 throw new IllegalArgumentException("callback cannot be null");
             }
-            if (!mBluetoothAdapter.isMultipleAdvertisementSupported() &&
-                    !mBluetoothAdapter.isPeripheralModeSupported()) {
-                postStartFailure(callback,
-                        AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED);
-                return;
-            }
             boolean isConnectable = settings.isConnectable();
             if (totalBytes(advertiseData, isConnectable) > MAX_ADVERTISING_DATA_BYTES ||
                     totalBytes(scanResponse, false) > MAX_ADVERTISING_DATA_BYTES) {
@@ -236,9 +230,9 @@
         private final AdvertiseSettings mSettings;
         private final IBluetoothGatt mBluetoothGatt;
 
-        // mAdvertiserId 0: not registered
-        // -1: advertise stopped or registration timeout
-        // >0: registered and advertising started
+        // mAdvertiserId -1: not registered
+        // -2: advertise stopped or registration timeout
+        // >=0: registered and advertising started
         private int mAdvertiserId;
         private boolean mIsAdvertising = false;
 
@@ -251,12 +245,12 @@
             mScanResponse = scanResponse;
             mSettings = settings;
             mBluetoothGatt = bluetoothGatt;
-            mAdvertiserId = 0;
+            mAdvertiserId = -1;
         }
 
         public void startRegisteration() {
             synchronized (this) {
-                if (mAdvertiserId == -1) return;
+                if (mAdvertiserId == -2) return;
 
                 try {
                     mBluetoothGatt.registerAdvertiser(this);
@@ -264,13 +258,13 @@
                 } catch (InterruptedException | RemoteException e) {
                     Log.e(TAG, "Failed to start registeration", e);
                 }
-                if (mAdvertiserId > 0 && mIsAdvertising) {
+                if (mAdvertiserId >= 0 && mIsAdvertising) {
                     mLeAdvertisers.put(mAdvertiseCallback, this);
-                } else if (mAdvertiserId <= 0) {
+                } else if (mAdvertiserId < 0) {
 
                     // Registration timeout, reset mClientIf to -1 so no subsequent operations can
                     // proceed.
-                    if (mAdvertiserId == 0) mAdvertiserId = -1;
+                    if (mAdvertiserId == 0) mAdvertiserId = -2;
                     // Post internal error if registration failed.
                     postStartFailure(mAdvertiseCallback,
                             AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
@@ -278,7 +272,7 @@
                     // Unregister application if it's already registered but advertise failed.
                     try {
                         mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
-                        mAdvertiserId = -1;
+                        mAdvertiserId = -2;
                     } catch (RemoteException e) {
                         Log.e(TAG, "remote exception when unregistering", e);
                     }
@@ -312,7 +306,7 @@
             synchronized (this) {
                 if (status == BluetoothGatt.GATT_SUCCESS) {
                     try {
-                        if (mAdvertiserId == -1) {
+                        if (mAdvertiserId == -2) {
                             // Registration succeeds after timeout, unregister advertiser.
                             mBluetoothGatt.unregisterAdvertiser(advertiserId);
                         } else {
@@ -326,7 +320,7 @@
                     }
                 }
                 // Registration failed.
-                mAdvertiserId = -1;
+                mAdvertiserId = -2;
                 notifyAll();
             }
         }
@@ -348,7 +342,7 @@
                     // unregister advertiser for stop.
                     try {
                         mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
-                        mAdvertiserId = -1;
+                        mAdvertiserId = -2;
                         mIsAdvertising = false;
                         mLeAdvertisers.remove(mAdvertiseCallback);
                     } catch (RemoteException e) {
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 886c0e6..f909580 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -267,9 +267,9 @@
 
     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
     if (interfaceName) {
-        String16 nameCopy(
+        String8 nameCopy = String8(String16(
                 reinterpret_cast<const char16_t *>(interfaceName),
-                env->GetStringLength(interfaceNameObj));
+                env->GetStringLength(interfaceNameObj)));
 
         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
         interfaceName = NULL;
@@ -277,7 +277,7 @@
         hardware::Parcel *parcel =
             JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
-        status_t err = parcel->writeInterfaceToken(nameCopy);
+        status_t err = parcel->writeInterfaceToken(nameCopy.string());
         signalExceptionForError(env, err);
     }
 }
@@ -294,9 +294,9 @@
 
     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
     if (interfaceName) {
-        String16 interfaceNameCopy(
+        String8 interfaceNameCopy = String8(String16(
                 reinterpret_cast<const char16_t *>(interfaceName),
-                env->GetStringLength(interfaceNameObj));
+                env->GetStringLength(interfaceNameObj)));
 
         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
         interfaceName = NULL;
@@ -304,7 +304,7 @@
         hardware::Parcel *parcel =
             JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
-        bool valid = parcel->enforceInterface(interfaceNameCopy);
+        bool valid = parcel->enforceInterface(interfaceNameCopy.string());
 
         if (!valid) {
             jniThrowException(
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3e111c0..ca09708 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -304,7 +304,7 @@
         storageSource = "/mnt/runtime/read";
     } else if (mount_mode == MOUNT_EXTERNAL_WRITE) {
         storageSource = "/mnt/runtime/write";
-    } else {
+    } else if (!force_mount_namespace) {
         // Sane default of no storage visible
         return true;
     }
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
index f90f1e2..fb91bbb 100644
--- a/media/java/android/media/AmrInputStream.java
+++ b/media/java/android/media/AmrInputStream.java
@@ -18,45 +18,69 @@
 
 import java.io.InputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import android.media.MediaCodec.BufferInfo;
+import android.util.Log;
 
 
 /**
  * AmrInputStream
  * @hide
  */
-public final class AmrInputStream extends InputStream
-{    
-    static {
-        System.loadLibrary("media_jni");
-    }
-    
+public final class AmrInputStream extends InputStream {
     private final static String TAG = "AmrInputStream";
     
     // frame is 20 msec at 8.000 khz
     private final static int SAMPLES_PER_FRAME = 8000 * 20 / 1000;
-    
+
+    MediaCodec mCodec;
+    BufferInfo mInfo;
+    boolean mSawOutputEOS;
+    boolean mSawInputEOS;
+
     // pcm input stream
     private InputStream mInputStream;
-    
-    // native handle
-    private long mGae;
-    
+
     // result amr stream
     private final byte[] mBuf = new byte[SAMPLES_PER_FRAME * 2];
     private int mBufIn = 0;
     private int mBufOut = 0;
-    
+
     // helper for bytewise read()
     private byte[] mOneByte = new byte[1];
-    
+
     /**
      * Create a new AmrInputStream, which converts 16 bit PCM to AMR
      * @param inputStream InputStream containing 16 bit PCM.
      */
     public AmrInputStream(InputStream inputStream) {
         mInputStream = inputStream;
-        mGae = GsmAmrEncoderNew();
-        GsmAmrEncoderInitialize(mGae);
+
+        MediaFormat format  = new MediaFormat();
+        format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_NB);
+        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
+        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, 12200);
+
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        String name = mcl.findEncoderForFormat(format);
+        if (name != null) {
+            try {
+                mCodec = MediaCodec.createByCodecName(name);
+                mCodec.configure(format,
+                        null /* surface */,
+                        null /* crypto */,
+                        MediaCodec.CONFIGURE_FLAG_ENCODE);
+                mCodec.start();
+            } catch (IOException e) {
+                if (mCodec != null) {
+                    mCodec.release();
+                }
+                mCodec = null;
+            }
+        }
+        mInfo = new BufferInfo();
     }
 
     @Override
@@ -64,7 +88,7 @@
         int rtn = read(mOneByte, 0, 1);
         return rtn == 1 ? (0xff & mOneByte[0]) : -1;
     }
-    
+
     @Override
     public int read(byte[] b) throws IOException {
         return read(b, 0, b.length);
@@ -72,67 +96,100 @@
 
     @Override
     public int read(byte[] b, int offset, int length) throws IOException {
-        if (mGae == 0) throw new IllegalStateException("not open");
-        
-        // local buffer of amr encoded audio empty
-        if (mBufOut >= mBufIn) {
-            // reset the buffer
+        if (mCodec == null) {
+            throw new IllegalStateException("not open");
+        }
+
+        if (mBufOut >= mBufIn && !mSawOutputEOS) {
+            // no data left in buffer, refill it
             mBufOut = 0;
             mBufIn = 0;
-            
-            // fetch a 20 msec frame of pcm
-            for (int i = 0; i < SAMPLES_PER_FRAME * 2; ) {
-                int n = mInputStream.read(mBuf, i, SAMPLES_PER_FRAME * 2 - i);
-                if (n == -1) return -1;
-                i += n;
+
+            // first push as much data into the encoder as possible
+            while (!mSawInputEOS) {
+                int index = mCodec.dequeueInputBuffer(0);
+                if (index < 0) {
+                    // no input buffer currently available
+                    break;
+                } else {
+                    int numRead;
+                    for (numRead = 0; numRead < SAMPLES_PER_FRAME * 2; ) {
+                        int n = mInputStream.read(mBuf, numRead, SAMPLES_PER_FRAME * 2 - numRead);
+                        if (n == -1) {
+                            mSawInputEOS = true;
+                            break;
+                        }
+                        numRead += n;
+                    }
+                    ByteBuffer buf = mCodec.getInputBuffer(index);
+                    buf.put(mBuf, 0, numRead);
+                    mCodec.queueInputBuffer(index,
+                            0 /* offset */,
+                            numRead,
+                            0 /* presentationTimeUs */,
+                            mSawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0 /* flags */);
+                }
             }
-            
-            // encode it
-            mBufIn = GsmAmrEncoderEncode(mGae, mBuf, 0, mBuf, 0);
+
+            // now read encoded data from the encoder (blocking, since we just filled up the
+            // encoder's input with data it should be able to output at least one buffer)
+            while (true) {
+                int index = mCodec.dequeueOutputBuffer(mInfo, -1);
+                if (index >= 0) {
+                    mBufIn = mInfo.size;
+                    ByteBuffer out = mCodec.getOutputBuffer(index);
+                    out.get(mBuf, 0 /* offset */, mBufIn /* length */);
+                    mCodec.releaseOutputBuffer(index,  false /* render */);
+                    if ((mInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                        mSawOutputEOS = true;
+                    }
+                    break;
+                }
+            }
         }
-        
-        // return encoded audio to user
-        if (length > mBufIn - mBufOut) length = mBufIn - mBufOut;
-        System.arraycopy(mBuf, mBufOut, b, offset, length);
-        mBufOut += length;
-        
-        return length;
+
+        if (mBufOut < mBufIn) {
+            // there is data in the buffer
+            if (length > mBufIn - mBufOut) {
+                length = mBufIn - mBufOut;
+            }
+            System.arraycopy(mBuf, mBufOut, b, offset, length);
+            mBufOut += length;
+            return length;
+        }
+
+        if (mSawInputEOS && mSawOutputEOS) {
+            // no more data available in buffer, codec or input stream
+            return -1;
+        }
+
+        // caller should try again
+        return 0;
     }
 
     @Override
     public void close() throws IOException {
         try {
-            if (mInputStream != null) mInputStream.close();
+            if (mInputStream != null) {
+                mInputStream.close();
+            }
         } finally {
             mInputStream = null;
             try {
-                if (mGae != 0) GsmAmrEncoderCleanup(mGae);
-            } finally {
-                try {
-                    if (mGae != 0) GsmAmrEncoderDelete(mGae);
-                } finally {
-                    mGae = 0;
+                if (mCodec != null) {
+                    mCodec.release();
                 }
+            } finally {
+                mCodec = null;
             }
         }
     }
 
     @Override
     protected void finalize() throws Throwable {
-        if (mGae != 0) {
-            close();
-            throw new IllegalStateException("someone forgot to close AmrInputStream");
+        if (mCodec != null) {
+            Log.w(TAG, "AmrInputStream wasn't closed");
+            mCodec.release();
         }
     }
-    
-    //
-    // AudioRecord JNI interface
-    //
-    private static native long GsmAmrEncoderNew();
-    private static native void GsmAmrEncoderInitialize(long gae);
-    private static native int GsmAmrEncoderEncode(long gae,
-            byte[] pcm, int pcmOffset, byte[] amr, int amrOffset) throws IOException;
-    private static native void GsmAmrEncoderCleanup(long gae);
-    private static native void GsmAmrEncoderDelete(long gae);
-
 }
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 3355d42..8640565 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,7 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    android_media_AmrInputStream.cpp \
     android_media_ExifInterface.cpp \
     android_media_ImageWriter.cpp \
     android_media_ImageReader.cpp \
@@ -46,11 +45,9 @@
     libusbhost \
     libexif \
     libpiex \
-    libstagefright_amrnb_common \
     libandroidfw
 
 LOCAL_STATIC_LIBRARIES := \
-    libstagefright_amrnbenc
 
 LOCAL_C_INCLUDES += \
     external/libexif/ \
@@ -60,9 +57,6 @@
     frameworks/base/libs/hwui \
     frameworks/av/media/libmedia \
     frameworks/av/media/libstagefright \
-    frameworks/av/media/libstagefright/codecs/amrnb/enc/src \
-    frameworks/av/media/libstagefright/codecs/amrnb/common \
-    frameworks/av/media/libstagefright/codecs/amrnb/common/include \
     frameworks/av/media/mtp \
     frameworks/native/include/media/openmax \
     $(call include-path-for, libhardware)/hardware \
diff --git a/media/jni/android_media_AmrInputStream.cpp b/media/jni/android_media_AmrInputStream.cpp
deleted file mode 100644
index b56a364..0000000
--- a/media/jni/android_media_AmrInputStream.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-**
-** Copyright 2007, 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.
-*/
-
-#define LOG_TAG "AmrInputStream"
-#include "utils/Log.h"
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "gsmamr_enc.h"
-
-// ----------------------------------------------------------------------------
-
-using namespace android;
-
-// Corresponds to max bit rate of 12.2 kbps.
-static const int MAX_OUTPUT_BUFFER_SIZE = 32;
-static const int FRAME_DURATION_MS = 20;
-static const int SAMPLING_RATE_HZ = 8000;
-static const int SAMPLES_PER_FRAME = ((SAMPLING_RATE_HZ * FRAME_DURATION_MS) / 1000);
-static const int BYTES_PER_SAMPLE = 2;  // Assume 16-bit PCM samples
-static const int BYTES_PER_FRAME = (SAMPLES_PER_FRAME * BYTES_PER_SAMPLE);
-
-struct GsmAmrEncoderState {
-    GsmAmrEncoderState()
-        : mEncState(NULL),
-          mSidState(NULL),
-          mLastModeUsed(0) {
-    }
-
-    ~GsmAmrEncoderState() {}
-
-    void*   mEncState;
-    void*   mSidState;
-    int32_t mLastModeUsed;
-};
-
-static jlong android_media_AmrInputStream_GsmAmrEncoderNew
-        (JNIEnv *env, jclass /* clazz */) {
-    GsmAmrEncoderState* gae = new GsmAmrEncoderState();
-    if (gae == NULL) {
-        jniThrowRuntimeException(env, "Out of memory");
-    }
-    return (jlong)gae;
-}
-
-static void android_media_AmrInputStream_GsmAmrEncoderInitialize
-        (JNIEnv *env, jclass /* clazz */, jlong gae) {
-    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
-    int32_t nResult = AMREncodeInit(&state->mEncState, &state->mSidState, false);
-    if (nResult != OK) {
-        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-                "GsmAmrEncoder initialization failed %d", nResult);
-    }
-}
-
-static jint android_media_AmrInputStream_GsmAmrEncoderEncode
-        (JNIEnv *env, jclass /* clazz */,
-         jlong gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {
-
-    jbyte inBuf[BYTES_PER_FRAME];
-    jbyte outBuf[MAX_OUTPUT_BUFFER_SIZE];
-
-    env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
-    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
-    int32_t length = AMREncode(state->mEncState, state->mSidState,
-                                (Mode) MR122,
-                                (int16_t *) inBuf,
-                                (unsigned char *) outBuf,
-                                (Frame_Type_3GPP*) &state->mLastModeUsed,
-                                AMR_TX_WMF);
-    if (length < 0) {
-        jniThrowExceptionFmt(env, "java/io/IOException",
-                "Failed to encode a frame with error code: %d", length);
-        return (jint)-1;
-    }
-
-    // The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
-    // bitpacked, i.e.;
-    //    [P(4) + FT(4)]. Q=1 for good frame, P=padding bit, 0
-    // Here we are converting the header to be as specified in Section 5.3 of
-    // RFC 3267 (AMR storage format) i.e.
-    //    [P(1) + FT(4) + Q(1) + P(2)].
-    if (length > 0) {
-      outBuf[0] = (outBuf[0] << 3) | 0x4;
-    }
-
-    env->SetByteArrayRegion(amr, amrOffset, length, outBuf);
-
-    return (jint)length;
-}
-
-static void android_media_AmrInputStream_GsmAmrEncoderCleanup
-        (JNIEnv* /* env */, jclass /* clazz */, jlong gae) {
-    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
-    AMREncodeExit(&state->mEncState, &state->mSidState);
-    state->mEncState = NULL;
-    state->mSidState = NULL;
-}
-
-static void android_media_AmrInputStream_GsmAmrEncoderDelete
-        (JNIEnv* /* env */, jclass /* clazz */, jlong gae) {
-    delete (GsmAmrEncoderState*)gae;
-}
-
-// ----------------------------------------------------------------------------
-
-static const JNINativeMethod gMethods[] = {
-    {"GsmAmrEncoderNew",        "()J",        (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
-    {"GsmAmrEncoderInitialize", "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
-    {"GsmAmrEncoderEncode",     "(J[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
-    {"GsmAmrEncoderCleanup",    "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderCleanup},
-    {"GsmAmrEncoderDelete",     "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderDelete},
-};
-
-
-int register_android_media_AmrInputStream(JNIEnv *env)
-{
-    const char* const kClassPathName = "android/media/AmrInputStream";
-
-    return AndroidRuntime::registerNativeMethods(env,
-            kClassPathName, gMethods, NELEM(gMethods));
-}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2fb1a3b..8f14b79 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1106,7 +1106,6 @@
 extern int register_android_media_MediaSync(JNIEnv *env);
 extern int register_android_media_ResampleInputStream(JNIEnv *env);
 extern int register_android_media_MediaProfiles(JNIEnv *env);
-extern int register_android_media_AmrInputStream(JNIEnv *env);
 extern int register_android_mtp_MtpDatabase(JNIEnv *env);
 extern int register_android_mtp_MtpDevice(JNIEnv *env);
 extern int register_android_mtp_MtpServer(JNIEnv *env);
@@ -1152,11 +1151,6 @@
         goto bail;
     }
 
-    if (register_android_media_AmrInputStream(env) < 0) {
-        ALOGE("ERROR: AmrInputStream native registration failed\n");
-        goto bail;
-    }
-
     if (register_android_media_ResampleInputStream(env) < 0) {
         ALOGE("ERROR: ResampleInputStream native registration failed\n");
         goto bail;
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 2a5b194..5b36598 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -58,6 +58,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -117,7 +118,6 @@
     private static final int SERVICE_IBLUETOOTHGATT = 2;
 
     private final Context mContext;
-    private static int mBleAppCount = 0;
 
     // Locks are not provided for mName and mAddress.
     // They are accessed in handler or broadcast receiver, same thread context.
@@ -211,10 +211,7 @@
 
                     if (isAirplaneModeOn()) {
                         // Clear registered LE apps to force shut-off
-                        synchronized (this) {
-                            mBleAppCount = 0;
-                            mBleApps.clear();
-                        }
+                        clearBleApps();
                         if (st == BluetoothAdapter.STATE_BLE_ON) {
                             //if state is BLE_ON make sure you trigger disableBLE part
                             try {
@@ -438,28 +435,28 @@
     class ClientDeathRecipient implements IBinder.DeathRecipient {
         public void binderDied() {
             if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App");
-            if (mBleAppCount > 0) --mBleAppCount;
-
-            if (mBleAppCount == 0) {
-                if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash");
-                try {
-                    mBluetoothLock.readLock().lock();
-                    if (mBluetooth != null &&
-                        mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
-                        mEnable = false;
-                        mBluetooth.onBrEdrDown();
-                    }
-                } catch (RemoteException e) {
-                     Slog.e(TAG,"Unable to call onBrEdrDown", e);
-                } finally {
-                    mBluetoothLock.readLock().unlock();
+            if (isBleAppPresent()) {
+              // Nothing to do, another app is here.
+              return;
+            }
+            if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash");
+            try {
+                mBluetoothLock.readLock().lock();
+                if (mBluetooth != null &&
+                    mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
+                    mEnable = false;
+                    mBluetooth.onBrEdrDown();
                 }
+            } catch (RemoteException e) {
+                 Slog.e(TAG,"Unable to call onBrEdrDown", e);
+            } finally {
+                mBluetoothLock.readLock().unlock();
             }
         }
     }
 
     /** Internal death rec list */
-    Map<IBinder, ClientDeathRecipient> mBleApps = new HashMap<IBinder, ClientDeathRecipient>();
+    Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
 
     @Override
     public boolean isBleScanAlwaysAvailable() {
@@ -479,17 +476,20 @@
         ContentObserver contentObserver = new ContentObserver(null) {
             @Override
             public void onChange(boolean selfChange) {
-                if (!isBleScanAlwaysAvailable()) {
-                    disableBleScanMode();
-                    clearBleApps();
-                    try {
-                        mBluetoothLock.readLock().lock();
-                        if (mBluetooth != null) mBluetooth.onBrEdrDown();
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error when disabling bluetooth", e);
-                    } finally {
-                        mBluetoothLock.readLock().unlock();
-                    }
+                if (isBleScanAlwaysAvailable()) {
+                  // Nothing to do
+                  return;
+                }
+                // BLE scan is not available.
+                disableBleScanMode();
+                clearBleApps();
+                try {
+                    mBluetoothLock.readLock().lock();
+                    if (mBluetooth != null) mBluetooth.onBrEdrDown();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error when disabling bluetooth", e);
+                } finally {
+                    mBluetoothLock.readLock().unlock();
                 }
             }
         };
@@ -525,9 +525,6 @@
                     throw new IllegalArgumentException("Wake lock is already dead.");
                 }
                 mBleApps.put(token, deathRec);
-                synchronized (this) {
-                    ++mBleAppCount;
-                }
                 if (DBG) Slog.d(TAG, "Registered for death Notification");
             }
 
@@ -537,31 +534,26 @@
                 // Unregister death recipient as the app goes away.
                 token.unlinkToDeath(r, 0);
                 mBleApps.remove(token);
-                synchronized (this) {
-                    if (mBleAppCount > 0) --mBleAppCount;
-                }
                 if (DBG) Slog.d(TAG, "Unregistered for death Notification");
             }
         }
-        if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount);
-        if (mBleAppCount == 0 && mEnable) {
+        int appCount = mBleApps.size();
+        if (DBG) Slog.d(TAG, appCount + " registered Ble Apps");
+        if (appCount == 0 && mEnable) {
             disableBleScanMode();
         }
-        return mBleAppCount;
+        return appCount;
     }
 
     // Clear all apps using BLE scan only mode.
     private void clearBleApps() {
-        synchronized (this) {
-            mBleApps.clear();
-            mBleAppCount = 0;
-        }
+        mBleApps.clear();
     }
 
     /** @hide*/
     public boolean isBleAppPresent() {
-        if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount);
-        return (mBleAppCount > 0);
+        if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
+        return mBleApps.size() > 0;
     }
 
     /**
@@ -1417,12 +1409,12 @@
                     if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) &&
                             (newState == BluetoothAdapter.STATE_OFF) &&
                             (mBluetooth != null) && mEnable) {
-                        recoverBluetoothServiceFromError();
+                        recoverBluetoothServiceFromError(false);
                     }
                     if ((prevState == BluetoothAdapter.STATE_TURNING_ON) &&
                             (newState == BluetoothAdapter.STATE_BLE_ON) &&
                             (mBluetooth != null) && mEnable) {
-                        recoverBluetoothServiceFromError();
+                        recoverBluetoothServiceFromError(true);
                     }
                     // If we tried to enable BT while BT was in the process of shutting down,
                     // wait for the BT process to fully tear down and then force a restart
@@ -1837,7 +1829,7 @@
                              quietMode ? 1 : 0, 0));
     }
 
-    private void recoverBluetoothServiceFromError() {
+    private void recoverBluetoothServiceFromError(boolean clearBle) {
         Slog.e(TAG,"recoverBluetoothServiceFromError");
         try {
             mBluetoothLock.readLock().lock();
@@ -1875,6 +1867,10 @@
         mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
         mState = BluetoothAdapter.STATE_OFF;
 
+        if (clearBle) {
+          clearBleApps();
+        }
+
         mEnable = false;
 
         if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) {
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index dbc2b0c..615ae49 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -114,7 +114,10 @@
     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
 
     /**
-     * Flag indicating that this {@code PhoneAccount} is capable of placing video calls.
+     * Flag indicating that this {@code PhoneAccount} is currently able to place video calls.
+     * <p>
+     * See also {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING} which indicates whether the
+     * {@code PhoneAccount} supports placing video calls.
      * <p>
      * See {@link #getCapabilities}
      */
@@ -179,6 +182,23 @@
     public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
 
     /**
+     * Flag indicating that this {@link PhoneAccount} supports video calling.
+     * This is not an indication that the {@link PhoneAccount} is currently able to make a video
+     * call, but rather that it has the ability to make video calls (but not necessarily at this
+     * time).
+     * <p>
+     * Whether a {@link PhoneAccount} can make a video call is ultimately controlled by
+     * {@link #CAPABILITY_VIDEO_CALLING}, which indicates whether the {@link PhoneAccount} is
+     * currently capable of making a video call.  Consider a case where, for example, a
+     * {@link PhoneAccount} supports making video calls (e.g.
+     * {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}), but a current lack of network connectivity
+     * prevents video calls from being made (e.g. {@link #CAPABILITY_VIDEO_CALLING}).
+     * <p>
+     * See {@link #getCapabilities}
+     */
+    public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 0x400;
+
+    /**
      * URI scheme for telephone number URIs.
      */
     public static final String SCHEME_TEL = "tel";
@@ -716,6 +736,9 @@
      */
     private String capabilitiesToString(int capabilities) {
         StringBuilder sb = new StringBuilder();
+        if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) {
+            sb.append("SuppVideo ");
+        }
         if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) {
             sb.append("Video ");
         }
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 3c0a8d6..434caad 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -168,20 +168,34 @@
     }
 
     /**
-     * @hide
+     * Get reference signal received quality
      */
     public int getRsrq() {
         return mRsrq;
     }
 
     /**
-     * @hide
+     * Get reference signal signal-to-noise ratio
      */
     public int getRssnr() {
         return mRssnr;
     }
 
     /**
+     * Get reference signal received power
+     */
+    public int getRsrp() {
+        return mRsrp;
+    }
+
+    /**
+     * Get channel quality indicator
+     */
+    public int getCqi() {
+        return mCqi;
+    }
+
+    /**
      * Get signal strength as dBm
      */
     @Override
diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
index ee2e895..8b1cfae 100644
--- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
+++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
@@ -28,5 +28,6 @@
     Messenger getMessenger();
     Messenger getP2pStateMachineMessenger();
     void setMiracastMode(int mode);
+    void checkConfigureWifiDisplayPermission();
 }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 398308d..c93ac7b 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1324,6 +1324,11 @@
             Channel c, WifiP2pWfdInfo wfdInfo,
             ActionListener listener) {
         checkChannel(c);
+        try {
+            mService.checkConfigureWifiDisplayPermission();
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
         c.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, c.putListener(listener), wfdInfo);
     }