Merge "Fix NPE in platform restore"
diff --git a/api/current.txt b/api/current.txt
index 95f6461..4b082f3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -134,7 +134,6 @@
     field public static final java.lang.String SET_WALLPAPER = "android.permission.SET_WALLPAPER";
     field public static final java.lang.String SET_WALLPAPER_HINTS = "android.permission.SET_WALLPAPER_HINTS";
     field public static final java.lang.String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
-    field public static final java.lang.String SIM_COMMUNICATION = "android.permission.SIM_COMMUNICATION";
     field public static final java.lang.String STATUS_BAR = "android.permission.STATUS_BAR";
     field public static final java.lang.String SUBSCRIBED_FEEDS_READ = "android.permission.SUBSCRIBED_FEEDS_READ";
     field public static final java.lang.String SUBSCRIBED_FEEDS_WRITE = "android.permission.SUBSCRIBED_FEEDS_WRITE";
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 2d7af85..7a4e5a5 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -16,8 +16,6 @@
 
 package android.hardware.soundtrigger;
 
-import android.content.Context;
-import android.content.Intent;
 import android.os.Handler;
 
 import java.util.ArrayList;
@@ -65,7 +63,7 @@
         public final int maxSoundModels;
 
         /** Maximum number of key phrases */
-        public final int maxKeyPhrases;
+        public final int maxKeyphrases;
 
         /** Maximum number of users per key phrase */
         public final int maxUsers;
