Merge "minor clean-up GLclampx -> GLclampf" into kraken
diff --git a/docs/html/guide/developing/tools/emulator.jd b/docs/html/guide/developing/tools/emulator.jd
index 6363ab2..f07cdd5 100644
--- a/docs/html/guide/developing/tools/emulator.jd
+++ b/docs/html/guide/developing/tools/emulator.jd
@@ -1142,7 +1142,7 @@
 emulator checks the value of the <code>http_proxy</code> environment variable at
 startup and uses its value automatically, if defined. </p>
 
-<p>You can use the <code>-verbose-proxy</code> option to diagnose proxy
+<p>You can use the <code>-debug-proxy</code> option to diagnose proxy
 connection problems.</p>
 
 <a name="connecting"></a>
diff --git a/docs/html/guide/practices/design/performance.jd b/docs/html/guide/practices/design/performance.jd
index b3f8830..f22d2d3 100644
--- a/docs/html/guide/practices/design/performance.jd
+++ b/docs/html/guide/practices/design/performance.jd
@@ -279,7 +279,7 @@
 <p>On devices without a JIT, it is true that invoking methods via a
 variable with an exact type rather than an interface is slightly more
 efficient. (So, for example, it was cheaper to invoke methods on a
-<code>Map map</code> than a <code>HashMap map</code>, even though in both
+<code>HashMap map</code> than a <code>Map map</code>, even though in both
 cases the map was a <code>HashMap</code>.) It was not the case that this
 was 2x slower; the actual difference was more like 6% slower. Furthermore,
 the JIT makes the two effectively indistinguishable.</p>
diff --git a/docs/html/guide/publishing/app-signing.jd b/docs/html/guide/publishing/app-signing.jd
index 39b230b..8c37d7a 100644
--- a/docs/html/guide/publishing/app-signing.jd
+++ b/docs/html/guide/publishing/app-signing.jd
@@ -337,17 +337,6 @@
 <td><code>-v</code></td><td>Enable verbose output.</td>
 </tr>
 <tr>
-<td><code>-keystore&nbsp;&lt;keystore-name&gt;.keystore</code></td><td>A name
-for the keystore containing the private key.</td>
-</tr>
-<tr>
-<td><code>-storepass &lt;password&gt;</code></td><td><p>A password for the
-keystore.</p><p>As a security precaution, do not include this option 
-in your command line unless you are working at a secure computer.
-If not supplied, Keytool prompts you to enter the password. In this 
-way, your password is not stored in your shell history.</p></td>
-</tr>
-<tr>
 <td><code>-alias &lt;alias_name&gt;</code></td><td>An alias for the key. Only
 the first 8 characters of the alias are used.</td>
 </tr>
@@ -356,6 +345,11 @@
 when generating the key. Both DSA and RSA are supported.</td>
 </tr>
 <tr>
+<td><code>-keysize &lt;size&gt;</code></td><td>The size of each generated key
+(bits). If not supplied, Keytool uses a default key size of 1024 bits. In
+general, we recommend using a key size of 2048 bits or higher. </td>
+</tr>
+<tr>
 <td><code>-dname &lt;name&gt;</code></td><td><p>A Distinguished Name that describes
 who created the key. The value is used as the issuer and subject fields in the
 self-signed certificate. </p><p>Note that you do not need to specify this option
@@ -363,22 +357,31 @@
 of the Distinguished Name fields (CN, OU, and so on).</p></td>
 </tr>
 <tr>
+<td><code>-keypass &lt;password&gt;</code></td><td><p>The password for the
+key.</p> <p>As a security precaution, do not include this option in your command
+line. If not supplied, Keytool prompts you to enter the password. In this way,
+your password is not stored in your shell history.</p></td>
+</tr>
+<tr>
 <td><code>-validity &lt;valdays&gt;</code></td><td><p>The validity period for the
 key, in days. </p><p><strong>Note:</strong> A value of 10000 or greater is recommended.</p></td>
 </tr>
 <tr>
