Merge change Ib904c2a4 into eclair-mr2

* changes:
  Remove old hack A/V sync hack that is no longer needed.
diff --git a/api/current.xml b/api/current.xml
index ef8f78f..027bc1b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -976,7 +976,7 @@
  value=""android.permission.SET_PREFERRED_APPLICATIONS""
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -34032,6 +34032,17 @@
 <parameter name="defaultValue" type="short">
 </parameter>
 </method>
+<method name="getSourceBounds"
+ return="android.graphics.Rect"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getStringArrayExtra"
  return="java.lang.String[]"
  abstract="false"
@@ -34843,6 +34854,19 @@
 <parameter name="packageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="setSourceBounds"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="r" type="android.graphics.Rect">
+</parameter>
+</method>
 <method name="setType"
  return="android.content.Intent"
  abstract="false"
@@ -36423,6 +36447,17 @@
  visibility="public"
 >
 </field>
+<field name="FILL_IN_SOURCE_BOUNDS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_ACTIVITY_BROUGHT_TO_FRONT"
  type="int"
  transient="false"
@@ -41108,7 +41143,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="packageName" type="java.lang.String">
@@ -41861,7 +41896,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="packageName" type="java.lang.String">
@@ -62109,6 +62144,17 @@
  visibility="public"
 >
 </method>
+<method name="flattenToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="height"
  return="int"
  abstract="false"
@@ -62335,6 +62381,19 @@
  visibility="public"
 >
 </method>
+<method name="unflattenFromString"
+ return="android.graphics.Rect"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="str" type="java.lang.String">
+</parameter>
+</method>
 <method name="union"
  return="void"
  abstract="false"
@@ -125196,6 +125255,20 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="rssi" type="int">
+</parameter>
+<parameter name="location" type="java.lang.String">
+</parameter>
+<parameter name="radioType" type="int">
+</parameter>
+</constructor>
+<constructor name="NeighboringCellInfo"
+ type="android.telephony.NeighboringCellInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 <parameter name="in" type="android.os.Parcel">
 </parameter>
 </constructor>
@@ -126007,6 +126080,21 @@
 <parameter name="state" type="int">
 </parameter>
 </method>
+<method name="onDataConnectionStateChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="state" type="int">
+</parameter>
+<parameter name="networkType" type="int">
+</parameter>
+</method>
 <method name="onMessageWaitingIndicatorChanged"
  return="void"
  abstract="false"
@@ -126046,6 +126134,19 @@
 <parameter name="asu" type="int">
 </parameter>
 </method>
+<method name="onSignalStrengthsChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="signalStrength" type="android.telephony.SignalStrength">
+</parameter>
+</method>
 <field name="LISTEN_CALL_FORWARDING_INDICATOR"
  type="int"
  transient="false"
@@ -126141,6 +126242,17 @@
  value="2"
  static="true"
  final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="LISTEN_SIGNAL_STRENGTHS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -126422,6 +126534,131 @@
 >
 </field>
 </class>
+<class name="SignalStrength"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCdmaDbm"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCdmaEcio"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEvdoDbm"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEvdoEcio"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEvdoSnr"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGsmBitErrorRate"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGsmSignalStrength"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isGsm"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+</class>
 <class name="SmsManager"
  extends="java.lang.Object"
  abstract="false"
diff --git a/calendar/Android.mk b/calendar/Android.mk
new file mode 100644
index 0000000..fd20dfa
--- /dev/null
+++ b/calendar/Android.mk
@@ -0,0 +1,18 @@
+# Copyright 2009 Google, Inc.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := calendar
+LOCAL_SRC_FILES := \
+	../core/java/android/provider/Calendar.java \
+	../core/java/android/pim/EventRecurrence.java \
+	../core/java/android/pim/ICalendar.java \
+	../core/java/android/pim/RecurrenceSet.java \
+	../core/java/android/pim/ContactsAsyncHelper.java \
+	../core/java/android/pim/DateException.java
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Include this library in the build server's output directory
+$(call dist-for-goals, droid, $(LOCAL_BUILT_MODULE):calendar.jar)
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index df59dcf..6419a5c 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -669,8 +669,14 @@
     LOGD("startRecording (pid %d)", getCallingPid());
 
     if (mMediaPlayerBeep.get() != NULL) {
-        mMediaPlayerBeep->seekTo(0);
-        mMediaPlayerBeep->start();
+        // do not play record jingle if stream volume is 0
+        // (typically because ringer mode is silent).
+        int index;
+        AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+        if (index != 0) {
+            mMediaPlayerBeep->seekTo(0);
+            mMediaPlayerBeep->start();
+        }
     }
 
     mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
@@ -888,8 +894,14 @@
 {
     // Play shutter sound.
     if (mMediaPlayerClick.get() != NULL) {
-        mMediaPlayerClick->seekTo(0);
-        mMediaPlayerClick->start();
+        // do not play shutter sound if stream volume is 0
+        // (typically because ringer mode is silent).
+        int index;
+        AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+        if (index != 0) {
+            mMediaPlayerClick->seekTo(0);
+            mMediaPlayerClick->start();
+        }
     }
 
     // Screen goes black after the buffer is unregistered.
diff --git a/camera/tests/CameraServiceTest/Android.mk b/camera/tests/CameraServiceTest/Android.mk
new file mode 100644
index 0000000..c2a02bb
--- /dev/null
+++ b/camera/tests/CameraServiceTest/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= CameraServiceTest.cpp
+
+LOCAL_MODULE:= CameraServiceTest
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_C_INCLUDES += \
+                frameworks/base/libs
+
+LOCAL_CFLAGS :=
+
+LOCAL_SHARED_LIBRARIES += \
+                libcutils \
+                libutils \
+                libui
+
+include $(BUILD_EXECUTABLE)
diff --git a/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/camera/tests/CameraServiceTest/CameraServiceTest.cpp
new file mode 100644
index 0000000..29320e0
--- /dev/null
+++ b/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -0,0 +1,848 @@
+#define LOG_TAG "CameraServiceTest"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <ui/ISurface.h>
+#include <ui/Camera.h>
+#include <ui/CameraParameters.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/ICamera.h>
+#include <ui/ICameraClient.h>
+#include <ui/ICameraService.h>
+#include <ui/Overlay.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+using namespace android;
+
+//
+//  Assertion and Logging utilities
+//
+#define INFO(...) \
+    do { \
+        printf(__VA_ARGS__); \
+        printf("\n"); \
+        LOGD(__VA_ARGS__); \
+    } while(0)
+
+void assert_fail(const char *file, int line, const char *func, const char *expr) {
+    INFO("assertion failed at file %s, line %d, function %s:",
+            file, line, func);
+    INFO("%s", expr);
+    exit(1);
+}
+
+void assert_eq_fail(const char *file, int line, const char *func,
+        const char *expr, int actual) {
+    INFO("assertion failed at file %s, line %d, function %s:",
+            file, line, func);
+    INFO("(expected) %s != (actual) %d", expr, actual);
+    exit(1);
+}
+
+#define ASSERT(e) \
+    do { \
+        if (!(e)) \
+            assert_fail(__FILE__, __LINE__, __func__, #e); \
+    } while(0)
+
+#define ASSERT_EQ(expected, actual) \
+    do { \
+        int _x = (actual); \
+        if (_x != (expected)) \
+            assert_eq_fail(__FILE__, __LINE__, __func__, #expected, _x); \
+    } while(0)
+
+//
+//  Holder service for pass objects between processes.
+//
+class IHolder : public IInterface {
+protected:
+    enum {
+        HOLDER_PUT = IBinder::FIRST_CALL_TRANSACTION,
+        HOLDER_GET,
+        HOLDER_CLEAR
+    };
+public:
+    DECLARE_META_INTERFACE(Holder);
+
+    virtual void put(sp<IBinder> obj) = 0;
+    virtual sp<IBinder> get() = 0;
+    virtual void clear() = 0;
+};
+
+class BnHolder : public BnInterface<IHolder> {
+    virtual status_t onTransact(uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+class BpHolder : public BpInterface<IHolder> {
+public:
+    BpHolder(const sp<IBinder>& impl)
+        : BpInterface<IHolder>(impl) {
+    }
+
+    virtual void put(sp<IBinder> obj) {
+        Parcel data, reply;
+        data.writeStrongBinder(obj);
+        remote()->transact(HOLDER_PUT, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    virtual sp<IBinder> get() {
+        Parcel data, reply;
+        remote()->transact(HOLDER_GET, data, &reply);
+        return reply.readStrongBinder();
+    }
+
+    virtual void clear() {
+        Parcel data, reply;
+        remote()->transact(HOLDER_CLEAR, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Holder, "CameraServiceTest.Holder");
+
+status_t BnHolder::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch(code) {
+        case HOLDER_PUT: {
+            put(data.readStrongBinder());
+            return NO_ERROR;
+        } break;
+        case HOLDER_GET: {
+            reply->writeStrongBinder(get());
+            return NO_ERROR;
+        } break;
+        case HOLDER_CLEAR: {
+            clear();
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+class HolderService : public BnHolder {
+    virtual void put(sp<IBinder> obj) {
+        mObj = obj;
+    }
+    virtual sp<IBinder> get() {
+        return mObj;
+    }
+    virtual void clear() {
+        mObj.clear();
+    }
+private:
+    sp<IBinder> mObj;
+};
+
+//
+//  A mock CameraClient
+//
+class MCameraClient : public BnCameraClient {
+public:
+    virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
+    virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
+    virtual void dataCallbackTimestamp(nsecs_t timestamp,
+            int32_t msgType, const sp<IMemory>& data) {}
+
+    // new functions
+    void clearStat();
+    enum OP { EQ, GE, LE, GT, LT };
+    void assertNotify(int32_t msgType, OP op, int count);
+    void assertData(int32_t msgType, OP op, int count);
+    void waitNotify(int32_t msgType, OP op, int count);
+    void waitData(int32_t msgType, OP op, int count);
+    void assertDataSize(int32_t msgType, OP op, int dataSize);
+
+    void setReleaser(ICamera *releaser) {
+        mReleaser = releaser;
+    }
+private:
+    Mutex mLock;
+    Condition mCond;
+    DefaultKeyedVector<int32_t, int> mNotifyCount;
+    DefaultKeyedVector<int32_t, int> mDataCount;
+    DefaultKeyedVector<int32_t, int> mDataSize;
+    bool test(OP op, int v1, int v2);
+
+    ICamera *mReleaser;
+};
+
+void MCameraClient::clearStat() {
+    Mutex::Autolock _l(mLock);
+    mNotifyCount.clear();
+    mDataCount.clear();
+    mDataSize.clear();
+}
+
+bool MCameraClient::test(OP op, int v1, int v2) {
+    switch (op) {
+        case EQ: return v1 == v2;
+        case GT: return v1 > v2;
+        case LT: return v1 < v2;
+        case GE: return v1 >= v2;
+        case LE: return v1 <= v2;
+        default: ASSERT(0); break;
+    }
+    return false;
+}
+
+void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
+    Mutex::Autolock _l(mLock);
+    int v = mNotifyCount.valueFor(msgType);
+    ASSERT(test(op, v, count));
+}
+
+void MCameraClient::assertData(int32_t msgType, OP op, int count) {
+    Mutex::Autolock _l(mLock);
+    int v = mDataCount.valueFor(msgType);
+    ASSERT(test(op, v, count));
+}
+
+void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
+    Mutex::Autolock _l(mLock);
+    int v = mDataSize.valueFor(msgType);
+    ASSERT(test(op, v, dataSize));
+}
+
+void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
+    INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ssize_t i = mNotifyCount.indexOfKey(msgType);
+    if (i < 0) {
+        mNotifyCount.add(msgType, 1);
+    } else {
+        ++mNotifyCount.editValueAt(i);
+    }
+    mCond.signal();
+}
+
+void MCameraClient::dataCallback(int32_t msgType, const sp<IMemory>& data) {
+    INFO(__func__);
+    int dataSize = data->size();
+    INFO("data type = %d, size = %d", msgType, dataSize);
+    Mutex::Autolock _l(mLock);
+    ssize_t i = mDataCount.indexOfKey(msgType);
+    if (i < 0) {
+        mDataCount.add(msgType, 1);
+        mDataSize.add(msgType, dataSize);
+    } else {
+        ++mDataCount.editValueAt(i);
+        mDataSize.editValueAt(i) = dataSize;
+    }
+    mCond.signal();
+
+    if (msgType == CAMERA_MSG_VIDEO_FRAME) {
+        ASSERT(mReleaser != NULL);
+        mReleaser->releaseRecordingFrame(data);
+    }
+}
+
+void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
+    INFO("waitNotify: %d, %d, %d", msgType, op, count);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        int v = mNotifyCount.valueFor(msgType);
+        if (test(op, v, count)) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+void MCameraClient::waitData(int32_t msgType, OP op, int count) {
+    INFO("waitData: %d, %d, %d", msgType, op, count);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        int v = mDataCount.valueFor(msgType);
+        if (test(op, v, count)) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+//
+//  A mock Surface
+//
+class MSurface : public BnSurface {
+public:
+    virtual status_t registerBuffers(const BufferHeap& buffers);
+    virtual void postBuffer(ssize_t offset);
+    virtual void unregisterBuffers();
+    virtual sp<OverlayRef> createOverlay(
+            uint32_t w, uint32_t h, int32_t format);
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
+
+    // new functions
+    void clearStat();
+    void waitUntil(int c0, int c1, int c2);
+
+private:
+    // check callback count
+    Condition mCond;
+    Mutex mLock;
+    int registerBuffersCount;
+    int postBufferCount;
+    int unregisterBuffersCount;
+};
+
+status_t MSurface::registerBuffers(const BufferHeap& buffers) {
+    INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ++registerBuffersCount;
+    mCond.signal();
+    return NO_ERROR;
+}
+
+void MSurface::postBuffer(ssize_t offset) {
+    // INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ++postBufferCount;
+    mCond.signal();
+}
+
+void MSurface::unregisterBuffers() {
+    INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ++unregisterBuffersCount;
+    mCond.signal();
+}
+
+sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
+    INFO(__func__);
+    return NULL;
+}
+
+void MSurface::clearStat() {
+    Mutex::Autolock _l(mLock);
+    registerBuffersCount = 0;
+    postBufferCount = 0;
+    unregisterBuffersCount = 0;
+}
+
+void MSurface::waitUntil(int c0, int c1, int c2) {
+    INFO("waitUntil: %d %d %d", c0, c1, c2);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        if (registerBuffersCount >= c0 &&
+            postBufferCount >= c1 &&
+            unregisterBuffersCount >= c2) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format) {
+    // We don't expect this to be called in current hardware.
+    ASSERT(0);
+    sp<OverlayRef> dummy;
+    return dummy;
+}
+
+//
+//  Utilities to use the Holder service
+//
+sp<IHolder> getHolder() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    ASSERT(sm != 0);
+    sp<IBinder> binder = sm->getService(String16("CameraServiceTest.Holder"));
+    ASSERT(binder != 0);
+    sp<IHolder> holder = interface_cast<IHolder>(binder);
+    ASSERT(holder != 0);
+    return holder;
+}
+
+void putTempObject(sp<IBinder> obj) {
+    INFO(__func__);
+    getHolder()->put(obj);
+}
+
+sp<IBinder> getTempObject() {
+    INFO(__func__);
+    return getHolder()->get();
+}
+
+void clearTempObject() {
+    INFO(__func__);
+    getHolder()->clear();
+}
+
+//
+//  Get a Camera Service
+//
+sp<ICameraService> getCameraService() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    ASSERT(sm != 0);
+    sp<IBinder> binder = sm->getService(String16("media.camera"));
+    ASSERT(binder != 0);
+    sp<ICameraService> cs = interface_cast<ICameraService>(binder);
+    ASSERT(cs != 0);
+    return cs;
+}
+
+//
+// Various Connect Tests
+//
+void testConnect() {
+    INFO(__func__);
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    c->disconnect();
+}
+
+void testAllowConnectOnceOnly() {
+    INFO(__func__);
+    sp<ICameraService> cs = getCameraService();
+    // Connect the first client.
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // Same client -- ok.
+    ASSERT(cs->connect(cc) != 0);
+    // Different client -- not ok.
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(cs->connect(cc2) == 0);
+    c->disconnect();
+}
+
+void testReconnectFailed() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(c->connect(cc2) != NO_ERROR);
+}
+
+void testReconnectSuccess() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    sp<MCameraClient> cc = new MCameraClient();
+    ASSERT(c->connect(cc) == NO_ERROR);
+}
+
+void testLockFailed() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() != NO_ERROR);
+}
+
+void testLockUnlockSuccess() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() == NO_ERROR);
+    ASSERT(c->unlock() == NO_ERROR);
+}
+
+void testLockSuccess() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() == NO_ERROR);
+}
+
+//
+// Run the connect tests in another process.
+//
+const char *gExecutable;
+
+struct FunctionTableEntry {
+    const char *name;
+    void (*func)();
+};
+
+FunctionTableEntry function_table[] = {
+#define ENTRY(x) {#x, &x}
+    ENTRY(testReconnectFailed),
+    ENTRY(testReconnectSuccess),
+    ENTRY(testLockUnlockSuccess),
+    ENTRY(testLockFailed),
+    ENTRY(testLockSuccess),
+#undef ENTRY
+};
+
+void runFunction(const char *tag) {
+    INFO("runFunction: %s", tag);
+    int entries = sizeof(function_table) / sizeof(function_table[0]);
+    for (int i = 0; i < entries; i++) {
+        if (strcmp(function_table[i].name, tag) == 0) {
+            (*function_table[i].func)();
+            return;
+        }
+    }
+    ASSERT(0);
+}
+
+void runInAnotherProcess(const char *tag) {
+    pid_t pid = fork();
+    if (pid == 0) {
+        execlp(gExecutable, gExecutable, tag, NULL);
+        ASSERT(0);
+    } else {
+        int status;
+        ASSERT_EQ(pid, wait(&status));
+        ASSERT_EQ(0, status);
+    }
+}
+
+void testReconnect() {
+    INFO(__func__);
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // Reconnect to the same client -- ok.
+    ASSERT(c->connect(cc) == NO_ERROR);
+    // Reconnect to a different client (but the same pid) -- ok.
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(c->connect(cc2) == NO_ERROR);
+    c->disconnect();
+    cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+}
+
+void testLockUnlock() {
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // We can lock as many times as we want.
+    ASSERT(c->lock() == NO_ERROR);
+    ASSERT(c->lock() == NO_ERROR);
+    // Lock from a different process -- not ok.
+    putTempObject(c->asBinder());
+    runInAnotherProcess("testLockFailed");
+    // Unlock then lock from a different process -- ok.
+    ASSERT(c->unlock() == NO_ERROR);
+    runInAnotherProcess("testLockUnlockSuccess");
+    // Unlock then lock from a different process -- ok.
+    runInAnotherProcess("testLockSuccess");
+    c->disconnect();
+    clearTempObject();
+}
+
+void testReconnectFromAnotherProcess() {
+    INFO(__func__);
+
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // Reconnect from a different process -- not ok.
+    putTempObject(c->asBinder());
+    runInAnotherProcess("testReconnectFailed");
+    // Unlock then reconnect from a different process -- ok.
+    ASSERT(c->unlock() == NO_ERROR);
+    runInAnotherProcess("testReconnectSuccess");
+    c->disconnect();
+    clearTempObject();
+}
+
+// We need to flush the command buffer after the reference
+// to ICamera is gone. The sleep is for the server to run
+// the destructor for it.
+static void flushCommands() {
+    IPCThreadState::self()->flushCommands();
+    usleep(200000);  // 200ms
+}
+
+// Run a test case
+#define RUN(class_name) do { \
+    { \
+        INFO(#class_name); \
+        class_name instance; \
+        instance.run(); \
+    } \
+    flushCommands(); \
+} while(0)
+
+// Base test case after the the camera is connected.
+class AfterConnect {
+protected:
+    sp<ICameraService> cs;
+    sp<MCameraClient> cc;
+    sp<ICamera> c;
+
+    AfterConnect() {
+        cs = getCameraService();
+        cc = new MCameraClient();
+        c = cs->connect(cc);
+        ASSERT(c != 0);
+    }
+
+    ~AfterConnect() {
+        c.clear();
+        cc.clear();
+        cs.clear();
+    }
+};
+
+class TestSetPreviewDisplay : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStartPreview : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+        ASSERT(c->startPreview() == NO_ERROR);
+        ASSERT(c->previewEnabled() == true);
+
+        surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
+        surface->clearStat();
+
+        c->disconnect();
+        // TODO: CameraService crashes for this. Fix it.
+#if 0
+        sp<MSurface> another_surface = new MSurface();
+        c->setPreviewDisplay(another_surface);  // just to make sure unregisterBuffers
+                                                // is called.
+        surface->waitUntil(0, 0, 1);  // needs unregisterBuffers
+#endif
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStartPreviewWithoutDisplay : AfterConnect {
+public:
+    void run() {
+        ASSERT(c->startPreview() == NO_ERROR);
+        ASSERT(c->previewEnabled() == true);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+// Base test case after the the camera is connected and the preview is started.
+class AfterStartPreview : public AfterConnect {
+protected:
+    sp<MSurface> surface;
+
+    AfterStartPreview() {
+        surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        ASSERT(c->startPreview() == NO_ERROR);
+    }
+
+    ~AfterStartPreview() {
+        surface.clear();
+    }
+};
+
+class TestAutoFocus : public AfterStartPreview {
+public:
+    void run() {
+        cc->assertNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 0);
+        c->autoFocus();
+        cc->waitNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 1);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStopPreview : public AfterStartPreview {
+public:
+    void run() {
+        ASSERT(c->previewEnabled() == true);
+        c->stopPreview();
+        ASSERT(c->previewEnabled() == false);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestTakePicture: public AfterStartPreview {
+public:
+    void run() {
+        ASSERT(c->takePicture() == NO_ERROR);
+        cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+        cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+        cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+        c->stopPreview();
+#if 1  // TODO: It crashes if we don't have this. Fix it.
+        usleep(100000);
+#endif
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestTakeMultiplePictures: public AfterStartPreview {
+public:
+    void run() {
+        for (int i = 0; i < 10; i++) {
+            cc->clearStat();
+            ASSERT(c->takePicture() == NO_ERROR);
+            cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+            cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+            cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+            usleep(100000);  // 100ms
+        }
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestGetParameters: public AfterStartPreview {
+public:
+    void run() {
+        String8 param_str = c->getParameters();
+        INFO(param_str);
+    }
+};
+
+class TestPictureSize : public AfterStartPreview {
+public:
+    void checkOnePicture(int w, int h) {
+        const float rate = 0.5;  // byte per pixel limit
+        int pixels = w * h;
+
+        CameraParameters param(c->getParameters());
+        param.setPictureSize(w, h);
+        c->setParameters(param.flatten());
+
+        cc->clearStat();
+        ASSERT(c->takePicture() == NO_ERROR);
+        cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+        cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
+        cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+        cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
+                int(pixels * rate));
+        cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+        usleep(100000);  // 100ms
+    }
+
+    void run() {
+        checkOnePicture(2048, 1536);
+        checkOnePicture(1600, 1200);
+        checkOnePicture(1024, 768);
+    }
+};
+
+class TestPreviewCallbackFlag : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+        // Try all flag combinations.
+        for (int v = 0; v < 8; v++) {
+            cc->clearStat();
+            c->setPreviewCallbackFlag(v);
+            ASSERT(c->previewEnabled() == false);
+            ASSERT(c->startPreview() == NO_ERROR);
+            ASSERT(c->previewEnabled() == true);
+            sleep(2);
+            c->stopPreview();
+            if ((v & FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
+                cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
+            } else {
+                if ((v & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
+                    cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
+                } else {
+                    cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
+                }
+            }
+        }
+    }
+};
+
+class TestRecording : public AfterConnect {
+public:
+    void run() {
+        ASSERT(c->recordingEnabled() == false);
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        cc->setReleaser(c.get());
+        c->startRecording();
+        ASSERT(c->recordingEnabled() == true);
+        sleep(2);
+        c->stopRecording();
+        cc->setReleaser(NULL);
+        cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
+    }
+};
+
+class TestPreviewSize : public AfterStartPreview {
+public:
+    void checkOnePicture(int w, int h) {
+        int size = w*h*3/2;  // should read from parameters
+
+        c->stopPreview();
+
+        CameraParameters param(c->getParameters());
+        param.setPreviewSize(w, h);
+        c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        c->setParameters(param.flatten());
+
+        c->startPreview();
+
+        cc->clearStat();
+        cc->waitData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 1);
+        cc->assertDataSize(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, size);
+    }
+
+    void run() {
+        checkOnePicture(480, 320);
+        checkOnePicture(352, 288);
+        checkOnePicture(176, 144);
+    }
+};
+
+void runHolderService() {
+    defaultServiceManager()->addService(
+            String16("CameraServiceTest.Holder"), new HolderService());
+    ProcessState::self()->startThreadPool();
+}
+
+int main(int argc, char **argv)
+{
+    if (argc != 1) {
+        runFunction(argv[1]);
+        return 0;
+    }
+    INFO("CameraServiceTest start");
+    gExecutable = argv[0];
+    runHolderService();
+
+    testConnect();                              flushCommands();
+    testAllowConnectOnceOnly();                 flushCommands();
+    testReconnect();                            flushCommands();
+    testLockUnlock();                           flushCommands();
+    testReconnectFromAnotherProcess();          flushCommands();
+
+    RUN(TestSetPreviewDisplay);
+    RUN(TestStartPreview);
+    RUN(TestStartPreviewWithoutDisplay);
+    RUN(TestAutoFocus);
+    RUN(TestStopPreview);
+    RUN(TestTakePicture);
+    RUN(TestTakeMultiplePictures);
+    RUN(TestGetParameters);
+    RUN(TestPictureSize);
+    RUN(TestPreviewCallbackFlag);
+    RUN(TestRecording);
+    RUN(TestPreviewSize);
+}
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index eca5af9..d640de1 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -2,16 +2,16 @@
 **
 ** Copyright 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -126,6 +126,10 @@
                 String value = nextArgRequired();
                 intent.putExtra(key, value);
                 hasIntentInfo = true;
+            } else if (opt.equals("--esn")) {
+                String key = nextArgRequired();
+                intent.putExtra(key, (String) null);
+                hasIntentInfo = true;
             } else if (opt.equals("--ei")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
@@ -364,7 +368,7 @@
         private boolean mRawMode = false;
 
         /**
-         * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode", 
+         * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode",
          * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
          * @param rawMode true for raw mode, false for pretty mode.
          */
@@ -507,6 +511,7 @@
                 "        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
                 "        [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
                 "        [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+                "        [--esn <EXTRA_KEY> ...]\n" +
                 "        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
                 "        [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
                 "        [-n <COMPONENT>] [-f <FLAGS>] [<URI>]\n"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 5b55252..100af89 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -43,4 +43,26 @@
 
 include $(BUILD_EXECUTABLE)
 
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=         \
+        SineSource.cpp    \
+        audioloop.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libstagefright
+
+LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
+	frameworks/base/media/libstagefright \
+	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= audioloop
+
+include $(BUILD_EXECUTABLE)
+
 endif
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
index e272a65..021f636 100644
--- a/cmds/stagefright/SineSource.cpp
+++ b/cmds/stagefright/SineSource.cpp
@@ -52,6 +52,7 @@
     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
     meta->setInt32(kKeyChannelCount, mNumChannels);
     meta->setInt32(kKeySampleRate, mSampleRate);
+    meta->setInt32(kKeyMaxInputSize, kBufferSize);
 
     return meta;
 }
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
new file mode 100644
index 0000000..70ab559
--- /dev/null
+++ b/cmds/stagefright/audioloop.cpp
@@ -0,0 +1,81 @@
+#include "SineSource.h"
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+
+using namespace android;
+
+int main() {
+    // We only have an AMR-WB encoder on sholes...
+    static bool outputWBAMR = false;
+    static const int32_t kSampleRate = outputWBAMR ? 16000 : 8000;
+    static const int32_t kNumChannels = 1;
+
+    android::ProcessState::self()->startThreadPool();
+
+    OMXClient client;
+    CHECK_EQ(client.connect(), OK);
+
+    sp<MediaSource> source = new SineSource(kSampleRate, kNumChannels);
+
+    sp<MetaData> meta = new MetaData;
+
+    meta->setCString(
+            kKeyMIMEType,
+            outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
+                        : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+
+    meta->setInt32(kKeyChannelCount, kNumChannels);
+    meta->setInt32(kKeySampleRate, kSampleRate);
+
+    int32_t maxInputSize;
+    if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+        meta->setInt32(kKeyMaxInputSize, maxInputSize);
+    }
+
+    sp<OMXCodec> encoder = OMXCodec::Create(
+            client.interface(),
+            meta, true /* createEncoder */,
+            source);
+
+    sp<OMXCodec> decoder = OMXCodec::Create(
+            client.interface(),
+            meta, false /* createEncoder */,
+            encoder);
+
+#if 1
+    AudioPlayer *player = new AudioPlayer(NULL);
+    player->setSource(decoder);
+
+    player->start();
+
+    sleep(10);
+
+    player->stop();
+
+    delete player;
+    player = NULL;
+#else
+    CHECK_EQ(decoder->start(), OK);
+
+    MediaBuffer *buffer;
+    while (decoder->read(&buffer) == OK) {
+        // do something with buffer
+
+        putchar('.');
+        fflush(stdout);
+
+        buffer->release();
+        buffer = NULL;
+    }
+
+    CHECK_EQ(decoder->stop(), OK);
+#endif
+
+    return 0;
+}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 1a8d9b6..de01153 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -225,6 +225,35 @@
 
         mSimWatcher = new SimWatcher(mContext);
         sThis.set(this);
+
+        validateAccounts();
+    }
+
+    private void validateAccounts() {
+        boolean accountDeleted = false;
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        Cursor cursor = db.query(TABLE_ACCOUNTS,
+                new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
+                null, null, null, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                final long accountId = cursor.getLong(0);
+                final String accountType = cursor.getString(1);
+                final String accountName = cursor.getString(2);
+                if (mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(accountType))
+                        == null) {
+                    Log.d(TAG, "deleting account " + accountName + " because type "
+                            + accountType + " no longer has a registered authenticator");
+                    db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
+                    accountDeleted = true;
+                }
+            }
+        } finally {
+            cursor.close();
+            if (accountDeleted) {
+                sendAccountsChangedBroadcast();
+            }
+        }
     }
 
     public void onServiceChanged(AuthenticatorDescription desc, boolean removed) {
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 90cff6b..5eb655a 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -100,9 +100,14 @@
     /** Connection canceled before completetion. */
     public static final int RESULT_CANCELED = 2;
 
-    /** Default priority for headsets that should be auto-connected */
-    public static final int PRIORITY_AUTO = 100;
-    /** Default priority for headsets that should not be auto-connected */
+    /** Default priority for headsets that  for which we will accept
+     * inconing connections and auto-connect */
+    public static final int PRIORITY_AUTO_CONNECT = 1000;
+    /** Default priority for headsets that  for which we will accept
+     * inconing connections but not auto-connect */
+    public static final int PRIORITY_ON = 100;
+    /** Default priority for headsets that should not be auto-connected
+     * and not allow incoming connections. */
     public static final int PRIORITY_OFF = 0;
 
     /** The voice dialer 'works' but the user experience is poor. The voice
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6ba79b4..8d69814 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -26,6 +26,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -2417,6 +2418,7 @@
     private int mFlags;
     private HashSet<String> mCategories;
     private Bundle mExtras;
+    private Rect mSourceBounds;
 
     // ---------------------------------------------------------------------
 
@@ -2442,6 +2444,9 @@
         if (o.mExtras != null) {
             this.mExtras = new Bundle(o.mExtras);
         }
+        if (o.mSourceBounds != null) {
+            this.mSourceBounds = new Rect(o.mSourceBounds);
+        }
     }
 
     @Override
@@ -2635,7 +2640,7 @@
                     intent.mType = value;
                 }
 
-                // launch  flags
+                // launch flags
                 else if (uri.startsWith("launchFlags=", i)) {
                     intent.mFlags = Integer.decode(value).intValue();
                 }
@@ -2655,6 +2660,11 @@
                     scheme = value;
                 }
 
+                // source bounds
+                else if (uri.startsWith("sourceBounds=", i)) {
+                    intent.mSourceBounds = Rect.unflattenFromString(value);
+                }
+
                 // extra
                 else {
                     String key = Uri.decode(uri.substring(i + 2, eq));
@@ -3547,6 +3557,15 @@
     }
 
     /**
+     * Get the bounds of the sender of this intent, in screen coordinates.  This can be
+     * used as a hint to the receiver for animations and the like.  Null means that there
+     * is no source bounds.
+     */
+    public Rect getSourceBounds() {
+        return mSourceBounds;
+    }
+
+    /**
      * Return the Activity component that should be used to handle this intent.
      * The appropriate component is determined based on the information in the
      * intent, evaluated as follows:
@@ -4648,6 +4667,19 @@
     }
 
     /**
+     * Set the bounds of the sender of this intent, in screen coordinates.  This can be
+     * used as a hint to the receiver for animations and the like.  Null means that there
+     * is no source bounds.
+     */
+    public void setSourceBounds(Rect r) {
+        if (r != null) {
+            mSourceBounds = new Rect(r);
+        } else {
+            r = null;
+        }
+    }
+
+    /**
      * Use with {@link #fillIn} to allow the current action value to be
      * overwritten, even if it is already set.
      */
@@ -4678,6 +4710,12 @@
     public static final int FILL_IN_PACKAGE = 1<<4;
 
     /**
+     * Use with {@link #fillIn} to allow the current package value to be
+     * overwritten, even if it is already set.
+     */
+    public static final int FILL_IN_SOURCE_BOUNDS = 1<<5;
+
+    /**
      * Copy the contents of <var>other</var> in to this object, but only
      * where fields are not defined by this object.  For purposes of a field
      * being defined, the following pieces of data in the Intent are
@@ -4691,6 +4729,7 @@
      * <li> package, as set by {@link #setPackage}.
      * <li> component, as set by {@link #setComponent(ComponentName)} or
      * related methods.
+     * <li> source bounds, as set by {@link #setSourceBounds}
      * <li> each top-level name in the associated extras.
      * </ul>
      *
@@ -4752,6 +4791,11 @@
             changes |= FILL_IN_COMPONENT;
         }
         mFlags |= other.mFlags;
+        if (other.mSourceBounds != null
+                && (mSourceBounds == null || (flags&FILL_IN_SOURCE_BOUNDS) != 0)) {
+            mSourceBounds = new Rect(other.mSourceBounds);
+            changes |= FILL_IN_SOURCE_BOUNDS;
+        }
         if (mExtras == null) {
             if (other.mExtras != null) {
                 mExtras = new Bundle(other.mExtras);
@@ -5005,6 +5049,13 @@
             first = false;
             b.append("cmp=").append(mComponent.flattenToShortString());
         }
+        if (mSourceBounds != null) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("bnds=").append(mSourceBounds.toShortString());
+        }
         if (extras && mExtras != null) {
             if (!first) {
                 b.append(' ');
@@ -5096,6 +5147,11 @@
             uri.append("component=").append(Uri.encode(
                     mComponent.flattenToShortString(), "/")).append(';');
         }
+        if (mSourceBounds != null) {
+            uri.append("sourceBounds=")
+                    .append(Uri.encode(mSourceBounds.flattenToString()))
+                    .append(';');
+        }
         if (mExtras != null) {
             for (String key : mExtras.keySet()) {
                 final Object value = mExtras.get(key);
@@ -5139,6 +5195,13 @@
         out.writeString(mPackage);
         ComponentName.writeToParcel(mComponent, out);
 
+        if (mSourceBounds != null) {
+            out.writeInt(1);
+            mSourceBounds.writeToParcel(out, flags);
+        } else {
+            out.writeInt(0);
+        }
+
         if (mCategories != null) {
             out.writeInt(mCategories.size());
             for (String category : mCategories) {
@@ -5174,6 +5237,10 @@
         mPackage = in.readString();
         mComponent = ComponentName.readFromParcel(in);
 
+        if (in.readInt() != 0) {
+            mSourceBounds = Rect.CREATOR.createFromParcel(in);
+        }
+
         int N = in.readInt();
         if (N > 0) {
             mCategories = new HashSet<String>();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e2030be..03d2a6d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1656,21 +1656,19 @@
             IPackageStatsObserver observer);
 
     /**
-     * Add a new package to the list of preferred packages.  This new package
-     * will be added to the front of the list (removed from its current location
-     * if already listed), meaning it will now be preferred over all other
-     * packages when resolving conflicts.
-     *
-     * @param packageName The package name of the new package to make preferred.
+     * @deprecated This function no longer does anything; it was an old
+     * approach to managing preferred activities, which has been superceeded
+     * (and conflicts with) the modern activity-based preferences.
      */
+    @Deprecated
     public abstract void addPackageToPreferred(String packageName);
 
     /**
-     * Remove a package from the list of preferred packages.  If it was on
-     * the list, it will no longer be preferred over other packages.
-     *
-     * @param packageName The package name to remove.
+     * @deprecated This function no longer does anything; it was an old
+     * approach to managing preferred activities, which has been superceeded
+     * (and conflicts with) the modern activity-based preferences.
      */
+    @Deprecated
     public abstract void removePackageFromPreferred(String packageName);
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 657bbcc..d9003a3 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -827,6 +827,15 @@
     }
 
     private void closeClosable() {
+        /* deallocate all compiled sql statement objects in compiledQueries cache.
+         * this should be done before de-referencing all {@link SQLiteClosable} objects
+         * from this database object because calling
+         * {@link SQLiteClosable#onAllReferencesReleasedFromContainer()} could cause the database
+         * to be closed. sqlite doesn't let a database close if there are
+         * any unfinalized statements - such as the compiled-sql objects in mCompiledQueries.
+         */
+        resetCompiledSqlCache();
+ 
         Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator();
         while (iter.hasNext()) {
             Map.Entry<SQLiteClosable, Object> entry = iter.next();
@@ -835,13 +844,6 @@
                 program.onAllReferencesReleasedFromContainer();
             }
         }
-
-        // finalize all compiled sql statement objects in compiledQueries cache
-        synchronized (mCompiledQueries) {
-            for (SQLiteCompiledSql compiledStatement : mCompiledQueries.values()) {
-                compiledStatement.releaseSqlStatement();
-            }
-        }
     }
 
     /**
@@ -1789,7 +1791,9 @@
      */
     public void setMaxSqlCacheSize(int cacheSize) {
         synchronized(mCompiledQueries) {
-            resetCompiledSqlCache();
+            if (mMaxSqlCacheSize > 0) {
+                resetCompiledSqlCache();
+            }
             mMaxSqlCacheSize = (cacheSize > MAX_SQL_CACHE_SIZE) ? MAX_SQL_CACHE_SIZE
                     : (cacheSize < 0) ? 0 : cacheSize;
         }
@@ -1800,6 +1804,9 @@
      */
     public void resetCompiledSqlCache() {
         synchronized(mCompiledQueries) {
+            for (SQLiteCompiledSql compiledStatement : mCompiledQueries.values()) {
+                compiledStatement.releaseSqlStatement();
+            }
             mCompiledQueries.clear();
         }
     }
@@ -1835,7 +1842,7 @@
                 /* reached max cachesize. before adding new entry, remove an entry from the
                  * cache. we don't want to wipe out the entire cache because of this:
                  * GCing {@link SQLiteCompiledSql} requires call to sqlite3_finalize
-                 * JNI method. If entire cache is wiped out, it could be cause a big GC activity
+                 * JNI method. If entire cache is wiped out, it could cause a big GC activity
                  * just because a (rogue) process is using the cache incorrectly.
                  */
                 Set<String> keySet = mCompiledQueries.keySet();
@@ -1844,8 +1851,7 @@
                     break;
                 }
             }
-            compiledSql = new SQLiteCompiledSql(this, sql);
-            mCompiledQueries.put(sql, compiledSql);
+            mCompiledQueries.put(sql, compiledStatement);
         }
         if (SQLiteDebug.DEBUG_SQL_CACHE) {
             Log.v(TAG, "|adding_sql_to_cache|" + getPath() + "|" + mCompiledQueries.size() + "|" +
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 0418324..5ee2f1e 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -76,7 +76,7 @@
     @Override
     protected void onAllReferencesReleased() {
         // release the compiled sql statement used by me if it is NOT in cache
-        if (!myCompiledSqlIsInCache) {
+        if (!myCompiledSqlIsInCache && compiledSql != null) {
             compiledSql.releaseSqlStatement();
             compiledSql = null; // so that GC doesn't call finalize() on it
         }
@@ -87,7 +87,7 @@
     @Override
     protected void onAllReferencesReleasedFromContainer() {
         // release the compiled sql statement used by me if it is NOT in cache
-        if (!myCompiledSqlIsInCache) {
+      if (!myCompiledSqlIsInCache && compiledSql != null) {
             compiledSql.releaseSqlStatement();
             compiledSql = null; // so that GC doesn't call finalize() on it
         }
@@ -100,7 +100,7 @@
      * @return a unique identifier for this program
      */
     public final int getUniqueId() {
-        return compiledSql.nStatement;
+        return  (compiledSql != null) ? compiledSql.nStatement : 0;
     }
 
     /* package */ String getSqlString() {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 4b733ef..ac159f4 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -477,6 +477,10 @@
      * application does not need a particular callback, a null can be passed
      * instead of a callback method.
      *
+     * This method will stop the preview. Applications should not call {@link
+     * #stopPreview()} before this. After jpeg callback is received,
+     * applications can call {@link #startPreview()} to restart the preview.
+     *
      * @param shutter   callback after the image is captured, may be null
      * @param raw       callback with raw image data, may be null
      * @param jpeg      callback with jpeg image data, may be null
@@ -500,6 +504,10 @@
      * application does not need a particular callback, a null can be passed
      * instead of a callback method.
      *
+     * This method will stop the preview. Applications should not call {@link
+     * #stopPreview()} before this. After jpeg callback is received,
+     * applications can call {@link #startPreview()} to restart the preview.
+     *
      * @param shutter   callback after the image is captured, may be null
      * @param raw       callback with raw image data, may be null
      * @param postview  callback with postview image data, may be null
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index c3b0f1c..30c73d7 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -293,6 +293,13 @@
         public static final String DISPLAY_NAME = "display_name";
 
         /**
+         * Reference to the row in the RawContacts table holding the contact name.
+         * <P>Type: INTEGER REFERENCES raw_contacts(_id)</P>
+         * @hide
+         */
+        public static final String NAME_RAW_CONTACT_ID = "name_raw_contact_id";
+
+        /**
          * Reference to the row in the data table holding the photo.
          * <P>Type: INTEGER REFERENCES data(_id)</P>
          */
@@ -423,13 +430,21 @@
      * row id changed as a result of a sync or aggregation.</td>
      * </tr>
      * <tr>
+     * <td>long</td>
+     * <td>NAME_RAW_CONTACT_ID</td>
+     * <td>read-only</td>
+     * <td>The ID of the raw contact that contributes the display name
+     * to the aggregate contact. During aggregation one of the constituent
+     * raw contacts is chosen using a heuristic: a longer name or a name
+     * with more diacritic marks or more upper case characters is chosen.</td>
+     * </tr>
+     * <tr>
      * <td>String</td>
      * <td>{@link #DISPLAY_NAME}</td>
      * <td>read-only</td>
-     * <td>The display name for the contact. During aggregation display name is
-     * computed from display names of constituent raw contacts using a
-     * heuristic: a longer name or a name with more diacritic marks or more
-     * upper case characters is chosen.</td>
+     * <td>The display name for the contact. It is the display name
+     * contributed by the raw contact referred to by the NAME_RAW_CONTACT_ID
+     * column.</td>
      * </tr>
      * <tr>
      * <td>long</td>
diff --git a/core/java/android/provider/Im.java b/core/java/android/provider/Im.java
index 025d5c2..ff52199 100644
--- a/core/java/android/provider/Im.java
+++ b/core/java/android/provider/Im.java
@@ -879,7 +879,7 @@
          * The thread_id column stores the contact id of the contact the message belongs to.
          * For groupchat messages, the thread_id stores the group id, which is the contact id
          * of the temporary group contact created for the groupchat. So there should be no
-         * collision between groupchat message thread id and regular message thread id. 
+         * collision between groupchat message thread id and regular message thread id.
          */
         String THREAD_ID = "thread_id";
 
@@ -947,6 +947,12 @@
          * <P>Type: INTEGER</P>
          */
         String DISPLAY_SENT_TIME = "show_ts";
+
+        /*
+         * For rows which have been consolidated this is the row id of the
+         * row into which they have been consolidated.
+         */
+        String CONSOLIDATION_KEY = "consolidation_key";
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index df40946..e826db9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1434,6 +1434,13 @@
         public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
 
         /**
+         * Whether the notification LED should repeatedly flash when a notification is
+         * pending. The value is boolean (1 or 0).
+         * @hide
+         */
+        public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          * @hide
@@ -1487,7 +1494,8 @@
             TTY_MODE,
             SOUND_EFFECTS_ENABLED,
             HAPTIC_FEEDBACK_ENABLED,
-            SHOW_WEB_SUGGESTIONS
+            SHOW_WEB_SUGGESTIONS,
+            NOTIFICATION_LIGHT_PULSE
         };
 
         // Settings moved to Settings.Secure
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 6380a8d..4860cbd 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -553,7 +553,8 @@
              *   <li><em>transactionId (Integer)</em> - The WAP transaction
              *    ID</li>
              *   <li><em>pduType (Integer)</em> - The WAP PDU type</li>
-             *   <li><em>data</em> - The data payload of the message</li>
+             *   <li><em>header (byte[])</em> - The header of the message</li>
+             *   <li><em>data (byte[])</em> - The data payload of the message</li>
              * </ul>
              *
              * <p>If a BroadcastReceiver encounters an error while processing
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 2c24817..46de708 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -328,9 +328,6 @@
             return true;
         }
 
-        // Sink is being disconnected, downgrade priority from AUTO_CONNECT.
-        setSinkPriority(device, BluetoothA2dp.PRIORITY_ON);
-
         // State is CONNECTING or CONNECTED or PLAYING
         if (!disconnectSinkNative(path)) {
             return false;
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index cb95396..f8592e2 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -344,14 +344,14 @@
                 // records, use a DBUS call instead.
                 switch (msg.arg1) {
                 case 1:
-                    Log.d(TAG, "Registering hsag record");
-                    SystemService.start("hsag");
+                    Log.d(TAG, "Registering hfag record");
+                    SystemService.start("hfag");
                     mHandler.sendMessageDelayed(
                             mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 2, -1), 500);
                     break;
                 case 2:
-                    Log.d(TAG, "Registering hfag record");
-                    SystemService.start("hfag");
+                    Log.d(TAG, "Registering hsag record");
+                    SystemService.start("hsag");
                     mHandler.sendMessageDelayed(
                             mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 3, -1), 500);
                     break;
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index 6995107..aa8d979 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -20,6 +20,7 @@
 import android.text.NoCopySpan;
 import android.text.Layout.Alignment;
 import android.text.Spannable;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 import android.widget.TextView;
@@ -156,8 +157,17 @@
                                                             padding));
                     ny = Math.max(ny, 0);
         
+                    int oldX = widget.getScrollX();
+                    int oldY = widget.getScrollY();
+
                     scrollTo(widget, layout, nx, ny);
-                    widget.cancelLongPress();
+
+                    // If we actually scrolled, then cancel the up action.
+                    if (oldX != widget.getScrollX()
+                            || oldY != widget.getScrollY()) {
+                        widget.cancelLongPress();
+                    }
+
                     return true;
                 }
             }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b8bd6a0..5d3840a 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -361,6 +361,8 @@
     public final int OFF_BECAUSE_OF_USER = 1;
     /** Screen turned off because of timeout */
     public final int OFF_BECAUSE_OF_TIMEOUT = 2;
+    /** Screen turned off because of proximity sensor */
+    public final int OFF_BECAUSE_OF_PROX_SENSOR = 3;
 
     /**
      * Magic constant to {@link IWindowManager#setRotation} to not actually
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index e6e26fa..1496f1b 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -105,10 +105,13 @@
      */
     public BrowserFrame(Context context, WebViewCore w, CallbackProxy proxy,
             WebSettings settings, Map<String, Object> javascriptInterfaces) {
+
+        Context appContext = context.getApplicationContext();
+
         // Create a global JWebCoreJavaBridge to handle timers and
         // cookies in the WebCore thread.
         if (sJavaBridge == null) {
-            sJavaBridge = new JWebCoreJavaBridge(context);
+            sJavaBridge = new JWebCoreJavaBridge(appContext);
             // set WebCore native cache size
             ActivityManager am = (ActivityManager) context
                     .getSystemService(Context.ACTIVITY_SERVICE);
@@ -118,18 +121,18 @@
                 sJavaBridge.setCacheSize(4 * 1024 * 1024);
             }
             // initialize CacheManager
-            CacheManager.init(context);
+            CacheManager.init(appContext);
             // create CookieSyncManager with current Context
-            CookieSyncManager.createInstance(context);
+            CookieSyncManager.createInstance(appContext);
             // create PluginManager with current Context
-            PluginManager.getInstance(context);
+            PluginManager.getInstance(appContext);
         }
         mJSInterfaceMap = javascriptInterfaces;
 
         mSettings = settings;
         mContext = context;
         mCallbackProxy = proxy;
-        mDatabase = WebViewDatabase.getInstance(context);
+        mDatabase = WebViewDatabase.getInstance(appContext);
         mWebViewCore = w;
 
         AssetManager am = context.getAssets();
@@ -496,7 +499,7 @@
      * @param uri A String representing the URI of the desired file.
      * @param buffer The byte array to copy the data into.
      * @param offset The offet into buffer to place the data.
-     * @param expectSize The size that the buffer has allocated for this file.
+     * @param expectedSize The size that the buffer has allocated for this file.
      * @return int The size of the given file, or zero if it fails.
      */
     private int getFile(String uri, byte[] buffer, int offset,
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index c167414..c4e26bc 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -167,7 +167,7 @@
      * @param context The application context.
      */
     static void init(Context context) {
-        mDataBase = WebViewDatabase.getInstance(context);
+        mDataBase = WebViewDatabase.getInstance(context.getApplicationContext());
         mBaseDir = new File(context.getCacheDir(), "webviewCache");
         if (createCacheDirectory() && mClearCacheOnInit) {
             removeAllCacheFiles();
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index 14375d2..abe9178 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -93,7 +93,7 @@
     public static synchronized CookieSyncManager createInstance(
             Context context) {
         if (sRef == null) {
-            sRef = new CookieSyncManager(context);
+            sRef = new CookieSyncManager(context.getApplicationContext());
         }
         return sRef;
     }
diff --git a/core/java/android/webkit/PluginActivity.java b/core/java/android/webkit/PluginActivity.java
index 22d6ccb..c60512b 100644
--- a/core/java/android/webkit/PluginActivity.java
+++ b/core/java/android/webkit/PluginActivity.java
@@ -18,18 +18,19 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.View;
 import android.webkit.plugin.SurfaceDrawingModel;
 import android.webkit.plugin.WebkitPlugin;
 
 /**
- * This activity  is invoked when a plugin elects to go into full screen mode.
+ * This activity is invoked when a plugin elects to go into full screen mode.
  * @hide
  */
 public class PluginActivity extends Activity {
 
-    /* package */ static final String INTENT_EXTRA_PACKAGE_NAME =
-            "android.webkit.plugin.PACKAGE_NAME";
+    private static final String LOGTAG = "PluginActivity";
+    
     /* package */ static final String INTENT_EXTRA_NPP_INSTANCE =
             "android.webkit.plugin.NPP_INSTANCE";
 
@@ -40,24 +41,30 @@
 
         final Intent intent = getIntent();
         if (intent == null) {
-            // No intent means no class to lookup.
+            Log.e(LOGTAG, "Unable to retrieve the intent responsible for this activity");
             finish();
             return;
         }
-        final String pkgName = intent.getStringExtra(INTENT_EXTRA_PACKAGE_NAME);
+
         final int npp = intent.getIntExtra(INTENT_EXTRA_NPP_INSTANCE, -1);
 
-        // XXX retrieve the existing object instead of creating a new one
-        WebkitPlugin plugin = PluginManager.getInstance(null).getPluginInstance(pkgName, npp);
+        if (npp == -1) {
+            Log.e(LOGTAG, "The intent did not include the NPP pointer");
+            finish();
+            return;
+        }
+
+        // retrieve the plugin's existing java object instead of creating a new one
+        WebkitPlugin plugin = nativeGetWebkitPlugin(npp);
 
         if (plugin == null) {
-            //TODO log error
+            Log.e(LOGTAG, "Unable to retrieve the plugin's java interface");
             finish();
             return;
         }
         SurfaceDrawingModel fullScreenSurface = plugin.getFullScreenSurface();
-        if(fullScreenSurface == null) {
-            //TODO log error
+        if (fullScreenSurface == null) {
+            Log.e(LOGTAG, "The plugin returned a null value for the full-screen interface");
             finish();
             return;
         }
@@ -67,7 +74,10 @@
         } else {
             // No custom full-sreen view returned by the plugin, odd but
             // just in case, finish the activity.
+            Log.e(LOGTAG, "The plugin's full-screen interface returned a null view");
             finish();
         }
     }
+
+    native WebkitPlugin nativeGetWebkitPlugin(int npp);
 }
diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java
index 88429c5..141984a 100644
--- a/core/java/android/webkit/PluginManager.java
+++ b/core/java/android/webkit/PluginManager.java
@@ -96,7 +96,7 @@
                 throw new IllegalStateException(
                         "First call to PluginManager need a valid context.");
             }
-            mInstance = new PluginManager(context);
+            mInstance = new PluginManager(context.getApplicationContext());
         }
         return mInstance;
     }
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 8e40b23..d5bb572 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -152,6 +152,7 @@
     private int             mMinimumLogicalFontSize = 8;
     private int             mDefaultFontSize = 16;
     private int             mDefaultFixedFontSize = 13;
+    private int             mPageCacheCapacity = 0;
     private boolean         mLoadsImagesAutomatically = true;
     private boolean         mBlockNetworkImage = false;
     private boolean         mBlockNetworkLoads;
@@ -879,6 +880,20 @@
     }
 
     /**
+     * Set the number of pages cached by the WebKit for the history navigation.
+     * @param size A non-negative integer between 0 (no cache) and 20 (max).
+     * @hide
+     */
+    public synchronized void setPageCacheCapacity(int size) {
+        if (size < 0) size = 0;
+        if (size > 20) size = 20;
+        if (mPageCacheCapacity != size) {
+            mPageCacheCapacity = size;
+            postSync();
+        }
+    }
+
+    /**
      * Tell the WebView to load image resources automatically.
      * @param flag True if the WebView should load images automatically.
      */
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 71b1f9f..f04b04f 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -103,6 +103,9 @@
     // do not want to pass this change to webkit.
     private boolean         mFromSetInputType;
     private boolean         mGotTouchDown;
+    // Keep track of whether a long press has happened.  Only meaningful after
+    // an ACTION_DOWN MotionEvent
+    private boolean         mHasPerformedLongClick;
     private boolean         mInSetTextAndKeepSelection;
     // Array to store the final character added in onTextChanged, so that its
     // KeyEvents may be determined.
@@ -453,8 +456,13 @@
             mDragSent = false;
             mScrolled = false;
             mGotTouchDown = true;
+            mHasPerformedLongClick = false;
             break;
         case MotionEvent.ACTION_MOVE:
+            if (mHasPerformedLongClick) {
+                mGotTouchDown = false;
+                return false;
+            }
             int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
             Spannable buffer = getText();
             int initialScrollX = Touch.getInitialScrollX(this, buffer);
@@ -478,6 +486,7 @@
                             mScrollX / maxScrollX : 0, mScrollY);
                 }
                 mScrolled = true;
+                cancelLongPress();
                 return true;
             }
             if (Math.abs((int) event.getX() - mDragStartX) < slop
@@ -504,6 +513,10 @@
             return false;
         case MotionEvent.ACTION_UP:
         case MotionEvent.ACTION_CANCEL:
+            if (mHasPerformedLongClick) {
+                mGotTouchDown = false;
+                return false;
+            }
             if (!mScrolled) {
                 // If the page scrolled, or the TextView scrolled, we do not
                 // want to change the selection
@@ -547,6 +560,12 @@
         return false;
     }
 
+    @Override
+    public boolean performLongClick() {
+        mHasPerformedLongClick = true;
+        return super.performLongClick();
+    }
+
     /**
      * Remove this WebTextView from its host WebView, and return
      * focus to the host.
@@ -625,7 +644,22 @@
     /* package */ void setDefaultSelection() {
         Spannable text = (Spannable) getText();
         int selection = mSingle ? text.length() : 0;
-        Selection. setSelection(text, selection, selection);
+        if (Selection.getSelectionStart(text) == selection
+                && Selection.getSelectionEnd(text) == selection) {
+            // The selection of the UI copy is set correctly, but the
+            // WebTextView still needs to inform the webkit thread to set the
+            // selection.  Normally that is done in onSelectionChanged, but
+            // onSelectionChanged will not be called because the UI copy is not
+            // changing.  (This can happen when the WebTextView takes focus.
+            // That onSelectionChanged was blocked because the selection set
+            // when focusing is not necessarily the desirable selection for
+            // WebTextView.)
+            if (mWebView != null) {
+                mWebView.setSelection(selection, selection);
+            }
+        } else {
+            Selection.setSelection(text, selection, selection);
+        }
     }
 
     /**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3207c79..7885b8a 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -732,7 +732,7 @@
     /**
      * Construct a new WebView with layout parameters, a default style and a set
      * of custom Javscript interfaces to be added to the WebView at initialization
-     * time. This guraratees that these interfaces will be available when the JS
+     * time. This guarantees that these interfaces will be available when the JS
      * context is initialized.
      * @param context A Context object used to access application assets.
      * @param attrs An AttributeSet passed to our parent.
@@ -3241,24 +3241,29 @@
             mWebTextView.setNodePointer(nodePointer);
             int maxLength = -1;
             boolean isTextField = nativeFocusCandidateIsTextField();
+            boolean isPassword;
             if (isTextField) {
                 maxLength = nativeFocusCandidateMaxLength();
                 String name = nativeFocusCandidateName();
-                if (mWebViewCore.getSettings().getSaveFormData()
-                        && name != null) {
+                isPassword = nativeFocusCandidateIsPassword();
+                if (!isPassword && mWebViewCore.getSettings().getSaveFormData()
+                        && name != null && name.length() > 0) {
                     Message update = mPrivateHandler.obtainMessage(
-                            REQUEST_FORM_DATA, nodePointer);
+                            REQUEST_FORM_DATA);
+                    update.arg1 = nodePointer;
                     RequestFormData updater = new RequestFormData(name,
                             getUrl(), update);
                     Thread t = new Thread(updater);
                     t.start();
                 }
+            } else {
+                isPassword = false;
             }
             mWebTextView.setMaxLength(maxLength);
             AutoCompleteAdapter adapter = null;
             mWebTextView.setAdapterCustom(adapter);
             mWebTextView.setSingleLine(isTextField);
-            mWebTextView.setInPassword(nativeFocusCandidateIsPassword());
+            mWebTextView.setInPassword(isPassword);
             if (null == text) {
                 if (DebugFlags.WEB_VIEW) {
                     Log.v(LOGTAG, "rebuildWebTextView null == text");
@@ -3990,6 +3995,13 @@
                     }
 
                     mTouchMode = TOUCH_DRAG_MODE;
+                    mLastTouchX = x;
+                    mLastTouchY = y;
+                    fDeltaX = 0.0f;
+                    fDeltaY = 0.0f;
+                    deltaX = 0;
+                    deltaY = 0;
+
                     WebViewCore.pauseUpdate(mWebViewCore);
                     if (!mDragFromTextInput) {
                         nativeHideCursor();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index be36fe0..33f3713c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2216,19 +2216,12 @@
 
     // called by JNI. PluginWidget function to launch an activity and overlays
     // the activity with the View provided by the plugin class.
-    private void startFullScreenPluginActivity(String libName, int npp) {
+    private void startFullScreenPluginActivity(int npp) {
         if (mWebView == null) {
             return;
         }
 
-        String pkgName = PluginManager.getInstance(null).getPluginsAPKName(libName);
-        if (pkgName == null) {
-            Log.w(LOGTAG, "Unable to resolve " + libName + " to a plugin APK");
-            return;
-        }
-
         Intent intent = new Intent("android.intent.webkit.PLUGIN");
-        intent.putExtra(PluginActivity.INTENT_EXTRA_PACKAGE_NAME, pkgName);
         intent.putExtra(PluginActivity.INTENT_EXTRA_NPP_INSTANCE, npp);
         mWebView.getContext().startActivity(intent);
     }
@@ -2249,6 +2242,7 @@
         }
 
         View pluginView = embeddedSurface.getSurface();
+        pluginView.setWillNotDraw(false);
 
         ViewManager.ChildView view = mWebView.mViewManager.createView();
         view.mView = pluginView;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 3b1f7a0..b847e57 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -23,6 +23,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Parcel;
@@ -136,10 +137,15 @@
             if (target != null && pendingIntent != null) {
                 OnClickListener listener = new OnClickListener() {
                     public void onClick(View v) {
+                        int[] pos = new int[2];
+                        v.getLocationOnScreen(pos);
+                        Intent intent = new Intent();
+                        intent.setSourceBounds(new Rect(pos[0], pos[1],
+                                    pos[0]+v.getWidth(), pos[1]+v.getHeight()));
                         try {
                             // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
                             v.getContext().startIntentSender(
-                                    pendingIntent.getIntentSender(), null,
+                                    pendingIntent.getIntentSender(), intent,
                                     Intent.FLAG_ACTIVITY_NEW_TASK,
                                     Intent.FLAG_ACTIVITY_NEW_TASK, 0);
                         } catch (IntentSender.SendIntentException e) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 24d97a5..bf16e28 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -51,8 +51,6 @@
  * <p>ScrollView only supports vertical scrolling.
  */
 public class ScrollView extends FrameLayout {
-    static final String TAG = "ScrollView";
-    
     static final int ANIMATED_SCROLL_GAP = 250;
 
     static final float MAX_SCROLL_FACTOR = 0.5f;
@@ -401,6 +399,7 @@
                 final int yDiff = (int) Math.abs(y - mLastMotionY);
                 if (yDiff > mTouchSlop) {
                     mIsBeingDragged = true;
+                    mLastMotionY = y;
                 }
                 break;
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f55ca3f..201cc0c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6529,6 +6529,7 @@
             // Reset this state; it will be re-set if super.onTouchEvent
             // causes focus to move to the view.
             mTouchFocusSelected = false;
+            mScrolled = false;
         }
         
         final boolean superResult = super.onTouchEvent(event);
@@ -6545,10 +6546,6 @@
 
         if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
             
-            if (action == MotionEvent.ACTION_DOWN) {
-                mScrolled = false;
-            }
-            
             boolean handled = false;
             
             int oldSelStart = Selection.getSelectionStart(mText);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8047436..4a7adcc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -597,11 +597,9 @@
         android:label="@string/permlab_getPackageSize"
         android:description="@string/permdesc_getPackageSize" />
 
-    <!-- Allows an application to modify the list of preferred applications
-         with the {@link android.content.pm.PackageManager#addPackageToPreferred
-         PackageManager.addPackageToPreferred()} and
-         {@link android.content.pm.PackageManager#removePackageFromPreferred
-         PackageManager.removePackageFromPreferred()} methods. -->
+    <!-- @deprecated No longer useful, see
+         {@link android.content.pm.PackageManager#addPackageToPreferred}
+         for details. -->
     <permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="dangerous"
diff --git a/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png
new file mode 100644
index 0000000..617dba3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_lock_normal.9.png b/core/res/res/drawable-hdpi/btn_lock_normal.9.png
deleted file mode 100644
index f1dac62..0000000
--- a/core/res/res/drawable-hdpi/btn_lock_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_half.png b/core/res/res/drawable-hdpi/rate_star_big_half.png
index 61906a5..4a91e87 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_half.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_off.png b/core/res/res/drawable-hdpi/rate_star_big_off.png
index a688a45..ae5883e 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_off.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_on.png b/core/res/res/drawable-hdpi/rate_star_big_on.png
index 77cb067..65c136e 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_on.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_half.png b/core/res/res/drawable-hdpi/rate_star_med_half.png
new file mode 100644
index 0000000..a436980
--- /dev/null
+++ b/core/res/res/drawable-hdpi/rate_star_med_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_off.png b/core/res/res/drawable-hdpi/rate_star_med_off.png
new file mode 100644
index 0000000..981aabe
--- /dev/null
+++ b/core/res/res/drawable-hdpi/rate_star_med_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_on.png b/core/res/res/drawable-hdpi/rate_star_med_on.png
new file mode 100644
index 0000000..320c14f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/rate_star_med_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_half.png b/core/res/res/drawable-hdpi/rate_star_small_half.png
index 6b2efd9..0b8974e 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_half.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_off.png b/core/res/res/drawable-hdpi/rate_star_small_off.png
index 8422919..7ae305f 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_off.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_on.png b/core/res/res/drawable-hdpi/rate_star_small_on.png
index 45e2324..ffa5258 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_on.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png
new file mode 100644
index 0000000..3b3dea9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_lock_normal.9.png b/core/res/res/drawable-mdpi/btn_lock_normal.9.png
deleted file mode 100644
index 6bdc2c6..0000000
--- a/core/res/res/drawable-mdpi/btn_lock_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/btn_default_transparent.xml b/core/res/res/drawable/btn_default_transparent.xml
new file mode 100644
index 0000000..f8e03ee
--- /dev/null
+++ b/core/res/res/drawable/btn_default_transparent.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" 
+        android:drawable="@drawable/btn_default_pressed" />
+    <item android:state_focused="true" android:state_enabled="true"
+        android:drawable="@drawable/btn_default_selected" />
+    <item android:state_enabled="true"
+        android:drawable="@drawable/btn_default_transparent_normal" />
+</selector>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 26b77bb..f8944b5 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -136,8 +136,10 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/screenLocked"
-        android:layout_marginTop="24dip"
+        android:layout_marginTop="8dip"
+        android:layout_marginLeft="24dip"
         android:drawableLeft="@drawable/ic_emergency"
+        style="@style/Widget.Button.Transparent"
         android:drawablePadding="8dip"
        />
 
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 5c80235..22c0b8e 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -128,8 +128,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@id/screenLocked"
-            android:layout_marginTop="24dip"
+            android:layout_marginTop="8dip"
             android:drawableLeft="@drawable/ic_emergency"
+            style="@style/Widget.Button.Transparent"
             android:drawablePadding="8dip"
            />
     </RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 6da82e9..602a37c 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -155,10 +155,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:text="@string/lockscreen_emergency_call"
-                    android:textSize="14sp"
-                    android:background="@drawable/btn_lock_normal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:textColor="?android:attr/textColorPrimary"
+                    style="@style/Widget.Button.Transparent"
                     android:drawableLeft="@drawable/ic_emergency"
                     android:drawablePadding="8dip"
                     />
@@ -174,20 +171,14 @@
                 <Button android:id="@+id/forgotPattern"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
-                    android:textSize="14sp"
-                    android:background="@drawable/btn_lock_normal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:textColor="?android:attr/textColorPrimary"
+                    style="@style/Widget.Button.Transparent"
                     android:visibility="invisible"
                     />
                 <Button android:id="@+id/emergencyCallTogether"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/lockscreen_emergency_call"
-                    android:textSize="14sp"
-                    android:background="@drawable/btn_lock_normal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:textColor="?android:attr/textColorPrimary"
+                    style="@style/Widget.Button.Transparent"
                     android:drawableLeft="@drawable/ic_emergency"
                     android:drawablePadding="8dip"
                     />
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 5916786..9ce5a25 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -165,9 +165,7 @@
                 android:layout_height="wrap_content"
                 android:layout_centerInParent="true"
                 android:text="@string/lockscreen_emergency_call"
-                android:background="@drawable/btn_lock_normal"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/Widget.Button.Transparent"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 />
@@ -190,9 +188,7 @@
                 android:layout_marginLeft="4dip"
                 android:layout_marginRight="2dip"
                 android:text="@string/lockscreen_emergency_call"
-                android:background="@drawable/btn_lock_normal"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/Widget.Button.Transparent"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 />
@@ -204,9 +200,7 @@
                 android:layout_marginBottom="4dip"
                 android:layout_marginLeft="2dip"
                 android:layout_marginRight="4dip"
-                android:background="@drawable/btn_lock_normal"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/Widget.Button.Transparent"
                 android:visibility="invisible"
                 />
         </LinearLayout>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a629bb2..c95ede7 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -237,6 +237,12 @@
         <item name="android:background">@android:drawable/button_inset</item>
     </style>
 
+    <style name="Widget.Button.Transparent">
+        <item name="android:background">@android:drawable/btn_default_transparent</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+        <item name="android:textColor">@android:color/white</item>
+    </style>
+
     <style name="Widget.CompoundButton">
         <item name="android:focusable">true</item>
         <item name="android:clickable">true</item>
diff --git a/docs/html/guide/appendix/api-levels.jd b/docs/html/guide/appendix/api-levels.jd
index 5487487..2c255a99 100644
--- a/docs/html/guide/appendix/api-levels.jd
+++ b/docs/html/guide/appendix/api-levels.jd
@@ -123,7 +123,9 @@
 API Level, rather than being restricted to using only those defined 
 for the minimum API Level.</li>
 <li><code>android:maxSdkVersion</code> &mdash; Specifies the maximum API Level
-on which the application is able to run.</li>
+on which the application is able to run. <strong>Important:</strong> Please read the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+documentation before using this attribute.  </li>
 </ul>
 
 <p>For example, to specify the minimum system API Level that an application
@@ -133,10 +135,11 @@
 corresponding to the API Level of the earliest version of the Android platform
 under which the application can run. </p>
 
-<p>When the user attempts to install an application, the Android system first
-checks the <code>&lt;uses-sdk&gt;</code> attributes in the application's
-manifest and compares them against its own internal API Level. The system
-allows the installation to begin only if these conditions are met:</p>
+<p>When the user attempts to install an application, or when revalidating an
+appplication after a system update, the Android system first checks the
+<code>&lt;uses-sdk&gt;</code> attributes in the application's manifest and
+compares the values against its own internal API Level. The system allows the
+installation to begin only if these conditions are met:</p>
 
 <ul>
 <li>If a <code>android:minSdkVersion</code> attribute is declared, its value
@@ -145,7 +148,9 @@
 <li>If a <code>android:maxSdkVersion</code> attribute is declared, its value
 must be equal to or greater than the system's API Level integer. 
 If not declared, the system assumes that the application
-has no maximum API Level. </li>
+has no maximum API Level. Please read the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+documentation for more information about how the system handles this attribute.</li>
 </ul>
 
 <p>When declared in an application's manifest, a <code>&lt;uses-sdk&gt;</code>
diff --git a/docs/html/guide/publishing/versioning.jd b/docs/html/guide/publishing/versioning.jd
index 0bec658..e2ee684 100644
--- a/docs/html/guide/publishing/versioning.jd
+++ b/docs/html/guide/publishing/versioning.jd
@@ -141,9 +141,16 @@
 <li><code>android:minSdkVersion</code> &mdash; The minimum version
 of the Android platform on which the application will run, specified
 by the platform's API Level identifier. </li>
+<li><code>android:targetSdkVersion</code> &mdash; Specifies the API Level
+on which the application is designed to run. In some cases, this allows the
+application to use manifest elements or behaviors defined in the target
+API Level, rather than being restricted to using only those defined 
+for the minimum API Level.</li>
 <li><code>android:maxSdkVersion</code> &mdash; The maximum version
 of the Android platform on which the application is designed to run, 
-specified by the platform's API Level identifier.  </li>
+specified by the platform's API Level identifier. <strong>Important:</strong> Please read the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+documentation before using this attribute. </li>
 </ul>
 
 <p>When preparing to install your application, the system checks the value of this
diff --git a/docs/html/guide/samples/images/BluetoothChat1.png b/docs/html/guide/samples/images/BluetoothChat1.png
new file mode 100644
index 0000000..f87da6a
--- /dev/null
+++ b/docs/html/guide/samples/images/BluetoothChat1.png
Binary files differ
diff --git a/docs/html/guide/samples/images/BluetoothChat2.png b/docs/html/guide/samples/images/BluetoothChat2.png
new file mode 100644
index 0000000..6218eff
--- /dev/null
+++ b/docs/html/guide/samples/images/BluetoothChat2.png
Binary files differ
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index 3fb0172..5494320 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -84,7 +84,7 @@
 <dt>see also:</dt>
 <dd>
   <ul>
-    <li><a href="{@docRoot}guide/practices/screens_suppport.html">Multiple Screens Support</a></li>
+    <li><a href="{@docRoot}guide/practices/screens_support.html">Multiple Screens Support</a></li>
     <li>{@link android.util.DisplayMetrics}</li>
   </ul>
 </dd>
diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd
index aa1e8ae..f8aff1e 100644
--- a/docs/html/guide/topics/manifest/uses-sdk-element.jd
+++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd
@@ -5,8 +5,8 @@
 <dt>syntax:</dt>
 <dd><pre>
 &lt;uses-sdk android:<a href="#min">minSdkVersion</a>="<i>integer</i>" 
-          android:<a href="#max">maxSdkVersion</a>="<i>integer</i>"
-          android:<a href="#target">targetSdkVersion</a>="<i>integer</i>" /&gt;</pre></dd>
+          android:<a href="#target">targetSdkVersion</a>="<i>integer</i>"
+          android:<a href="#max">maxSdkVersion</a>="<i>integer</i>" /&gt;</pre></dd>
 
 <dt>contained in:</dt>
 <dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
@@ -17,19 +17,31 @@
 API Level of a given Android system, which may vary among different Android devices.
 </p>
 
-<p>
-Despite its name, this element is used to specify the API Level, <em>not</em> the 
-version number of the SDK (software development kit).  The API Level is always 
-a single integer; the SDK version may be split into major and minor components 
-(such as 1.5).  You cannot derive the API Level from the SDK version number 
-(for example, it is not the same as the major version or the sum of the major 
-and minor versions).</p>
+<p>Despite its name, this element is used to specify the API Level, <em>not</em>
+the version number of the SDK (software development kit) or Android platform. 
+The API Level is always a single integer. You cannot derive the API Level from
+its associated Android version number (for example, it is not the same as the
+major version or the sum of the major and minor versions).</p>
 
 <p>For more information, read about 
 <a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> and
 <a href="{@docRoot}guide/publishing/versioning.html">Versioning Your Applications</a>.
 </p></dd> 
 
+ <div class="sidebox-wrapper" xstyle="margin-bottom:2em;margin-top:.5em;width:90%;"> 
+  <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png"> 
+  <div id="qv-sub-rule"> 
+    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;"> 
+    <p style="color:#669999;">Android Market and &lt;uses-sdk&gt; attributes</p> 
+    <p>Android Market filters the applications that are visible to users, so
+that users can only see and download applications that are compatible with their
+devices. One of the ways Market filters applications is by Android
+version-compatibility. To do this, Market checks the <code>&lt;uses-sdk&gt;</code>
+attributes in each application's manifest to establish its version-compatibility
+range, then shows or hides the application based on a comparison with the API
+Level of the user's Android system version. </p>
+  </div>
+</div>
 
 <dt>attributes:</dt>
 
@@ -40,44 +52,86 @@
   for the application to run. The Android system will prevent the user from installing
   the application if the system's API Level is lower than the value specified in
   this attribute. You should always declare this attribute.
-  
-  <p class="caution"><strong>Caution:</strong>
-  If you do not declare this attribute, then a value of "1" is assumed, which
-  indicates that your application is compatible with all versions of Android. If your
-  application is <em>not</em> compatible with all versions (for instance, it uses APIs
-  introduced in API Level 3) and you have not declared the proper <code>minSdkVersion</code>,
-  then when installed on a system with an API Level less than 3, the application will crash
-  during runtime when attempting to access the unavailable APIs. For this reason, 
-  be certain to declare the appropriate API Level
-  in the <code>minSdkVersion</code> attribute.</p>
+
+  <p class="caution"><strong>Caution:</strong> If you do not declare this
+  attribute, the system assumes a default value of "1", which indicates that your
+  application is compatible with all versions of Android. If your application is
+  <em>not</em> compatible with all versions (for instance, it uses APIs introduced
+  in API Level 3) and you have not declared the proper <code>android:minSdkVersion</code>,
+  then when installed on a system with an API Level less than 3, the application
+  will crash during runtime when attempting to access the unavailable APIs. For
+  this reason, be certain to declare the appropriate API Level in the
+  <code>minSdkVersion</code> attribute.</p>
   </dd>
-  
-  <dt><a name="max"></a>{@code android:maxSdkVersion}</dt>
-  <dd>An integer designating the maximum API Level on which the application is 
-  designed to run. The Android system will prevent the user from installing the 
-  application if the system's API Level is higher than the value specified
-  in this attribute. 
-  
-  <p>Introduced in: API Level 4</p>
-  </dd>
-  
+
   <dt><a name="target"></a>{@code android:targetSdkVersion}</dt>
   <dd>An integer designating the API Level that the application is targetting.
-  
-  <p>With this attribute set, the application says that it is able to run on 
-  older versions (down to {@code minSdkVersion}), but was explicitly tested to work 
-  with the version specified here.
-  Specifying this target version allows the platform to disable compatibility
-  settings that are not required for the target version (which may otherwise be turned on
-  in order to maintain forward-compatibility) or enable newer features that are not
-  available to older applications. This does not mean that you can program different 
-  features for different versions of the platform&mdash;it simply informs the platform that you
-  have tested against the target version and the platform should not perform any extra
-  work to maintain forward-compatibility with the target version.</p>
-  
+
+  <p>With this attribute set, the application says that it is able to run on
+  older versions (down to {@code minSdkVersion}), but was explicitly tested to
+  work with the version specified here. Specifying this target version allows the
+  platform to disable compatibility settings that are not required for the target
+  version (which may otherwise be turned on in order to maintain
+  forward-compatibility) or enable newer features that are not available to older
+  applications. This does not mean that you can program different features for
+  different versions of the platform&mdash;it simply informs the platform that you
+  have tested against the target version and the platform should not perform any
+  extra work to maintain forward-compatibility with the target version.</p>
+
   <p>Introduced in: API Level 4</p>
   </dd>
 
+  <dt><a name="max"></a>{@code android:maxSdkVersion}</dt>
+  <dd>An integer designating the maximum API Level on which the application is 
+  designed to run. 
+
+  <p>In Android 1.5, 1.6, 2.0, and 2.0.1, the system checks the value of this
+  attribute when installing an application and when revalidating the application
+  after a system update. In either case, if the application's
+  <code>android:maxSdkVersion</code> attribute is lower than the API Level used by
+  the system itself, then the system will not allow the application to be
+  installed. In the case of revalidation after system update, this effectively
+  removes your application from the device.
+
+  <p>To illustrate how this attribute can affect your application after system
+  updates, consider the following example: </p>
+
+  <p>An application declaring <code>android:maxSdkVersion="5"</code> in its
+  manifest is published on Android Market. A user whose device is running Android
+  1.6 (API Level 4) downloads and installs the app. After a few weeks, the user
+  receives an over-the-air system update to Android 2.0 (API Level 5). After the
+  update is installed, the system checks the application's
+  <code>android:maxSdkVersion</code> and successfully revalidates it. The
+  application functions as normal. However, some time later, the device receives
+  another system update, this time to Android 2.0.1 (API Level 6). After the
+  update, the system can no longer revalidate the application because the system's
+  own API Level (6) is now higher than the maximum supported by the application
+  (5). The system prevents the application from being visible to the user, in
+  effect removing it from the device.</p>
+
+  <p class="warning"><strong>Warning:</strong> Declaring this attribute is not
+  recommended. First, there is no need to set the attribute as means of blocking
+  deployment of your application onto new versions of the Android platform as they
+  are released. By design, new versions of the platform are fully
+  backward-compatible. Your application should work properly on new versions,
+  provided it uses only standard APIs and follows development best practices.
+  Second, note that in some cases, declaring the attribute can <strong>result in
+  your application being removed from users' devices after a system
+  update</strong> to a higher API Level. Most devices on which your appplication
+  is likely to be installed will receive periodic system updates over the air, so
+  you should consider their effect on your application before setting this
+  attribute.</p>
+
+  <p style="margin-bottom:1em;">Introduced in: API Level 4</p>
+
+  <div class="special">Future versions of Android (beyond Android 2.0.1) will no
+longer check or enforce the <code>android:maxSdkVersion</code> attribute during
+installation or revalidation. Android Market will continue to use the attribute
+as a filter, however, when presenting users with applications available for
+download. </div>
+  </dd>
+  
+
 </dl></dd>
 
 <!-- ##api level indication## -->
diff --git a/docs/html/sdk/android-1.6.jd b/docs/html/sdk/android-1.6.jd
index 646b61d..7151325 100644
--- a/docs/html/sdk/android-1.6.jd
+++ b/docs/html/sdk/android-1.6.jd
@@ -74,7 +74,7 @@
 
 <p>API related:</p>
 <ul>
-<li>Properly exposes CDMA-related constants {@link android.telephony.TelephonyManager}: <code>DATA_ACTIVITY_DORMANT</code>,
+<li>Properly exposes CDMA-related constants in {@link android.telephony.TelephonyManager android.telephony.TelephonyManager}: <code>DATA_ACTIVITY_DORMANT</code>,
 <code>PHONE_TYPE_CDMA</code>, <code>NETWORK_TYPE_CDMA</code>,
 <code>NETWORK_TYPE_EVDO_0</code>, <code>NETWORK_TYPE_EVDO_A</code>, and
 <code>NETWORK_TYPE_1xRTT</code>.</li>
@@ -362,15 +362,15 @@
       <li>New attributes for the 
       <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk>}</a> element:
         <ul>
-          <li><code>maxSdkVersion</code>: This indicates the maximum API Level on which an application is 
-          designed to run. If an application declares this attribute, the Android system prevents the user 
-          from installing the application if the system's API Level is higher than the value specified in 
-          this attribute. </li>
-          <li><code>targetSdkVersion</code>: This indicates the API Level that the application is targeting. 
+          <li><code>targetSdkVersion</code>: Indicates the API Level that the application is targeting. 
           It is able to run on older versions (down to minSdkVersion), but was explicitly tested to 
           work with the version specified here. Specifying this version allows the platform to 
           disable compatibility code that is not required or enable newer features that are not 
           available to older applications. </li>
+          <li><code>maxSdkVersion</code>: Indicates the maximum API Level on which an application is 
+          designed to run. <strong>Important:</strong> Please read the <a
+          href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+          documentation before using this attribute. </li>
         </ul>
       </li>
 
diff --git a/docs/html/sdk/android-2.0.1.jd b/docs/html/sdk/android-2.0.1.jd
index f5df1ac..fbce45e 100644
--- a/docs/html/sdk/android-2.0.1.jd
+++ b/docs/html/sdk/android-2.0.1.jd
@@ -287,8 +287,6 @@
 <h4>Other Framework fixes</h4>
 
 <ul>
-<li>{@link android.content.res.Resources#getDisplayMetrics()} now properly
-reports the screen DPI for the Verizon Droid.</li>
 <li>{@link android.app.Activity#getCallingPackage()} now properly reports the
 package name, rather than the process name.</li>
 </ul>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index fd0576a..6ca02b6 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -3,15 +3,15 @@
 sdk.version=2.0.1
 sdk.date=December 2009
 
-sdk.win_download=android-sdk_r4-windows.zip
+sdk.win_download=android-sdk_r04-windows.zip
 sdk.win_bytes=23069119
 sdk.win_checksum=c48b407de852ba483869f17337e90997
 
-sdk.mac_download=android-sdk_r4-mac.zip
+sdk.mac_download=android-sdk_r04-mac_86.zip
 sdk.mac_bytes=19657927
 sdk.mac_checksum=b08512765aa9b0369bb9b8fecdf763e3
 
-sdk.linux_download=android-sdk_r4-linux.tgz
+sdk.linux_download=android-sdk_r04-linux_86.tgz
 sdk.linux_bytes=15984887
 sdk.linux_checksum=ef84b08fd9da84f4c4ae77564fe4eaee
 
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 42a14ce..98ffb8b 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -20,6 +20,8 @@
 import android.os.Parcelable;
 
 import java.io.PrintWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Rect holds four integer coordinates for a rectangle. The rectangle is
@@ -34,6 +36,9 @@
     public int right;
     public int bottom;
 
+    private static final Pattern FLATTENED_PATTERN = Pattern.compile(
+            "(-?\\d+) (-?\\d+) (-?\\d+) (-?\\d+)");
+
     /**
      * Create a new empty Rect. All coordinates are initialized to 0.
      */
@@ -105,6 +110,43 @@
         sb.append(','); sb.append(bottom); sb.append(']');
         return sb.toString();
     }
+
+    /**
+     * Return a string representation of the rectangle in a well-defined format.
+     *
+     * <p>You can later recover the Rect from this string through
+     * {@link #unflattenFromString(String)}.
+     * 
+     * @return Returns a new String of the form "left top right bottom"
+     */
+    public String flattenToString() {
+        StringBuilder sb = new StringBuilder(32);
+        // WARNING: Do not change the format of this string, it must be
+        // preserved because Rects are saved in this flattened format.
+        sb.append(left);
+        sb.append(' ');
+        sb.append(top);
+        sb.append(' ');
+        sb.append(right);
+        sb.append(' ');
+        sb.append(bottom);
+        return sb.toString();
+    }
+
+    /**
+     * Returns a Rect from a string of the form returned by {@link #flattenToString},
+     * or null if the string is not of that form.
+     */
+    public static Rect unflattenFromString(String str) {
+        Matcher matcher = FLATTENED_PATTERN.matcher(str);
+        if (!matcher.matches()) {
+            return null;
+        }
+        return new Rect(Integer.parseInt(matcher.group(1)),
+                Integer.parseInt(matcher.group(2)),
+                Integer.parseInt(matcher.group(3)),
+                Integer.parseInt(matcher.group(4)));
+    }
     
     /**
      * Print short representation to given writer.
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 4c60623..4199252 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -146,8 +146,7 @@
 
     void setComponentRole();
 
-    void setAMRFormat();
-    void setAMRWBFormat();
+    void setAMRFormat(bool isWAMR);
     void setAACFormat(int32_t numChannels, int32_t sampleRate);
 
     status_t setVideoPortFormatType(
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index daec6e8..9ec8de5 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2277,10 +2277,8 @@
     LOGV("PlaybackThread::Track destructor");
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        thread->mLock.lock();
+        Mutex::Autolock _l(thread->mLock);
         mState = TERMINATED;
-        thread->mLock.unlock();
-        AudioSystem::releaseOutput(thread->id());
     }
 }
 
@@ -2298,8 +2296,11 @@
     { // scope for mLock
         sp<ThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            if (!isOutputTrack() && (mState == ACTIVE || mState == RESUMING)) {
-                AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+            if (!isOutputTrack()) {
+                if (mState == ACTIVE || mState == RESUMING) {
+                    AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+                }
+                AudioSystem::releaseOutput(thread->id());
             }
             Mutex::Autolock _l(thread->mLock);
             PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index f5a5a0b..f11bf18 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -515,6 +515,11 @@
         dirtyRegion.andSelf(visibleRegionScreen);
         outDirtyRegion.orSelf(dirtyRegion);
     }
+    if (visibleRegionScreen.isEmpty()) {
+        // an invisible layer should not hold a freeze-lock
+        // (because it may never be updated and thereore never release it)
+        mFreezeLock.clear();
+    }
 }
 
 void Layer::finishPageFlip()
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 88ef7e4..eb017bf 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -266,7 +266,16 @@
     : mBufferHeap(buffers)
 {
     NativeBuffer& src(mNativeBuffer);
-    src.img.handle = 0;
+    src.crop.l = 0;
+    src.crop.t = 0;
+    src.crop.r = buffers.w;
+    src.crop.b = buffers.h;
+
+    src.img.w       = buffers.hor_stride ?: buffers.w;
+    src.img.h       = buffers.ver_stride ?: buffers.h;
+    src.img.format  = buffers.format;
+    src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
+    src.img.handle  = 0;
 
     gralloc_module_t const * module = LayerBuffer::getGrallocModule();
     if (module && module->perform) {
@@ -276,19 +285,12 @@
                 offset, buffers.heap->base(),
                 &src.img.handle);
 
-        if (err == NO_ERROR) {
-            src.crop.l = 0;
-            src.crop.t = 0;
-            src.crop.r = buffers.w;
-            src.crop.b = buffers.h;
-
-            src.img.w       = buffers.hor_stride ?: buffers.w;
-            src.img.h       = buffers.ver_stride ?: buffers.h;
-            src.img.format  = buffers.format;
-            src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
-        }
+        LOGE_IF(err, "CREATE_HANDLE_FROM_BUFFER (heapId=%d, size=%d, "
+             "offset=%ld, base=%p) failed (%s)",
+                buffers.heap->heapID(), buffers.heap->getSize(),
+                offset, buffers.heap->base(), strerror(-err));
     }
-}
+ }
 
 LayerBuffer::Buffer::~Buffer()
 {
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 9694cf1..965b7dd 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -417,9 +417,9 @@
 {
     while (true) {
         nsecs_t timeout = -1;
+        const nsecs_t freezeDisplayTimeout = ms2ns(5000);
         if (UNLIKELY(isFrozen())) {
             // wait 5 seconds
-            const nsecs_t freezeDisplayTimeout = ms2ns(5000);
             const nsecs_t now = systemTime();
             if (mFreezeDisplayTime == 0) {
                 mFreezeDisplayTime = now;
@@ -429,23 +429,27 @@
         }
 
         MessageList::value_type msg = mEventQueue.waitMessage(timeout);
+
+        // see if we timed out
+        if (isFrozen()) {
+            const nsecs_t now = systemTime();
+            nsecs_t frozenTime = (now - mFreezeDisplayTime);
+            if (frozenTime >= freezeDisplayTimeout) {
+                // we timed out and are still frozen
+                LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
+                        mFreezeDisplay, mFreezeCount);
+                mFreezeDisplayTime = 0;
+                mFreezeCount = 0;
+                mFreezeDisplay = false;
+            }
+        }
+
         if (msg != 0) {
-            mFreezeDisplayTime = 0;
             switch (msg->what) {
                 case MessageQueue::INVALIDATE:
                     // invalidate message, just return to the main loop
                     return;
             }
-        } else {
-            // we timed out
-            if (isFrozen()) {
-                // we timed out and are still frozen
-                LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
-                        mFreezeDisplay, mFreezeCount);
-                mFreezeCount = 0;
-                mFreezeDisplay = false;
-                return;
-            }
         }
     }
 }
@@ -1646,6 +1650,7 @@
             }
             case 1007: // set mFreezeCount
                 mFreezeCount = data.readInt32();
+                mFreezeDisplayTime = 0;
                 return NO_ERROR;
             case 1010:  // interrogate.
                 reply->writeInt32(0);
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index f9bfe6c..c0ab73d 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -291,7 +291,11 @@
 
             friend class FreezeLock;
             sp<FreezeLock> getFreezeLock() const;
-            inline void incFreezeCount() { mFreezeCount++; }
+            inline void incFreezeCount() {
+                if (mFreezeCount == 0)
+                    mFreezeDisplayTime = 0;
+                mFreezeCount++;
+            }
             inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; }
             inline bool hasFreezeRequest() const { return mFreezeDisplay; }
             inline bool isFrozen() const { 
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 6cd4b92..c49ad5c 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -22,6 +22,7 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.TimeZone;
 
 /**
  * This is a class for reading and writing Exif tags in a JPEG file.
@@ -56,9 +57,12 @@
     // Constants used for white balance
     public static final int WHITEBALANCE_AUTO = 0;
     public static final int WHITEBALANCE_MANUAL = 1;
+    private static SimpleDateFormat sFormatter;
 
     static {
         System.loadLibrary("exif");
+        sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
+        sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
     }
 
     private String mFilename;
@@ -242,9 +246,6 @@
         }
     }
 
-    private static SimpleDateFormat sFormatter =
-            new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
-
     /**
      * Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
      * Returns -1 if the date time information if not available.
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index da25f97..079b4c3 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -640,13 +640,13 @@
                 map.put(Video.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaFile.UNKNOWN_STRING));
                 map.put(Video.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaFile.UNKNOWN_STRING));
                 map.put(Video.Media.DURATION, mDuration);
-                map.put(Video.Media.DATE_TAKEN, mLastModified);
+                map.put(Video.Media.DATE_TAKEN, mLastModified * 1000);
                 // FIXME - add RESOLUTION
             } else if (MediaFile.isImageFileType(mFileType)) {
                 // FIXME - add DESCRIPTION
                 // DATE_TAKEN will be overridden later if this is a JPEG image whose EXIF data
                 // contains date time information.
-                map.put(Images.Media.DATE_TAKEN, mLastModified);
+                map.put(Images.Media.DATE_TAKEN, mLastModified * 1000);
             } else if (MediaFile.isAudioFileType(mFileType)) {
                 map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaFile.UNKNOWN_STRING));
                 map.put(Audio.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaFile.UNKNOWN_STRING));
@@ -746,7 +746,7 @@
 
                     long time = exif.getDateTime();
                     if (time != -1) {
-                        values.put(Images.Media.DATE_TAKEN, time);
+                        values.put(Images.Media.DATE_TAKEN, time * 1000);
                     }
 
                     int orientation = exif.getAttributeInt(
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 1713324..0ce3526 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -63,11 +63,13 @@
     private AssetFileDescriptor mAssetFileDescriptor;
 
     private int mStreamType = AudioManager.STREAM_RING;
+    private AudioManager mAudioManager;
 
     private Context mContext;
 
     Ringtone(Context context) {
         mContext = context;
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
     }
 
     /**
@@ -215,7 +217,11 @@
             }
         }
         if (mAudio != null) {
-            mAudio.start();
+            // do not ringtones if stream volume is 0
+            // (typically because ringer mode is silent).
+            if (mAudioManager.getStreamVolume(mStreamType) != 0) {
+                mAudio.start();
+            }
         }
     }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index c5e935d0..670f748 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -416,10 +416,10 @@
     }
 
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
-        codec->setAMRFormat();
+        codec->setAMRFormat(false /* isWAMR */);
     }
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
-        codec->setAMRWBFormat();
+        codec->setAMRFormat(true /* isWAMR */);
     }
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
         int32_t numChannels, sampleRate;
@@ -1900,54 +1900,24 @@
     CHECK_EQ(err, OK);
 }
 
-void OMXCodec::setAMRFormat() {
-    if (!mIsEncoder) {
-        OMX_AUDIO_PARAM_AMRTYPE def;
-        InitOMXParams(&def);
-        def.nPortIndex = kPortIndexInput;
+void OMXCodec::setAMRFormat(bool isWAMR) {
+    OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
 
-        status_t err =
-            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+    OMX_AUDIO_PARAM_AMRTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = portIndex;
 
-        CHECK_EQ(err, OK);
+    status_t err =
+        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
 
-        def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
-        def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
+    CHECK_EQ(err, OK);
 
-        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
-        CHECK_EQ(err, OK);
-    }
+    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+    def.eAMRBandMode =
+        isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0;
 
-    ////////////////////////
-
-    if (mIsEncoder) {
-        sp<MetaData> format = mSource->getFormat();
-        int32_t sampleRate;
-        int32_t numChannels;
-        CHECK(format->findInt32(kKeySampleRate, &sampleRate));
-        CHECK(format->findInt32(kKeyChannelCount, &numChannels));
-
-        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
-    }
-}
-
-void OMXCodec::setAMRWBFormat() {
-    if (!mIsEncoder) {
-        OMX_AUDIO_PARAM_AMRTYPE def;
-        InitOMXParams(&def);
-        def.nPortIndex = kPortIndexInput;
-
-        status_t err =
-            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
-
-        CHECK_EQ(err, OK);
-
-        def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
-        def.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
-
-        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
-        CHECK_EQ(err, OK);
-    }
+    err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+    CHECK_EQ(err, OK);
 
     ////////////////////////
 
diff --git a/opengl/java/android/opengl/GLLogWrapper.java b/opengl/java/android/opengl/GLLogWrapper.java
index 4119bf8..f332448 100644
--- a/opengl/java/android/opengl/GLLogWrapper.java
+++ b/opengl/java/android/opengl/GLLogWrapper.java
@@ -1517,7 +1517,7 @@
         arg("count", count);
         startLogIndices();
         for (int i = 0; i < count; i++) {
-            doElement(mStringBuilder, i, first + count);
+            doElement(mStringBuilder, i, first + i);
         }
         endLogIndices();
         end();
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
index a68750e..4cacc11 100644
--- a/opengl/libagl/copybit.cpp
+++ b/opengl/libagl/copybit.cpp
@@ -38,7 +38,7 @@
 #include <ui/Rect.h>
 
 
-#define DEBUG_COPYBIT true
+#define DEBUG_COPYBIT false
 
 // ----------------------------------------------------------------------------
 
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index fbfe755..ab93d8c 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -48,4 +48,7 @@
     
     <bool name="def_backup_enabled">false</bool>
     <string name="def_backup_transport" translatable="false"></string>
+    <!-- Default value for whether or not to pulse the notification LED when there is a 
+         pending notification -->
+    <bool name="def_notification_pulse">true</bool>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index e25c648..1a64e20 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -71,7 +71,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 42;
+    private static final int DATABASE_VERSION = 43;
 
     private Context mContext;
 
@@ -521,6 +521,24 @@
             upgradeVersion = 42;
         }
 
+        if (upgradeVersion == 42) {
+            /*
+             * Initialize new notification pulse setting
+             */
+            db.beginTransaction();
+            try {
+                SQLiteStatement stmt = db.compileStatement("INSERT INTO system(name,value)"
+                        + " VALUES(?,?);");
+                loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
+                        R.bool.def_notification_pulse);
+                stmt.close();
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+            upgradeVersion = 43;
+        }
+
         if (upgradeVersion != currentVersion) {
             Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
                     + ", must wipe the settings provider");
@@ -767,6 +785,8 @@
 
         loadDefaultHapticSettings(stmt);
 
+        loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
+                R.bool.def_notification_pulse);
         stmt.close();
     }
 
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 7c19f24..6f207e0 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -313,14 +313,17 @@
             long bestDistance = -1;
             int bestIndex = -1;
             for (int j=0; j<lastNumPointers; j++) {
-                if (!allowOverlap && last2Next[j] < 0) {
+                // If we are not allowing multiple new points to be assigned
+                // to the same old pointer, then skip this one if it is already
+                // detected as a conflict (-2).
+                if (!allowOverlap && last2Next[j] < -1) {
                     continue;
                 }
                 final int jd = j * MotionEvent.NUM_SAMPLE_DATA;
                 final int xd = lastData[jd + MotionEvent.SAMPLE_X] - x1;
                 final int yd = lastData[jd + MotionEvent.SAMPLE_Y] - y1;
                 final long distance = xd*(long)xd + yd*(long)yd;
-                if (j == 0 || distance < bestDistance) {
+                if (bestDistance == -1 || distance < bestDistance) {
                     bestDistance = distance;
                     bestIndex = j;
                 }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index c179eb8..147580b 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -99,7 +99,11 @@
     private NotificationRecord mVibrateNotification;
     private Vibrator mVibrator = new Vibrator();
 
-    // adb
+    // for enabling and disabling notification pulse behavior
+    private boolean mScreenOn = true;
+    private boolean mNotificationPulseEnabled;
+
+    // for adb connected notifications
     private boolean mUsbConnected;
     private boolean mAdbEnabled = false;
     private boolean mAdbNotificationShown = false;
@@ -336,6 +340,12 @@
                     return;
                 }
                 cancelAllNotificationsInt(pkgName, 0, 0);
+            } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                mScreenOn = true;
+                updateNotificationPulse();
+            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                mScreenOn = false;
+                updateNotificationPulse();
             }
         }
     };
@@ -349,6 +359,8 @@
             ContentResolver resolver = mContext.getContentResolver();
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.ADB_ENABLED), false, this);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.NOTIFICATION_LIGHT_PULSE), false, this);
             update();
         }
 
@@ -358,13 +370,21 @@
 
         public void update() {
             ContentResolver resolver = mContext.getContentResolver();
-            mAdbEnabled = Settings.Secure.getInt(resolver,
+            boolean adbEnabled = Settings.Secure.getInt(resolver,
                         Settings.Secure.ADB_ENABLED, 0) != 0;
-            updateAdbNotification();
+            if (mAdbEnabled != adbEnabled) {
+                mAdbEnabled = adbEnabled;
+                updateAdbNotification();
+            }
+            boolean pulseEnabled = Settings.System.getInt(resolver,
+                        Settings.System.NOTIFICATION_LIGHT_PULSE, 0) != 0;
+            if (mNotificationPulseEnabled != pulseEnabled) {
+                mNotificationPulseEnabled = pulseEnabled;
+                updateNotificationPulse();
+            }
         }
     }
-    private final SettingsObserver mSettingsObserver;
-    
+
     NotificationManagerService(Context context, StatusBarService statusBar,
             LightsService lights)
     {
@@ -399,10 +419,12 @@
         filter.addAction(Intent.ACTION_UMS_DISCONNECTED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
         mContext.registerReceiver(mIntentReceiver, filter);
         
-        mSettingsObserver = new SettingsObserver(mHandler);
-        mSettingsObserver.observe();
+        SettingsObserver observer = new SettingsObserver(mHandler);
+        observer.observe();
     }
 
     void systemReady() {
@@ -711,6 +733,9 @@
                     && (!(old != null
                         && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                     && mSystemReady) {
+
+                final AudioManager audioManager = (AudioManager) mContext
+                .getSystemService(Context.AUDIO_SERVICE);
                 // sound
                 final boolean useDefaultSound =
                     (notification.defaults & Notification.DEFAULT_SOUND) != 0; 
@@ -729,18 +754,20 @@
                         audioStreamType = DEFAULT_STREAM_TYPE;
                     }
                     mSoundNotification = r;
-                    long identity = Binder.clearCallingIdentity();
-                    try {
-                        mSound.play(mContext, uri, looping, audioStreamType);
-                    }
-                    finally {
-                        Binder.restoreCallingIdentity(identity);
+                    // do not play notifications if stream volume is 0
+                    // (typically because ringer mode is silent).
+                    if (audioManager.getStreamVolume(audioStreamType) != 0) {
+                        long identity = Binder.clearCallingIdentity();
+                        try {
+                            mSound.play(mContext, uri, looping, audioStreamType);
+                        }
+                        finally {
+                            Binder.restoreCallingIdentity(identity);
+                        }
                     }
                 }
 
                 // vibrate
-                final AudioManager audioManager = (AudioManager) mContext
-                        .getSystemService(Context.AUDIO_SERVICE);
                 final boolean useDefaultVibrate =
                     (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; 
                 if ((useDefaultVibrate || notification.vibrate != null)
@@ -1000,7 +1027,9 @@
                 mLedNotification = mLights.get(n-1);
             }
         }
-        if (mLedNotification == null) {
+
+        // we only flash if screen is off and persistent pulsing is enabled
+        if (mLedNotification == null || mScreenOn || !mNotificationPulseEnabled) {
             mNotificationLight.turnOff();
         } else {
             mNotificationLight.setFlashing(
@@ -1092,7 +1121,13 @@
             }
         }
     }
-    
+
+    private void updateNotificationPulse() {
+        synchronized (mNotificationList) {
+            updateLightsLocked();
+        }
+    }
+
     // ======================================================================
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 5ed2d35..9382146 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2966,12 +2966,6 @@
             TAG, "Removing package " + pkg.applicationInfo.packageName );
 
         synchronized (mPackages) {
-            if (pkg.mPreferredOrder > 0) {
-                mSettings.mPreferredPackages.remove(pkg);
-                pkg.mPreferredOrder = 0;
-                updatePreferredIndicesLP();
-            }
-    
             clearPackagePreferredActivitiesLP(pkg.packageName);
     
             mPackages.remove(pkg.applicationInfo.packageName);
@@ -4938,62 +4932,17 @@
     public void addPackageToPreferred(String packageName) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
-
-        synchronized (mPackages) {
-            PackageParser.Package p = mPackages.get(packageName);
-            if (p == null) {
-                return;
-            }
-            PackageSetting ps = (PackageSetting)p.mExtras;
-            if (ps != null) {
-                mSettings.mPreferredPackages.remove(ps);
-                mSettings.mPreferredPackages.add(0, ps);
-                updatePreferredIndicesLP();
-                mSettings.writeLP();
-            }
-        }
+        Log.w(TAG, "addPackageToPreferred: no longer implemented");
     }
 
     public void removePackageFromPreferred(String packageName) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
-
-        synchronized (mPackages) {
-            PackageParser.Package p = mPackages.get(packageName);
-            if (p == null) {
-                return;
-            }
-            if (p.mPreferredOrder > 0) {
-                PackageSetting ps = (PackageSetting)p.mExtras;
-                if (ps != null) {
-                    mSettings.mPreferredPackages.remove(ps);
-                    p.mPreferredOrder = 0;
-                    updatePreferredIndicesLP();
-                    mSettings.writeLP();
-                }
-            }
-        }
-    }
-
-    private void updatePreferredIndicesLP() {
-        final ArrayList<PackageSetting> pkgs
-                = mSettings.mPreferredPackages;
-        final int N = pkgs.size();
-        for (int i=0; i<N; i++) {
-            pkgs.get(i).pkg.mPreferredOrder = N - i;
-        }
+        Log.w(TAG, "removePackageFromPreferred: no longer implemented");
     }
 
     public List<PackageInfo> getPreferredPackages(int flags) {
-        synchronized (mPackages) {
-            final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
-            final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
-            final int N = pref.size();
-            for (int i=0; i<N; i++) {
-                res.add(generatePackageInfo(pref.get(i).pkg, flags));
-            }
-            return res;
-        }
+        return new ArrayList<PackageInfo>();
     }
 
     public void addPreferredActivity(IntentFilter filter, int match,
@@ -5307,13 +5256,6 @@
             pw.println("Preferred Activities:");
             mSettings.mPreferredActivities.dump(pw, "  ");
             pw.println(" ");
-            pw.println("Preferred Packages:");
-            {
-                for (PackageSetting ps : mSettings.mPreferredPackages) {
-                    pw.print("  "); pw.println(ps.name);
-                }
-            }
-            pw.println(" ");
             pw.println("Permissions:");
             {
                 for (BasePermission p : mSettings.mPermissions.values()) {
@@ -6064,10 +6006,6 @@
         private final File mBackupSettingsFilename;
         private final HashMap<String, PackageSetting> mPackages =
                 new HashMap<String, PackageSetting>();
-        // The user's preferred packages/applications, in order of preference.
-        // First is the most preferred.
-        private final ArrayList<PackageSetting> mPreferredPackages =
-                new ArrayList<PackageSetting>();
         // List of replaced system applications
         final HashMap<String, PackageSetting> mDisabledSysPackages =
             new HashMap<String, PackageSetting>();
@@ -6112,9 +6050,6 @@
         final HashMap<String, BasePermission> mPermissionTrees =
                 new HashMap<String, BasePermission>();
 
-        private final ArrayList<String> mPendingPreferredPackages
-                = new ArrayList<String>();
-
         private final StringBuilder mReadMessages = new StringBuilder();
 
         private static final class PendingPackage extends PackageSettingBase {
@@ -6598,16 +6533,6 @@
                     writeDisabledSysPackage(serializer, pkg);
                 }
 
-                serializer.startTag(null, "preferred-packages");
-                int N = mPreferredPackages.size();
-                for (int i=0; i<N; i++) {
-                    PackageSetting pkg = mPreferredPackages.get(i);
-                    serializer.startTag(null, "item");
-                    serializer.attribute(null, "name", pkg.name);
-                    serializer.endTag(null, "item");
-                }
-                serializer.endTag(null, "preferred-packages");
-
                 serializer.startTag(null, "preferred-activities");
                 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
                     serializer.startTag(null, "item");
@@ -6885,7 +6810,7 @@
                     } else if (tagName.equals("shared-user")) {
                         readSharedUserLP(parser);
                     } else if (tagName.equals("preferred-packages")) {
-                        readPreferredPackagesLP(parser);
+                        // no longer used.
                     } else if (tagName.equals("preferred-activities")) {
                         readPreferredActivitiesLP(parser);
                     } else if(tagName.equals("updated-package")) {
@@ -6939,19 +6864,6 @@
             }
             mPendingPackages.clear();
 
-            N = mPendingPreferredPackages.size();
-            mPreferredPackages.clear();
-            for (int i=0; i<N; i++) {
-                final String name = mPendingPreferredPackages.get(i);
-                final PackageSetting p = mPackages.get(name);
-                if (p != null) {
-                    mPreferredPackages.add(p);
-                } else {
-                    Log.w(TAG, "Unknown preferred package: " + name);
-                }
-            }
-            mPendingPreferredPackages.clear();
-
             mReadMessages.append("Read completed successfully: "
                     + mPackages.size() + " packages, "
                     + mSharedUsers.size() + " shared uids\n");
@@ -7410,37 +7322,6 @@
             }
         }
 
-        private void readPreferredPackagesLP(XmlPullParser parser)
-                throws XmlPullParserException, IOException {
-            int outerDepth = parser.getDepth();
-            int type;
-            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-                   && (type != XmlPullParser.END_TAG
-                           || parser.getDepth() > outerDepth)) {
-                if (type == XmlPullParser.END_TAG
-                        || type == XmlPullParser.TEXT) {
-                    continue;
-                }
-
-                String tagName = parser.getName();
-                if (tagName.equals("item")) {
-                    String name = parser.getAttributeValue(null, "name");
-                    if (name != null) {
-                        mPendingPreferredPackages.add(name);
-                    } else {
-                        reportSettingsProblem(Log.WARN,
-                                "Error in package manager settings: <preferred-package> has no name at "
-                                + parser.getPositionDescription());
-                    }
-                } else {
-                    reportSettingsProblem(Log.WARN,
-                            "Unknown element under <preferred-packages>: "
-                            + parser.getName());
-                }
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-
         private void readPreferredActivitiesLP(XmlPullParser parser)
                 throws XmlPullParserException, IOException {
             int outerDepth = parser.getDepth();
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 8584d74..6e769c7 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -161,7 +161,9 @@
     private int[] mBroadcastWhy = new int[3];
     private int mPartialCount = 0;
     private int mPowerState;
-    private boolean mOffBecauseOfUser;
+    // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
+    // WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT or WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
+    private int mScreenOffReason;
     private int mUserState;
     private boolean mKeyboardVisible = false;
     private boolean mUserActivityAllowed = true;
@@ -919,7 +921,7 @@
                 + " " + ((mNextTimeout-now)/1000) + "s from now");
         pw.println("  mDimScreen=" + mDimScreen
                 + " mStayOnConditions=" + mStayOnConditions);
-        pw.println("  mOffBecauseOfUser=" + mOffBecauseOfUser
+        pw.println("  mScreenOffReason=" + mScreenOffReason
                 + " mUserState=" + mUserState);
         pw.println("  mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
                 + ',' + mBroadcastQueue[2] + "}");
@@ -1384,10 +1386,10 @@
 
     private void setPowerState(int state)
     {
-        setPowerState(state, false, false);
+        setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
     }
 
-    private void setPowerState(int newState, boolean noChangeLights, boolean becauseOfUser)
+    private void setPowerState(int newState, boolean noChangeLights, int reason)
     {
         synchronized (mLocks) {
             int err;
@@ -1395,7 +1397,8 @@
             if (mSpew) {
                 Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
                         + " newState=0x" + Integer.toHexString(newState)
-                        + " noChangeLights=" + noChangeLights);
+                        + " noChangeLights=" + noChangeLights
+                        + " reason=" + reason);
             }
 
             if (noChangeLights) {
@@ -1489,7 +1492,7 @@
                     mLastTouchDown = 0;
                     mTotalTouchDownTime = 0;
                     mTouchCycles = 0;
-                    EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, becauseOfUser ? 1 : 0,
+                    EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, reason,
                             mTotalTouchDownTime, mTouchCycles);
                     if (err == 0) {
                         mPowerState |= SCREEN_ON_BIT;
@@ -1508,10 +1511,10 @@
                         Binder.restoreCallingIdentity(identity);
                     }
                     mPowerState &= ~SCREEN_ON_BIT;
+                    mScreenOffReason = reason;
                     if (!mScreenBrightness.animating) {
-                        err = screenOffFinishedAnimatingLocked(becauseOfUser);
+                        err = screenOffFinishedAnimatingLocked(reason);
                     } else {
-                        mOffBecauseOfUser = becauseOfUser;
                         err = 0;
                         mLastTouchDown = 0;
                     }
@@ -1520,19 +1523,16 @@
         }
     }
     
-    private int screenOffFinishedAnimatingLocked(boolean becauseOfUser) {
+    private int screenOffFinishedAnimatingLocked(int reason) {
         // I don't think we need to check the current state here because all of these
         // Power.setScreenState and sendNotificationLocked can both handle being 
         // called multiple times in the same state. -joeo
-        EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
-                mTotalTouchDownTime, mTouchCycles);
+        EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles);
         mLastTouchDown = 0;
         int err = setScreenStateLocked(false);
         if (err == 0) {
-            int why = becauseOfUser
-                    ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
-                    : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
-            sendNotificationLocked(false, why);
+            mScreenOffReason = reason;
+            sendNotificationLocked(false, reason);
         }
         return err;
     }
