Merge "Fix: Retrieval of location to caclulate twilight"
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index bf9b021..ebc64d7 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -19,23 +19,25 @@
 
 import static android.app.SuggestionsAdapter.getColumnString;
 
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
 import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.provider.Browser;
 import android.speech.RecognizerIntent;
@@ -43,11 +45,8 @@
 import android.text.InputType;
 import android.text.TextUtils;
 import android.text.TextWatcher;
-import android.util.AndroidRuntimeException;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Patterns;
-import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -69,10 +68,6 @@
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemSelectedListener;
 
-import java.util.ArrayList;
-import java.util.WeakHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-
 /**
  * Search dialog. This is controlled by the 
  * SearchManager and runs in the current foreground process.
@@ -154,6 +149,16 @@
         mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
         mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         mSearchManager = searchManager;
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        context.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
+                    onConfigurationChanged();
+                }
+            }
+        }, filter);
     }
 
     /**
@@ -394,10 +399,18 @@
             updateSearchAppIcon();
             updateSearchBadge();
             updateQueryHint();
+            if (isLandscapeMode(getContext())) {
+                mSearchAutoComplete.ensureImeVisible(true);
+            }
             mSearchAutoComplete.showDropDownAfterLayout();
-        } 
+        }
     }
-    
+
+    static boolean isLandscapeMode(Context context) {
+        return context.getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE;
+    }
+
     /**
      * Update the UI according to the info in the current value of {@link #mSearchable}.
      */
@@ -983,7 +996,7 @@
                 mSearchAutoComplete.setSelection(selPoint);
                 mSearchAutoComplete.setListSelection(0);
                 mSearchAutoComplete.clearListSelection();
-                mSearchAutoComplete.ensureImeVisible();
+                mSearchAutoComplete.ensureImeVisible(true);
                 
                 return true;
             }
@@ -1362,6 +1375,11 @@
                 InputMethodManager inputManager = (InputMethodManager)
                         getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                 inputManager.showSoftInput(this, 0);
+                // If in landscape mode, then make sure that
+                // the ime is in front of the dropdown.
+                if (isLandscapeMode(getContext())) {
+                    ensureImeVisible(true);
+                }
             }
         }
                 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 825ea46..390550f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2301,15 +2301,18 @@
         scrollBar.draw(canvas);
     }
 
