Merge change 9267

* changes:
  Don't invalidate view if setEnabled doesn't change the state.
diff --git a/api/current.xml b/api/current.xml
index 1f53be9..b0b9ce65 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -117837,6 +117837,746 @@
 >
 </field>
 </class>
+<class name="SmsManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="divideMessage"
+ return="java.util.ArrayList&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.String">
+</parameter>
+</method>
+<method name="getDefault"
+ return="android.telephony.SmsManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="sendDataMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationPort" type="short">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="sentIntent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="deliveryIntent" type="android.app.PendingIntent">
+</parameter>
+</method>
+<method name="sendMultipartTextMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="parts" type="java.util.ArrayList&lt;java.lang.String&gt;">
+</parameter>
+<parameter name="sentIntents" type="java.util.ArrayList&lt;android.app.PendingIntent&gt;">
+</parameter>
+<parameter name="deliveryIntents" type="java.util.ArrayList&lt;android.app.PendingIntent&gt;">
+</parameter>
+</method>
+<method name="sendTextMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="text" type="java.lang.String">
+</parameter>
+<parameter name="sentIntent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="deliveryIntent" type="android.app.PendingIntent">
+</parameter>
+</method>
+<field name="RESULT_ERROR_GENERIC_FAILURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESULT_ERROR_NO_SERVICE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESULT_ERROR_NULL_PDU"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESULT_ERROR_RADIO_OFF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_FREE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_READ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_SENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_UNREAD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_UNSENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SmsMessage"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="calculateLength"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msgBody" type="java.lang.CharSequence">
+</parameter>
+<parameter name="use7bitOnly" type="boolean">
+</parameter>
+</method>
+<method name="calculateLength"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messageBody" type="java.lang.String">
+</parameter>
+<parameter name="use7bitOnly" type="boolean">
+</parameter>
+</method>
+<method name="createFromPdu"
+ return="android.telephony.SmsMessage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pdu" type="byte[]">
+</parameter>
+</method>
+<method name="getDisplayMessageBody"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDisplayOriginatingAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEmailBody"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEmailFrom"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIndexOnIcc"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIndexOnSim"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessageBody"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessageClass"
+ return="android.telephony.SmsMessage.MessageClass"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOriginatingAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPdu"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProtocolIdentifier"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPseudoSubject"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getServiceCenterAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStatus"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStatusOnIcc"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStatusOnSim"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubmitPdu"
+ return="android.telephony.SmsMessage.SubmitPdu"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="statusReportRequested" type="boolean">
+</parameter>
+</method>
+<method name="getSubmitPdu"
+ return="android.telephony.SmsMessage.SubmitPdu"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationPort" type="short">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="statusReportRequested" type="boolean">
+</parameter>
+</method>
+<method name="getTPLayerLengthForPDU"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pdu" type="java.lang.String">
+</parameter>
+</method>
+<method name="getTimestampMillis"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUserData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isCphsMwiMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isEmail"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMWIClearMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMWISetMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMwiDontStore"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isReplace"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isReplyPathPresent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isStatusReportMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="ENCODING_16BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCODING_7BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCODING_8BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCODING_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_BYTES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="140"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_BYTES_WITH_HEADER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="134"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_SEPTETS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="160"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_SEPTETS_WITH_HEADER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="153"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SmsMessage.MessageClass"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.telephony.SmsMessage.MessageClass"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.telephony.SmsMessage.MessageClass[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="SmsMessage.SubmitPdu"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="encodedMessage"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="encodedScAddress"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="TelephonyManager"
  extends="java.lang.Object"
  abstract="false"
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index c45b53c..9a1f845 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -228,6 +228,11 @@
     char keyfile[KEYFILE_LEN];
 
     if (state != UNLOCKED) return -state;
+    if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
+        (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
+        LOGE("keyname is too long.");
+        return -1;
+    }
     sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
     return unlink(keyfile);
 }
@@ -243,12 +248,12 @@
         LOGE("Can not store key with current state %d\n", state);
         return -state;
     }
-    sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
-    // flatten the args
-    if (strlen(keyname) >= MAX_KEY_NAME_LENGTH) {
+    if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
+        (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
         LOGE("keyname is too long.");
         return -1;
     }
+    sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
     strcpy(blob.keyname, keyname);
     blob.value_size = size;
     if (size > MAX_KEY_VALUE_LENGTH) {
@@ -271,6 +276,11 @@
         LOGE("Can not retrieve key value with current state %d\n", state);
         return -state;
     }
+    if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
+        (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
+        LOGE("keyname is too long.");
+        return -1;
+    }
     sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
     ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
     if (!ret) {
@@ -299,6 +309,13 @@
         LOGE("cannot open keystore dir or namespace is null\n");
         return -1;
     }
+
+    if (strlen(namespace) >= MAX_KEY_NAME_LENGTH) {
+        LOGE("namespace is too long.");
+        return -1;
+    }
+
+    reply[0] = 0;
     while ((de = readdir(d))) {
         char *prefix, *name, *keyfile = de->d_name;
         char *context = NULL;
@@ -367,6 +384,7 @@
 
 int reset_keystore()
 {
+    int ret = 0;
     DIR *d;
     struct dirent *de;
 
@@ -374,18 +392,24 @@
         LOGE("cannot open keystore dir\n");
         return -1;
     }
-    while ((de = readdir(d))) unlink(de->d_name);
+    while ((de = readdir(d))) {
+        if (unlink(de->d_name) != 0) ret = -1;
+    }
     closedir(d);
     state = UNINITIALIZED;
-    LOGI("keystore is reset.");
-    return 0;
+    if (ret == 0) {
+        LOGI("keystore is reset.");
+    } else {
+        LOGI("keystore can not be cleaned up entirely.");
+    }
+    return ret;
 }
 
 int init_keystore(const char *dir)
 {
     int fd;
 
-    if (!dir) mkdir(dir, 0770);
+    if (dir) mkdir(dir, 0770);
     if (!dir || chdir(dir)) {
         LOGE("Can not open/create the keystore directory %s\n",
              dir ? dir : "(null)");
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
new file mode 100644
index 0000000..33541cc
--- /dev/null
+++ b/cmds/keystore/tests/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      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.
+#
+# define the KEYSTORE_TESTS environment variable to build the test programs
+ifdef KEYSTORE_TESTS
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
+LOCAL_SHARED_LIBRARIES := libcutils libssl
+LOCAL_MODULE:= netkeystore_test
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := external/openssl/include \
+								frameworks/base/cmds/keystore
+EXTRA_CFLAGS := -g -O0 -DGTEST_OS_LINUX -DGTEST_HAS_STD_STRING
+include $(BUILD_EXECUTABLE)
+
+endif  #KEYSTORE_TESTS
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
new file mode 100644
index 0000000..e7e686b
--- /dev/null
+++ b/cmds/keystore/tests/netkeystore_test.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "keymgmt.h"
+
+typedef int FUNC_PTR();
+typedef struct {
+    const char *name;
+    FUNC_PTR *func;
+} TESTFUNC;
+
+#define FUNC_NAME(x) { #x, test_##x }
+#define FUNC_BODY(x) int test_##x()
+
+#define TEST_PASSWD        "12345678"
+#define TEST_NPASSWD    "11111111"
+#define TEST_DIR        "/data/local/tmp/keystore"
+#define READONLY_DIR    "/proc/keystore"
+#define TEST_NAMESPACE    "test"
+#define TEST_KEYNAME    "key"
+#define TEST_KEYNAME2    "key2"
+#define TEST_KEYVALUE    "ANDROID"
+
+void setup()
+{
+    if (init_keystore(TEST_DIR) != 0) {
+        fprintf(stderr, "Can not create the test directory %s\n", TEST_DIR);
+        exit(-1);
+    }
+}
+
+void teardown()
+{
+    reset_keystore();
+    rmdir(TEST_DIR);
+}
+
+FUNC_BODY(init_keystore)
+{
+    if (init_keystore(READONLY_DIR) == 0) return -1;
+
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(reset_keystore)
+{
+    chdir("/procx");
+    if (reset_keystore() == 0) return -1;
+    chdir(TEST_DIR);
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(get_state)
+{
+    if (get_state() != UNINITIALIZED) return -1;
+    passwd(TEST_PASSWD);
+    if (get_state() != UNLOCKED) return -1;
+    lock();
+    if (get_state() != LOCKED) return -1;
+    reset_keystore();
+    if (get_state() != UNINITIALIZED) return -1;
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(passwd)
+{
+    char buf[512];
+
+    if (passwd(" 23432dsfsdf") == 0) return -1;
+    if (passwd("dsfsdf") == 0) return -1;
+    passwd(TEST_PASSWD);
+    lock();
+    if (unlock("55555555") == 0) return -1;
+    if (unlock(TEST_PASSWD) != 0) return -1;
+
+    // change the password
+    sprintf(buf, "%s %s", "klfdjdsklfjg", "abcdefghi");
+    if (passwd(buf) == 0) return -1;
+
+    sprintf(buf, "%s %s", TEST_PASSWD, TEST_NPASSWD);
+    if (passwd(buf) != 0) return -1;
+    lock();
+
+    if (unlock(TEST_PASSWD) == 0) return -1;
+    if (unlock(TEST_NPASSWD) != 0) return -1;
+
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(lock)
+{
+    if (lock() == 0) return -1;
+    passwd(TEST_PASSWD);
+    if (lock() != 0) return -1;
+    if (lock() != 0) return -1;
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(unlock)
+{
+    int i = MAX_RETRY_COUNT;
+    passwd(TEST_PASSWD);
+    lock();
+    while (i > 1) {
+        if (unlock(TEST_NPASSWD) != --i) return -1;
+    }
+    if (unlock(TEST_NPASSWD) != -1) return -1;
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(put_key)
+{
+    int i = 0;
+    char keyname[512];
+
+    if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+                strlen(TEST_KEYVALUE)) == 0) return -1;
+    passwd(TEST_PASSWD);
+    if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+                strlen(TEST_KEYVALUE)) != 0) return -1;
+
+    for(i = 0; i < 500; i++) keyname[i] = 'K';
+    keyname[i] = 0;
+    if (put_key(TEST_NAMESPACE, keyname, (unsigned char *)TEST_KEYVALUE,
+                strlen(TEST_KEYVALUE)) == 0) return -1;
+    if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+                MAX_KEY_VALUE_LENGTH + 1) == 0) return -1;
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(get_key)
+{
+    int size;
+    unsigned char data[MAX_KEY_VALUE_LENGTH];
+
+    if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) == 0) return -1;
+
+    passwd(TEST_PASSWD);
+    put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+            strlen(TEST_KEYVALUE));
+    if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) != 0) return -1;
+    if (memcmp(data, TEST_KEYVALUE, size) != 0) return -1;
+
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(remove_key)
+{
+    if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
+
+    passwd(TEST_PASSWD);
+    if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
+
+    put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+            strlen(TEST_KEYVALUE));
+    if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) != 0) return -1;
+
+    return EXIT_SUCCESS;
+}
+
+FUNC_BODY(list_keys)
+{
+    int i;
+    char buf[128];
+    char reply[BUFFER_MAX];
+
+    for(i = 0; i < 100; i++) buf[i] = 'K';
+    buf[i] = 0;
+
+    if (list_keys(TEST_NAMESPACE, reply) == 0) return -1;
+
+    passwd(TEST_PASSWD);
+    if (list_keys(buf, reply) == 0) return -1;
+
+    if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
+    if (strcmp(reply, "") != 0) return -1;
+
+    put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+            strlen(TEST_KEYVALUE));
+    if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
+    if (strcmp(reply, TEST_KEYNAME) != 0) return -1;
+
+    put_key(TEST_NAMESPACE, TEST_KEYNAME2, (unsigned char *)TEST_KEYVALUE,
+            strlen(TEST_KEYVALUE));
+
+    if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
+    sprintf(buf, "%s %s", TEST_KEYNAME2, TEST_KEYNAME);
+    if (strcmp(reply, buf) != 0) return -1;
+
+    return EXIT_SUCCESS;
+}
+
+TESTFUNC all_tests[] = {
+    FUNC_NAME(init_keystore),
+    FUNC_NAME(reset_keystore),
+    FUNC_NAME(get_state),
+    FUNC_NAME(passwd),
+    FUNC_NAME(lock),
+    FUNC_NAME(unlock),
+    FUNC_NAME(put_key),
+    FUNC_NAME(get_key),
+    FUNC_NAME(remove_key),
+    FUNC_NAME(list_keys),
+};
+
+int main(int argc, char **argv) {
+    int i, ret;
+    for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
+        setup();
+        if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
+            fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
+            return ret;
+        } else {
+            fprintf(stderr, "function %s PASSED!\n", all_tests[i].name);
+        }
+        teardown();
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 4dd2433..18e4a528 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -903,6 +903,12 @@
                     getContext().startActivity(mVoiceWebSearchIntent);
                 } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
                     Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent);
+                    
+                    // Stop the existing search before starting voice search, or else we'll end
+                    // up showing the search dialog again once we return to the app.
+                    ((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE)).
+                            stopSearch();
+                    
                     getContext().startActivity(appSearchIntent);
                 }
             } catch (ActivityNotFoundException e) {
@@ -1238,11 +1244,11 @@
         // ensure the icons will work for global search
         cv.put(SearchManager.SUGGEST_COLUMN_ICON_1,
                         wrapIconForPackage(
-                                source,
+                                mSearchable.getSuggestPackage(),
                                 getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_1)));
         cv.put(SearchManager.SUGGEST_COLUMN_ICON_2,
                         wrapIconForPackage(
-                                source,
+                                mSearchable.getSuggestPackage(),
                                 getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_2)));
 
         // the rest can be passed through directly
@@ -1281,11 +1287,11 @@
      * Wraps an icon for a particular package.  If the icon is a resource id, it is converted into
      * an android.resource:// URI.
      *
-     * @param source The source of the icon
+     * @param packageName The source of the icon
      * @param icon The icon retrieved from a suggestion column
      * @return An icon string appropriate for the package.
      */