@@ -1808,7 +1808,7 @@
             animating = more;
             if (!more) {
                 if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
-                    screenOffFinishedAnimatingLocked(mOffBecauseOfUser);
+                    screenOffFinishedAnimatingLocked(mScreenOffReason);
                 }
             }
             return more;
@@ -1994,7 +1994,8 @@
                     }
                     
                     mWakeLockState = mLocks.reactivateScreenLocksLocked();
-                    setPowerState(mUserState | mWakeLockState, noChangeLights, true);
+                    setPowerState(mUserState | mWakeLockState, noChangeLights,
+                            WindowManagerPolicy.OFF_BECAUSE_OF_USER);
                     setTimeoutLocked(time, SCREEN_BRIGHT);
                 }
             }
@@ -2125,7 +2126,7 @@
     {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
         synchronized (mLocks) {
-            goToSleepLocked(time);
+            goToSleepLocked(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
         }
     }
     
@@ -2143,7 +2144,7 @@
         }
     }
 
-    private void goToSleepLocked(long time) {
+    private void goToSleepLocked(long time, int reason) {
 
         if (mLastEventTime <= time) {
             mLastEventTime = time;
@@ -2161,7 +2162,7 @@
             EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared);
             mStillNeedSleepNotification = true;
             mUserState = SCREEN_OFF;
-            setPowerState(SCREEN_OFF, false, true);
+            setPowerState(SCREEN_OFF, false, reason);
             cancelTimerLocked();
         }
     }