-<td><code>-keypass &lt;password&gt;</code></td><td><p>The password for the key.</p>
-<p>As a security precaution, do not include this option 
-in your command line unless you are working at a secure computer.
-If not supplied, Keytool prompts you to enter the password. In this 
-way, your password is not stored in your shell history.</p></td>
+<td><code>-keystore&nbsp;&lt;keystore-name&gt;.keystore</code></td><td>A name
+for the keystore containing the private key.</td>
+</tr>
+<tr>
+<td><code>-storepass &lt;password&gt;</code></td><td><p>A password for the
+keystore.</p><p>As a security precaution, do not include this option in your
+command line. If not supplied, Keytool prompts you to enter the password. In
+this way, your password is not stored in your shell history.</p></td>
 </tr>
 </table>
 
 <p>Here's an example of a Keytool command that generates a private key:</p>
 
 <pre>$ keytool -genkey -v -keystore my-release-key.keystore 
--alias alias_name -keyalg RSA -validity 10000</pre>
+-alias alias_name -keyalg RSA -keysize 2048 -validity 10000</pre>
 
 <p>Running the example command above, Keytool prompts you to provide
 passwords for the keystore and key, and to provide the Distinguished
diff --git a/docs/html/guide/topics/providers/content-providers.jd b/docs/html/guide/topics/providers/content-providers.jd
index 5da760a..30f8d8c 100644
--- a/docs/html/guide/topics/providers/content-providers.jd
+++ b/docs/html/guide/topics/providers/content-providers.jd
@@ -176,17 +176,7 @@
 <p>
 <p style="margin-left: 2em">{@code android.provider.Contacts.Phones.CONTENT_URI}
 <br/>{@code android.provider.Contacts.Photos.CONTENT_URI}
-</p>   
-
-<p>
-Similarly, the URIs for the table of recent phone calls and the table 
-of calendar entries are:
-</p>   
-
-<p>
-<p style="margin-left: 2em">{@code android.provider.CallLog.Calls.CONTENT_URI}
-<br/>{@code android.provider.Calendar.CONTENT_URI}
-</p>   
+</p>
 
 <p>
 The URI constant is used in all interactions with the content provider. 
diff --git a/docs/html/sdk/adt_download.jd b/docs/html/sdk/adt_download.jd
index 96896c7..f98caf5 100644
--- a/docs/html/sdk/adt_download.jd
+++ b/docs/html/sdk/adt_download.jd
@@ -22,11 +22,18 @@
     <th>Notes</th>
   </tr>
   <tr>
-     <td>0.9.6</td>
-     <td><a href="http://dl-ssl.google.com/android/ADT-0.9.6.zip">ADT-0.9.6.zip</a></td>
+     <td>0.9.7</td>
+     <td><a href="http://dl-ssl.google.com/android/ADT-0.9.7.zip">ADT-0.9.7.zip</a></td>
      <td><nobr>{@adtZipBytes} bytes</nobr></td>
      <td>{@adtZipChecksum}</td>
-     <td>Requires SDK Tools, Revision 5 <em><nobr>March 2009</nobr></em></td>
+     <td>Requires SDK Tools, Revision 6 <em><nobr>May 2010</nobr></em></td>
+  </tr>
+  <tr>
+     <td>0.9.6</td>
+     <td><a href="http://dl-ssl.google.com/android/ADT-0.9.6.zip">ADT-0.9.6.zip</a></td>
+     <td><nobr>7456339 bytes</nobr></td>
+     <td>ea45d271be52b87b5dd1c9fb17536223</td>
+     <td>Requires SDK Tools, Revision 5 <em><nobr>March 2010</nobr></em></td>
   </tr>
   <tr>
      <td>0.9.5</td>