-    private String wrapIconForPackage(ComponentName source, String icon) {
+    private String wrapIconForPackage(String packageName, String icon) {
         if (icon == null || icon.length() == 0 || "0".equals(icon)) {
             // SearchManager specifies that null or zero can be returned to indicate
             // no icon. We also allow empty string.
@@ -1293,7 +1299,6 @@
         } else if (!Character.isDigit(icon.charAt(0))){
             return icon;
         } else {
-            String packageName = source.getPackageName();
             return new Uri.Builder()
                     .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                     .authority(packageName)
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 5c7b01f..8ebe093 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -637,12 +637,13 @@
      *  mRetData. */
     private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
                                                boolean resolve);
-    /*package*/ static final int STYLE_NUM_ENTRIES = 5;
+    /*package*/ static final int STYLE_NUM_ENTRIES = 6;
     /*package*/ static final int STYLE_TYPE = 0;
     /*package*/ static final int STYLE_DATA = 1;
     /*package*/ static final int STYLE_ASSET_COOKIE = 2;
     /*package*/ static final int STYLE_RESOURCE_ID = 3;
     /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
+    /*package*/ static final int STYLE_DENSITY = 5;
     /*package*/ native static final boolean applyStyle(int theme,
             int defStyleAttr, int defStyleRes, int xmlParser,
             int[] inAttrs, int[] outValues, int[] outIndices);
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 3a32c03..016ee7f 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -654,6 +654,7 @@
         outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
         outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
         outValue.changingConfigurations = data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS];
+        outValue.density = data[index+AssetManager.STYLE_DENSITY];
         if (type == TypedValue.TYPE_STRING) {
             outValue.string = loadStringValueAt(index);
         }
diff --git a/core/java/android/provider/SocialContract.java b/core/java/android/provider/SocialContract.java
index d542774..ee271ba 100644
--- a/core/java/android/provider/SocialContract.java
+++ b/core/java/android/provider/SocialContract.java
@@ -165,11 +165,11 @@
 
         /**
          * The {@link Uri} for the latest social activity performed by any
-         * contact aggregated under the specified {@link Contacts#_ID}. Will
+         * raw contact aggregated under the specified {@link Contacts#_ID}. Will
          * also join with most-present {@link Presence} for this aggregate.
          */
-        public static final Uri CONTENT_AGGREGATE_STATUS_URI =
-            Uri.withAppendedPath(AUTHORITY_URI, "aggregate_status");
+        public static final Uri CONTENT_CONTACT_STATUS_URI =
+            Uri.withAppendedPath(AUTHORITY_URI, "contact_status");
 
         /**
          * The MIME type of {@link #CONTENT_URI} providing a directory of social
diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java
index 045b0c2..69ef98c 100644
--- a/core/java/android/server/search/SearchableInfo.java
+++ b/core/java/android/server/search/SearchableInfo.java
@@ -103,6 +103,14 @@
     }
 
     /**
+     * Gets the name of the package where the suggestion provider lives,
+     * or {@code null}.
+     */
+    public String getSuggestPackage() {
+        return mSuggestProviderPackage;
+    }
+
+    /**
      * Gets the component name of the searchable activity.
      */
     public ComponentName getSearchActivity() {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 884950f..0d44b4e 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -21,7 +21,6 @@
 
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
-import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -1220,6 +1219,8 @@
                         if (mTranslator != null) {
                             mTranslator.translateCanvas(canvas);
                         }
+                        canvas.setScreenDensity(scalingRequired
+                                ? DisplayMetrics.DENSITY_DEVICE : 0);
                         mView.draw(canvas);
                         if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
                             mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);
@@ -1328,6 +1329,8 @@
                     if (mTranslator != null) {
                         mTranslator.translateCanvas(canvas);
                     }
+                    canvas.setScreenDensity(scalingRequired
+                            ? DisplayMetrics.DENSITY_DEVICE : 0);
                     mView.draw(canvas);
                 } finally {
                     mAttachInfo.mIgnoreDirtyState = false;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 358fc9e..05a7806 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -206,11 +206,6 @@
 
     static final String LOGTAG = "webview";
 
-    static class ScaleLimitData {
-        int mMinScale;
-        int mMaxScale;
-    }
-
     private static class ExtendedZoomControls extends FrameLayout {
         public ExtendedZoomControls(Context context, AttributeSet attrs) {
             super(context, attrs);
@@ -472,7 +467,6 @@
     static final int UPDATE_TEXT_ENTRY_MSG_ID           = 15;
     static final int WEBCORE_INITIALIZED_MSG_ID         = 16;
     static final int UPDATE_TEXTFIELD_TEXT_MSG_ID       = 17;
-    static final int DID_FIRST_LAYOUT_MSG_ID            = 18;
     static final int MOVE_OUT_OF_PLUGIN                 = 19;
     static final int CLEAR_TEXT_ENTRY                   = 20;
 
@@ -502,7 +496,7 @@
         "UPDATE_TEXT_ENTRY_MSG_ID", //       = 15;
         "WEBCORE_INITIALIZED_MSG_ID", //     = 16;
         "UPDATE_TEXTFIELD_TEXT_MSG_ID", //   = 17;
-        "DID_FIRST_LAYOUT_MSG_ID", //        = 18;
+        "18", //        = 18;
         "MOVE_OUT_OF_PLUGIN", //             = 19;
         "CLEAR_TEXT_ENTRY", //               = 20;
         "21", //                             = 21;
@@ -1892,6 +1886,13 @@
         r.bottom = viewToContent(r.bottom);
     }
 
+    static class ViewSizeData {
+        int mWidth;
+        int mHeight;
+        int mTextWrapWidth;
+        float mScale;
+    }
+
     /**
      * Compute unzoomed width and height, and if they differ from the last
      * values we sent, send them to webkit (to be used has new viewport)
@@ -1899,7 +1900,8 @@
      * @return true if new values were sent
      */
     private boolean sendViewSizeZoom() {
-        int newWidth = Math.round(getViewWidth() * mInvActualScale);
+        int viewWidth = getViewWidth();
+        int newWidth = Math.round(viewWidth * mInvActualScale);
         int newHeight = Math.round(getViewHeight() * mInvActualScale);
         /*
          * Because the native side may have already done a layout before the
@@ -1914,8 +1916,16 @@
         }
         // Avoid sending another message if the dimensions have not changed.
         if (newWidth != mLastWidthSent || newHeight != mLastHeightSent) {
-            mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED,
-                    newWidth, newHeight, new Float(mActualScale));
+            ViewSizeData data = new ViewSizeData();
+            data.mWidth = newWidth;
+            data.mHeight = newHeight;
+            // while in zoom overview mode, the text are wrapped to the screen
+            // width matching mLastScale. So that we don't trigger re-flow while
+            // toggling between overview mode and normal mode.
+            data.mTextWrapWidth = mInZoomOverview ? Math.round(viewWidth
+                    / mLastScale) : newWidth;
+            data.mScale = mActualScale;
+            mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
             mLastWidthSent = newWidth;
             mLastHeightSent = newHeight;
             return true;
@@ -3877,11 +3887,6 @@
                     if (!mDragFromTextInput) {
                         nativeHideCursor();
                     }
-                    // remove the zoom anchor if there is any
-                    if (mZoomScale != 0) {
-                        mWebViewCore
-                                .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0);
-                    }
                     WebSettings settings = getSettings();
                     if (settings.supportZoom() && !mInZoomOverview
                             && settings.getBuiltInZoomControls()
@@ -4982,15 +4987,35 @@
                     final WebViewCore.DrawData draw =
                             (WebViewCore.DrawData) msg.obj;
                     final Point viewSize = draw.mViewPoint;
-                    if (mZoomScale > 0) {
-                        // use the same logic in sendViewSizeZoom() to make sure
-                        // the mZoomScale has matched the viewSize so that we
-                        // can clear mZoomScale
-                        if (Math.round(viewWidth / mZoomScale) == viewSize.x) {
-                            mZoomScale = 0;
-                            mWebViewCore.sendMessage(EventHub.SET_SNAP_ANCHOR,
-                                    0, 0);
+                    boolean useWideViewport =
+                            mWebViewCore.getSettings().getUseWideViewPort();
+                    WebViewCore.RestoreState restoreState = draw.mRestoreState;
+                    if (restoreState != null) {
+                        mInZoomOverview = false;
+                        mLastScale = restoreState.mTextWrapScale;
+                        if (restoreState.mMinScale == 0) {
+                            mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
+                            mMinZoomScaleFixed = false;
+                        } else {
+                            mMinZoomScale = restoreState.mMinScale;
+                            mMinZoomScaleFixed = true;
                         }
+                        if (restoreState.mMaxScale == 0) {
+                            mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
+                        } else {
+                            mMaxZoomScale = restoreState.mMaxScale;
+                        }
+                        if (useWideViewport && restoreState.mViewScale == 0) {
+                            mInZoomOverview = ENABLE_DOUBLETAP_ZOOM;
+                        }
+                        setNewZoomScale(mLastScale, false);
+                        setContentScrollTo(restoreState.mScrollX,
+                                restoreState.mScrollY);
+                        // As we are on a new page, remove the WebTextView. This
+                        // is necessary for page loads driven by webkit, and in
+                        // particular when the user was on a password field, so
+                        // the WebTextView was visible.
+                        clearTextEntry();
                     }
                     // We update the layout (i.e. request a layout from the
                     // view system) if the last view size that we sent to
@@ -5009,7 +5034,7 @@
                     if (mPictureListener != null) {
                         mPictureListener.onNewPicture(WebView.this, capturePicture());
                     }
-                    if (mWebViewCore.getSettings().getUseWideViewPort()) {
+                    if (useWideViewport) {
                         mZoomOverviewWidth = Math.max(draw.mMinPrefWidth,
                                 draw.mViewPoint.x);
                     }
@@ -5056,76 +5081,6 @@
                         }
                     }
                     break;
-                case DID_FIRST_LAYOUT_MSG_ID: {
-                    if (mNativeClass == 0) {
-                        break;
-                    }
-                    ScaleLimitData scaleLimit = (ScaleLimitData) msg.obj;
-                    int minScale = scaleLimit.mMinScale;
-                    if (minScale == 0) {
-                        mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
-                        mMinZoomScaleFixed = false;
-                    } else {
-                        mMinZoomScale = (float) (minScale / 100.0);
-                        mMinZoomScaleFixed = true;
-                    }
-                    int maxScale = scaleLimit.mMaxScale;
-                    if (maxScale == 0) {
-                        mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
-                    } else {
-                        mMaxZoomScale = (float) (maxScale / 100.0);
-                    }
-                    // If history Picture is drawn, don't update zoomWidth
-                    if (mDrawHistory) {
-                        break;
-                    }
-                    int width = getViewWidth();
-                    if (width == 0) {
-                        break;
-                    }
-                    final WebSettings settings = mWebViewCore.getSettings();
-                    int initialScale = msg.arg1;
-                    int viewportWidth = msg.arg2;
-                    // start a new page with DEFAULT_SCALE zoom scale.
-                    float scale = mDefaultScale;
-                    mInZoomOverview = false;
-                    if (mInitialScale > 0) {
-                        scale = mInitialScale / 100.0f;
-                    } else  {
-                        if (initialScale == -1) break;
-                        if (settings.getUseWideViewPort()) {
-                            // force viewSizeChanged by setting mLastWidthSent
-                            // to 0
-                            mLastWidthSent = 0;
-                        }
-                        if (initialScale == 0) {
-                            // if viewportWidth is defined and it is smaller
-                            // than the view width, zoom in to fill the view
-                            if (viewportWidth > 0 && viewportWidth < width) {
-                                scale = (float) width / viewportWidth;
-                            } else {
-                                if (settings.getUseWideViewPort()) {
-                                    mInZoomOverview = ENABLE_DOUBLETAP_ZOOM;
-                                }
-                            }
-                        } else if (initialScale < 0) {
-                            // this should only happen when
-                            // ENABLE_DOUBLETAP_ZOOM is true
-                            mInZoomOverview = true;
-                            scale = -initialScale / 100.0f;
-                        } else {
-                            scale = initialScale / 100.0f;
-                        }
-                    }
-                    mLastScale = scale;
-                    setNewZoomScale(scale, false);
-                    // As we are on a new page, remove the WebTextView.  This
-                    // is necessary for page loads driven by webkit, and in
-                    // particular when the user was on a password field, so
-                    // the WebTextView was visible.
-                    clearTextEntry();
-                    break;
-                }
                 case MOVE_OUT_OF_PLUGIN:
                     if (nativePluginEatsNavKey()) {
                         navHandledKey(msg.arg1, 1, false, 0, true);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 4afc4cd..8ec8174 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -443,10 +443,6 @@
 
     private native void nativeUpdateFrameCache();
 
-    private native void nativeSetSnapAnchor(int x, int y);
-
-    private native void nativeSnapToAnchor();
-
     private native void nativeSetBackgroundColor(int color);
 
     private native void nativeDumpDomTree(boolean useFile);
@@ -674,7 +670,7 @@
             "CLICK", // = 118;
             "SET_NETWORK_STATE", // = 119;
             "DOC_HAS_IMAGES", // = 120;
-            "SET_SNAP_ANCHOR", // = 121;
+            "121", // = 121;
             "DELETE_SELECTION", // = 122;
             "LISTBOX_CHOICES", // = 123;
             "SINGLE_LISTBOX_CHOICE", // = 124;
@@ -725,7 +721,6 @@
         static final int CLICK = 118;
         static final int SET_NETWORK_STATE = 119;
         static final int DOC_HAS_IMAGES = 120;
-        static final int SET_SNAP_ANCHOR = 121;
         static final int DELETE_SELECTION = 122;
         static final int LISTBOX_CHOICES = 123;
         static final int SINGLE_LISTBOX_CHOICE = 124;
@@ -904,11 +899,13 @@
                             nativeClick(msg.arg1, msg.arg2);
                             break;
 
-                        case VIEW_SIZE_CHANGED:
-                            viewSizeChanged(msg.arg1, msg.arg2,
-                                    ((Float) msg.obj).floatValue());
+                        case VIEW_SIZE_CHANGED: {
+                            WebView.ViewSizeData data =
+                                    (WebView.ViewSizeData) msg.obj;
+                            viewSizeChanged(data.mWidth, data.mHeight,
+                                    data.mTextWrapWidth, data.mScale);
                             break;
-
+                        }
                         case SET_SCROLL_OFFSET:
                             // note: these are in document coordinates
                             // (inv-zoom)
@@ -1107,10 +1104,6 @@
                             imageResult.sendToTarget();
                             break;
 
-                        case SET_SNAP_ANCHOR:
-                            nativeSetSnapAnchor(msg.arg1, msg.arg2);
-                            break;
-
                         case DELETE_SELECTION:
                             DeleteSelectionData deleteSelectionData
                                     = (DeleteSelectionData) msg.obj;
@@ -1401,16 +1394,20 @@
     // These values are used to avoid requesting a layout based on old values
     private int mCurrentViewWidth = 0;
     private int mCurrentViewHeight = 0;
+    private float mCurrentViewScale = 1.0f;
 
     // notify webkit that our virtual view size changed size (after inv-zoom)
-    private void viewSizeChanged(int w, int h, float scale) {
-        if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "CORE onSizeChanged");
+    private void viewSizeChanged(int w, int h, int textwrapWidth, float scale) {
+        if (DebugFlags.WEB_VIEW_CORE) {
+            Log.v(LOGTAG, "viewSizeChanged w=" + w + "; h=" + h
+                    + "; textwrapWidth=" + textwrapWidth + "; scale=" + scale);
+        }
         if (w == 0) {
             Log.w(LOGTAG, "skip viewSizeChanged as w is 0");
             return;
         }
+        int width = w;
         if (mSettings.getUseWideViewPort()) {
-            int width;
             if (mViewportWidth == -1) {
                 if (mSettings.getLayoutAlgorithm() ==
                         WebSettings.LayoutAlgorithm.NORMAL) {
@@ -1433,19 +1430,14 @@
             } else {
                 width = Math.max(w, mViewportWidth);
             }
-            // while in zoom overview mode, the text are wrapped to the screen
-            // width matching mWebView.mLastScale. So that we don't trigger
-            // re-flow while toggling between overview mode and normal mode.
-            nativeSetSize(width, Math.round((float) width * h / w),
-                    Math.round(mWebView.mInZoomOverview ? w * scale
-                            / mWebView.mLastScale : w), scale, w, h);
-        } else {
-            nativeSetSize(w, h, w, scale, w, h);
         }
+        nativeSetSize(width, width == w ? h : Math.round((float) width * h / w),
+                textwrapWidth, scale, w, h);
         // Remember the current width and height
         boolean needInvalidate = (mCurrentViewWidth == 0);
         mCurrentViewWidth = w;
         mCurrentViewHeight = h;
+        mCurrentViewScale = scale;
         if (needInvalidate) {
             // ensure {@link #webkitDraw} is called as we were blocking in
             // {@link #contentDraw} when mCurrentViewWidth is 0
@@ -1490,15 +1482,30 @@
     // Used to end scale+scroll mode, accessed by both threads
     boolean mEndScaleZoom = false;
 
-    public class DrawData {
-        public DrawData() {
+    // mRestoreState is set in didFirstLayout(), and reset in the next
+    // webkitDraw after passing it to the UI thread.
+    private RestoreState mRestoreState = null;
+
+    static class RestoreState {
+        float mMinScale;
+        float mMaxScale;
+        float mViewScale;
+        float mTextWrapScale;
+        int mScrollX;
+        int mScrollY;
+    }
+
+    static class DrawData {
+        DrawData() {
             mInvalRegion = new Region();
             mWidthHeight = new Point();
         }
-        public Region mInvalRegion;
-        public Point mViewPoint;
-        public Point mWidthHeight;
-        public int mMinPrefWidth;
+        Region mInvalRegion;
+        Point mViewPoint;
+        Point mWidthHeight;
+        int mMinPrefWidth;
+        RestoreState mRestoreState; // only non-null if it is for the first
+                                    // picture set after the first layout
     }
 
     private void webkitDraw() {
@@ -1517,6 +1524,10 @@
             if (WebView.ENABLE_DOUBLETAP_ZOOM && mSettings.getUseWideViewPort()) {
                 draw.mMinPrefWidth = nativeGetContentMinPrefWidth();
             }
+            if (mRestoreState != null) {
+                draw.mRestoreState = mRestoreState;
+                mRestoreState = null;
+            }
             if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
             Message.obtain(mWebView.mPrivateHandler,
                     WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
@@ -1527,9 +1538,6 @@
                         mWebkitScrollY).sendToTarget();
                 mWebkitScrollX = mWebkitScrollY = 0;
             }
-            // nativeSnapToAnchor() needs to be called after NEW_PICTURE_MSG_ID
-            // is sent, so that scroll will be based on the new content size.
-            nativeSnapToAnchor();
         }
     }
 
@@ -1751,17 +1759,8 @@
 
     // called by JNI
     private void didFirstLayout(boolean standardLoad) {
-        // Trick to ensure that the Picture has the exact height for the content
-        // by forcing to layout with 0 height after the page is ready, which is
-        // indicated by didFirstLayout. This is essential to get rid of the
-        // white space in the GMail which uses WebView for message view.
-        if (mWebView != null && mWebView.mHeightCanMeasure) {
-            mWebView.mLastHeightSent = 0;
-            // Send a negative scale to indicate that WebCore should reuse the
-            // current scale
-            mEventHub.sendMessage(Message.obtain(null,
-                    EventHub.VIEW_SIZE_CHANGED, mWebView.mLastWidthSent,
-                    mWebView.mLastHeightSent, -1.0f));
+        if (DebugFlags.WEB_VIEW_CORE) {
+            Log.v(LOGTAG, "didFirstLayout standardLoad =" + standardLoad);
         }
 
         mBrowserFrame.didFirstLayout();
@@ -1769,6 +1768,9 @@
         // reset the scroll position as it is a new page now
         mWebkitScrollX = mWebkitScrollY = 0;
 
+        // for non-standard load, we only adjust scale if mRestoredScale > 0
+        if (mWebView == null || (mRestoredScale == 0 && !standardLoad)) return;
+
         // set the viewport settings from WebKit
         setViewportSettingsFromNative();
 
@@ -1820,47 +1822,74 @@
         }
 
         // now notify webview
-        if (mWebView != null) {
-            WebView.ScaleLimitData scaleLimit = new WebView.ScaleLimitData();
-            scaleLimit.mMinScale = mViewportMinimumScale;
-            scaleLimit.mMaxScale = mViewportMaximumScale;
-
-            if (mRestoredScale > 0) {
-                Message.obtain(mWebView.mPrivateHandler,
-                        WebView.DID_FIRST_LAYOUT_MSG_ID,
-                        mRestoredScreenWidthScale > 0 ?
-                        -mRestoredScreenWidthScale : mRestoredScale, 0,
-                        scaleLimit).sendToTarget();
+        int webViewWidth = Math.round(mCurrentViewWidth * mCurrentViewScale);
+        mRestoreState = new RestoreState();
+        mRestoreState.mMinScale = mViewportMinimumScale / 100.0f;
+        mRestoreState.mMaxScale = mViewportMaximumScale / 100.0f;
+        mRestoreState.mScrollX = mRestoredX;
+        mRestoreState.mScrollY = mRestoredY;
+        if (mRestoredScale > 0) {
+            if (mRestoredScreenWidthScale > 0) {
+                mRestoreState.mTextWrapScale =
+                        mRestoredScreenWidthScale / 100.0f;
+                // 0 will trigger WebView to turn on zoom overview mode
+                mRestoreState.mViewScale = 0;
             } else {
-                // if standardLoad is true, use mViewportInitialScale, otherwise
-                // pass -1 to the WebView to indicate no change of the scale.
-                Message.obtain(mWebView.mPrivateHandler,
-                        WebView.DID_FIRST_LAYOUT_MSG_ID,
-                        standardLoad ? mViewportInitialScale : -1,
-                        mViewportWidth, scaleLimit).sendToTarget();
+                mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
+                        mRestoredScale / 100.0f;
             }
-
-            // force an early draw for quick feedback after the first layout
-            if (mCurrentViewWidth != 0) {
-                synchronized (this) {
-                    if (mDrawIsScheduled) {
-                        mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
-                    }
-                    mDrawIsScheduled = true;
-                    // if no restored offset, move the new page to (0, 0)
-                    mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
-                            EventHub.MESSAGE_RELAY, Message.obtain(
-                                    mWebView.mPrivateHandler,
-                                    WebView.SCROLL_TO_MSG_ID, mRestoredX,
-                                    mRestoredY)));
-                    mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
-                            EventHub.WEBKIT_DRAW));
-                }
+        } else {
+            if (mViewportInitialScale > 0) {
+                mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
+                        mViewportInitialScale / 100.0f;
+            } else if (mViewportWidth > 0 && mViewportWidth < webViewWidth) {
+                mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
+                        (float) webViewWidth / mViewportWidth;
+            } else {
+                mRestoreState.mTextWrapScale =
+                        WebView.DEFAULT_SCALE_PERCENT / 100.0f;
+                // 0 will trigger WebView to turn on zoom overview mode
+                mRestoreState.mViewScale = 0;
             }
-
-            // reset restored offset, scale
-            mRestoredX = mRestoredY = mRestoredScale = mRestoredScreenWidthScale = 0;
         }
+
+        if (mWebView.mHeightCanMeasure) {
+            // Trick to ensure that the Picture has the exact height for the
+            // content by forcing to layout with 0 height after the page is
+            // ready, which is indicated by didFirstLayout. This is essential to
+            // get rid of the white space in the GMail which uses WebView for
+            // message view.
+            mWebView.mLastHeightSent = 0;
+            // Send a negative scale to indicate that WebCore should reuse
+            // the current scale
+            WebView.ViewSizeData data = new WebView.ViewSizeData();
+            data.mWidth = mWebView.mLastWidthSent;
+            data.mHeight = 0;
+            // if mHeightCanMeasure is true, getUseWideViewPort() can't be
+            // true. It is safe to use mWidth for mTextWrapWidth.
+            data.mTextWrapWidth = data.mWidth;
+            data.mScale = -1.0f;
+            mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
+                    EventHub.VIEW_SIZE_CHANGED, data));
+        } else if (mSettings.getUseWideViewPort() && mCurrentViewWidth > 0) {
+            WebView.ViewSizeData data = new WebView.ViewSizeData();
+            // mViewScale as 0 means it is in zoom overview mode. So we don't
+            // know the exact scale. If mRestoredScale is non-zero, use it;
+            // otherwise just use mTextWrapScale as the initial scale.
+            data.mScale = mRestoreState.mViewScale == 0
+                    ? (mRestoredScale > 0 ? mRestoredScale
+                            : mRestoreState.mTextWrapScale)
+                    : mRestoreState.mViewScale;
+            data.mWidth = Math.round(webViewWidth / data.mScale);
+            data.mHeight = mCurrentViewHeight * data.mWidth
+                    / mCurrentViewWidth;
+            data.mTextWrapWidth = Math.round(webViewWidth
+                    / mRestoreState.mTextWrapScale);
+            mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
+                    EventHub.VIEW_SIZE_CHANGED, data));
+        }
+        // reset restored offset, scale
+        mRestoredX = mRestoredY = mRestoredScale = mRestoredScreenWidthScale = 0;
     }
 
     // called by JNI
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index c16a75e..dc72008 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -464,13 +464,22 @@
                                           SkCanvas* canvas, SkBitmap* bitmap,
                                           jfloat left, jfloat top,
                                           SkPaint* paint, jint canvasDensity,
-                                          jint bitmapDensity) {
+                                          jint screenDensity, jint bitmapDensity) {
         SkScalar left_ = SkFloatToScalar(left);
         SkScalar top_ = SkFloatToScalar(top);
 
         if (canvasDensity == bitmapDensity || canvasDensity == 0
                 || bitmapDensity == 0) {
-            canvas->drawBitmap(*bitmap, left_, top_, paint);
+            if (screenDensity != 0 && screenDensity != bitmapDensity) {
+                SkPaint filteredPaint;
+                if (paint) {
+                    filteredPaint = *paint;
+                }
+                filteredPaint.setFilterBitmap(true);
+                canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
+            } else {
+                canvas->drawBitmap(*bitmap, left_, top_, paint);
+            }
         } else {
             canvas->save();
             SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
@@ -490,30 +499,45 @@
     }
 
     static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
-                        jobject srcIRect, const SkRect& dst, SkPaint* paint) {
+                        jobject srcIRect, const SkRect& dst, SkPaint* paint,
+                        jint screenDensity, jint bitmapDensity) {
         SkIRect    src, *srcPtr = NULL;
 
         if (NULL != srcIRect) {
             GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
             srcPtr = &src;
         }
-        canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
+        
+        if (screenDensity != 0 && screenDensity != bitmapDensity) {
+            SkPaint filteredPaint;
+            if (paint) {
+                filteredPaint = *paint;
+            }
+            filteredPaint.setFilterBitmap(true);
+            canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
+        } else {
+            canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
+        }
     }
 
     static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas,
                              SkBitmap* bitmap, jobject srcIRect,
-                             jobject dstRectF, SkPaint* paint) {
+                             jobject dstRectF, SkPaint* paint,
+                             jint screenDensity, jint bitmapDensity) {
         SkRect      dst;
         GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
-        doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint);
+        doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
+                screenDensity, bitmapDensity);
     }
     
     static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas,
                              SkBitmap* bitmap, jobject srcIRect,
-                             jobject dstRect, SkPaint* paint) {
+                             jobject dstRect, SkPaint* paint,
+                             jint screenDensity, jint bitmapDensity) {
         SkRect      dst;
         GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
-        doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint);
+        doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
+                screenDensity, bitmapDensity);
     }
     
     static void drawBitmapArray(JNIEnv* env, jobject, SkCanvas* canvas,
@@ -907,11 +931,11 @@
     {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
         (void*) SkCanvasGlue::drawRoundRect},
     {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
-    {"native_drawBitmap","(IIFFIII)V",
+    {"native_drawBitmap","(IIFFIIII)V",
         (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
-    {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;I)V",
+    {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;III)V",
         (void*) SkCanvasGlue::drawBitmapRF},
-    {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;I)V",
+    {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;III)V",
         (void*) SkCanvasGlue::drawBitmapRR},
     {"native_drawBitmap", "(I[IIIFFIIZI)V",
     (void*)SkCanvasGlue::drawBitmapArray},
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index e6048cd..0f8dff1 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -4,15 +4,23 @@
 
 #include <jni.h>
 
+static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
+    if (NULL == ptr) {
+        doThrowIAE(env);
+    }
+}
+
 class SkMaskFilterGlue {
 public:
     static void destructor(JNIEnv* env, jobject, SkMaskFilter* filter) {
-        SkASSERT(filter);
-        filter->unref();
+        filter->safeUnref();
     }
 
     static SkMaskFilter* createBlur(JNIEnv* env, jobject, float radius, int blurStyle) {
-        return SkBlurMaskFilter::Create(SkFloatToScalar(radius), (SkBlurMaskFilter::BlurStyle)blurStyle);
+        SkMaskFilter* filter = SkBlurMaskFilter::Create(SkFloatToScalar(radius),
+                                        (SkBlurMaskFilter::BlurStyle)blurStyle);
+        ThrowIAE_IfNull(env, filter);
+        return filter;
     }
  
     static SkMaskFilter* createEmboss(JNIEnv* env, jobject, jfloatArray dirArray, float ambient, float specular, float radius) {
@@ -24,8 +32,12 @@
             direction[i] = SkFloatToScalar(values[i]);
         }
 
-        return SkBlurMaskFilter::CreateEmboss(direction, SkFloatToScalar(ambient),
-                                              SkFloatToScalar(specular), SkFloatToScalar(radius));
+        SkMaskFilter* filter =  SkBlurMaskFilter::CreateEmboss(direction,
+                                                      SkFloatToScalar(ambient),
+                                                      SkFloatToScalar(specular),
+                                                      SkFloatToScalar(radius));
+        ThrowIAE_IfNull(env, filter);
+        return filter;
     }
 };
 
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b28eb90..b09c62b 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -43,25 +43,23 @@
 
 static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader)
 {
-    SkASSERT(shader != NULL);
-    shader->unref();
+    shader->safeUnref();
 }
 
 static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix)
 {
-    SkASSERT(shader != NULL);    
-    return shader->getLocalMatrix(matrix);
+    return shader ? shader->getLocalMatrix(matrix) : false;
 }
  
 static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix)
 {
-    SkASSERT(shader != NULL);
-    
-    if (NULL == matrix) {
-        shader->resetLocalMatrix();
-    }
-    else {
-        shader->setLocalMatrix(*matrix);
+    if (shader) {
+        if (NULL == matrix) {
+            shader->resetLocalMatrix();
+        }
+        else {
+            shader->setLocalMatrix(*matrix);
+        }
     }
 }
 
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 59f4067..66b2506 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -74,12 +74,13 @@
 }
 
 enum {
-    STYLE_NUM_ENTRIES = 5,
+    STYLE_NUM_ENTRIES = 6,
     STYLE_TYPE = 0,
     STYLE_DATA = 1,
     STYLE_ASSET_COOKIE = 2,
     STYLE_RESOURCE_ID = 3,
-    STYLE_CHANGING_CONFIGURATIONS = 4
+    STYLE_CHANGING_CONFIGURATIONS = 4,
+    STYLE_DENSITY = 5
 };
 
 static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
@@ -896,6 +897,7 @@
     ResTable::Theme* theme = (ResTable::Theme*)themeToken;
     const ResTable& res = theme->getResTable();
     ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
+    ResTable_config config;
     Res_value value;
 
     const jsize NI = env->GetArrayLength(attrs);
@@ -995,6 +997,7 @@
         value.dataType = Res_value::TYPE_NULL;
         value.data = 0;
         typeSetFlags = 0;
+        config.density = 0;
 
         // Skip through XML attributes until the end or the next possible match.
         while (ix < NX && curIdent > curXmlAttr) {
@@ -1042,7 +1045,8 @@
         if (value.dataType != Res_value::TYPE_NULL) {
             // Take care of resolving the found resource to its final value.
             //printf("Resolving attribute reference\n");
-            ssize_t newBlock = theme->resolveAttributeReference(&value, block, &resid, &typeSetFlags);
+            ssize_t newBlock = theme->resolveAttributeReference(&value, block,
+                    &resid, &typeSetFlags, &config);
             if (newBlock >= 0) block = newBlock;
         } else {
             // If we still don't have a value for this attribute, try to find
@@ -1051,7 +1055,8 @@
             ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
             if (newBlock >= 0) {
                 //printf("Resolving resource reference\n");
-                newBlock = res.resolveReference(&value, block, &resid, &typeSetFlags);
+                newBlock = res.resolveReference(&value, block, &resid,
+                        &typeSetFlags, &config);
                 if (newBlock >= 0) block = newBlock;
             }
         }
@@ -1070,6 +1075,7 @@
             block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+        dest[STYLE_DENSITY] = config.density;
         
         if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
             indicesIdx++;
@@ -1108,6 +1114,7 @@
     }
     const ResTable& res(am->getResources());
     ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
+    ResTable_config config;
     Res_value value;
     
     const jsize NI = env->GetArrayLength(attrs);
@@ -1160,6 +1167,7 @@
         value.dataType = Res_value::TYPE_NULL;
         value.data = 0;
         typeSetFlags = 0;
+        config.density = 0;
         
         // Skip through XML attributes until the end or the next possible match.
         while (ix < NX && curIdent > curXmlAttr) {
@@ -1179,7 +1187,8 @@
         if (value.dataType != Res_value::TYPE_NULL) {
             // Take care of resolving the found resource to its final value.
             //printf("Resolving attribute reference\n");
-            ssize_t newBlock = res.resolveReference(&value, block, &resid, &typeSetFlags);
+            ssize_t newBlock = res.resolveReference(&value, block, &resid,
+                    &typeSetFlags, &config);
             if (newBlock >= 0) block = newBlock;
         }
         
@@ -1197,6 +1206,7 @@
             block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+        dest[STYLE_DENSITY] = config.density;
         
         if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
             indicesIdx++;
@@ -1250,6 +1260,7 @@
         return JNI_FALSE;
     }
     const ResTable& res(am->getResources());
+    ResTable_config config;
     Res_value value;
     ssize_t block;
     
@@ -1276,13 +1287,15 @@
     while (i < NV && arrayEnt < endArrayEnt) {
         block = arrayEnt->stringBlock;
         typeSetFlags = arrayTypeSetFlags;
+        config.density = 0;
         value = arrayEnt->map.value;
                 
         uint32_t resid = 0;
         if (value.dataType != Res_value::TYPE_NULL) {
             // Take care of resolving the found resource to its final value.
             //printf("Resolving attribute reference\n");
-            ssize_t newBlock = res.resolveReference(&value, block, &resid, &typeSetFlags);
+            ssize_t newBlock = res.resolveReference(&value, block, &resid,
+                    &typeSetFlags, &config);
             if (newBlock >= 0) block = newBlock;
         }
 
@@ -1299,6 +1312,7 @@
         dest[STYLE_ASSET_COOKIE] = (jint)res.getTableCookie(block);
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+        dest[STYLE_DENSITY] = config.density;
         dest += STYLE_NUM_ENTRIES;
         i+= STYLE_NUM_ENTRIES;
         arrayEnt++;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5f94ee5..69ef96c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1132,8 +1132,7 @@
 
         <activity android:name="com.android.server.ShutdownActivity"
             android:permission="android.permission.SHUTDOWN"
-            android:excludeFromRecents="true"
-            android:multiprocess="true">
+            android:excludeFromRecents="true">
             <intent-filter>
                 <action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 549b668..558d91e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -916,12 +916,12 @@
         you.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_readPhoneState">read phone state</string>
+    <string name="permlab_readPhoneState">read phone state and identity</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_readPhoneState">Allows the application to access the phone
         features of the device.  An application with this permission can determine the phone
-        number of this phone, whether a call is active, the number that call is connected to
-        and the like.</string>
+        number and serial number of this phone, whether a call is active, the number that call
+        is connected to and the like.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_wakeLock">prevent phone from sleeping</string>
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index bc2e42e..345f810 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -50,6 +50,9 @@
 
     // Package-scoped for quick access.
     /*package*/ int mDensity = Bitmap.DENSITY_NONE;
+
+    // Used to determine when compatibility scaling is in effect.
+    private int mScreenDensity = Bitmap.DENSITY_NONE;
     
     // Used by native code
     @SuppressWarnings({"UnusedDeclaration"})
@@ -219,6 +222,11 @@
         mDensity = density;
     }
 
+    /** @hide */
+    public void setScreenDensity(int density) {
+        mScreenDensity = density;
+    }
+    
     // the SAVE_FLAG constants must match their native equivalents
 
     /** restore the current matrix when restore() is called */
@@ -971,7 +979,8 @@
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
         throwIfRecycled(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), left, top,
-                paint != null ? paint.mNativePaint : 0, mDensity, bitmap.mDensity);
+                paint != null ? paint.mNativePaint : 0, mDensity, mScreenDensity,
+                bitmap.mDensity);
     }
 
     /**
@@ -1002,7 +1011,8 @@
         }
         throwIfRecycled(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
-                          paint != null ? paint.mNativePaint : 0);
+                          paint != null ? paint.mNativePaint : 0,
+                          mScreenDensity, bitmap.mDensity);
     }
 
     /**
@@ -1033,7 +1043,8 @@
         }
         throwIfRecycled(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
-                          paint != null ? paint.mNativePaint : 0);
+                          paint != null ? paint.mNativePaint : 0,
+                          mScreenDensity, bitmap.mDensity);
     }
     
     /**
@@ -1513,13 +1524,19 @@
     private native void native_drawBitmap(int nativeCanvas, int bitmap,
                                                  float left, float top,
                                                  int nativePaintOrZero,
-                                                 int canvasDensity, int bitmapDensity);
+                                                 int canvasDensity,
+                                                 int screenDensity,
+                                                 int bitmapDensity);
     private native void native_drawBitmap(int nativeCanvas, int bitmap,
                                                  Rect src, RectF dst,
-                                                 int nativePaintOrZero);
+                                                 int nativePaintOrZero,
+                                                 int screenDensity,
+                                                 int bitmapDensity);
     private static native void native_drawBitmap(int nativeCanvas, int bitmap,
                                                  Rect src, Rect dst,
-                                                 int nativePaintOrZero);
+                                                 int nativePaintOrZero,
+                                                 int screenDensity,
+                                                 int bitmapDensity);
     private static native void native_drawBitmap(int nativeCanvas, int[] colors,
                                                 int offset, int stride, float x,
                                                  float y, int width, int height,
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 2b9e448..1770a7a 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -23,6 +23,12 @@
 import java.io.InputStream;
 import java.io.IOException;
 
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.Color;
+
 import android.os.Bundle;
 import android.content.res.Resources;
 import android.util.Log;
@@ -32,8 +38,6 @@
 import android.view.Window;
 import android.view.View;
 import android.view.Surface;
-import android.graphics.Bitmap;
-import android.graphics.Color;
 
 /**
  * @hide
@@ -53,6 +57,8 @@
     private static boolean sInitialized;
     native private static void _nInit();
 
+    private static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
+
     static {
         sInitialized = false;
         try {
@@ -62,6 +68,7 @@
         } catch (UnsatisfiedLinkError e) {
             Log.d(LOG_TAG, "RenderScript JNI library not found!");
         }
+        mBitmapOptions.inScaled = false;
     }
 
     native private int  nDeviceCreate();
@@ -539,6 +546,17 @@
         return new Allocation(id);
     }
 
+    public Allocation allocationCreateFromBitmapResource(Resources res, int id, ElementPredefined internalElement, boolean genMips) {
+        Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
+        return allocationCreateFromBitmap(b, internalElement, genMips);
+    }
+
+    public Allocation allocationCreateFromBitmapResourceBoxed(Resources res, int id, ElementPredefined internalElement, boolean genMips) {
+        Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
+        return allocationCreateFromBitmapBoxed(b, internalElement, genMips);
+    }
+
+
     //////////////////////////////////////////////////////////////////////////////////
     // Adapter1D
 
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index ad27903..13316a9 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -93,10 +93,6 @@
     VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
 };
 
-
-// Maximum frames per second is 24
-#define MEDIA_RECORDER_MAX_FRAME_RATE         24
-
 /*
  * The state machine of the media_recorder uses a set of different state names.
  * The mapping between the media_recorder and the pvauthorengine is shown below:
diff --git a/include/ui/Overlay.h b/include/ui/Overlay.h
index acc9bea..a9ae1c4 100644
--- a/include/ui/Overlay.h
+++ b/include/ui/Overlay.h
@@ -82,10 +82,16 @@
     /* release the overlay buffer and post it */
     status_t queueBuffer(overlay_buffer_t buffer);
 
+    /* change the width and height of the overlay */
+    status_t resizeInput(uint32_t width, uint32_t height);
+
     status_t setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;
 
     status_t getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;
 
+    /* set the buffer attributes */
+    status_t setParameter(int param, int value);
+
     /* returns the address of a given buffer if supported, NULL otherwise. */
     void* getBufferAddress(overlay_buffer_t buffer);
 
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index edd0cae6..e524e2a 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -1655,7 +1655,8 @@
     ssize_t resolveReference(Res_value* inOutValue,
                              ssize_t blockIndex,
                              uint32_t* outLastRef = NULL,
-                             uint32_t* inoutTypeSpecFlags = NULL) const;
+                             uint32_t* inoutTypeSpecFlags = NULL,
+                             ResTable_config* outConfig = NULL) const;
 
     enum {
         TMP_BUFFER_SIZE = 16
@@ -1729,7 +1730,8 @@
          */
         ssize_t resolveAttributeReference(Res_value* inOutValue,
                 ssize_t blockIndex, uint32_t* outLastRef = NULL,
-                uint32_t* inoutTypeSpecFlags = NULL) const;
+                uint32_t* inoutTypeSpecFlags = NULL,
+                ResTable_config* inoutConfig = NULL) const;
 
         void dumpToLog() const;
         
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java
index a639c55..12a14e3 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmRS.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -163,7 +163,6 @@
         mPVImages.setName("PVImages");
     }
 
-
     private void loadImages() {
         mBufferIDs = new int[13];
         mImages = new RenderScript.Allocation[13];
@@ -171,51 +170,22 @@
             RenderScript.ElementPredefined.USER_FLOAT,
             mBufferIDs.length);
 
-        Bitmap b;
-        BitmapFactory.Options opts = new BitmapFactory.Options();
-        opts.inScaled = false;
-
         RenderScript.ElementPredefined ie = 
             RenderScript.ElementPredefined.RGB_565;
 
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p01, opts);
-        mImages[0] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p02, opts);
-        mImages[1] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p03, opts);
-        mImages[2] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p04, opts);
-        mImages[3] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p05, opts);
-        mImages[4] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p06, opts);
-        mImages[5] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p07, opts);
-        mImages[6] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p08, opts);
-        mImages[7] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p09, opts);
-        mImages[8] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p10, opts);
-        mImages[9] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p11, opts);
-        mImages[10] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p12, opts);
-        mImages[11] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
-
-        b = BitmapFactory.decodeResource(mRes, R.drawable.p13, opts);
-        mImages[12] = mRS.allocationCreateFromBitmapBoxed(b, ie, true);
+        mImages[0] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p01, ie, true);
+        mImages[1] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p02, ie, true);
+        mImages[2] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p03, ie, true);
+        mImages[3] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p04, ie, true);
+        mImages[4] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p05, ie, true);
+        mImages[5] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p06, ie, true);
+        mImages[6] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p07, ie, true);
+        mImages[7] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p08, ie, true);
+        mImages[8] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p09, ie, true);
+        mImages[9] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p10, ie, true);
+        mImages[10] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p11, ie, true);
+        mImages[11] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p12, ie, true);
+        mImages[12] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p13, ie, true);
 
         for(int ct=0; ct < mImages.length; ct++) {
             mImages[ct].uploadToTexture(1);
diff --git a/libs/rs/java/Rollo/res/raw/maps.png b/libs/rs/java/Rollo/res/raw/maps.png
new file mode 100644
index 0000000..fd5fc39
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/maps.png
Binary files differ
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java b/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
index c080176..039d4e9 100644
--- a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
+++ b/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
@@ -18,7 +18,6 @@
 
 import java.io.Writer;
 
-import android.renderscript.RSSurfaceView;
 import android.renderscript.RenderScript;
 import android.renderscript.ProgramVertexAlloc;
 
@@ -33,13 +32,7 @@
 import android.graphics.Typeface;
 import android.os.Handler;
 import android.os.Message;
-import android.util.AttributeSet;
 import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
 
 public class RolloRS {
     //public static final int STATE_SELECTED_ID = 0;
@@ -101,7 +94,6 @@
     private RenderScript.Sampler mSamplerText;
     private RenderScript.ProgramFragmentStore mPFSBackground;
     private RenderScript.ProgramFragmentStore mPFSText;
-    private RenderScript.ProgramFragment mPFBackground;
     private RenderScript.ProgramFragment mPFImages;
     private RenderScript.ProgramFragment mPFText;
     private RenderScript.ProgramVertex mPV;
@@ -110,8 +102,6 @@
     private ProgramVertexAlloc mPVOrthoAlloc;
     private RenderScript.Allocation[] mIcons;
     private RenderScript.Allocation[] mLabels;
-    private RenderScript.Allocation mIconPlate;
-    private RenderScript.Allocation mBackground;
 
     private int[] mAllocStateBuf;
     private RenderScript.Allocation mAllocState;
@@ -219,155 +209,85 @@
             mAllocLabelID = mRS.allocationCreatePredefSized(
                 RenderScript.ElementPredefined.USER_I32, mLabels.length);
 
+            RenderScript.ElementPredefined ie565 =
+                RenderScript.ElementPredefined.RGB_565;
+            RenderScript.ElementPredefined ie8888 =
+                RenderScript.ElementPredefined.RGBA_8888;
 
-            Bitmap b;
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScaled = false;
+            mIcons[0] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.browser, ie8888, true);
+            mIcons[1] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.market, ie8888, true);
+            mIcons[2] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.photos, ie8888, true);
+            mIcons[3] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.settings, ie8888, true);
+            mIcons[4] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.calendar, ie8888, true);
+            mIcons[5] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.g1155, ie8888, true);
+            mIcons[6] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.g2140, ie8888, true);
+            mIcons[7] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.maps, ie8888, true);
+            mIcons[8] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path431, ie8888, true);
+            mIcons[9] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path676, ie8888, true);
+            mIcons[10] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path754, ie8888, true);
+            mIcons[11] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path815, ie8888, true);
+            mIcons[12] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path1920, ie8888, true);
+            mIcons[13] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path1927, ie8888, true);
+            mIcons[14] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path3099, ie8888, true);
+            mIcons[15] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path3950, ie8888, true);
+            mIcons[16] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path4481, ie8888, true);
+            mIcons[17] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path5168, ie8888, true);
+            mIcons[18] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.polygon2408, ie8888, true);
 
