Merge "async find-on-page implementation via WebKit"
diff --git a/drm/java/android/drm/DrmInfo.java b/drm/java/android/drm/DrmInfo.java
index 8812bfe..22d06c7 100755
--- a/drm/java/android/drm/DrmInfo.java
+++ b/drm/java/android/drm/DrmInfo.java
@@ -49,6 +49,13 @@
         mInfoType = infoType;
         mMimeType = mimeType;
         mData = data;
+        if (!isValid()) {
+            final String msg = "infoType: " + infoType + "," +
+                               "mimeType: " + mimeType + "," +
+                               "data: " + data;
+
+            throw new IllegalArgumentException(msg);
+        }
     }
 
     /**
@@ -69,6 +76,13 @@
             // call would fail with IllegalArgumentException because of mData = null
             mData = null;
         }
+        if (!isValid()) {
+            final String msg = "infoType: " + infoType + "," +
+                               "mimeType: " + mimeType + "," +
+                               "data: " + mData;
+
+            throw new IllegalArgumentException();
+        }
     }
 
     /**
diff --git a/drm/java/android/drm/DrmInfoRequest.java b/drm/java/android/drm/DrmInfoRequest.java
index 1429fa5..621da41 100755
--- a/drm/java/android/drm/DrmInfoRequest.java
+++ b/drm/java/android/drm/DrmInfoRequest.java
@@ -67,6 +67,11 @@
     public DrmInfoRequest(int infoType, String mimeType) {
         mInfoType = infoType;
         mMimeType = mimeType;
+        if (!isValid()) {
+            final String msg = "infoType: " + infoType + "," +
+                               "mimeType: " + mimeType;
+            throw new IllegalArgumentException(msg);
+        }
     }
 
     /**
diff --git a/drm/java/android/drm/DrmInfoStatus.java b/drm/java/android/drm/DrmInfoStatus.java
index 5c12ae3..2fe0a78 100755
--- a/drm/java/android/drm/DrmInfoStatus.java
+++ b/drm/java/android/drm/DrmInfoStatus.java
@@ -56,6 +56,10 @@
      * @param _mimeType The MIME type.
      */
     public DrmInfoStatus(int _statusCode, int _infoType, ProcessedData _data, String _mimeType) {
+        if (!DrmInfoRequest.isValidType(_infoType)) {
+            throw new IllegalArgumentException("infoType: " + _infoType);
+        }
+
         statusCode = _statusCode;
         infoType = _infoType;
         data = _data;
diff --git a/drm/java/android/drm/DrmRights.java b/drm/java/android/drm/DrmRights.java
index ef9c21d..d4afed1 100755
--- a/drm/java/android/drm/DrmRights.java
+++ b/drm/java/android/drm/DrmRights.java
@@ -103,6 +103,11 @@
         }
 
         mMimeType = mimeType;
+        if (!isValid()) {
+            final String msg = "mimeType: " + mMimeType + "," +
+                               "data: " + mData;
+            throw new IllegalArgumentException(msg);
+        }
     }
 
     /**
@@ -117,17 +122,25 @@
             mData = data.getData();
 
             String accountId = data.getAccountId();
-            if (null != accountId && !accountId.equals("")) {
-                mAccountId = accountId;
+            if (null == accountId || !accountId.equals("")) {
+                throw new IllegalArgumentException("accountId: " + accountId);
             }
+            mAccountId = accountId;
 
             String subscriptionId = data.getSubscriptionId();
-            if (null != subscriptionId && !subscriptionId.equals("")) {
-                mSubscriptionId = subscriptionId;
+            if (null == subscriptionId || !subscriptionId.equals("")) {
+                throw new IllegalArgumentException(
+                            "subscriptionId: " + subscriptionId);
             }
+            mSubscriptionId = subscriptionId;
         }
 
         mMimeType = mimeType;
+        if (!isValid()) {
+            final String msg = "mimeType: " + mMimeType + "," +
+                               "data: " + mData;
+            throw new IllegalArgumentException(msg);
+        }
     }
 
     /**
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 79437bf..f5466e8 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -95,6 +95,7 @@
         int32_t startFrame, int32_t rampDurationFrames,
         uint8_t *data,   size_t bytes);
 
+    void queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs);
     void releaseQueuedFrames_l();
     void waitOutstandingEncodingFrames_l();
     status_t reset();
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index fef2a00..5b2ea1f 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -282,8 +282,6 @@
         mPrevSampleTimeUs = mStartTimeUs;
     }
 
-    int64_t timestampUs = mPrevSampleTimeUs;
-
     size_t numLostBytes = 0;
     if (mNumFramesReceived > 0) {  // Ignore earlier frame lost
         // getInputFramesLost() returns the number of lost frames.
@@ -293,37 +291,58 @@
 
     CHECK_EQ(numLostBytes & 1, 0u);
     CHECK_EQ(audioBuffer.size & 1, 0u);
-    size_t bufferSize = numLostBytes + audioBuffer.size;
-    MediaBuffer *buffer = new MediaBuffer(bufferSize);
     if (numLostBytes > 0) {
-        memset(buffer->data(), 0, numLostBytes);
-        memcpy((uint8_t *) buffer->data() + numLostBytes,
-                    audioBuffer.i16, audioBuffer.size);
-    } else {
-        if (audioBuffer.size == 0) {
-            ALOGW("Nothing is available from AudioRecord callback buffer");
-            buffer->release();
-            return OK;
-        }
-        memcpy((uint8_t *) buffer->data(),
-                audioBuffer.i16, audioBuffer.size);
+        // Loss of audio frames should happen rarely; thus the LOGW should
+        // not cause a logging spam
+        ALOGW("Lost audio record data: %d bytes", numLostBytes);
     }
 
+    while (numLostBytes > 0) {
+        size_t bufferSize = numLostBytes;
+        if (numLostBytes > kMaxBufferSize) {
+            numLostBytes -= kMaxBufferSize;
+            bufferSize = kMaxBufferSize;
+        } else {
+            numLostBytes = 0;
+        }
+        MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize);
+        memset(lostAudioBuffer->data(), 0, bufferSize);
+        lostAudioBuffer->set_range(0, bufferSize);
+        queueInputBuffer_l(lostAudioBuffer, timeUs);
+    }
+
+    if (audioBuffer.size == 0) {
+        ALOGW("Nothing is available from AudioRecord callback buffer");
+        return OK;
+    }
+
+    const size_t bufferSize = audioBuffer.size;
+    MediaBuffer *buffer = new MediaBuffer(bufferSize);
+    memcpy((uint8_t *) buffer->data(),
+            audioBuffer.i16, audioBuffer.size);
     buffer->set_range(0, bufferSize);
-    timestampUs += ((1000000LL * (bufferSize >> 1)) +
-                    (mSampleRate >> 1)) / mSampleRate;
+    queueInputBuffer_l(buffer, timeUs);
+    return OK;
+}
+
+void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) {
+    const size_t bufferSize = buffer->range_length();
+    const size_t frameSize = mRecord->frameSize();
+    const int64_t timestampUs =
+                mPrevSampleTimeUs +
+                    ((1000000LL * (bufferSize / frameSize)) +
+                        (mSampleRate >> 1)) / mSampleRate;
 
     if (mNumFramesReceived == 0) {
         buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
     }
+
     buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
     buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
     mPrevSampleTimeUs = timestampUs;
-    mNumFramesReceived += buffer->range_length() / sizeof(int16_t);
+    mNumFramesReceived += bufferSize / frameSize;
     mBuffersReceived.push_back(buffer);
     mFrameAvailableCondition.signal();
-
-    return OK;
 }
 
 void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {