Merge "Tag stagefright development tools as "debug-only"."
diff --git a/api/current.xml b/api/current.xml
index 2729ff4..67c5dc2 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -211739,6 +211739,17 @@
 <parameter name="measureSpec" type="int">
 </parameter>
 </method>
+<method name="resume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="seekTo"
  return="void"
  abstract="false"
@@ -211852,6 +211863,17 @@
  visibility="public"
 >
 </method>
+<method name="suspend"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </class>
 <class name="ViewAnimator"
  extends="android.widget.FrameLayout"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 78f90a1..adec5a4 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -96,6 +96,7 @@
 
     run_command("NETWORK INTERFACES", 10, "netcfg", NULL);
     dump_file("NETWORK ROUTES", "/proc/net/route");
+    dump_file("ARP CACHE", "/proc/net/arp");
 
 #ifdef FWDUMP_bcm4329
     run_command("DUMP WIFI FIRMWARE LOG", 60,
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0355016..0756c71 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -77,9 +77,12 @@
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -460,6 +463,7 @@
                     mClassLoader =
                         ApplicationLoaders.getDefault().getClassLoader(
                             zip, mDataDir, mBaseClassLoader);
+                    initializeJavaContextClassLoader();
                 } else {
                     if (mBaseClassLoader == null) {
                         mClassLoader = ClassLoader.getSystemClassLoader();
@@ -471,6 +475,120 @@
             }
         }
 