+    private boolean canOverscrollHorizontally() {
+        return (Math.abs(mMinZoomScale - mMaxZoomScale) >= MINIMUM_SCALE_INCREMENT)
+                && getSettings().supportZoom()
+                && getSettings().getUseWideViewPort();
+    }
+
     @Override
     protected void onOverscrolled(int scrollX, int scrollY, boolean clampedX,
             boolean clampedY) {
         mInOverScrollMode = false;
         int maxX = computeMaxScrollX();
-        if (maxX == 0 && (Math.abs(mMinZoomScale - mMaxZoomScale)
-                < MINIMUM_SCALE_INCREMENT)
-                || !getSettings().supportZoom()
-                || !getSettings().getUseWideViewPort()) {
+        if (maxX == 0 && !canOverscrollHorizontally()) {
             // do not over scroll x if the page just fits the screen and it
             // can't zoom or the view doesn't use wide viewport
             scrollX = pinLocX(scrollX);
@@ -3115,6 +3118,14 @@
             return;
         }
 
+        // if both mContentWidth and mContentHeight are 0, it means there is no
+        // valid Picture passed to WebView yet. This can happen when WebView
+        // just starts. Draw the background and return.
+        if ((mContentWidth | mContentHeight) == 0 && mHistoryPicture == null) {
+            canvas.drawColor(mBackgroundColor);
+            return;
+        }
+
         int saveCount = canvas.save();
         if (mInOverScrollMode
                 && getSettings().getUseSystemOverscrollBackground()) {
@@ -4207,7 +4218,7 @@
 
         // Textfields and plugins need to receive the shift up key even if
         // another key was released while the shift key was held down.
-        if (!inEditingMode() && !nativeFocusIsPlugin()) {
+        if (!inEditingMode() && (mNativeClass == 0 || !nativeFocusIsPlugin())) {
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
                 mGotKeyDown = true;
             } else {
@@ -5112,8 +5123,10 @@
             if (ev.getY() < 0) pageUp(true);
             return true;
         }
+        boolean shiftPressed = mShiftIsPressed && (mNativeClass == 0
+                || !nativeFocusIsPlugin());
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+            if (shiftPressed) {
                 return true; // discard press if copy in progress
             }
             mTrackballDown = true;
@@ -5138,7 +5151,7 @@
             mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
             mTrackballDown = false;
             mTrackballUpTime = time;
-            if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+            if (shiftPressed) {
                 if (mExtendSelection) {
                     commitCopy();
                 } else {
@@ -5276,7 +5289,7 @@
         float yRate = mTrackballRemainsY * 1000 / elapsed;
         int viewWidth = getViewWidth();
         int viewHeight = getViewHeight();
-        if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+        if (mShiftIsPressed && (mNativeClass == 0 || !nativeFocusIsPlugin())) {
             moveSelection(scaleTrackballX(xRate, viewWidth),
                     scaleTrackballY(yRate, viewHeight));
             mTrackballRemainsX = mTrackballRemainsY = 0;
@@ -5314,7 +5327,7 @@
                         + " mTrackballRemainsX=" + mTrackballRemainsX
                         + " mTrackballRemainsY=" + mTrackballRemainsY);
             }
-            if (nativeFocusIsPlugin()) {
+            if (mNativeClass != 0 && nativeFocusIsPlugin()) {
                 for (int i = 0; i < count; i++) {
                     letPluginHandleNavKey(selectKeyCode, time, true);
                 }
@@ -5381,7 +5394,9 @@
                 vx = 0;
             }
         }
-
+        if (maxX == 0 && !canOverscrollHorizontally()) {
+            vx = 0;
+        }
         if (true /* EMG release: make our fling more like Maps' */) {
             // maps cuts their velocity in half
             vx = vx * 3 / 4;
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index ed63787..65f7cdb 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -17,9 +17,11 @@
 package android.widget;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable.Orientation;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.TextUtils;
@@ -210,10 +212,10 @@
      * Private hook into the on click event, dispatched from {@link PassThroughClickListener}
      */
     private void onClickImpl() {
-        // If the dropdown is showing, bring it back in front of the soft
-        // keyboard when the user touches the text field.
-        if (mPopup.isShowing() && isInputMethodNotNeeded()) {
-            ensureImeVisible();
+        // If the dropdown is showing, bring the keyboard to the front
+        // when the user touches the text field.
+        if (mPopup.isShowing()) {
+            ensureImeVisible(true);
         }
     }
 
@@ -1114,11 +1116,13 @@
     
     /**
      * Ensures that the drop down is not obscuring the IME.
-     * 
+     * @param visible whether the ime should be in front. If false, the ime is pushed to
+     * the background.
      * @hide internal used only here and SearchDialog
      */
-    public void ensureImeVisible() {
-        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
+    public void ensureImeVisible(boolean visible) {
+        mPopup.setInputMethodMode(visible
+                ? PopupWindow.INPUT_METHOD_NEEDED : PopupWindow.INPUT_METHOD_NOT_NEEDED);
         showDropDown();
     }
 
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 999b27d..ee2fc12 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
 package com.android.internal.widget;
 
 import android.content.Context;
diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java
index 25f6b33..1871682 100644
--- a/core/java/com/google/android/util/AbstractMessageParser.java
+++ b/core/java/com/google/android/util/AbstractMessageParser.java
@@ -1,5 +1,18 @@
-// Copyright 2007 The Android Open Source Project
-// All Rights Reserved.
+/*
+ * Copyright (C) 2007 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.google.android.util;
 
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index 23522bd..b6176eb 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -20,6 +20,7 @@
 
 #include <media/stagefright/DataSource.h>
 #include <utils/String8.h>
+#include <utils/threads.h>
 
 namespace android {
 
@@ -35,6 +36,9 @@
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL);
 
+    status_t connect();
+    void disconnect();
+
     virtual status_t initCheck() const;
 
     virtual ssize_t readAt(off_t offset, void *data, size_t size);
@@ -53,8 +57,21 @@
         kBufferSize = 32 * 1024
     };
 
+    enum State {
+        DISCONNECTED,
+        CONNECTING,
+        CONNECTED
+    };
+
+    State mState;
+    mutable Mutex mStateLock;
+
     String8 mHeaders;
 
+    String8 mStartingHost;
+    String8 mStartingPath;
+    int mStartingPort;
+
     HTTPStream *mHttp;
     char *mHost;
     int mPort;
@@ -67,11 +84,7 @@
     bool mContentLengthValid;
     unsigned long long mContentLength;
 
-    status_t mInitCheck;
-
-    void init(
-            const char *_host, int port, const char *_path,
-            const KeyedVector<String8, String8> *headers);
+    void init(const KeyedVector<String8, String8> *headers);
 
     ssize_t sendRangeRequest(size_t offset);
     void initHeaders(const KeyedVector<String8, String8> *overrides);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e00ba470..10b7be34 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -26,6 +26,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/CachingDataSource.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
@@ -318,6 +319,14 @@
 }
 
 void AwesomePlayer::reset_l() {
+    if (mFlags & PREPARING) {
+        mFlags |= PREPARE_CANCELLED;
+        if (mConnectingDataSource != NULL) {
+            LOGI("interrupting the connection process");
+            mConnectingDataSource->disconnect();
+        }
+    }
+
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -337,6 +346,12 @@
     // If we did this later, audio would continue playing while we
     // shutdown the video-related resources and the player appear to
     // not be as responsive to a reset request.
+    if (mAudioPlayer == NULL && mAudioSource != NULL) {
+        // If we had an audio player, it would have effectively
+        // taken possession of the audio source and stopped it when
+        // _it_ is stopped. Otherwise this is still our responsibility.
+        mAudioSource->stop();
+    }
     mAudioSource.clear();
 
     if (mTimeSource != mAudioPlayer) {
@@ -1039,8 +1054,29 @@
 }
 
 status_t AwesomePlayer::finishSetDataSource_l() {
-    sp<DataSource> dataSource =
-        DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+    sp<DataSource> dataSource;
+
+    if (!strncasecmp("http://", mUri.string(), 7)) {
+        mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
+
+        mLock.unlock();
+        status_t err = mConnectingDataSource->connect();
+        mLock.lock();
+
+        if (err != OK) {
+            mConnectingDataSource.clear();
+
+            LOGI("mConnectingDataSource->connect() returned %d", err);
+            return err;
+        }
+
+        dataSource = new CachingDataSource(
+                mConnectingDataSource, 32 * 1024, 20);
+
+        mConnectingDataSource.clear();
+    } else {
+        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+    }
 
     if (dataSource == NULL) {
         return UNKNOWN_ERROR;
@@ -1067,7 +1103,7 @@
     }
 
     mPrepareResult = err;
-    mFlags &= ~PREPARING;
+    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
     mAsyncPrepareEvent = NULL;
     mPreparedCondition.broadcast();
 }
@@ -1078,6 +1114,12 @@
     {
         Mutex::Autolock autoLock(mLock);
 
+        if (mFlags & PREPARE_CANCELLED) {
+            LOGI("prepare was cancelled before doing anything");
+            abortPrepare(UNKNOWN_ERROR);
+            return;
+        }
+
         if (mUri.size() > 0) {
             status_t err = finishSetDataSource_l();
 
@@ -1109,7 +1151,19 @@
     }
 
     if (prefetcher != NULL) {
+        {
+            Mutex::Autolock autoLock(mLock);
+            if (mFlags & PREPARE_CANCELLED) {
+                LOGI("prepare was cancelled before preparing the prefetcher");
+                abortPrepare(UNKNOWN_ERROR);
+                return;
+            }
+        }
+
+        LOGI("calling prefetcher->prepare()");
         prefetcher->prepare();
+        LOGV("prefetcher is done preparing");
+
         prefetcher.clear();
     }
 
@@ -1126,20 +1180,28 @@
     }
 
     mPrepareResult = OK;
-    mFlags &= ~PREPARING;
+    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
     mFlags |= PREPARED;
     mAsyncPrepareEvent = NULL;
     mPreparedCondition.broadcast();
 }
 
 status_t AwesomePlayer::suspend() {
-    LOGI("suspend");
+    LOGV("suspend");
     Mutex::Autolock autoLock(mLock);
 
     if (mSuspensionState != NULL) {
         return INVALID_OPERATION;
     }
 
+    if (mFlags & PREPARING) {
+        mFlags |= PREPARE_CANCELLED;
+        if (mConnectingDataSource != NULL) {
+            LOGI("interrupting the connection process");
+            mConnectingDataSource->disconnect();
+        }
+    }
+
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -1180,7 +1242,7 @@
 }
 
 status_t AwesomePlayer::resume() {
-    LOGI("resume");
+    LOGV("resume");
     Mutex::Autolock autoLock(mLock);
 
     if (mSuspensionState == NULL) {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 8468a07..284e3bc 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -101,8 +101,11 @@
     if (!strncasecmp("file://", uri, 7)) {
         source = new FileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7)) {
-        source = new HTTPDataSource(uri, headers);
-        source = new CachingDataSource(source, 32 * 1024, 20);
+        sp<HTTPDataSource> httpSource = new HTTPDataSource(uri, headers);
+        if (httpSource->connect() != OK) {
+            return NULL;
+        }
+        source = new CachingDataSource(httpSource, 32 * 1024, 20);
     } else {
         // Assume it's a filename.
         source = new FileSource(uri);
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index d79c1bd..451fc26 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -126,41 +126,71 @@
         host = string(host, 0, colon - host.c_str());
     }
 
-    init(host.c_str(), port, path.c_str(), headers);
+    mStartingHost = host.c_str();
+    mStartingPath = path.c_str();
+    mStartingPort = port;
+
+    init(headers);
 }
 
 HTTPDataSource::HTTPDataSource(
         const char *_host, int port, const char *_path,
         const KeyedVector<String8, String8> *headers) {
-    init(_host, port, _path, headers);
+    mStartingHost = _host;
+    mStartingPath = _path;
+    mStartingPort = port;
+
+    init(headers);
 }
 
-void HTTPDataSource::init(
-        const char *_host, int port, const char *_path,
-        const KeyedVector<String8, String8> *headers) {
+void HTTPDataSource::init(const KeyedVector<String8, String8> *headers) {
+    mState = DISCONNECTED;
     mHttp = new HTTPStream;
+
     mHost = NULL;
     mPort = 0;
-    mPath = NULL,
-    mBuffer = malloc(kBufferSize);
-    mBufferLength = 0;
-    mBufferOffset = 0;
-    mContentLengthValid = false;
+    mPath = NULL;
 
     initHeaders(headers);
 
-    string host = _host;
-    string path = _path;
+    mBuffer = malloc(kBufferSize);
+    mBufferLength = 0;
+    mBufferOffset = 0;
+}
+
+status_t HTTPDataSource::connect() {
+    {
+        Mutex::Autolock autoLock(mStateLock);
+
+        if (mState != DISCONNECTED) {
+            return ERROR_ALREADY_CONNECTED;
+        }
+
+        mState = CONNECTING;
+    }
+
+    mContentLengthValid = false;
+
+    string host = mStartingHost.string();
+    string path = mStartingPath.string();
+    int port = mStartingPort;
 
     LOGI("Connecting to host '%s', port %d, path '%s'",
          host.c_str(), port, path.c_str());
 
     int numRedirectsRemaining = 5;
     do {
-        mInitCheck = mHttp->connect(host.c_str(), port);
+        status_t err = mHttp->connect(host.c_str(), port);
 
-        if (mInitCheck != OK) {
-            return;
+        if (err != OK) {
+            Mutex::Autolock autoLock(mStateLock);
+
+            if (mState != CONNECTING) {
+                LOGV("connect() cancelled");
+            }
+            mState = DISCONNECTED;
+
+            return err;
         }
     } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port)
              && numRedirectsRemaining-- > 0);
@@ -175,17 +205,44 @@
     mHost = strdup(host.c_str());
     mPort = port;
     mPath = strdup(path.c_str());
+
+    Mutex::Autolock autoLock(mStateLock);
+
+    if (mState != CONNECTING) {
+        // disconnect was called when we had just successfully connected.
+        LOGV("connect() cancelled (we had just succeeded connecting)");
+
+        mHttp->disconnect();
+        return UNKNOWN_ERROR;
+    }
+
+    mState = CONNECTED;
+    return OK;
+}
+
+void HTTPDataSource::disconnect() {
+    Mutex::Autolock autoLock(mStateLock);
+
+    if (mState == CONNECTING || mState == CONNECTED) {
+        mHttp->disconnect();
+        mState = DISCONNECTED;
+    }
 }
 
 status_t HTTPDataSource::initCheck() const {
-    return mInitCheck;
+    Mutex::Autolock autoLock(mStateLock);
+
+    return (mState == CONNECTED) ? (status_t)OK : ERROR_NOT_CONNECTED;
 }
 
 status_t HTTPDataSource::getSize(off_t *size) {
     *size = 0;
 
-    if (mInitCheck != OK) {
-        return mInitCheck;
+    {
+        Mutex::Autolock autoLock(mStateLock);
+        if (mState != CONNECTED) {
+            return ERROR_NOT_CONNECTED;
+        }
     }
 
     if (!mContentLengthValid) {
@@ -198,7 +255,10 @@
 }
 
 HTTPDataSource::~HTTPDataSource() {
-    mHttp->disconnect();
+    disconnect();
+
+    delete mHttp;
+    mHttp = NULL;
 
     free(mBuffer);
     mBuffer = NULL;
@@ -212,9 +272,6 @@
         free(mHost);
         mHost = NULL;
     }
-
-    delete mHttp;
-    mHttp = NULL;
 }
 
 ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
@@ -271,6 +328,13 @@
 ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
     LOGV("readAt %ld, size %d", offset, size);
 
+    {
+        Mutex::Autolock autoLock(mStateLock);
+        if (mState != CONNECTED) {
+            return ERROR_NOT_CONNECTED;
+        }
+    }
+
     if (offset >= mBufferOffset
             && offset < (off_t)(mBufferOffset + mBufferLength)) {
         size_t num_bytes_available = mBufferLength - (offset - mBufferOffset);
@@ -304,7 +368,7 @@
     mBufferOffset = offset;
 
     if (mContentLengthValid
-            && mBufferOffset + contentLength >= mContentLength) {
+            && mBufferOffset + contentLength >= (off_t)mContentLength) {
         // If we never triggered a range request but know the content length,
         // make sure to not read more data than there could be, otherwise
         // we'd block indefinitely if the server doesn't close the connection.
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index 2c5da68..66eadf6 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -44,12 +44,19 @@
 }
 
 status_t HTTPStream::connect(const char *server, int port) {
+    Mutex::Autolock autoLock(mLock);
+
     status_t err = OK;
 
     if (mState == CONNECTED) {
         return ERROR_ALREADY_CONNECTED;
     }
 
+    struct hostent *ent = gethostbyname(server);
+    if (ent == NULL) {
+        return ERROR_UNKNOWN_HOST;
+    }
+
     CHECK_EQ(mSocket, -1);
     mSocket = socket(AF_INET, SOCK_STREAM, 0);
 
@@ -57,11 +64,11 @@
         return UNKNOWN_ERROR;
     }
 
-    struct hostent *ent = gethostbyname(server);
-    if (ent == NULL) {
-        err = ERROR_UNKNOWN_HOST;
-        goto exit1;
-    }
+    mState = CONNECTING;
+
+    int s = mSocket;
+
+    mLock.unlock();
 
     struct sockaddr_in addr;
     addr.sin_family = AF_INET;
@@ -69,24 +76,31 @@
     addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
     memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
 
-    if (::connect(mSocket, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
-        err = ERROR_CANNOT_CONNECT;
-        goto exit1;
+    int res = ::connect(s, (const struct sockaddr *)&addr, sizeof(addr));
+
+    mLock.lock();
+
+    if (mState != CONNECTING) {
+        return UNKNOWN_ERROR;
+    }
+
+    if (res < 0) {
+        close(mSocket);
+        mSocket = -1;
+
+        mState = READY;
+        return UNKNOWN_ERROR;
     }
 
     mState = CONNECTED;
 
     return OK;
-
-exit1:
-    close(mSocket);
-    mSocket = -1;
-
-    return err;
 }
 
 status_t HTTPStream::disconnect() {
-    if (mState != CONNECTED) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mState != CONNECTED && mState != CONNECTING) {
         return ERROR_NOT_CONNECTED;
     }
 
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index c0cf97c..4679207 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -23,7 +23,6 @@
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
-#include <media/stagefright/HTTPDataSource.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MetaData.h>
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 7106524..32c28c1 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -22,6 +22,7 @@
 
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/DataSource.h>
+#include <media/stagefright/HTTPDataSource.h>
 #include <media/stagefright/OMXClient.h>
 #include <utils/threads.h>
 
@@ -87,12 +88,13 @@
     friend struct AwesomeEvent;
 
     enum Flags {
-        PLAYING     = 1,
-        LOOPING     = 2,
-        FIRST_FRAME = 4,
-        PREPARING   = 8,
-        PREPARED    = 16,
-        AT_EOS      = 32,
+        PLAYING             = 1,
+        LOOPING             = 2,
+        FIRST_FRAME         = 4,
+        PREPARING           = 8,
+        PREPARED            = 16,
+        AT_EOS              = 32,
+        PREPARE_CANCELLED   = 64,
     };
 
     mutable Mutex mLock;
@@ -160,6 +162,7 @@
     MediaBuffer *mVideoBuffer;
 
     sp<Prefetcher> mPrefetcher;
+    sp<HTTPDataSource> mConnectingDataSource;
 
     struct SuspensionState {
         String8 mUri;
diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h
index 43ef614..5d638f3 100644
--- a/media/libstagefright/include/HTTPStream.h
+++ b/media/libstagefright/include/HTTPStream.h
@@ -24,6 +24,7 @@
 
 #include <media/stagefright/MediaErrors.h>
 #include <utils/KeyedVector.h>
+#include <utils/threads.h>
 
 namespace android {
 
@@ -54,10 +55,12 @@
 private:
     enum State {
         READY,
+        CONNECTING,
         CONNECTED
     };
 
     State mState;
+    Mutex mLock;
     int mSocket;
 
     KeyedVector<string, string> mHeaders;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index fc6bfcd..d72416d 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2205,32 +2205,28 @@
         if (mHandler == null || !ActivityManagerNative.isSystemReady()) {
             throw new IllegalStateException("Too early to call reboot()");
         }
-        
+
         final String finalReason = reason;
         Runnable runnable = new Runnable() {
             public void run() {
                 synchronized (this) {
                     ShutdownThread.reboot(mContext, finalReason, false);
-                    // if we get here we failed
-                    notify();
                 }
                 
             }
         };
-
+        // ShutdownThread must run on a looper capable of displaying the UI.
         mHandler.post(runnable);
 
-        // block until we reboot or fail.
-        // throw an exception if we failed to reboot
+        // PowerManager.reboot() is documented not to return so just wait for the inevitable.
         synchronized (runnable) {
-            try {
-                runnable.wait();
-            } catch (InterruptedException e) {
+            while (true) {
+                try {
+                    runnable.wait();
+                } catch (InterruptedException e) {
+                }
             }
         }
-     
-        // if we get here we failed
-        throw new IllegalStateException("unable to reboot!");
     }
 
     /**
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 3f64b25..be1d1c4 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -828,7 +828,13 @@
 
             ArrayList pids = new ArrayList();
             pids.add(Process.myPid());
+            if (mPhonePid > 0) pids.add(mPhonePid);
             File stack = ActivityManagerService.dumpStackTraces(pids);
+
+            // Give some extra time to make sure the stack traces get written.
+            // The system's been hanging for a minute, another second or two won't hurt much.
+            SystemClock.sleep(2000);
+
             mActivity.addErrorToDropBox("watchdog", null, null, null, name, null, stack, null);
 
             // Only kill the process if the debugger is not attached.
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f6289ae..8866bbd 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4708,7 +4708,8 @@
 
     final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
             HistoryRecord parent, final String annotation) {
-        if (app.notResponding || app.crashing) {
+        // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
+        if (mShuttingDown || app.notResponding || app.crashing) {
             return;
         }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 08946d2..188145b 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -592,8 +592,11 @@
         if (!isIncoming) {
             // outgoing calls only
             processNextPostDialChar();
+        } else {
+            // Only release wake lock for incoming calls, for outgoing calls the wake lock
+            // will be released after any pause-dial is completed
+            releaseWakeLock();
         }
-        releaseWakeLock();
     }
 
     private void
@@ -688,6 +691,7 @@
         Registrant postDialHandler;
 
         if (postDialState == PostDialState.CANCELLED) {
+            releaseWakeLock();
             //Log.v("CDMA", "##### processNextPostDialChar: postDialState == CANCELLED, bail");
             return;
         }
@@ -696,6 +700,9 @@
                 postDialString.length() <= nextPostDialChar) {
             setPostDialState(PostDialState.COMPLETE);
 
+            // We were holding a wake lock until pause-dial was complete, so give it up now
+            releaseWakeLock();
+
             // notifyMessage.arg1 is 0 on complete
             c = 0;
         } else {
@@ -770,19 +777,24 @@
     }
 
     /**
-     * Set post dial state and acquire wake lock while switching to "started"
-     * state, the wake lock will be released if state switches out of "started"
+     * Set post dial state and acquire wake lock while switching to "started" or "wait"
+     * state, the wake lock will be released if state switches out of "started" or "wait"
      * state or after WAKE_LOCK_TIMEOUT_MILLIS.
      * @param s new PostDialState
      */
     private void setPostDialState(PostDialState s) {
-        if (postDialState != PostDialState.STARTED
-                && s == PostDialState.STARTED) {
-            acquireWakeLock();
-            Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
-            h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
-        } else if (postDialState == PostDialState.STARTED
-                && s != PostDialState.STARTED) {
+        if (s == PostDialState.STARTED ||
+                s == PostDialState.PAUSE) {
+            synchronized (mPartialWakeLock) {
+                if (mPartialWakeLock.isHeld()) {
+                    h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
+                } else {
+                    acquireWakeLock();
+                }
+                Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
+                h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
+            }
+        } else {
             h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
             releaseWakeLock();
         }
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
index 5c8e23e..3e5d37e 100644
--- a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
+++ b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2009 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
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriManager.java b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
index 37c1d55..1bcc90a 100644
--- a/telephony/java/com/android/internal/telephony/cdma/EriManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2009 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
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index eecd00a..e3486a0 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -24,9 +24,8 @@
     private static final String LOGTAG = "FileFilter";
 
     // Returns whether we should ignore this test and skip running it.
-    // Currently we use this only for tests that crash the browser.
-    // TODO: Once these crashes are fixed, we should probably eliminate this
-    // method, as no test should crash.
+    // Currently we use this only for tests that crash or hang DumpRenderTree.
+    // TODO: Fix these and eliminate this method.
     public static boolean ignoreTest(String file) {
         for (int i = 0; i < ignoreTestList.length; i++) {
             if (file.endsWith(ignoreTestList[i])) {
@@ -74,6 +73,8 @@
 
     static final String[] ignoreTestList = {
         "fast/js/regexp-charclass-crash.html", // RegExp is too large, causing OOM
+        "fast/regex/test1.html", // Causes DumpRenderTree to hang with V8
+        "fast/regex/slow.html", // Causes DumpRenderTree to hang with V8
         "editing/selection/move-left-right.html" // Causes DumpRenderTree to hang
     };