Merge "add more logging into DRT"
diff --git a/core/java/android/widget/MultiAutoCompleteTextView.java b/core/java/android/widget/MultiAutoCompleteTextView.java
index 02c1ec7..134e4c4 100644
--- a/core/java/android/widget/MultiAutoCompleteTextView.java
+++ b/core/java/android/widget/MultiAutoCompleteTextView.java
@@ -30,7 +30,7 @@
  * can show completion suggestions for the substring of the text where
  * the user is typing instead of necessarily for the entire thing.
  * <p>
- * You must must provide a {@link Tokenizer} to distinguish the
+ * You must provide a {@link Tokenizer} to distinguish the
  * various substrings.
  *
  * <p>The following code snippet shows how to create a text view which suggests
@@ -41,7 +41,7 @@
  *     protected void onCreate(Bundle savedInstanceState) {
  *         super.onCreate(savedInstanceState);
  *         setContentView(R.layout.autocomplete_7);
- * 
+ *
  *         ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;String&gt;(this,
  *                 android.R.layout.simple_dropdown_item_1line, COUNTRIES);
  *         MultiAutoCompleteTextView textView = (MultiAutoCompleteTextView) findViewById(R.id.edit);
@@ -132,7 +132,7 @@
      * Instead of validating the entire text, this subclass method validates
      * each token of the text individually.  Empty tokens are removed.
      */
-    @Override 
+    @Override
     public void performValidation() {
         Validator v = getValidator();
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 445f4b5..2eaedaa 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -320,8 +320,7 @@
     }
     jint id = (jint)rsElementCreate2(con,
                                      (RsElement *)ids, fieldCount,
-                                     nameArray, fieldCount,
-                                     sizeArray, fieldCount,
+                                     nameArray, fieldCount * sizeof(size_t),  sizeArray,
                                      (const uint32_t *)arraySizes, fieldCount);
     for (int ct=0; ct < fieldCount; ct++) {
         jstring s = (jstring)_env->GetObjectArrayElement(_names, ct);
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index c336c0d..ef00b30 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -91,6 +91,7 @@
 	rsDevice.cpp \
 	rsElement.cpp \
 	rsFBOCache.cpp \
+	rsFifoSocket.cpp \
 	rsFileA3D.cpp \
 	rsFont.cpp \
 	rsLocklessFifo.cpp \
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 5370e25..00e3a0a 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -176,7 +176,6 @@
 ElementCreate2 {
 	param const RsElement * elements
 	param const char ** names
-	param const size_t * nameLengths
 	param const uint32_t * arraySize
 	ret RsElement
 	}
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index d5d5ca5..2b58e9e 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -347,13 +347,15 @@
     return (RsElement)e;
 }
 
+
 RsElement rsi_ElementCreate2(Context *rsc,
                              const RsElement * ein,
                              size_t ein_length,
+
                              const char ** names,
-                             size_t names_length,
-                             const size_t * nameLengths,
                              size_t nameLengths_length,
+                             const size_t * nameLengths,
+
                              const uint32_t * arraySizes,
                              size_t arraySizes_length) {
     const Element *e = Element::create(rsc, ein_length, (const Element **)ein, names, nameLengths, arraySizes);
diff --git a/libs/rs/rsFifo.cpp b/libs/rs/rsFifo.cpp
new file mode 100644
index 0000000..3d5d8c4
--- /dev/null
+++ b/libs/rs/rsFifo.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "rsFifoSocket.h"
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+Fifo::Fifo() {
+
+}
+
+Fifo::~Fifo() {
+
+}
+
diff --git a/libs/rs/rsFifo.h b/libs/rs/rsFifo.h
new file mode 100644
index 0000000..f924b95
--- /dev/null
+++ b/libs/rs/rsFifo.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 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_RS_FIFO_H
+#define ANDROID_RS_FIFO_H
+
+
+#include "rsUtils.h"
+
+namespace android {
+namespace renderscript {
+
+
+// A simple FIFO to be used as a producer / consumer between two
+// threads.  One is writer and one is reader.  The common cases
+// will not require locking.  It is not threadsafe for multiple
+// readers or writers by design.
+
+class Fifo {
+protected:
+    Fifo();
+    virtual ~Fifo();
+
+public:
+    void virtual writeAsync(const void *data, size_t bytes) = 0;
+    void virtual writeWaitReturn(void *ret, size_t retSize) = 0;
+    size_t virtual read(void *data, size_t bytes) = 0;
+    void virtual readReturn(const void *data, size_t bytes) = 0;
+
+    void virtual flush() = 0;
+
+};
+
+}
+}
+#endif
diff --git a/libs/rs/rsFifoSocket.cpp b/libs/rs/rsFifoSocket.cpp
new file mode 100644
index 0000000..1ce57b9
--- /dev/null
+++ b/libs/rs/rsFifoSocket.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "rsFifoSocket.h"
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+FifoSocket::FifoSocket() {
+    sequence = 1;
+}
+
+FifoSocket::~FifoSocket() {
+
+}
+
+bool FifoSocket::init() {
+    int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
+    return false;
+}
+
+void FifoSocket::shutdown() {
+}
+
+void FifoSocket::writeAsync(const void *data, size_t bytes) {
+    size_t ret = ::write(sv[0], data, bytes);
+    rsAssert(ret == bytes);
+}
+
+void FifoSocket::writeWaitReturn(void *retData, size_t retBytes) {
+    size_t ret = ::read(sv[1], retData, retBytes);
+    rsAssert(ret == retBytes);
+}
+
+size_t FifoSocket::read(void *data, size_t bytes) {
+    size_t ret = ::read(sv[0], data, bytes);
+    rsAssert(ret == bytes);
+    return ret;
+}
+
+void FifoSocket::readReturn(const void *data, size_t bytes) {
+    size_t ret = ::write(sv[1], data, bytes);
+    rsAssert(ret == bytes);
+}
+
+
+void FifoSocket::flush() {
+}
+
+
diff --git a/libs/rs/rsFifoSocket.h b/libs/rs/rsFifoSocket.h
new file mode 100644
index 0000000..7df2b67
--- /dev/null
+++ b/libs/rs/rsFifoSocket.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 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_RS_FIFO_SOCKET_H
+#define ANDROID_RS_FIFO_SOCKET_H
+
+
+#include "rsFifo.h"
+
+namespace android {
+namespace renderscript {
+
+
+class FifoSocket {
+public:
+    FifoSocket();
+    virtual ~FifoSocket();
+
+    bool init();
+    void shutdown();
+
+
+
+    void virtual writeAsync(const void *data, size_t bytes);
+    void virtual writeWaitReturn(void *ret, size_t retSize);
+    size_t virtual read(void *data, size_t bytes);
+    void virtual readReturn(const void *data, size_t bytes);
+
+    void virtual flush();
+
+protected:
+    int sv[2];
+    uint32_t sequence;
+
+
+};
+
+}
+}
+
+#endif
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 1d8b9b5..d550712 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -189,6 +189,7 @@
     fprintf(f, "#include \"rsThreadIO.h\"\n");
     //fprintf(f, "#include \"rsgApiStructs.h\"\n");
     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
+    fprintf(f, "#include \"rsFifo.h\"\n");
     fprintf(f, "\n");
     fprintf(f, "using namespace android;\n");
     fprintf(f, "using namespace android::renderscript;\n");
@@ -290,11 +291,103 @@
 
             if (api->ret.typeName[0]) {
                 fprintf(f, "    return reinterpret_cast<");
-                printVarTypeAndName(f, &api->ret);
+                printVarType(f, &api->ret);
                 fprintf(f, ">(io->mToCoreRet);\n");
             }
         }
         fprintf(f, "};\n\n");
+
+
+        fprintf(f, "static ");
+        printFuncDecl(f, api, "RF_", 0, 0);
+        fprintf(f, "\n{\n");
+        fprintf(f, "    Fifo *f = NULL;\n");
+        fprintf(f, "    RS_CMD_%s cmd;\n", api->name);
+        fprintf(f, "    const uint32_t cmdSize = sizeof(cmd);\n");
+        fprintf(f, "    const uint32_t cmdID = RS_CMD_ID_%s;\n", api->name);
+        fprintf(f, "    f->writeAsync(&cmdID, sizeof(cmdID));\n");
+
+        if (api->handcodeApi) {
+            fprintf(f, "    rsHCAPI_%s(rsc", api->name);
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                if (ct2 > 0 || !api->nocontext) {
+                    fprintf(f, ", ");
+                }
+                fprintf(f, "%s", vt->name);
+            }
+            fprintf(f, ");\n");
+        } else {
+            fprintf(f, "    intptr_t offset = cmdSize;\n");
+            fprintf(f, "    uint32_t dataSize = 0;\n");
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                if (vt->isConst && vt->ptrLevel) {
+                    switch(vt->ptrLevel) {
+                    case 1:
+                        fprintf(f, "    dataSize += %s_length;\n", vt->name);
+                        break;
+                    case 2:
+                        fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+                        fprintf(f, "        dataSize += %s_length[ct];\n", vt->name);
+                        fprintf(f, "    }\n");
+                        break;
+                    default:
+                        printf("pointer level not handled!!");
+                    }
+                }
+            }
+            fprintf(f, "\n");
+
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                switch(vt->ptrLevel) {
+                case 0:
+                    fprintf(f, "    cmd.%s = %s;\n", vt->name, vt->name);
+                    break;
+                case 1:
+                    fprintf(f, "    cmd.%s = (", vt->name);
+                    printVarType(f, vt);
+                    fprintf(f, ")offset;\n");
+                    fprintf(f, "    offset += %s_length;\n", vt->name);
+                    break;
+                case 2:
+                    fprintf(f, "    cmd.%s = (", vt->name);
+                    printVarType(f, vt);
+                    fprintf(f, ")offset;\n");
+                    fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+                    fprintf(f, "        offset += %s_length[ct];\n", vt->name);
+                    fprintf(f, "    }\n");
+                    break;
+                default:
+                    printf("pointer level not handled!!");
+                }
+            }
+            fprintf(f, "\n");
+
+            fprintf(f, "    f->writeAsync(&cmd, cmdSize);\n");
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                if (vt->ptrLevel == 1) {
+                    fprintf(f, "    f->writeAsync(%s, %s_length);\n", vt->name, vt->name);
+                }
+                if (vt->ptrLevel == 2) {
+                    fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+                    fprintf(f, "        f->writeAsync(%s, %s_length[ct]);\n", vt->name, vt->name);
+                    fprintf(f, "        offset += %s_length[ct];\n", vt->name);
+                    fprintf(f, "    }\n");
+                }
+            }
+
+            if (api->ret.typeName[0]) {
+                fprintf(f, "    ");
+                printVarType(f, &api->ret);
+                fprintf(f, " retValue;\n");
+                fprintf(f, "    f->writeWaitReturn(&retValue, sizeof(retValue));\n");
+                fprintf(f, "    return retValue;\n");
+            }
+        }
+        fprintf(f, "}\n\n");
     }
 
     fprintf(f, "\n");