+        /**
+         * Setup value for Thread.getContextClassLoader(). If the
+         * package will not run in in a VM with other packages, we set
+         * the Java context ClassLoader to the
+         * PackageInfo.getClassLoader value. However, if this VM can
+         * contain multiple packages, we intead set the Java context
+         * ClassLoader to a proxy that will warn about the use of Java
+         * context ClassLoaders and then fall through to use the
+         * system ClassLoader.
+         *
+         * <p> Note that this is similar to but not the same as the
+         * android.content.Context.getClassLoader(). While both
+         * context class loaders are typically set to the
+         * PathClassLoader used to load the package archive in the
+         * single application per VM case, a single Android process
+         * may contain several Contexts executing on one thread with
+         * their own logical ClassLoaders while the Java context
+         * ClassLoader is a thread local. This is why in the case when
+         * we have multiple packages per VM we do not set the Java
+         * context ClassLoader to an arbitrary but instead warn the
+         * user to set their own if we detect that they are using a
+         * Java library that expects it to be set.
+         */
+        private void initializeJavaContextClassLoader() {
+            IPackageManager pm = getPackageManager();
+            android.content.pm.PackageInfo pi;
+            try {
+                pi = pm.getPackageInfo(mPackageName, 0);
+            } catch (RemoteException e) {
+                throw new AssertionError(e);
+            }
+            /*
+             * Two possible indications that this package could be
+             * sharing its virtual machine with other packages:
+             *
+             * 1.) the sharedUserId attribute is set in the manifest,
+             *     indicating a request to share a VM with other
+             *     packages with the same sharedUserId.
+             *
+             * 2.) the application element of the manifest has an
+             *     attribute specifying a non-default process name,
+             *     indicating the desire to run in another packages VM.
+             */
+            boolean sharedUserIdSet = (pi.sharedUserId != null);
+            boolean processNameNotDefault =
+                (pi.applicationInfo != null &&
+                 !mPackageName.equals(pi.applicationInfo.processName));
+            boolean sharable = (sharedUserIdSet || processNameNotDefault);
+            ClassLoader contextClassLoader =
+                (sharable)
+                ? new WarningContextClassLoader()
+                : mClassLoader;
+            Thread.currentThread().setContextClassLoader(contextClassLoader);
+        }
+
+        private static class WarningContextClassLoader extends ClassLoader {
+
+            private static boolean warned = false;
+
+            private void warn(String methodName) {
+                if (warned) {
+                    return;
+                }
+                warned = true;
+                Thread.currentThread().setContextClassLoader(getParent());
+                Log.w(TAG, "ClassLoader." + methodName + ": " +
+                      "The class loader returned by " +
+                      "Thread.getContextClassLoader() may fail for processes " +
+                      "that host multiple applications. You should explicitly " +
+                      "specify a context class loader. For example: " +
+                      "Thread.setContextClassLoader(getClass().getClassLoader());");
+            }
+
+            @Override public URL getResource(String resName) {
+                warn("getResource");
+                return getParent().getResource(resName);
+            }
+
+            @Override public Enumeration<URL> getResources(String resName) throws IOException {
+                warn("getResources");
+                return getParent().getResources(resName);
+            }
+
+            @Override public InputStream getResourceAsStream(String resName) {
+                warn("getResourceAsStream");
+                return getParent().getResourceAsStream(resName);
+            }
+
+            @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
+                warn("loadClass");
+                return getParent().loadClass(className);
+            }
+
+            @Override public void setClassAssertionStatus(String cname, boolean enable) {
+                warn("setClassAssertionStatus");
+                getParent().setClassAssertionStatus(cname, enable);
+            }
+
+            @Override public void setPackageAssertionStatus(String pname, boolean enable) {
+                warn("setPackageAssertionStatus");
+                getParent().setPackageAssertionStatus(pname, enable);
+            }
+
+            @Override public void setDefaultAssertionStatus(boolean enable) {
+                warn("setDefaultAssertionStatus");
+                getParent().setDefaultAssertionStatus(enable);
+            }
+
+            @Override public void clearAssertionStatus() {
+                warn("clearAssertionStatus");
+                getParent().clearAssertionStatus();
+            }
+        }
+
         public String getAppDir() {
             return mAppDir;
         }
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
index 4bf59eb..07c08ff 100644
--- a/core/java/android/backup/BackupManager.java
+++ b/core/java/android/backup/BackupManager.java
@@ -47,9 +47,6 @@
 public class BackupManager {
     private static final String TAG = "BackupManager";
 
-    /** @hide TODO: REMOVE THIS */
-    public static final boolean EVEN_THINK_ABOUT_DOING_RESTORE = true;
-
     private Context mContext;
     private static IBackupManager sService;
 
@@ -78,9 +75,6 @@
      * {@link android.app.BackupAgent} subclass will be scheduled when you call this method.
      */
     public void dataChanged() {
-        if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
-            return;
-        }
         checkServiceBinder();
         if (sService != null) {
             try {
@@ -100,9 +94,6 @@
      * permission if the package named in the argument is not the caller's own.
      */
     public static void dataChanged(String packageName) {
-        if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
-            return;
-        }
         checkServiceBinder();
         if (sService != null) {
             try {
@@ -118,9 +109,6 @@
      * {@link android.backup.RestoreSession} class for documentation on that process.
      */
     public RestoreSession beginRestoreSession() {
-        if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
-            return null;
-        }
         RestoreSession session = null;
         checkServiceBinder();
         if (sService != null) {
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index 9aa23fe..915c5d7 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -45,10 +45,10 @@
     }
 
     private static void putAddress(StringBuffer buf, int addr) {
-        buf.append(addr  & 0xff).append('.').
-            append((addr >>>= 8) & 0xff).append('.').
-            append((addr >>>= 8) & 0xff).append('.').
-            append((addr >>>= 8) & 0xff);
+        buf.append((addr >> 24) & 0xff).append('.').
+            append((addr >> 16) & 0xff).append('.').
+            append((addr >> 8) & 0xff).append('.').
+            append(addr & 0xff);
     }
 
     /** Implement the Parcelable interface {@hide} */
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
index 5d09fb5..635323e 100644
--- a/core/java/android/pim/RecurrenceSet.java
+++ b/core/java/android/pim/RecurrenceSet.java
@@ -18,7 +18,6 @@
 
 import android.content.ContentValues;
 import android.database.Cursor;
-import android.os.Bundle;
 import android.provider.Calendar;
 import android.text.TextUtils;
 import android.text.format.Time;
@@ -26,6 +25,7 @@
 import android.util.Log;
 
 import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * Basic information about a recurrence, following RFC 2445 Section 4.8.5.
@@ -36,6 +36,7 @@
     private final static String TAG = "CalendarProvider";
 
     private final static String RULE_SEPARATOR = "\n";
+    private final static String FOLDING_SEPARATOR = "\n ";
 
     // TODO: make these final?
     public EventRecurrence[] rrules = null;
@@ -309,7 +310,8 @@
         String rdateStr = values.getAsString(Calendar.Events.RDATE);
         String exruleStr = values.getAsString(Calendar.Events.EXRULE);
         String exdateStr = values.getAsString(Calendar.Events.EXDATE);
-        boolean allDay = values.getAsInteger(Calendar.Events.ALL_DAY) == 1;
+        Integer allDayInteger = values.getAsInteger(Calendar.Events.ALL_DAY);
+        boolean allDay = (null != allDayInteger) ? (allDayInteger == 1) : false;
 
         if ((dtstart == -1) ||
             (TextUtils.isEmpty(duration))||
@@ -361,7 +363,7 @@
         if (TextUtils.isEmpty(ruleStr)) {
             return;
         }
-        String[] rrules = ruleStr.split(RULE_SEPARATOR);
+        String[] rrules = getRuleStrings(ruleStr);
         for (String rrule : rrules) {
             ICalendar.Property prop = new ICalendar.Property(propertyName);
             prop.setValue(rrule);
@@ -369,6 +371,52 @@
         }
     }
 
+    private static String[] getRuleStrings(String ruleStr) {
+        if (null == ruleStr) {
+            return new String[0];
+        }
+        String unfoldedRuleStr = unfold(ruleStr);
+        String[] split = unfoldedRuleStr.split(RULE_SEPARATOR);
+        int count = split.length;
+        for (int n = 0; n < count; n++) {
+            split[n] = fold(split[n]);
+        }
+        return split;
+    }
+
+
+    private static final Pattern IGNORABLE_ICAL_WHITESPACE_RE =
+            Pattern.compile("(?:\\r\\n?|\\n)[ \t]");
+
+    private static final Pattern FOLD_RE = Pattern.compile(".{75}");
+
+    /**
+    * fold and unfolds ical content lines as per RFC 2445 section 4.1.
+    *
+    * <h3>4.1 Content Lines</h3>
+    *
+    * <p>The iCalendar object is organized into individual lines of text, called
+    * content lines. Content lines are delimited by a line break, which is a CRLF
+    * sequence (US-ASCII decimal 13, followed by US-ASCII decimal 10).
+    *
+    * <p>Lines of text SHOULD NOT be longer than 75 octets, excluding the line
+    * break. Long content lines SHOULD be split into a multiple line
+    * representations using a line "folding" technique. That is, a long line can
+    * be split between any two characters by inserting a CRLF immediately
+    * followed by a single linear white space character (i.e., SPACE, US-ASCII
+    * decimal 32 or HTAB, US-ASCII decimal 9). Any sequence of CRLF followed
+    * immediately by a single linear white space character is ignored (i.e.,
+    * removed) when processing the content type.
+    */
+    public static String fold(String unfoldedIcalContent) {
+        return FOLD_RE.matcher(unfoldedIcalContent).replaceAll("$0\r\n ");
+    }
+
+    public static String unfold(String foldedIcalContent) {
+        return IGNORABLE_ICAL_WHITESPACE_RE.matcher(
+            foldedIcalContent).replaceAll("");
+    }
+
     private static void addPropertyForDateStr(ICalendar.Component component,
                                               String propertyName,
                                               String dateStr) {
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 2eb25954..194fe33 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -26,8 +26,6 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.pim.vcard.exception.VCardException;
-import android.provider.CallLog;
-import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.RawContacts;
@@ -44,8 +42,6 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.text.TextUtils;
-import android.text.format.Time;
 import android.util.CharsetUtils;
 import android.util.Log;
 
@@ -60,7 +56,6 @@
 import java.lang.reflect.Method;
 import java.nio.charset.UnsupportedCharsetException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -125,12 +120,6 @@
 
     public static final String VCARD_TYPE_STRING_DOCOMO = "docomo";
 
-    // Property for call log entry
-    private static final String VCARD_PROPERTY_X_TIMESTAMP = "X-IRMC-CALL-DATETIME";
-    private static final String VCARD_PROPERTY_CALLTYPE_INCOMING = "INCOMING";
-    private static final String VCARD_PROPERTY_CALLTYPE_OUTGOING = "OUTGOING";
-    private static final String VCARD_PROPERTY_CALLTYPE_MISSED = "MISSED";
-
     private static final String SHIFT_JIS = "SHIFT_JIS";
     private static final String UTF_8 = "UTF-8";
 
@@ -275,30 +264,14 @@
 
     private final String mCharsetString;
     private boolean mTerminateIsCalled;
-    final private List<OneEntryHandler> mHandlerList;
+    private final List<OneEntryHandler> mHandlerList;
 
     private String mErrorReason = NO_ERROR;
 
-    private boolean mIsCallLogComposer;
-
     private static final String[] sContactsProjection = new String[] {
         Contacts._ID,
     };
 
-    /** The projection to use when querying the call log table */
-    private static final String[] sCallLogProjection = new String[] {
-            Calls.NUMBER, Calls.DATE, Calls.TYPE, Calls.CACHED_NAME, Calls.CACHED_NUMBER_TYPE,
-            Calls.CACHED_NUMBER_LABEL
-    };
-    private static final int NUMBER_COLUMN_INDEX = 0;
-    private static final int DATE_COLUMN_INDEX = 1;
-    private static final int CALL_TYPE_COLUMN_INDEX = 2;
-    private static final int CALLER_NAME_COLUMN_INDEX = 3;
-    private static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 4;
-    private static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 5;
-
-    private static final String FLAG_TIMEZONE_UTC = "Z";
-
     public VCardComposer(Context context) {
         this(context, VCardConfig.VCARD_TYPE_DEFAULT, true);
     }
@@ -377,6 +350,7 @@
         if (contentUri == null) {
             return false;
         }
+
         if (mCareHandlerErrors) {
             List<OneEntryHandler> finishedList = new ArrayList<OneEntryHandler>(
                     mHandlerList.size());
@@ -396,10 +370,7 @@
         }
 
         final String[] projection;
-        if (CallLog.Calls.CONTENT_URI.equals(contentUri)) {
-            projection = sCallLogProjection;
-            mIsCallLogComposer = true;
-        } else if (Contacts.CONTENT_URI.equals(contentUri) ||
+        if (Contacts.CONTENT_URI.equals(contentUri) ||
                 CONTACTS_TEST_CONTENT_URI.equals(contentUri)) {
             projection = sContactsProjection;
         } else {
@@ -426,11 +397,7 @@
             return false;
         }
 
-        if (mIsCallLogComposer) {
-            mIdColumn = -1;
-        } else {
-            mIdColumn = mCursor.getColumnIndex(Contacts._ID);
-        }
+        mIdColumn = mCursor.getColumnIndex(Contacts._ID);
 
         return true;
     }
@@ -448,19 +415,14 @@
             mErrorReason = FAILURE_REASON_NOT_INITIALIZED;
             return false;
         }
-        String name = null;
         String vcard;
         try {
-            if (mIsCallLogComposer) {
-                vcard = createOneCallLogEntryInternal();
+            if (mIdColumn >= 0) {
+                vcard = createOneEntryInternal(mCursor.getString(mIdColumn),
+                        getEntityIteratorMethod);
             } else {
-                if (mIdColumn >= 0) {
-                    vcard = createOneEntryInternal(mCursor.getString(mIdColumn),
-                            getEntityIteratorMethod);
-                } else {
-                    Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn);
-                    return true;
-                }
+                Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn);
+                return true;
             }
         } catch (VCardException e) {
             Log.e(LOG_TAG, "VCardException has been thrown: " + e.getMessage());
@@ -468,7 +430,7 @@
         } catch (OutOfMemoryError error) {
             // Maybe some data (e.g. photo) is too big to have in memory. But it
             // should be rare.
-            Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry: " + name);
+            Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry.");
             System.gc();
             // TODO: should tell users what happened?
             return true;
@@ -630,99 +592,4 @@
     public String getErrorReason() {
         return mErrorReason;
     }
-
-    /**
-     * This static function is to compose vCard for phone own number
-     */
-    public String composeVCardForPhoneOwnNumber(int phonetype, String phoneName,
-            String phoneNumber, boolean vcardVer21) {
-        final int vcardType = (vcardVer21 ?
-                VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8 :
-                    VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8);
-        final VCardBuilder builder = new VCardBuilder(vcardType);
-        boolean needCharset = false;
-        if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) {
-            needCharset = true;
-        }
-        builder.appendLine(VCardConstants.PROPERTY_FN, phoneName, needCharset, false);
-        builder.appendLine(VCardConstants.PROPERTY_N, phoneName, needCharset, false);
-
-        if (!TextUtils.isEmpty(phoneNumber)) {
-            String label = Integer.toString(phonetype);
-            builder.appendTelLine(phonetype, label, phoneNumber, false);
-        }
-
-        return builder.toString();
-    }
-
-    /**
-     * Format according to RFC 2445 DATETIME type.
-     * The format is: ("%Y%m%dT%H%M%SZ").
-     */
-    private final String toRfc2455Format(final long millSecs) {
-        Time startDate = new Time();
-        startDate.set(millSecs);
-        String date = startDate.format2445();
-        return date + FLAG_TIMEZONE_UTC;
-    }
-
-    /**
-     * Try to append the property line for a call history time stamp field if possible.
-     * Do nothing if the call log type gotton from the database is invalid.
-     */
-    private void tryAppendCallHistoryTimeStampField(final VCardBuilder builder) {
-        // Extension for call history as defined in
-        // in the Specification for Ic Mobile Communcation - ver 1.1,
-        // Oct 2000. This is used to send the details of the call
-        // history - missed, incoming, outgoing along with date and time
-        // to the requesting device (For example, transferring phone book
-        // when connected over bluetooth)
-        //
-        // e.g. "X-IRMC-CALL-DATETIME;MISSED:20050320T100000Z"
-        final int callLogType = mCursor.getInt(CALL_TYPE_COLUMN_INDEX);
-        final String callLogTypeStr;
-        switch (callLogType) {
-            case Calls.INCOMING_TYPE: {
-                callLogTypeStr = VCARD_PROPERTY_CALLTYPE_INCOMING;
-                break;
-            }
-            case Calls.OUTGOING_TYPE: {
-                callLogTypeStr = VCARD_PROPERTY_CALLTYPE_OUTGOING;
-                break;
-            }
-            case Calls.MISSED_TYPE: {
-                callLogTypeStr = VCARD_PROPERTY_CALLTYPE_MISSED;
-                break;
-            }
-            default: {
-                Log.w(LOG_TAG, "Call log type not correct.");
-                return;
-            }
-        }
-
-        final long dateAsLong = mCursor.getLong(DATE_COLUMN_INDEX);
-        builder.appendLine(VCARD_PROPERTY_X_TIMESTAMP,
-                Arrays.asList(callLogTypeStr), toRfc2455Format(dateAsLong));
-    }
-
-    private String createOneCallLogEntryInternal() {
-        final VCardBuilder builder = new VCardBuilder(VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
-        String name = mCursor.getString(CALLER_NAME_COLUMN_INDEX);
-        if (TextUtils.isEmpty(name)) {
-            name = mCursor.getString(NUMBER_COLUMN_INDEX);
-        }
-        final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
-        builder.appendLine(VCardConstants.PROPERTY_FN, name, needCharset, false);
-        builder.appendLine(VCardConstants.PROPERTY_N, name, needCharset, false);
-
-        final String number = mCursor.getString(NUMBER_COLUMN_INDEX);
-        final int type = mCursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
-        String label = mCursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
-        if (TextUtils.isEmpty(label)) {
-            label = Integer.toString(type);
-        }
-        builder.appendTelLine(type, label, number, false);
-        tryAppendCallHistoryTimeStampField(builder);
-        return builder.toString();
-    }
 }
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 2eebe77..caa3144 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -16,20 +16,14 @@
 
 package android.server.search;
 
-import android.app.ActivityManagerNative;
-import android.app.IActivityWatcher;
+import com.android.internal.content.PackageMonitor;
+
 import android.app.ISearchManager;
-import android.app.ISearchManagerCallback;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
 import android.util.Log;
 
 import java.util.List;
@@ -42,13 +36,11 @@
 
     // general debugging support
     private static final String TAG = "SearchManagerService";
-    private static final boolean DBG = false;
 
     // Context that the service is running in.
     private final Context mContext;
 
-    // This field is initialized in ensureSearchablesCreated(), and then never modified.
-    // Only accessed by ensureSearchablesCreated() and getSearchables()
+    // This field is initialized lazily in getSearchables(), and then never modified.
     private Searchables mSearchables;
 
     /**
@@ -61,58 +53,28 @@
         mContext = context;
     }
 
-    private synchronized void ensureSearchablesCreated() {
-        if (mSearchables != null) return;  // already created
-
-        mSearchables = new Searchables(mContext);
-        mSearchables.buildSearchableList();
-
-        IntentFilter packageFilter = new IntentFilter();
-        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        packageFilter.addDataScheme("package");
-        mContext.registerReceiver(mPackageChangedReceiver, packageFilter);
-        // Register for events related to sdcard installation.
-        IntentFilter sdFilter = new IntentFilter();
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
-        mContext.registerReceiver(mPackageChangedReceiver, sdFilter);
-    }
-
     private synchronized Searchables getSearchables() {
-        ensureSearchablesCreated();
+        if (mSearchables == null) {
+            mSearchables = new Searchables(mContext);
+            mSearchables.buildSearchableList();
+            new MyPackageMonitor().register(mContext, true);
+        }
         return mSearchables;
     }
 
     /**
      * Refreshes the "searchables" list when packages are added/removed.
      */
-    private BroadcastReceiver mPackageChangedReceiver = new BroadcastReceiver() {
+    class MyPackageMonitor extends PackageMonitor {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-
-            if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
-                    Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
-                    Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
-                    Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action) ||
-                    Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
-                if (DBG) Log.d(TAG, "Got " + action);
-                // Update list of searchable activities
-                getSearchables().buildSearchableList();
-                broadcastSearchablesChanged();
-            }
+        public void onSomePackagesChanged() {
+            // Update list of searchable activities
+            getSearchables().buildSearchableList();
+            // Inform all listeners that the list of searchables has been updated.
+            Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            mContext.sendBroadcast(intent);
         }
-    };
-
-    /**
-     * Informs all listeners that the list of searchables has been updated.
-     */
-    void broadcastSearchablesChanged() {
-        Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
-        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        mContext.sendBroadcast(intent);
     }
 
     //
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6c89f92..6de9c65 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -1012,12 +1012,12 @@
         int extra;
 
         if (needMultiply) {
-            // XXX: this looks like it is using the +0.5 and the cast to int
-            // to do rounding, but this I expect this isn't doing the intended
-            // thing when spacingmult < 1.  An intended extra of, say, -1.2
-            // will get 'rounded' to -.7 and then truncated to 0.
-            extra = (int) ((below - above) * (spacingmult - 1)
-                           + spacingadd + 0.5);
+            double ex = (below - above) * (spacingmult - 1) + spacingadd;
+            if (ex >= 0) {
+                extra = (int)(ex + 0.5);
+            } else {
+                extra = -(int)(-ex + 0.5);
+            }
         } else {
             extra = 0;
         }
diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java
index cdcb662..df7d0c4 100644
--- a/core/java/android/webkit/PluginManager.java
+++ b/core/java/android/webkit/PluginManager.java
@@ -165,6 +165,7 @@
                     continue;
                 }
 
+/*              temporarily disable signatures checking
                 // check to ensure the plugin is properly signed
                 Signature signatures[] = pkgInfo.signatures;
                 if (signatures == null) {
@@ -184,7 +185,7 @@
                         continue;
                     }
                 }
-
+*/
                 // determine the type of plugin from the manifest
                 if (serviceInfo.metaData == null) {
                     Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no type defined");
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 906bca1..c2517a8 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -62,6 +62,8 @@
     private static final int STATE_PLAYING            = 3;
     private static final int STATE_PAUSED             = 4;
     private static final int STATE_PLAYBACK_COMPLETED = 5;
+    private static final int STATE_SUSPEND            = 6;
+    private static final int STATE_RESUME             = 7;
 
     // mCurrentState is a VideoView object's current state.
     // mTargetState is the state that a method caller intends to reach.
@@ -87,6 +89,7 @@
     private boolean     mCanPause;
     private boolean     mCanSeekBack;
     private boolean     mCanSeekForward;
+    private int         mStateWhenSuspended;  //state before calling suspend()
 
     public VideoView(Context context) {
         super(context);
@@ -466,7 +469,14 @@
         public void surfaceCreated(SurfaceHolder holder)
         {
             mSurfaceHolder = holder;
-            openVideo();
+            //resume() was called before surfaceCreated()
+            if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND
+                   && mTargetState == STATE_RESUME) {
+                mMediaPlayer.setDisplay(mSurfaceHolder);
+                resume();
+            } else {
+                openVideo();
+            }
         }
 
         public void surfaceDestroyed(SurfaceHolder holder)
@@ -474,7 +484,6 @@
             // after we return from this we can't use the surface any more
             mSurfaceHolder = null;
             if (mMediaController != null) mMediaController.hide();
-            release(true);
         }
     };
 
@@ -567,7 +576,36 @@
         mTargetState = STATE_PAUSED;
     }
 
-    // cache duration as mDuration for faster access
+    public void suspend() {
+        if (isInPlaybackState()) {
+            if (mMediaPlayer.suspend()) {
+                mStateWhenSuspended = mCurrentState;
+                mCurrentState = STATE_SUSPEND;
+                mTargetState = STATE_SUSPEND;
+            } else {
+                Log.w(TAG, "Unable to suspend video");
+                mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+            }
+        }
+    }
+
+    public void resume() {
+        if (mSurfaceHolder == null && mCurrentState == STATE_SUSPEND){
+            mTargetState = STATE_RESUME;
+            return;
+        }
+        if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND) {
+            if (mMediaPlayer.resume()) {
+                mCurrentState = mStateWhenSuspended;
+                mTargetState = mStateWhenSuspended;
+            } else {
+                Log.w(TAG, "Unable to resume video");
+                mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+            }
+        }
+    }
+
+   // cache duration as mDuration for faster access
     public int getDuration() {
         if (isInPlaybackState()) {
             if (mDuration > 0) {
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index a82a21e..5afa0342 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1466,19 +1466,25 @@
     for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
         value = bag->map.value;
         jstring str = NULL;
-        
+
         // Take care of resolving the found resource to its final value.
         ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
         if (value.dataType == Res_value::TYPE_STRING) {
-            const char16_t* str16 = res.getTableStringBlock(block)->stringAt(value.data, &strLen);
-            str = env->NewString(str16, strLen);
-            if (str == NULL) {
-                doThrow(env, "java/lang/OutOfMemoryError");
-                res.unlockBag(startOfBag);
-                return NULL;
+            const ResStringPool* pool = res.getTableStringBlock(block);
+            const char* str8 = pool->string8At(value.data, &strLen);
+            if (str8 != NULL) {
+                str = env->NewStringUTF(str8);
+            } else {
+                const char16_t* str16 = pool->stringAt(value.data, &strLen);
+                str = env->NewString(str16, strLen);
+                if (str == NULL) {
+                    doThrow(env, "java/lang/OutOfMemoryError");
+                    res.unlockBag(startOfBag);
+                    return NULL;
+                }
             }
         }
-        
+
         env->SetObjectArrayElement(array, i, str);
     }
     res.unlockBag(startOfBag);
diff --git a/core/jni/android_util_StringBlock.cpp b/core/jni/android_util_StringBlock.cpp
index ffb271c..641fbce 100644
--- a/core/jni/android_util_StringBlock.cpp
+++ b/core/jni/android_util_StringBlock.cpp
@@ -89,6 +89,11 @@
     }
 
     size_t len;
+    const char* str8 = osb->string8At(idx, &len);
+    if (str8 != NULL) {
+        return env->NewStringUTF(str8);
+    }
+
     const char16_t* str = osb->stringAt(idx, &len);
     if (str == NULL) {
         doThrow(env, "java/lang/IndexOutOfBoundsException");
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_first.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_first.9.png
deleted file mode 100644
index af80855..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_first.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_last.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_last.9.png
deleted file mode 100644
index dc47275..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_last.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_middle.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_middle.9.png
deleted file mode 100644
index 007f279..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_middle.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinnerbox_arrow_single.9.png b/core/res/res/drawable-hdpi/spinnerbox_arrow_single.9.png
deleted file mode 100644
index 24592a3..0000000
--- a/core/res/res/drawable-hdpi/spinnerbox_arrow_single.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_first.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_first.9.png
deleted file mode 100644
index d8e268d..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_first.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_last.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_last.9.png
deleted file mode 100644
index 087e650..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_last.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_middle.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_middle.9.png
deleted file mode 100644
index f1f2ff5..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_middle.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinnerbox_arrow_single.9.png b/core/res/res/drawable-mdpi/spinnerbox_arrow_single.9.png
deleted file mode 100644
index f537b3b..0000000
--- a/core/res/res/drawable-mdpi/spinnerbox_arrow_single.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/spinnerbox_arrows.xml b/core/res/res/drawable/spinnerbox_arrows.xml
deleted file mode 100644
index 276a0f0..0000000
--- a/core/res/res/drawable/spinnerbox_arrows.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/res/drawable/spinnerbox_arrows.xml
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_single="true" android:drawable="@drawable/spinnerbox_arrow_single" />
-    <item android:state_first="true" android:drawable="@drawable/spinnerbox_arrow_first" />
-    <item android:state_last="true" android:drawable="@drawable/spinnerbox_arrow_last" />
-    <item android:state_middle="true" android:drawable="@drawable/spinnerbox_arrow_middle" />
-    <item android:state_pressed="true" android:drawable="@drawable/spinnerbox_arrow_single" />
-</selector>
diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml
index a0cd11d..30138a7 100644
--- a/core/res/res/layout/status_bar_expanded.xml
+++ b/core/res/res/layout/status_bar_expanded.xml
@@ -20,9 +20,9 @@
 
 <com.android.server.status.ExpandedView xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
-    android:background="@drawable/status_bar_background"
     android:focusable="true"
-    android:descendantFocusability="afterDescendants">
+    android:descendantFocusability="afterDescendants"
+    >
 
     <LinearLayout
         android:layout_width="match_parent"
@@ -79,19 +79,18 @@
     <FrameLayout
         android:layout_width="match_parent" 
         android:layout_height="wrap_content"
+        android:layout_weight="1"
         >
         <ScrollView
             android:id="@+id/scroll"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
+            android:layout_height="match_parent"
             android:fadingEdge="none"
             >
             <com.android.server.status.NotificationLinearLayout
                 android:id="@+id/notificationLinearLayout"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_weight="1"
                 android:orientation="vertical"
                 >
                 
@@ -136,7 +135,7 @@
 
         <ImageView
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
+            android:layout_height="match_parent"
             android:src="@drawable/title_bar_shadow"
             android:scaleType="fitXY"
         />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f1501ae..5d2d272 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -779,18 +779,18 @@
         applications can use this to read phone owner data.</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_readCalendar">read calendar data</string>
+    <string name="permlab_readCalendar">read calendar events</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_readCalendar">Allows an application to read all
         of the calendar events stored on your phone. Malicious applications
         can use this to send your calendar events to other people.</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_writeCalendar">write calendar data</string>
+    <string name="permlab_writeCalendar">add or modify calendar events and send email to guests</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_writeCalendar">Allows an application to modify the
-        calendar events stored on your phone. Malicious
-        applications can use this to erase or modify your calendar data.</string>
+    <string name="permdesc_writeCalendar">Allows an application to add or change the 
+        events on your calendar, which may send email to guests. Malicious applications can use this 
+	to erase or modify your calendar events or to send email to guests.</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_accessMockLocation">mock location sources for testing</string>
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index 1e4db3d..7511ec1 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -213,13 +213,13 @@
         }
 
         public int scale(float height) {
-            int altVal = (int)(height * sMult + sAdd + 0.5); // existing impl
+            int altVal = (int)(height * sMult + sAdd + 0.5);
             int rndVal = Math.round(height * sMult + sAdd);
             if (altVal != rndVal) {
                 Log.i("Scale", "expected scale: " + rndVal +
                         " != returned scale: " + altVal);
             }
-            return altVal; // existing implementation
+            return rndVal;
         }
     }
 
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 13ea27e..cd657e8 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -447,6 +447,8 @@
     }
     const char16_t* stringAt(size_t idx, size_t* outLen) const;
 
+    const char* string8At(size_t idx, size_t* outLen) const;
+
     const ResStringPool_span* styleAt(const ResStringPool_ref& ref) const;
     const ResStringPool_span* styleAt(size_t idx) const;
 
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index 096aa73..42b6508 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -295,13 +295,31 @@
     if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
         newDevice = hwOutputDesc->device();
     }
+
+    // when changing from ring tone to in call mode, mute the ringing tone
+    // immediately and delay the route change to avoid sending the ring tone
+    // tail into the earpiece or headset.
+    int delayMs = 0;
+    if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
+        // delay the device change command by twice the output latency to have some margin
+        // and be sure that audio buffers not yet affected by the mute are out when
+        // we actually apply the route change
+        delayMs = hwOutputDesc->mLatency*2;
+        setStreamMute(AudioSystem::RING, true, mHardwareOutput);
+    }
+
     // change routing is necessary
-    setOutputDevice(mHardwareOutput, newDevice, force);
+    setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
 
     // if entering in call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
     if (state == AudioSystem::MODE_IN_CALL) {
         LOGV("setPhoneState() in call state management: new state is %d", state);
+        // unmute the ringing tone after a sufficient delay if it was muted before
+        // setting output device above
+        if (oldState == AudioSystem::MODE_RINGTONE) {
+            setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
+        }
         for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
             handleIncallSonification(stream, true, true);
         }
@@ -1207,10 +1225,10 @@
         return INVALID_OPERATION;
     }
 
-    // mute media during 2 seconds to avoid outputing sound on hardware output while music stream
+    // mute media strategy to avoid outputting sound on hardware output while music stream
     // is switched from A2DP output and before music is paused by music application
     setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
-    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, 2000);
+    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
 
     if (!a2dpUsedForSonification()) {
         // unmute music on A2DP output if a notification or ringtone is playing
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index e8bd5cf..38600b9 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -497,6 +497,34 @@
     return NULL;
 }
 
