Merge "MountService: Move boot-time mount to a thread - avoids ANR at boot"
diff --git a/core/java/android/webkit/DateSorter.java b/core/java/android/webkit/DateSorter.java
index 16feaa9..bc135046 100644
--- a/core/java/android/webkit/DateSorter.java
+++ b/core/java/android/webkit/DateSorter.java
@@ -26,7 +26,7 @@
  * Sorts dates into the following groups:
  *   Today
  *   Yesterday
- *   five days ago
+ *   seven days ago
  *   one month ago
  *   older than a month ago
  */
@@ -41,7 +41,7 @@
     private long [] mBins = new long[DAY_COUNT-1];
     private String [] mLabels = new String[DAY_COUNT];
     
-    private static final int NUM_DAYS_AGO = 5;
+    private static final int NUM_DAYS_AGO = 7;
 
     /**
      * @param context Application context
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
index d12d828..4565b756 100755
--- a/core/java/android/webkit/GeolocationPermissions.java
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -23,6 +23,7 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.Vector;
 
 
 /**
@@ -61,11 +62,8 @@
     private Handler mHandler;
     private Handler mUIHandler;
 
-    // Members used to transfer the origins and permissions between threads.
-    private Set<String> mOrigins;
-    private boolean mAllowed;
-    private Set<String> mOriginsToClear;
-    private Set<String> mOriginsToAllow;
+    // A queue to store messages until the handler is ready.
+    private Vector<Message> mQueuedMessages;
 
     // Message ids
     static final int GET_ORIGINS = 0;
@@ -126,7 +124,7 @@
      * Creates the message handler. Must be called on the WebKit thread.
      * @hide
      */