@@ -304,8 +397,14 @@
     }
     fprintf(f, "};\n");
 
-    fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
+    fprintf(f, "\n");
+    fprintf(f, "static RsApiEntrypoints_t s_RemoteTable = {\n");
+    for (ct=0; ct < apiCount; ct++) {
+        fprintf(f, "    RF_%s,\n", apis[ct].name);
+    }
+    fprintf(f, "};\n");
 
+    fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
     for (ct=0; ct < apiCount; ct++) {
         int needFlush = 0;
         const ApiEntry * api = &apis[ct];
@@ -357,8 +456,7 @@
             continue;
         }
 
-        fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes)\n", api->name);
-        fprintf(f, "{\n");
+        fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
 
         //fprintf(f, "    LOGE(\"play command %s\\n\");\n", api->name);
         fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
@@ -377,7 +475,63 @@
         fprintf(f, "};\n\n");
     }
 
-    fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
+    for (ct=0; ct < apiCount; ct++) {
+        const ApiEntry * api = &apis[ct];
+
+        fprintf(f, "void rspr_%s(Context *con, Fifo *f, uint8_t *scratch, size_t scratchSize) {\n", api->name);
+
+        //fprintf(f, "    LOGE(\"play command %s\\n\");\n", api->name);
+        fprintf(f, "    RS_CMD_%s cmd;\n", api->name);
+        fprintf(f, "    f->read(&cmd, sizeof(cmd));\n");
+
+        for (ct2=0; ct2 < api->paramCount; ct2++) {
+            const VarType *vt = &api->params[ct2];
+            if (vt->ptrLevel == 1) {
+                fprintf(f, "    cmd.%s = (", vt->name);
+                printVarType(f, vt);
+                fprintf(f, ")scratch;\n");
+                fprintf(f, "    f->read(scratch, cmd.%s_length);\n", vt->name);
+                fprintf(f, "    scratch += cmd.%s_length;\n", vt->name);
+            }
+            if (vt->ptrLevel == 2) {
+                fprintf(f, "    size_t sum_%s = 0;\n", vt->name);
+                fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
+                fprintf(f, "        ((size_t *)scratch)[ct] = cmd.%s_length[ct];\n", vt->name);
+                fprintf(f, "        sum_%s += cmd.%s_length[ct];\n", vt->name, vt->name);
+                fprintf(f, "    }\n");
+                fprintf(f, "    f->read(scratch, sum_%s);\n", vt->name);
+                fprintf(f, "    scratch += sum_%s;\n", vt->name);
+            }
+        }
+        fprintf(f, "\n");
+
+        if (api->ret.typeName[0]) {
+            fprintf(f, "    ");
+            printVarType(f, &api->ret);
+            fprintf(f, " ret =\n");
+        }
+
+        fprintf(f, "    rsi_%s(", api->name);
+        if (!api->nocontext) {
+            fprintf(f, "con");
+        }
+        for (ct2=0; ct2 < api->paramCount; ct2++) {
+            const VarType *vt = &api->params[ct2];
+            if (ct2 > 0 || !api->nocontext) {
+                fprintf(f, ",\n");
+            }
+            fprintf(f, "           cmd.%s", vt->name);
+        }
+        fprintf(f, ");\n");
+
+        if (api->ret.typeName[0]) {
+            fprintf(f, "    f->readReturn(&ret, sizeof(ret));\n");
+        }
+
+        fprintf(f, "};\n\n");
+    }
+
+    fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
     fprintf(f, "    NULL,\n");
     for (ct=0; ct < apiCount; ct++) {
         if (apis[ct].direct) {
@@ -388,6 +542,13 @@
     }
     fprintf(f, "};\n");
 
+    fprintf(f, "RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i] = {\n", apiCount + 1);
+    fprintf(f, "    NULL,\n");
+    for (ct=0; ct < apiCount; ct++) {
+        fprintf(f, "    %s%s,\n", "rspr_", apis[ct].name);
+    }
+    fprintf(f, "};\n");
+
     fprintf(f, "};\n");
     fprintf(f, "};\n");
 }