+const char* ResStringPool::string8At(size_t idx, size_t* outLen) const
+{
+    if (mError == NO_ERROR && idx < mHeader->stringCount) {
+        const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
+        const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
+        if (off < (mStringPoolSize-1)) {
+            if (isUTF8) {
+                const uint8_t* strings = (uint8_t*)mStrings;
+                const uint8_t* str = strings+off;
+                DECODE_LENGTH(str, sizeof(uint8_t), *outLen)
+                size_t encLen;
+                DECODE_LENGTH(str, sizeof(uint8_t), encLen)
+                if ((uint32_t)(str+encLen-strings) < mStringPoolSize) {
+                    return (const char*)str;
+                } else {
+                    LOGW("Bad string block: string #%d extends to %d, past end at %d\n",
+                            (int)idx, (int)(str+encLen-strings), (int)mStringPoolSize);
+                }
+            }
+        } else {
+            LOGW("Bad string block: string #%d entry is at %d, past end at %d\n",
+                    (int)idx, (int)(off*sizeof(uint16_t)),
+                    (int)(mStringPoolSize*sizeof(uint16_t)));
+        }
+    }
+    return NULL;
+}
+
 const ResStringPool_span* ResStringPool::styleAt(const ResStringPool_ref& ref) const
 {
     return styleAt(ref.index);
@@ -4018,14 +4046,19 @@
         printf("(attribute) 0x%08x\n", value.data);
     } else if (value.dataType == Res_value::TYPE_STRING) {
         size_t len;
-        const char16_t* str = pkg->header->values.stringAt(
+        const char* str8 = pkg->header->values.string8At(
                 value.data, &len);
-        if (str == NULL) {
-            printf("(string) null\n");
+        if (str8 != NULL) {
+            printf("(string8) \"%s\"\n", str8);
         } else {
-            printf("(string%d) \"%s\"\n",
-                    pkg->header->values.isUTF8()?8:16,
-                    String8(str, len).string());
+            const char16_t* str16 = pkg->header->values.stringAt(
+                    value.data, &len);
+            if (str16 != NULL) {
+                printf("(string16) \"%s\"\n",
+                    String8(str16, len).string());
+            } else {
+                printf("(string) null\n");
+            }
         } 
     } else if (value.dataType == Res_value::TYPE_FLOAT) {
         printf("(float) %g\n", *(const float*)&value.data);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
index 717f7ba..d7cf069 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
@@ -1,28 +1,35 @@
 package com.android.mediaframeworktest;
 
 import android.media.MediaRecorder;
+import android.media.EncoderCapabilities;
+import android.media.EncoderCapabilities.VideoEncoderCap;
+import android.media.EncoderCapabilities.AudioEncoderCap;
+import android.media.DecoderCapabilities;
+import android.media.DecoderCapabilities.VideoDecoder;
+import android.media.DecoderCapabilities.AudioDecoder;
+
 import android.os.SystemProperties;
+import java.util.List;
 import java.util.HashMap;
 
-public class MediaProfileReader {
+public class MediaProfileReader
+{
+    private static final List<VideoDecoder> videoDecoders = DecoderCapabilities.getVideoDecoders();
+    private static final List<AudioDecoder> audioDecoders = DecoderCapabilities.getAudioDecoders();
+    private static final List<VideoEncoderCap> videoEncoders = EncoderCapabilities.getVideoEncoders();
+    private static final List<AudioEncoderCap> audioEncoders = EncoderCapabilities.getAudioEncoders();
+    private static final HashMap<Integer, String> encoderMap = new HashMap<Integer, String>();
 
-    public static final HashMap<String, Integer>
-    OUTPUT_FORMAT_TABLE = new HashMap<String, Integer>();
-    public static String MEDIA_ENC_VID = "ro.media.enc.vid.";
-    public static String MEDIA_AUD_VID = "ro.media.enc.aud.";
-    public static String[] VIDEO_ENCODER_PROPERTY = {".width", ".height", ".bps", ".fps",};
-    public static String[] AUDIO_ENCODER_PROPERTY = {".bps", ".hz", ".ch",};
+    static {
+        initEncoderMap();
+    };
 
-    public static String getVideoCodecProperty() {
-        String s;
-        s = SystemProperties.get("ro.media.enc.vid.codec");
-        return s;
+    public static List<VideoEncoderCap> getVideoEncoders() {
+        return videoEncoders;
     }
 
-    public static String getAudioCodecProperty() {
-        String s;
-        s = SystemProperties.get("ro.media.enc.aud.codec");
-        return s;
+    public static List<AudioEncoderCap> getAudioEncoders() {
+        return audioEncoders;
     }
 
     public static String getDeviceType() {
@@ -33,78 +40,56 @@
     }
 
     public static boolean getWMAEnable() {
-        // push all the property into one big table
-        int wmaEnable = 1;
-        wmaEnable = SystemProperties.getInt("ro.media.dec.aud.wma.enabled",
-                wmaEnable);
-        if (wmaEnable == 1) {
-            return true;
-        } else {
-            return false;
+        for (AudioDecoder decoder: audioDecoders) {
+            if (decoder == AudioDecoder.AUDIO_DECODER_WMA) {
+                return true;
+            }
         }
+        return false;
     }
 
     public static boolean getWMVEnable(){
-        int wmvEnable = 1;
-        wmvEnable = SystemProperties.getInt("ro.media.dec.vid.wmv.enabled",
-                wmvEnable);
-        if (wmvEnable == 1) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    public static void createVideoProfileTable() {
-        // push all the property into one big table
-        String encoderType = getVideoCodecProperty();
-        if (encoderType.length() != 0) {
-            String encoder[] = encoderType.split(",");
-            for (int i = 0; i < encoder.length; i++) {
-                for (int j = 0; j < VIDEO_ENCODER_PROPERTY.length; j++) {
-                    String propertyName = MEDIA_ENC_VID + encoder[i] + VIDEO_ENCODER_PROPERTY[j];
-                    String prop = SystemProperties.get(propertyName);
-                    // push to the table
-                    String propRange[] = prop.split(",");
-                    OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_low"),
-                            Integer.parseInt(propRange[0]));
-                    OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_high"),
-                            Integer.parseInt(propRange[1]));
-                }
-
+        for (VideoDecoder decoder: videoDecoders) {
+            if (decoder == VideoDecoder.VIDEO_DECODER_WMV) {
+                return true;
             }
         }
+        return false;
     }
 
-    public static void createAudioProfileTable() {
-        // push all the property into one big table
-        String audioType = getAudioCodecProperty();
-        String encoder[] = audioType.split(",");
-        if (audioType.length() != 0) {
-            for (int i = 0; i < encoder.length; i++) {
-                for (int j = 0; j < AUDIO_ENCODER_PROPERTY.length; j++) {
-                    String propertyName = MEDIA_AUD_VID + encoder[i] + AUDIO_ENCODER_PROPERTY[j];
-                    String prop = SystemProperties.get(propertyName);
-                    // push to the table
-                    String propRange[] = prop.split(",");
-                    OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_low"),
-                            Integer.parseInt(propRange[0]));
-                    OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_high"),
-                            Integer.parseInt(propRange[1]));
-                }
-            }
+    public static String getVideoCodecName(int videoEncoder) {
+        if (videoEncoder != MediaRecorder.VideoEncoder.H263 &&
+            videoEncoder != MediaRecorder.VideoEncoder.H264 &&
+            videoEncoder != MediaRecorder.VideoEncoder.MPEG_4_SP) {
+            throw new IllegalArgumentException("Unsupported video encoder " + videoEncoder);
         }
+        return encoderMap.get(videoEncoder);
     }
 
-    public static void createEncoderTable(){
-        OUTPUT_FORMAT_TABLE.put("h263", MediaRecorder.VideoEncoder.H263);
-        OUTPUT_FORMAT_TABLE.put("h264", MediaRecorder.VideoEncoder.H264);
-        OUTPUT_FORMAT_TABLE.put("m4v", MediaRecorder.VideoEncoder.MPEG_4_SP);
-        OUTPUT_FORMAT_TABLE.put("amrnb", MediaRecorder.AudioEncoder.AMR_NB);
-        OUTPUT_FORMAT_TABLE.put("amrwb", MediaRecorder.AudioEncoder.AMR_WB);
-        OUTPUT_FORMAT_TABLE.put("aac", MediaRecorder.AudioEncoder.AAC);
-        OUTPUT_FORMAT_TABLE.put("aacplus", MediaRecorder.AudioEncoder.AAC_PLUS);
-        OUTPUT_FORMAT_TABLE.put("eaacplus",
-                MediaRecorder.AudioEncoder.EAAC_PLUS);
+    public static String getAudioCodecName(int audioEncoder) {
+        if (audioEncoder != MediaRecorder.AudioEncoder.AMR_NB &&
+            audioEncoder != MediaRecorder.AudioEncoder.AMR_WB &&
+            audioEncoder != MediaRecorder.AudioEncoder.AAC &&
+            audioEncoder != MediaRecorder.AudioEncoder.AAC_PLUS &&
+            audioEncoder != MediaRecorder.AudioEncoder.EAAC_PLUS) {
+            throw new IllegalArgumentException("Unsupported audio encodeer " + audioEncoder);
+        }
+        return encoderMap.get(audioEncoder);
+    }
+
+    private MediaProfileReader() {} // Don't call me
+
+    private static void initEncoderMap() {
+        // video encoders
+        encoderMap.put(MediaRecorder.VideoEncoder.H263, "h263");
+        encoderMap.put(MediaRecorder.VideoEncoder.H264, "h264");
+        encoderMap.put(MediaRecorder.VideoEncoder.MPEG_4_SP, "m4v");
+
+        // audio encoders
+        encoderMap.put(MediaRecorder.AudioEncoder.AMR_NB, "amrnb");
+        encoderMap.put(MediaRecorder.AudioEncoder.AMR_WB, "amrwb");
+        encoderMap.put(MediaRecorder.AudioEncoder.AAC, "aac");
+        encoderMap.put(MediaRecorder.AudioEncoder.AAC_PLUS, "aacplus");
+        encoderMap.put(MediaRecorder.AudioEncoder.EAAC_PLUS, "eaacplus");
     }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index fdc5970..39caccd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -25,6 +25,9 @@
 import android.hardware.Camera;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
+import android.media.EncoderCapabilities;
+import android.media.EncoderCapabilities.VideoEncoderCap;
+import android.media.EncoderCapabilities.AudioEncoderCap;
 import android.test.ActivityInstrumentationTestCase;
 import android.util.Log;
 import android.view.SurfaceHolder;
@@ -33,6 +36,7 @@
 
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.Suppress;
+import java.util.List;
 
 
 /**
@@ -99,31 +103,29 @@
         }
     }
     
-    private boolean recordVideoWithPara(String encoder, String audio, String quality){
+    private boolean recordVideoWithPara(VideoEncoderCap videoCap, AudioEncoderCap audioCap, boolean highQuality){
         boolean recordSuccess = false;
-        int videoEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder);
-        int audioEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio);
-        int videoWidth = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".width_" + quality);
-        int videoHeight =
-                MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".height_" + quality);
-        int videoFps = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".fps_" + quality);
-        int videoBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".bps_" + quality);
-        int audioBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".bps_" + quality);
-        int audioChannels = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".ch_" + quality);
-        int audioSamplingRate =
-                MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".hz_" + quality);
+        int videoEncoder = videoCap.mCodec;
+        int audioEncoder = audioCap.mCodec;
+        int videoWidth = highQuality? videoCap.mMaxFrameWidth: videoCap.mMinFrameWidth;
+        int videoHeight = highQuality? videoCap.mMaxFrameHeight: videoCap.mMinFrameHeight;
+        int videoFps = highQuality? videoCap.mMaxFrameRate: videoCap.mMinFrameRate;
+        int videoBitrate = highQuality? videoCap.mMaxBitRate: videoCap.mMinBitRate;
+        int audioBitrate = highQuality? audioCap.mMaxBitRate: audioCap.mMinBitRate;
+        int audioChannels = highQuality? audioCap.mMaxChannels: audioCap.mMinChannels ;
+        int audioSamplingRate = highQuality? audioCap.mMaxSampleRate: audioCap.mMinSampleRate;
 
         if (videoFps < MIN_VIDEO_FPS) {
             videoFps = MIN_VIDEO_FPS;
         }
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
-        String filename = ("/sdcard/" + encoder + "_" + audio + "_" + quality + ".3gp");
+        String filename = ("/sdcard/" + videoEncoder + "_" + audioEncoder + "_" + highQuality + ".3gp");
         try {
             Log.v(TAG, "video encoder :" + videoEncoder);
             Log.v(TAG, "audio encoder :" + audioEncoder);
-            Log.v(TAG, "quality : " + quality);
-            Log.v(TAG, "encoder : " + encoder);
-            Log.v(TAG, "audio : " + audio);
+            Log.v(TAG, "quality : " + (highQuality?"high": "low"));
+            Log.v(TAG, "encoder : " + MediaProfileReader.getVideoCodecName(videoEncoder));
+            Log.v(TAG, "audio : " + MediaProfileReader.getAudioCodecName(audioEncoder));
             Log.v(TAG, "videoWidth : " + videoWidth);
             Log.v(TAG, "videoHeight : " + videoHeight);
             Log.v(TAG, "videoFPS : " + videoFps);
@@ -434,35 +436,26 @@
         boolean recordSuccess = false;
         String deviceType = MediaProfileReader.getDeviceType();
         Log.v(TAG, "deviceType = " + deviceType);
-        // Test cases are device specified
-        MediaProfileReader.createVideoProfileTable();
-        MediaProfileReader.createAudioProfileTable();
-        MediaProfileReader.createEncoderTable();
-        String encoderType = MediaProfileReader.getVideoCodecProperty();
-        String audioType = MediaProfileReader.getAudioCodecProperty();
-        if ((encoderType.length() != 0) || (audioType.length() != 0)) {
-            String audio[] = audioType.split(",");
-            String encoder[] = encoderType.split(",");
-            for (int k = 0; k < 2; k++) {
-                for (int i = 0; i < encoder.length; i++) {
-                    for (int j = 0; j < audio.length; j++) {
-                        if (k == 0) {
-                            recordSuccess = recordVideoWithPara(encoder[i], audio[j], "high");
-                        } else {
-                            recordSuccess = recordVideoWithPara(encoder[i], audio[j], "low");
-                        }
-                        if (!recordSuccess) {
-                            Log.v(TAG, "testDeviceSpecificCodec failed");
-                            Log.v(TAG, "Encoder = " + encoder[i] + "Audio Encoder = " + audio[j]);
-                            noOfFailure++;
-                        }
-                        // assertTrue((encoder[i] + audio[j]), recordSuccess);
+        List<VideoEncoderCap> videoEncoders = MediaProfileReader.getVideoEncoders();
+        List<AudioEncoderCap> audioEncoders = MediaProfileReader.getAudioEncoders();
+        for (int k = 0; k < 2; k++) {
+            for (VideoEncoderCap videoEncoder: videoEncoders) {
+                for (AudioEncoderCap audioEncoder: audioEncoders) {
+                    if (k == 0) {
+                        recordSuccess = recordVideoWithPara(videoEncoder, audioEncoder, true);
+                    } else {
+                        recordSuccess = recordVideoWithPara(videoEncoder, audioEncoder, false);
+                    }
+                    if (!recordSuccess) {
+                        Log.v(TAG, "testDeviceSpecificCodec failed");
+                        Log.v(TAG, "Encoder = " + videoEncoder.mCodec + "Audio Encoder = " + audioEncoder.mCodec);
+                        noOfFailure++;
                     }
                 }
             }
-            if (noOfFailure != 0) {
-                assertTrue("testDeviceSpecificCodec", false);
-            }
+        }
+        if (noOfFailure != 0) {
+            assertTrue("testDeviceSpecificCodec", false);
         }
     }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
index 8750098..4c259f1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
@@ -39,9 +39,8 @@
     public static void testAlbumArt() throws Exception {
         Log.v(TAG, "testAlbumArt starts.");
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        MediaProfileReader reader = new MediaProfileReader();
-        boolean supportWMA = reader.getWMAEnable();
-        boolean supportWMV = reader.getWMVEnable();
+        boolean supportWMA = MediaProfileReader.getWMAEnable();
+        boolean supportWMV = MediaProfileReader.getWMVEnable();
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) {
             try {
@@ -74,9 +73,8 @@
     @LargeTest
     public static void testThumbnailCapture() throws Exception {
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        MediaProfileReader reader = new MediaProfileReader();
-        boolean supportWMA = reader.getWMAEnable();
-        boolean supportWMV = reader.getWMVEnable();
+        boolean supportWMA = MediaProfileReader.getWMAEnable();
+        boolean supportWMV = MediaProfileReader.getWMVEnable();
         Log.v(TAG, "Thumbnail processing starts");
         long startedAt = System.currentTimeMillis();
         for(int i = 0, n = MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length; i < n; ++i) {
@@ -110,9 +108,8 @@
     
     @LargeTest
     public static void testMetadataRetrieval() throws Exception {
-        MediaProfileReader reader = new MediaProfileReader();
-        boolean supportWMA = reader.getWMAEnable();
-        boolean supportWMV = reader.getWMVEnable();
+        boolean supportWMA = MediaProfileReader.getWMAEnable();
+        boolean supportWMV = MediaProfileReader.getWMVEnable();
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) {
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 654ca32..a5a518b 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -61,12 +61,12 @@
     <!-- user interface sound effects -->
     <integer name="def_power_sounds_enabled">1</integer>
     <string name="def_low_battery_sound">/system/media/ui/LowBattery.ogg</string>
-    <integer name="def_dock_sounds_enabled">1</integer>
-    <string name="def_desk_dock_sound">/system/media/audio/ui/dock.ogg</string>
-    <string name="def_desk_undock_sound">/system/media/audio/ui/undock.ogg</string>
+    <integer name="def_dock_sounds_enabled">0</integer>
+    <string name="def_desk_dock_sound">/system/media/audio/ui/Dock.ogg</string>
+    <string name="def_desk_undock_sound">/system/media/audio/ui/Undock.ogg</string>
     <string name="def_car_dock_sound">/system/media/audio/ui/Dock.ogg</string>
     <string name="def_car_undock_sound">/system/media/audio/ui/Undock.ogg</string>
-    <integer name="def_lockscreen_sounds_enabled">1</integer>
+    <integer name="def_lockscreen_sounds_enabled">0</integer>
     <string name="def_lock_sound">/system/media/audio/ui/Lock.ogg</string>
     <string name="def_unlock_sound">/system/media/audio/ui/Unlock.ogg</string>
 
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 958d089..7c555e2 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -256,14 +256,14 @@
             Log.e(TAG, "Failed to parse netmask", uhe);
             cfg.netmask = 0;
         }
-        cfg.interfaceFlags = st.nextToken("]");
+        cfg.interfaceFlags = st.nextToken("]").trim() +"]";
         Log.d(TAG, String.format("flags <%s>", cfg.interfaceFlags));
         return cfg;
     }
 
     public void setInterfaceConfig(
             String iface, InterfaceConfiguration cfg) throws IllegalStateException {
-        String cmd = String.format("interface setcfg %s %s %s", iface,
+        String cmd = String.format("interface setcfg %s %s %s %s", iface,
                 intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags);
         mConnector.doCommand(cmd);
     }
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 1d20074..10d6e3a 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -27,6 +27,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.InterfaceConfiguration;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.NetworkInfo;
@@ -56,6 +57,7 @@
  *
  * TODO - look for parent classes and code sharing
  */
+
 public class Tethering extends INetworkManagementEventObserver.Stub {
 
     private Notification mTetheringNotification;
@@ -80,6 +82,10 @@
 
     private String mUpstreamIfaceName;
 
+    // turning on/off RNDIS resets the interface generating and extra discon/conn cycle
+    // count how many to ignore..  Self correcting if you plug/unplug a bunch of times.
+    private int mUsbResetExpected = 0;
+
     HierarchicalStateMachine mTetherMasterSM;
 
     public Tethering(Context context) {
@@ -113,7 +119,7 @@
                 com.android.internal.R.array.config_tether_dhcp_range);
         if (mDhcpRange.length == 0) {
             mDhcpRange = new String[2];
-            mDhcpRange[0] = new String("169.254.2.1");
+            mDhcpRange[0] = new String("169.254.2.2");
             mDhcpRange[1] = new String("169.254.2.64");
         } else if(mDhcpRange.length == 1) {
             String[] tmp = new String[2];
@@ -127,16 +133,6 @@
         mTetherableWifiRegexs = context.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_wifi_regexs);
 
-        String[] ifaces = new String[0];
-        try {
-            ifaces = service.listInterfaces();
-        } catch (Exception e) {
-            Log.e(TAG, "Error listing Interfaces :" + e);
-        }
-        for (String iface : ifaces) {
-            interfaceAdded(iface);
-        }
-
         // TODO - remove and rely on real notifications of the current iface
         mDnsServers = new String[2];
         mDnsServers[0] = "8.8.8.8";
@@ -147,6 +143,7 @@
     public void interfaceLinkStatusChanged(String iface, boolean link) {
         Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
         boolean found = false;
+        boolean usb = false;
         for (String regex : mTetherableWifiRegexs) {
             if (iface.matches(regex)) {
                 found = true;
@@ -156,6 +153,7 @@
         for (String regex: mTetherableUsbRegexs) {
             if (iface.matches(regex)) {
                 found = true;
+                usb = true;
                 break;
             }
         }
@@ -165,7 +163,7 @@
             TetherInterfaceSM sm = mIfaces.get(iface);
             if (link) {
                 if (sm == null) {
-                    sm = new TetherInterfaceSM(iface);
+                    sm = new TetherInterfaceSM(iface, usb);
                     mIfaces.put(iface, sm);
                     sm.start();
                 }
@@ -179,7 +177,10 @@
     }
 
     public void interfaceAdded(String iface) {
+        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
         boolean found = false;
+        boolean usb = false;
         for (String regex : mTetherableWifiRegexs) {
             if (iface.matches(regex)) {
                 found = true;
@@ -189,6 +190,7 @@
         for (String regex : mTetherableUsbRegexs) {
             if (iface.matches(regex)) {
                 found = true;
+                usb = true;
                 break;
             }
         }
@@ -196,13 +198,14 @@
             Log.d(TAG, iface + " is not a tetherable iface, ignoring");
             return;
         }
+
         synchronized (mIfaces) {
             TetherInterfaceSM sm = mIfaces.get(iface);
             if (sm != null) {
                 Log.e(TAG, "active iface (" + iface + ") reported as added, ignoring");
                 return;
             }
-            sm = new TetherInterfaceSM(iface);
+            sm = new TetherInterfaceSM(iface, usb);
             mIfaces.put(iface, sm);
             sm.start();
         }
@@ -314,8 +317,8 @@
         if (tellUser) {
             for (Object o : availableList) {
                 String s = (String)o;
-                for (Object matchObject : mTetherableUsbRegexs) {
-                    if (s.matches((String)matchObject)) {
+                for (String match : mTetherableUsbRegexs) {
+                    if (s.matches(match)) {
                         showTetherAvailableNotification();
                         return;
                     }
@@ -414,20 +417,32 @@
         }
     }
 
-
-
-
     private class StateReceiver extends BroadcastReceiver {
         public void onReceive(Context content, Intent intent) {
             String action = intent.getAction();
             if (action.equals(Intent.ACTION_UMS_CONNECTED)) {
-                Tethering.this.handleTtyConnect();
+                Log.w(TAG, "got UMS connected");
+                synchronized (Tethering.this) {
+                    if(mUsbResetExpected != 0) {
+                        Log.w(TAG, "mUsbResetExpected == " + mUsbResetExpected + ", ignored");
+                        mUsbResetExpected--;
+                        return;
+                    }
+                }
+                Tethering.this.toggleUsbIfaces(true); // add them
             } else if (action.equals(Intent.ACTION_UMS_DISCONNECTED)) {
-                Tethering.this.handleTtyDisconnect();
+                Log.w(TAG, "got UMS disconneded broadcast");
+                synchronized (Tethering.this) {
+                    if(mUsbResetExpected != 0) {
+                        Log.w(TAG, "mUsbResetExpected == " + mUsbResetExpected + ", ignored");
+                        mUsbResetExpected--;
+                        return;
+                    }
+                }
+                Tethering.this.toggleUsbIfaces(false); // remove them
             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-                IConnectivityManager service =
-                        IConnectivityManager.Stub.asInterface(b);
+                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
                 try {
                     NetworkInfo info = service.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_DUN);
                     int msg;
@@ -442,6 +457,114 @@
         }
     }
 
+    // used on cable insert/remove
+    private void toggleUsbIfaces(boolean add) {
+        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+        String[] ifaces = new String[0];
+        try {
+            ifaces = service.listInterfaces();
+        } catch (Exception e) {
+            Log.e(TAG, "Error listing Interfaces :" + e);
+            return;
+        }
+        for (String iface : ifaces) {
+            for (String regex : mTetherableUsbRegexs) {
+                if (iface.matches(regex)) {
+                    if (add) {
+                        interfaceAdded(iface);
+                    } else {
+                        interfaceRemoved(iface);
+                    }
+                }
+            }
+        }
+    }
+
+    // toggled when we enter/leave the fully teathered state
+    private boolean enableRndisUsb(boolean enabled) {
+        Log.d(TAG, "enableRndisUsb(" + enabled + ")");
+        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+                INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+
+        try {
+            if (enabled) {
+                // turning this on will reset USB and generate two bogus events - ignore them
+                synchronized (this) {
+                    if (!service.isUsbRNDISStarted()) {
+                        mUsbResetExpected += 2;
+                        service.startUsbRNDIS();
+                    }
+                }
+            } else {
+                if (service.isUsbRNDISStarted()) {
+                    service.stopUsbRNDIS();
+                }
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error toggling usb RNDIS :" + e);
+            return false;
+        }
+        return true;
+    }
+
+    // configured when we start tethering and unconfig'd on error or conclusion
+    private boolean configureUsb(boolean enabled) {
+        Log.d(TAG, "configureUsb(" + enabled + ")");
+
+        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+
+        // bring toggle the interfaces
+        String[] ifaces = new String[0];
+        try {
+            ifaces = service.listInterfaces();
+        } catch (Exception e) {
+            Log.e(TAG, "Error listing Interfaces :" + e);
+            return false;
+        }
+        for (String iface : ifaces) {
+            for (String regex : mTetherableUsbRegexs) {
+                if (iface.matches(regex)) {
+                    InterfaceConfiguration ifcg = null;
+                    try {
+                        ifcg = service.getInterfaceConfig(iface);
+                        if (ifcg != null) {
+                            ifcg.ipAddr = (169 << 24) + (254 << 16) + (2 << 8) + 1;
+                            ifcg.netmask = (255 << 24) + (255 << 16) + (255 << 8) + 0;
+                            if (enabled) {
+                                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
+                            } else {
+                                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
+                            }
+                            service.setInterfaceConfig(iface, ifcg);
+                        }
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
+                        return false;
+                    }
+                }
+            }
+        }
+
+        if (!enabled) {
+            // turn off ndis
+            try {
+                synchronized (this) {
+                    if (service.isUsbRNDISStarted()) {
+                        mUsbResetExpected += 2;
+                        service.stopUsbRNDIS();
+                    }
+                }
+            } catch (Exception e) {
+                Log.e(TAG, "Error stopping usb RNDIS :" + e);
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     private void handleTtyConnect() {
         Log.d(TAG, "handleTtyConnect");
         // for each of the available Tty not already supported by a ppp session,
@@ -609,6 +732,7 @@
         private HierarchicalState mUntetherInterfaceErrorState;
         private HierarchicalState mEnableNatErrorState;
         private HierarchicalState mDisableNatErrorState;
+        private HierarchicalState mUsbConfigurationErrorState;
 
         private HierarchicalState mUnavailableState;
 
@@ -617,10 +741,12 @@
         private boolean mTethered;
 
         String mIfaceName;
+        boolean mUsb;
 
-        TetherInterfaceSM(String name) {
+        TetherInterfaceSM(String name, boolean usb) {
             super(name);
             mIfaceName = name;
+            mUsb = usb;
 
             mInitialState = new InitialState();
             addState(mInitialState);
@@ -638,6 +764,8 @@
             addState(mEnableNatErrorState);
             mDisableNatErrorState = new DisableNatErrorState();
             addState(mDisableNatErrorState);
+            mUsbConfigurationErrorState = new UsbConfigurationErrorState();
+            addState(mUsbConfigurationErrorState);
             mUnavailableState = new UnavailableState();
             addState(mUnavailableState);
 
@@ -656,6 +784,7 @@
             if (current == mUntetherInterfaceErrorState) res += "UntetherInterfaceErrorState";
             if (current == mEnableNatErrorState) res += "EnableNatErrorState";
             if (current == mDisableNatErrorState) res += "DisableNatErrorState";
+            if (current == mUsbConfigurationErrorState) res += "UsbConfigurationErrorState";
             if (current == mUnavailableState) res += "UnavailableState";
             if (mAvailable) res += " - Available";
             if (mTethered) res += " - Tethered";
@@ -686,8 +815,15 @@
             return mErrored;
         }
 
-        private synchronized void setErrored(boolean errored) {
-            mErrored = errored;
+        private void setErrored(boolean errored) {
+            synchronized (this) {
+                mErrored = errored;
+            }
+            if (errored && mUsb) {
+                // note everything's been unwound by this point so nothing to do on
+                // further error..
+                Tethering.this.configureUsb(false);
+            }
         }
 
         class InitialState extends HierarchicalState {
@@ -726,6 +862,19 @@
             @Override
             public void enter() {
                 setAvailable(false);
+                if (mUsb) {
+                    if (!Tethering.this.configureUsb(true)) {
+                        Message m = mTetherMasterSM.obtainMessage(
+                                TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
+                        m.obj = TetherInterfaceSM.this;
+                        mTetherMasterSM.sendMessage(m);
+
+                        m = obtainMessage(CMD_TRANSITION_TO_ERROR);
+                        m.obj = mUsbConfigurationErrorState;
+                        sendMessageAtFrontOfQueue(m);
+                        return;
+                    }
+                }
                 sendTetherStateChangedBroadcast();
             }
             @Override
@@ -739,6 +888,12 @@
                                 TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
                         m.obj = TetherInterfaceSM.this;
                         mTetherMasterSM.sendMessage(m);
+                        if (mUsb) {
+                            if (!Tethering.this.configureUsb(false)) {
+                                transitionTo(mUsbConfigurationErrorState);
+                                break;
+                            }
+                        }
                         transitionTo(mInitialState);
                         break;
                     case CMD_TETHER_MODE_ALIVE:
@@ -759,6 +914,10 @@
                         mTetherMasterSM.sendMessage(m);
                         transitionTo(mUnavailableState);
                         break;
+                   case CMD_TRANSITION_TO_ERROR:
+                       HierarchicalState s = (HierarchicalState)(message.obj);
+                       transitionTo(s);
+                       break;
                     default:
                         retValue = false;
                 }
@@ -788,12 +947,17 @@
                     sendMessageAtFrontOfQueue(m);
                     return;
                 }
+                if (mUsb) Tethering.this.enableRndisUsb(true);
                 Log.d(TAG, "Tethered " + mIfaceName);
                 setAvailable(false);
                 setTethered(true);
                 sendTetherStateChangedBroadcast();
             }
             @Override
+            public void exit() {
+                if(mUsb) Tethering.this.enableRndisUsb(false);
+            }
+            @Override
             public boolean processMessage(Message message) {
                 Log.d(TAG, "TetheredState.processMessage what=" + message.what);
                 boolean retValue = true;
@@ -821,7 +985,15 @@
                         m.obj = TetherInterfaceSM.this;
                         mTetherMasterSM.sendMessage(m);
                         if (message.what == CMD_TETHER_UNREQUESTED) {
-                            transitionTo(mInitialState);
+                            if (mUsb) {
+                                if (!Tethering.this.configureUsb(false)) {
+                                    transitionTo(mUsbConfigurationErrorState);
+                                } else {
+                                    transitionTo(mInitialState);
+                                }
+                            } else {
+                                transitionTo(mInitialState);
+                            }
                         } else if (message.what == CMD_INTERFACE_DOWN) {
                             transitionTo(mUnavailableState);
                         }
@@ -857,6 +1029,12 @@
                         }
                         Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
                         sendTetherStateChangedBroadcast();
+                        if (mUsb) {
+                            if (!Tethering.this.configureUsb(false)) {
+                                transitionTo(mUsbConfigurationErrorState);
+                                break;
+                            }
+                        }
                         transitionTo(mInitialState);
                         break;
                     case CMD_TRANSITION_TO_ERROR:
@@ -974,6 +1152,15 @@
                 sendTetherStateChangedBroadcast();
             }
         }
+
+        class UsbConfigurationErrorState extends ErrorState {
+            @Override
+            public void enter() {
+                Log.e(TAG, "Error trying to configure USB " + mIfaceName);
+                setAvailable(false);
+                setErrored(true);
+            }
+        }
     }
 
     class TetherMasterSM extends HierarchicalStateMachine {
@@ -1179,6 +1366,7 @@
         class CellDunAliveState extends HierarchicalState {
             @Override
             public void enter() {
+                Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms");
                 sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
             }
 
@@ -1228,6 +1416,8 @@
                         transitionTo(mInitialState);
                         break;
                     case CMD_CELL_DUN_RENEW:
+                        Log.d(TAG, "renewing dun connection - requeuing for another " +
+                                CELL_DUN_RENEW_MS + "ms");
                         b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                         IConnectivityManager cservice = IConnectivityManager.Stub.asInterface(b);
                         try {
@@ -1248,6 +1438,8 @@
         class TetherModeAliveState extends HierarchicalState {
             @Override
             public void enter() {
+                Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms");
+                sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
                 for (Object o : mNotifyList) {
                     TetherInterfaceSM sm = (TetherInterfaceSM)o;
                     sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_TETHER_MODE_ALIVE));
@@ -1298,6 +1490,18 @@
                         }
                         transitionTo(mInitialState);
                         break;
+                    case CMD_CELL_DUN_RENEW:
+                        Log.d(TAG, "renewing dun connection - requeuing for another " +
+                                CELL_DUN_RENEW_MS + "ms");
+                        b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+                        IConnectivityManager cservice = IConnectivityManager.Stub.asInterface(b);
+                        try {
+                            cservice.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
+                                    Phone.FEATURE_ENABLE_DUN, new Binder());
+                        } catch (Exception e) {
+                        }
+                        sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
+                        break;
                     default:
                        retValue = false;
                        break;
diff --git a/services/java/com/android/server/status/ExpandedView.java b/services/java/com/android/server/status/ExpandedView.java
index d0f14cb..33ac8c1 100644
--- a/services/java/com/android/server/status/ExpandedView.java
+++ b/services/java/com/android/server/status/ExpandedView.java
@@ -11,17 +11,11 @@
 
 
 public class ExpandedView extends LinearLayout {
-    final Display mDisplay;
     StatusBarService mService;
-    boolean mTracking;
-    int mStartX, mStartY;
-    int mMaxHeight = 0;
     int mPrevHeight = -1;
 
     public ExpandedView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mDisplay = ((WindowManager)context.getSystemService(
-                Context.WINDOW_SERVICE)).getDefaultDisplay();
     }
 
     @Override
@@ -36,12 +30,6 @@
     }
 
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec,
-                MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.AT_MOST));
-    }
-
-    @Override
      protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
          super.onLayout(changed, left, top, right, bottom);
          int height = bottom - top;
@@ -51,11 +39,4 @@
              mService.updateExpandedViewPos(StatusBarService.EXPANDED_LEAVE_ALONE);
          }
      }
-
-    void setMaxHeight(int h) {
-        if (h != mMaxHeight) {
-            mMaxHeight = h;
-            requestLayout();
-        }
-    }
 }
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 493bd93..3f77291 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -187,8 +187,9 @@
     TextView mSpnLabel;
     TextView mPlmnLabel;
     TextView mClearButton;
+    View mExpandedContents;
     CloseDragHandle mCloseView;
-    int[] mCloseLocation = new int[2];
+    int[] mPositionTmp = new int[2];
     boolean mExpanded;
     boolean mExpandedVisible;
 
@@ -198,7 +199,7 @@
     // the tracker view
     TrackingView mTrackingView;
     WindowManager.LayoutParams mTrackingParams;
-    int mTrackingPosition;
+    int mTrackingPosition; // the position of the top of the tracking view.
 
     // ticker
     private Ticker mTicker;
@@ -274,6 +275,7 @@
 
         mExpandedDialog = new ExpandedDialog(context);
         mExpandedView = expanded;
+        mExpandedContents = expanded.findViewById(R.id.notificationLinearLayout);
         mOngoingTitle = (TextView)expanded.findViewById(R.id.ongoingTitle);
         mOngoingItems = (LinearLayout)expanded.findViewById(R.id.ongoingItems);
         mLatestTitle = (TextView)expanded.findViewById(R.id.latestTitle);
@@ -1530,20 +1532,11 @@
 
         /// ---------- Expanded View --------------
         pixelFormat = PixelFormat.TRANSLUCENT;
-        bg = mExpandedView.getBackground();
-        if (bg != null) {
-            pixelFormat = bg.getOpacity();
-            if (pixelFormat != PixelFormat.TRANSLUCENT) {
-                // we want good-looking gradients, so we force a 8-bits per
-                // pixel format.
-                pixelFormat = PixelFormat.RGBX_8888;
-            }
-        }
 
         final int disph = mDisplay.getHeight();
         lp = mExpandedDialog.getWindow().getAttributes();
         lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
-        lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        lp.height = getExpandedHeight();
         lp.x = 0;
         mTrackingPosition = lp.y = -disph; // sufficiently large negative
         lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
@@ -1562,10 +1555,10 @@
         mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
         mExpandedDialog.setContentView(mExpandedView,
                 new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
-                                           ViewGroup.LayoutParams.WRAP_CONTENT));
+                                           ViewGroup.LayoutParams.MATCH_PARENT));
+        mExpandedDialog.getWindow().setBackgroundDrawable(null);
         mExpandedDialog.show();
         FrameLayout hack = (FrameLayout)mExpandedView.getParent();
-        hack.setForeground(null);
     }
 
     void setDateViewVisibility(boolean visible, int anim) {
@@ -1630,11 +1623,15 @@
         mTrackingParams.height = disph-h;
         WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
 
-        mCloseView.getLocationInWindow(mCloseLocation);
-
         if (mExpandedParams != null) {
+            mCloseView.getLocationInWindow(mPositionTmp);
+            final int closePos = mPositionTmp[1];
+
+            mExpandedContents.getLocationInWindow(mPositionTmp);
+            final int contentsBottom = mPositionTmp[1] + mExpandedContents.getHeight();
+
             mExpandedParams.y = pos + mTrackingView.getHeight()
-                    - (mTrackingParams.height-mCloseLocation[1]) - mExpandedView.getHeight();
+                    - (mTrackingParams.height-closePos) - contentsBottom;
             int max = h;
             if (mExpandedParams.y > max) {
                 mExpandedParams.y = max;
@@ -1644,13 +1641,13 @@
                 mExpandedParams.y = min;
             }
 
-            /*
-            Log.d(TAG, "mTrackingPosition=" + mTrackingPosition
-                    + " mTrackingView.height=" + mTrackingView.getHeight()
-                    + " diff=" + (mTrackingPosition + mTrackingView.getHeight())
-                    + " h=" + h);
-            */
-            panelSlightlyVisible((mTrackingPosition + mTrackingView.getHeight()) > h);
+            boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
+            if (!visible) {
+                // if the contents aren't visible, move the expanded view way off screen
+                // because the window itself extends below the content view.
+                mExpandedParams.y = -disph;
+            }
+            panelSlightlyVisible(visible);
             mExpandedDialog.getWindow().setAttributes(mExpandedParams);
         }
 
@@ -1658,16 +1655,19 @@
             Log.d(TAG, "updateExpandedViewPos after  expandedPosition=" + expandedPosition
                     + " mTrackingParams.y=" + mTrackingParams.y
                     + " mTrackingPosition=" + mTrackingPosition
-                    + " mExpandedParams.y=" + mExpandedParams.y);
+                    + " mExpandedParams.y=" + mExpandedParams.y
+                    + " mExpandedParams.height=" + mExpandedParams.height);
         }
     }
 
-    void updateAvailableHeight() {
+    int getExpandedHeight() {
+        return mDisplay.getHeight() - mStatusBarView.getHeight() - mCloseView.getHeight();
+    }
+
+    void updateExpandedHeight() {
         if (mExpandedView != null) {
-            int disph = mDisplay.getHeight();
-            int h = mStatusBarView.getHeight();
-            int max = disph - (mCloseView.getHeight() + h);
-            mExpandedView.setMaxHeight(max);
+            mExpandedParams.height = getExpandedHeight();
+            mExpandedDialog.getWindow().setAttributes(mExpandedParams);
         }
     }
 
diff --git a/services/java/com/android/server/status/TrackingView.java b/services/java/com/android/server/status/TrackingView.java
index 722d10c..886d66d 100644
--- a/services/java/com/android/server/status/TrackingView.java
+++ b/services/java/com/android/server/status/TrackingView.java
@@ -23,7 +23,7 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        mService.updateAvailableHeight();
+        mService.updateExpandedHeight();
     }
 
     @Override
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 52c8b1f..cab7b81 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -440,10 +440,11 @@
             return Phone.APN_REQUEST_FAILED;
         }
 
-        if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+        if (DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
                 + isApnTypeActive(type) + " and state = " + state);
 
         if (!isApnTypeAvailable(type)) {
+            if (DBG) Log.d(LOG_TAG, "type not available");
             return Phone.APN_TYPE_NOT_AVAILABLE;
         }
 
diff --git a/tests/CoreTests/android/core/MiscRegressionTest.java b/tests/CoreTests/android/core/MiscRegressionTest.java
index 8fe064c..8281db0 100644
--- a/tests/CoreTests/android/core/MiscRegressionTest.java
+++ b/tests/CoreTests/android/core/MiscRegressionTest.java
@@ -110,6 +110,16 @@
         Logger.global.finest("This has logging Level.FINEST, should become VERBOSE");
     }
 
+    // Regression test for Issue 5697:
+    // getContextClassLoader returns a non-application classloader
+    // http://code.google.com/p/android/issues/detail?id=5697
+    //
+    @MediumTest
+    public void testJavaContextClassLoader() throws Exception {
+        Assert.assertNotNull("Must hava a Java context ClassLoader",
+                             Thread.currentThread().getContextClassLoader());
+    }
+
     // Regression test for #1045939: Different output for Method.toString()
     @SmallTest
     public void testMethodToString() {
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 51afc0a..a09cec0 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -25,8 +25,12 @@
     const size_t NS = pool->size();
     for (size_t s=0; s<NS; s++) {
         size_t len;
-        printf("String #%ld: %s\n", s,
-                String8(pool->stringAt(s, &len)).string());
+        const char *str = (const char*)pool->string8At(s, &len);
+        if (str == NULL) {
+            str = String8(pool->stringAt(s, &len)).string();
+        }
+
+        printf("String #%ld: %s\n", s, str);
     }
 }
 
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index afaed24..810e4d2 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -943,7 +943,7 @@
                         } else {
                             newDetailedState = DetailedState.FAILED;
                         }
-                        handleDisconnectedState(newDetailedState);
+                        handleDisconnectedState(newDetailedState, true);
                         /**
                          * If we were associated with a network (networkId != -1),
                          * assume we reached this state because of a failed attempt
@@ -965,7 +965,7 @@
                     } else if (newState == SupplicantState.DISCONNECTED) {
                         mHaveIpAddress = false;
                         if (isDriverStopped() || mDisconnectExpected) {
-                            handleDisconnectedState(DetailedState.DISCONNECTED);
+                            handleDisconnectedState(DetailedState.DISCONNECTED, true);
                         } else {
                             scheduleDisconnect();
                         }
@@ -1072,16 +1072,10 @@
                      */
                     if (wasDisconnectPending) {
                         DetailedState saveState = getNetworkInfo().getDetailedState();
-                        handleDisconnectedState(DetailedState.DISCONNECTED);
+                        handleDisconnectedState(DetailedState.DISCONNECTED, false);
                         setDetailedStateInternal(saveState);
-                    } else {
-                        /**
-                         *  stop DHCP to ensure there is a new IP address
-                         *  even if the supplicant transitions without disconnect
-                         *  COMPLETED -> ASSOCIATED -> COMPLETED
-                         */
-                        resetConnections(false);
                     }
+
                     configureInterface();
                     mLastBssid = result.BSSID;
                     mLastSsid = mWifiInfo.getSSID();
@@ -1116,7 +1110,7 @@
             
             case EVENT_DEFERRED_DISCONNECT:
                 if (mWifiInfo.getSupplicantState() != SupplicantState.UNINITIALIZED) {
-                    handleDisconnectedState(DetailedState.DISCONNECTED);
+                    handleDisconnectedState(DetailedState.DISCONNECTED, true);
                 }
                 break;
 
@@ -1284,13 +1278,15 @@
      * Reset our IP state and send out broadcasts following a disconnect.
      * @param newState the {@code DetailedState} to set. Should be either
      * {@code DISCONNECTED} or {@code FAILED}.
+     * @param disableInterface indicates whether the interface should
+     * be disabled
      */
-    private void handleDisconnectedState(DetailedState newState) {
+    private void handleDisconnectedState(DetailedState newState, boolean disableInterface) {
         if (mDisconnectPending) {
             cancelDisconnect();
         }
         mDisconnectExpected = false;
-        resetConnections(true);
+        resetConnections(disableInterface);
         setDetailedState(newState);
         sendNetworkStateChangeBroadcast(mLastBssid);
         mWifiInfo.setBSSID(null);