diff --git a/include/media/IEffect.h b/include/media/IEffect.h
new file mode 100644
index 0000000..6dad393
--- /dev/null
+++ b/include/media/IEffect.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IEFFECT_H
+#define ANDROID_IEFFECT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+
+namespace android {
+
+class IEffect: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(Effect);
+
+    virtual status_t enable() = 0;
+
+    virtual status_t disable() = 0;
+
+    virtual status_t command(int cmdCode, int cmdSize, void *pCmdData, int *pReplySize, void *pReplyData) = 0;
+
+    virtual void disconnect() = 0;
+
+    virtual sp<IMemory> getCblk() const = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnEffect: public BnInterface<IEffect>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IEFFECT_H
diff --git a/include/media/IEffectClient.h b/include/media/IEffectClient.h
new file mode 100644
index 0000000..d22daf8
--- /dev/null
+++ b/include/media/IEffectClient.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IEFFECTCLIENT_H
+#define ANDROID_IEFFECTCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+
+namespace android {
+
+class IEffectClient: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(EffectClient);
+
+    virtual void controlStatusChanged(bool controlGranted) = 0;
+    virtual void enableStatusChanged(bool enabled) = 0;
+    virtual void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnEffectClient: public BnInterface<IEffectClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IEFFECTCLIENT_H
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 42d6634..9d6b01d 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -19,6 +19,7 @@
 #define CAMERA_SOURCE_H_
 
 #include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaSource.h>
 #include <utils/List.h>
 #include <utils/RefBase.h>
@@ -61,6 +62,7 @@
     int32_t mNumFramesReceived;
     int32_t mNumFramesEncoded;
     int32_t mNumFramesDropped;
+    MediaBufferGroup *mBufferGroup;
     bool mStarted;
 
     CameraSource(const sp<Camera> &camera);
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 3adabcc..29cd2ee 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -26,7 +26,9 @@
     MediaScannerClient.cpp \
     autodetect.cpp \
     IMediaDeathNotifier.cpp \
-    MediaProfiles.cpp
+    MediaProfiles.cpp \
+    IEffect.cpp \
+    IEffectClient.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp
new file mode 100644
index 0000000..8e3ac71
--- /dev/null
+++ b/media/libmedia/IEffect.cpp
@@ -0,0 +1,191 @@
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IEffect"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IEffect.h>
+
+namespace android {
+
+enum {
+    ENABLE = IBinder::FIRST_CALL_TRANSACTION,
+    DISABLE,
+    COMMAND,
+    DISCONNECT,
+    GET_CBLK
+};
+
+class BpEffect: public BpInterface<IEffect>
+{
+public:
+    BpEffect(const sp<IBinder>& impl)
+        : BpInterface<IEffect>(impl)
+    {
+    }
+
+    status_t enable()
+    {
+        LOGV("enable");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        remote()->transact(ENABLE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t disable()
+    {
+        LOGV("disable");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        remote()->transact(DISABLE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t command(int cmdCode, int cmdSize, void *pCmdData, int *pReplySize, void *pReplyData)
+    {
+        LOGV("command");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        data.writeInt32(cmdCode);
+        int size = cmdSize;
+        if (pCmdData == NULL) {
+            size = 0;
+        }
+        data.writeInt32(size);
+        if (size) {
+            data.write(pCmdData, size);
+        }
+        if (pReplySize == NULL) {
+            size = 0;
+        } else {
+            size = *pReplySize;
+        }
+        data.writeInt32(size);
+        remote()->transact(COMMAND, data, &reply);
+        status_t status = reply.readInt32();
+        size = reply.readInt32();
+        if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
+            reply.read(pReplyData, size);
+            *pReplySize = size;
+        }
+        return status;
+    }
+
+    void disconnect()
+    {
+        LOGV("disconnect");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        remote()->transact(DISCONNECT, data, &reply);
+        return;
+    }
+
+    virtual sp<IMemory> getCblk() const
+    {
+        Parcel data, reply;
+        sp<IMemory> cblk;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_CBLK, data, &reply);
+        if (status == NO_ERROR) {
+            cblk = interface_cast<IMemory>(reply.readStrongBinder());
+        }
+        return cblk;
+    }
+ };
+
+IMPLEMENT_META_INTERFACE(Effect, "android.media.IEffect");
+
+// ----------------------------------------------------------------------
+
+status_t BnEffect::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case ENABLE: {
+            LOGV("ENABLE");
+            CHECK_INTERFACE(IEffect, data, reply);
+            reply->writeInt32(enable());
+            return NO_ERROR;
+        } break;
+
+        case DISABLE: {
+            LOGV("DISABLE");
+            CHECK_INTERFACE(IEffect, data, reply);
+            reply->writeInt32(disable());
+            return NO_ERROR;
+        } break;
+
+        case COMMAND: {
+            LOGV("COMMAND");
+            CHECK_INTERFACE(IEffect, data, reply);
+            int cmdCode = data.readInt32();
+            int cmdSize = data.readInt32();
+            char *cmd = NULL;
+            if (cmdSize) {
+                cmd = (char *)malloc(cmdSize);
+                data.read(cmd, cmdSize);
+            }
+            int replySize = data.readInt32();
+            int replySz = replySize;
+            char *resp = NULL;
+            if (replySize) {
+                resp = (char *)malloc(replySize);
+            }
+            status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp);
+            reply->writeInt32(status);
+            if (replySz < replySize) {
+                replySize = replySz;
+            }
+            reply->writeInt32(replySize);
+            if (replySize) {
+                reply->write(resp, replySize);
+            }
+            if (cmd) {
+                free(cmd);
+            }
+            if (resp) {
+                free(resp);
+            }
+            return NO_ERROR;
+        } break;
+
+        case DISCONNECT: {
+            LOGV("DISCONNECT");
+            CHECK_INTERFACE(IEffect, data, reply);
+            disconnect();
+            return NO_ERROR;
+        } break;
+
+        case GET_CBLK: {
+             CHECK_INTERFACE(IEffect, data, reply);
+             reply->writeStrongBinder(getCblk()->asBinder());
+             return NO_ERROR;
+         } break;
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IEffectClient.cpp b/media/libmedia/IEffectClient.cpp
new file mode 100644
index 0000000..e7659ae
--- /dev/null
+++ b/media/libmedia/IEffectClient.cpp
@@ -0,0 +1,141 @@
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IEffectClient"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <media/IEffectClient.h>
+
+namespace android {
+
+enum {
+    CONTROL_STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
+    ENABLE_STATUS_CHANGED,
+    COMMAND_EXECUTED
+};
+
+class BpEffectClient: public BpInterface<IEffectClient>
+{
+public:
+    BpEffectClient(const sp<IBinder>& impl)
+        : BpInterface<IEffectClient>(impl)
+    {
+    }
+
+    void controlStatusChanged(bool controlGranted)
+    {
+        LOGV("controlStatusChanged");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+        data.writeInt32((uint32_t)controlGranted);
+        remote()->transact(CONTROL_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    void enableStatusChanged(bool enabled)
+    {
+        LOGV("enableStatusChanged");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+        data.writeInt32((uint32_t)enabled);
+        remote()->transact(ENABLE_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData)
+    {
+        LOGV("commandExecuted");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+        data.writeInt32(cmdCode);
+        int size = cmdSize;
+        if (pCmdData == NULL) {
+            size = 0;
+        }
+        data.writeInt32(size);
+        if (size) {
+            data.write(pCmdData, size);
+        }
+        size = replySize;
+        if (pReplyData == NULL) {
+            size = 0;
+        }
+        data.writeInt32(size);
+        if (size) {
+            data.write(pReplyData, size);
+        }
+        remote()->transact(COMMAND_EXECUTED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(EffectClient, "android.media.IEffectClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnEffectClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case CONTROL_STATUS_CHANGED: {
+            LOGV("CONTROL_STATUS_CHANGED");
+            CHECK_INTERFACE(IEffectClient, data, reply);
+            bool hasControl = (bool)data.readInt32();
+            controlStatusChanged(hasControl);
+            return NO_ERROR;
+        } break;
+        case ENABLE_STATUS_CHANGED: {
+            LOGV("ENABLE_STATUS_CHANGED");
+            CHECK_INTERFACE(IEffectClient, data, reply);
+            bool enabled = (bool)data.readInt32();
+            enableStatusChanged(enabled);
+            return NO_ERROR;
+        } break;
+        case COMMAND_EXECUTED: {
+            LOGV("COMMAND_EXECUTED");
+            CHECK_INTERFACE(IEffectClient, data, reply);
+            int cmdCode = data.readInt32();
+            int cmdSize = data.readInt32();
+            char *cmd = NULL;
+            if (cmdSize) {
+                cmd = (char *)malloc(cmdSize);
+                data.read(cmd, cmdSize);
+            }
+            int replySize = data.readInt32();
+            char *resp = NULL;
+            if (replySize) {
+                resp = (char *)malloc(replySize);
+                data.read(resp, replySize);
+            }
+            commandExecuted(cmdCode, cmdSize, cmd, replySize, resp);
+            if (cmd) {
+                free(cmd);
+            }
+            if (resp) {
+                free(resp);
+            }
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 681943f..8d15013 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -77,6 +77,8 @@
         libstagefright_mp3dec \
         libstagefright_vorbisdec \
         libstagefright_matroska \
+        libstagefright_vpxdec \
+        libvpx \
 
 LOCAL_SHARED_LIBRARIES += \
         libstagefright_amrnb_common \
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index cd26e6b..87d7ebb 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -104,6 +104,7 @@
       mNumFramesReceived(0),
       mNumFramesEncoded(0),
       mNumFramesDropped(0),
+      mBufferGroup(NULL),
       mStarted(false) {
     String8 s = mCamera->getParameters();
     printf("params: \"%s\"\n", s.string());
@@ -118,6 +119,23 @@
     }
 }
 
+static int bytesPerPixelTimes10(const char *colorFormat) {
+    LOGI("color format: %s", colorFormat);
+    return 20;
+#if 0
+    // XXX: Fix Camera Hal bug?
+    // On sholes, it returns CameraParameters::PIXEL_FORMAT_YUV420SP???
+    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP) ||
+        !strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)  ||
+        !strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
+        return 20;
+    } else if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+        return 15;
+    }
+    CHECK_EQ(0, "Unknown color format");
+#endif
+}
+
 status_t CameraSource::start(MetaData *) {
     LOGV("start");
     CHECK(!mStarted);
@@ -126,6 +144,12 @@
     CHECK_EQ(OK, mCamera->startRecording());
 
     mStarted = true;
+    mBufferGroup = new MediaBufferGroup();
+    String8 s = mCamera->getParameters();
+    CameraParameters params(s);
+    const char *colorFormat = params.getPreviewFormat();
+    const int size = (mWidth * mHeight * bytesPerPixelTimes10(colorFormat))/10;
+    mBufferGroup->add_buffer(new MediaBuffer(size));
 
     return OK;
 }
@@ -139,6 +163,8 @@
     mCamera->stopRecording();
 
     releaseQueuedFrames();
+    delete mBufferGroup;
+    mBufferGroup = NULL;
     LOGI("Frames received/encoded/dropped: %d/%d/%d, timestamp (us) last/first: %lld/%lld",
             mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
             mLastFrameTimestampUs, mFirstFrameTimeUs);
@@ -197,7 +223,7 @@
         ++mNumFramesEncoded;
     }
 
-    *buffer = new MediaBuffer(frame->size());
+    mBufferGroup->acquire_buffer(buffer);
     memcpy((*buffer)->data(), frame->pointer(), frame->size());
     (*buffer)->set_range(0, frame->size());
     mCamera->releaseRecordingFrame(frame);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 928a6c8..66011ca9 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -28,6 +28,7 @@
 #include "include/M4vH263Decoder.h"
 #include "include/MP3Decoder.h"
 #include "include/VorbisDecoder.h"
+#include "include/VPXDecoder.h"
 
 #include "include/ESDS.h"
 
@@ -76,6 +77,7 @@
 FACTORY_CREATE(AVCDecoder)
 FACTORY_CREATE(M4vH263Decoder)
 FACTORY_CREATE(VorbisDecoder)
+FACTORY_CREATE(VPXDecoder)
 FACTORY_CREATE_ENCODER(AMRNBEncoder)
 FACTORY_CREATE_ENCODER(AMRWBEncoder)
 FACTORY_CREATE_ENCODER(AACEncoder)
@@ -118,6 +120,7 @@
         FACTORY_REF(AVCDecoder)
         FACTORY_REF(M4vH263Decoder)
         FACTORY_REF(VorbisDecoder)
+        FACTORY_REF(VPXDecoder)
     };
     for (size_t i = 0;
          i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
@@ -158,6 +161,7 @@
     { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
 //    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" },
     { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
+    { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
 };
 
 static const CodecInfo kEncoderInfo[] = {
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index bd16db9..6013b6f 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -76,7 +76,7 @@
     status_t seekToOffset(off_t offset);
     status_t readNextPacket(MediaBuffer **buffer);
 
-    void init();
+    status_t init();
 
     sp<MetaData> getFileMetaData() { return mFileMeta; }
 
@@ -107,7 +107,7 @@
     ssize_t readPage(off_t offset, Page *page);
     status_t findNextPage(off_t startOffset, off_t *pageOffset);
 
-    void verifyHeader(
+    status_t verifyHeader(
             MediaBuffer *buffer, uint8_t type);
 
     void parseFileMetaData();
@@ -308,6 +308,7 @@
         totalSize += page->mLace[i];
     }
 
+#if 0
     String8 tmp;
     for (size_t i = 0; i < page->mNumSegments; ++i) {
         char x[32];
@@ -316,7 +317,8 @@
         tmp.append(x);
     }
 
-    // LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
+    LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
+#endif
 
     return sizeof(header) + page->mNumSegments + totalSize;
 }
@@ -432,43 +434,60 @@
     }
 }
 
-void MyVorbisExtractor::init() {
+status_t MyVorbisExtractor::init() {
     mMeta = new MetaData;
     mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
 
     MediaBuffer *packet;
-    CHECK_EQ(readNextPacket(&packet), OK);
+    status_t err;
+    if ((err = readNextPacket(&packet)) != OK) {
+        return err;
+    }
     LOGV("read packet of size %d\n", packet->range_length());
-    verifyHeader(packet, 1);
+    err = verifyHeader(packet, 1);
     packet->release();
     packet = NULL;
+    if (err != OK) {
+        return err;
+    }
 
-    CHECK_EQ(readNextPacket(&packet), OK);
+    if ((err = readNextPacket(&packet)) != OK) {
+        return err;
+    }
     LOGV("read packet of size %d\n", packet->range_length());
-    verifyHeader(packet, 3);
+    err = verifyHeader(packet, 3);
     packet->release();
     packet = NULL;
+    if (err != OK) {
+        return err;
+    }
 
-    CHECK_EQ(readNextPacket(&packet), OK);
+    if ((err = readNextPacket(&packet)) != OK) {
+        return err;
+    }
     LOGV("read packet of size %d\n", packet->range_length());
-    verifyHeader(packet, 5);
+    err = verifyHeader(packet, 5);
     packet->release();
     packet = NULL;
+    if (err != OK) {
+        return err;
+    }
 
     mFirstDataOffset = mOffset + mCurrentPageSize;
+
+    return OK;
 }
 
-void MyVorbisExtractor::verifyHeader(
+status_t MyVorbisExtractor::verifyHeader(
         MediaBuffer *buffer, uint8_t type) {
     const uint8_t *data =
         (const uint8_t *)buffer->data() + buffer->range_offset();
 
     size_t size = buffer->range_length();
 
-    CHECK(size >= 7);
-
-    CHECK_EQ(data[0], type);
-    CHECK(!memcmp(&data[1], "vorbis", 6));
+    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
+        return ERROR_MALFORMED;
+    }
 
     ogg_buffer buf;
     buf.data = (uint8_t *)data;
@@ -515,7 +534,9 @@
 
         case 3:
         {
-            CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits));
+            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
+                return ERROR_MALFORMED;
+            }
 
             parseFileMetaData();
             break;
@@ -523,12 +544,16 @@
 
         case 5:
         {
-            CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits));
+            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
+                return ERROR_MALFORMED;
+            }
 
             mMeta->setData(kKeyVorbisBooks, 0, data, size);
             break;
         }
     }
+
+    return OK;
 }
 
 uint64_t MyVorbisExtractor::approxBitrate() {
@@ -732,10 +757,11 @@
       mInitCheck(NO_INIT),
       mImpl(NULL) {
     mImpl = new MyVorbisExtractor(mDataSource);
-    CHECK_EQ(mImpl->seekToOffset(0), OK);
-    mImpl->init();
+    mInitCheck = mImpl->seekToOffset(0);
 
-    mInitCheck = OK;
+    if (mInitCheck == OK) {
+        mInitCheck = mImpl->init();
+    }
 }
 
 OggExtractor::~OggExtractor() {
diff --git a/media/libstagefright/codecs/on2/Android.mk b/media/libstagefright/codecs/on2/Android.mk
new file mode 100644
index 0000000..2e431205
--- /dev/null
+++ b/media/libstagefright/codecs/on2/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
new file mode 100644
index 0000000..03dfb75
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+        VPXDecoder.cpp
+
+LOCAL_MODULE := libstagefright_vpxdec
+
+LOCAL_C_INCLUDES := \
+        $(TOP)/frameworks/base/media/libstagefright/include \
+        $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+        $(TOP)/external/libvpx \
+        $(TOP)/external/libvpx/vpx_codec \
+        $(TOP)/external/libvpx/vpx_ports
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
new file mode 100644
index 0000000..bad8956
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "VPXDecoder"
+#include <utils/Log.h>
+
+#include "VPXDecoder.h"
+
+#include <OMX_Component.h>
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include "vpx_codec/vpx_decoder.h"
+#include "vp8/vp8dx.h"
+
+namespace android {
+
+VPXDecoder::VPXDecoder(const sp<MediaSource> &source)
+    : mSource(source),
+      mStarted(false),
+      mBufferSize(0),
+      mCtx(NULL),
+      mBufferGroup(NULL) {
+    sp<MetaData> inputFormat = source->getFormat();
+    const char *mime;
+    CHECK(inputFormat->findCString(kKeyMIMEType, &mime));
+    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_VPX));
+
+    CHECK(inputFormat->findInt32(kKeyWidth, &mWidth));
+    CHECK(inputFormat->findInt32(kKeyHeight, &mHeight));
+
+    mBufferSize = (mWidth * mHeight * 3) / 2;
+
+    mFormat = new MetaData;
+    mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+    mFormat->setInt32(kKeyWidth, mWidth);
+    mFormat->setInt32(kKeyHeight, mHeight);
+    mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+    mFormat->setCString(kKeyDecoderComponent, "VPXDecoder");
+
+    int64_t durationUs;
+    if (inputFormat->findInt64(kKeyDuration, &durationUs)) {
+        mFormat->setInt64(kKeyDuration, durationUs);
+    }
+}
+
+VPXDecoder::~VPXDecoder() {
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t VPXDecoder::start(MetaData *) {
+    if (mStarted) {
+        return UNKNOWN_ERROR;
+    }
+
+    status_t err = mSource->start();
+
+    if (err != OK) {
+        return err;
+    }
+
+    mCtx = new vpx_codec_ctx_t;
+    if (vpx_codec_dec_init(
+                (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0)) {
+        LOGE("on2 decoder failed to initialize.");
+
+        mSource->stop();
+
+        return UNKNOWN_ERROR;
+    }
+
+    mBufferGroup = new MediaBufferGroup;
+    mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+    mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+    mStarted = true;
+
+    return OK;
+}
+
+status_t VPXDecoder::stop() {
+    if (!mStarted) {
+        return UNKNOWN_ERROR;
+    }
+
+    delete mBufferGroup;
+    mBufferGroup = NULL;
+
+    vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
+    delete (vpx_codec_ctx_t *)mCtx;
+    mCtx = NULL;
+
+    mSource->stop();
+
+    mStarted = false;
+
+    return OK;
+}
+
+sp<MetaData> VPXDecoder::getFormat() {
+    return mFormat;
+}
+
+status_t VPXDecoder::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    *out = NULL;
+
+    MediaBuffer *input;
+    status_t err = mSource->read(&input, options);
+
+    if (err != OK) {
+        return err;
+    }
+
+    LOGV("read %d bytes from source\n", input->range_length());
+
+    if (vpx_codec_decode(
+                (vpx_codec_ctx_t *)mCtx,
+                (uint8_t *)input->data() + input->range_offset(),
+                input->range_length(),
+                NULL,
+                0)) {
+        LOGE("on2 decoder failed to decode frame.");
+        input->release();
+        input = NULL;
+
+        return UNKNOWN_ERROR;
+    }
+
+    LOGV("successfully decoded 1 or more frames.");
+
+    int64_t timeUs;
+    CHECK(input->meta_data()->findInt64(kKeyTime, &timeUs));
+
+    input->release();
+    input = NULL;
+
+    vpx_codec_iter_t iter = NULL;
+    vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
+
+    if (img == NULL) {
+        LOGI("on2 decoder did not return a frame.");
+
+        *out = new MediaBuffer(0);
+        return OK;
+    }
+
+    CHECK_EQ(img->fmt, IMG_FMT_I420);
+
+    int32_t width = img->d_w;
+    int32_t height = img->d_h;
+
+    if (width != mWidth || height != mHeight) {
+        LOGI("Image dimensions changed, width = %d, height = %d",
+             width, height);
+
+        mWidth = width;
+        mHeight = height;
+        mFormat->setInt32(kKeyWidth, width);
+        mFormat->setInt32(kKeyHeight, height);
+
+        mBufferSize = (mWidth * mHeight * 3) / 2;
+        delete mBufferGroup;
+        mBufferGroup = new MediaBufferGroup;
+        mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+        mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+        return INFO_FORMAT_CHANGED;
+    }
+
+    MediaBuffer *output;
+    CHECK_EQ(mBufferGroup->acquire_buffer(&output), OK);
+
+    const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
+    uint8_t *dst = (uint8_t *)output->data();
+    for (size_t i = 0; i < img->d_h; ++i) {
+        memcpy(dst, srcLine, img->d_w);
+
+        srcLine += img->stride[PLANE_Y];
+        dst += img->d_w;
+    }
+
+    srcLine = (const uint8_t *)img->planes[PLANE_U];
+    for (size_t i = 0; i < img->d_h / 2; ++i) {
+        memcpy(dst, srcLine, img->d_w / 2);
+
+        srcLine += img->stride[PLANE_U];
+        dst += img->d_w / 2;
+    }
+
+    srcLine = (const uint8_t *)img->planes[PLANE_V];
+    for (size_t i = 0; i < img->d_h / 2; ++i) {
+        memcpy(dst, srcLine, img->d_w / 2);
+
+        srcLine += img->stride[PLANE_V];
+        dst += img->d_w / 2;
+    }
+
+    output->set_range(0, (width * height * 3) / 2);
+
+    output->meta_data()->setInt64(kKeyTime, timeUs);
+
+    *out = output;
+
+    return OK;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/include/VPXDecoder.h b/media/libstagefright/include/VPXDecoder.h
new file mode 100644
index 0000000..550c612
--- /dev/null
+++ b/media/libstagefright/include/VPXDecoder.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VPX_DECODER_H_
+
+#define VPX_DECODER_H_
+
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct VPXDecoder : public MediaSource {
+    VPXDecoder(const sp<MediaSource> &source);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+protected:
+    virtual ~VPXDecoder();
+
+private:
+    sp<MediaSource> mSource;
+    bool mStarted;
+    int32_t mWidth, mHeight;
+    size_t mBufferSize;
+
+    void *mCtx;
+    MediaBufferGroup *mBufferGroup;
+
+    sp<MetaData> mFormat;
+
+    VPXDecoder(const VPXDecoder &);
+    VPXDecoder &operator=(const VPXDecoder &);
+};
+
+}  // namespace android
+
+#endif  // VPX_DECODER_H_
+
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 552bed4..cbbc7be 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -494,15 +494,23 @@
              * argv8 - Max SCB
              */
             String str = String.format("softap set " + wlanIface + " " + softapIface +
-                                       " \"%s\" %s %s", wifiConfig.SSID,
+                                       " %s %s %s", convertQuotedString(wifiConfig.SSID),
                                        wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
                                        "wpa2-psk" : "open",
-                                       wifiConfig.preSharedKey);
+                                       convertQuotedString(wifiConfig.preSharedKey));
             mConnector.doCommand(str);
         }
         mConnector.doCommand(String.format("softap startap"));
     }
 
+    private String convertQuotedString(String s) {
+        if (s == null) {
+            return s;
+        }
+        /* Replace \ with \\, then " with \" and add quotes at end */
+        return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"';
+    }
+
     public void stopAccessPoint() throws IllegalStateException {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
@@ -521,10 +529,10 @@
             mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
         } else {
             String str = String.format("softap set " + wlanIface + " " + softapIface +
-                                       " \"%s\" %s %s", wifiConfig.SSID,
+                                       " %s %s %s", convertQuotedString(wifiConfig.SSID),
                                        wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
                                        "wpa2-psk" : "open",
-                                       wifiConfig.preSharedKey);
+                                       convertQuotedString(wifiConfig.preSharedKey));
             mConnector.doCommand(str);
         }
     }