-    public void createHandler() {
+    public synchronized void createHandler() {
         if (mHandler == null) {
             mHandler = new Handler() {
                 @Override
@@ -134,21 +132,21 @@
                     // Runs on the WebKit thread.
                     switch (msg.what) {
                         case GET_ORIGINS: {
-                            getOriginsImpl();
+                            Set origins = nativeGetOrigins();
                             ValueCallback callback = (ValueCallback) msg.obj;
                             Map values = new HashMap<String, Object>();
                             values.put(CALLBACK, callback);
-                            values.put(ORIGINS, mOrigins);
+                            values.put(ORIGINS, origins);
                             postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
                             } break;
                         case GET_ALLOWED: {
                             Map values = (Map) msg.obj;
                             String origin = (String) values.get(ORIGIN);
                             ValueCallback callback = (ValueCallback) values.get(CALLBACK);
-                            getAllowedImpl(origin);
+                            boolean allowed = nativeGetAllowed(origin);
                             Map retValues = new HashMap<String, Object>();
                             retValues.put(CALLBACK, callback);
-                            retValues.put(ALLOWED, new Boolean(mAllowed));
+                            retValues.put(ALLOWED, new Boolean(allowed));
                             postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues));
                             } break;
                         case CLEAR:
@@ -164,15 +162,12 @@
                 }
             };
 
-            if (mOriginsToClear != null) {
-                for (String origin : mOriginsToClear) {
-                    nativeClear(origin);
+            // Handle the queued messages
+            if (mQueuedMessages != null) {
+                while (!mQueuedMessages.isEmpty()) {
+                    mHandler.sendMessage(mQueuedMessages.remove(0));
                 }
-            }
-            if (mOriginsToAllow != null) {
-                for (String origin : mOriginsToAllow) {
-                    nativeAllow(origin);
-                }
+                mQueuedMessages = null;
             }
         }
     }
@@ -180,9 +175,15 @@
     /**
      * Utility function to send a message to our handler.
      */
-    private void postMessage(Message msg) {
-        assert(mHandler != null);
-        mHandler.sendMessage(msg);
+    private synchronized void postMessage(Message msg) {
+        if (mHandler == null) {
+            if (mQueuedMessages == null) {
+                mQueuedMessages = new Vector<Message>();
+            }
+            mQueuedMessages.add(msg);
+        } else {
+            mHandler.sendMessage(msg);
+        }
     }
 
     /**
@@ -207,8 +208,8 @@
     public void getOrigins(ValueCallback<Set<String> > callback) {
         if (callback != null) {
             if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
-                getOriginsImpl();
-                callback.onReceiveValue(mOrigins);
+                Set origins = nativeGetOrigins();
+                callback.onReceiveValue(origins);
             } else {
                 postMessage(Message.obtain(null, GET_ORIGINS, callback));
             }
@@ -216,14 +217,6 @@
     }
 
     /**
-     * Helper method to get the set of origins.
-     */
-    private void getOriginsImpl() {
-        // Called on the WebKit thread.
-        mOrigins = nativeGetOrigins();
-    }
-
-    /**
      * Gets the permission state for the specified origin.
      *
      * Callback is a ValueCallback object whose onReceiveValue method will be
@@ -238,8 +231,8 @@
             return;
         }
         if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
-            getAllowedImpl(origin);
-            callback.onReceiveValue(new Boolean(mAllowed));
+            boolean allowed = nativeGetAllowed(origin);
+            callback.onReceiveValue(new Boolean(allowed));
         } else {
             Map values = new HashMap<String, Object>();
             values.put(ORIGIN, origin);
@@ -249,31 +242,13 @@
     }
 
     /**
-     * Helper method to get the permission state for the specified origin.
-     */
-    private void getAllowedImpl(String origin) {
-        // Called on the WebKit thread.
-        mAllowed = nativeGetAllowed(origin);
-    }
-
-    /**
      * Clears the permission state for the specified origin. This method may be
      * called before the WebKit thread has intialized the message handler.
      * Messages will be queued until this time.
      */
     public void clear(String origin) {
         // Called on the UI thread.
-        if (mHandler == null) {
-            if (mOriginsToClear == null) {
-                mOriginsToClear = new HashSet<String>();
-            }
-            mOriginsToClear.add(origin);
-            if (mOriginsToAllow != null) {
-                mOriginsToAllow.remove(origin);
-            }
-        } else {
-            postMessage(Message.obtain(null, CLEAR, origin));
-        }
+        postMessage(Message.obtain(null, CLEAR, origin));
     }
 
     /**
@@ -283,17 +258,7 @@
      */
     public void allow(String origin) {
         // Called on the UI thread.
-        if (mHandler == null) {
-            if (mOriginsToAllow == null) {
-                mOriginsToAllow = new HashSet<String>();
-            }
-            mOriginsToAllow.add(origin);
-            if (mOriginsToClear != null) {
-                mOriginsToClear.remove(origin);
-            }
-        } else {
-            postMessage(Message.obtain(null, ALLOW, origin));
-        }
+        postMessage(Message.obtain(null, ALLOW, origin));
     }
 
     /**
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index cf71a84..9314d7b 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -146,7 +146,7 @@
      * @hide
      * Message handler, webcore side
      */
-    public void createHandler() {
+    public synchronized void createHandler() {
         if (mHandler == null) {
             mHandler = new Handler() {
                 @Override
@@ -342,7 +342,7 @@
     /**
      * Utility function to send a message to our handler
      */
-    private void postMessage(Message msg) {
+    private synchronized void postMessage(Message msg) {
         if (mHandler != null) {
             mHandler.sendMessage(msg);
         }
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index b4fc035..50dad33 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1614,6 +1614,8 @@
     size_t actualSize = (*me->mCallback)(
             me, buffer->raw, buffer->size, me->mCallbackCookie);
 
+    buffer->size = actualSize;
+
     if (actualSize > 0) {
         me->snoopWrite(buffer->raw, actualSize);
     }
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 59a5f9d..b3a73b0 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -178,7 +178,8 @@
 }
 
 AwesomePlayer::AwesomePlayer()
-    : mTimeSource(NULL),
+    : mQueueStarted(false),
+      mTimeSource(NULL),
       mVideoRendererIsPreview(false),
       mAudioPlayer(NULL),
       mFlags(0),
@@ -201,13 +202,13 @@
 
     mAudioStatusEventPending = false;
 
-    mQueue.start();
-
     reset();
 }
 
 AwesomePlayer::~AwesomePlayer() {
-    mQueue.stop();
+    if (mQueueStarted) {
+        mQueue.stop();
+    }
 
     reset();
 
@@ -443,6 +444,8 @@
         notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
 
         pause_l();
+
+        mFlags |= AT_EOS;
     }
 }
 
@@ -517,6 +520,12 @@
 
     postBufferingEvent_l();
 
+    if (mFlags & AT_EOS) {
+        // Legacy behaviour, if a stream finishes playing and then
+        // is started again, we play from the start...
+        seekTo_l(0);
+    }
+
     return OK;
 }
 
@@ -651,6 +660,7 @@
 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
     mSeeking = true;
     mSeekTimeUs = timeUs;
+    mFlags &= ~AT_EOS;
 
     seekAudioIfNecessary_l();
 
@@ -989,6 +999,11 @@
         return UNKNOWN_ERROR;  // async prepare already pending
     }
 
+    if (!mQueueStarted) {
+        mQueue.start();
+        mQueueStarted = true;
+    }
+
     mFlags |= PREPARING;
     mAsyncPrepareEvent = new AwesomeEvent(
             this, &AwesomePlayer::onPrepareAsyncEvent);
@@ -1089,7 +1104,7 @@
     state->mUriHeaders = mUriHeaders;
     state->mFileSource = mFileSource;
 
-    state->mFlags = mFlags & (PLAYING | LOOPING);
+    state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
     getPosition_l(&state->mPositionUs);
 
     if (mLastVideoBuffer) {
@@ -1150,7 +1165,7 @@
 
     seekTo_l(state->mPositionUs);
 
-    mFlags = state->mFlags & LOOPING;
+    mFlags = state->mFlags & (LOOPING | AT_EOS);
 
     if (state->mLastVideoFrame && mISurface != NULL) {
         mVideoRenderer =
diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp
index 76ca77b..363e121 100644
--- a/media/libstagefright/Prefetcher.cpp
+++ b/media/libstagefright/Prefetcher.cpp
@@ -337,24 +337,20 @@
 void PrefetchedSource::cacheMore() {
     MediaSource::ReadOptions options;
 
-    {
-        Mutex::Autolock autoLock(mLock);
+    Mutex::Autolock autoLock(mLock);
 
-        if (!mStarted) {
-            return;
-        }
+    if (!mStarted) {
+        return;
+    }
 
-        if (mSeekTimeUs >= 0) {
-            options.setSeekTo(mSeekTimeUs);
-            mSeekTimeUs = -1;
-        }
+    if (mSeekTimeUs >= 0) {
+        options.setSeekTo(mSeekTimeUs);
+        mSeekTimeUs = -1;
     }
 
     MediaBuffer *buffer;
     status_t err = mSource->read(&buffer, &options);
 
-    Mutex::Autolock autoLock(mLock);
-
     if (err != OK) {
         mReachedEOS = true;
         mCondition.signal();
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 114d4c6..ce8eeae 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -92,12 +92,14 @@
         FIRST_FRAME = 4,
         PREPARING   = 8,
         PREPARED    = 16,
+        AT_EOS      = 32,
     };
 
     mutable Mutex mLock;
 
     OMXClient mClient;
     TimedEventQueue mQueue;
+    bool mQueueStarted;
     wp<MediaPlayerBase> mListener;
 
     sp<ISurface> mISurface;