@@ -86,7 +84,7 @@
         public final int powerConsumptionMw;
 
         ModuleProperties(int id, String implementor, String description,
-                String uuid, int version, int maxSoundModels, int maxKeyPhrases,
+                String uuid, int version, int maxSoundModels, int maxKeyphrases,
                 int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
                 int maxBufferMs, boolean supportsConcurrentCapture,
                 int powerConsumptionMw) {
@@ -96,7 +94,7 @@
             this.uuid = UUID.fromString(uuid);
             this.version = version;
             this.maxSoundModels = maxSoundModels;
-            this.maxKeyPhrases = maxKeyPhrases;
+            this.maxKeyphrases = maxKeyphrases;
             this.maxUsers = maxUsers;
             this.recognitionModes = recognitionModes;
             this.supportsCaptureTransition = supportsCaptureTransition;
@@ -109,7 +107,7 @@
     /*****************************************************************************
      * A SoundModel describes the attributes and contains the binary data used by the hardware
      * implementation to detect a particular sound pattern.
-     * A specialized version {@link KeyPhraseSoundModel} is defined for key phrase
+     * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
      * sound models.
      ****************************************************************************/
     public static class SoundModel {
@@ -119,23 +117,30 @@
         /** Keyphrase sound model */
         public static final int TYPE_KEYPHRASE = 0;
 
+        /** Unique sound model identifier */
+        public final UUID uuid;
+
         /** Sound model type (e.g. TYPE_KEYPHRASE); */
         public final int type;
 
         /** Opaque data. For use by vendor implementation and enrollment application */
         public final byte[] data;
 
-        public SoundModel(int type, byte[] data) {
+        public SoundModel(UUID uuid, int type, byte[] data) {
+            this.uuid = uuid;
             this.type = type;
             this.data = data;
         }
     }
 
     /*****************************************************************************
-     * A KeyPhrase describes a key phrase that can be detected by a
-     * {@link KeyPhraseSoundModel}
+     * A Keyphrase describes a key phrase that can be detected by a
+     * {@link KeyphraseSoundModel}
      ****************************************************************************/
-    public static class KeyPhrase {
+    public static class Keyphrase {
+        /** Unique identifier for this keyphrase */
+        public final int id;
+
         /** Recognition modes supported for this key phrase in the model */
         public final int recognitionModes;
 
@@ -145,29 +150,31 @@
         /** Key phrase text */
         public final String text;
 
-        /** Number of users this key phrase has been trained for */
-        public final int numUsers;
+        /** Users this key phrase has been trained for. countains sound trigger specific user IDs
+         * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
+        public final int[] users;
 
-        public KeyPhrase(int recognitionModes, String locale, String text, int numUsers) {
+        public Keyphrase(int id, int recognitionModes, String locale, String text, int[] users) {
+            this.id = id;
             this.recognitionModes = recognitionModes;
             this.locale = locale;
             this.text = text;
-            this.numUsers = numUsers;
+            this.users = users;
         }
     }
 
     /*****************************************************************************
-     * A KeyPhraseSoundModel is a specialized {@link SoundModel} for key phrases.
+     * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
      * It contains data needed by the hardware to detect a certain number of key phrases
-     * and the list of corresponding {@link KeyPhrase} descriptors.
+     * and the list of corresponding {@link Keyphrase} descriptors.
      ****************************************************************************/
-    public static class KeyPhraseSoundModel extends SoundModel {
+    public static class KeyphraseSoundModel extends SoundModel {
         /** Key phrases in this sound model */
-        public final KeyPhrase[] keyPhrases; // keyword phrases in model
+        public final Keyphrase[] keyphrases; // keyword phrases in model
 
-        public KeyPhraseSoundModel(byte[] data, KeyPhrase[] keyPhrases) {
-            super(TYPE_KEYPHRASE, data);
-            this.keyPhrases = keyPhrases;
+        public KeyphraseSoundModel(UUID id, byte[] data, Keyphrase[] keyphrases) {
+            super(id, TYPE_KEYPHRASE, data);
+            this.keyphrases = keyphrases;
         }
     }
 
@@ -209,55 +216,106 @@
         /** Delay in ms between end of model detection and start of audio available for capture.
          * A negative value is possible (e.g. if keyphrase is also available for capture) */
         public final int captureDelayMs;
+        /** Duration in ms of audio captured before the start of the trigger. 0 if none. */
+        public final int capturePreambleMs;
         /** Opaque data for use by system applications who know about voice engine internals,
          * typically during enrollment. */
         public final byte[] data;
 
         RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
-                int captureSession, int captureDelayMs, byte[] data) {
+                int captureSession, int captureDelayMs, int capturePreambleMs, byte[] data) {
             this.status = status;
             this.soundModelHandle = soundModelHandle;
             this.captureAvailable = captureAvailable;
             this.captureSession = captureSession;
             this.captureDelayMs = captureDelayMs;
+            this.capturePreambleMs = capturePreambleMs;
             this.data = data;
         }
     }
 
     /**
-     *  Additional data conveyed by a {@link KeyPhraseRecognitionEvent}
+     *  A RecognitionConfig is provided to
+     *  {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the
+     *  recognition request.
+     */
+    public static class RecognitionConfig {
+        /** True if the DSP should capture the trigger sound and make it available for further
+         * capture. */
+        public final boolean captureRequested;
+        /** List of all keyphrases in the sound model for which recognition should be performed with
+         * options for each keyphrase. */
+        public final KeyphraseRecognitionExtra keyphrases[];
+        /** Opaque data for use by system applications who know about voice engine internals,
+         * typically during enrollment. */
+        public final byte[] data;
+
+        public RecognitionConfig(boolean captureRequested,
+                KeyphraseRecognitionExtra keyphrases[], byte[] data) {
+            this.captureRequested = captureRequested;
+            this.keyphrases = keyphrases;
+            this.data = data;
+        }
+    }
+
+    /**
+     * Confidence level for users defined in a keyphrase.
+     * - The confidence level is expressed in percent (0% -100%).
+     * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
+     * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
+     * should trigger a recognition.
+     * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
+     */
+    public static class ConfidenceLevel {
+        public final int userId;
+        public final int confidenceLevel;
+
+        public ConfidenceLevel(int userId, int confidenceLevel) {
+            this.userId = userId;
+            this.confidenceLevel = confidenceLevel;
+        }
+    }
+
+    /**
+     *  Additional data conveyed by a {@link KeyphraseRecognitionEvent}
      *  for a key phrase detection.
      */
-    public static class KeyPhraseRecognitionExtra {
-        /** Confidence level for each user defined in the key phrase in the same order as
-         * users in the key phrase. The confidence level is expressed in percentage (0% -100%) */
-        public final int[] confidenceLevels;
+    public static class KeyphraseRecognitionExtra {
+        /** The keyphrse ID */
+        public final int id;
 
         /** Recognition modes matched for this event */
         public final int recognitionModes;
 
-        KeyPhraseRecognitionExtra(int[] confidenceLevels, int recognitionModes) {
-            this.confidenceLevels = confidenceLevels;
+        /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
+         * be recognized (RecognitionConfig) */
+        public final ConfidenceLevel[] confidenceLevels;
+
+        public KeyphraseRecognitionExtra(int id, int recognitionModes,
+                                  ConfidenceLevel[] confidenceLevels) {
+            this.id = id;
             this.recognitionModes = recognitionModes;
+            this.confidenceLevels = confidenceLevels;
         }
     }
 
     /**
      *  Specialized {@link RecognitionEvent} for a key phrase detection.
      */
-    public static class KeyPhraseRecognitionEvent extends RecognitionEvent {
+    public static class KeyphraseRecognitionEvent extends RecognitionEvent {
         /** Indicates if the key phrase is present in the buffered audio available for capture */
-        public final KeyPhraseRecognitionExtra[] keyPhraseExtras;
+        public final KeyphraseRecognitionExtra[] keyphraseExtras;
 
         /** Additional data available for each recognized key phrases in the model */
-        public final boolean keyPhraseInCapture;
+        public final boolean keyphraseInCapture;
 
-        KeyPhraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
-               int captureSession, int captureDelayMs, byte[] data,
-               boolean keyPhraseInCapture, KeyPhraseRecognitionExtra[] keyPhraseExtras) {
-            super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs, data);
-            this.keyPhraseInCapture = keyPhraseInCapture;
-            this.keyPhraseExtras = keyPhraseExtras;
+        KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
+               int captureSession, int captureDelayMs, int capturePreambleMs, byte[] data,
+               boolean keyphraseInCapture, KeyphraseRecognitionExtra[] keyphraseExtras) {
+            super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
+                  capturePreambleMs, data);
+            this.keyphraseInCapture = keyphraseInCapture;
+            this.keyphraseExtras = keyphraseExtras;
         }
     }
 
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index 776f85d..4a54fd8 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -94,7 +94,8 @@
      * Recognition must be restarted after each callback (success or failure) received on
      * the {@link SoundTrigger.StatusListener}.
      * @param soundModelHandle The sound model handle to start listening to
-     * @param data Opaque data for use by the implementation for this recognition
+     * @param config contains configuration information for this recognition request:
+     *  recognition mode, keyphrases, users, minimum confidence levels...
      * @return - {@link SoundTrigger#STATUS_OK} in case of success
      *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
      *         - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have
@@ -105,7 +106,7 @@
      *         service fails
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
-    public native int startRecognition(int soundModelHandle, byte[] data);
+    public native int startRecognition(int soundModelHandle, SoundTrigger.RecognitionConfig config);
 
     /**
      * Stop listening to all key phrases in a {@link SoundTrigger.SoundModel}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 5bd6f52..916586c 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -689,7 +689,7 @@
         try {
             getLockSettings().setLockPassword(password, userHandle);
             DevicePolicyManager dpm = getDevicePolicyManager();
-            if (password != null) {
+            if (!TextUtils.isEmpty(password)) {
                 int computedQuality = computePasswordQuality(password);
 
                 if (userHandle == UserHandle.USER_OWNER) {
@@ -764,9 +764,10 @@
                 }
                 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
             } else {
+                // Empty password
                 if (userHandle == UserHandle.USER_OWNER) {
-                    // Update the encryption password.
-                    updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, password);
+                    // Set the encryption password to default.
+                    updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
                 }
 
                 dpm.setActivePasswordState(
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index f7886d3..53aca3d 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -316,7 +316,7 @@
 static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                               jint offset, jint stride, jint width, jint height,
                               jint configHandle, jboolean isMutable) {
-    SkColorType colorType = SkBitmapConfigToColorType(static_cast<SkBitmap::Config>(configHandle));
+    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
     if (NULL != jColors) {
         size_t n = env->GetArrayLength(jColors);
         if (n < SkAbs32(stride) * (size_t)height) {
@@ -350,11 +350,11 @@
 static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
                            jint dstConfigHandle, jboolean isMutable) {
     const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
-    SkBitmap::Config dstConfig = static_cast<SkBitmap::Config>(dstConfigHandle);
+    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
     SkBitmap            result;
     JavaPixelAllocator  allocator(env);
 
-    if (!src->copyTo(&result, SkBitmapConfigToColorType(dstConfig), &allocator)) {
+    if (!src->copyTo(&result, dstCT, &allocator)) {
         return NULL;
     }
     return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),
@@ -389,8 +389,7 @@
         jint width, jint height, jint configHandle, jint allocSize,
         jboolean requestPremul) {
     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-    SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
-    SkColorType colorType = SkBitmapConfigToColorType(config);
+    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
 
     // ARGB_4444 is a deprecated format, convert automatically to 8888
     if (colorType == kARGB_4444_SkColorType) {
@@ -494,7 +493,7 @@
 
 static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-    return static_cast<jint>(bitmap->config());
+    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->colorType());
 }
 
 static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
@@ -810,7 +809,7 @@
     const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle);
     if (bm0->width() != bm1->width() ||
         bm0->height() != bm1->height() ||
-        bm0->config() != bm1->config()) {
+        bm0->colorType() != bm1->colorType()) {
         return JNI_FALSE;
     }
 
@@ -822,7 +821,7 @@
         return JNI_FALSE;
     }
 
-    if (bm0->config() == SkBitmap::kIndex8_Config) {
+    if (bm0->colorType() == kIndex_8_SkColorType) {
         SkColorTable* ct0 = bm0->getColorTable();
         SkColorTable* ct1 = bm1->getColorTable();
         if (NULL == ct0 || NULL == ct1) {
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 7a186a2..9177696 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -291,6 +291,54 @@
     env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY));
 }
 
+// This enum must keep these int values, to match the int values
+// in the java Bitmap.Config enum.
+enum LegacyBitmapConfig {
+    kNo_LegacyBitmapConfig          = 0,
+    kA8_LegacyBitmapConfig          = 1,
+    kIndex8_LegacyBitmapConfig      = 2,
+    kRGB_565_LegacyBitmapConfig     = 3,
+    kARGB_4444_LegacyBitmapConfig   = 4,
+    kARGB_8888_LegacyBitmapConfig   = 5,
+
+    kLastEnum_LegacyBitmapConfig = kARGB_8888_LegacyBitmapConfig
+};
+
+jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
+    switch (colorType) {
+        case kN32_SkColorType:
+            return kARGB_8888_LegacyBitmapConfig;
+        case kARGB_4444_SkColorType:
+            return kARGB_4444_LegacyBitmapConfig;
+        case kRGB_565_SkColorType:
+            return kRGB_565_LegacyBitmapConfig;
+        case kIndex_8_SkColorType:
+            return kIndex8_LegacyBitmapConfig;
+        case kAlpha_8_SkColorType:
+            return kA8_LegacyBitmapConfig;
+        case kUnknown_SkColorType:
+        default:
+            break;
+    }
+    return kNo_LegacyBitmapConfig;
+}
+
+SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
+    const uint8_t gConfig2ColorType[] = {
+        kUnknown_SkColorType,
+        kAlpha_8_SkColorType,
+        kIndex_8_SkColorType,
+        kRGB_565_SkColorType,
+        kARGB_4444_SkColorType,
+        kN32_SkColorType
+    };
+
+    if (legacyConfig < 0 || legacyConfig > kLastEnum_LegacyBitmapConfig) {
+        legacyConfig = kNo_LegacyBitmapConfig;
+    }
+    return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
+}
+
 SkBitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
     SkASSERT(env);
     SkASSERT(bitmap);
@@ -308,10 +356,7 @@
     }
     SkASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class));
     int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID);
-    if (c < 0 || c >= SkBitmap::kConfigCount) {
-        c = kUnknown_SkColorType;
-    }
-    return SkBitmapConfigToColorType(static_cast<SkBitmap::Config>(c));
+    return legacyBitmapConfigToColorType(c);
 }
 
 SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 6d82ceb..a03391d 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -58,6 +58,14 @@
     // ref to its SkRasterizer* (or NULL).
     static SkRasterizer* refNativeRasterizer(jlong rasterizerHandle);
 
+    /*
+     *  LegacyBitmapConfig is the old enum in Skia that matched the enum int values
+     *  in Bitmap.Config. Skia no longer supports this config, but has replaced it
+     *  with SkColorType. These routines convert between the two.
+     */
+    static SkColorType legacyBitmapConfigToColorType(jint legacyConfig);
+    static jint colorTypeToLegacyBitmapConfig(SkColorType colorType);
+
     /** Return the corresponding native colorType from the java Config enum,
         or kUnknown_SkColorType if the java object is null.
     */
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/core/jni/android/graphics/NinePatchImpl.cpp
index 1793208..c162c48 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/core/jni/android/graphics/NinePatchImpl.cpp
@@ -38,18 +38,18 @@
 #include <utils/Log.h>
 
 static bool getColor(const SkBitmap& bitmap, int x, int y, SkColor* c) {
-    switch (bitmap.config()) {
-        case SkBitmap::kARGB_8888_Config:
+    switch (bitmap.colorType()) {
+        case kN32_SkColorType:
             *c = SkUnPreMultiply::PMColorToColor(*bitmap.getAddr32(x, y));
             break;
-        case SkBitmap::kRGB_565_Config:
+        case kRGB_565_SkColorType:
             *c = SkPixel16ToPixel32(*bitmap.getAddr16(x, y));
             break;
-        case SkBitmap::kARGB_4444_Config:
+        case kARGB_4444_SkColorType:
             *c = SkUnPreMultiply::PMColorToColor(
                                 SkPixel4444ToPixel32(*bitmap.getAddr16(x, y)));
             break;
-        case SkBitmap::kIndex8_Config: {
+        case kIndex_8_SkColorType: {
             SkColorTable* ctable = bitmap.getColorTable();
             *c = SkUnPreMultiply::PMColorToColor(
                                             (*ctable)[*bitmap.getAddr8(x, y)]);
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index a91c622..89baef8 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -562,18 +562,18 @@
     setGLDebugLevel(level);
 }
 
-static int checkFormat(SkBitmap::Config config, int format, int type)
+static int checkFormat(SkColorType colorType, int format, int type)
 {
-    switch(config) {
-        case SkBitmap::kIndex8_Config:
+    switch(colorType) {
+        case kIndex_8_SkColorType:
             if (format == GL_PALETTE8_RGBA8_OES)
                 return 0;
-        case SkBitmap::kARGB_8888_Config:
-        case SkBitmap::kA8_Config:
+        case kN32_SkColorType:
+        case kAlpha_8_SkColorType:
             if (type == GL_UNSIGNED_BYTE)
                 return 0;
-        case SkBitmap::kARGB_4444_Config:
-        case SkBitmap::kRGB_565_Config:
+        case kARGB_4444_SkColorType:
+        case kRGB_565_SkColorType:
             switch (type) {
                 case GL_UNSIGNED_SHORT_4_4_4_4:
                 case GL_UNSIGNED_SHORT_5_6_5:
@@ -590,36 +590,36 @@
     return -1;
 }
 
-static int getInternalFormat(SkBitmap::Config config)
+static int getInternalFormat(SkColorType colorType)
 {
-    switch(config) {
-        case SkBitmap::kA8_Config:
+    switch(colorType) {
+        case kAlpha_8_SkColorType:
             return GL_ALPHA;
-        case SkBitmap::kARGB_4444_Config:
+        case kARGB_4444_SkColorType:
             return GL_RGBA;
-        case SkBitmap::kARGB_8888_Config:
+        case kN32_SkColorType:
             return GL_RGBA;
-        case SkBitmap::kIndex8_Config:
+        case kIndex_8_SkColorType:
             return GL_PALETTE8_RGBA8_OES;
-        case SkBitmap::kRGB_565_Config:
+        case kRGB_565_SkColorType:
             return GL_RGB;
         default:
             return -1;
     }
 }
 
-static int getType(SkBitmap::Config config)
+static int getType(SkColorType colorType)
 {
-    switch(config) {
-        case SkBitmap::kA8_Config:
+    switch(colorType) {
+        case kAlpha_8_SkColorType:
             return GL_UNSIGNED_BYTE;
-        case SkBitmap::kARGB_4444_Config:
+        case kARGB_4444_SkColorType:
             return GL_UNSIGNED_SHORT_4_4_4_4;
-        case SkBitmap::kARGB_8888_Config:
+        case kN32_SkColorType:
             return GL_UNSIGNED_BYTE;
-        case SkBitmap::kIndex8_Config:
+        case kIndex_8_SkColorType:
             return -1; // No type for compressed data.
-        case SkBitmap::kRGB_565_Config:
+        case kRGB_565_SkColorType:
             return GL_UNSIGNED_SHORT_5_6_5;
         default:
             return -1;
@@ -631,9 +631,7 @@
 {
     SkBitmap const * nativeBitmap =
             (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
-    const SkBitmap& bitmap(*nativeBitmap);
-    SkBitmap::Config config = bitmap.config();
-    return getInternalFormat(config);
+    return getInternalFormat(nativeBitmap->colorType());
 }
 
 static jint util_getType(JNIEnv *env, jclass clazz,
@@ -641,9 +639,7 @@
 {
     SkBitmap const * nativeBitmap =
             (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
-    const SkBitmap& bitmap(*nativeBitmap);
-    SkBitmap::Config config = bitmap.config();
-    return getType(config);
+    return getType(nativeBitmap->colorType());
 }
 
 static jint util_texImage2D(JNIEnv *env, jclass clazz,
@@ -653,14 +649,14 @@
     SkBitmap const * nativeBitmap =
             (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
     const SkBitmap& bitmap(*nativeBitmap);
-    SkBitmap::Config config = bitmap.config();
+    SkColorType colorType = bitmap.colorType();
     if (internalformat < 0) {
-        internalformat = getInternalFormat(config);
+        internalformat = getInternalFormat(colorType);
     }
     if (type < 0) {
-        type = getType(config);
+        type = getType(colorType);
     }
-    int err = checkFormat(config, internalformat, type);
+    int err = checkFormat(colorType, internalformat, type);
     if (err)
         return err;
     bitmap.lockPixels();
@@ -702,13 +698,13 @@
     SkBitmap const * nativeBitmap =
             (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
     const SkBitmap& bitmap(*nativeBitmap);
-    SkBitmap::Config config = bitmap.config();
+    SkColorType colorType = bitmap.colorType();
     if (format < 0) {
-        format = getInternalFormat(config);
+        format = getInternalFormat(colorType);
         if (format == GL_PALETTE8_RGBA8_OES)
             return -1; // glCompressedTexSubImage2D() not supported
     }
-    int err = checkFormat(config, format, type);
+    int err = checkFormat(colorType, format, type);
     if (err)
         return err;
     bitmap.lockPixels();
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 69e991d..c9a0b1e 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -37,6 +37,11 @@
     jmethodID    add;
 } gArrayListMethods;
 
+static jclass gUUIDClass;
+static struct {
+    jmethodID    toString;
+} gUUIDMethods;
+
 static const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger";
 static jclass gSoundTriggerClass;
 
@@ -57,41 +62,65 @@
                                      "android/hardware/soundtrigger/SoundTrigger$SoundModel";
 static jclass gSoundModelClass;
 static struct {
+    jfieldID    uuid;
     jfieldID    data;
 } gSoundModelFields;
 
-static const char* const kKeyPhraseClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$KeyPhrase";
-static jclass gKeyPhraseClass;
+static const char* const kKeyphraseClassPathName =
+                                     "android/hardware/soundtrigger/SoundTrigger$Keyphrase";
+static jclass gKeyphraseClass;
 static struct {
+    jfieldID id;
     jfieldID recognitionModes;
     jfieldID locale;
     jfieldID text;
-    jfieldID numUsers;
-} gKeyPhraseFields;
+    jfieldID users;
+} gKeyphraseFields;
 
-static const char* const kKeyPhraseSoundModelClassPathName =
-                                 "android/hardware/soundtrigger/SoundTrigger$KeyPhraseSoundModel";
-static jclass gKeyPhraseSoundModelClass;
+static const char* const kKeyphraseSoundModelClassPathName =
+                                 "android/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel";
+static jclass gKeyphraseSoundModelClass;
 static struct {
-    jfieldID    keyPhrases;
-} gKeyPhraseSoundModelFields;
+    jfieldID    keyphrases;
+} gKeyphraseSoundModelFields;
 
+static const char* const kRecognitionConfigClassPathName =
+                                     "android/hardware/soundtrigger/SoundTrigger$RecognitionConfig";
+static jclass gRecognitionConfigClass;
+static struct {
+    jfieldID captureRequested;
+    jfieldID keyphrases;
+    jfieldID data;
+} gRecognitionConfigFields;
 
 static const char* const kRecognitionEventClassPathName =
                                      "android/hardware/soundtrigger/SoundTrigger$RecognitionEvent";
 static jclass gRecognitionEventClass;
 static jmethodID   gRecognitionEventCstor;
 
-static const char* const kKeyPhraseRecognitionEventClassPathName =
-                             "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionEvent";
-static jclass gKeyPhraseRecognitionEventClass;
-static jmethodID   gKeyPhraseRecognitionEventCstor;
+static const char* const kKeyphraseRecognitionEventClassPathName =
+                             "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent";
+static jclass gKeyphraseRecognitionEventClass;
+static jmethodID   gKeyphraseRecognitionEventCstor;
 
-static const char* const kKeyPhraseRecognitionExtraClassPathName =
-                             "android/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra";
-static jclass gKeyPhraseRecognitionExtraClass;
-static jmethodID   gKeyPhraseRecognitionExtraCstor;
+static const char* const kKeyphraseRecognitionExtraClassPathName =
+                             "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra";
+static jclass gKeyphraseRecognitionExtraClass;
+static jmethodID   gKeyphraseRecognitionExtraCstor;
+static struct {
+    jfieldID id;
+    jfieldID recognitionModes;
+    jfieldID confidenceLevels;
+} gKeyphraseRecognitionExtraFields;
+
+static const char* const kConfidenceLevelClassPathName =
+                             "android/hardware/soundtrigger/SoundTrigger$ConfidenceLevel";
+static jclass gConfidenceLevelClass;
+static jmethodID   gConfidenceLevelCstor;
+static struct {
+    jfieldID userId;
+    jfieldID confidenceLevel;
+} gConfidenceLevelFields;
 
 static Mutex gLock;
 
@@ -170,40 +199,51 @@
                 (struct sound_trigger_phrase_recognition_event *)event;
 
         jobjectArray jExtras = env->NewObjectArray(phraseEvent->num_phrases,
-                                                  gKeyPhraseRecognitionExtraClass, NULL);
+                                                  gKeyphraseRecognitionExtraClass, NULL);
         if (jExtras == NULL) {
             return;
         }
 
         for (size_t i = 0; i < phraseEvent->num_phrases; i++) {
-            jintArray jConfidenceLevels = env->NewIntArray(phraseEvent->phrase_extras[i].num_users);
+            jobjectArray jConfidenceLevels = env->NewObjectArray(
+                                                        phraseEvent->phrase_extras[i].num_levels,
+                                                        gConfidenceLevelClass, NULL);
+
             if (jConfidenceLevels == NULL) {
                 return;
             }
-            jint *nConfidenceLevels = env->GetIntArrayElements(jConfidenceLevels, NULL);
-            memcpy(nConfidenceLevels,
-                   phraseEvent->phrase_extras[i].confidence_levels,
-                   phraseEvent->phrase_extras[i].num_users * sizeof(int));
-            env->ReleaseIntArrayElements(jConfidenceLevels, nConfidenceLevels, 0);
-            jobject jNewExtra = env->NewObject(gKeyPhraseRecognitionExtraClass,
-                                               gKeyPhraseRecognitionExtraCstor,
-                                               jConfidenceLevels,
-                                               phraseEvent->phrase_extras[i].recognition_modes);
+            for (size_t j = 0; j < phraseEvent->phrase_extras[i].num_levels; j++) {
+                jobject jConfidenceLevel = env->NewObject(gConfidenceLevelClass,
+                                                  gConfidenceLevelCstor,
+                                                  phraseEvent->phrase_extras[i].levels[j].user_id,
+                                                  phraseEvent->phrase_extras[i].levels[j].level);
+                env->SetObjectArrayElement(jConfidenceLevels, j, jConfidenceLevel);
+                env->DeleteLocalRef(jConfidenceLevel);
+            }
+
+            jobject jNewExtra = env->NewObject(gKeyphraseRecognitionExtraClass,
+                                               gKeyphraseRecognitionExtraCstor,
+                                               phraseEvent->phrase_extras[i].id,
+                                               phraseEvent->phrase_extras[i].recognition_modes,
+                                               jConfidenceLevels);
 
             if (jNewExtra == NULL) {
                 return;
             }
             env->SetObjectArrayElement(jExtras, i, jNewExtra);
-
+            env->DeleteLocalRef(jNewExtra);
+            env->DeleteLocalRef(jConfidenceLevels);
         }
-        jEvent = env->NewObject(gKeyPhraseRecognitionEventClass, gKeyPhraseRecognitionEventCstor,
+        jEvent = env->NewObject(gKeyphraseRecognitionEventClass, gKeyphraseRecognitionEventCstor,
                                 event->status, event->model, event->capture_available,
-                               event->capture_session, event->capture_delay_ms, jData,
+                               event->capture_session, event->capture_delay_ms,
+                               event->capture_preamble_ms, jData,
                                phraseEvent->key_phrase_in_capture, jExtras);
     } else {
         jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
                                 event->status, event->model, event->capture_available,
-                                event->capture_session, event->capture_delay_ms, jData);
+                                event->capture_session, event->capture_delay_ms,
+                                event->capture_preamble_ms, jData);
     }
 
 
@@ -374,13 +414,16 @@
                                              jobject jSoundModel, jintArray jHandle)
 {
     jint status = SOUNDTRIGGER_STATUS_OK;
-    char *nData = NULL;
+    jbyte *nData = NULL;
     struct sound_trigger_sound_model *nSoundModel;
     jbyteArray jData;
     sp<MemoryDealer> memoryDealer;
     sp<IMemory> memory;
     size_t size;
     sound_model_handle_t handle;
+    jobject jUuid;
+    jstring jUuidString;
+    const char *nUuidString;
 
     ALOGV("loadSoundModel");
     sp<SoundTrigger> module = getSoundTrigger(env, thiz);
@@ -404,13 +447,22 @@
     }
     size_t offset;
     sound_trigger_sound_model_type_t type;
-    if (env->IsInstanceOf(jSoundModel, gKeyPhraseSoundModelClass)) {
+    if (env->IsInstanceOf(jSoundModel, gKeyphraseSoundModelClass)) {
         offset = sizeof(struct sound_trigger_phrase_sound_model);
         type = SOUND_MODEL_TYPE_KEYPHRASE;
     } else {
         offset = sizeof(struct sound_trigger_sound_model);
         type = SOUND_MODEL_TYPE_UNKNOWN;
     }
+
+    jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.uuid);
+    jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString);
+    nUuidString = env->GetStringUTFChars(jUuidString, NULL);
+    sound_trigger_uuid_t nUuid;
+    SoundTrigger::stringToGuid(nUuidString, &nUuid);
+    env->ReleaseStringUTFChars(jUuidString, nUuidString);
+    env->DeleteLocalRef(jUuidString);
+
     jData = (jbyteArray)env->GetObjectField(jSoundModel, gSoundModelFields.data);
     if (jData == NULL) {
         status = SOUNDTRIGGER_STATUS_BAD_VALUE;
@@ -418,7 +470,7 @@
     }
     size = env->GetArrayLength(jData);
 
-    nData = (char *)env->GetByteArrayElements(jData, NULL);
+    nData = env->GetByteArrayElements(jData, NULL);
     if (jData == NULL) {
         status = SOUNDTRIGGER_STATUS_ERROR;
         goto exit;
@@ -438,6 +490,7 @@
     nSoundModel = (struct sound_trigger_sound_model *)memory->pointer();
 
     nSoundModel->type = type;
+    nSoundModel->uuid = nUuid;
     nSoundModel->data_size = size;
     nSoundModel->data_offset = offset;
     memcpy((char *)nSoundModel + offset, nData, size);
@@ -446,7 +499,7 @@
                 (struct sound_trigger_phrase_sound_model *)nSoundModel;
 
         jobjectArray jPhrases =
-            (jobjectArray)env->GetObjectField(jSoundModel, gKeyPhraseSoundModelFields.keyPhrases);
+            (jobjectArray)env->GetObjectField(jSoundModel, gKeyphraseSoundModelFields.keyphrases);
         if (jPhrases == NULL) {
             status = SOUNDTRIGGER_STATUS_BAD_VALUE;
             goto exit;
@@ -457,16 +510,26 @@
         ALOGV("loadSoundModel numPhrases %d", numPhrases);
         for (size_t i = 0; i < numPhrases; i++) {
             jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
+            phraseModel->phrases[i].id =
+                                    env->GetIntField(jPhrase,gKeyphraseFields.id);
             phraseModel->phrases[i].recognition_mode =
-                                    env->GetIntField(jPhrase,gKeyPhraseFields.recognitionModes);
-            phraseModel->phrases[i].num_users =
-                                    env->GetIntField(jPhrase, gKeyPhraseFields.numUsers);
-            jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.locale);
+                                    env->GetIntField(jPhrase,gKeyphraseFields.recognitionModes);
+
+            jintArray jUsers = (jintArray)env->GetObjectField(jPhrase, gKeyphraseFields.users);
+            phraseModel->phrases[i].num_users = env->GetArrayLength(jUsers);
+            jint *nUsers = env->GetIntArrayElements(jUsers, NULL);
+            memcpy(phraseModel->phrases[i].users,
+                   nUsers,
+                   phraseModel->phrases[i].num_users * sizeof(int));
+            env->ReleaseIntArrayElements(jUsers, nUsers, 0);
+            env->DeleteLocalRef(jUsers);
+
+            jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.locale);
             const char *nLocale = env->GetStringUTFChars(jLocale, NULL);
             strncpy(phraseModel->phrases[i].locale,
                     nLocale,
                     SOUND_TRIGGER_MAX_LOCALE_LEN);
-            jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyPhraseFields.text);
+            jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.text);
             const char *nText = env->GetStringUTFChars(jText, NULL);
             strncpy(phraseModel->phrases[i].text,
                     nText,
@@ -478,6 +541,7 @@
             env->DeleteLocalRef(jText);
             ALOGV("loadSoundModel phrases %d text %s locale %s",
                   i, phraseModel->phrases[i].text, phraseModel->phrases[i].locale);
+            env->DeleteLocalRef(jPhrase);
         }
         env->DeleteLocalRef(jPhrases);
     }
@@ -490,7 +554,7 @@
         env->ReleaseIntArrayElements(jHandle, nHandle, NULL);
     }
     if (nData != NULL) {
-        env->ReleaseByteArrayElements(jData, (jbyte *)nData, NULL);
+        env->ReleaseByteArrayElements(jData, nData, NULL);
     }
     return status;
 }
@@ -512,7 +576,7 @@
 
 static jint
 android_hardware_SoundTrigger_startRecognition(JNIEnv *env, jobject thiz,
-                                               jint jHandle, jbyteArray jData)
+                                               jint jHandle, jobject jConfig)
 {
     jint status = SOUNDTRIGGER_STATUS_OK;
     ALOGV("startRecognition");
@@ -520,30 +584,83 @@
     if (module == NULL) {
         return SOUNDTRIGGER_STATUS_ERROR;
     }
+
+    if (!env->IsInstanceOf(jConfig, gRecognitionConfigClass)) {
+        return SOUNDTRIGGER_STATUS_BAD_VALUE;
+    }
+
+    jbyteArray jData = (jbyteArray)env->GetObjectField(jConfig, gRecognitionConfigFields.data);
     jsize dataSize = 0;
-    char *nData = NULL;
-    sp<IMemory> memory;
+    jbyte *nData = NULL;
     if (jData != NULL) {
         dataSize = env->GetArrayLength(jData);
         if (dataSize == 0) {
             return SOUNDTRIGGER_STATUS_BAD_VALUE;
         }
-        nData = (char *)env->GetByteArrayElements(jData, NULL);
+        nData = env->GetByteArrayElements(jData, NULL);
         if (nData == NULL) {
             return SOUNDTRIGGER_STATUS_ERROR;
         }
-        sp<MemoryDealer> memoryDealer =
-                new MemoryDealer(dataSize, "SoundTrigge-JNI::StartRecognition");
-        if (memoryDealer == 0) {
-            return SOUNDTRIGGER_STATUS_ERROR;
-        }
-        memory = memoryDealer->allocate(dataSize);
-        if (memory == 0 || memory->pointer() == NULL) {
-            return SOUNDTRIGGER_STATUS_ERROR;
-        }
-        memcpy(memory->pointer(), nData, dataSize);
     }
 
+    size_t totalSize = sizeof(struct sound_trigger_recognition_config) + dataSize;
+    sp<MemoryDealer> memoryDealer =
+            new MemoryDealer(totalSize, "SoundTrigge-JNI::StartRecognition");
+    if (memoryDealer == 0) {
+        return SOUNDTRIGGER_STATUS_ERROR;
+    }
+    sp<IMemory> memory = memoryDealer->allocate(totalSize);
+    if (memory == 0 || memory->pointer() == NULL) {
+        return SOUNDTRIGGER_STATUS_ERROR;
+    }
+    if (dataSize != 0) {
+        memcpy((char *)memory->pointer() + sizeof(struct sound_trigger_recognition_config),
+                nData,
+                dataSize);
+        env->ReleaseByteArrayElements(jData, nData, 0);
+    }
+    env->DeleteLocalRef(jData);
+    struct sound_trigger_recognition_config *config =
+                                    (struct sound_trigger_recognition_config *)memory->pointer();
+    config->data_size = dataSize;
+    config->data_offset = sizeof(struct sound_trigger_recognition_config);
+    config->capture_requested = env->GetIntField(jConfig,
+                                                 gRecognitionConfigFields.captureRequested);
+
+    config->num_phrases = 0;
+    jobjectArray jPhrases =
+        (jobjectArray)env->GetObjectField(jConfig, gRecognitionConfigFields.keyphrases);
+    if (jPhrases != NULL) {
+        config->num_phrases = env->GetArrayLength(jPhrases);
+    }
+    ALOGV("startRecognition num phrases %d", config->num_phrases);
+    for (size_t i = 0; i < config->num_phrases; i++) {
+        jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
+        config->phrases[i].id = env->GetIntField(jPhrase,
+                                                gKeyphraseRecognitionExtraFields.id);
+        config->phrases[i].recognition_modes = env->GetIntField(jPhrase,
+                                                gKeyphraseRecognitionExtraFields.recognitionModes);
+        config->phrases[i].num_levels = 0;
+        jobjectArray jConfidenceLevels = (jobjectArray)env->GetObjectField(jPhrase,
+                                                gKeyphraseRecognitionExtraFields.confidenceLevels);
+        if (jConfidenceLevels != NULL) {
+            config->phrases[i].num_levels = env->GetArrayLength(jConfidenceLevels);
+        }
+        ALOGV("startRecognition phrase %d num_levels %d", i, config->phrases[i].num_levels);
+        for (size_t j = 0; j < config->phrases[i].num_levels; j++) {
+            jobject jConfidenceLevel = env->GetObjectArrayElement(jConfidenceLevels, j);
+            config->phrases[i].levels[j].user_id = env->GetIntField(jConfidenceLevel,
+                                                                    gConfidenceLevelFields.userId);
+            config->phrases[i].levels[j].level = env->GetIntField(jConfidenceLevel,
+                                                          gConfidenceLevelFields.confidenceLevel);
+            env->DeleteLocalRef(jConfidenceLevel);
+        }
+        ALOGV("startRecognition phrases %d", i);
+        env->DeleteLocalRef(jConfidenceLevels);
+        env->DeleteLocalRef(jPhrase);
+    }
+    env->DeleteLocalRef(jPhrases);
+
     status = module->startRecognition(jHandle, memory);
     return status;
 }
@@ -586,7 +703,7 @@
         "(I)I",
         (void *)android_hardware_SoundTrigger_unloadSoundModel},
     {"startRecognition",
-        "(I[B)I",
+        "(ILandroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I",
         (void *)android_hardware_SoundTrigger_startRecognition},
     {"stopRecognition",
         "(I)I",
@@ -599,6 +716,10 @@
     gArrayListClass = (jclass) env->NewGlobalRef(arrayListClass);
     gArrayListMethods.add = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
 
+    jclass uuidClass = env->FindClass("java/util/UUID");
+    gUUIDClass = (jclass) env->NewGlobalRef(uuidClass);
+    gUUIDMethods.toString = env->GetMethodID(uuidClass, "toString", "()Ljava/lang/String;");
+
     jclass lClass = env->FindClass(kSoundTriggerClassPathName);
     gSoundTriggerClass = (jclass) env->NewGlobalRef(lClass);
 
@@ -617,37 +738,63 @@
 
     jclass soundModelClass = env->FindClass(kSoundModelClassPathName);
     gSoundModelClass = (jclass) env->NewGlobalRef(soundModelClass);
+    gSoundModelFields.uuid = env->GetFieldID(soundModelClass, "uuid", "Ljava/util/UUID;");
     gSoundModelFields.data = env->GetFieldID(soundModelClass, "data", "[B");
 
-    jclass keyPhraseClass = env->FindClass(kKeyPhraseClassPathName);
-    gKeyPhraseClass = (jclass) env->NewGlobalRef(keyPhraseClass);
-    gKeyPhraseFields.recognitionModes = env->GetFieldID(keyPhraseClass, "recognitionModes", "I");
-    gKeyPhraseFields.locale = env->GetFieldID(keyPhraseClass, "locale", "Ljava/lang/String;");
-    gKeyPhraseFields.text = env->GetFieldID(keyPhraseClass, "text", "Ljava/lang/String;");
-    gKeyPhraseFields.numUsers = env->GetFieldID(keyPhraseClass, "numUsers", "I");
+    jclass keyphraseClass = env->FindClass(kKeyphraseClassPathName);
+    gKeyphraseClass = (jclass) env->NewGlobalRef(keyphraseClass);
+    gKeyphraseFields.id = env->GetFieldID(keyphraseClass, "id", "I");
+    gKeyphraseFields.recognitionModes = env->GetFieldID(keyphraseClass, "recognitionModes", "I");
+    gKeyphraseFields.locale = env->GetFieldID(keyphraseClass, "locale", "Ljava/lang/String;");
+    gKeyphraseFields.text = env->GetFieldID(keyphraseClass, "text", "Ljava/lang/String;");
+    gKeyphraseFields.users = env->GetFieldID(keyphraseClass, "users", "[I");
 
-    jclass keyPhraseSoundModelClass = env->FindClass(kKeyPhraseSoundModelClassPathName);
-    gKeyPhraseSoundModelClass = (jclass) env->NewGlobalRef(keyPhraseSoundModelClass);
-    gKeyPhraseSoundModelFields.keyPhrases = env->GetFieldID(keyPhraseSoundModelClass,
-                                         "keyPhrases",
-                                         "[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhrase;");
+    jclass keyphraseSoundModelClass = env->FindClass(kKeyphraseSoundModelClassPathName);
+    gKeyphraseSoundModelClass = (jclass) env->NewGlobalRef(keyphraseSoundModelClass);
+    gKeyphraseSoundModelFields.keyphrases = env->GetFieldID(keyphraseSoundModelClass,
+                                         "keyphrases",
+                                         "[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;");
 
 
     jclass recognitionEventClass = env->FindClass(kRecognitionEventClassPathName);
     gRecognitionEventClass = (jclass) env->NewGlobalRef(recognitionEventClass);
     gRecognitionEventCstor = env->GetMethodID(recognitionEventClass, "<init>",
-                                              "(IIZII[B)V");
+                                              "(IIZIII[B)V");
 
-    jclass keyPhraseRecognitionEventClass = env->FindClass(kKeyPhraseRecognitionEventClassPathName);
-    gKeyPhraseRecognitionEventClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionEventClass);
-    gKeyPhraseRecognitionEventCstor = env->GetMethodID(keyPhraseRecognitionEventClass, "<init>",
-              "(IIZII[BZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyPhraseRecognitionExtra;)V");
+    jclass keyphraseRecognitionEventClass = env->FindClass(kKeyphraseRecognitionEventClassPathName);
+    gKeyphraseRecognitionEventClass = (jclass) env->NewGlobalRef(keyphraseRecognitionEventClass);
+    gKeyphraseRecognitionEventCstor = env->GetMethodID(keyphraseRecognitionEventClass, "<init>",
+              "(IIZIII[BZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V");
 
 
-    jclass keyPhraseRecognitionExtraClass = env->FindClass(kKeyPhraseRecognitionExtraClassPathName);
-    gKeyPhraseRecognitionExtraClass = (jclass) env->NewGlobalRef(keyPhraseRecognitionExtraClass);
-    gKeyPhraseRecognitionExtraCstor = env->GetMethodID(keyPhraseRecognitionExtraClass, "<init>",
-                                              "([II)V");
+    jclass keyRecognitionConfigClass = env->FindClass(kRecognitionConfigClassPathName);
+    gRecognitionConfigClass = (jclass) env->NewGlobalRef(keyRecognitionConfigClass);
+    gRecognitionConfigFields.captureRequested = env->GetFieldID(keyRecognitionConfigClass,
+                                                              "captureRequested",
+                                                              "Z");
+    gRecognitionConfigFields.keyphrases = env->GetFieldID(keyRecognitionConfigClass,
+                        "keyphrases",
+                        "[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;");
+    gRecognitionConfigFields.data = env->GetFieldID(keyRecognitionConfigClass,
+                                                              "data",
+                                                              "[B");
+
+    jclass keyphraseRecognitionExtraClass = env->FindClass(kKeyphraseRecognitionExtraClassPathName);
+    gKeyphraseRecognitionExtraClass = (jclass) env->NewGlobalRef(keyphraseRecognitionExtraClass);
+    gKeyphraseRecognitionExtraCstor = env->GetMethodID(keyphraseRecognitionExtraClass, "<init>",
+                           "(II[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;)V");
+    gKeyphraseRecognitionExtraFields.id = env->GetFieldID(gKeyphraseRecognitionExtraClass, "id", "I");
+    gKeyphraseRecognitionExtraFields.recognitionModes = env->GetFieldID(gKeyphraseRecognitionExtraClass, "recognitionModes", "I");
+    gKeyphraseRecognitionExtraFields.confidenceLevels = env->GetFieldID(gKeyphraseRecognitionExtraClass,
+                                             "confidenceLevels",
+                                             "[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;");
+
+    jclass confidenceLevelClass = env->FindClass(kConfidenceLevelClassPathName);
+    gConfidenceLevelClass = (jclass) env->NewGlobalRef(confidenceLevelClass);
+    gConfidenceLevelCstor = env->GetMethodID(confidenceLevelClass, "<init>", "(II)V");
+    gConfidenceLevelFields.userId = env->GetFieldID(confidenceLevelClass, "userId", "I");
+    gConfidenceLevelFields.confidenceLevel = env->GetFieldID(confidenceLevelClass,
+                                                             "confidenceLevel", "I");
 
     int status = AndroidRuntime::registerNativeMethods(env,
                 kSoundTriggerClassPathName, gMethods, NELEM(gMethods));
@@ -657,5 +804,6 @@
                 kModuleClassPathName, gModuleMethods, NELEM(gModuleMethods));
     }
 
+
     return status;
 }
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 3d421d5..8ad2eea 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -257,13 +257,13 @@
     return reinterpret_cast<jlong>(sur);
 }
 
-static PixelFormat convertPixelFormat(SkBitmap::Config format)
+static PixelFormat convertPixelFormat(SkColorType format)
 {
     switch (format) {
-    case SkBitmap::kARGB_8888_Config:   return PIXEL_FORMAT_RGBA_8888;
-    case SkBitmap::kARGB_4444_Config:   return PIXEL_FORMAT_RGBA_4444;
-    case SkBitmap::kRGB_565_Config:     return PIXEL_FORMAT_RGB_565;
-    default:                            return PIXEL_FORMAT_NONE;
+    case kN32_SkColorType:         return PIXEL_FORMAT_RGBA_8888;
+    case kARGB_4444_SkColorType:   return PIXEL_FORMAT_RGBA_4444;
+    case kRGB_565_SkColorType:     return PIXEL_FORMAT_RGB_565;
+    default:                       return PIXEL_FORMAT_NONE;
     }
 }
 
@@ -297,7 +297,7 @@
     pixmap.width  = nativeBitmap->width();
     pixmap.height = nativeBitmap->height();
     pixmap.stride = nativeBitmap->rowBytes() / nativeBitmap->bytesPerPixel();
-    pixmap.format = convertPixelFormat(nativeBitmap->config());
+    pixmap.format = convertPixelFormat(nativeBitmap->colorType());
     pixmap.data   = (uint8_t*)ref->pixels();
 
     base = beginNativeAttribList(_env, attrib_list);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e675dc7..2d1cc59 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1068,14 +1068,6 @@
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="signature" />
 
-    <!-- Allows an application to communicate with a SIM card using logical
-         channels. -->
-    <permission android:name="android.permission.SIM_COMMUNICATION"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:label="@string/permlab_sim_communication"
-        android:description="@string/permdesc_sim_communication"
-        android:protectionLevel="dangerous" />
-
     <!-- @SystemApi Allows TvInputService to access underlying TV input hardware such as
          built-in tuners and HDMI-in's.
          @hide This should only be used by OEM's TvInputService's.
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 901c69e..75d52b4 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -732,7 +732,7 @@
         deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
                 !state.mClipSideFlags &&
                 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
-                (mBitmap->config() != SkBitmap::kA8_Config);
+                (mBitmap->colorType() != kAlpha_8_SkColorType);
     }
 
     const SkBitmap* bitmap() { return mBitmap; }
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 873baf5..a92ef94 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -383,20 +383,20 @@
         GLenum error = GL_NO_ERROR;
         bool status = false;
 
-        switch (bitmap->config()) {
-            case SkBitmap::kA8_Config:
+        switch (bitmap->colorType()) {
+            case kAlpha_8_SkColorType:
                 format = GL_ALPHA;
                 type = GL_UNSIGNED_BYTE;
                 break;
-            case SkBitmap::kRGB_565_Config:
+            case kRGB_565_SkColorType:
                 format = GL_RGB;
                 type = GL_UNSIGNED_SHORT_5_6_5;
                 break;
-            case SkBitmap::kARGB_4444_Config:
+            case kARGB_4444_SkColorType:
                 format = GL_RGBA;
                 type = GL_UNSIGNED_SHORT_4_4_4_4;
                 break;
-            case SkBitmap::kARGB_8888_Config:
+            case kN32_SkColorType:
             default:
                 format = GL_RGBA;
                 type = GL_UNSIGNED_BYTE;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1bbcff1..c9f541b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1957,7 +1957,7 @@
 
     const float x = (int) floorf(bounds.left + 0.5f);
     const float y = (int) floorf(bounds.top + 0.5f);
-    if (CC_UNLIKELY(bitmap->config() == SkBitmap::kA8_Config)) {
+    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
         drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
                 texture->id, paint, &vertices[0].x, &vertices[0].u,
                 GL_TRIANGLES, bitmapCount * 6, true,
@@ -1986,7 +1986,7 @@
     if (!texture) return DrawGlInfo::kStatusDone;
     const AutoTexture autoCleanup(texture);
 
-    if (CC_UNLIKELY(bitmap->config() == SkBitmap::kA8_Config)) {
+    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
         drawAlphaBitmap(texture, left, top, paint);
     } else {
         drawTextureRect(left, top, right, bottom, texture, paint);
@@ -2014,7 +2014,7 @@
     // to the vertex shader. The save/restore is a bit overkill.
     save(SkCanvas::kMatrix_SaveFlag);
     concatMatrix(matrix);
-    if (CC_UNLIKELY(bitmap->config() == SkBitmap::kA8_Config)) {
+    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
         drawAlphaBitmap(texture, 0.0f, 0.0f, paint);
     } else {
         drawTextureRect(0.0f, 0.0f, bitmap->width(), bitmap->height(), texture, paint);
@@ -2037,7 +2037,7 @@
     Texture* texture = mCaches.textureCache.getTransient(bitmap);
     const AutoTexture autoCleanup(texture);
 
-    if (CC_UNLIKELY(bitmap->config() == SkBitmap::kA8_Config)) {
+    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
         drawAlphaBitmap(texture, left, top, paint);
     } else {
         drawTextureRect(left, top, right, bottom, texture, paint);
@@ -2232,7 +2232,7 @@
         dstBottom = srcBottom - srcTop;
     }
 
-    if (CC_UNLIKELY(bitmap->config() == SkBitmap::kA8_Config)) {
+    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
         drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom,
                 texture->id, paint,
                 &mMeshVertices[0].x, &mMeshVertices[0].u,
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 9212d0a..ec9e30a 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -285,20 +285,20 @@
 
     Caches::getInstance().bindTexture(texture->id);
 
-    switch (bitmap->config()) {
-    case SkBitmap::kA8_Config:
+    switch (bitmap->colorType()) {
+    case kAlpha_8_SkColorType:
         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
         uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
                 texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels());
         texture->blend = true;
         break;
-    case SkBitmap::kRGB_565_Config:
+    case kRGB_565_SkColorType:
         glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
         uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
                 texture->width, texture->height, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
         texture->blend = false;
         break;
-    case SkBitmap::kARGB_8888_Config:
+    case kN32_SkColorType:
         glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
         uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
                 texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels());
@@ -306,14 +306,14 @@
         // decoding happened
         texture->blend = !bitmap->isOpaque();
         break;
-    case SkBitmap::kARGB_4444_Config:
-    case SkBitmap::kIndex8_Config:
+    case kARGB_4444_SkColorType:
+    case kIndex_8_SkColorType:
         glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
         uploadLoFiTexture(resize, bitmap, texture->width, texture->height);
         texture->blend = !bitmap->isOpaque();
         break;
     default:
-        ALOGW("Unsupported bitmap config: %d", bitmap->config());
+        ALOGW("Unsupported bitmap colorType: %d", bitmap->colorType());
         break;
     }
 
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index eaa2cbe..df0751d 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -34,17 +34,17 @@
         info->stride    = bm->rowBytes();
         info->flags     = 0;
 
-        switch (bm->config()) {
-            case SkBitmap::kARGB_8888_Config:
+        switch (bm->colorType()) {
+            case kN32_SkColorType:
                 info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
                 break;
-            case SkBitmap::kRGB_565_Config:
+            case kRGB_565_SkColorType:
                 info->format = ANDROID_BITMAP_FORMAT_RGB_565;
                 break;
-            case SkBitmap::kARGB_4444_Config:
+            case kARGB_4444_SkColorType:
                 info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
                 break;
-            case SkBitmap::kA8_Config:
+            case kAlpha_8_SkColorType:
                 info->format = ANDROID_BITMAP_FORMAT_A_8;
                 break;
             default:
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dd7775d..8257f29 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7960,7 +7960,7 @@
                 checkedGrants = true;
             }
             userId = handleIncomingUser(callingPid, callingUid, userId,
-                    false, true, "checkContentProviderPermissionLocked " + cpi.authority, null);
+                    false, false, "checkContentProviderPermissionLocked " + cpi.authority, null);
         }
         if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
                 cpi.applicationInfo.uid, cpi.exported)
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
new file mode 100644
index 0000000..a1240f4
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright (C) 2014 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 com.android.server.voiceinteraction;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @hide
+ */
+public class DatabaseHelper extends SQLiteOpenHelper {
+    static final String TAG = "SoundModelDBHelper";
+
+    private static final String NAME = "sound_model.db";
+    private static final int VERSION = 1;
+
+    public static interface KeyphraseContract {
+        public static final String TABLE = "keyphrase";
+        public static final String KEY_ID = "_id";
+        public static final String KEY_RECOGNITION_MODES = "modes";
+        public static final String KEY_LOCALE = "locale";
+        public static final String KEY_HINT_TEXT = "hint_text";
+        public static final String KEY_USERS = "users";
+        public static final String KEY_SOUND_MODEL_ID = "sound_model_id";
+    }
+
+    public static interface SoundModelContract {
+        public static final String TABLE = "sound_model";
+        public static final String KEY_ID = "_id";
+        public static final String KEY_TYPE = "type";
+        public static final String KEY_DATA = "data";
+    }
+
+    // Table Create Statements
+    private static final String CREATE_TABLE_KEYPRHASES = "CREATE TABLE "
+            + KeyphraseContract.TABLE + "("
+            + KeyphraseContract.KEY_ID + " INTEGER PRIMARY KEY,"
+            + KeyphraseContract.KEY_RECOGNITION_MODES + " INTEGER,"
+            + KeyphraseContract.KEY_USERS + " INTEGER,"
+            + KeyphraseContract.KEY_SOUND_MODEL_ID + " TEXT,"
+            + KeyphraseContract.KEY_LOCALE + " TEXT,"
+            + KeyphraseContract.KEY_HINT_TEXT + " TEXT" + ")";
+
+    private static final String CREATE_TABLE_SOUND_MODEL = "CREATE TABLE "
+            + SoundModelContract.TABLE + "("
+            + SoundModelContract.KEY_ID + " TEXT PRIMARY KEY,"
+            + SoundModelContract.KEY_TYPE + " INTEGER,"
+            + SoundModelContract.KEY_DATA + " BLOB" + ")";
+
+    public DatabaseHelper(Context context, CursorFactory factory) {
+        super(context, NAME, null, VERSION);
+    }
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        // creating required tables
+        db.execSQL(CREATE_TABLE_KEYPRHASES);
+        db.execSQL(CREATE_TABLE_SOUND_MODEL);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        // TODO(sansid): For now, drop older tables and recreate new ones.
+        db.execSQL("DROP TABLE IF EXISTS " + KeyphraseContract.TABLE);
+        db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE);
+        onCreate(db);
+    }
+
+    /**
+     * TODO(sansid): Change to addOrUpdate to handle changes here.
+     */
+    public void addKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
+        SQLiteDatabase db = this.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        // Generate a random ID for the model.
+        values.put(SoundModelContract.KEY_ID, soundModel.uuid.toString());
+        values.put(SoundModelContract.KEY_DATA, soundModel.data);
+        values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE);
+
+        if (db.insert(SoundModelContract.TABLE, null, values) != -1) {
+            for (Keyphrase keyphrase : soundModel.keyphrases) {
+                addKeyphrase(soundModel.uuid, keyphrase);
+            }
+        } else {
+            Slog.w(TAG, "Failed to persist sound model to database");
+        }
+    }
+
+    /**
+     * TODO(sansid): Change to addOrUpdate to handle changes here.
+     */
+    private void addKeyphrase(UUID modelId, SoundTrigger.Keyphrase keyphrase) {
+        SQLiteDatabase db = this.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put(KeyphraseContract.KEY_ID, keyphrase.id);
+        values.put(KeyphraseContract.KEY_RECOGNITION_MODES, keyphrase.recognitionModes);
+        values.put(KeyphraseContract.KEY_SOUND_MODEL_ID, keyphrase.id);
+        values.put(KeyphraseContract.KEY_HINT_TEXT, keyphrase.text);
+        values.put(KeyphraseContract.KEY_LOCALE, keyphrase.locale);
+        if (db.insert(KeyphraseContract.TABLE, null, values) == -1) {
+            Slog.w(TAG, "Failed to persist keyphrase to database");
+        }
+    }
+
+    /**
+     * Lists all the keyphrase sound models currently registered with the system.
+     */
+    public List<KeyphraseSoundModel> getKephraseSoundModels() {
+        List<KeyphraseSoundModel> models = new ArrayList<>();
+        String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE;
+        SQLiteDatabase db = this.getReadableDatabase();
+        Cursor c = db.rawQuery(selectQuery, null);
+
+        // looping through all rows and adding to list
+        if (c.moveToFirst()) {
+            do {
+                int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
+                if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) {
+                    // Ignore non-keyphrase sound models.
+                    continue;
+                }
+                String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID));
+                byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
+                // Get all the keyphrases for this this sound model.
+                models.add(new KeyphraseSoundModel(
+                        UUID.fromString(id), data, getKeyphrasesForSoundModel(id)));
+            } while (c.moveToNext());
+        }
+        return models;
+    }
+
+    private Keyphrase[] getKeyphrasesForSoundModel(String modelId) {
+        List<Keyphrase> keyphrases = new ArrayList<>();
+        String selectQuery = "SELECT  * FROM " + KeyphraseContract.TABLE
+                + " WHERE " + KeyphraseContract.KEY_SOUND_MODEL_ID + " = '" + modelId + "'";
+        SQLiteDatabase db = this.getReadableDatabase();
+        Cursor c = db.rawQuery(selectQuery, null);
+
+        // looping through all rows and adding to list
+        if (c.moveToFirst()) {
+            do {
+                int id = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_ID));
+                int modes = c.getInt(c.getColumnIndex(KeyphraseContract.KEY_RECOGNITION_MODES));
+                int[] users = {c.getInt(c.getColumnIndex(KeyphraseContract.KEY_USERS))};
+                String locale = c.getString(c.getColumnIndex(KeyphraseContract.KEY_LOCALE));
+                String hintText = c.getString(c.getColumnIndex(KeyphraseContract.KEY_HINT_TEXT));
+
+                keyphrases.add(new Keyphrase(id, modes, locale, hintText, users));
+            } while (c.moveToNext());
+        }
+        Keyphrase[] keyphraseArr = new Keyphrase[keyphrases.size()];
+        keyphrases.toArray(keyphraseArr);
+        return keyphraseArr;
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b29cc12..e4885a1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2300,7 +2300,7 @@
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#SIM_COMMUNICATION SIM_COMMUNICATION}
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * @param AID Application id. See ETSI 102.221 and 101.220.
      * @return The logical channel id which is negative on error.
@@ -2322,7 +2322,7 @@
      * Input parameters equivalent to TS 27.007 AT+CCHC command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#SIM_COMMUNICATION SIM_COMMUNICATION}
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * @param channel is the channel id to be closed as retruned by a successful
      *            iccOpenLogicalChannel.
@@ -2345,7 +2345,7 @@
      * Input parameters equivalent to TS 27.007 AT+CGLA command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#SIM_COMMUNICATION SIM_COMMUNICATION}
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * @param channel is the channel id to be closed as returned by a successful
      *            iccOpenLogicalChannel.
@@ -2376,7 +2376,7 @@
      * Send ENVELOPE to the SIM and return the response.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#SIM_COMMUNICATION SIM_COMMUNICATION}
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * @param content String containing SAT/USAT response in hexadecimal
      *                format starting with command tag. See TS 102 223 for
@@ -2756,6 +2756,25 @@
     }
 
     /**
+     * Get the calculated preferred network type.
+     * Used for debugging incorrect network type.
+     *
+     * @return the preferred network type, defined in RILConstants.java or -1 if
+     *         none available.
+     * @hide
+     */
+    public int getCalculatedPreferredNetworkType() {
+        try {
+            return getITelephony().getCalculatedPreferredNetworkType();
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getCalculatedPreferredNetworkType RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "getCalculatedPreferredNetworkType NPE", ex);
+        }
+        return -1;
+    }
+
+    /**
      * Get the preferred network type.
      * Used for device configuration by some CDMA operators.
      *
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5b6db4d..7bf3b3f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -584,6 +584,14 @@
     boolean nvResetConfig(int resetType);
 
     /*
+     * Get the calculated preferred network type.
+     * Used for device configuration by some CDMA operators.
+     *
+     * @return the calculated preferred network type, defined in RILConstants.java.
+     */
+    int getCalculatedPreferredNetworkType();
+
+    /*
      * Get the preferred network type.
      * Used for device configuration by some CDMA operators.
      *