@@ -422,14 +583,21 @@
         {
             fprintf(f, "\n");
             fprintf(f, "#include \"rsContext.h\"\n");
+            fprintf(f, "#include \"rsFifo.h\"\n");
             fprintf(f, "\n");
             fprintf(f, "namespace android {\n");
             fprintf(f, "namespace renderscript {\n");
             printStructures(f);
             printFuncDecls(f, "rsi_", 1);
             printPlaybackFuncs(f, "rsp_");
-            fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *, size_t sizeBytes);\n");
-            fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[%i];\n", apiCount + 1);
+            fprintf(f, "\n\ntypedef struct RsPlaybackRemoteHeaderRec {\n");
+            fprintf(f, "    uint32_t command;\n");
+            fprintf(f, "    uint32_t size;\n");
+            fprintf(f, "} RsPlaybackRemoteHeader;\n\n");
+            fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
+            fprintf(f, "typedef void (*RsPlaybackRemoteFunc)(Context *, Fifo *, uint8_t *scratch, size_t scratchSize);\n");
+            fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
+            fprintf(f, "extern RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i];\n", apiCount + 1);
 
             fprintf(f, "}\n");
             fprintf(f, "}\n");
diff --git a/libs/rs/spec.l b/libs/rs/spec.l
index dcd4435..a24bfd3 100644
--- a/libs/rs/spec.l
+++ b/libs/rs/spec.l
@@ -21,15 +21,26 @@
    int typeNextState;
 
    void checkPointerType() {
-       VarType *lastType = currType;
-       if (lastType->ptrLevel) {
+       VarType *baseType = currType;
+       int curPtrLevel = 0;
+       while (curPtrLevel < baseType->ptrLevel) {
            currType = &apis[apiCount].params[apis[apiCount].paramCount];
            currType->type = 4;
+           currType->ptrLevel = curPtrLevel;
+           if (currType->ptrLevel > 0) {
+              currType->isConst = 1;
+           }
            sprintf(currType->typeName, "%s", "size_t");
-           if (lastType->name[0]) {
-               sprintf(currType->name, "%s_length", lastType->name);
+           switch(baseType->ptrLevel - curPtrLevel) {
+           case 1:
+              sprintf(currType->name, "%s_length", baseType->name);
+              break;
+           case 2:
+              sprintf(currType->name, "%s_length_length", baseType->name);
+              break;
            }
            apis[apiCount].paramCount++;
+           curPtrLevel ++;
        }
    }
 
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 69f9c23..dd69e6b 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -84,7 +84,13 @@
 
     CHECK(mFirstBuffer == NULL);
 
-    mFirstBufferResult = mSource->read(&mFirstBuffer);
+    MediaSource::ReadOptions options;
+    if (mSeeking) {
+        options.setSeekTo(mSeekTimeUs);
+        mSeeking = false;
+    }
+
+    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
     if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
         LOGV("INFO_FORMAT_CHANGED!!!");
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index cccd0b7..dcc268f 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -831,6 +831,8 @@
     if (!(mFlags & AUDIOPLAYER_STARTED)) {
         mFlags |= AUDIOPLAYER_STARTED;
 
+        bool wasSeeking = mAudioPlayer->isSeeking();
+
         // We've already started the MediaSource in order to enable
         // the prefetcher to read its data.
         status_t err = mAudioPlayer->start(
@@ -840,6 +842,13 @@
             notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
             return err;
         }
+
+        if (wasSeeking) {
+            CHECK(!mAudioPlayer->isSeeking());
+
+            // We will have finished the seek while starting the audio player.
+            postAudioSeekComplete_l();
+        }
     } else {
         mAudioPlayer->resume();
     }
@@ -1957,6 +1966,10 @@
 
 void AwesomePlayer::postAudioSeekComplete() {
     Mutex::Autolock autoLock(mLock);
+    postAudioSeekComplete_l();
+}
+
+void AwesomePlayer::postAudioSeekComplete_l() {
     postCheckAudioStatusEvent_l(0 /* delayUs */);
 }
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index fd3ddf7..835d2bb 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -281,6 +281,7 @@
     void ensureCacheIsFetching_l();
 
     status_t startAudioPlayer_l();
+    void postAudioSeekComplete_l();
 
     void shutdownVideoDecoder_l();
     void setNativeWindow_l(const sp<ANativeWindow> &native);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 6e1093f..de439ca 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -2855,8 +2855,8 @@
     }
 
     private File getDataPathForPackage(String packageName, int userId) {
-        return new File(mUserAppDataDir.getAbsolutePath() + File.separator
-                    + userId + File.separator + packageName);
+        return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
+                + File.separator + packageName);
     }
 
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
@@ -3319,36 +3319,42 @@
              *        only for non-system apps and system app upgrades.
              */
             if (pkg.applicationInfo.nativeLibraryDir != null) {
-                final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
-                final String dataPathString = dataPath.getPath();
+                try {
+                    final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+                    final String dataPathString = dataPath.getCanonicalFile().getPath();
 
-                if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
-                    /*
-                     * Upgrading from a previous version of the OS sometimes
-                     * leaves native libraries in the /data/data/<app>/lib
-                     * directory for system apps even when they shouldn't be.
-                     * Recent changes in the JNI library search path
-                     * necessitates we remove those to match previous behavior.
-                     */
-                    if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
-                        Log.i(TAG, "removed obsolete native libraries for system package " + path);
+                    if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+                        /*
+                         * Upgrading from a previous version of the OS sometimes
+                         * leaves native libraries in the /data/data/<app>/lib
+                         * directory for system apps even when they shouldn't be.
+                         * Recent changes in the JNI library search path
+                         * necessitates we remove those to match previous behavior.
+                         */
+                        if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
+                            Log.i(TAG, "removed obsolete native libraries for system package "
+                                    + path);
+                        }
+                    } else if (nativeLibraryDir.getCanonicalFile().getParent()
+                            .equals(dataPathString)) {
+                        /*
+                         * If this is an internal application or our
+                         * nativeLibraryPath points to our data directory, unpack
+                         * the libraries. The native library path pointing to the
+                         * data directory for an application in an ASEC container
+                         * can happen for older apps that existed before an OTA to
+                         * Gingerbread.
+                         */
+                        Slog.i(TAG, "Unpacking native libraries for " + path);
+                        mInstaller.unlinkNativeLibraryDirectory(dataPathString);
+                        NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
+                    } else {
+                        Slog.i(TAG, "Linking native library dir for " + path);
+                        mInstaller.linkNativeLibraryDirectory(dataPathString,
+                                pkg.applicationInfo.nativeLibraryDir);
                     }
-                } else if (nativeLibraryDir.getParent().equals(dataPathString)) {
-                    /*
-                     * If this is an internal application or our
-                     * nativeLibraryPath points to our data directory, unpack
-                     * the libraries. The native library path pointing to the
-                     * data directory for an application in an ASEC container
-                     * can happen for older apps that existed before an OTA to
-                     * Gingerbread.
-                     */
-                    Slog.i(TAG, "Unpacking native libraries for " + path);
-                    mInstaller.unlinkNativeLibraryDirectory(dataPathString);
-                    NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
-                } else {
-                    Slog.i(TAG, "Linking native library dir for " + path);
-                    mInstaller.linkNativeLibraryDirectory(dataPathString,
-                            pkg.applicationInfo.nativeLibraryDir);
+                } catch (IOException ioe) {
+                    Log.e(TAG, "Unable to get canonical file " + ioe.toString());
                 }
             }
             pkg.mScanPath = path;