-            b = BitmapFactory.decodeResource(mRes, R.raw.cf_background, opts);
-            mBackground = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mBackground.setName("TexBk");
-
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.browser, opts);
-            mIcons[0] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
             mLabels[0] = makeTextBitmap("browser");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.market, opts);
-            mIcons[1] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
             mLabels[1] = makeTextBitmap("market");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.photos, opts);
-            mIcons[2] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
             mLabels[2] = makeTextBitmap("photos");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.settings, opts);
-            mIcons[3] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
             mLabels[3] = makeTextBitmap("settings");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.calendar, opts);
-            mIcons[4] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[4] = makeTextBitmap("creed");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.g1155, opts);
-            mIcons[5] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[5] = makeTextBitmap("BOA");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.g2140, opts);
-            mIcons[6] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[6] = makeTextBitmap("chess");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.maps, opts);
-            mIcons[7] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[7] = makeTextBitmap("Dictionary");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path431, opts);
-            mIcons[8] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[8] = makeTextBitmap("facebook");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path676, opts);
-            mIcons[9] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[9] = makeTextBitmap("Flash Light");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path754, opts);
-            mIcons[10] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[10] = makeTextBitmap("Flight Control");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path815, opts);
-            mIcons[11] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[11] = makeTextBitmap("google earth");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path1920, opts);
-            mIcons[12] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[12] = makeTextBitmap("Harry Potter");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path1927, opts);
-            mIcons[13] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[13] = makeTextBitmap("Movies");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path3099, opts);
-            mIcons[14] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[14] = makeTextBitmap("NY Times");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path3950, opts);
-            mIcons[15] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[15] = makeTextBitmap("Pandora");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path4481, opts);
-            mIcons[16] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[16] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.path5168, opts);
-            mIcons[17] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[17] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.polygon2408, opts);
-            mIcons[18] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
-            mLabels[18] = makeTextBitmap("Public Radio");
-
-            /*
-            b = BitmapFactory.decodeResource(mRes, R.raw.solitaire, opts);
-            mIcons[19] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[19] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.sudoku, opts);
-            mIcons[20] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[20] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.taptaprevenge, opts);
-            mIcons[21] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[21] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.tetris, opts);
-            mIcons[22] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[22] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.tictactoe, opts);
-            mIcons[23] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[23] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.tweetie, opts);
-            mIcons[24] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[24] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.urbanspoon, opts);
-            mIcons[25] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[25] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.waterslide_extreme, opts);
-            mIcons[26] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[26] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.weather_channel, opts);
-            mIcons[27] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[27] = makeTextBitmap("Public Radio");
-
-            b = BitmapFactory.decodeResource(mRes, R.raw.zippo, opts);
-            mIcons[28] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-            mLabels[28] = makeTextBitmap("Public Radio");
-*/
+            mLabels[4] = makeTextBitmap("calendar");
+            mLabels[5] = makeTextBitmap("g1155");
+            mLabels[6] = makeTextBitmap("g2140");
+            mLabels[7] = makeTextBitmap("maps");
+            mLabels[8] = makeTextBitmap("path431");
+            mLabels[9] = makeTextBitmap("path676");
+            mLabels[10] = makeTextBitmap("path754");
+            mLabels[11] = makeTextBitmap("path815");
+            mLabels[12] = makeTextBitmap("path1920");
+            mLabels[13] = makeTextBitmap("path1927");
+            mLabels[14] = makeTextBitmap("path3099");
+            mLabels[15] = makeTextBitmap("path3950");
+            mLabels[16] = makeTextBitmap("path4481");
+            mLabels[17] = makeTextBitmap("path5168");
+            mLabels[18] = makeTextBitmap("polygon2408");
 
             mIcons[19] = mIcons[0];
             mIcons[20] = mIcons[1];
             mIcons[21] = mIcons[2];
             mIcons[22] = mIcons[3];
-            mIcons[23] = mIcons[2];
-            mIcons[24] = mIcons[1];
-            mIcons[25] = mIcons[0];
-            mIcons[26] = mIcons[1];
-            mIcons[27] = mIcons[2];
-            mIcons[28] = mIcons[3];
+            mIcons[23] = mIcons[4];
+            mIcons[24] = mIcons[5];
+            mIcons[25] = mIcons[6];
+            mIcons[26] = mIcons[7];
+            mIcons[27] = mIcons[8];
+            mIcons[28] = mIcons[9];
 
             mLabels[19] = mLabels[0];
             mLabels[20] = mLabels[1];
             mLabels[21] = mLabels[2];
             mLabels[22] = mLabels[3];
-            mLabels[23] = mLabels[2];
-            mLabels[24] = mLabels[1];
-            mLabels[25] = mLabels[0];
-            mLabels[26] = mLabels[1];
-            mLabels[27] = mLabels[2];
-            mLabels[28] = mLabels[3];
+            mLabels[23] = mLabels[4];
+            mLabels[24] = mLabels[5];
+            mLabels[25] = mLabels[6];
+            mLabels[26] = mLabels[7];
+            mLabels[27] = mLabels[8];
+            mLabels[28] = mLabels[9];
+
+/*
+            mIcons[19] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.solitaire, ie8888, true);
+            mIcons[20] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.sudoku, ie8888, true);
+            mIcons[21] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.taptaprevenge, ie8888, true);
+            mIcons[22] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.tetris, ie8888, true);
+            mIcons[23] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.tictactoe, ie8888, true);
+            mIcons[24] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.tweetie, ie8888, true);
+            mIcons[25] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.urbanspoon, ie8888, true);
+            mIcons[26] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.waterslide_extreme, ie8888, true);
+            mIcons[27] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.weather_channel, ie8888, true);
+            mIcons[28] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.zippo, ie8888, true);
+*/
 
 
             for(int ct=0; ct < mIcons.length; ct++) {
@@ -378,33 +298,6 @@
             }
             mAllocIconID.data(mAllocIconIDBuf);
             mAllocLabelID.data(mAllocLabelIDBuf);
-
-            RenderScript.Element e = mRS.elementGetPredefined(RenderScript.ElementPredefined.RGB_565);
-            mRS.typeBegin(e);
-            mRS.typeAdd(RenderScript.Dimension.X, 64);
-            mRS.typeAdd(RenderScript.Dimension.Y, 64);
-            RenderScript.Type t = mRS.typeCreate();
-            mIconPlate = mRS.allocationCreateTyped(t);
-            //t.destroy();
-            //e.destroy();
-
-            int tmp[] = new int[64 * 32];
-            for(int ct = 0; ct < (64*32); ct++) {
-                tmp[ct] = 7 | (13 << 5) | (7 << 11);
-                tmp[ct] = tmp[ct] | (tmp[ct] << 16);
-            }
-            for(int ct = 0; ct < 32; ct++) {
-                tmp[ct] = 0;
-                tmp[ct + (63*32)] = 0;
-            }
-            for(int ct = 0; ct < 64; ct++) {
-                tmp[ct * 32] = 0;
-                tmp[ct * 32 + 31] = 0;
-            }
-            mIconPlate.data(tmp);
-            mIconPlate.uploadToTexture(0);
-            mIconPlate.setName("Plate");
-            mPFImages.bindTexture(mIconPlate, 0);
         }
 
     }
@@ -427,7 +320,6 @@
         mRS.scriptCSetScript(mRes, R.raw.rollo);
         //mRS.scriptCSetScript(mRes, R.raw.rollo2);
         mRS.scriptCSetRoot(true);
-        //mRS.scriptCSetClearDepth(0);
         mScript = mRS.scriptCCreate();
 
         mAllocStateBuf = new int[] {0, 0, 0, 8, 0, 0, -1, 0, mAllocIconIDBuf.length, 0, 0};
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index a841ab3..fbce73d 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -461,7 +461,8 @@
                 glRotatef(-90, 0, 0, 1);
             }
 
-            if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
+            if (!(mFlags & (DisplayHardware::NPOT_EXTENSION |
+                            DisplayHardware::DIRECT_TEXTURE))) {
                 // find the smallest power-of-two that will accommodate our surface
                 GLuint tw = 1 << (31 - clz(width));
                 GLuint th = 1 << (31 - clz(height));
diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp
index 92a9a86..4add8f9 100644
--- a/libs/ui/BufferMapper.cpp
+++ b/libs/ui/BufferMapper.cpp
@@ -65,7 +65,7 @@
 {
     status_t err = mAllocMod->lock(mAllocMod, handle, usage,
             bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr);
-    LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+    LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
     return err;
 }
 
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index 4854d6a..3aa8950 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -59,6 +59,18 @@
     return mOverlayData->queueBuffer(mOverlayData, buffer);
 }
 
+status_t Overlay::resizeInput(uint32_t width, uint32_t height)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->resizeInput(mOverlayData, width, height);
+}
+
+status_t Overlay::setParameter(int param, int value)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->setParameter(mOverlayData, param, value);
+}
+
 status_t Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
 {
     if (mStatus != NO_ERROR) return mStatus;
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 4dca8bd..0831f4a 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -1486,7 +1486,7 @@
 
 ssize_t ResTable::Theme::resolveAttributeReference(Res_value* inOutValue,
         ssize_t blockIndex, uint32_t* outLastRef,
-        uint32_t* inoutTypeSpecFlags) const
+        uint32_t* inoutTypeSpecFlags, ResTable_config* inoutConfig) const
 {
     //printf("Resolving type=0x%x\n", inOutValue->dataType);
     if (inOutValue->dataType == Res_value::TYPE_ATTRIBUTE) {
@@ -1498,7 +1498,8 @@
             return blockIndex;
         }
     }
-    return mTable.resolveReference(inOutValue, blockIndex, outLastRef);
+    return mTable.resolveReference(inOutValue, blockIndex, outLastRef,
+            inoutTypeSpecFlags, inoutConfig);
 }
 
 void ResTable::Theme::dumpToLog() const
@@ -1891,7 +1892,8 @@
 }
 
 ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