@@ -2517,7 +2518,8 @@
             return;
         }
         if (active) {
-            goToSleepLocked(SystemClock.uptimeMillis());
+            goToSleepLocked(SystemClock.uptimeMillis(),
+                    WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
             mProximitySensorActive = true;
         } else {
             // proximity sensor negative events trigger as user activity.
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 538d60e..05d340e 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -6397,7 +6397,9 @@
                             // Ignore
                         }
 
-                        if (eventType != TOUCH_EVENT
+                        if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) {
+                            // do not wake screen in this case
+                        } else if (eventType != TOUCH_EVENT
                                 && eventType != LONG_TOUCH_EVENT
                                 && eventType != CHEEK_EVENT) {
                             mPowerManager.userActivity(curTime, false,
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 1db20df..a103dcb 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.IBinder;
@@ -1277,8 +1278,13 @@
                 ActivityManagerNative.getDefault().resumeAppSwitches();
             } catch (RemoteException e) {
             }
+            int[] pos = new int[2];
+            v.getLocationOnScreen(pos);
+            Intent overlay = new Intent();
+            overlay.setSourceBounds(
+                    new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
             try {
-                mIntent.send();
+                mIntent.send(mContext, 0, overlay);
                 mNotificationCallbacks.onNotificationClick(mPkg, mTag, mId);
             } catch (PendingIntent.CanceledException e) {
                 // the stack trace isn't very helpful here.  Just log the exception message.
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 1d69761..ad7dfc9 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -68,12 +68,13 @@
     private int mNetworkType;
 
     /**
-     * @deprecated
      * Empty constructor.  Initializes the RSSI and CID.
      *
      * NeighboringCellInfo is one time shot for the neighboring cells based on
      * the radio network type at that moment. Its constructor needs radio network
      * type.
+     *
+     * @deprecated by {@link #NeighboringCellInfo(int, String, int)}
      */
     @Deprecated
     public NeighboringCellInfo() {
@@ -85,12 +86,13 @@
     }
 
     /**
-     * @deprecated
      * Initialize the object from rssi and cid.
      *
      * NeighboringCellInfo is one time shot for the neighboring cells based on
      * the radio network type at that moment. Its constructor needs radio network
      * type.
+     *
+     * @deprecated by {@link #NeighboringCellInfo(int, String, int)}
      */
     @Deprecated
     public NeighboringCellInfo(int rssi, int cid) {
@@ -99,7 +101,6 @@
     }
 
     /**
-     * @hide
      * Initialize the object from rssi, location string, and radioType
      * radioType is one of following
      * {@link TelephonyManager#NETWORK_TYPE_GPRS TelephonyManager.NETWORK_TYPE_GPRS},
@@ -223,12 +224,14 @@
         return mNetworkType;
     }
     /**
-     * @deprecated
      * Set the cell id.
      *
      * NeighboringCellInfo is a one time shot for the neighboring cells based on
      * the radio network type at that moment. It shouldn't be changed after
      * creation.
+     *
+     * @deprecated cid value passed as in location parameter passed to constructor
+     *              {@link #NeighboringCellInfo(int, String, int)}
      */
     @Deprecated
     public void setCid(int cid) {
@@ -236,12 +239,14 @@
     }
 
     /**
-     * @deprecated
      * Set the signal strength of the cell.
      *
      * NeighboringCellInfo is a one time shot for the neighboring cells based on
      * the radio network type at that moment. It shouldn't be changed after
      * creation.
+     *
+     * @deprecated initial rssi value passed as parameter to constructor
+     *              {@link #NeighboringCellInfo(int, String, int)}
      */
     @Deprecated
     public void setRssi(int rssi) {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index ea6593e..9bfd900 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -49,8 +49,9 @@
      *
      * @see #onSignalStrengthChanged
      *
-     * TODO: @deprecated to be deprecated by LISTEN_SIGNAL_STRENGTHS, @see #onSignalStrengthsChanged
+     * @deprecated by {@link #LISTEN_SIGNAL_STRENGTHS}
      */
+    @Deprecated
     public static final int LISTEN_SIGNAL_STRENGTH                          = 0x00000002;
 
     /**
@@ -127,8 +128,6 @@
      * icon.
      *
      * @see #onSignalStrengthsChanged
-     *
-     * @hide
      */
     public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100;
 
@@ -206,7 +205,6 @@
     }
 
     /**
-     * @hide
      * same as above, but with the network type.  Both called.
      */
     public void onDataConnectionStateChanged(int state, int networkType) {
@@ -232,8 +230,6 @@
      * @see ServiceState#STATE_IN_SERVICE
      * @see ServiceState#STATE_OUT_OF_SERVICE
      * @see ServiceState#STATE_POWER_OFF
-     *
-     * @hide
      */
     public void onSignalStrengthsChanged(SignalStrength signalStrength) {
         // default implementation empty
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 8ed0065..c9e304a 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -24,8 +24,6 @@
 
 /**
  * Contains phone signal strength related information.
- *
- * @hide
  */
 public class SignalStrength implements Parcelable {
 
@@ -50,6 +48,7 @@
      * @param m Bundle from intent notifier
      * @return newly created SignalStrength
      *
+     * @hide
      */
     public static SignalStrength newFromBundle(Bundle m) {
         SignalStrength ret;
@@ -61,6 +60,7 @@
     /**
      * Empty constructor
      *
+     * @hide
      */
     public SignalStrength() {
         mGsmSignalStrength = 99;
@@ -76,6 +76,7 @@
     /**
      * Constructor
      *
+     * @hide
      */
     public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
             int cdmaDbm, int cdmaEcio,
@@ -94,6 +95,8 @@
      * Copy constructors
      *
      * @param s Source SignalStrength
+     *
+     * @hide
      */
     public SignalStrength(SignalStrength s) {
         copyFrom(s);
@@ -115,6 +118,8 @@
 
     /**
      * Construct a SignalStrength object from the given parcel.
+     *
+     * @hide
      */
     public SignalStrength(Parcel in) {
         mGsmSignalStrength = in.readInt();
@@ -127,6 +132,9 @@
         isGsm = (in.readInt() != 0);
     }
 
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mGsmSignalStrength);
         out.writeInt(mGsmBitErrorRate);
@@ -138,10 +146,18 @@
         out.writeInt(isGsm ? 1 : 0);
     }
 
+    /**
+     * {@link Parcelable#describeContents}
+     */
     public int describeContents() {
         return 0;
     }
 
+    /**
+     * {@link Parcelable.Creator}
+     *
+     * @hide
+     */
     public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
         public SignalStrength createFromParcel(Parcel in) {
             return new SignalStrength(in);
@@ -202,14 +218,14 @@
     }
 
     /**
-     * @hide
+     * @return true if this is for GSM
      */
     public boolean isGsm() {
         return this.isGsm;
     }
 
     /**
-     * @hide
+     * @return hash code
      */
     @Override
     public int hashCode() {
@@ -221,7 +237,7 @@
     }
 
     /**
-     * @hide
+     * @return true if the signal strengths are the same
      */
     @Override
     public boolean equals (Object o) {
@@ -248,7 +264,7 @@
     }
 
     /**
-     * @hide
+     * @return string representation.
      */
     @Override
     public String toString() {
diff --git a/telephony/java/com/android/internal/telephony/MccTable.java b/telephony/java/com/android/internal/telephony/MccTable.java
index c4877cb..e25eb7b 100644
--- a/telephony/java/com/android/internal/telephony/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/MccTable.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.Arrays;
@@ -573,34 +574,36 @@
      * @param mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
      */
     public static void updateMccMncConfiguration(PhoneBase phone, String mccmnc) {
-        int mcc, mnc;
+        if (!TextUtils.isEmpty(mccmnc)) {
+            int mcc, mnc;
 
-        try {
-            mcc = Integer.parseInt(mccmnc.substring(0,3));
-            mnc = Integer.parseInt(mccmnc.substring(3));
-        } catch (NumberFormatException e) {
-            Log.e(LOG_TAG, "Error parsing IMSI");
-            return;
-        }
+            try {
+                mcc = Integer.parseInt(mccmnc.substring(0,3));
+                mnc = Integer.parseInt(mccmnc.substring(3));
+            } catch (NumberFormatException e) {
+                Log.e(LOG_TAG, "Error parsing IMSI");
+                return;
+            }
 
-        Log.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
+            Log.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
 
-        if (mcc != 0) {
-            setTimezoneFromMccIfNeeded(phone, mcc);
-            setLocaleFromMccIfNeeded(phone, mcc);
-            setWifiChannelsFromMccIfNeeded(phone, mcc);
-        }
-        try {
-            Configuration config = ActivityManagerNative.getDefault().getConfiguration();
             if (mcc != 0) {
-                config.mcc = mcc;
+                setTimezoneFromMccIfNeeded(phone, mcc);
+                setLocaleFromMccIfNeeded(phone, mcc);
+                setWifiChannelsFromMccIfNeeded(phone, mcc);
             }
-            if (mnc != 0) {
-                config.mnc = mnc;
+            try {
+                Configuration config = ActivityManagerNative.getDefault().getConfiguration();
+                if (mcc != 0) {
+                    config.mcc = mcc;
+                }
+                if (mnc != 0) {
+                    config.mnc = mnc;
+                }
+                ActivityManagerNative.getDefault().updateConfiguration(config);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can't update configuration", e);
             }
-            ActivityManagerNative.getDefault().updateConfiguration(config);
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, "Can't update configuration", e);
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index e47f799..279f57f 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -2191,6 +2191,7 @@
             case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break;
             case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
             case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break;
+            case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break;
             default:
                 throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
             //break;
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
index 99709406..a636a4b 100644
--- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -109,6 +109,7 @@
         String mimeType = pduDecoder.getValueString();
         if (mimeType == null) {
             binaryContentType = (int)pduDecoder.getValue32();
+            // TODO we should have more generic way to map binaryContentType code to mimeType.
             switch (binaryContentType) {
                 case WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_XML:
                     mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML;
@@ -128,6 +129,9 @@
                 case WspTypeDecoder.CONTENT_TYPE_B_MMS:
                     mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS;
                     break;
+                case WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF:
+                    mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF;
+                    break;
                 default:
                     if (Config.LOGD) {
                         Log.w(LOG_TAG,
@@ -148,6 +152,8 @@
                 binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO;
             } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS)) {
                 binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_MMS;
+            } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF)) {
+                binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF;
             } else {
                 if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Unknown Content-Type = " + mimeType);
                 return Intents.RESULT_SMS_HANDLED;
@@ -155,28 +161,31 @@
         }
         index += pduDecoder.getDecodedDataLength();
 
-        int dataIndex = headerStartIndex + headerLength;
         boolean dispatchedByApplication = false;
         switch (binaryContentType) {
             case WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO:
-                dispatchWapPdu_PushCO(pdu, transactionId, pduType);
+                dispatchWapPdu_PushCO(pdu, transactionId, pduType, headerStartIndex, headerLength);
                 dispatchedByApplication = true;
                 break;
             case WspTypeDecoder.CONTENT_TYPE_B_MMS:
-                dispatchWapPdu_MMS(pdu, transactionId, pduType, dataIndex);
+                dispatchWapPdu_MMS(pdu, transactionId, pduType, headerStartIndex, headerLength);
                 dispatchedByApplication = true;
                 break;
             default:
                 break;
         }
         if (dispatchedByApplication == false) {
-            dispatchWapPdu_default(pdu, transactionId, pduType, mimeType, dataIndex);
+            dispatchWapPdu_default(pdu, transactionId, pduType, mimeType,
+                                   headerStartIndex, headerLength);
         }
         return Activity.RESULT_OK;
     }
 
-    private void dispatchWapPdu_default(
-            byte[] pdu, int transactionId, int pduType, String mimeType, int dataIndex) {
+    private void dispatchWapPdu_default(byte[] pdu, int transactionId, int pduType,
+                                        String mimeType, int headerStartIndex, int headerLength) {
+        byte[] header = new byte[headerLength];
+        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+        int dataIndex = headerStartIndex + headerLength;
         byte[] data;
 
         data = new byte[pdu.length - dataIndex];
@@ -186,31 +195,40 @@
         intent.setType(mimeType);
         intent.putExtra("transactionId", transactionId);
         intent.putExtra("pduType", pduType);
+        intent.putExtra("header", header);
         intent.putExtra("data", data);
 
         mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
     }
 
-    private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType) {
+    private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType,
+                                       int headerStartIndex, int headerLength) {
+        byte[] header = new byte[headerLength];
+        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+
         Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
         intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO);
         intent.putExtra("transactionId", transactionId);
         intent.putExtra("pduType", pduType);
+        intent.putExtra("header", header);
         intent.putExtra("data", pdu);
 
         mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
     }
 
-    private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType, int dataIndex) {
-        byte[] data;
-
-        data = new byte[pdu.length - dataIndex];
+    private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType,
+                                    int headerStartIndex, int headerLength) {
+        byte[] header = new byte[headerLength];
+        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+        int dataIndex = headerStartIndex + headerLength;
+        byte[] data = new byte[pdu.length - dataIndex];
         System.arraycopy(pdu, dataIndex, data, 0, data.length);
 
         Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
         intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS);
         intent.putExtra("transactionId", transactionId);
         intent.putExtra("pduType", pduType);
+        intent.putExtra("header", header);
         intent.putExtra("data", data);
 
         mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_MMS");
diff --git a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
index 3bbe0e1..336bc82 100644
--- a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
+++ b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
@@ -30,12 +30,16 @@
     public static final int PDU_TYPE_PUSH = 0x06;
     public static final int PDU_TYPE_CONFIRMED_PUSH = 0x07;
 
+    // TODO we should have mapping between those binary code and mime type string.
+    //  see http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx
+
     public static final int CONTENT_TYPE_B_DRM_RIGHTS_XML = 0x4a;
     public static final int CONTENT_TYPE_B_DRM_RIGHTS_WBXML = 0x4b;
     public static final int CONTENT_TYPE_B_PUSH_SI = 0x2e;
     public static final int CONTENT_TYPE_B_PUSH_SL = 0x30;
     public static final int CONTENT_TYPE_B_PUSH_CO = 0x32;
     public static final int CONTENT_TYPE_B_MMS = 0x3e;
+    public static final int CONTENT_TYPE_B_VND_DOCOMO_PF = 0x0310;
 
     public static final String CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML =
             "application/vnd.oma.drm.rights+xml";
@@ -45,6 +49,7 @@
     public static final String CONTENT_MIME_TYPE_B_PUSH_SL = "application/vnd.wap.slc";
     public static final String CONTENT_MIME_TYPE_B_PUSH_CO = "application/vnd.wap.coc";
     public static final String CONTENT_MIME_TYPE_B_MMS = "application/vnd.wap.mms-message";
+    public static final String CONTENT_MIME_TYPE_B_VND_DOCOMO_PF = "application/vnd.docomo.pf";
 
     public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f;
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 04a03b2..422cc19 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -202,10 +202,6 @@
         // Sets current entry in the telephony carrier table
         updateCurrentCarrierInProvider(operatorNumeric);
 
-        // Updates MCC MNC device configuration information
-        MccTable.updateMccMncConfiguration(this, operatorNumeric);
-
-
         // Notify voicemails.
         notifier.notifyMessageWaitingChanged(this);
     }
@@ -1401,20 +1397,22 @@
     }
 
     /**
-     * Sets the "current" field in the telephony provider according to the build-time
-     * operator numeric property
+     * Sets the "current" field in the telephony provider according to the
+     * build-time operator numeric property
      *
      * @return true for success; false otherwise.
      */
-    // TODO(Moto): move this method into PhoneBase, since it looks identical to
-    // the one in GsmPhone
-    private boolean updateCurrentCarrierInProvider(String operatorNumeric) {
+    boolean updateCurrentCarrierInProvider(String operatorNumeric) {
         if (!TextUtils.isEmpty(operatorNumeric)) {
             try {
                 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
                 ContentValues map = new ContentValues();
                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
                 getContext().getContentResolver().insert(uri, map);
+
+                // Updates MCC MNC device configuration information
+                MccTable.updateMccMncConfiguration(this, operatorNumeric);
+
                 return true;
             } catch (SQLException e) {
                 Log.e(LOG_TAG, "Can't store current operator", e);
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index ebd60a9..d627baf 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -280,6 +280,7 @@
             // send it as a UCS-2 encoded message
             try {
                 userData = encodeUCS2(message, header);
+                encoding = ENCODING_16BIT;
             } catch(UnsupportedEncodingException uex) {
                 Log.e(LOG_TAG,
                         "Implausible UnsupportedEncodingException ",
diff --git a/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp b/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
index 706c27e..2eff394 100644
--- a/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
+++ b/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
@@ -46,7 +46,7 @@
 
 void EventPlugin::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) {
 
-    gLogI.log(inst(), kDebug_ANPLogType, " ------ %p drawing the plugin (%d,%d)",
+    gLogI.log(kDebug_ANPLogType, " ------ %p drawing the plugin (%d,%d)",
               inst(), bitmap.width, bitmap.height);
 
     // get the plugin's dimensions according to the DOM
@@ -60,7 +60,7 @@
 
     // check to make sure the zoom level is uniform
     if (zoomFactorW + .01 < zoomFactorH && zoomFactorW - .01 > zoomFactorH)
-        gLogI.log(inst(), kError_ANPLogType, " ------ %p zoom is out of sync (%f,%f)",
+        gLogI.log(kError_ANPLogType, " ------ %p zoom is out of sync (%f,%f)",
                   inst(), zoomFactorW, zoomFactorH);
 
     // scale the variables based on the zoom level
@@ -109,7 +109,7 @@
     browser->getvalue(inst(), NPNVWindowNPObject, &windowObject);
 
     if (!windowObject)
-        gLogI.log(inst(), kError_ANPLogType, " ------ %p Unable to retrieve DOM Window", inst());
+        gLogI.log(kError_ANPLogType, " ------ %p Unable to retrieve DOM Window", inst());
 
     // create a string (JS code) that is stored in memory allocated by the browser
     const char* jsBegin = "var outputDiv = document.getElementById('eventOutput'); outputDiv.innerHTML += ' ";
@@ -126,13 +126,13 @@
     memcpy(middleMem, text, length);
     memcpy(endMem, jsEnd, strlen(jsEnd));
 
-    gLogI.log(inst(), kError_ANPLogType, "text: %.*s\n", totalLength, (char*)beginMem);
+    gLogI.log(kDebug_ANPLogType, "text: %.*s\n", totalLength, (char*)beginMem);
 
     // execute the javascript in the plugin's DOM object
     NPString script = { (char*)beginMem, totalLength };
     NPVariant scriptVariant;
     if (!browser->evaluate(inst(), windowObject, &script, &scriptVariant))
-        gLogI.log(inst(), kError_ANPLogType, " ------ %p Unable to eval the JS.", inst());
+        gLogI.log(kError_ANPLogType, " ------ %p Unable to eval the JS.", inst());
 
     // free the memory allocated within the browser
     browser->memfree(beginMem);
@@ -170,10 +170,10 @@
             }
             return 1;
         case kTouch_ANPEventType:
-            gLogI.log(inst(), kError_ANPLogType, " ------ %p the plugin did not request touch events", inst());
+            gLogI.log(kError_ANPLogType, " ------ %p the plugin did not request touch events", inst());
             break;
         case kKey_ANPEventType:
-            gLogI.log(inst(), kError_ANPLogType, " ------ %p the plugin did not request key events", inst());
+            gLogI.log(kError_ANPLogType, " ------ %p the plugin did not request key events", inst());
             break;
         default:
             break;
diff --git a/tests/BrowserTestPlugin/jni/main.cpp b/tests/BrowserTestPlugin/jni/main.cpp
index 2f295f0..c896ad5 100644
--- a/tests/BrowserTestPlugin/jni/main.cpp
+++ b/tests/BrowserTestPlugin/jni/main.cpp
@@ -134,7 +134,7 @@
 {
 
 
-    gLogI.log(instance, kDebug_ANPLogType, "creating plugin");
+    gLogI.log(kDebug_ANPLogType, "creating plugin");
 
     PluginObject *obj = NULL;
 
@@ -155,7 +155,7 @@
     NPError err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue,
                             reinterpret_cast<void*>(model));
     if (err) {
-        gLogI.log(instance, kError_ANPLogType, "request model %d err %d", model, err);
+        gLogI.log(kError_ANPLogType, "request model %d err %d", model, err);
         return err;
     }
 
@@ -220,7 +220,7 @@
     const ANPEvent* evt = reinterpret_cast<const ANPEvent*>(event);
 
     if(!obj->subPlugin) {
-        gLogI.log(instance, kError_ANPLogType, "the sub-plugin is null.");
+        gLogI.log(kError_ANPLogType, "the sub-plugin is null.");
         return 0; // unknown or unhandled event
     }
     else {
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 7dd4a88..8b8fb38 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -20,7 +20,7 @@
 
 def main(options, args):
   """Run the tests. Will call sys.exit when complete.
-  
+
   """
 
   # Set up logging format.
@@ -56,7 +56,15 @@
   run_load_test_cmd_postfix = " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
 
   # Call LoadTestsAutoTest::runTest.
-  run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms + run_load_test_cmd_postfix
+  run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms
+
+  if options.drawtime:
+    run_load_test_cmd += " -e drawtime true "
+
+  if options.save_image:
+    run_load_test_cmd += " -e saveimage \"%s\"" % options.save_image
+
+  run_load_test_cmd += run_load_test_cmd_postfix
 
   (adb_output, adb_error) = subprocess.Popen(run_load_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
   fail_flag = False
@@ -101,18 +109,26 @@
 
 if '__main__' == __name__:
   option_parser = optparse.OptionParser()
-  option_parser.add_option("", "--time-out-ms",
+  option_parser.add_option("-t", "--time-out-ms",
                            default=None,
                            help="set the timeout for each test")
-  option_parser.add_option("", "--verbose", action="store_true",
+  option_parser.add_option("-v", "--verbose", action="store_true",
                            default=False,
                            help="include debug-level logging")
-  option_parser.add_option("", "--adb-options",
+  option_parser.add_option("-a", "--adb-options",
                            default=None,
                            help="pass options to adb, such as -d -e, etc");
-  option_parser.add_option("", "--results-directory",
+  option_parser.add_option("-r", "--results-directory",
                            default="layout-test-results",
                            help="directory which results are stored.")
 
+  option_parser.add_option("-d", "--drawtime", action="store_true",
+                           default=False,
+                           help="log draw time for each page rendered.")
+
+  option_parser.add_option("-s", "--save-image",
+                           default=None,
+                           help="stores rendered page to a location on device.")
+
   options, args = option_parser.parse_args();
   main(options, args)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index fea366c..1a265e8 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -25,6 +25,7 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.util.regex.Pattern;
 
@@ -156,4 +157,43 @@
         return same;
     }
 
+    public static boolean isTestPageUrl(String url) {
+        int qmPostion = url.indexOf('?');
+        int slashPostion = url.lastIndexOf('/');
+        if (slashPostion < qmPostion) {
+            String fileName = url.substring(slashPostion + 1, qmPostion);
+            if ("index.html".equals(fileName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static String getLastSegmentInPath(String path) {
+        int endPos = path.lastIndexOf('/');
+        path = path.substring(0, endPos);
+        endPos = path.lastIndexOf('/');
+        return path.substring(endPos + 1);
+    }
+
+    public static void writeDrawTime(String fileName, String url, long[] times) {
+        StringBuffer lineBuffer = new StringBuffer();
+        // grab the last segment of path in url
+        lineBuffer.append(getLastSegmentInPath(url));
+        for (long time : times) {
+            lineBuffer.append('\t');
+            lineBuffer.append(time);
+        }
+        lineBuffer.append('\n');
+        String line = lineBuffer.toString();
+        Log.v(LOGTAG, "logging draw times: " + line);
+        try {
+            FileWriter fw = new FileWriter(fileName, true);
+            fw.write(line);
+            fw.close();
+        } catch (IOException ioe) {
+            Log.e(LOGTAG, "Failed to log draw times", ioe);
+        }
+    }
+
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
index 283b98c..539d551 100755
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
@@ -73,13 +73,20 @@
         this.mLogtime = (logtime != null
                 && logtime.toLowerCase().equals("true"));
 
+        String drawTime = (String) icicle.get("drawtime");
+        this.mGetDrawTime = (drawTime != null
+                && drawTime.toLowerCase().equals("true"));
+
+        mSaveImagePath = (String) icicle.get("saveimage");
+
         super.onCreate(icicle);
     }
     
     public String mTestPath = null;
+    public String mSaveImagePath = null;
     public int mTimeoutInMillis = 0;
     public int mDelay = 0;
     public boolean mRebaseline = false;
     public boolean mLogtime = false;
+    public boolean mGetDrawTime = false;
 }
-
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index ba46197..2ef342f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -70,7 +70,8 @@
         freeMem();
 
         // Run tests
-        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis);
+        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis,
+                runner.mGetDrawTime, runner.mSaveImagePath);
 
         activity.clearCache();
         try {
@@ -161,7 +162,8 @@
     }
 
     // A convenient method to be called by another activity.
-    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout) {
+    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout,
+            boolean getDrawTime, String saveImagePath) {
         activity.setCallback(new TestShellCallback() {
             public void finished() {
                 synchronized (LoadTestsAutoTest.this) {
@@ -181,6 +183,9 @@
         intent.putExtra(TestShellActivity.TEST_URL, url);
         intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
         intent.putExtra(TestShellActivity.RESULT_FILE, LOAD_TEST_RESULT);
+        intent.putExtra(TestShellActivity.GET_DRAW_TIME, getDrawTime);
+        if (saveImagePath != null)
+            intent.putExtra(TestShellActivity.SAVE_IMAGE, saveImagePath);
         activity.startActivity(intent);
 
         // Wait until done.
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index aeb55b4..b6b1661 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -25,6 +25,9 @@
 import android.content.Intent;
 import android.content.DialogInterface.OnClickListener;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Bitmap.Config;
 import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.Handler;
@@ -163,6 +166,8 @@
 
         mResultFile = intent.getStringExtra(RESULT_FILE);
         mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 0);
+        mGetDrawtime = intent.getBooleanExtra(GET_DRAW_TIME, false);
+        mSaveImagePath = intent.getStringExtra(SAVE_IMAGE);
 
         Log.v(LOGTAG, "  Loading " + mTestUrl);
         mWebView.loadUrl(mTestUrl);
@@ -459,6 +464,18 @@
         public void onPageFinished(WebView view, String url) {
             Log.v(LOGTAG, "onPageFinished, url=" + url);
             mPageFinished = true;
+            // get page draw time
+            if (FsUtils.isTestPageUrl(url)) {
+                if (mGetDrawtime) {
+                    long[] times = new long[DRAW_RUNS];
+                    times = getDrawWebViewTime(mWebView, DRAW_RUNS);
+                    FsUtils.writeDrawTime(DRAW_TIME_LOG, url, times);
+                }
+                if (mSaveImagePath != null) {
+                    String name = FsUtils.getLastSegmentInPath(url);
+                    drawPageToFile(mSaveImagePath + "/" + name + ".png", mWebView);
+                }
+            }
             // Calling finished() will check if we've met all the conditions for completing
             // this test and move to the next one if we are ready.
             if (finished()) {
@@ -691,6 +708,41 @@
         mPageFinished = false;
         mOneHundredPercentComplete = false;
         mDumpWebKitData = false;
+        mGetDrawtime = false;
+        mSaveImagePath = null;
+    }
+
+    private long[] getDrawWebViewTime(WebView view, int count) {
+        if (count == 0)
+            return null;
+        long[] ret = new long[count];
+        long start;
+        Canvas canvas = new Canvas();
+        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888);
+        canvas.setBitmap(bitmap);
+        for (int i = 0; i < count; i++) {
+            start = System.currentTimeMillis();
+            view.draw(canvas);
+            ret[i] = System.currentTimeMillis() - start;
+        }
+        return ret;
+    }
+
+    private void drawPageToFile(String fileName, WebView view) {
+        Canvas canvas = new Canvas();
+        Bitmap bitmap = Bitmap.createBitmap(view.getContentWidth(), view.getContentHeight(),
+                Config.ARGB_8888);
+        canvas.setBitmap(bitmap);
+        view.drawPage(canvas);
+        try {
+            FileOutputStream fos = new FileOutputStream(fileName);
+            if(!bitmap.compress(CompressFormat.PNG, 90, fos)) {
+                Log.w(LOGTAG, "Failed to compress and save image.");
+            }
+        } catch (IOException ioe) {
+            Log.e(LOGTAG, "", ioe);
+        }
+        bitmap.recycle();
     }
 
     private boolean canMoveToNextTest() {
@@ -730,7 +782,9 @@
     private String mResultFile;
     private int mTimeoutInMillis;
     private String mUiAutoTestPath;
+    private String mSaveImagePath;
     private BufferedReader mTestListReader;
+    private boolean mGetDrawtime;
 
     // States
     private boolean mTimedOut;
@@ -766,6 +820,11 @@
     static final String RESULT_FILE = "ResultFile";
     static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis";
     static final String UI_AUTO_TEST = "UiAutoTest";
+    static final String GET_DRAW_TIME = "GetDrawTime";
+    static final String SAVE_IMAGE = "SaveImage";
+
+    static final int DRAW_RUNS = 5;
+    static final String DRAW_TIME_LOG = "/sdcard/android/page_draw_time.txt";
 
     private boolean mGeolocationPermissionSet;
     private boolean mGeolocationPermission;
diff --git a/tests/backup/test_backup.sh b/tests/backup/test_backup.sh
index 10b809d..113a26d 100755
--- a/tests/backup/test_backup.sh
+++ b/tests/backup/test_backup.sh
@@ -18,10 +18,12 @@
 #export DRY_RUN="echo"
 source test_backup_common.sh
 
-# wipe prior backup data for packages
+# figure out what packages are participating in backup
 b_pkgs=$(a shell dumpsys backup | \
-         ruby -ne 'print($1+" ") if $_ =~ /^\s*ApplicationInfo\S+ (.+?)\}/')
+         ruby -e 'p_stanza = STDIN.read.match(/Participants:.*?(?=Ever)/m)[0]
+                  puts p_stanza.scan(/^    (.+?)\s*$/).flatten.join(" ")')
 
+# wipe data for the package participating in backup
 for pkg in $b_pkgs; do
     a shell bmgr wipe "$pkg"
 done
@@ -36,7 +38,7 @@
 set -x
 
 # set the transport
-a shell bmgr transport com.google.android.backup/.BackupTransportService
+#a shell bmgr transport com.google.android.backup/.BackupTransportService
 
 # load up the three files
 a shell \
diff --git a/tests/backup/test_restore.sh b/tests/backup/test_restore.sh
index 46b46e4..48e5c66 100755
--- a/tests/backup/test_restore.sh
+++ b/tests/backup/test_restore.sh
@@ -45,7 +45,7 @@
     fi
 }
 
-# run adb as root so we can poke at com.android.backuptest's data
+# Make sure adb is root so we can poke at com.android.backuptest's data
 adb_root
 
 # delete the old data