-        uint32_t* outLastRef, uint32_t* inoutTypeSpecFlags) const
+        uint32_t* outLastRef, uint32_t* inoutTypeSpecFlags,
+        ResTable_config* outConfig) const
 {
     int count=0;
     while (blockIndex >= 0 && value->dataType == value->TYPE_REFERENCE
@@ -1899,7 +1901,8 @@
         if (outLastRef) *outLastRef = value->data;
         uint32_t lastRef = value->data;
         uint32_t newFlags = 0;
-        const ssize_t newIndex = getResource(value->data, value, true, &newFlags);
+        const ssize_t newIndex = getResource(value->data, value, true, &newFlags,
+                outConfig);
         //LOGI("Resolving reference d=%p: newIndex=%d, t=0x%02x, d=%p\n",
         //     (void*)lastRef, (int)newIndex, (int)value->dataType, (void*)value->data);
         //printf("Getting reference 0x%08x: newIndex=%d\n", value->data, newIndex);
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 0273a5a..304f521 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -276,7 +276,7 @@
 android_media_MediaRecorder_setVideoFrameRate(JNIEnv *env, jobject thiz, jint rate)
 {
     LOGV("setVideoFrameRate(%d)", rate);
-    if (rate <= 0 || rate > MEDIA_RECORDER_MAX_FRAME_RATE) {
+    if (rate <= 0) {
         jniThrowException(env, "java/lang/IllegalArgumentException", "invalid frame rate");
         return;
     }
diff --git a/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java b/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
index b749821..289ee45 100644
--- a/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
+++ b/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
@@ -25,6 +25,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.Serializable;
 
 /**
  * Proxy to start, stop and interact with a VPN daemon.
@@ -33,7 +34,10 @@
  * connection with the daemon, to both send commands to the daemon and receive
  * response and connecting error code from the daemon.
  */
-class DaemonProxy {
+class DaemonProxy implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private static final boolean DBG = true;
+
     private static final int WAITING_TIME = 15; // sec
 
     private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
@@ -45,8 +49,8 @@
     private static final int END_OF_ARGUMENTS = 255;
 
     private String mName;
-    private LocalSocket mControlSocket;
     private String mTag;
+    private transient LocalSocket mControlSocket;
 
     /**
      * Creates a proxy of the specified daemon.
@@ -63,14 +67,8 @@
 
     void start() throws IOException {
         String svc = mName;
-        Log.d(mTag, "-----  Stop the daemon just in case: " + mName);
-        SystemProperties.set(SVC_STOP_CMD, mName);
-        if (!blockUntil(SVC_STATE_STOPPED, 5)) {
-            throw new IOException("cannot start service anew: " + svc
-                    + ", it is still running");
-        }
 
-        Log.d(mTag, "+++++  Start: " + svc);
+        Log.i(mTag, "Start VPN daemon: " + svc);
         SystemProperties.set(SVC_START_CMD, svc);
 
         if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) {
@@ -103,7 +101,7 @@
         try {
             mControlSocket.close();
         } catch (IOException e) {
-            Log.e(mTag, "close control socket", e);
+            Log.w(mTag, "close control socket", e);
         } finally {
             mControlSocket = null;
         }
@@ -111,10 +109,10 @@
 
     void stop() {
         String svc = mName;
-        Log.d(mTag, "-----  Stop: " + svc);
+        Log.i(mTag, "Stop VPN daemon: " + svc);
         SystemProperties.set(SVC_STOP_CMD, svc);
         boolean success = blockUntil(SVC_STATE_STOPPED, 5);
-        Log.d(mTag, "stopping " + svc + ", success? " + success);
+        if (DBG) Log.d(mTag, "stopping " + svc + ", success? " + success);
     }
 
     boolean isStopped() {
@@ -129,7 +127,7 @@
         if (!blocking && in.available() == 0) return 0;
 
         int data = in.read();
-        Log.d(mTag, "got data from control socket: " + data);
+        Log.i(mTag, "got data from control socket: " + data);
 
         return data;
     }
@@ -146,7 +144,7 @@
                 s.connect(a);
                 return s;
             } catch (IOException e) {
-                Log.d(mTag, "service not yet listen()ing; try again");
+                if (DBG) Log.d(mTag, "service not yet listen()ing; try again");
                 excp = e;
                 sleep(500);
             }
@@ -173,8 +171,10 @@
         int n = waitTime * 1000 / sleepTime;
         for (int i = 0; i < n; i++) {
             if (expectedState.equals(SystemProperties.get(cmd))) {
-                Log.d(mTag, mName + " is " + expectedState + " after "
-                        + (i * sleepTime) + " msec");
+                if (DBG) {
+                    Log.d(mTag, mName + " is " + expectedState + " after "
+                            + (i * sleepTime) + " msec");
+                }
                 break;
             }
             sleep(sleepTime);
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
index 8efd7c4..7910f4a 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
@@ -45,4 +45,10 @@
                 (p.isSecretEnabled() ? p.getSecretString() : null),
                 username, password);
     }
+
+    @Override
+    protected void stopPreviouslyRunDaemons() {
+        stopDaemon(IPSEC);
+        stopDaemon(MtpdHelper.MTPD);
+    }
 }
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
index 56694b6..13b4952 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
@@ -46,6 +46,12 @@
                 username, password);
     }
 
+    @Override
+    protected void stopPreviouslyRunDaemons() {
+        stopDaemon(IPSEC);
+        stopDaemon(MtpdHelper.MTPD);
+    }
+
     private String getCaCertPath() {
         return CertTool.getInstance().getCaCertificate(
                 getProfile().getCaCertificate());
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
index 9273f35..d658a366 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
@@ -35,4 +35,9 @@
                 (p.isSecretEnabled() ? p.getSecretString() : null),
                 username, password);
     }
+
+    @Override
+    protected void stopPreviouslyRunDaemons() {
+        stopDaemon(MtpdHelper.MTPD);
+    }
 }
diff --git a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
index 805a5b5..9078d9b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
+++ b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
@@ -24,26 +24,33 @@
  * A helper class for sending commands to the MTP daemon (mtpd).
  */
 class MtpdHelper {
-    private static final String MTPD = "mtpd";
+    static final String MTPD = "mtpd";
     private static final String VPN_LINKNAME = "vpn";
     private static final String PPP_ARGS_SEPARATOR = "";
 
     static void sendCommand(VpnService<?> vpnService, String protocol,
             String serverIp, String port, String secret, String username,
             String password) throws IOException {
+        sendCommand(vpnService, protocol, serverIp, port, secret, username,
+                password, false);
+    }
+
+    static void sendCommand(VpnService<?> vpnService, String protocol,
+            String serverIp, String port, String secret, String username,
+            String password, boolean encryption) throws IOException {
         ArrayList<String> args = new ArrayList<String>();
         args.addAll(Arrays.asList(protocol, serverIp, port));
         if (secret != null) args.add(secret);
         args.add(PPP_ARGS_SEPARATOR);
-        addPppArguments(vpnService, args, serverIp, username, password);
+        addPppArguments(args, serverIp, username, password, encryption);
 
         DaemonProxy mtpd = vpnService.startDaemon(MTPD);
         mtpd.sendCommand(args.toArray(new String[args.size()]));
     }
 
-    private static void addPppArguments(VpnService<?> vpnService,
-            ArrayList<String> args, String serverIp, String username,
-            String password) throws IOException {
+    private static void addPppArguments(ArrayList<String> args, String serverIp,
+            String username, String password, boolean encryption)
+            throws IOException {
         args.addAll(Arrays.asList(
                 "linkname", VPN_LINKNAME,
                 "name", username,
@@ -52,6 +59,9 @@
                 "idle", "1800",
                 "mtu", "1400",
                 "mru", "1400"));
+        if (encryption) {
+            args.add("+mppe");
+        }
     }
 
     private MtpdHelper() {
diff --git a/packages/VpnServices/src/com/android/server/vpn/PptpService.java b/packages/VpnServices/src/com/android/server/vpn/PptpService.java
index 01362a5..d903d1b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/PptpService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/PptpService.java
@@ -26,11 +26,17 @@
 class PptpService extends VpnService<PptpProfile> {
     static final String PPTP_DAEMON = "pptp";
     static final String PPTP_PORT = "1723";
+
     @Override
     protected void connect(String serverIp, String username, String password)
             throws IOException {
+        PptpProfile p = getProfile();
         MtpdHelper.sendCommand(this, PPTP_DAEMON, serverIp, PPTP_PORT, null,
-                username, password);
+                username, password, p.isEncryptionEnabled());
     }
 
+    @Override
+    protected void stopPreviouslyRunDaemons() {
+        stopDaemon(MtpdHelper.MTPD);
+    }
 }
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 60a07d5..b107c7d 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -28,7 +28,11 @@
 import android.util.Log;
 
 import java.io.IOException;
+import java.io.Serializable;
+import java.net.DatagramSocket;
+import java.net.Socket;
 import java.net.InetAddress;
+import java.net.NetworkInterface;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
@@ -36,7 +40,9 @@
 /**
  * The service base class for managing a type of VPN connection.
  */
-abstract class VpnService<E extends VpnProfile> {
+abstract class VpnService<E extends VpnProfile> implements Serializable {
+    protected static final long serialVersionUID = 1L;
+    private static final boolean DBG = true;
     private static final int NOTIFICATION_ID = 1;
 
     private static final String DNS1 = "net.dns1";
@@ -50,12 +56,16 @@
     private static final String REMOTE_IP = "net.ipremote";
     private static final String DNS_DOMAIN_SUFFICES = "net.dns.search";
 
+    private static final int CHALLENGE_ERROR_CODE = 5;
+    private static final int REMOTE_HUNG_UP_ERROR_CODE = 7;
     private static final int AUTH_ERROR_CODE = 51;
 
     private final String TAG = VpnService.class.getSimpleName();
 
+    // FIXME: profile is only needed in connecting phase, so we can just save
+    // the profile name and service class name for recovery
     E mProfile;
-    VpnServiceBinder mContext;
+    transient VpnServiceBinder mContext;
 
     private VpnState mState = VpnState.IDLE;
     private Throwable mError;
@@ -63,9 +73,9 @@
     // connection settings
     private String mOriginalDns1;
     private String mOriginalDns2;
-    private String mVpnDns1 = "";
-    private String mVpnDns2 = "";
     private String mOriginalDomainSuffices;
+    private String mLocalIp;
+    private String mLocalIf;
 
     private long mStartTime; // VPN connection start time
 
@@ -73,7 +83,7 @@
     private DaemonHelper mDaemonHelper = new DaemonHelper();
 
     // for helping showing, updating notification
-    private NotificationHelper mNotification = new NotificationHelper();
+    private transient NotificationHelper mNotification;
 
     /**
      * Establishes a VPN connection with the specified username and password.
@@ -81,6 +91,8 @@
     protected abstract void connect(String serverIp, String username,
             String password) throws IOException;
 
+    protected abstract void stopPreviouslyRunDaemons();
+
     /**
      * Starts a VPN daemon.
      */
@@ -90,6 +102,13 @@
     }
 
     /**
+     * Stops a VPN daemon.
+     */
+    protected void stopDaemon(String daemonName) {
+        new DaemonProxy(daemonName).stop();
+    }
+
+    /**
      * Returns the VPN profile associated with the connection.
      */
     protected E getProfile() {
@@ -104,8 +123,22 @@
     }
 
     void setContext(VpnServiceBinder context, E profile) {
-        mContext = context;
         mProfile = profile;
+        recover(context);
+    }
+
+    void recover(VpnServiceBinder context) {
+        mContext = context;
+        mNotification = new NotificationHelper();
+
+        if (VpnState.CONNECTED.equals(mState)) {
+            Log.i("VpnService", "     recovered: " + mProfile.getName());
+            new Thread(new Runnable() {
+                public void run() {
+                    enterConnectivityLoop();
+                }
+            }).start();
+        }
     }
 
     VpnState getState() {
@@ -117,14 +150,14 @@
             mState = VpnState.CONNECTING;
             broadcastConnectivity(VpnState.CONNECTING);
 
+            stopPreviouslyRunDaemons();
             String serverIp = getIp(getProfile().getServerName());
-
+            saveLocalIpAndInterface(serverIp);
             onBeforeConnect();
             connect(serverIp, username, password);
             waitUntilConnectedOrTimedout();
             return true;
         } catch (Throwable e) {
-            Log.e(TAG, "onConnect()", e);
             onError(e);
             return false;
         }
@@ -132,7 +165,7 @@
 
     synchronized void onDisconnect() {
         try {
-            Log.d(TAG, "       disconnecting VPN...");
+            Log.i(TAG, "disconnecting VPN...");
             mState = VpnState.DISCONNECTING;
             broadcastConnectivity(VpnState.DISCONNECTING);
             mNotification.showDisconnect();
@@ -152,6 +185,7 @@
             Log.w(TAG, "   multiple errors occur, record the last one: "
                     + error);
         }
+        Log.e(TAG, "onError()", error);
         mError = error;
         onDisconnect();
     }
@@ -161,16 +195,18 @@
     }
 
 
-    private void onBeforeConnect() {
+    private void onBeforeConnect() throws IOException {
         mNotification.disableNotification();
 
-        SystemProperties.set(VPN_DNS1, "-");
-        SystemProperties.set(VPN_DNS2, "-");
+        SystemProperties.set(VPN_DNS1, "");
+        SystemProperties.set(VPN_DNS2, "");
         SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
-        Log.d(TAG, "       VPN UP: " + SystemProperties.get(VPN_STATUS));
+        if (DBG) {
+            Log.d(TAG, "       VPN UP: " + SystemProperties.get(VPN_STATUS));
+        }
     }
 
-    private void waitUntilConnectedOrTimedout() {
+    private void waitUntilConnectedOrTimedout() throws IOException {
         sleep(2000); // 2 seconds
         for (int i = 0; i < 60; i++) {
             if (mState != VpnState.CONNECTING) {
@@ -187,39 +223,49 @@
 
         synchronized (VpnService.this) {
             if (mState == VpnState.CONNECTING) {
-                Log.d(TAG, "       connecting timed out !!");
                 onError(new IOException("Connecting timed out"));
             }
         }
     }
 
-    private synchronized void onConnected() {
-        Log.d(TAG, "onConnected()");
+    private synchronized void onConnected() throws IOException {
+        if (DBG) Log.d(TAG, "onConnected()");
 
         mDaemonHelper.closeSockets();
-        saveVpnDnsProperties();
+        saveOriginalDns();
         saveAndSetDomainSuffices();
 
         mState = VpnState.CONNECTED;
+        mStartTime = System.currentTimeMillis();
+
+        // set DNS after saving the states in case the process gets killed
+        // before states are saved
+        saveSelf();
+        setVpnDns();
         broadcastConnectivity(VpnState.CONNECTED);
 
         enterConnectivityLoop();
     }
 
+    private void saveSelf() throws IOException {
+        mContext.saveStates();
+    }
+
     private synchronized void onFinalCleanUp() {
-        Log.d(TAG, "onFinalCleanUp()");
+        if (DBG) Log.d(TAG, "onFinalCleanUp()");
 
         if (mState == VpnState.IDLE) return;
 
         // keep the notification when error occurs
         if (!anyError()) mNotification.disableNotification();
 
-        restoreOriginalDnsProperties();
+        restoreOriginalDns();
         restoreOriginalDomainSuffices();
         mState = VpnState.IDLE;
         broadcastConnectivity(VpnState.IDLE);
 
         // stop the service itself
+        mContext.removeStates();
         mContext.stopSelf();
     }
 
@@ -227,46 +273,38 @@
         return (mError != null);
     }
 
-    private void restoreOriginalDnsProperties() {
+    private void restoreOriginalDns() {
         // restore only if they are not overridden
-        if (mVpnDns1.equals(SystemProperties.get(DNS1))) {
-            Log.d(TAG, String.format("restore original dns prop: %s --> %s",
+        String vpnDns1 = SystemProperties.get(VPN_DNS1);
+        if (vpnDns1.equals(SystemProperties.get(DNS1))) {
+            Log.i(TAG, String.format("restore original dns prop: %s --> %s",
                     SystemProperties.get(DNS1), mOriginalDns1));
-            Log.d(TAG, String.format("restore original dns prop: %s --> %s",
+            Log.i(TAG, String.format("restore original dns prop: %s --> %s",
                     SystemProperties.get(DNS2), mOriginalDns2));
             SystemProperties.set(DNS1, mOriginalDns1);
             SystemProperties.set(DNS2, mOriginalDns2);
         }
     }
 
-    private void saveVpnDnsProperties() {
-        mOriginalDns1 = mOriginalDns2 = "";
-        for (int i = 0; i < 5; i++) {
-            mVpnDns1 = SystemProperties.get(VPN_DNS1);
-            mVpnDns2 = SystemProperties.get(VPN_DNS2);
-            if (mOriginalDns1.equals(mVpnDns1)) {
-                Log.d(TAG, "wait for vpn dns to settle in..." + i);
-                sleep(200);
-            } else {
-                mOriginalDns1 = SystemProperties.get(DNS1);
-                mOriginalDns2 = SystemProperties.get(DNS2);
-                SystemProperties.set(DNS1, mVpnDns1);
-                SystemProperties.set(DNS2, mVpnDns2);
-                Log.d(TAG, String.format("save original dns prop: %s, %s",
-                        mOriginalDns1, mOriginalDns2));
-                Log.d(TAG, String.format("set vpn dns prop: %s, %s",
-                        mVpnDns1, mVpnDns2));
-                return;
-            }
-        }
-        Log.d(TAG, "saveVpnDnsProperties(): DNS not updated??");
-        mOriginalDns1 = mVpnDns1 = SystemProperties.get(DNS1);
-        mOriginalDns2 = mVpnDns2 = SystemProperties.get(DNS2);
+    private void saveOriginalDns() {
+        mOriginalDns1 = SystemProperties.get(DNS1);
+        mOriginalDns2 = SystemProperties.get(DNS2);
+        Log.i(TAG, String.format("save original dns prop: %s, %s",
+                mOriginalDns1, mOriginalDns2));
+    }
+
+    private void setVpnDns() {
+        String vpnDns1 = SystemProperties.get(VPN_DNS1);
+        String vpnDns2 = SystemProperties.get(VPN_DNS2);
+        SystemProperties.set(DNS1, vpnDns1);
+        SystemProperties.set(DNS2, vpnDns2);
+        Log.i(TAG, String.format("set vpn dns prop: %s, %s",
+                vpnDns1, vpnDns2));
     }
 
     private void saveAndSetDomainSuffices() {
         mOriginalDomainSuffices = SystemProperties.get(DNS_DOMAIN_SUFFICES);
-        Log.d(TAG, "save original dns search: " + mOriginalDomainSuffices);
+        Log.i(TAG, "save original suffices: " + mOriginalDomainSuffices);
         String list = mProfile.getDomainSuffices();
         if (!TextUtils.isEmpty(list)) {
             SystemProperties.set(DNS_DOMAIN_SUFFICES, list);
@@ -274,7 +312,7 @@
     }
 
     private void restoreOriginalDomainSuffices() {
-        Log.d(TAG, "restore original dns search --> " + mOriginalDomainSuffices);
+        Log.i(TAG, "restore original suffices --> " + mOriginalDomainSuffices);
         SystemProperties.set(DNS_DOMAIN_SUFFICES, mOriginalDomainSuffices);
     }
 
@@ -298,46 +336,73 @@
     }
 
     private void enterConnectivityLoop() {
-        mStartTime = System.currentTimeMillis();
-
-        Log.d(TAG, "   +++++   connectivity monitor running");
+        Log.i(TAG, "VPN connectivity monitor running");
         try {
             for (;;) {
                 synchronized (VpnService.this) {
-                    if (mState != VpnState.CONNECTED) break;
+                    if (mState != VpnState.CONNECTED || !checkConnectivity()) {
+                        break;
+                    }
                     mNotification.update();
-                    checkConnectivity();
+                    checkDns();
                     VpnService.this.wait(1000); // 1 second
                 }
             }
         } catch (InterruptedException e) {
-            Log.e(TAG, "connectivity monitor", e);
+            onError(e);
         }
-        Log.d(TAG, "   -----   connectivity monitor stopped");
+        Log.i(TAG, "VPN connectivity monitor stopped");
     }
 
-    private void checkConnectivity() {
+    private void saveLocalIpAndInterface(String serverIp) throws IOException {
+        DatagramSocket s = new DatagramSocket();
+        int port = 80; // arbitrary
+        s.connect(InetAddress.getByName(serverIp), port);
+        InetAddress localIp = s.getLocalAddress();
+        mLocalIp = localIp.getHostAddress();
+        NetworkInterface localIf = NetworkInterface.getByInetAddress(localIp);
+        mLocalIf = (localIf == null) ? null : localIf.getName();
+        if (TextUtils.isEmpty(mLocalIf)) {
+            throw new IOException("Local interface is empty!");
+        }
+        if (DBG) {
+            Log.d(TAG, "  Local IP: " + mLocalIp + ", if: " + mLocalIf);
+        }
+    }
+
+    // returns false if vpn connectivity is broken
+    private boolean checkConnectivity() {
         if (mDaemonHelper.anyDaemonStopped() || isLocalIpChanged()) {
             onDisconnect();
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    private void checkDns() {
+        String dns1 = SystemProperties.get(DNS1);
+        String vpnDns1 = SystemProperties.get(VPN_DNS1);
+        if (!dns1.equals(vpnDns1) && dns1.equals(mOriginalDns1)) {
+            // dhcp expires?
+            setVpnDns();
         }
     }
 
     private boolean isLocalIpChanged() {
-        // TODO
-        if (!isDnsIntact()) {
-            Log.w(TAG, "       local IP changed");
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private boolean isDnsIntact() {
-        String dns1 = SystemProperties.get(DNS1);
-        if (!mVpnDns1.equals(dns1)) {
-            Log.w(TAG, "   dns being overridden by: " + dns1);
-            return false;
-        } else {
+        try {
+            InetAddress localIp = InetAddress.getByName(mLocalIp);
+            NetworkInterface localIf =
+                    NetworkInterface.getByInetAddress(localIp);
+            if (localIf == null || !mLocalIf.equals(localIf.getName())) {
+                Log.w(TAG, "       local If changed from " + mLocalIf
+                        + " to " + localIf);
+                return true;
+            } else {
+                return false;
+            }
+        } catch (IOException e) {
+            Log.w(TAG, "isLocalIpChanged()", e);
             return true;
         }
     }
@@ -349,7 +414,7 @@
         }
     }
 
-    private class DaemonHelper {
+    private class DaemonHelper implements Serializable {
         private List<DaemonProxy> mDaemonList =
                 new ArrayList<DaemonProxy>();
 
@@ -376,7 +441,7 @@
         synchronized boolean anyDaemonStopped() {
             for (DaemonProxy s : mDaemonList) {
                 if (s.isStopped()) {
-                    Log.w(TAG, "       daemon gone: " + s.getName());
+                    Log.w(TAG, "    VPN daemon gone: " + s.getName());
                     return true;
                 }
             }
@@ -401,6 +466,14 @@
                         onError(VpnManager.VPN_ERROR_AUTH);
                         return true;
 
+                    case CHALLENGE_ERROR_CODE:
+                        onError(VpnManager.VPN_ERROR_CHALLENGE);
+                        return true;
+
+                    case REMOTE_HUNG_UP_ERROR_CODE:
+                        onError(VpnManager.VPN_ERROR_REMOTE_HUNG_UP);
+                        return true;
+
                     default:
                         onError(VpnManager.VPN_ERROR_CONNECTION_FAILED);
                         return true;
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
index 513a2c9..4892a7b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
@@ -27,23 +27,31 @@
 import android.net.vpn.VpnProfile;
 import android.net.vpn.VpnState;
 import android.os.IBinder;
+import android.util.Log;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 
 /**
  * The service class for managing a VPN connection. It implements the
  * {@link IVpnService} binder interface.
  */
 public class VpnServiceBinder extends Service {
-    private final String TAG = VpnServiceBinder.class.getSimpleName();
+    private static final String TAG = VpnServiceBinder.class.getSimpleName();
+    private static final boolean DBG = true;
+
+    private static final String STATES_FILE_PATH = "/data/misc/vpn/.states";
 
     // The actual implementation is delegated to the VpnService class.
     private VpnService<? extends VpnProfile> mService;
 
     private final IBinder mBinder = new IVpnService.Stub() {
         public boolean connect(VpnProfile p, String username, String password) {
-            android.util.Log.d("VpnServiceBinder", "becoming foreground");
-            setForeground(true);
             return VpnServiceBinder.this.connect(p, username, password);
         }
 
@@ -57,6 +65,13 @@
     };
 
     @Override
+    public void onCreate() {
+        super.onCreate();
+        checkSavedStates();
+    }
+
+
+    @Override
     public void onStart(Intent intent, int startId) {
         super.onStart(intent, startId);
     }
@@ -66,14 +81,30 @@
         return mBinder;
     }
 
+    void saveStates() throws IOException {
+        if (DBG) Log.d("VpnServiceBinder", "     saving states");
+        ObjectOutputStream oos =
+                new ObjectOutputStream(new FileOutputStream(STATES_FILE_PATH));
+        oos.writeObject(mService);
+        oos.close();
+    }
+
+    void removeStates() {
+        try {
+            new File(STATES_FILE_PATH).delete();
+        } catch (Throwable e) {
+            if (DBG) Log.d("VpnServiceBinder", "     remove states: " + e);
+        }
+    }
+
     private synchronized boolean connect(final VpnProfile p,
             final String username, final String password) {
         if (mService != null) return false;
+        final VpnService s = mService = createService(p);
 
         new Thread(new Runnable() {
             public void run() {
-                mService = createService(p);
-                mService.onConnect(username, password);
+                s.onConnect(username, password);
             }
         }).start();
         return true;
@@ -81,12 +112,11 @@
 
     private synchronized void disconnect() {
         if (mService == null) return;
+        final VpnService s = mService;
 
         new Thread(new Runnable() {
             public void run() {
-                mService.onDisconnect();
-                android.util.Log.d("VpnServiceBinder", "becoming background");
-                setForeground(false);
+                s.onDisconnect();
             }
         }).start();
     }
@@ -100,6 +130,21 @@
         }
     }
 
+    private void checkSavedStates() {
+        try {
+            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
+                    STATES_FILE_PATH));
+            mService = (VpnService<? extends VpnProfile>) ois.readObject();
+            mService.recover(this);
+            ois.close();
+        } catch (FileNotFoundException e) {
+            // do nothing
+        } catch (Throwable e) {
+            Log.i("VpnServiceBinder", "recovery error, remove states: " + e);
+            removeStates();
+        }
+    }
+
     private VpnService<? extends VpnProfile> createService(VpnProfile p) {
         switch (p.getType()) {
             case L2TP:
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 134fb6f..9e8816b 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -494,7 +494,7 @@
             mDrmAppInstallObserver = new AppDirObserver(
                 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
             mDrmAppInstallObserver.startWatching();
-            scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode);
+            scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
 
             EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
                     SystemClock.uptimeMillis());
@@ -1766,7 +1766,12 @@
         int i;
         for (i=0; i<files.length; i++) {
             File file = new File(dir, files[i]);
-            PackageParser.Package pkg = scanPackageLI(file, file, file, 
+            File resFile = file;
+            // Pick up the resource path from settings for fwd locked apps
+            if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
+                resFile = null;
+            }
+            PackageParser.Package pkg = scanPackageLI(file, file, resFile,
                     flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
         }
     }
@@ -1868,8 +1873,12 @@
         if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
             scanMode |= SCAN_FORWARD_LOCKED;
         }
+        File resFile = destResourceFile;
+        if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
+            resFile = getFwdLockedResource(ps.name);
+        }
         // Note that we invoke the following method only if we are about to unpack an application
-        return scanPackageLI(scanFile, destCodeFile, destResourceFile,
+        return scanPackageLI(scanFile, destCodeFile, resFile,
                 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
     }
 
@@ -3811,6 +3820,11 @@
         }
     }
     
+    private File getFwdLockedResource(String pkgName) {
+        final String publicZipFileName = pkgName + ".zip";
+        return new File(mAppInstallDir, publicZipFileName);
+    }
+
     private PackageInstalledInfo installPackageLI(Uri pPackageURI,
             int pFlags, boolean newInstall, String installerPackageName) {
         File tmpPackageFile = null;
@@ -3890,8 +3904,7 @@
             final String destFilePath = destPackageFile.getAbsolutePath();
             File destResourceFile;
             if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
-                final String publicZipFileName = pkgName + ".zip";
-                destResourceFile = new File(mAppInstallDir, publicZipFileName);
+                destResourceFile = getFwdLockedResource(pkgName);
                 forwardLocked = true;
             } else {
                 destResourceFile = destPackageFile;
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 890f930..82539fb 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -40,7 +40,6 @@
 /**
  * Manages SMS operations such as sending data, text, and pdu SMS messages.
  * Get this object by calling the static method SmsManager.getDefault().
- * @hide
  */
 public final class SmsManager {
     private static SmsManager sInstance;
@@ -202,6 +201,8 @@
 
     /**
      * Send a raw SMS PDU.
+     * A PDU is a protocol data unit. It contains the message and the
+     * associated meta information.
      *
      * @param smsc the SMSC to send the message through, or NULL for the
      *  default SMSC
@@ -219,8 +220,6 @@
      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is delivered to the recipient.  The
      *  raw pdu of the status report is in the extended data ("pdu").
-     *
-     * @hide
      */
     private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
             PendingIntent deliveryIntent) {
@@ -252,6 +251,8 @@
 
     /**
      * Copy a raw SMS PDU to the ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
      *
      * @param smsc the SMSC for this message, or NULL for the default SMSC
      * @param pdu the raw PDU to store
@@ -278,6 +279,8 @@
 
     /**
      * Delete the specified message from the ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
      *
      * @param messageIndex is the record index of the message on ICC
      * @return true for success
@@ -304,6 +307,8 @@
 
     /**
      * Update the specified message on the ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
      *
      * @param messageIndex record index of message to update
      * @param newStatus new message status (STATUS_ON_ICC_READ,
@@ -331,6 +336,8 @@
 
     /**
      * Retrieves all messages currently stored on ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
      *
      * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
      *
@@ -359,12 +366,12 @@
      *   <code>getAllMessagesFromIcc</code>
      * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
      */
-    private ArrayList<SmsMessage> createMessageListFromRawRecords(List records) {
+    private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
         ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
         if (records != null) {
             int count = records.size();
             for (int i = 0; i < count; i++) {
-                SmsRawData data = (SmsRawData)records.get(i);
+                SmsRawData data = records.get(i);
                 // List contains all records, including "free" records (null)
                 if (data != null) {
                     SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index fc491d7..0617dad 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -28,13 +28,13 @@
 
 import java.lang.Math;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
 
 
 /**
  * A Short Message Service message.
- * @hide
  */
 public class SmsMessage {
     private static final boolean LOCAL_DEBUG = true;
@@ -49,18 +49,6 @@
         UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
     }
 
-    /**
-     * TODO(cleanup): given that we now have more than one possible
-     * 7bit encoding, this result starts to look rather vague and
-     * maybe confusing...  If this is just an indication of code unit
-     * size, maybe that is no problem.  Otherwise, should we try to
-     * create an aggregate collection of GSM and CDMA encodings?  CDMA
-     * contains a superset of the encodings we use (it does not
-     * support 8-bit GSM, but we also do not use that encoding
-     * currently)...  We could get rid of these and directly reference
-     * the CDMA encoding definitions...
-     */
-
     /** User data text encoding code unit size */
     public static final int ENCODING_UNKNOWN = 0;
     public static final int ENCODING_7BIT = 1;
@@ -71,24 +59,9 @@
     public static final int MAX_USER_DATA_BYTES = 140;
 
     /**
-     * TODO(cleanup): It would be more flexible and less fragile to
-     * rewrite this (meaning get rid of the following constant) such
-     * that an actual UDH is taken into consideration (meaning its
-     * length is measured), allowing for messages that actually
-     * contain other UDH fields...  Hence it is actually a shame to
-     * extend the API with this constant.  If necessary, maybe define
-     * the size of such a header and let the math for calculating
-     * max_octets/septets be done elsewhere.  And, while I am griping,
-     * if we use the word septet, we should use the word octet in
-     * corresponding places, not byte...
-     */
-
-    /**
      * The maximum number of payload bytes per message if a user data header
      * is present.  This assumes the header only contains the
      * CONCATENATED_8_BIT_REFERENCE element.
-     *
-     * @hide pending API Council approval to extend the public API
      */
     public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
 
@@ -103,17 +76,26 @@
     public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
 
     /** Contains actual SmsMessage. Only public for debugging and for framework layer.
-    * {@hide}
-    */
+     *
+     * @hide
+     */
     public SmsMessageBase mWrappedSmsMessage;
 
-    public static class SubmitPdu extends SubmitPduBase {
+    public static class SubmitPdu {
 
-        //Constructor
-        public SubmitPdu() {
+        public byte[] encodedScAddress; // Null if not applicable.
+        public byte[] encodedMessage;
+
+        public String toString() {
+            return "SubmitPdu: encodedScAddress = "
+                    + Arrays.toString(encodedScAddress)
+                    + ", encodedMessage = "
+                    + Arrays.toString(encodedMessage);
         }
 
-        /* {@hide} */
+        /**
+         * @hide
+         */
         protected SubmitPdu(SubmitPduBase spb) {
             this.encodedMessage = spb.encodedMessage;
             this.encodedScAddress = spb.encodedScAddress;
@@ -121,7 +103,11 @@
 
     }
 
-    // Constructor
+    /**
+     * Constructor
+     *
+     * @hide
+     */
     public SmsMessage() {
         this(getSmsFacility());
     }
@@ -295,6 +281,8 @@
      * @param text text, must not be null.
      * @return an <code>ArrayList</code> of strings that, in order,
      *   comprise the original msg text
+     *
+     * @hide
      */
     public static ArrayList<String> fragmentText(String text) {
         int activePhone = TelephonyManager.getDefault().getPhoneType();
@@ -343,10 +331,11 @@
      * current encoding.
      *
      * @param messageBody the message to encode
-     * @param use7bitOnly if true, characters that are not part of the GSM
-     *         alphabet are counted as a single space char.  If false, a
-     *         messageBody containing non-GSM alphabet characters is calculated
-     *         for 16-bit encoding.
+     * @param use7bitOnly if true, characters that are not part of the radio
+     *         specific (GSM / CDMA) alphabet encoding are converted to as a
+     *         single space characters. If false, a messageBody containing
+     *         non-GSM or non-CDMA alphabet characters are encoded using
+     *         16-bit encoding.
      * @return an int[4] with int[0] being the number of SMS's required, int[1]
      *         the number of code units used, and int[2] is the number of code
      *         units remaining until the next message. int[3] is the encoding
@@ -688,6 +677,8 @@
     /** This method returns the reference to a specific
      *  SmsMessage object, which is used for accessing its static methods.
      * @return Specific SmsMessage.
+     *
+     * @hide
      */
     private static final SmsMessageBase getSmsFacility(){
         int activePhone = TelephonyManager.getDefault().getPhoneType();
diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java
index cdd707e..241c485 100644
--- a/telephony/java/android/telephony/gsm/SmsManager.java
+++ b/telephony/java/android/telephony/gsm/SmsManager.java
@@ -43,6 +43,7 @@
         return sInstance;
     }
 
+    @Deprecated
     private SmsManager() {
         mSmsMgrProxy = android.telephony.SmsManager.getDefault();
     }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 1f4ce3d..0763e63 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -86,14 +86,6 @@
    >>java/android/com.android.internal.telephony/gsm/RILConstants.java
 */
 
-
-    int RIL_SIM_ABSENT = 0;
-    int RIL_SIM_NOT_READY = 1;
-    int RIL_SIM_READY = 2;
-    int RIL_SIM_PIN = 3;
-    int RIL_SIM_PUK = 4;
-    int RIL_SIM_NETWORK_PERSONALIZATION = 5;
-
     /**
      * No restriction at all including voice/SMS/USSD/SS/AV64
      * and packet data.
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 9c78b98..7a15c32 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -118,6 +118,7 @@
         public int codeUnitSize;
     }
 
+    // TODO(): This class is duplicated in SmsMessage.java. Refactor accordingly.
     public static abstract class SubmitPduBase  {
         public byte[] encodedScAddress; // Null if not applicable.
         public byte[] encodedMessage;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 28ce6a5..0d46777 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -1338,25 +1338,26 @@
         return isOtaSpNum;
     }
 
-     /**
-      * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
-      * OTASP dial string.
-      *
-      * @param dialStr the number to look up.
-      * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
-      */
+    /**
+     * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
+     * OTASP dial string.
+     *
+     * @param dialStr the number to look up.
+     * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
+     */
     @Override
-     public  boolean isOtaSpNumber(String dialStr){
-         boolean isOtaSpNum = false;
-         if (dialStr != null) {
-             isOtaSpNum = isIs683OtaSpDialStr(dialStr);
-             if(isOtaSpNum == false){
-                 isOtaSpNum = isCarrierOtaSpNum(dialStr);
-             }
-         }
-         if (DBG) Log.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
-         return isOtaSpNum;
-     }
+    public  boolean isOtaSpNumber(String dialStr){
+        boolean isOtaSpNum = false;
+        String dialableStr = PhoneNumberUtils.extractNetworkPortion(dialStr);
+        if (dialableStr != null) {
+            isOtaSpNum = isIs683OtaSpDialStr(dialableStr);
+            if (isOtaSpNum == false) {
+                isOtaSpNum = isCarrierOtaSpNum(dialableStr);
+            }
+        }
+        if (DBG) Log.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
+        return isOtaSpNum;
+    }
 
     @Override
     public int getCdmaEriIconIndex() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 0cae604..53f0274 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -121,8 +121,8 @@
     private int curSpnRule = 0;
 
     private String mMdn;
-    private int mHomeSystemId;
-    private int mHomeNetworkId;
+    private int mHomeSystemId[] = null;
+    private int mHomeNetworkId[] = null;
     private String mMin;
     private String mPrlVersion;
 
@@ -398,23 +398,31 @@
                 String cdmaSubscription[] = (String[])ar.result;
                 if (cdmaSubscription != null && cdmaSubscription.length >= 5) {
                     mMdn = cdmaSubscription[0];
-                    // TODO: Only grabbing the first SID/NID for now.
                     if (cdmaSubscription[1] != null) {
                         String[] sid = cdmaSubscription[1].split(",");
-                        try {
-                            mHomeSystemId = sid.length > 0 ? Integer.parseInt(sid[0]) : 0;
-                        } catch (NumberFormatException e) {
-                            mHomeSystemId = 0;
+                        mHomeSystemId = new int[sid.length];
+                        for (int i = 0; i < sid.length; i++) {
+                            try {
+                                mHomeSystemId[i] = Integer.parseInt(sid[i]);
+                            } catch (NumberFormatException ex) {
+                                Log.e(LOG_TAG, "error parsing system id: ", ex);
+                            }
                         }
                     }
+                    Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION SID=" + cdmaSubscription[1] );
+
                     if (cdmaSubscription[2] != null) {
                         String[] nid = cdmaSubscription[2].split(",");
-                        try {
-                            mHomeNetworkId = nid.length > 0 ? Integer.parseInt(nid[0]) : 0;
-                        } catch (NumberFormatException e) {
-                            mHomeNetworkId = 0;
+                        mHomeNetworkId = new int[nid.length];
+                        for (int i = 0; i < nid.length; i++) {
+                            try {
+                                mHomeNetworkId[i] = Integer.parseInt(nid[i]);
+                            } catch (NumberFormatException ex) {
+                                Log.e(LOG_TAG, "error parsing network id: ", ex);
+                            }
                         }
                     }
+                    Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION NID=" + cdmaSubscription[2] );
                     mMin = cdmaSubscription[3];
                     mPrlVersion = cdmaSubscription[4];
                     Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION MDN=" + mMdn);
@@ -712,7 +720,7 @@
 
         if (pollingContext[0] == 0) {
             boolean namMatch = false;
-            if ((mHomeSystemId != 0) && (mHomeSystemId == newSS.getSystemId()) ) {
+            if (!isSidsAllZeros() && isHomeSid(newSS.getSystemId())) {
                 namMatch = true;
             }
 
@@ -724,33 +732,43 @@
             }
 
             // Setting SS CdmaRoamingIndicator and CdmaDefaultRoamingIndicator
-            // TODO(Teleca): Validate this is correct.
-            if (mIsInPrl) {
-                if (namMatch && (mRoamingIndicator <= 2)) {
-                        // System is acquired, prl match, nam match and mRoamingIndicator <= 2
-                        newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
-                } else {
-                    // System is acquired, prl match, no nam match  or mRoamingIndicator > 2
-                    newSS.setCdmaRoamingIndicator(mRoamingIndicator);
-                }
-            } else {
-                if (mRegistrationState == 5) {
-                    // System is acquired but prl not loaded or no prl match
+            newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
+            newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+            boolean isPrlLoaded = true;
+            if (TextUtils.isEmpty(mPrlVersion)) {
+                isPrlLoaded = false;
+            }
+            if (!isPrlLoaded) {
+                newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH);
+            } else if (!isSidsAllZeros()) {
+                if (!namMatch && !mIsInPrl) {
+                    // Use default
+                    newSS.setCdmaRoamingIndicator(mDefaultRoamingIndicator);
+                } else if (namMatch && !mIsInPrl) {
                     newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH);
+                } else if (!namMatch && mIsInPrl) {
+                    // Use the one from PRL/ERI
+                    newSS.setCdmaRoamingIndicator(mRoamingIndicator);
                 } else {
-                    // Use the default indicator
+                    // It means namMatch && mIsInPrl
+                    if ((mRoamingIndicator <= 2)) {
+                        newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
+                    } else {
+                        // Use the one from PRL/ERI
+                        newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+                    }
                 }
             }
 
-            newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
 
             // NOTE: Some operator may require to override the mCdmaRoaming (set by the modem)
             // depending on the mRoamingIndicator.
 
             if (DBG) {
                 log("Set CDMA Roaming Indicator to: " + newSS.getCdmaRoamingIndicator()
-                    + ". mCdmaRoaming = " + mCdmaRoaming + ",  namMatch = " + namMatch
-                    + ", mIsInPrl = " + mIsInPrl + ", mRoamingIndicator = " + mRoamingIndicator
+                    + ". mCdmaRoaming = " + mCdmaRoaming + ", isPrlLoaded = " + isPrlLoaded
+                    + ". namMatch = " + namMatch + " , mIsInPrl = " + mIsInPrl
+                    + ", mRoamingIndicator = " + mRoamingIndicator
                     + ", mDefaultRoamingIndicator= " + mDefaultRoamingIndicator);
             }
             pollStateDone();
@@ -1458,6 +1476,31 @@
         }
     }
 
+    private boolean isSidsAllZeros() {
+        if (mHomeSystemId != null) {
+            for (int i=0; i < mHomeSystemId.length; i++) {
+                if (mHomeSystemId[i] != 0) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Check whether a specified system ID that matches one of the home system IDs.
+     */
+    private boolean isHomeSid(int sid) {
+        if (mHomeSystemId != null) {
+            for (int i=0; i < mHomeSystemId.length; i++) {
+                if (sid == mHomeSystemId[i]) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * @return true if phone is camping on a technology
      * that could support voice and data simultaneously.
diff --git a/tests/DpiTest/res/drawable-hdpi/reslogo240dpi.png b/tests/DpiTest/res/drawable-hdpi/reslogo240dpi.png
new file mode 100644
index 0000000..4d717a8
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/reslogo240dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-hdpi/stylogo240dpi.png b/tests/DpiTest/res/drawable-hdpi/stylogo240dpi.png
new file mode 100644
index 0000000..4d717a8
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/stylogo240dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/reslogo120dpi.png b/tests/DpiTest/res/drawable-ldpi/reslogo120dpi.png
new file mode 100644
index 0000000..46bbd5b
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/reslogo120dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/stylogo120dpi.png b/tests/DpiTest/res/drawable-ldpi/stylogo120dpi.png
new file mode 100644
index 0000000..46bbd5b
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/stylogo120dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/reslogo160dpi.png b/tests/DpiTest/res/drawable/reslogo160dpi.png
new file mode 100644
index 0000000..c23b2ce
--- /dev/null
+++ b/tests/DpiTest/res/drawable/reslogo160dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/stylogo160dpi.png b/tests/DpiTest/res/drawable/stylogo160dpi.png
new file mode 100644
index 0000000..c23b2ce
--- /dev/null
+++ b/tests/DpiTest/res/drawable/stylogo160dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/layout/image_views.xml b/tests/DpiTest/res/layout/image_views.xml
new file mode 100644
index 0000000..6a91497
--- /dev/null
+++ b/tests/DpiTest/res/layout/image_views.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/reslogo120dpi" />
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/reslogo160dpi" />
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/reslogo240dpi" />
+
+</LinearLayout>
diff --git a/tests/DpiTest/res/layout/styled_image_views.xml b/tests/DpiTest/res/layout/styled_image_views.xml
new file mode 100644
index 0000000..86c63bf
--- /dev/null
+++ b/tests/DpiTest/res/layout/styled_image_views.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <ImageView style="@style/ImageView120dpi" />
+    <ImageView style="@style/ImageView160dpi" />
+    <ImageView style="@style/ImageView240dpi" />
+
+</LinearLayout>
diff --git a/tests/DpiTest/res/values/styles.xml b/tests/DpiTest/res/values/styles.xml
new file mode 100644
index 0000000..bb4b13c
--- /dev/null
+++ b/tests/DpiTest/res/values/styles.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          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.
+-->
+
+<resources>
+    <style name="ImageView120dpi">
+        <item name="android:src">@drawable/stylogo120dpi</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+    </style>
+
+    <style name="ImageView160dpi">
+        <item name="android:src">@drawable/stylogo160dpi</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+    </style>
+
+    <style name="ImageView240dpi">
+        <item name="android:src">@drawable/stylogo240dpi</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+    </style>
+</resources>
diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
index 68220a1..ae53b76 100644
--- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
+++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
@@ -28,6 +28,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.ScrollView;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -71,6 +72,9 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        final LayoutInflater li = (LayoutInflater)getSystemService(
+                LAYOUT_INFLATER_SERVICE);
+        
         this.setTitle(R.string.act_title);
         LinearLayout root = new LinearLayout(this);
         root.setOrientation(LinearLayout.VERTICAL);
@@ -96,6 +100,14 @@
         addLabelToRoot(root, "Prescaled resource drawable");
         addChildToRoot(root, layout);
 
+        layout = (LinearLayout)li.inflate(R.layout.image_views, null);
+        addLabelToRoot(root, "Inflated layout");
+        addChildToRoot(root, layout);
+        
+        layout = (LinearLayout)li.inflate(R.layout.styled_image_views, null);
+        addLabelToRoot(root, "Inflated styled layout");
+        addChildToRoot(root, layout);
+        
         layout = new LinearLayout(this);
         addCanvasBitmap(layout, R.drawable.logo120dpi, true);
         addCanvasBitmap(layout, R.drawable.logo160dpi, true);
diff --git a/vpn/java/android/net/vpn/PptpProfile.java b/vpn/java/android/net/vpn/PptpProfile.java
index c68bb71..b4b7be5 100644
--- a/vpn/java/android/net/vpn/PptpProfile.java
+++ b/vpn/java/android/net/vpn/PptpProfile.java
@@ -16,15 +16,41 @@
 
 package android.net.vpn;
 
+import android.os.Parcel;
+
 /**
  * The profile for PPTP type of VPN.
  * {@hide}
  */
 public class PptpProfile extends VpnProfile {
     private static final long serialVersionUID = 1L;
+    private boolean mEncryption = true;
 
     @Override
     public VpnType getType() {
         return VpnType.PPTP;
     }
+
+    /**
+     * Enables/disables the encryption for PPTP tunnel.
+     */
+    public void setEncryptionEnabled(boolean enabled) {
+        mEncryption = enabled;
+    }
+
+    public boolean isEncryptionEnabled() {
+        return mEncryption;
+    }
+
+    @Override
+    protected void readFromParcel(Parcel in) {
+        super.readFromParcel(in);
+        mEncryption = in.readInt() > 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeInt(mEncryption ? 1 : 0);
+    }
 }
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index 0bf2346..e448e5a 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -50,6 +50,10 @@
     public static final int VPN_ERROR_CONNECTION_FAILED = 2;
     /** Error code to indicate the server is not known. */
     public static final int VPN_ERROR_UNKNOWN_SERVER = 3;
+    /** Error code to indicate an error from challenge response. */
+    public static final int VPN_ERROR_CHALLENGE = 4;
+    /** Error code to indicate an error of remote server hanging up. */
+    public static final int VPN_ERROR_REMOTE_HUNG_UP = 5;
     private static final int VPN_ERROR_NO_ERROR = 0;
 
     public static final String PROFILES_PATH = "/data/misc/vpn/profiles";