Merge "Bug 5156756 Fix AAC ADTS header size computation"
diff --git a/api/current.txt b/api/current.txt
index 334df2f..dfc17ba 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -370,6 +370,7 @@
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
     field public static final int direction = 16843217; // 0x10101d1
+    field public static final int directionDescriptions = 16843695; // 0x10103af
     field public static final int directionPriority = 16843218; // 0x10101d2
     field public static final int disableDependentsState = 16843249; // 0x10101f1
     field public static final int disabledAlpha = 16842803; // 0x1010033
@@ -938,6 +939,7 @@
     field public static final int tag = 16842961; // 0x10100d1
     field public static final int targetActivity = 16843266; // 0x1010202
     field public static final int targetClass = 16842799; // 0x101002f
+    field public static final int targetDescriptions = 16843694; // 0x10103ae
     field public static final int targetDrawables = 16843654; // 0x1010386
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetSdkVersion = 16843376; // 0x1010270
@@ -1610,6 +1612,7 @@
     field public static final int TextAppearance_StatusBar_EventContent_Title = 16973928; // 0x1030068
     field public static final int TextAppearance_StatusBar_Icon = 16973926; // 0x1030066
     field public static final int TextAppearance_StatusBar_Title = 16973925; // 0x1030065
+    field public static final int TextAppearance_SuggestionHighlight = 16974104; // 0x1030118
     field public static final int TextAppearance_Theme = 16973888; // 0x1030040
     field public static final int TextAppearance_Theme_Dialog = 16973896; // 0x1030048
     field public static final int TextAppearance_Widget = 16973897; // 0x1030049
@@ -3276,6 +3279,7 @@
     method public void setArguments(android.os.Bundle);
     method public void setHasOptionsMenu(boolean);
     method public void setInitialSavedState(android.app.Fragment.SavedState);
+    method public void setMenuVisibility(boolean);
     method public void setRetainInstance(boolean);
     method public void setTargetFragment(android.app.Fragment, int);
     method public void startActivity(android.content.Intent);
@@ -3341,6 +3345,7 @@
     method public abstract java.lang.CharSequence getBreadCrumbTitle();
     method public abstract int getBreadCrumbTitleRes();
     method public abstract int getId();
+    method public abstract java.lang.String getName();
   }
 
   public static abstract interface FragmentManager.OnBackStackChangedListener {
@@ -4039,6 +4044,7 @@
 
   public abstract class BackupAgent extends android.content.ContextWrapper {
     ctor public BackupAgent();
+    method public final void fullBackupFile(java.io.File, android.app.backup.FullBackupDataOutput);
     method public abstract void onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) throws java.io.IOException;
     method public void onCreate();
     method public void onDestroy();
@@ -16713,6 +16719,7 @@
     field public static final java.lang.String ACCOUNT_TYPE = "account_type";
     field public static final java.lang.String COMMENTS = "comments";
     field public static final java.lang.String CONTACT_ID = "contact_id";
+    field public static final java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
     field public static final java.lang.String DATA_SET = "data_set";
     field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
     field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 1271ddd..0e3eaaa 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4206,7 +4206,6 @@
             fragment.mContainerId = containerId;
             fragment.mTag = tag;
             fragment.mInLayout = true;
-            fragment.mImmediateActivity = this;
             fragment.mFragmentManager = mFragments;
             fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
             mFragments.addFragment(fragment, true);
@@ -4222,7 +4221,6 @@
             // This fragment was retained from a previous instance; get it
             // going now.
             fragment.mInLayout = true;
-            fragment.mImmediateActivity = this;
             // If this fragment is newly instantiated (either right now, or
             // from last saved state), then give it the attributes to
             // initialize itself.
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 93330a7..e9e8e16 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -344,10 +344,6 @@
     }
 
     private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
-        if (fragment.mImmediateActivity != null) {
-            throw new IllegalStateException("Fragment already added: " + fragment);
-        }
-        fragment.mImmediateActivity = mManager.mActivity;
         fragment.mFragmentManager = mManager;
 
         if (tag != null) {
@@ -388,11 +384,6 @@
     }
 
     public FragmentTransaction remove(Fragment fragment) {
-        if (fragment.mImmediateActivity == null) {
-            throw new IllegalStateException("Fragment not added: " + fragment);
-        }
-        fragment.mImmediateActivity = null;
-
         Op op = new Op();
         op.cmd = OP_REMOVE;
         op.fragment = fragment;
@@ -402,10 +393,6 @@
     }
 
     public FragmentTransaction hide(Fragment fragment) {
-        if (fragment.mImmediateActivity == null) {
-            throw new IllegalStateException("Fragment not added: " + fragment);
-        }
-
         Op op = new Op();
         op.cmd = OP_HIDE;
         op.fragment = fragment;
@@ -415,10 +402,6 @@
     }
 
     public FragmentTransaction show(Fragment fragment) {
-        if (fragment.mImmediateActivity == null) {
-            throw new IllegalStateException("Fragment not added: " + fragment);
-        }
-
         Op op = new Op();
         op.cmd = OP_SHOW;
         op.fragment = fragment;
@@ -428,10 +411,6 @@
     }
 
     public FragmentTransaction detach(Fragment fragment) {
-        //if (fragment.mImmediateActivity == null) {
-        //    throw new IllegalStateException("Fragment not added: " + fragment);
-        //}
-
         Op op = new Op();
         op.cmd = OP_DETACH;
         op.fragment = fragment;
@@ -441,10 +420,6 @@
     }
 
     public FragmentTransaction attach(Fragment fragment) {
-        //if (fragment.mImmediateActivity == null) {
-        //    throw new IllegalStateException("Fragment not added: " + fragment);
-        //}
-
         Op op = new Op();
         op.cmd = OP_ATTACH;
         op.fragment = fragment;
@@ -663,7 +638,6 @@
                 case OP_ADD: {
                     Fragment f = op.fragment;
                     f.mNextAnim = op.popExitAnim;
-                    f.mImmediateActivity = null;
                     mManager.removeFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition),
                             mTransitionStyle);
@@ -671,7 +645,6 @@
                 case OP_REPLACE: {
                     Fragment f = op.fragment;
                     f.mNextAnim = op.popExitAnim;
-                    f.mImmediateActivity = null;
                     mManager.removeFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition),
                             mTransitionStyle);
@@ -679,7 +652,6 @@
                         for (int i=0; i<op.removed.size(); i++) {
                             Fragment old = op.removed.get(i);
                             old.mNextAnim = op.popEnterAnim;
-                            f.mImmediateActivity = mManager.mActivity;
                             mManager.addFragment(old, false);
                         }
                     }
@@ -687,7 +659,6 @@
                 case OP_REMOVE: {
                     Fragment f = op.fragment;
                     f.mNextAnim = op.popEnterAnim;
-                    f.mImmediateActivity = mManager.mActivity;
                     mManager.addFragment(f, false);
                 } break;
                 case OP_HIDE: {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index a8621f8..3a08e6d 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -402,10 +402,6 @@
     // from all transactions.
     FragmentManager mFragmentManager;
 
-    // Set as soon as a fragment is added to a transaction (or removed),
-    // to be able to do validation.
-    Activity mImmediateActivity;
-    
     // Activity this fragment is attached to.
     Activity mActivity;
     
@@ -438,7 +434,10 @@
     
     // If set this fragment has menu items to contribute.
     boolean mHasMenu;
-    
+
+    // Set to true to allow the fragment's menu to be shown.
+    boolean mMenuVisible = true;
+
     // Used to verify that subclasses call through to super class.
     boolean mCalled;
     
@@ -888,7 +887,25 @@
             }
         }
     }
-    
+
+    /**
+     * Set a hint for whether this fragment's menu should be visible.  This
+     * is useful if you know that a fragment has been placed in your view
+     * hierarchy so that the user can not currently seen it, so any menu items
+     * it has should also not be shown.
+     *
+     * @param menuVisible The default is true, meaning the fragment's menu will
+     * be shown as usual.  If false, the user will not see the menu.
+     */
+    public void setMenuVisibility(boolean menuVisible) {
+        if (mMenuVisible != menuVisible) {
+            mMenuVisible = menuVisible;
+            if (mHasMenu && isAdded() && !isHidden()) {
+                mFragmentManager.invalidateOptionsMenu();
+            }
+        }
+    }
+
     /**
      * Return the LoaderManager for this fragment, creating it if needed.
      */
@@ -1233,7 +1250,7 @@
         mRestored = false;
         mBackStackNesting = 0;
         mFragmentManager = null;
-        mActivity = mImmediateActivity = null;
+        mActivity = null;
         mFragmentId = 0;
         mContainerId = 0;
         mTag = null;
@@ -1421,17 +1438,14 @@
                 writer.print(" mInLayout="); writer.println(mInLayout);
         writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
                 writer.print(" mDetached="); writer.print(mDetached);
-                writer.print(" mRetainInstance="); writer.print(mRetainInstance);
-                writer.print(" mRetaining="); writer.print(mRetaining);
+                writer.print(" mMenuVisible="); writer.print(mMenuVisible);
                 writer.print(" mHasMenu="); writer.println(mHasMenu);
+        writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance);
+                writer.print(" mRetaining="); writer.println(mRetaining);
         if (mFragmentManager != null) {
             writer.print(prefix); writer.print("mFragmentManager=");
                     writer.println(mFragmentManager);
         }
-        if (mImmediateActivity != null) {
-            writer.print(prefix); writer.print("mImmediateActivity=");
-                    writer.println(mImmediateActivity);
-        }
         if (mActivity != null) {
             writer.print(prefix); writer.print("mActivity=");
                     writer.println(mActivity);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 70e6866..7a6759f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -67,6 +67,13 @@
         public int getId();
 
         /**
+         * Get the name that was supplied to
+         * {@link FragmentTransaction#addToBackStack(String)
+         * FragmentTransaction.addToBackStack(String)} when creating this entry.
+         */
+        public String getName();
+
+        /**
          * Return the full bread crumb title resource identifier for the entry,
          * or 0 if it does not have one.
          */
@@ -949,7 +956,6 @@
                             if (!f.mRetaining) {
                                 makeInactive(f);
                             } else {
-                                f.mImmediateActivity = null;
                                 f.mActivity = null;
                                 f.mFragmentManager = null;
                             }
@@ -1037,7 +1043,7 @@
             mAdded.add(fragment);
             fragment.mAdded = true;
             fragment.mRemoving = false;
-            if (fragment.mHasMenu) {
+            if (fragment.mHasMenu && fragment.mMenuVisible) {
                 mNeedMenuInvalidate = true;
             }
             if (moveToStateNow) {
@@ -1051,7 +1057,7 @@
         final boolean inactive = !fragment.isInBackStack();
         if (!fragment.mDetached || inactive) {
             mAdded.remove(fragment);
-            if (fragment.mHasMenu) {
+            if (fragment.mHasMenu && fragment.mMenuVisible) {
                 mNeedMenuInvalidate = true;
             }
             fragment.mAdded = false;
@@ -1086,7 +1092,7 @@
                     fragment.mView.setVisibility(View.GONE);
                 }
             }
-            if (fragment.mAdded && fragment.mHasMenu) {
+            if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
                 mNeedMenuInvalidate = true;
             }
             fragment.onHiddenChanged(true);
@@ -1106,7 +1112,7 @@
                 }
                 fragment.mView.setVisibility(View.VISIBLE);
             }
-            if (fragment.mAdded && fragment.mHasMenu) {
+            if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
                 mNeedMenuInvalidate = true;
             }
             fragment.onHiddenChanged(false);
@@ -1120,7 +1126,7 @@
             if (fragment.mAdded) {
                 // We are not already in back stack, so need to remove the fragment.
                 mAdded.remove(fragment);
-                if (fragment.mHasMenu) {
+                if (fragment.mHasMenu && fragment.mMenuVisible) {
                     mNeedMenuInvalidate = true;
                 }
                 fragment.mAdded = false;
@@ -1136,7 +1142,7 @@
             if (!fragment.mAdded) {
                 mAdded.add(fragment);
                 fragment.mAdded = true;
-                if (fragment.mHasMenu) {
+                if (fragment.mHasMenu && fragment.mMenuVisible) {
                     mNeedMenuInvalidate = true;
                 }
                 moveToState(fragment, mCurState, transition, transitionStyle);
@@ -1640,7 +1646,6 @@
                             "No instantiated fragment for index #" + fms.mAdded[i]);
                 }
                 f.mAdded = true;
-                f.mImmediateActivity = mActivity;
                 if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
                 mAdded.add(f);
             }
@@ -1748,7 +1753,7 @@
         if (mActive != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu) {
+                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
                     show = true;
                     f.onCreateOptionsMenu(menu, inflater);
                     if (newMenus == null) {
@@ -1778,7 +1783,7 @@
         if (mActive != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu) {
+                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
                     show = true;
                     f.onPrepareOptionsMenu(menu);
                 }
@@ -1791,7 +1796,7 @@
         if (mActive != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu) {
+                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
                     if (f.onOptionsItemSelected(item)) {
                         return true;
                     }
@@ -1819,7 +1824,7 @@
         if (mActive != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu) {
+                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
                     f.onOptionsMenuClosed(menu);
                 }
             }
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 58ea0c3..9542874 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -255,10 +255,7 @@
      * will be delivered to the backup destination along with the metadata necessary
      * to place it with the proper location and permissions on the device where the
      * data is restored.
-     * @hide
      *
-     * @param context The BackupAgent that is calling this method.  It is an error to
-     *     call it from something other than a running BackupAgent instance.
      * @param file The file to be backed up.  The file must exist and be readable by
      *     the caller.
      * @param output The destination to which the backed-up file data will be sent.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 2236928..254c98f 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -22,6 +22,7 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -348,6 +349,8 @@
 
     private final IBluetooth mService;
 
+    private Handler mServiceRecordHandler;
+
     /**
      * Get a handle to the default local Bluetooth adapter.
      * <p>Currently Android only supports one Bluetooth adapter, but the API
@@ -376,6 +379,7 @@
             throw new IllegalArgumentException("service is null");
         }
         mService = service;
+        mServiceRecordHandler = null;
     }
 
     /**
@@ -1011,7 +1015,21 @@
             } catch (IOException e) {}
             throw new IOException("Not able to register SDP record for " + name);
         }
-        socket.setCloseHandler(mHandler, handle);
+
+        if (mServiceRecordHandler == null) {
+            mServiceRecordHandler = new Handler(Looper.getMainLooper()) {
+                    public void handleMessage(Message msg) {
+                        /* handle socket closing */
+                        int handle = msg.what;
+                        try {
+                            if (DBG) Log.d(TAG, "Removing service record " +
+                                           Integer.toHexString(handle));
+                            mService.removeServiceRecord(handle);
+                        } catch (RemoteException e) {Log.e(TAG, "", e);}
+                    }
+                };
+        }
+        socket.setCloseHandler(mServiceRecordHandler, handle);
         return socket;
     }
 
@@ -1243,17 +1261,6 @@
         return Collections.unmodifiableSet(devices);
     }
 
-    private Handler mHandler = new Handler() {
-        public void handleMessage(Message msg) {
-            /* handle socket closing */
-            int handle = msg.what;
-            try {
-                if (DBG) Log.d(TAG, "Removing service record " + Integer.toHexString(handle));
-                mService.removeServiceRecord(handle);
-            } catch (RemoteException e) {Log.e(TAG, "", e);}
-        }
-    };
-
     /**
      * Validate a Bluetooth address, such as "00:43:A8:23:10:F0"
      * <p>Alphabetic characters must be uppercase to be valid.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 9c96883..3441217 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -23,6 +23,7 @@
 import android.os.Binder;
 import android.os.Build.VERSION_CODES;
 import android.os.RemoteException;
+import android.provider.Settings;
 
 import java.net.InetAddress;
 
@@ -71,6 +72,15 @@
     public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
 
     /**
+     * Identical to {@link #CONNECTIVITY_ACTION} broadcast, but sent without any
+     * applicable {@link Settings.Secure#CONNECTIVITY_CHANGE_DELAY}.
+     *
+     * @hide
+     */
+    public static final String CONNECTIVITY_ACTION_IMMEDIATE =
+            "android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE";
+
+    /**
      * The lookup key for a {@link NetworkInfo} object. Retrieve with
      * {@link android.content.Intent#getParcelableExtra(String)}.
      *
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index e9221fe..5321c6a 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3083,12 +3083,25 @@
         /**
          * A reference to the {@link android.provider.ContactsContract.Contacts#_ID}
          * that this stream item belongs to.
+         *
+         * <p>Type: INTEGER</p>
+         * <p>read-only</p>
          */
         public static final String CONTACT_ID = "contact_id";
 
         /**
+         * A reference to the {@link android.provider.ContactsContract.Contacts#LOOKUP_KEY}
+         * that this stream item belongs to.
+         *
+         * <p>Type: TEXT</p>
+         * <p>read-only</p>
+         */
+        public static final String CONTACT_LOOKUP_KEY = "contact_lookup";
+
+        /**
          * A reference to the {@link RawContacts#_ID}
          * that this stream item belongs to.
+         * <p>Type: INTEGER</p>
          */
         public static final String RAW_CONTACT_ID = "raw_contact_id";
 
@@ -3104,7 +3117,7 @@
          * The account type to which the raw_contact of this item is associated. See
          * {@link RawContacts#ACCOUNT_TYPE}
          *
-         * <p>TYPE: text</p>
+         * <p>Type: TEXT</p>
          * <p>read-only</p>
          */
         public static final String ACCOUNT_TYPE = "account_type";
@@ -3113,7 +3126,7 @@
          * The account name to which the raw_contact of this item is associated. See
          * {@link RawContacts#ACCOUNT_NAME}
          *
-         * <p>TYPE: text</p>
+         * <p>Type: TEXT</p>
          * <p>read-only</p>
          */
         public static final String ACCOUNT_NAME = "account_name";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0c791e1..efdb79e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1738,6 +1738,14 @@
         public static final String POINTER_LOCATION = "pointer_location";
 
         /**
+         * Show touch positions on screen?
+         * 0 = no
+         * 1 = yes
+         * @hide
+         */
+        public static final String SHOW_TOUCHES = "show_touches";
+
+        /**
          * Log raw orientation data from {@link WindowOrientationListener} for use with the
          * orientationplot.py tool.
          * 0 = no
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index e942969..55a0624 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -117,6 +117,7 @@
 
     private static final int MESSAGE_UUID_INTENT = 1;
     private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2;
+    private static final int MESSAGE_REMOVE_SERVICE_RECORD = 3;
 
     private static final int RFCOMM_RECORD_REAPER = 10;
     private static final int STATE_CHANGE_REAPER = 11;
@@ -537,6 +538,10 @@
                 }
                 if (attempt > 0) mBondState.clearPinAttempts(address);
                 break;
+            case MESSAGE_REMOVE_SERVICE_RECORD:
+                Pair<Integer, Integer> pair = (Pair<Integer, Integer>) msg.obj;
+                checkAndRemoveRecord(pair.first, pair.second);
+                break;
             }
         }
     };
@@ -1542,7 +1547,9 @@
     public void removeServiceRecord(int handle) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
                                                 "Need BLUETOOTH permission");
-        checkAndRemoveRecord(handle, Binder.getCallingPid());
+        Message message = mHandler.obtainMessage(MESSAGE_REMOVE_SERVICE_RECORD);
+        message.obj = new Pair<Integer, Integer>(handle, Binder.getCallingPid());
+        mHandler.sendMessage(message);
     }
 
     private synchronized void checkAndRemoveRecord(int handle, int pid) {
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 83ef6ce..b8b54f4 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -31,9 +31,11 @@
 import android.text.style.RelativeSizeSpan;
 import android.text.style.ReplacementSpan;
 import android.text.style.ScaleXSpan;
+import android.text.style.SpellCheckSpan;
 import android.text.style.StrikethroughSpan;
 import android.text.style.StyleSpan;
 import android.text.style.SubscriptSpan;
+import android.text.style.SuggestionRangeSpan;
 import android.text.style.SuggestionSpan;
 import android.text.style.SuperscriptSpan;
 import android.text.style.TextAppearanceSpan;
@@ -579,6 +581,10 @@
     public static final int ANNOTATION = 18;
     /** @hide */
     public static final int SUGGESTION_SPAN = 19;
+    /** @hide */
+    public static final int SPELL_CHECK_SPAN = 20;
+    /** @hide */
+    public static final int SUGGESTION_RANGE_SPAN = 21;
 
     /**
      * Flatten a CharSequence and whatever styles can be copied across processes
@@ -734,6 +740,14 @@
                     readSpan(p, sp, new SuggestionSpan(p));
                     break;
 
+                case SPELL_CHECK_SPAN:
+                    readSpan(p, sp, new SpellCheckSpan(p));
+                    break;
+
+                case SUGGESTION_RANGE_SPAN:
+                    readSpan(p, sp, new SuggestionRangeSpan());
+                    break;
+                    
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
index 9b23177..caaae99 100644
--- a/core/java/android/text/style/SpellCheckSpan.java
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -16,6 +16,10 @@
 
 package android.text.style;
 
+import android.os.Parcel;
+import android.text.ParcelableSpan;
+import android.text.TextUtils;
+
 /**
  * A SpellCheckSpan is an internal data structure created by the TextView's SpellChecker to
  * annotate portions of the text that are about to or currently being spell checked. They are
@@ -23,7 +27,7 @@
  *
  * @hide
  */
-public class SpellCheckSpan {
+public class SpellCheckSpan implements ParcelableSpan {
 
     private boolean mSpellCheckInProgress;
 
@@ -31,6 +35,10 @@
         mSpellCheckInProgress = false;
     }
 
+    public SpellCheckSpan(Parcel src) {
+        mSpellCheckInProgress = (src.readInt() != 0);
+    }
+
     public void setSpellCheckInProgress() {
         mSpellCheckInProgress = true;
     }
@@ -38,4 +46,19 @@
     public boolean isSpellCheckInProgress() {
         return mSpellCheckInProgress;
     }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSpellCheckInProgress ? 1 : 0);
+    }
+
+    @Override
+    public int getSpanTypeId() {
+        return TextUtils.SPELL_CHECK_SPAN;
+    }
 }
diff --git a/core/java/android/text/style/SuggestionRangeSpan.java b/core/java/android/text/style/SuggestionRangeSpan.java
new file mode 100644
index 0000000..fc91697
--- /dev/null
+++ b/core/java/android/text/style/SuggestionRangeSpan.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.style;
+
+import android.graphics.Color;
+import android.os.Parcel;
+import android.text.ParcelableSpan;
+import android.text.TextPaint;
+import android.text.TextUtils;
+
+/**
+ * A SuggestionRangeSpan is used to show which part of an EditText is affected by a suggestion
+ * popup window.
+ *
+ * @hide
+ */
+public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpan {
+    @Override
+    public void updateDrawState(TextPaint tp) {
+        tp.setColor(Color.GREEN);            
+    }
+
+    public SuggestionRangeSpan() { /* Nothing to do*/ }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) { /* Nothing to do*/ }
+
+    @Override
+    public int getSpanTypeId() {
+        return TextUtils.SUGGESTION_RANGE_SPAN;
+    }
+}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 5e7e509..ef3d3fa5 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -36,6 +36,20 @@
     public static final int ROTATION_270     = 3;
 
     /**
+     * Create Surface from a SurfaceTexture.
+     *
+     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface.
+     * @hide
+     */
+    public Surface(SurfaceTexture surfaceTexture) {
+        if (DEBUG_RELEASE) {
+            mCreationStack = new Exception();
+        }
+        mCanvas = new CompatibleCanvas();
+        initFromSurfaceTexture(surfaceTexture);
+    }
+
+    /**
      * Does this object hold a valid surface?  Returns true if it holds
      * a physical surface, so lockCanvas() will succeed.  Otherwise
      * returns false.
@@ -222,20 +236,6 @@
     native private static void nativeClassInit();
     static { nativeClassInit(); }
 
-    /**
-     * Create Surface from a SurfaceTexture.
-     *
-     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface.
-     * @hide
-     */
-    public Surface(SurfaceTexture surfaceTexture) {
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
-        initFromSurfaceTexture(surfaceTexture);
-    }
-    
     /** create a surface @hide */
     public Surface(SurfaceSession s,
             int pid, int display, int w, int h, int format, int flags)
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7713bd8..14677e1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6497,6 +6497,8 @@
             if (mParent instanceof ViewGroup) {
                 ((ViewGroup) mParent).onChildVisibilityChanged(this, (flags & VISIBILITY_MASK));
                 ((View) mParent).invalidate(true);
+            } else if (mParent != null) {
+                mParent.invalidateChild(this, null);
             }
             dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
         }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6238b72..4748522 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4004,9 +4004,12 @@
         // state.
         // If mNativeClass is 0, we should not reach here, so we do not
         // need to check it again.
-        nativeRecordButtons(hasFocus() && hasWindowFocus(),
-                            mTouchMode == TOUCH_SHORTPRESS_START_MODE
-                            || mTrackballDown || mGotCenterDown, false);
+        if (mDrawCursorRing && drawRings) {
+            // Only update if we are actually going to use the result
+            nativeRecordButtons(hasFocus() && hasWindowFocus(),
+                    mTouchMode == TOUCH_SHORTPRESS_START_MODE
+                    || mTrackballDown || mGotCenterDown, false);
+        }
         drawCoreAndCursorRing(canvas, mBackgroundColor,
                 mDrawCursorRing && drawRings);
     }
@@ -4075,7 +4078,8 @@
         boolean drawJavaRings = !mTouchHighlightRegion.isEmpty()
                 && (mTouchMode == TOUCH_INIT_MODE
                 || mTouchMode == TOUCH_SHORTPRESS_START_MODE
-                || mTouchMode == TOUCH_SHORTPRESS_MODE);
+                || mTouchMode == TOUCH_SHORTPRESS_MODE
+                || mTouchMode == TOUCH_DONE_MODE);
         boolean drawNativeRings = !drawJavaRings;
         if (USE_WEBKIT_RINGS) {
             drawNativeRings = !drawJavaRings && !isInTouchMode();
@@ -9120,7 +9124,9 @@
 
     /** @hide send content invalidate */
     protected void contentInvalidateAll() {
-        mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL);
+        if (mWebViewCore != null && !mBlockWebkitViewMessages) {
+            mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL);
+        }
     }
 
     /** @hide call pageSwapCallback upon next page swap */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index c021c48..e9662ae 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -84,10 +84,10 @@
 import android.text.style.ClickableSpan;
 import android.text.style.ParagraphStyle;
 import android.text.style.SpellCheckSpan;
+import android.text.style.SuggestionRangeSpan;
 import android.text.style.SuggestionSpan;
 import android.text.style.TextAppearanceSpan;
 import android.text.style.URLSpan;
-import android.text.style.UnderlineSpan;
 import android.text.style.UpdateAppearance;
 import android.text.util.Linkify;
 import android.util.AttributeSet;
@@ -2894,7 +2894,6 @@
                     sp.removeSpan(cw);
                 }
 
-                // hideControllers would do it, but it gets called after this method on rotation
                 sp.removeSpan(mSuggestionRangeSpan);
 
                 ss.text = sp;
@@ -5099,10 +5098,9 @@
     @Override
     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK) {
-            boolean areSuggestionsShown = areSuggestionsShown();
             boolean isInSelectionMode = mSelectionActionMode != null;
 
-            if (areSuggestionsShown || isInSelectionMode) {
+            if (isInSelectionMode) {
                 if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
                     KeyEvent.DispatcherState state = getKeyDispatcherState();
                     if (state != null) {
@@ -5115,10 +5113,6 @@
                         state.handleUpEvent(event);
                     }
                     if (event.isTracking() && !event.isCanceled()) {
-                        if (areSuggestionsShown) {
-                            hideSuggestions();
-                            return true;
-                        }
                         if (isInSelectionMode) {
                             stopSelectionActionMode();
                             return true;
@@ -5282,10 +5276,6 @@
 
                 // Has to be done on key down (and not on key up) to correctly be intercepted.
             case KeyEvent.KEYCODE_BACK:
-                if (areSuggestionsShown()) {
-                    hideSuggestions();
-                    return -1;
-                }
                 if (mSelectionActionMode != null) {
                     stopSelectionActionMode();
                     return -1;
@@ -7950,9 +7940,6 @@
             }
 
             hideControllers();
-
-            removeSpans(0, mText.length(), SuggestionSpan.class);
-            removeSpans(0, mText.length(), SpellCheckSpan.class);
         }
 
         startStopMarquee(hasWindowFocus);
@@ -9196,11 +9183,6 @@
         }
     }
 
-    private static class SuggestionRangeSpan extends UnderlineSpan {
-        // TODO themable, would be nice to make it a child class of TextAppearanceSpan, but
-        // there is no way to have underline and TextAppearanceSpan.
-    }
-
     private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnClickListener {
         private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
         private static final int NO_SUGGESTIONS = -1;
@@ -9208,13 +9190,42 @@
         private WordIterator mSuggestionWordIterator;
         private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan
                 [(int) (AVERAGE_HIGHLIGHTS_PER_SUGGESTION * MAX_NUMBER_SUGGESTIONS)];
+        private boolean mCursorWasVisibleBeforeSuggestions;
+
+        private class CustomPopupWindow extends PopupWindow {
+            public CustomPopupWindow(Context context, int defStyle) {
+                super(context, null, defStyle);
+            }
+
+            @Override
+            public void dismiss() {
+                super.dismiss();
+
+                if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
+                    ((Editable) mText).removeSpan(mSuggestionRangeSpan);
+                }
+
+                setCursorVisible(mCursorWasVisibleBeforeSuggestions);
+                if (hasInsertionController()) {
+                    getInsertionController().show(); 
+                }
+            }
+        }
+
+        public SuggestionsPopupWindow() {
+            for (int i = 0; i < mHighlightSpans.length; i++) {
+                mHighlightSpans[i] = new TextAppearanceSpan(mContext,
+                        android.R.style.TextAppearance_SuggestionHighlight);
+            }
+            mCursorWasVisibleBeforeSuggestions = mCursorVisible;
+        }
 
         @Override
         protected void createPopupWindow() {
-            mPopupWindow = new PopupWindow(TextView.this.mContext, null,
+            mPopupWindow = new CustomPopupWindow(TextView.this.mContext,
                 com.android.internal.R.attr.textSuggestionsWindowStyle);
             mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
-            mPopupWindow.setOutsideTouchable(true);
+            mPopupWindow.setFocusable(true);
             mPopupWindow.setClippingEnabled(false);
         }
 
@@ -9288,6 +9299,8 @@
             if (!(mText instanceof Editable)) return;
 
             if (updateSuggestions()) {
+                mCursorWasVisibleBeforeSuggestions = mCursorVisible;
+                setCursorVisible(false);
                 super.show();
             }
         }
@@ -9312,9 +9325,6 @@
         @Override
         public void hide() {
             super.hide();
-            if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
-                ((Editable) mText).removeSpan(mSuggestionRangeSpan);
-            }
         }
 
         private boolean updateSuggestions() {
@@ -9553,7 +9563,7 @@
                 final int spanEnd = suggestionInfo.spanEnd;
                 if (spanStart != NO_SUGGESTIONS) {
                     // SuggestionSpans are removed by replace: save them before
-                    Editable editable = ((Editable) mText);
+                    Editable editable = (Editable) mText;
                     SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
                             SuggestionSpan.class);
                     final int length = suggestionSpans.length;
@@ -9572,7 +9582,7 @@
                     final String suggestion = textView.getText().subSequence(
                             suggestionStart, suggestionEnd).toString();
                     final String originalText = mText.subSequence(spanStart, spanEnd).toString();
-                    ((Editable) mText).replace(spanStart, spanEnd, suggestion);
+                    editable.replace(spanStart, spanEnd, suggestion);
 
                     // A replacement on a misspelled text removes the misspelled flag.
                     // TODO restore the flag if the misspelled word is selected back?
@@ -9624,12 +9634,6 @@
         mSuggestionsPopupWindow.show();
     }
 
-    void hideSuggestions() {
-        if (mSuggestionsPopupWindow != null) {
-            mSuggestionsPopupWindow.hide();
-        }
-    }
-
     boolean areSuggestionsShown() {
         return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing();
     }
@@ -10579,7 +10583,6 @@
             mEndHandle.setActionPopupWindow(mStartHandle.getActionPopupWindow());
 
             hideInsertionPointCursorController();
-            hideSuggestions();
         }
 
         public void hide() {
@@ -10691,7 +10694,6 @@
     private void hideControllers() {
         hideInsertionPointCursorController();
         stopSelectionActionMode();
-        hideSuggestions();
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/TransportControlView.java b/core/java/com/android/internal/widget/TransportControlView.java
index 3961de3..1c47ca88a 100644
--- a/core/java/com/android/internal/widget/TransportControlView.java
+++ b/core/java/com/android/internal/widget/TransportControlView.java
@@ -16,88 +16,369 @@
 
 package com.android.internal.widget;
 
-import com.android.internal.R;
+import java.lang.ref.WeakReference;
 
+import com.android.internal.widget.LockScreenWidgetCallback;
+import com.android.internal.widget.LockScreenWidgetInterface;
+
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
 import android.media.AudioManager;
+import android.media.MediaMetadataRetriever;
+import android.media.RemoteControlClient;
+import android.media.IRemoteControlDisplay;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.os.RemoteException;
+import android.text.Spannable;
+import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
 import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
 
-/**
- * A special widget for displaying audio playback ("transport controls") in LockScreen.
- *
- */
-public class TransportControlView extends LinearLayout implements LockScreenWidgetInterface,
-        OnClickListener {
-    private static final String TAG = "TransportControlView";
-    static final int sViewIds[] = { R.id.control_prev, R.id.control_pauseplay, R.id.control_next };
-    protected static final int AUDIO_FOCUS_CHANGED = 100;
-    private LockScreenWidgetCallback mCallback;
 
+import com.android.internal.R;
+
+public class TransportControlView extends FrameLayout implements OnClickListener,
+        LockScreenWidgetInterface {
+
+    private static final int MSG_UPDATE_STATE = 100;
+    private static final int MSG_SET_METADATA = 101;
+    private static final int MSG_SET_TRANSPORT_CONTROLS = 102;
+    private static final int MSG_SET_ARTWORK = 103;
+    private static final int MSG_SET_GENERATION_ID = 104;
+    private static final int MAXDIM = 512;
+    protected static final boolean DEBUG = true;
+    protected static final String TAG = "TransportControlView";
+
+    private ImageView mAlbumArt;
+    private TextView mTrackTitle;
+    private ImageView mBtnPrev;
+    private ImageView mBtnPlay;
+    private ImageView mBtnNext;
+    private int mClientGeneration;
+    private Metadata mMetadata = new Metadata();
+    private boolean mAttached;
+    private ComponentName mClientName;
+    private int mTransportControlFlags;
+    private int mPlayState;
+    private AudioManager mAudioManager;
+    private LockScreenWidgetCallback mWidgetCallbacks;
+    private IRemoteControlDisplayWeak mIRCD;
+
+    /**
+     * The metadata which should be populated into the view once we've been attached
+     */
+    private Bundle mPopulateMetadataWhenAttached = null;
+
+    // This handler is required to ensure messages from IRCD are handled in sequence and on
+    // the UI thread.
     private Handler mHandler = new Handler() {
+        @Override
         public void handleMessage(Message msg) {
-            switch (msg.what){
-            case AUDIO_FOCUS_CHANGED:
-                handleAudioFocusChange(msg.arg1);
+            switch (msg.what) {
+            case MSG_UPDATE_STATE:
+                if (mClientGeneration == msg.arg1) updatePlayPauseState(msg.arg2);
+                break;
+
+            case MSG_SET_METADATA:
+                if (mClientGeneration == msg.arg1) updateMetadata((Bundle) msg.obj);
+                break;
+
+            case MSG_SET_TRANSPORT_CONTROLS:
+                if (mClientGeneration == msg.arg1) updateTransportControls(msg.arg2);
+                break;
+
+            case MSG_SET_ARTWORK:
+                if (mClientGeneration == msg.arg1) {
+                    mMetadata.bitmap = (Bitmap) msg.obj;
+                    mAlbumArt.setImageBitmap(mMetadata.bitmap);
+                }
+                break;
+
+            case MSG_SET_GENERATION_ID:
+                if (mWidgetCallbacks != null) {
+                    boolean clearing = msg.arg2 != 0;
+                    if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + clearing);
+                    if (!clearing) {
+                        mWidgetCallbacks.requestShow(TransportControlView.this);
+                    } else {
+                        mWidgetCallbacks.requestHide(TransportControlView.this);
+                    }
+                }
+                mClientGeneration = msg.arg1;
+                mClientName = (ComponentName) msg.obj;
+                break;
+
             }
         }
     };
 
-    AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener =
-        new AudioManager.OnAudioFocusChangeListener() {
-            public void onAudioFocusChange(final int focusChange) {
-                mHandler.obtainMessage(AUDIO_FOCUS_CHANGED, focusChange, 0).sendToTarget();
-            }
-        };
+    /**
+     * This class is required to have weak linkage to the current TransportControlView
+     * because the remote process can hold a strong reference to this binder object and
+     * we can't predict when it will be GC'd in the remote process. Without this code, it
+     * would allow a heavyweight object to be held on this side of the binder when there's
+     * no requirement to run a GC on the other side.
+     */
+    private static class IRemoteControlDisplayWeak extends IRemoteControlDisplay.Stub {
+        private WeakReference<Handler> mLocalHandler;
 
-    public TransportControlView(Context context) {
-        this(context, null);
-    }
+        IRemoteControlDisplayWeak(Handler handler) {
+            mLocalHandler = new WeakReference<Handler>(handler);
+        }
+
+        public void setPlaybackState(int generationId, int state) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_UPDATE_STATE, generationId, state).sendToTarget();
+            }
+        }
+
+        public void setMetadata(int generationId, Bundle metadata) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
+            }
+        }
+
+        public void setTransportControlFlags(int generationId, int flags) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_TRANSPORT_CONTROLS, generationId, flags)
+                        .sendToTarget();
+            }
+        }
+
+        public void setArtwork(int generationId, Bitmap bitmap) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
+            }
+        }
+
+        public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
+                handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
+            }
+        }
+
+        public void setCurrentClientId(int clientGeneration, ComponentName clientEventReceiver,
+                boolean clearing) throws RemoteException {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_GENERATION_ID,
+                    clientGeneration, (clearing ? 1 : 0), clientEventReceiver).sendToTarget();
+            }
+        }
+    };
 
     public TransportControlView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        Log.v(TAG, "Create TCV " + this);
+        mAudioManager = new AudioManager(mContext);
+        mIRCD = new IRemoteControlDisplayWeak(mHandler);
     }
 
-    protected void handleAudioFocusChange(int focusChange) {
-        // TODO
-    }
-
-    public void setCallback(LockScreenWidgetCallback callback) {
-        mCallback = callback;
+    private void updateTransportControls(int transportControlFlags) {
+        mTransportControlFlags = transportControlFlags;
     }
 
     @Override
     public void onFinishInflate() {
-        for (int i = 0; i < sViewIds.length; i++) {
-            View view = findViewById(sViewIds[i]);
-            if (view != null) {
-                view.setOnClickListener(this);
+        super.onFinishInflate();
+        mTrackTitle = (TextView) findViewById(R.id.title);
+        mTrackTitle.setSelected(true); // enable marquee
+        mAlbumArt = (ImageView) findViewById(R.id.albumart);
+        mBtnPrev = (ImageView) findViewById(R.id.btn_prev);
+        mBtnPlay = (ImageView) findViewById(R.id.btn_play);
+        mBtnNext = (ImageView) findViewById(R.id.btn_next);
+        final View buttons[] = { mBtnPrev, mBtnPlay, mBtnNext };
+        for (View view : buttons) {
+            view.setOnClickListener(this);
+        }
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mPopulateMetadataWhenAttached != null) {
+            updateMetadata(mPopulateMetadataWhenAttached);
+            mPopulateMetadataWhenAttached = null;
+        }
+        if (!mAttached) {
+            if (DEBUG) Log.v(TAG, "Registering TCV " + this);
+            mAudioManager.registerRemoteControlDisplay(mIRCD);
+        }
+        mAttached = true;
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mAttached) {
+            if (DEBUG) Log.v(TAG, "Unregistering TCV " + this);
+            mAudioManager.unregisterRemoteControlDisplay(mIRCD);
+        }
+        mAttached = false;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        int dim = Math.min(MAXDIM, Math.max(getWidth(), getHeight()));
+//        Log.v(TAG, "setting max bitmap size: " + dim + "x" + dim);
+//        mAudioManager.remoteControlDisplayUsesBitmapSize(mIRCD, dim, dim);
+    }
+
+    class Metadata {
+        private String artist;
+        private String trackTitle;
+        private String albumTitle;
+        private Bitmap bitmap;
+
+        public String toString() {
+            return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + " albumTitle=" + albumTitle + "]";
+        }
+    }
+
+    private String getMdString(Bundle data, int id) {
+        return data.getString(Integer.toString(id));
+    }
+
+    private void updateMetadata(Bundle data) {
+        if (mAttached) {
+            mMetadata.artist = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST);
+            mMetadata.trackTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_TITLE);
+            mMetadata.albumTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUM);
+            populateMetadata();
+        } else {
+            mPopulateMetadataWhenAttached = data;
+        }
+    }
+
+    /**
+     * Populates the given metadata into the view
+     */
+    private void populateMetadata() {
+        StringBuilder sb = new StringBuilder();
+        int trackTitleLength = 0;
+        if (!TextUtils.isEmpty(mMetadata.trackTitle)) {
+            sb.append(mMetadata.trackTitle);
+            trackTitleLength = mMetadata.trackTitle.length();
+        }
+        if (!TextUtils.isEmpty(mMetadata.artist)) {
+            if (sb.length() != 0) {
+                sb.append(" - ");
+            }
+            sb.append(mMetadata.artist);
+        }
+        if (!TextUtils.isEmpty(mMetadata.albumTitle)) {
+            if (sb.length() != 0) {
+                sb.append(" - ");
+            }
+            sb.append(mMetadata.albumTitle);
+        }
+        mTrackTitle.setText(sb.toString(), TextView.BufferType.SPANNABLE);
+        Spannable str = (Spannable) mTrackTitle.getText();
+        if (trackTitleLength != 0) {
+            str.setSpan(new ForegroundColorSpan(0xffffffff), 0, trackTitleLength,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            trackTitleLength++;
+        }
+        if (sb.length() > trackTitleLength) {
+            str.setSpan(new ForegroundColorSpan(0x7fffffff), trackTitleLength, sb.length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }
+
+        mAlbumArt.setImageBitmap(mMetadata.bitmap);
+        final int flags = mTransportControlFlags;
+        setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
+        setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
+        setVisibilityBasedOnFlag(mBtnPrev, flags,
+                RemoteControlClient.FLAG_KEY_MEDIA_PLAY
+                | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE
+                | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
+                | RemoteControlClient.FLAG_KEY_MEDIA_STOP);
+
+        updatePlayPauseState(mPlayState);
+    }
+
+    private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
+        if ((flags & flag) != 0) {
+            view.setVisibility(View.VISIBLE);
+        } else {
+            view.setVisibility(View.GONE);
+        }
+    }
+
+    private void updatePlayPauseState(int state) {
+        if (DEBUG) Log.v(TAG,
+                "updatePlayPauseState(), old=" + mPlayState + ", state=" + state);
+        if (state == mPlayState) {
+            return;
+        }
+        switch (state) {
+            case RemoteControlClient.PLAYSTATE_PLAYING:
+                mBtnPlay.setImageResource(com.android.internal.R.drawable.ic_media_pause);
+                break;
+
+            case RemoteControlClient.PLAYSTATE_BUFFERING:
+                mBtnPlay.setImageResource(com.android.internal.R.drawable.ic_media_stop);
+                break;
+
+            case RemoteControlClient.PLAYSTATE_PAUSED:
+            default:
+                mBtnPlay.setImageResource(com.android.internal.R.drawable.ic_media_play);
+                break;
+        }
+        mPlayState = state;
+    }
+
+    public void onClick(View v) {
+        int keyCode = -1;
+        if (v == mBtnPrev) {
+            keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
+        } else if (v == mBtnNext) {
+            keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
+        } else if (v == mBtnPlay) {
+            keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
+
+        }
+        if (keyCode != -1) {
+            sendMediaButtonClick(keyCode);
+            if (mWidgetCallbacks != null) {
+                mWidgetCallbacks.userActivity(this);
             }
         }
     }
 
-    public void onClick(View v) {
-        switch (v.getId()) {
-            case R.id.control_prev:
-                // TODO
-                break;
+    private void sendMediaButtonClick(int keyCode) {
+        // TODO: target to specific player based on mClientName
+        KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+        Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+        intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+        getContext().sendOrderedBroadcast(intent, null);
 
-            case R.id.control_pauseplay:
-                // TODO
-                break;
+        keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
+        intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+        intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+        getContext().sendOrderedBroadcast(intent, null);
+    }
 
-            case R.id.control_next:
-                // TODO
-                break;
-        }
-        // Have any button click extend lockscreen's timeout.
-        if (mCallback != null) {
-            mCallback.userActivity(this);
-        }
+    public void setCallback(LockScreenWidgetCallback callback) {
+        mWidgetCallbacks = callback;
     }
 
 }
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index ec926e4..76bc535 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.widget.multiwaveview;
 
-import java.util.ArrayList;
-
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
@@ -31,15 +29,20 @@
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Vibrator;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.MeasureSpec;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.R;
 
+import java.util.ArrayList;
+
 /**
  * A special widget containing a center and outer ring. Moving the center ring to the outer ring
  * causes an event that can be caught by implementing OnTriggerListener.
@@ -82,6 +85,8 @@
     private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
     private ArrayList<Tweener> mChevronAnimations = new ArrayList<Tweener>();
     private ArrayList<Tweener> mTargetAnimations = new ArrayList<Tweener>();
+    private ArrayList<String> mTargetDescriptions;
+    private ArrayList<String> mDirectionDescriptions;
     private Tweener mHandleAnimation;
     private OnTriggerListener mOnTriggerListener;
     private TargetDrawable mHandleDrawable;
@@ -103,6 +108,9 @@
     private boolean mDragging;
     private int mNewTargetResources;
 
+    private boolean mWaveHovered = false;
+    private long mLastHoverExitTimeMillis = 0;
+
     private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
         public void onAnimationEnd(Animator animator) {
             switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
@@ -128,6 +136,8 @@
         }
     };
     private int mTargetResourceId;
+    private int mTargetDescriptionsResourceId;
+    private int mDirectionDescriptionsResourceId;
 
     public MultiWaveView(Context context) {
         this(context, null);
@@ -177,6 +187,25 @@
             throw new IllegalStateException("Must specify at least one target drawable");
         }
 
+        // Read array of target descriptions
+        if (a.getValue(R.styleable.MultiWaveView_targetDescriptions, outValue)) {
+            final int resourceId = outValue.resourceId;
+            if (resourceId == 0) {
+                throw new IllegalStateException("Must specify target descriptions");
+            }
+            setTargetDescriptionsResourceId(resourceId);
+        }
+
+        // Read array of direction descriptions
+        if (a.getValue(R.styleable.MultiWaveView_directionDescriptions, outValue)) {
+            final int resourceId = outValue.resourceId;
+            if (resourceId == 0) {
+                throw new IllegalStateException("Must specify direction descriptions");
+            }
+            setDirectionDescriptionsResourceId(resourceId);
+        }
+
+        a.recycle();
         setVibrateEnabled(mVibrationDuration > 0);
     }
 
@@ -247,6 +276,9 @@
                 showTargets(true);
                 mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
                 setGrabbedState(OnTriggerListener.CENTER_HANDLE);
+                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                    announceTargets();
+                }
                 break;
 
             case STATE_TRACKING:
@@ -347,6 +379,13 @@
         }
     }
 
+    private void dispatchGrabbedEvent(int whichHandler) {
+        vibrate();
+        if (mOnTriggerListener != null) {
+            mOnTriggerListener.onGrabbed(this, whichHandler);
+        }
+    }
+
     private void doFinish() {
         final int activeTarget = mActiveTarget;
         boolean targetHit =  activeTarget != -1;
@@ -475,6 +514,7 @@
             Drawable drawable = array.getDrawable(i);
             targetDrawables.add(new TargetDrawable(res, drawable));
         }
+        array.recycle();
         mTargetResourceId = resourceId;
         mTargetDrawables = targetDrawables;
         updateTargetPositions();
@@ -499,6 +539,48 @@
     }
 
     /**
+     * Sets the resource id specifying the target descriptions for accessibility.
+     *
+     * @param resourceId The resource id.
+     */
+    public void setTargetDescriptionsResourceId(int resourceId) {
+        mTargetDescriptionsResourceId = resourceId;
+        if (mTargetDescriptions != null) {
+            mTargetDescriptions.clear();
+        }
+    }
+
+    /**
+     * Gets the resource id specifying the target descriptions for accessibility.
+     *
+     * @return The resource id.
+     */
+    public int getTargetDescriptionsResourceId() {
+        return mTargetDescriptionsResourceId;
+    }
+
+    /**
+     * Sets the resource id specifying the target direction descriptions for accessibility.
+     *
+     * @param resourceId The resource id.
+     */
+    public void setDirectionDescriptionsResourceId(int resourceId) {
+        mDirectionDescriptionsResourceId = resourceId;
+        if (mDirectionDescriptions != null) {
+            mDirectionDescriptions.clear();
+        }
+    }
+
+    /**
+     * Gets the resource id specifying the target direction descriptions.
+     *
+     * @return The resource id.
+     */
+    public int getDirectionDescriptionsResourceId() {
+        return mDirectionDescriptionsResourceId;
+    }
+
+    /**
      * Enable or disable vibrate on touch.
      *
      * @param enabled
@@ -593,6 +675,43 @@
         }
     }
 
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+            final int action = event.getAction();
+            switch (action) {
+                case MotionEvent.ACTION_HOVER_ENTER:
+                case MotionEvent.ACTION_HOVER_MOVE:
+                    final float dx = event.getX() - mWaveCenterX;
+                    final float dy = event.getY() - mWaveCenterY;
+                    if (dist2(dx,dy) <= square(mTapRadius)) {
+                        if (!mWaveHovered) {
+                            mWaveHovered = true;
+                            final long timeSinceLastHoverExitMillis =
+                                event.getEventTime() - mLastHoverExitTimeMillis;
+                            final long recurringEventsInterval =
+                                ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
+                            if (timeSinceLastHoverExitMillis > recurringEventsInterval) {
+                                String text =
+                                    mContext.getString(R.string.content_description_sliding_handle);
+                                announceText(text);
+                            }
+                        }
+                    } else {
+                        mWaveHovered = false;
+                    }
+                    break;
+                case MotionEvent.ACTION_HOVER_EXIT:
+                    mLastHoverExitTimeMillis = event.getEventTime();
+                    mWaveHovered = false;
+                    break;
+                default:
+                    mWaveHovered = false;
+            }
+        }
+        return super.onHoverEvent(event);
+    }
+
     private void handleUp(MotionEvent event) {
         if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
         switchToState(STATE_FINISH, event.getX(), event.getY());
@@ -663,7 +782,11 @@
         invalidateGlobalRegion(mHandleDrawable);
 
         if (mActiveTarget != activeTarget && activeTarget != -1) {
-            vibrate();
+            dispatchGrabbedEvent(activeTarget);
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                String targetContentDescription = getTargetDescription(activeTarget);
+                announceText(targetContentDescription);
+            }
         }
         mActiveTarget = activeTarget;
     }
@@ -771,4 +894,62 @@
         return dx*dx + dy*dy;
     }
 
-}
\ No newline at end of file
+    private void announceTargets() {
+        StringBuilder utterance = new StringBuilder();
+        final int targetCount = mTargetDrawables.size();
+        for (int i = 0; i < targetCount; i++) {
+            String targetDescription = getTargetDescription(i);
+            String directionDescription = getDirectionDescription(i);
+            if (!TextUtils.isEmpty(targetDescription)
+                    && !TextUtils.isEmpty(directionDescription)) {
+                utterance.append(targetDescription);
+                utterance.append(" ");
+                utterance.append(directionDescription);
+                utterance.append(".");
+            }
+        }
+        announceText(utterance.toString());
+    }
+
+    private void announceText(String text) {
+        setContentDescription(text);
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        setContentDescription(null);
+    }
+
+    private String getTargetDescription(int index) {
+        if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
+            mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
+            if (mTargetDrawables.size() != mTargetDescriptions.size()) {
+                Log.w(TAG, "The number of target drawables must be"
+                        + " euqal to the number of target descriptions.");
+                return null;
+            }
+        }
+        return mTargetDescriptions.get(index);
+    }
+
+    private String getDirectionDescription(int index) {
+        if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
+            mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
+            if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
+                Log.w(TAG, "The number of target drawables must be"
+                        + " euqal to the number of direction descriptions.");
+                return null;
+            }
+        }
+        return mDirectionDescriptions.get(index);
+    }
+
+    private ArrayList<String> loadDescriptions(int resourceId) {
+        TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
+        final int count = array.length();
+        ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
+        for (int i = 0; i < count; i++) {
+            String contentDescription = array.getString(i);
+            targetContentDescriptions.add(contentDescription);
+        }
+        array.recycle();
+        return targetContentDescriptions;
+    }
+}
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 3cbd912..84a50f0 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -124,6 +124,11 @@
     return (jboolean)(::wifi_start_supplicant() == 0);
 }
 
+static jboolean android_net_wifi_startP2pSupplicant(JNIEnv* env, jobject)
+{
+    return (jboolean)(::wifi_start_p2p_supplicant() == 0);
+}
+
 static jboolean android_net_wifi_stopSupplicant(JNIEnv* env, jobject)
 {
     return doBooleanCommand("OK", "TERMINATE");
@@ -581,6 +586,7 @@
     { "isDriverLoaded", "()Z",  (void *)android_net_wifi_isDriverLoaded},
     { "unloadDriver", "()Z",  (void *)android_net_wifi_unloadDriver },
     { "startSupplicant", "()Z",  (void *)android_net_wifi_startSupplicant },
+    { "startP2pSupplicant", "()Z",  (void *)android_net_wifi_startP2pSupplicant },
     { "stopSupplicant", "()Z", (void*) android_net_wifi_stopSupplicant },
     { "killSupplicant", "()Z",  (void *)android_net_wifi_killSupplicant },
     { "connectToSupplicant", "()Z",  (void *)android_net_wifi_connectToSupplicant },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 540c65a..01f2a8f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -93,6 +93,9 @@
     <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
     <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
 
+    <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+    <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
+
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
     <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
     <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-hdpi/ic_lockscreen_player_background.9.png
new file mode 100644
index 0000000..b187358
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_embed_play.png b/core/res/res/drawable-hdpi/ic_media_embed_play.png
index 05778c1..23ac7e4 100644
--- a/core/res/res/drawable-hdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-hdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-mdpi/ic_lockscreen_player_background.9.png
new file mode 100644
index 0000000..8cfd1af
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_embed_play.png b/core/res/res/drawable-mdpi/ic_media_embed_play.png
index 3576ce5..fc5d8c6 100644
--- a/core/res/res/drawable-mdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_ff.png b/core/res/res/drawable-mdpi/ic_media_ff.png
index 170dd2d..892772e 100644
--- a/core/res/res/drawable-mdpi/ic_media_ff.png
+++ b/core/res/res/drawable-mdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_fullscreen.png b/core/res/res/drawable-mdpi/ic_media_fullscreen.png
index 960aa85..1c60e15 100644
--- a/core/res/res/drawable-mdpi/ic_media_fullscreen.png
+++ b/core/res/res/drawable-mdpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png
index a6feed0..bbe311b 100644
--- a/core/res/res/drawable-mdpi/ic_media_next.png
+++ b/core/res/res/drawable-mdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png
index 548ba02..e4e8d86 100644
--- a/core/res/res/drawable-mdpi/ic_media_pause.png
+++ b/core/res/res/drawable-mdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png
index 0fe6806..8eaf962 100644
--- a/core/res/res/drawable-mdpi/ic_media_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png
index 0163d0945..e9abc7f 100644
--- a/core/res/res/drawable-mdpi/ic_media_previous.png
+++ b/core/res/res/drawable-mdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_rew.png b/core/res/res/drawable-mdpi/ic_media_rew.png
index 5489180..a5eb94a2 100644
--- a/core/res/res/drawable-mdpi/ic_media_rew.png
+++ b/core/res/res/drawable-mdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-xhdpi/ic_lockscreen_player_background.9.png
new file mode 100644
index 0000000..7fb0cbc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 12df99e..694db50 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -186,6 +186,8 @@
         android:layout_rowSpan="6"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
         />
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 6145e47..cf3bd42 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -174,6 +174,8 @@
         android:layout_rowSpan="3"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
         />
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 6016d4e..4c8c0d1 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -130,6 +130,8 @@
             android:layout_alignParentBottom="true"
 
             android:targetDrawables="@array/lockscreen_targets_with_camera"
+            android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
+            android:directionDescriptions="@array/lockscreen_direction_descriptions_with_camera"
             android:handleDrawable="@drawable/ic_lockscreen_handle"
             android:waveDrawable="@drawable/ic_lockscreen_outerring"
             android:outerRadius="@dimen/multiwaveview_target_placement_radius"
@@ -188,6 +190,8 @@
         android:layout_rowSpan="4"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
         />
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 0568dd9..ba55f0c0 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -135,6 +135,8 @@
         android:layout_rowSpan="7"
 
         android:targetDrawables="@array/lockscreen_targets_with_camera"
+        android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
+        android:directionDescriptions="@array/lockscreen_direction_descriptions_with_camera"
         android:handleDrawable="@drawable/ic_lockscreen_handle"
         android:waveDrawable="@drawable/ic_lockscreen_outerring"
         android:outerRadius="@dimen/multiwaveview_target_placement_radius"
@@ -155,6 +157,8 @@
         android:layout_rowSpan="5"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
         />
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 9b28731..d71dbff 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -156,6 +156,8 @@
         android:layout_rowSpan="5"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
         />
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 433dda7..64c479f 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -167,6 +167,8 @@
         android:layout_rowSpan="4"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
         />
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_transport_control.xml b/core/res/res/layout/keyguard_transport_control.xml
index 6308b02..2ebe5fc 100644
--- a/core/res/res/layout/keyguard_transport_control.xml
+++ b/core/res/res/layout/keyguard_transport_control.xml
@@ -1,53 +1,102 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2011 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.
 -->
 
+<!-- Note: This file is meant to be included in various password unlock screens. As such,
+     LayoutParams (layout_*) for TransportControlView should *NOT* be specified here,
+     but rather as include tags for this file or the layout will break. -->
 <com.android.internal.widget.TransportControlView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:gravity="bottom"
-    android:orientation="horizontal"
-    android:background="#a0808080"
-    android:visibility="gone">
+    android:id="@+id/transport_controls"
+    android:background="@drawable/ic_lockscreen_player_background">
 
-    <Button android:id="@+id/control_prev"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:background="#80ff0000"
+    <ImageView
+        android:id="@+id/albumart"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="fill"
+        android:scaleType="centerCrop"
+        android:adjustViewBounds="false"
         />
 
-    <Space android:layout_width="0dip"
-        android:layout_height="0dip"
-        android:layout_weight="1"/>
-
-    <Button android:id="@+id/control_pauseplay"
-        android:layout_width="wrap_content"
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="#8000ff00"
+        android:background="#c8000000"
+        android:layout_gravity="bottom">
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dip"
+            android:layout_marginLeft="16dip"
+            android:layout_marginRight="16dip"
+            android:gravity="center_horizontal"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textAppearance="?android:attr/textAppearanceMedium"
         />
-
-    <Space android:layout_width="0dip"
-        android:layout_height="0dip"
-        android:layout_weight="1"/>
-
-    <Button android:id="@+id/control_next"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:background="#800000ff"
-        />
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layout_marginTop="5dip">
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_prev"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:src="@drawable/ic_media_rew"
+                    android:clickable="true"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_play"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@drawable/ic_media_play"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_next"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@drawable/ic_media_ff"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"/>
+            </FrameLayout>
+        </LinearLayout>
+    </LinearLayout>
 
 </com.android.internal.widget.TransportControlView>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index fd492ec..57aafc8 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -27,13 +27,41 @@
         <item>@drawable/ic_lockscreen_soundon</item>
     </array>
 
+    <array name="lockscreen_target_descriptions_when_silent">
+        <item>@null</item>
+        <item>@string/description_target_unlock</item>
+        <item>@null</item>
+        <item>@string/description_target_soundon</item>
+    </array>
+
+    <array name="lockscreen_direction_descriptions_when_silent">
+        <item>@null</item>
+        <item>@string/description_direction_up</item>
+        <item>@null</item>
+        <item>@string/description_direction_down</item>
+    </array>
+
     <array name="lockscreen_targets_when_soundon">
-        <item>@null</item>"
+        <item>@null</item>
         <item>@drawable/ic_lockscreen_unlock</item>
         <item>@null</item>
         <item>@drawable/ic_lockscreen_silent</item>
     </array>
 
+    <array name="lockscreen_target_descriptions_when_soundon">
+        <item>@null</item>
+        <item>@string/description_target_unlock</item>
+        <item>@null</item>
+        <item>@string/description_target_silent</item>
+    </array>
+
+    <array name="lockscreen_direction_descriptions_when_soundon">
+        <item>@null</item>
+        <item>@string/description_direction_up</item>
+        <item>@null</item>
+        <item>@string/description_direction_down</item>
+    </array>
+
     <array name="lockscreen_targets_with_camera">
         <item>@null</item>
         <item>@drawable/ic_lockscreen_unlock</item>
@@ -41,4 +69,18 @@
         <item>@drawable/ic_lockscreen_camera</item>
     </array>
 
+    <array name="lockscreen_target_descriptions_with_camera">
+        <item>@null</item>
+        <item>@string/description_target_unlock</item>
+        <item>@null</item>
+        <item>@string/description_target_camera</item>
+    </array>
+
+    <array name="lockscreen_direction_descriptions_with_camera">
+        <item>@null</item>
+        <item>@string/description_direction_up</item>
+        <item>@null</item>
+        <item>@string/description_direction_down</item>
+    </array>
+
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 57e9bbf..c9043ba 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -349,18 +349,60 @@
         <item>@null</item>
     </array>
 
+    <array name="lockscreen_target_descriptions_when_silent">
+        <item>@string/description_target_unlock</item>
+        <item>@null</item>
+        <item>@string/description_target_soundon</item>
+        <item>@null</item>
+    </array>
+
+    <array name="lockscreen_direction_descriptions_when_silent">
+        <item>@string/description_direction_right</item>
+        <item>@null</item>
+        <item>@string/description_direction_left</item>
+        <item>@null</item>
+    </array>
+
     <array name="lockscreen_targets_when_soundon">
         <item>@drawable/ic_lockscreen_unlock</item>
         <item>@null</item>
         <item>@drawable/ic_lockscreen_silent</item>
-        <item>@null</item>"
+        <item>@null</item>
+    </array>
+
+    <array name="lockscreen_target_descriptions_when_soundon">
+        <item>@string/description_target_unlock</item>
+        <item>@null</item>
+        <item>@string/description_target_silent</item>
+        <item>@null</item>
+    </array>
+
+    <array name="lockscreen_direction_descriptions_when_soundon">
+        <item>@string/description_direction_right</item>
+        <item>@null</item>
+        <item>@string/description_direction_left</item>
+        <item>@null</item>
     </array>
 
     <array name="lockscreen_targets_with_camera">
         <item>@drawable/ic_lockscreen_unlock</item>
         <item>@null</item>
         <item>@drawable/ic_lockscreen_camera</item>
-        <item>@null</item>"
+        <item>@null</item>
+    </array>
+
+    <array name="lockscreen_target_descriptions_with_camera">
+        <item>@string/description_target_unlock</item>
+        <item>@null</item>
+        <item>@string/description_target_camera</item>
+        <item>@null</item>
+    </array>
+
+    <array name="lockscreen_direction_descriptions_with_camera">
+        <item>@string/description_direction_right</item>
+        <item>@null</item>
+        <item>@string/description_direction_left</item>
+        <item>@null</item>
     </array>
 
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index dae9f70..8c0d826 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5169,6 +5169,12 @@
         <!-- Reference to an array resource that be shown as targets around a circle. -->
         <attr name="targetDrawables" format="reference"/>
 
+        <!-- Reference to an array resource that be used as description for the targets around the circle. -->
+        <attr name="targetDescriptions" format="reference"/>
+
+        <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
+        <attr name="directionDescriptions" format="reference"/>
+
         <!-- Sets a drawable as the drag center. -->
         <attr name="handleDrawable" format="reference" />
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b155b803..051ed14 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -189,6 +189,9 @@
 
     <!-- Boolean indicating whether the wifi chipset has p2p support -->
     <bool translatable="false" name="config_wifi_p2p_support">false</bool>
+    <!-- Device type information conforming to Annex B format in WiFi Direct specification.
+         The default represents a dual-mode smartphone -->
+    <string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
 
     <!-- Boolean indicating whether the wifi chipset supports background scanning mechanism.
          This mechanism allows the host to remain in suspend state and the dongle to actively
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index fcd3bba..6988f6b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2006,4 +2006,8 @@
   <public type="color" name="holo_orange_dark" />
   <public type="color" name="holo_purple" />
   <public type="color" name="holo_blue_bright" />
+
+  <public type="attr" name="targetDescriptions" />
+  <public type="attr" name="directionDescriptions" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8e0f300..de10825 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3129,6 +3129,29 @@
     <!-- Description of the Enter button in a KeyboardView. [CHAR LIMIT=NONE] -->
     <string name="keyboardview_keycode_enter">Enter</string>
 
+    <!-- Slide lock screen -->
+
+    <!-- Description of the sliding handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="content_description_sliding_handle">"Sliding handle. Tap and hold."</string>
+
+    <!-- Description of the up direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_direction_up">"Up</string>
+    <!-- Description of the down direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_direction_down">Down</string>
+    <!-- Description of the left direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_direction_left">"Left</string>
+    <!-- Description of the right direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_direction_right">Right</string>
+
+    <!-- Description of the unlock target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_target_unlock">Unlock</string>
+    <!-- Description of the camera target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_target_camera">Camera</string>
+    <!-- Description of the silent target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_target_silent">Silent</string>
+    <!-- Description of the sound on target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+    <string name="description_target_soundon">Sound on</string>
+
     <!-- Announce that a headset is required to hear keyboard keys while typing a password. [CHAR LIMIT=NONE] -->
     <string name="keyboard_headset_required_to_hear_password">Key. Headset required to hear
     keys while typing a password.</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index c35c5e6..052a040 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -890,11 +890,9 @@
         <item name="android:textSize">30sp</item>
     </style>
 
-     <!-- @hide -->
      <style name="TextAppearance.SuggestionHighlight">
          <item name="android:textSize">18sp</item>
          <item name="android:textColor">@android:color/suggestion_highlight_text</item>
-         <item name="android:textStyle">bold</item>
      </style>
 
     <!-- Preference Styles -->
diff --git a/docs/html/guide/topics/usb/index.jd b/docs/html/guide/topics/usb/index.jd
index 3e2a18b..6dc8ec5 100644
--- a/docs/html/guide/topics/usb/index.jd
+++ b/docs/html/guide/topics/usb/index.jd
@@ -6,9 +6,9 @@
       <h2>Topics</h2>
 
       <ol>
-        <li><a href="{@docRoot}guide/topics/USB/accessory.jd">USB Accessory</a></li>
+        <li><a href="{@docRoot}guide/topics/usb/accessory.html">USB Accessory</a></li>
 
-        <li><a href="{@docRoot}guide/topics/USB/host.jd">USB Host</a></li>
+        <li><a href="{@docRoot}guide/topics/usb/host.html">USB Host</a></li>
       </ol>
     </div>
   </div>
diff --git a/docs/html/resources/tutorials/hello-world.jd b/docs/html/resources/tutorials/hello-world.jd
index b11770f..9afab6a 100644
--- a/docs/html/resources/tutorials/hello-world.jd
+++ b/docs/html/resources/tutorials/hello-world.jd
@@ -18,16 +18,14 @@
   </div>
 </div>
 
-<p>As a developer, you know that the first impression
-of a development framework is how easy it is to write "Hello,
-World." Well, on Android, it's pretty easy. 
-It's particularly easy if you're using Eclipse as your IDE, because we've provided a
-great plugin that handles your project creation and management to greatly speed-up your
-development cycles.</p>
+<p>As a developer, you know that the first impression of a development framework is how easy it is
+to write "Hello, World." Well, on Android, it's pretty easy. It's particularly easy if you're using
+Eclipse as your IDE, because we've provided a great plugin that handles your project creation and
+management to greatly speed up your development cycles.</p>
 
-<p>This tutorial assumes that you're using Eclipse. If you're not, see 
-<a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.
-You can then return to this tutorial and ignore anything about Eclipse.</p>
+<p>This tutorial assumes that you're using Eclipse. If you're using the command line, see
+<a href="{@docRoot}/guide/developing/building/building-cmdline.html">Building and Running from the
+Command Line</a>. You can then return to this tutorial and ignore anything about Eclipse.</p>
 
 <p>Before you start, you should already have the SDK installed, and if you're
 using Eclipse, you should have installed the ADT plugin as well. If you have not
@@ -43,12 +41,12 @@
 <p>To install a platform in Eclipse:</p>
 
 <ol>
-  
+
   <li>In the Android SDK and AVD Manager, choose <strong>Available
-Packages</strong> in the left panel.</li> 
- 
-<li>Click the repository site checkbox to display the components
-available for installation.</li>
+Packages</strong> in the left panel.</li>
+
+<li>In the right panel, expand the Android Repository list to display
+the components available for installation.</li>
 
   <li>Select at least one platform to install, and click <strong>Install
 Selected</strong>. If you aren't sure which platform to install, use the latest
@@ -59,15 +57,14 @@
 
 <div class="sidebox-wrapper">
   <div class="sidebox">
-    <p>To learn more about how to use AVDs and the options 
-       available to you, refer to the 
-       <a href="{@docRoot}guide/developing/tools/avd.html">Android 
-       Virtual Devices</a> document.</p>
+    <p>To learn more about how to use AVDs and the options
+       available to you, see <a href="{@docRoot}guide/developing/devices/index.html">Managing
+       Virtual Devices</a>.</p>
   </div>
 </div>
 
 <p>In this tutorial, you will run your application in the Android Emulator.
-Before you can launch the emulator, you must create an 
+Before you can launch the emulator, you must create an
 Android Virtual Device (AVD). An AVD defines the system image and
 device settings used by the emulator.</p>
 
@@ -75,32 +72,31 @@
 
 <p>To create an AVD:</p>
 <ol>
-  <li>In Eclipse, choose <strong>Window &gt; Android SDK and AVD Manager</strong>. 
+  <li>In Eclipse, select <strong>Window &gt; Android SDK and AVD Manager</strong>.</li>
   <li>Select <strong>Virtual Devices</strong> in the left panel.</li>
 
-  <li>Click <strong>New</strong>. </li>
- 
-
-<p>The <strong>Create New AVD</strong> dialog appears.</p>
-
+  <li>Click <strong>New...</strong>.
+    <p>The <strong>Create New AVD</strong> dialog appears.</p>
+  </li>
   <li>Type the name of the AVD, such as "my_avd".</li>
-  <li>Choose a target. The target is the platform (that is, the version of the Android
-    SDK, such as 2.1) you want to run on the emulator. </li>
-  
-  <p>You can ignore the rest of the fields for now. </p>
+  <li>Choose a target.
+    <p>The target is the platform (that is, the version of the Android SDK, such as 2.3.3) you want
+    to run on the emulator. For this tutorial, choose the latest platform that you have installed
+    and ignore the rest of the fields.</p>
+  </li>
   <li>Click <strong>Create AVD</strong>.</li>
 </ol>
 <h2 id="create">Create a New Android Project</h2>
 
-<p>After you've created an AVD, the next step is to start a new
-Android project in Eclipse.</p>
+<p>After you've created an AVD you can move to the next step and start a new Android project in
+Eclipse.</p>
 
 <ol>
-    <li>From Eclipse, select <strong>File &gt; New &gt; Project</strong>. 
+    <li>In Eclipse, select <strong>File &gt; New &gt; Project...</strong>.
       <p>If the ADT
       Plugin for Eclipse has been successfully installed, the resulting dialog
       should have a folder labeled "Android" which should contain
-      "Android Project". (After you create one or more Android projects, an entry for 
+      "Android Project". (After you create one or more Android projects, an entry for
       "Android XML File" will also be available.)</p>
     </li>
 
@@ -111,6 +107,8 @@
     <li>Fill in the project details with the following values:
         <ul>
           <li><em>Project name:</em> HelloAndroid</li>
+          <li><em>Build Target:</em> Select a platform version that is equal to or lower than the
+          target you chose for your AVD.</li>
           <li><em>Application name:</em> Hello, Android</li>
           <li><em>Package name:</em> com.example.helloandroid (or your own private namespace)</li>
           <li><em>Create Activity:</em> HelloAndroid</li>
@@ -120,55 +118,60 @@
         <a href="images/hello_world_1.png"><img src="images/hello_world_1.png" style="height:400px" alt="" /></a>
 
         <p>Here is a description of each field:</p>
-      
+
         <dl>
             <dt><em>Project Name</em></dt>
-                <dd>This is the Eclipse Project name &mdash; the name of the directory
-                that will contain the project files.</dd>
+                <dd>This is the Eclipse project name &mdash; the name of the directory
+                that contains the project files.</dd>
+            <dt><em>Build Target</em></dt>
+                <dd>This is the version of the Android SDK that you're using to build your
+                application. For example, if you choose Android 2.1, your application will be
+                compiled against the Android 2.1 platform library. The target you choose here
+                does not have to match the target you chose for your AVD; however, the target must
+                be equal to or lower than the target you chose for your AVD. Android
+                applications are forward-compatible, which means an application will run on the
+                platform against which it is built as well as all platforms that are released in the
+                future. For example, an application that is built against the 2.1 platform library
+                will run normally on an AVD or device that is running the 2.3.3. The reverse is not
+                true.</dd>
             <dt><em>Application Name</em></dt>
                 <dd>This is the human-readable title for your application &mdash; the name that
-                will appear on the Android device.</dd>
+                appears on the Android device.</dd>
             <dt><em>Package Name</em></dt>
                 <dd>This is the package namespace (following the same rules as for
                   packages in the Java programming language) that you want all your source code to
                   reside under. This also sets the package name under which the stub
-                  Activity will be generated.
+                  Activity is generated.
                   <p>Your package name must be unique across
-                  all packages installed on the Android system; for this reason, it's 
+                  all packages installed on the Android system; for this reason, it's
                   important to use a standard domain-style package for your
                   applications.  The example above uses the "com.example" namespace, which is
                   a namespace reserved for example documentation &mdash;
                   when you develop your own applications, you should use a namespace that's
                   appropriate to your organization or entity.</p></dd>
             <dt><em>Create Activity</em></dt>
-                <dd>This is the name for the class stub that will be generated by the plugin.
-                This will be a subclass of Android's {@link android.app.Activity} class.  An 
-                Activity is simply a class that can run and do work. It can create a UI if it 
+                <dd>This is the name for the class stub that is generated by the plugin.
+                This is a subclass of Android's {@link android.app.Activity} class.  An
+                Activity is simply a class that can run and do work. It can create a UI if it
                 chooses, but it doesn't need to. As the checkbox suggests, this is optional, but an
                 Activity is almost always used as the basis for an application.</dd>
             <dt><em>Min SDK Version</em></dt>
-                <dd>This value specifies the minimum API Level required by your application. For
-                more information, see <a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a>.
+                <dd>This value specifies the minimum API Level on which your application will run.
+                The <em>Min SDK Version</em> should be the same as the <em>Build Target</em> you
+                chose. For example, if the <em>Build Target</em> is Android 2.1, then the <em>Min
+                SDK Version</em> should be 7 or lower (it can never be higher than 7). For more
+                information, see
+                <a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a>.
                </dd>
         </dl>
-      
-        <p><em>Other fields</em>: The checkbox for "Use default location" allows you to change 
-        the location on disk where the project's files will be generated and stored. "Build Target"
-        is the platform target that your application will be compiled against 
-        (this should be selected automatically, based on your Min SDK Version).</p>
 
-        <p class="note">Notice that the "Build Target" you've selected uses the Android 1.1
-        platform. This means that your application will be compiled against the Android 1.1 
-        platform library. If you recall, the AVD created above runs on the Android 1.5 platform.
-        These don't have to match; Android applications are forward-compatible, so an application
-        built against the 1.1 platform library will run normally on the 1.5 platform. The reverse
-        is not true.</p>
+        <p><em>Other fields</em>: The checkbox for "Use default location" allows you to change
+        the location on disk where the project's files are generated and stored.</p>
     </li>
 </ol>
 
-<p>Your Android project is now ready. It should be visible in the Package
-Explorer on the left.
-Open the <code>HelloAndroid.java</code> file, located inside <em>HelloAndroid > src > 
+<p>Your Android project is now ready. It should be visible in the Package Explorer on the left. Open
+the <code>HelloAndroid.java</code> file, located inside <em>HelloAndroid > src >
 com.example.helloandroid</em>). It should look like this:</p>
 
 <pre>
@@ -186,13 +189,13 @@
     }
 }</pre>
 
-<p>Notice that the class is based on the {@link android.app.Activity} class. An Activity is a 
-single application entity that is used to perform actions. An application may have many separate 
-activities, but the user interacts with them one at a time. The 
-{@link android.app.Activity#onCreate(Bundle) onCreate()} method  
-will be called by the Android system when your Activity starts &mdash;
+<p>Notice that the class is based on the {@link android.app.Activity} class. An Activity is a
+single application entity that is used to perform actions. An application may have many separate
+activities, but the user interacts with them one at a time. The
+{@link android.app.Activity#onCreate(Bundle) onCreate()} method
+is called by the Android system when your Activity starts &mdash;
 it is where you should perform all initialization and UI setup. An activity is not required to
-have a user interface, but usually will.</p>
+have a user interface, but usually does.</p>
 
 <p>Now let's modify some code! </p>
 
@@ -221,11 +224,12 @@
 }</pre>
 
 <p class="note"><strong>Tip:</strong> An easy way to add import packages to your project is
-to press <strong>Ctrl-Shift-O</strong> (<strong>Cmd-Shift-O</strong>, on Mac). This is an Eclipse 
-shortcut that identifies missing packages based on your code and adds them for you.</p>
+to press <strong>Ctrl-Shift-O</strong> (<strong>Cmd-Shift-O</strong>, on Mac). This is an Eclipse
+shortcut that identifies missing packages based on your code and adds them for you. You may have
+to expand the <code>import</code> statements in your code for this to work.</p>
 
 <p>An Android user interface is composed of hierarchies of objects called
-Views. A {@link android.view.View} is a drawable object used as an element in your UI layout, 
+Views. A {@link android.view.View} is a drawable object used as an element in your UI layout,
 such as a button, image, or (in this case) a text label. Each of these objects is a subclass
 of the View class and the subclass that handles text is {@link android.widget.TextView}.</p>
 
@@ -237,7 +241,7 @@
 HelloAndroid class is a subclass of Activity, it is also a Context. So, you can
 pass <code>this</code> as your Context reference to the TextView.</p>
 
-<p>Next, you define the text content with 
+<p>Next, you define the text content with
 {@link android.widget.TextView#setText(CharSequence) setText()}.</p>
 
 <p>Finally, you pass the TextView to
@@ -277,7 +281,7 @@
 
 <p>The "Hello, Android" you see in the grey bar is actually the application title. The Eclipse plugin
 creates this automatically (the string is defined in the <code>res/values/strings.xml</code> file and referenced
-by your <code>AndroidManifest.xml</code> file). The text below the title is the actual text that you have 
+by your <code>AndroidManifest.xml</code> file). The text below the title is the actual text that you have
 created in the TextView object.</p>
 
 <p>That concludes the basic "Hello World" tutorial, but you should continue reading for some more
@@ -307,7 +311,7 @@
   android:text=&quot;@string/hello&quot;/&gt;</pre>
 
 <p>The general structure of an Android XML layout file is simple: it's a tree
-of XML elements, wherein each node is the name of a View class 
+of XML elements, wherein each node is the name of a View class
 (this example, however, is just one View element). You can use the
 name of any class that extends {@link android.view.View} as an element in your XML layouts,
 including custom View classes you define in your own code. This
@@ -316,7 +320,7 @@
 by the web development model, wherein you can separate the presentation of your
 application (its UI) from the application logic used to fetch and fill in data.</p>
 
-<p>In the above XML example, there's just one View element: the <code>TextView</code>, 
+<p>In the above XML example, there's just one View element: the <code>TextView</code>,
 which has five XML attributes.  Here's a summary of what they mean:</p>
 
 <table>
@@ -343,7 +347,7 @@
             </td>
             <td>
                 This attribute assigns a unique identifier to the <code>TextView</code> element.
-                You can use the assigned ID to reference this View from your source code or from other 
+                You can use the assigned ID to reference this View from your source code or from other
                 XML resource declarations.
             </td>
         </tr>
@@ -352,7 +356,7 @@
                 <code>android:layout_width</code>
             </td>
             <td>
-                This attribute defines how much of the available width on the screen this View should consume. 
+                This attribute defines how much of the available width on the screen this View should consume.
                 In this case, it's the only View so you want it to take up the entire screen, which is what a value of "fill_parent" means.<br>
             </td>
         </tr>
@@ -369,7 +373,7 @@
                 <code>android:text</code>
             </td>
             <td>
-                This sets the text that the TextView should display. In this example, you use a string 
+                This sets the text that the TextView should display. In this example, you use a string
                 resource instead of a hard-coded string value.
                 The <em>hello</em> string is defined in the <em>res/values/strings.xml</em> file. This is the
                 recommended practice for inserting strings to your application, because it makes the localization
@@ -396,17 +400,17 @@
 </div>
 </div>
 
-<p>The Eclipse plugin automatically creates one of these layout files for you: main.xml. 
-In the "Hello World" application you just completed, this file was ignored and you created a 
+<p>The Eclipse plugin automatically creates one of these layout files for you: main.xml.
+In the "Hello World" application you just completed, this file was ignored and you created a
 layout programmatically. This was meant to teach you more
-about the Android framework, but you should almost always define your layout 
+about the Android framework, but you should almost always define your layout
 in an XML file instead of in your code.
-The following procedures will instruct you how to change your 
+The following procedures will instruct you how to change your
 existing application to use an XML layout.</p>
 
 <ol>
   <li>In the Eclipse Package Explorer, expand the
-<code>/res/layout/</code> folder and open <code>main.xml</code> (once opened, you might need to click 
+<code>/res/layout/</code> folder and open <code>main.xml</code> (once opened, you might need to click
 the "main.xml" tab at the bottom of the window to see the XML source). Replace the contents with
 the following XML:
 
@@ -421,7 +425,7 @@
 
 <li>Inside the <code>res/values/</code> folder, open <code>strings.xml</code>.
 This is where you should save all default text strings for your user interface. If you're using Eclipse, then
-ADT will have started you with two strings, <em>hello</em> and <em>app_name</em>. 
+ADT will have started you with two strings, <em>hello</em> and <em>app_name</em>.
 Revise <em>hello</em> to something else. Perhaps "Hello, Android! I am a string resource!"
 The entire file should now look like this:
 <pre>
@@ -450,11 +454,11 @@
     }
 }</pre>
 
-<p>When you make this change, type it by hand to try the 
+<p>When you make this change, type it by hand to try the
 code-completion feature. As you begin typing "R.layout.main" the plugin will offer you
 suggestions. You'll find that it helps in a lot of situations.</p>
 
-<p>Instead of passing <code>setContentView()</code> a View object, you give it a reference 
+<p>Instead of passing <code>setContentView()</code> a View object, you give it a reference
 to the layout resource.
 The resource is identified as <code>R.layout.main</code>, which is actually a compiled object representation of
 the layout defined in <code>/res/layout/main.xml</code>. The Eclipse plugin automatically creates this reference for
@@ -464,25 +468,27 @@
 </ol>
 
 <p>Now re-run your application &mdash; because you've created a launch configuration, all
-you need to do is click the green arrow icon to run, or select 
+you need to do is click the green arrow icon to run, or select
 <strong>Run &gt; Run History &gt; Android Activity</strong>. Other than the change to the TextView
 string, the application looks the same. After all, the point was to show that the two different
 layout approaches produce identical results.</p>
 
-<p class="note"><strong>Tip:</strong> Use the shortcut <strong>Ctrl-F11</strong> 
-(<strong>Cmd-Shift-F11</strong>, on Mac) to run your currently visible application.</p>
+<p class="note"><strong>Note:</strong> You may have to unlock the screen on the emulator to see
+your application &mdash; just as you would unlock the screen on a device. If you have problems
+running the emulator, see <a href="{@docRoot}guide/developing/devices/emulator.html">Using the
+Android Emulator</a>.</p>
 
 <p>Continue reading for an introduction
 to debugging and a little more information on using other IDEs. When you're ready to learn more,
 read <a href="{@docRoot}guide/topics/fundamentals.html">Application
-Fundamentals</a> for an introduction to all the elements that make Android applications work. 
+Fundamentals</a> for an introduction to all the elements that make Android applications work.
 Also refer to the <a href="{@docRoot}guide/index.html">Developer's Guide</a>
 introduction page for an overview of the <em>Dev Guide</em> documentation.</p>
 
 
 <div class="special">
 <h3>R class</h3>
-<p>In Eclipse, open the file named <code>R.java</code> (in the <code>gen/</code> [Generated Java Files] folder). 
+<p>In Eclipse, open the file named <code>R.java</code> (in the <code>gen/</code> [Generated Java Files] folder).
 It should look something like this:</p>
 
 <pre>
@@ -510,16 +516,17 @@
 <p>A project's <code>R.java</code> file is an index into all the resources defined in the
 file. You use this class in your source code as a sort of short-hand
 way to refer to resources you've included in your project. This is
-particularly powerful with the code-completion features of IDEs like Eclipse 
+particularly powerful with the code-completion features of IDEs like Eclipse
 because it lets you quickly and interactively locate the specific reference
 you're looking for.</p>
 
-<p>It's possible yours looks slighly different than this (perhaps the hexadecimal values are different). 
+<p>It's possible yours looks slightly different than this (perhaps the hexadecimal values are
+different).
 For now, notice the inner class named "layout", and its
 member field "main". The Eclipse plugin noticed the XML
 layout file named main.xml and generated a class for it here.  As you add other
 resources to your project (such as strings in the <code>res/values/string.xml</code> file or drawables inside
-the <code>res/drawable/</code> direcory) you'll see <code>R.java</code> change to keep up.</p>
+the <code>res/drawable/</code> directory) you'll see <code>R.java</code> change to keep up.</p>
 <p>When not using Eclipse, this class file will be generated for you at build time (with the Ant tool).</p>
 <p><em>You should never edit this file by hand.</em></p>
 </div>
@@ -554,9 +561,9 @@
 
 <p>Press "Force Quit" to terminate the application and close the emulator window.</p>
 
-<p>To find out more about the error, set a breakpoint in your source code 
-on the line <code>Object o = null;</code> (double-click on the marker bar next to the source code line). Then select <strong>Run &gt; Debug History &gt; Hello, 
-Android</strong> from the menu to enter debug mode. Your app will restart in the 
+<p>To find out more about the error, set a breakpoint in your source code
+on the line <code>Object o = null;</code> (double-click on the marker bar next to the source code line). Then select <strong>Run &gt; Debug History &gt; Hello,
+Android</strong> from the menu to enter debug mode. Your app will restart in the
 emulator, but this time it will suspend when it reaches the breakpoint you
 set. You can then step through the code in Eclipse's Debug Perspective,
 just as you would for any other application.</p>
@@ -565,36 +572,36 @@
 
 
 <h2 id="noeclipse">Creating the Project without Eclipse</h2>
-  
+
   <p>If you don't use Eclipse (such as if you prefer another IDE, or simply use text
   editors and command line tools) then the Eclipse plugin can't help you.
   Don't worry though &mdash; you don't lose any functionality just because you don't
   use Eclipse.</p>
-  
+
   <p>The Android Plugin for Eclipse is really just a wrapper around a set of tools
   included with the Android SDK. (These tools, like the emulator, aapt, adb,
-  ddms, and others are <a href="{@docRoot}guide/developing/tools/index.html">documented elsewhere.</a>) 
+  ddms, and others are <a href="{@docRoot}guide/developing/tools/index.html">documented elsewhere.</a>)
   Thus, it's possible to
   wrap those tools with another tool, such as an 'ant' build file.</p>
-  
+
   <p>The Android SDK includes a tool named "android" that can be
   used to create all the source code and directory stubs for your project, as well
   as an ant-compatible <code>build.xml</code> file. This allows you to build your project
   from the command line, or integrate it with the IDE of your choice.</p>
-  
+
   <p>For example, to create a HelloAndroid project similar to the one created
   in Eclipse, use this command:</p>
-  
+
   <pre>
 android create project \
     --package com.example.helloandroid \
-    --activity HelloAndroid \ 
+    --activity HelloAndroid \
     --target 2 \
-    --path <em>&lt;path-to-your-project></em>/HelloAndroid 
+    --path <em>&lt;path-to-your-project></em>/HelloAndroid
 </pre>
 
-  <p>This creates the required folders and files for the project at the location 
+  <p>This creates the required folders and files for the project at the location
   defined by the <em>path</em>.</p>
-  
-  <p>For more information on how to use the SDK tools to create and build projects, please read 
+
+  <p>For more information on how to use the SDK tools to create and build projects, please read
 <a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.</p>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index cde997e..b4d94f3 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -358,22 +358,7 @@
      */
     public Paint(Paint paint) {
         mNativePaint = native_initWithPaint(paint.mNativePaint);
-        mHasCompatScaling = paint.mHasCompatScaling;
-        mCompatScaling = paint.mCompatScaling;
-        mInvCompatScaling = paint.mInvCompatScaling;
-        mBidiFlags = paint.mBidiFlags;
-        hasShadow = paint.hasShadow;
-        mColorFilter = paint.mColorFilter;
-        mMaskFilter = paint.mMaskFilter;
-        mPathEffect = paint.mPathEffect;
-        mRasterizer = paint.mRasterizer;
-        mShader = paint.mShader;
-        mTypeface = paint.mTypeface;
-        mXfermode = paint.mXfermode;
-        shadowColor = paint.shadowColor;
-        shadowDx = paint.shadowDx;
-        shadowDy = paint.shadowDy;
-        shadowRadius = paint.shadowRadius;
+        setClassVariablesFrom(paint);
     }
 
     /** Restores the paint to its default settings. */
@@ -396,21 +381,36 @@
         if (this != src) {
             // copy over the native settings
             native_set(mNativePaint, src.mNativePaint);
-            // copy over our java settings
-            mColorFilter    = src.mColorFilter;
-            mMaskFilter     = src.mMaskFilter;
-            mPathEffect     = src.mPathEffect;
-            mRasterizer     = src.mRasterizer;
-            mShader         = src.mShader;
-            mTypeface       = src.mTypeface;
-            mXfermode       = src.mXfermode;
-            mHasCompatScaling = src.mHasCompatScaling;
-            mCompatScaling    = src.mCompatScaling;
-            mInvCompatScaling = src.mInvCompatScaling;
-            mBidiFlags      = src.mBidiFlags;
+            setClassVariablesFrom(src);
         }
     }
 
+    /**
+     * Set all class variables using current values from the given
+     * {@link Paint}.
+     */
+    private void setClassVariablesFrom(Paint paint) {
+        mColorFilter = paint.mColorFilter;
+        mMaskFilter = paint.mMaskFilter;
+        mPathEffect = paint.mPathEffect;
+        mRasterizer = paint.mRasterizer;
+        mShader = paint.mShader;
+        mTypeface = paint.mTypeface;
+        mXfermode = paint.mXfermode;
+
+        mHasCompatScaling = paint.mHasCompatScaling;
+        mCompatScaling = paint.mCompatScaling;
+        mInvCompatScaling = paint.mInvCompatScaling;
+
+        hasShadow = paint.hasShadow;
+        shadowDx = paint.shadowDx;
+        shadowDy = paint.shadowDy;
+        shadowRadius = paint.shadowRadius;
+        shadowColor = paint.shadowColor;
+
+        mBidiFlags = paint.mBidiFlags;
+    }
+
     /** @hide */
     public void setCompatibilityScaling(float factor) {
         if (factor == 1.0) {
diff --git a/include/utils/threads.h b/include/utils/threads.h
index c84a9b4..c685625 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -143,6 +143,13 @@
 // in either case errno is set.  Thread ID zero means current thread.
 extern int androidSetThreadPriority(pid_t tid, int prio);
 
+// Get the current scheduling group of a particular thread. Normally returns
+// one of the ANDROID_TGROUP constants other than ANDROID_TGROUP_DEFAULT.
+// Returns ANDROID_TGROUP_DEFAULT if no pthread support (e.g. on host) or if
+// scheduling groups are disabled.  Returns INVALID_OPERATION if unexpected error.
+// Thread ID zero means current thread.
+extern int androidGetThreadSchedulingGroup(pid_t tid);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/rs/scriptc/rs_time.rsh b/libs/rs/scriptc/rs_time.rsh
index f8f297d..60e3dee 100644
--- a/libs/rs/scriptc/rs_time.rsh
+++ b/libs/rs/scriptc/rs_time.rsh
@@ -15,43 +15,96 @@
  */
 
 /** @file rs_time.rsh
- *  \brief Time routines
+ *  \brief Renderscript time routines
  *
- *
+ *  This file contains Renderscript functions relating to time and date
+ *  manipulation.
  */
 
 #ifndef __RS_TIME_RSH__
 #define __RS_TIME_RSH__
 
+/**
+ * Calendar time interpreted as seconds elapsed since the Epoch (00:00:00 on
+ * January 1, 1970, Coordinated Universal Time (UTC)).
+ */
 typedef int rs_time_t;
 
+/**
+ * Data structure for broken-down time components.
+ *
+ * tm_sec   - Seconds after the minute. This ranges from 0 to 59, but possibly
+ *            up to 60 for leap seconds.
+ * tm_min   - Minutes after the hour. This ranges from 0 to 59.
+ * tm_hour  - Hours past midnight. This ranges from 0 to 23.
+ * tm_mday  - Day of the month. This ranges from 1 to 31.
+ * tm_mon   - Months since January. This ranges from 0 to 11.
+ * tm_year  - Years since 1900.
+ * tm_wday  - Days since Sunday. This ranges from 0 to 6.
+ * tm_yday  - Days since January 1. This ranges from 0 to 365.
+ * tm_isdst - Flag to indicate whether daylight saving time is in effect. The
+ *            value is positive if it is in effect, zero if it is not, and
+ *            negative if the information is not available.
+ */
 typedef struct {
-    int tm_sec;
-    int tm_min;
-    int tm_hour;
-    int tm_mday;
-    int tm_mon;
-    int tm_year;
-    int tm_wday;
-    int tm_yday;
-    int tm_isdst;
+    int tm_sec;     ///< seconds
+    int tm_min;     ///< minutes
+    int tm_hour;    ///< hours
+    int tm_mday;    ///< day of the month
+    int tm_mon;     ///< month
+    int tm_year;    ///< year
+    int tm_wday;    ///< day of the week
+    int tm_yday;    ///< day of the year
+    int tm_isdst;   ///< daylight savings time
 } rs_tm;
 
+/**
+ * Returns the number of seconds since the Epoch (00:00:00 UTC, January 1,
+ * 1970). If @p timer is non-NULL, the result is also stored in the memory
+ * pointed to by this variable. If an error occurs, a value of -1 is returned.
+ *
+ * @param timer Location to also store the returned calendar time.
+ *
+ * @return Seconds since the Epoch.
+ */
 extern rs_time_t __attribute__((overloadable))
     rsTime(rs_time_t *timer);
 
+/**
+ * Converts the time specified by @p timer into broken-down time and stores it
+ * in @p local. This function also returns a pointer to @p local. If @p local
+ * is NULL, this function does nothing and returns NULL.
+ *
+ * @param local Broken-down time.
+ * @param timer Input time as calendar time.
+ *
+ * @return Pointer to broken-down time (same as input @p local).
+ */
 extern rs_tm * __attribute__((overloadable))
     rsLocaltime(rs_tm *local, const rs_time_t *timer);
 
-// Return the current system clock in milliseconds
+/**
+ * Returns the current system clock (uptime) in milliseconds.
+ *
+ * @return Uptime in milliseconds.
+ */
 extern int64_t __attribute__((overloadable))
     rsUptimeMillis(void);
 
-// Return the current system clock in nanoseconds
+/**
+ * Returns the current system clock (uptime) in nanoseconds.
+ *
+ * @return Uptime in nanoseconds.
+ */
 extern int64_t __attribute__((overloadable))
     rsUptimeNanos(void);
 
-// Return the time in seconds since function was last called in this script.
+/**
+ * Returns the time in seconds since this function was last called in this
+ * script.
+ *
+ * @return Time in seconds.
+ */
 extern float __attribute__((overloadable))
     rsGetDt(void);
 
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index 875beb9..5d5df60 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -89,7 +89,7 @@
  */
 typedef uint32_t uint;
 /**
- * Typedef for unsigned char (use for 64-bit unsigned integers)
+ * Typedef for unsigned long (use for 64-bit unsigned integers)
  */
 typedef uint64_t ulong;
 /**
@@ -102,67 +102,67 @@
 typedef int32_t ssize_t;
 
 /**
- * \brief Opaque handle to a RenderScript element.
+ * \brief Opaque handle to a Renderscript element.
  *
  * See: android.renderscript.Element
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_element;
 /**
- * \brief Opaque handle to a RenderScript type.
+ * \brief Opaque handle to a Renderscript type.
  *
  * See: android.renderscript.Type
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_type;
 /**
- * \brief Opaque handle to a RenderScript allocation.
+ * \brief Opaque handle to a Renderscript allocation.
  *
  * See: android.renderscript.Allocation
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_allocation;
 /**
- * \brief Opaque handle to a RenderScript sampler object.
+ * \brief Opaque handle to a Renderscript sampler object.
  *
  * See: android.renderscript.Sampler
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_sampler;
 /**
- * \brief Opaque handle to a RenderScript script object.
+ * \brief Opaque handle to a Renderscript script object.
  *
  * See: android.renderscript.ScriptC
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_script;
 /**
- * \brief Opaque handle to a RenderScript mesh object.
+ * \brief Opaque handle to a Renderscript mesh object.
  *
  * See: android.renderscript.Mesh
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_mesh;
 /**
- * \brief Opaque handle to a RenderScript ProgramFragment object.
+ * \brief Opaque handle to a Renderscript ProgramFragment object.
  *
  * See: android.renderscript.ProgramFragment
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_fragment;
 /**
- * \brief Opaque handle to a RenderScript ProgramVertex object.
+ * \brief Opaque handle to a Renderscript ProgramVertex object.
  *
  * See: android.renderscript.ProgramVertex
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_vertex;
 /**
- * \brief Opaque handle to a RenderScript sampler object.
+ * \brief Opaque handle to a Renderscript ProgramRaster object.
  *
- * See: android.renderscript.Sampler
+ * See: android.renderscript.ProgramRaster
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_raster;
 /**
- * \brief Opaque handle to a RenderScript ProgramStore object.
+ * \brief Opaque handle to a Renderscript ProgramStore object.
  *
  * See: android.renderscript.ProgramStore
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_store;
 /**
- * \brief Opaque handle to a RenderScript font object.
+ * \brief Opaque handle to a Renderscript font object.
  *
  * See: android.renderscript.Font
  */
@@ -170,163 +170,163 @@
 
 /**
  * Vector version of the basic float type.
- * Provides two float fields packed into a single 64bit field with 64 bit
+ * Provides two float fields packed into a single 64 bit field with 64 bit
  * alignment.
  */
 typedef float float2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic float type. Provides three float fields packed
- * into a single 128bit field with 128 bit alignment.
+ * into a single 128 bit field with 128 bit alignment.
  */
 typedef float float3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic float type.
- * Provides four float fields packed into a single 128bit field with 128bit
+ * Provides four float fields packed into a single 128 bit field with 128 bit
  * alignment.
  */
 typedef float float4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic double type. Provides two double fields packed
- * into a single 128bit field with 128bit alignment.
+ * into a single 128 bit field with 128 bit alignment.
  */
 typedef double double2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic double type. Provides three double fields packed
- * into a single 256bit field with 256bit alignment.
+ * into a single 256 bit field with 256 bit alignment.
  */
 typedef double double3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic double type. Provides four double fields packed
- * into a single 256bit field with 256bit alignment.
+ * into a single 256 bit field with 256 bit alignment.
  */
 typedef double double4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic uchar type. Provides two uchar fields packed
- * into a single 16bit field with 16bit alignment.
+ * into a single 16 bit field with 16 bit alignment.
  */
 typedef uchar uchar2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic uchar type. Provides three uchar fields packed
- * into a single 32bit field with 32bit alignment.
+ * into a single 32 bit field with 32 bit alignment.
  */
 typedef uchar uchar3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic uchar type. Provides four uchar fields packed
- * into a single 32bit field with 32bit alignment.
+ * into a single 32 bit field with 32 bit alignment.
  */
 typedef uchar uchar4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic ushort type. Provides two ushort fields packed
- * into a single 32bit field with 32bit alignment.
+ * into a single 32 bit field with 32 bit alignment.
  */
 typedef ushort ushort2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic ushort type. Provides three ushort fields packed
- * into a single 64bit field with 64bit alignment.
+ * into a single 64 bit field with 64 bit alignment.
  */
 typedef ushort ushort3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic ushort type. Provides four ushort fields packed
- * into a single 64bit field with 64bit alignment.
+ * into a single 64 bit field with 64 bit alignment.
  */
 typedef ushort ushort4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic uint type. Provides two uint fields packed into a
- * single 64bit field with 64bit alignment.
+ * single 64 bit field with 64 bit alignment.
  */
 typedef uint uint2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic uint type. Provides three uint fields packed into
- * a single 128bit field with 128bit alignment.
+ * a single 128 bit field with 128 bit alignment.
  */
 typedef uint uint3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic uint type. Provides four uint fields packed into
- * a single 128bit field with 128bit alignment.
+ * a single 128 bit field with 128 bit alignment.
  */
 typedef uint uint4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic ulong type. Provides two ulong fields packed into
- * a single 128bit field with 128bit alignment.
+ * a single 128 bit field with 128 bit alignment.
  */
 typedef ulong ulong2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic ulong type. Provides three ulong fields packed
- * into a single 256bit field with 256bit alignment.
+ * into a single 256 bit field with 256 bit alignment.
  */
 typedef ulong ulong3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic ulong type. Provides four ulong fields packed
- * into a single 256bit field with 256bit alignment.
+ * into a single 256 bit field with 256 bit alignment.
  */
 typedef ulong ulong4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic char type. Provides two char fields packed into a
- * single 16bit field with 16bit alignment.
+ * single 16 bit field with 16 bit alignment.
  */
 typedef char char2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic char type. Provides three char fields packed into
- * a single 32bit field with 32bit alignment.
+ * a single 32 bit field with 32 bit alignment.
  */
 typedef char char3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic char type. Provides four char fields packed into
- * a single 32bit field with 32bit alignment.
+ * a single 32 bit field with 32 bit alignment.
  */
 typedef char char4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic short type. Provides two short fields packed into
- * a single 32bit field with 32bit alignment.
+ * a single 32 bit field with 32 bit alignment.
  */
 typedef short short2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic short type. Provides three short fields packed
- * into a single 64bit field with 64bit alignment.
+ * into a single 64 bit field with 64 bit alignment.
  */
 typedef short short3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic short type. Provides four short fields packed
- * into a single 64bit field with 64bit alignment.
+ * into a single 64 bit field with 64 bit alignment.
  */
 typedef short short4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic int type. Provides two int fields packed into a
- * single 64bit field with 64bit alignment.
+ * single 64 bit field with 64 bit alignment.
  */
 typedef int int2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic int type. Provides three int fields packed into a
- * single 128bit field with 128bit alignment.
+ * single 128 bit field with 128 bit alignment.
  */
 typedef int int3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic int type. Provides two four fields packed into a
- * single 128bit field with 128bit alignment.
+ * single 128 bit field with 128 bit alignment.
  */
 typedef int int4 __attribute__((ext_vector_type(4)));
 
 /**
  * Vector version of the basic long type. Provides two long fields packed into a
- * single 128bit field with 128bit alignment.
+ * single 128 bit field with 128 bit alignment.
  */
 typedef long long2 __attribute__((ext_vector_type(2)));
 /**
  * Vector version of the basic long type. Provides three long fields packed into
- * a single 256bit field with 256bit alignment.
+ * a single 256 bit field with 256 bit alignment.
  */
 typedef long long3 __attribute__((ext_vector_type(3)));
 /**
  * Vector version of the basic long type. Provides four long fields packed into
- * a single 256bit field with 256bit alignment.
+ * a single 256 bit field with 256 bit alignment.
  */
 typedef long long4 __attribute__((ext_vector_type(4)));
 
@@ -369,8 +369,6 @@
 
 /**
  * \brief Enum for selecting cube map faces
- *
- * Used todo-alexst
  */
 typedef enum {
     RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X = 0,
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index d18c0a2..02c380b 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -368,6 +368,41 @@
     return rc;
 }
 
+int androidGetThreadSchedulingGroup(pid_t tid)
+{
+    int ret = ANDROID_TGROUP_DEFAULT;
+
+#if defined(HAVE_PTHREADS)
+    // convention is to not call get/set_sched_policy methods if disabled by property
+    pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
+    if (gDoSchedulingGroup) {
+        SchedPolicy policy;
+        // get_sched_policy does not support tid == 0
+        if (tid == 0) {
+            tid = androidGetTid();
+        }
+        if (get_sched_policy(tid, &policy) < 0) {
+            ret = INVALID_OPERATION;
+        } else {
+            switch (policy) {
+            case SP_BACKGROUND:
+                ret = ANDROID_TGROUP_BG_NONINTERACT;
+                break;
+            case SP_FOREGROUND:
+                ret = ANDROID_TGROUP_FG_BOOST;
+                break;
+            default:
+                // should not happen, as enum SchedPolicy does not have any other values
+                ret = INVALID_OPERATION;
+                break;
+            }
+        }
+    }
+#endif
+
+    return ret;
+}
+
 namespace android {
 
 /*
diff --git a/media/java/android/media/videoeditor/VideoEditorProfile.java b/media/java/android/media/videoeditor/VideoEditorProfile.java
index ecdcdfb..202a2df 100755
--- a/media/java/android/media/videoeditor/VideoEditorProfile.java
+++ b/media/java/android/media/videoeditor/VideoEditorProfile.java
@@ -91,7 +91,7 @@
             case MediaProperties.VCODEC_H263:
             case MediaProperties.VCODEC_H264:
             case MediaProperties.VCODEC_MPEG4:
-                 level = native_get_videoeditor_export_profile(vidCodec);
+                 level = native_get_videoeditor_export_level(vidCodec);
                  break;
             default :
                throw new IllegalArgumentException("Unsupported video codec" + vidCodec);
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 40e055c..cd4b1ef 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -72,16 +72,14 @@
 status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) {
     LOGV("setVideoSurface");
 
-    mPlayer->setSurface(surface);
-    return OK;
+    return mPlayer->setSurface(surface);
 }
 
 status_t StagefrightPlayer::setVideoSurfaceTexture(
         const sp<ISurfaceTexture> &surfaceTexture) {
     LOGV("setVideoSurfaceTexture");
 
-    mPlayer->setSurfaceTexture(surfaceTexture);
-    return OK;
+    return mPlayer->setSurfaceTexture(surfaceTexture);
 }
 
 status_t StagefrightPlayer::prepare() {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index bc42a42..142dda0 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1152,22 +1152,26 @@
     return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
 }
 
-void AwesomePlayer::setSurface(const sp<Surface> &surface) {
+status_t AwesomePlayer::setSurface(const sp<Surface> &surface) {
     Mutex::Autolock autoLock(mLock);
 
     mSurface = surface;
-    setNativeWindow_l(surface);
+    return setNativeWindow_l(surface);
 }
 
-void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
+status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
     Mutex::Autolock autoLock(mLock);
 
     mSurface.clear();
+
+    status_t err;
     if (surfaceTexture != NULL) {
-        setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
+        err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
     } else {
-        setNativeWindow_l(NULL);
+        err = setNativeWindow_l(NULL);
     }
+
+    return err;
 }
 
 void AwesomePlayer::shutdownVideoDecoder_l() {
@@ -1190,11 +1194,11 @@
     LOGI("video decoder shutdown completed");
 }
 
-void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
+status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
     mNativeWindow = native;
 
     if (mVideoSource == NULL) {
-        return;
+        return OK;
     }
 
     LOGI("attempting to reconfigure to use new surface");
@@ -1206,7 +1210,12 @@
 
     shutdownVideoDecoder_l();
 
-    CHECK_EQ(initVideoDecoder(), (status_t)OK);
+    status_t err = initVideoDecoder();
+
+    if (err != OK) {
+        LOGE("failed to reinstantiate video decoder after surface change.");
+        return err;
+    }
 
     if (mLastVideoTimeUs >= 0) {
         mSeeking = SEEK;
@@ -1217,6 +1226,8 @@
     if (wasPlaying) {
         play_l();
     }
+
+    return OK;
 }
 
 void AwesomePlayer::setAudioSink(
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 14476d3..24cf77c 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -84,8 +84,8 @@
 
     bool isPlaying() const;
 
-    void setSurface(const sp<Surface> &surface);
-    void setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
+    status_t setSurface(const sp<Surface> &surface);
+    status_t setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
     status_t setLooping(bool shouldLoop);
 
@@ -298,7 +298,7 @@
     void postAudioSeekComplete_l();
 
     void shutdownVideoDecoder_l();
-    void setNativeWindow_l(const sp<ANativeWindow> &native);
+    status_t setNativeWindow_l(const sp<ANativeWindow> &native);
 
     bool isStreamingHTTP() const;
     void sendCacheStats();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index b396223..0810643 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -181,9 +181,10 @@
     }
 
     // Note: This test is to assume the mediaserver's pid is 34
-    private void stressVideoRecord(int frameRate, int width, int height, int videoFormat,
+    private boolean stressVideoRecord(int frameRate, int width, int height, int videoFormat,
             int outFormat, String outFile, boolean videoOnly) {
         // Video recording
+        boolean doesTestFail = false;
         for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
             MediaRecorder mRecorder = new MediaRecorder();
             try {
@@ -212,8 +213,11 @@
             } catch (Exception e) {
                 Log.v("record video failed ", e.toString());
                 mRecorder.release();
+                doesTestFail = true;
+                break;
             }
         }
+        return !doesTestFail;
     }
 
     public void stressAudioRecord(String filePath) {
@@ -366,8 +370,8 @@
         Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut, true));
         output.write("H263 video record only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
-            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
-                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
+            assertTrue(stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
+                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true));
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
@@ -386,8 +390,8 @@
         Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut, true));
         output.write("MPEG4 video record only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
-            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
-                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
+            assertTrue(stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
+                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true));
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
@@ -407,8 +411,8 @@
         Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut, true));
         output.write("Audio and h263 video record\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
-            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
-                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false);
+            assertTrue(stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
+                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false));
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index 9629702..40cc7d8 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -20,6 +20,7 @@
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.IccCard.State;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.TransportControlView;
 import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
 
 import java.util.ArrayList;
@@ -52,8 +53,6 @@
     public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
     private static final long INSTRUCTION_RESET_DELAY = 2000; // time until instruction text resets
 
-    private static final int SHOW_WIDGET = 8;
-    private static final int HIDE_WIDGET = 9;
     private static final int INSTRUCTION_TEXT = 10;
     private static final int CARRIER_TEXT = 11;
     private static final int CARRIER_HELP_TEXT = 12;
@@ -71,7 +70,7 @@
     private TextView mStatus1View;
     private TextView mOwnerInfoView;
     private TextView mAlarmStatusView;
-    private View mTransportView;
+    private TransportControlView mTransportView;
 
     // Top-level container view for above views
     private View mContainer;
@@ -162,7 +161,7 @@
         mStatus1View = (TextView) findViewById(R.id.status1);
         mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
         mOwnerInfoView = (TextView) findViewById(R.id.propertyOf);
-        mTransportView = findViewById(R.id.transport);
+        mTransportView = (TransportControlView) findViewById(R.id.transport);
         mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
         if (mEmergencyCallButton != null) {
             mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
@@ -192,20 +191,6 @@
                 mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn()));
     }
 
-    public void enterWidgetMode() {
-        if (mTransportView != null) {
-            mTransportView.setVisibility(View.VISIBLE);
-            update(SHOW_WIDGET, null);
-        }
-    }
-
-    public void leaveWidgetMode() {
-        if (mTransportView != null) {
-            mTransportView.setVisibility(View.GONE);
-            update(HIDE_WIDGET, null);
-        }
-    }
-
     private boolean inWidgetMode() {
         return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE;
     }
@@ -248,7 +233,8 @@
      * @param lockIcon
      */
     public void setHelpMessage(int textResId, int lockIcon) {
-        mHelpMessageText = getText(textResId).toString();
+        final CharSequence tmp = getText(textResId);
+        mHelpMessageText = tmp == null ? null : tmp.toString();
         update(HELP_MESSAGE_TEXT, mHelpMessageText);
     }
 
@@ -603,15 +589,6 @@
         public void onPhoneStateChanged(String newState) {
             updateEmergencyCallButtonState();
         }
-
-        public void onTransportControlStateChanged(int state) {
-            // TODO: define what state means
-            if (state == 0) {
-                leaveWidgetMode();
-            } else {
-                enterWidgetMode();
-            }
-        }
     };
 
     private SimStateCallback mSimStateCallback = new SimStateCallback() {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 77f1932..2955de3 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -25,6 +25,7 @@
 import static android.os.BatteryManager.BATTERY_STATUS_FULL;
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
 import android.media.AudioManager;
+import android.media.IRemoteControlClient;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Message;
@@ -93,8 +94,6 @@
     private static final int MSG_SIM_STATE_CHANGE = 304;
     private static final int MSG_RINGER_MODE_CHANGED = 305;
     private static final int MSG_PHONE_STATE_CHANGED = 306;
-    private static final int MSG_TRANSPORT_CONTROL_STATE_CHANGED = 307;
-
 
     /**
      * When we receive a
@@ -171,9 +170,6 @@
                     case MSG_PHONE_STATE_CHANGED:
                         handlePhoneStateChanged((String)msg.obj);
                         break;
-                    case MSG_TRANSPORT_CONTROL_STATE_CHANGED:
-                        handleTransportControlStateChanged(msg.arg1);
-                        break;
                 }
             }
         };
@@ -263,23 +259,10 @@
                     String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
                 }
-                // TODO
-                else if ("android.media.TRANSPORT_CONTROL_CHANGED".equals(action)) {
-                    int state = intent.getIntExtra("state", 0);
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_TRANSPORT_CONTROL_STATE_CHANGED,
-                            state));
-                }
             }
         }, filter);
     }
 
-    protected void handleTransportControlStateChanged(int state) {
-        if (DEBUG) Log.d(TAG, "handleTransportControlStateChanged()");
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onTransportControlStateChanged(state);
-        }
-    }
-
     protected void handlePhoneStateChanged(String newState) {
         if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
         for (int i = 0; i < mInfoCallbacks.size(); i++) {
@@ -465,11 +448,6 @@
          */
         void onPhoneStateChanged(String newState);
 
-        /**
-         * Called when AudioService informs us of a change to the transport control client.
-         *
-         */
-        void onTransportControlStateChanged(int state);
     }
 
     /**
@@ -567,4 +545,5 @@
     public void reportFailedAttempt() {
         mFailedAttempts++;
     }
+
 }
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 70772eb..9c14734 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -17,8 +17,11 @@
 package com.android.internal.policy.impl;
 
 import com.android.internal.R;
+import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockScreenWidgetCallback;
+import com.android.internal.widget.TransportControlView;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
@@ -31,6 +34,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
@@ -64,6 +68,8 @@
  */
 public class LockPatternKeyguardView extends KeyguardViewBase {
 
+    private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
+
     static final boolean DEBUG_CONFIGURATION = false;
 
     // time after launching EmergencyDialer before the screen goes blank.
@@ -84,6 +90,8 @@
     private boolean mScreenOn = false;
     private boolean mEnableFallback = false; // assume no fallback UI until we know better
 
+    private boolean mShowLockBeforeUnlock = false;
+
     /**
      * The current {@link KeyguardScreen} will use this to communicate back to us.
      */
@@ -148,7 +156,7 @@
      * Keeps track of what mode the current unlock screen is (cached from most recent computation in
      * {@link #getUnlockMode}).
      */
-    private UnlockMode mUnlockScreenMode;
+    private UnlockMode mUnlockScreenMode = UnlockMode.Unknown;
 
     private boolean mForgotPattern;
 
@@ -164,8 +172,6 @@
      */
     private final LockPatternUtils mLockPatternUtils;
 
-    private UnlockMode mCurrentUnlockMode = UnlockMode.Unknown;
-
     /**
      * The current configuration.
      */
@@ -173,7 +179,23 @@
 
     private Runnable mRecreateRunnable = new Runnable() {
         public void run() {
-            recreateScreens();
+            updateScreen(mMode, false);
+        }
+    };
+
+    private LockScreenWidgetCallback mWidgetCallback = new LockScreenWidgetCallback() {
+        public void userActivity(View self) {
+            mKeyguardScreenCallback.pokeWakelock(TRANSPORT_USERACTIVITY_TIMEOUT);
+        }
+
+        public void requestShow(View view) {
+            if (DEBUG) Log.v(TAG, "View " + view + " requested show transports");
+            view.setVisibility(View.VISIBLE);
+        }
+
+        public void requestHide(View view) {
+            if (DEBUG) Log.v(TAG, "View " + view + " requested hide transports");
+            view.setVisibility(View.GONE);
         }
     };
 
@@ -204,16 +226,11 @@
 
         mConfiguration = context.getResources().getConfiguration();
         mEnableFallback = false;
-
-        mRequiresSim =
-                TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
-
+        mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
         mUpdateMonitor = updateMonitor;
         mLockPatternUtils = lockPatternUtils;
         mWindowController = controller;
 
-        mMode = getInitialMode();
-
         mKeyguardScreenCallback = new KeyguardScreenCallback() {
 
             public void goToLockScreen() {
@@ -224,7 +241,7 @@
                     mIsVerifyUnlockOnly = false;
                     getCallback().keyguardDone(false);
                 } else {
-                    updateScreen(Mode.LockScreen);
+                    updateScreen(Mode.LockScreen, false);
                 }
             }
 
@@ -240,14 +257,14 @@
                 if (!isSecure()) {
                     getCallback().keyguardDone(true);
                 } else {
-                    updateScreen(Mode.UnlockScreen);
+                    updateScreen(Mode.UnlockScreen, false);
                 }
             }
 
             public void forgotPattern(boolean isForgotten) {
                 if (mEnableFallback) {
                     mForgotPattern = isForgotten;
-                    updateScreen(Mode.UnlockScreen);
+                    updateScreen(Mode.UnlockScreen, false);
                 }
             }
 
@@ -260,7 +277,6 @@
             }
 
             public void recreateMe(Configuration config) {
-                mConfiguration = config;
                 removeCallbacks(mRecreateRunnable);
                 post(mRecreateRunnable);
             }
@@ -330,7 +346,7 @@
                         showAlmostAtAccountLoginDialog();
                     } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
                         mLockPatternUtils.setPermanentlyLocked(true);
-                        updateScreen(mMode);
+                        updateScreen(mMode, false);
                     }
                 } else {
                     final boolean showTimeout =
@@ -358,21 +374,8 @@
         setFocusableInTouchMode(true);
         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
 
-        // create both the lock and unlock screen so they are quickly available
-        // when the screen turns on
-        mLockScreen = createLockScreen();
-        addView(mLockScreen);
-        final UnlockMode unlockMode = getUnlockMode();
-        if (DEBUG) Log.d(TAG,
-            "LockPatternKeyguardView ctor: about to createUnlockScreenFor; mEnableFallback="
-            + mEnableFallback);
-        mUnlockScreen = createUnlockScreenFor(unlockMode);
-        mUnlockScreenMode = unlockMode;
-
+        updateScreen(getInitialMode(), false);
         maybeEnableFallback(context);
-
-        addView(mUnlockScreen);
-        updateScreen(mMode);
     }
 
     private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
@@ -449,7 +452,7 @@
     public void reset() {
         mIsVerifyUnlockOnly = false;
         mForgotPattern = false;
-        updateScreen(getInitialMode());
+        updateScreen(getInitialMode(), false);
     }
 
     @Override
@@ -457,7 +460,7 @@
         mScreenOn = false;
         mForgotPattern = false;
         if (mMode == Mode.LockScreen) {
-           ((KeyguardScreen) mLockScreen).onPause();
+            ((KeyguardScreen) mLockScreen).onPause();
         } else {
             ((KeyguardScreen) mUnlockScreen).onPause();
         }
@@ -467,50 +470,54 @@
     public void onScreenTurnedOn() {
         mScreenOn = true;
         if (mMode == Mode.LockScreen) {
-           ((KeyguardScreen) mLockScreen).onResume();
+            ((KeyguardScreen) mLockScreen).onResume();
         } else {
             ((KeyguardScreen) mUnlockScreen).onResume();
         }
     }
 
     private void recreateLockScreen() {
-        if (mLockScreen.getVisibility() == View.VISIBLE) {
-            ((KeyguardScreen) mLockScreen).onPause();
+        if (mLockScreen != null) {
+            if (mLockScreen.getVisibility() == View.VISIBLE) {
+                ((KeyguardScreen) mLockScreen).onPause();
+            }
+            ((KeyguardScreen) mLockScreen).cleanUp();
+            removeView(mLockScreen);
         }
-        ((KeyguardScreen) mLockScreen).cleanUp();
-        removeView(mLockScreen);
 
         mLockScreen = createLockScreen();
         mLockScreen.setVisibility(View.INVISIBLE);
         addView(mLockScreen);
     }
 
-    private void recreateUnlockScreen() {
-        if (mUnlockScreen.getVisibility() == View.VISIBLE) {
-            ((KeyguardScreen) mUnlockScreen).onPause();
+    private void recreateUnlockScreen(UnlockMode unlockMode) {
+        if (mUnlockScreen != null) {
+            if (mUnlockScreen.getVisibility() == View.VISIBLE) {
+                ((KeyguardScreen) mUnlockScreen).onPause();
+            }
+            ((KeyguardScreen) mUnlockScreen).cleanUp();
+            removeView(mUnlockScreen);
         }
-        ((KeyguardScreen) mUnlockScreen).cleanUp();
-        removeView(mUnlockScreen);
 
-        final UnlockMode unlockMode = getUnlockMode();
         mUnlockScreen = createUnlockScreenFor(unlockMode);
         mUnlockScreen.setVisibility(View.INVISIBLE);
-        mUnlockScreenMode = unlockMode;
         addView(mUnlockScreen);
     }
 
-    private void recreateScreens() {
-        recreateLockScreen();
-        recreateUnlockScreen();
-        updateScreen(mMode);
-    }
-
     @Override
     protected void onDetachedFromWindow() {
         removeCallbacks(mRecreateRunnable);
         super.onDetachedFromWindow();
     }
 
+    protected void onConfigurationChanged(Configuration newConfig) {
+        Resources resources = getResources();
+        mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
+        mConfiguration = newConfig;
+        if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
+        updateScreen(mMode, true /* force */);
+    }
+
     @Override
     protected boolean dispatchHoverEvent(MotionEvent event) {
         // Do not let the screen to get locked while the user is disabled and touch
@@ -529,7 +536,7 @@
         if (keyCode == KeyEvent.KEYCODE_MENU && isSecure() && (mMode == Mode.LockScreen)
                 && (mUpdateMonitor.getSimState() != IccCard.State.PUK_REQUIRED)) {
             if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
-            updateScreen(Mode.UnlockScreen);
+            updateScreen(Mode.UnlockScreen, false);
             getCallback().pokeWakelock();
         } else {
             if (DEBUG) Log.d(TAG, "poking wake lock immediately");
@@ -542,24 +549,31 @@
         if (!isSecure()) {
             // non-secure keyguard screens are successfull by default
             getCallback().keyguardDone(true);
-        } else if (mUnlockScreenMode != UnlockMode.Pattern) {
-            // can only verify unlock when in pattern mode
+        } else if (mUnlockScreenMode != UnlockMode.Pattern
+                && mUnlockScreenMode != UnlockMode.Password) {
+            // can only verify unlock when in pattern/password mode
             getCallback().keyguardDone(false);
         } else {
             // otherwise, go to the unlock screen, see if they can verify it
             mIsVerifyUnlockOnly = true;
-            updateScreen(Mode.UnlockScreen);
+            updateScreen(Mode.UnlockScreen, false);
         }
     }
 
     @Override
     public void cleanUp() {
-        ((KeyguardScreen) mLockScreen).onPause();
-        ((KeyguardScreen) mLockScreen).cleanUp();
-        this.removeView(mLockScreen);
-        ((KeyguardScreen) mUnlockScreen).onPause();
-        ((KeyguardScreen) mUnlockScreen).cleanUp();
-        this.removeView(mUnlockScreen);
+        if (mLockScreen != null) {
+            ((KeyguardScreen) mLockScreen).onPause();
+            ((KeyguardScreen) mLockScreen).cleanUp();
+            this.removeView(mLockScreen);
+            mLockScreen = null;
+        }
+        if (mUnlockScreen != null) {
+            ((KeyguardScreen) mUnlockScreen).onPause();
+            ((KeyguardScreen) mUnlockScreen).cleanUp();
+            this.removeView(mUnlockScreen);
+            mUnlockScreen = null;
+        }
     }
 
     private boolean isSecure() {
@@ -587,19 +601,30 @@
         return secure;
     }
 
-    private void updateScreen(final Mode mode) {
+    private void updateScreen(Mode mode, boolean force) {
 
         if (DEBUG_CONFIGURATION) Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode
                 + " last mode=" + mMode, new RuntimeException());
 
         mMode = mode;
 
-        // Re-create the unlock screen if necessary. This is primarily required to properly handle
-        // SIM state changes. This typically happens when this method is called by reset()
-        if (mode == Mode.UnlockScreen && mCurrentUnlockMode != getUnlockMode()) {
-            recreateUnlockScreen();
+        // Re-create the lock screen if necessary
+        if (mode == Mode.LockScreen || mShowLockBeforeUnlock) {
+            if (force || mLockScreen == null) {
+                recreateLockScreen();
+            }
         }
 
+        // Re-create the unlock screen if necessary. This is primarily required to properly handle
+        // SIM state changes. This typically happens when this method is called by reset()
+        if (mode == Mode.UnlockScreen) {
+            final UnlockMode unlockMode = getUnlockMode();
+            if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
+                recreateUnlockScreen(unlockMode);
+            }
+        }
+
+        // visibleScreen should never be null
         final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
         final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
 
@@ -613,7 +638,7 @@
         }
 
         if (mScreenOn) {
-            if (goneScreen.getVisibility() == View.VISIBLE) {
+            if (goneScreen != null && goneScreen.getVisibility() == View.VISIBLE) {
                 ((KeyguardScreen) goneScreen).onPause();
             }
             if (visibleScreen.getVisibility() != View.VISIBLE) {
@@ -621,7 +646,9 @@
             }
         }
 
-        goneScreen.setVisibility(View.GONE);
+        if (goneScreen != null) {
+            goneScreen.setVisibility(View.GONE);
+        }
         visibleScreen.setVisibility(View.VISIBLE);
         requestLayout();
 
@@ -632,12 +659,14 @@
     }
 
     View createLockScreen() {
-        return new LockScreen(
+        View lockView = new LockScreen(
                 mContext,
                 mConfiguration,
                 mLockPatternUtils,
                 mUpdateMonitor,
                 mKeyguardScreenCallback);
+        initializeTransportControlView(lockView);
+        return lockView;
     }
 
     View createUnlockScreenFor(UnlockMode unlockMode) {
@@ -691,7 +720,7 @@
                 // regular pattern unlock UI, regardless of the value of
                 // mUnlockScreenMode or whether or not we're in the
                 // "permanently locked" state.)
-                unlockView = createUnlockScreenFor(UnlockMode.Pattern);
+                return createUnlockScreenFor(UnlockMode.Pattern);
             }
         } else if (unlockMode == UnlockMode.Password) {
             unlockView = new PasswordUnlockScreen(
@@ -703,10 +732,22 @@
         } else {
             throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
         }
-        mCurrentUnlockMode = unlockMode;
+        initializeTransportControlView(unlockView);
+        mUnlockScreenMode = unlockMode;
         return unlockView;
     }
 
+    private void initializeTransportControlView(View view) {
+        com.android.internal.widget.TransportControlView tcv =
+                (TransportControlView) view.findViewById(R.id.transport);
+        if (tcv == null) {
+            if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
+        } else {
+            tcv.setVisibility(View.GONE); // hide tcv until we get the callback below to show it.
+            tcv.setCallback(mWidgetCallback);
+        }
+    }
+
     /**
      * Given the current state of things, what should be the initial mode of
      * the lock screen (lock or unlock).
@@ -718,16 +759,10 @@
                         !mLockPatternUtils.isPukUnlockScreenEnable())) {
             return Mode.LockScreen;
         } else {
-            // Show LockScreen first for any screen other than Pattern unlock.
-            final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
-                    == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-
-            boolean showLockBeforeUnlock = getResources()
-                    .getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
-            if (isSecure() && (usingLockPattern || !showLockBeforeUnlock)) {
-                return Mode.UnlockScreen;
-            } else {
+            if (!isSecure() || mShowLockBeforeUnlock) {
                 return Mode.LockScreen;
+            } else {
+                return Mode.UnlockScreen;
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index ce3bc74..2f2d3b7 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -347,7 +347,8 @@
 
     public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
         // Check if this was the result of hitting the enter key
-        if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE) {
+        if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
+                || actionId == EditorInfo.IME_ACTION_NEXT) {
             verifyPasswordAndUnlock();
             return true;
         }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 744fa50..d617af8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -151,7 +151,7 @@
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(),
         mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),
-        mBtNrec(false)
+        mBtNrecIsOff(false)
 {
 }
 
@@ -751,15 +751,15 @@
         String8 value;
         if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
             Mutex::Autolock _l(mLock);
-            bool btNrec = (value == AUDIO_PARAMETER_VALUE_ON);
-            if (mBtNrec != btNrec) {
+            bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
+            if (mBtNrecIsOff != btNrecIsOff) {
                 for (size_t i = 0; i < mRecordThreads.size(); i++) {
                     sp<RecordThread> thread = mRecordThreads.valueAt(i);
                     RecordThread::RecordTrack *track = thread->track();
                     if (track != NULL) {
                         audio_devices_t device = (audio_devices_t)(
                                 thread->device() & AUDIO_DEVICE_IN_ALL);
-                        bool suspend = audio_is_bluetooth_sco_device(device) && btNrec;
+                        bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
                         thread->setEffectSuspended(FX_IID_AEC,
                                                    suspend,
                                                    track->sessionId());
@@ -768,7 +768,7 @@
                                                    track->sessionId());
                     }
                 }
-                mBtNrec = btNrec;
+                mBtNrecIsOff = btNrecIsOff;
             }
         }
         return final_result;
@@ -4394,7 +4394,7 @@
         mTrack = track.get();
         // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
         bool suspend = audio_is_bluetooth_sco_device(
-                (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrec();
+                (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
         setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
         setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
     }
@@ -4619,7 +4619,7 @@
                 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
                 if (mTrack != NULL) {
                     bool suspend = audio_is_bluetooth_sco_device(
-                            (audio_devices_t)value) && mAudioFlinger->btNrec();
+                            (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
                     setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
                     setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
                 }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1141f6c..1ceb0ec 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -210,7 +210,7 @@
 
                 uint32_t    getMode() { return mMode; }
 
-                bool        btNrec() { return mBtNrec; }
+                bool        btNrecIsOff() { return mBtNrecIsOff; }
 
 private:
                             AudioFlinger();
@@ -1389,7 +1389,7 @@
                 DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
                 volatile int32_t                    mNextUniqueId;
                 uint32_t                            mMode;
-                bool                                mBtNrec;
+                bool                                mBtNrecIsOff;
 
                 Vector<AudioSessionRef*> mAudioSessionRefs;
 };
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index bfcf8e0..e39712e 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2491,7 +2491,8 @@
 
     bool resetNeeded = false;
     if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
-            | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT))) {
+            | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
+            | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {
         // Configure device sources, surface dimensions, orientation and
         // scaling factors.
         configureSurface(when, &resetNeeded);
@@ -2523,17 +2524,17 @@
         }
     }
 
-    if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
+    if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
+        // The device is a touch screen.
+        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
+        // The device is a pointing device like a track pad.
+        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+    } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
             || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
         // The device is a cursor device with a touch pad attached.
         // By default don't use the touch pad to move the pointer.
         mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
-    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
-        // The device is a pointing device like a track pad.
-        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
-    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
-        // The device is a touch screen.
-        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
     } else {
         // The device is a touch pad of unknown purpose.
         mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
@@ -2681,18 +2682,19 @@
     bool deviceModeChanged;
     if (mDeviceMode != oldDeviceMode) {
         deviceModeChanged = true;
-
-        if (mDeviceMode == DEVICE_MODE_POINTER) {
-            if (mPointerController == NULL) {
-                mPointerController = getPolicy()->obtainPointerController(getDeviceId());
-            }
-        } else {
-            mPointerController.clear();
-        }
-
         mOrientedRanges.clear();
     }
 
+    // Create pointer controller if needed.
+    if (mDeviceMode == DEVICE_MODE_POINTER ||
+            (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
+        if (mPointerController == NULL) {
+            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+        }
+    } else {
+        mPointerController.clear();
+    }
+
     bool orientationChanged = mSurfaceOrientation != orientation;
     if (orientationChanged) {
         mSurfaceOrientation = orientation;
@@ -3380,7 +3382,7 @@
         cookPointerData();
 
         // Dispatch the touches either directly or by translation through a pointer on screen.
-        if (mPointerController != NULL) {
+        if (mDeviceMode == DEVICE_MODE_POINTER) {
             for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
                 uint32_t id = idBits.clearFirstMarkedBit();
                 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
@@ -3418,6 +3420,17 @@
 
             dispatchPointerUsage(when, policyFlags, pointerUsage);
         } else {
+            if (mDeviceMode == DEVICE_MODE_DIRECT
+                    && mConfig.showTouches && mPointerController != NULL) {
+                mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
+                mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+
+                mPointerController->setButtonState(mCurrentButtonState);
+                mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
+                        mCurrentCookedPointerData.idToIndex,
+                        mCurrentCookedPointerData.touchingIdBits);
+            }
+
             dispatchHoverExit(when, policyFlags);
             dispatchTouches(when, policyFlags);
             dispatchHoverEnterAndMove(when, policyFlags);
@@ -3442,7 +3455,7 @@
 }
 
 void TouchInputMapper::timeoutExpired(nsecs_t when) {
-    if (mPointerController != NULL) {
+    if (mDeviceMode == DEVICE_MODE_POINTER) {
         if (mPointerUsage == POINTER_USAGE_GESTURES) {
             dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
         }
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index bad96df..cd3ea37 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -56,6 +56,9 @@
         // The display size or orientation changed.
         CHANGE_DISPLAY_INFO = 1 << 2,
 
+        // The visible touches option changed.
+        CHANGE_SHOW_TOUCHES = 1 << 3,
+
         // All devices must be reopened.
         CHANGE_MUST_REOPEN = 1 << 31,
     };
@@ -140,6 +143,9 @@
     // will cover this portion of the display diagonal.
     float pointerGestureZoomSpeedRatio;
 
+    // True to show the location of touches on the touch screen as spots.
+    bool showTouches;
+
     InputReaderConfiguration() :
             virtualKeyQuietTime(0),
             pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
@@ -155,7 +161,8 @@
             pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees
             pointerGestureSwipeMaxWidthRatio(0.25f),
             pointerGestureMovementSpeedRatio(0.8f),
-            pointerGestureZoomSpeedRatio(0.3f) { }
+            pointerGestureZoomSpeedRatio(0.3f),
+            showTouches(false) { }
 
     bool getDisplayInfo(int32_t displayId, bool external,
             int32_t* width, int32_t* height, int32_t* orientation) const;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index bfca851..3815c3b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -17,6 +17,8 @@
 package com.android.server;
 
 import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
@@ -1418,6 +1420,9 @@
         // do this before we broadcast the change
         handleConnectivityChange(prevNetType, doReset);
 
+        final Intent immediateIntent = new Intent(intent);
+        immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
+        sendStickyBroadcast(immediateIntent);
         sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
         /*
          * If the failover network is already connected, then immediately send
@@ -1476,11 +1481,13 @@
     }
 
     private void sendConnectedBroadcast(NetworkInfo info) {
-        sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
+        sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
+        sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
     }
 
     private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
-        sendGeneralBroadcastDelayed(info, ConnectivityManager.CONNECTIVITY_ACTION, delayMs);
+        sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
+        sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs);
     }
 
     private void sendInetConditionBroadcast(NetworkInfo info) {
@@ -1559,6 +1566,10 @@
         }
 
         intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
+
+        final Intent immediateIntent = new Intent(intent);
+        immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
+        sendStickyBroadcast(immediateIntent);
         sendStickyBroadcast(intent);
         /*
          * If the failover network is already connected, then immediately send
@@ -1576,8 +1587,7 @@
             }
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             if (DBG) {
-                log("sendStickyBroadcast: NetworkInfo=" +
-                    intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
+                log("sendStickyBroadcast: action=" + intent.getAction());
             }
 
             mContext.sendStickyBroadcast(intent);
@@ -1588,7 +1598,10 @@
         if (delayMs <= 0) {
             sendStickyBroadcast(intent);
         } else {
-            if (DBG) log("sendStickyBroadcastDelayed: delayMs=" + delayMs + " intent=" + intent);
+            if (DBG) {
+                log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action="
+                        + intent.getAction());
+            }
             mHandler.sendMessageDelayed(mHandler.obtainMessage(
                     EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
         }
@@ -2281,7 +2294,6 @@
                 case EVENT_SEND_STICKY_BROADCAST_INTENT:
                 {
                     Intent intent = (Intent)msg.obj;
-                    log("EVENT_SEND_STICKY_BROADCAST_INTENT: sendStickyBroadcast intent=" + intent);
                     sendStickyBroadcast(intent);
                     break;
                 }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 7a3a344..6ee20bb 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -101,6 +101,7 @@
     private Vibrator mVibrator = new Vibrator();
 
     // for enabling and disabling notification pulse behavior
+    private boolean mScreenOn = true;
     private boolean mInCall = false;
     private boolean mNotificationPulseEnabled;
 
@@ -344,9 +345,19 @@
                         cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart);
                     }
                 }
+            } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                // Keep track of screen on/off state, but do not turn off the notification light
+                // until user passes through the lock screen or views the notification.
+                mScreenOn = true;
+            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                mScreenOn = false;
             } else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
-                mInCall = (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK));
+                mInCall = (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
+                        TelephonyManager.EXTRA_STATE_OFFHOOK));
                 updateNotificationPulse();
+            } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
+                // turn off LED when user passes through lock screen
+                mNotificationLight.turnOff();
             }
         }
     };
@@ -417,6 +428,7 @@
         filter.addAction(Intent.ACTION_SCREEN_ON);
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_USER_PRESENT);
         mContext.registerReceiver(mIntentReceiver, filter);
         IntentFilter pkgFilter = new IntentFilter();
         pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -1057,8 +1069,8 @@
             }
         }
 
-        // Don't flash while we are in a call
-        if (mLedNotification == null || mInCall) {
+        // Don't flash while we are in a call or screen is on
+        if (mLedNotification == null || mInCall || mScreenOn) {
             mNotificationLight.turnOff();
         } else {
             int ledARGB = mLedNotification.notification.ledARGB;
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 77f53c2..8af90ff 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -26,7 +26,7 @@
 import static android.content.Intent.ACTION_PACKAGE_ADDED;
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -51,6 +51,7 @@
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute;
 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute;
 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute;
@@ -60,7 +61,6 @@
 import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
-import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 
 import android.app.IActivityManager;
 import android.app.INotificationManager;
@@ -321,7 +321,7 @@
         mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
 
         // watch for network interfaces to be claimed
-        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
+        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
 
         // listen for package/uid changes to update policy
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index bb0a0d1..e0dc96f 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -24,7 +24,7 @@
 import static android.content.Intent.ACTION_SHUTDOWN;
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
@@ -239,7 +239,7 @@
         }
 
         // watch for network interfaces to be claimed
-        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
+        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
 
         // listen for periodic polling events
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index c8b18c8..60333a3 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -94,6 +94,7 @@
     private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
             InputChannel toChannel);
     private static native void nativeSetPointerSpeed(int speed);
+    private static native void nativeSetShowTouches(boolean enabled);
     private static native String nativeDump();
     private static native void nativeMonitor();
     
@@ -147,7 +148,10 @@
         nativeStart();
 
         registerPointerSpeedSettingObserver();
+        registerShowTouchesSettingObserver();
+
         updatePointerSpeedFromSettings();
+        updateShowTouchesFromSettings();
     }
     
     public void setDisplaySize(int displayId, int width, int height,
@@ -454,6 +458,32 @@
         return speed;
     }
 
+    public void updateShowTouchesFromSettings() {
+        int setting = getShowTouchesSetting(0);
+        nativeSetShowTouches(setting != 0);
+    }
+
+    private void registerShowTouchesSettingObserver() {
+        mContext.getContentResolver().registerContentObserver(
+                Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
+                new ContentObserver(mWindowManagerService.mH) {
+                    @Override
+                    public void onChange(boolean selfChange) {
+                        updateShowTouchesFromSettings();
+                    }
+                });
+    }
+
+    private int getShowTouchesSetting(int defaultValue) {
+        int result = defaultValue;
+        try {
+            result = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.SHOW_TOUCHES);
+        } catch (SettingNotFoundException snfe) {
+        }
+        return result;
+    }
+
     public void dump(PrintWriter pw) {
         String dumpStr = nativeDump();
         if (dumpStr != null) {
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index f2a0a71..0a723e8 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -179,6 +179,7 @@
     void setInputDispatchMode(bool enabled, bool frozen);
     void setSystemUiVisibility(int32_t visibility);
     void setPointerSpeed(int32_t speed);
+    void setShowTouches(bool enabled);
 
     /* --- InputReaderPolicyInterface implementation --- */
 
@@ -233,6 +234,9 @@
         // True if pointer gestures are enabled.
         bool pointerGesturesEnabled;
 
+        // Show touches feature enable/disable.
+        bool showTouches;
+
         // Sprite controller singleton, created on first use.
         sp<SpriteController> spriteController;
 
@@ -276,6 +280,7 @@
         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
         mLocked.pointerSpeed = 0;
         mLocked.pointerGesturesEnabled = true;
+        mLocked.showTouches = false;
     }
 
     sp<EventHub> eventHub = new EventHub();
@@ -431,6 +436,8 @@
                 * POINTER_SPEED_EXPONENT);
         outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled;
 
+        outConfig->showTouches = mLocked.showTouches;
+
         outConfig->setDisplayInfo(0, false /*external*/,
                 mLocked.displayWidth, mLocked.displayHeight, mLocked.displayOrientation);
         outConfig->setDisplayInfo(0, true /*external*/,
@@ -678,6 +685,22 @@
             InputReaderConfiguration::CHANGE_POINTER_SPEED);
 }
 
+void NativeInputManager::setShowTouches(bool enabled) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (mLocked.showTouches == enabled) {
+            return;
+        }
+
+        LOGI("Setting show touches feature to %s.", enabled ? "enabled" : "disabled");
+        mLocked.showTouches = enabled;
+    } // release lock
+
+    mInputManager->getReader()->requestRefreshConfiguration(
+            InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
+}
+
 bool NativeInputManager::isScreenOn() {
     return android_server_PowerManagerService_isScreenOn();
 }
@@ -1276,6 +1299,15 @@
     gNativeInputManager->setPointerSpeed(speed);
 }
 
+static void android_server_InputManager_nativeSetShowTouches(JNIEnv* env,
+        jclass clazz, jboolean enabled) {
+    if (checkInputManagerUnitialized(env)) {
+        return;
+    }
+
+    gNativeInputManager->setShowTouches(enabled);
+}
+
 static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
     if (checkInputManagerUnitialized(env)) {
         return NULL;
@@ -1343,6 +1375,8 @@
             (void*) android_server_InputManager_nativeTransferTouchFocus },
     { "nativeSetPointerSpeed", "(I)V",
             (void*) android_server_InputManager_nativeSetPointerSpeed },
+    { "nativeSetShowTouches", "(Z)V",
+            (void*) android_server_InputManager_nativeSetShowTouches },
     { "nativeDump", "()Ljava/lang/String;",
             (void*) android_server_InputManager_nativeDump },
     { "nativeMonitor", "()V",
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index f67d251..e892b5e 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -18,7 +18,7 @@
 
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.SNOOZE_NEVER;
@@ -511,7 +511,7 @@
         future = expectMeteredIfacesChanged();
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         future.get();
         verifyAndReset();
 
@@ -615,7 +615,7 @@
             future = expectMeteredIfacesChanged(TEST_IFACE);
 
             replay();
-            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
             future.get();
             verifyAndReset();
         }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 6dd8cd6..54f3bb0 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -18,7 +18,7 @@
 
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
@@ -180,7 +180,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -232,7 +232,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -322,7 +322,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         verifyAndReset();
 
         // modify some number on wifi, and trigger poll event
@@ -372,7 +372,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         verifyAndReset();
 
         // create some traffic on first network
@@ -410,7 +410,7 @@
         expectNetworkStatsPoll();
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
         verifyAndReset();
 
@@ -452,7 +452,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         verifyAndReset();
 
         // create some traffic
@@ -509,7 +509,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         verifyAndReset();
 
         // create some traffic
@@ -541,7 +541,7 @@
         expectNetworkStatsPoll();
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
         verifyAndReset();
 
@@ -575,7 +575,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         verifyAndReset();
 
         // create some traffic for two apps
@@ -637,7 +637,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
 
         replay();
-        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
         verifyAndReset();
 
         // create some initial traffic
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 134227a..e92a276 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -39,6 +39,7 @@
     CDMALTEPhone mCdmaLtePhone;
 
     private ServiceState  mLteSS;  // The last LTE state from Voice Registration
+    private boolean mNeedToRegForSimLoaded = true;
 
     public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
         super(phone);
@@ -71,7 +72,10 @@
             isSubscriptionFromRuim = false;
             // Register SIM_RECORDS_LOADED dynamically.
             // This is to avoid confilct with RUIM_READY scenario)
-            phone.mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
+            if (mNeedToRegForSimLoaded) {
+                phone.mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
+                mNeedToRegForSimLoaded = false;
+            }
             pollState();
             // Signal strength polling stops when radio is off.
             queueNextSignalStrengthPoll();
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index c1f6785..2cd54d9 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -60,7 +60,9 @@
 
     public native static boolean startSupplicant();
 
-    /* Does a graceful shutdown of supplicant.
+    public native static boolean startP2pSupplicant();
+
+    /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta.
      *
      * Note that underneath we use a harsh-sounding "terminate" supplicant command
      * for a graceful stop and a mild-sounding "stop" interface
@@ -215,6 +217,19 @@
         return doBooleanCommand("WPS_PIN any " + pin);
     }
 
+    public static boolean setPersistentReconnect(boolean enabled) {
+        int value = (enabled == true) ? 1 : 0;
+        return WifiNative.doBooleanCommand("SET persistent_reconnect " + value);
+    }
+
+    public static boolean setDeviceName(String name) {
+        return WifiNative.doBooleanCommand("SET device_name " + name);
+    }
+
+    public static boolean setDeviceType(String type) {
+        return WifiNative.doBooleanCommand("SET device_type " + type);
+    }
+
     public static boolean p2pFind() {
         return doBooleanCommand("P2P_FIND");
     }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index c6f7da2..4fc5e08 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -2524,23 +2524,11 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
-               case CMD_START_DRIVER:
-                   mWakeLock.acquire();
-                   WifiNative.startDriverCommand();
-                   mWakeLock.release();
-                   break;
-                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
-                    SupplicantState state = handleSupplicantStateChange(message);
-                    /* A driver start causes supplicant to first report an INTERFACE_DISABLED
-                     * state before transitioning out of it for connection. Stay in
-                     * DriverStoppedState until we get an INTERFACE_DISABLED state and transition
-                     * to DriverStarting upon getting that
-                     * TODO: Fix this when the supplicant can be made to just transition out of
-                     * INTERFACE_DISABLED state when driver gets started
-                     */
-                    if (state == SupplicantState.INTERFACE_DISABLED) {
-                        transitionTo(mDriverStartingState);
-                    }
+                case CMD_START_DRIVER:
+                    mWakeLock.acquire();
+                    WifiNative.startDriverCommand();
+                    mWakeLock.release();
+                    transitionTo(mDriverStartingState);
                     break;
                 default:
                     return NOT_HANDLED;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index adf13be..f67680d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -50,6 +50,7 @@
 import android.os.Messenger;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -126,6 +127,8 @@
     private static final int WIFI_DISABLE_USER_ACCEPT       =   BASE + 11;
 
     private final boolean mP2pSupported;
+    private final String mDeviceType;
+    private String mDeviceName;
 
     private NetworkInfo mNetworkInfo;
 
@@ -142,6 +145,9 @@
 
         mP2pSupported = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_wifi_p2p_support);
+        mDeviceType = mContext.getResources().getString(
+                com.android.internal.R.string.config_wifi_p2p_device_type);
+        mDeviceName = getDefaultDeviceName();
 
         mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
         mP2pStateMachine.start();
@@ -182,6 +188,14 @@
                 "WifiP2pService");
     }
 
+    /* We use the 4 digits of the ANDROID_ID to have a friendly
+     * default that has low likelihood of collision with a peer */
+    private String getDefaultDeviceName() {
+        String id = Settings.Secure.getString(mContext.getContentResolver(),
+                    Settings.Secure.ANDROID_ID);
+        return "Android_" + id.substring(0,4);
+    }
+
     /**
      * Get a reference to handler. This is used by a client to establish
      * an AsyncChannel communication with WifiP2pService
@@ -514,7 +528,7 @@
                         if (DBG) Slog.w(TAG, "Unable to bring down wlan interface: " + e);
                     }
 
-                    if (WifiNative.startSupplicant()) {
+                    if (WifiNative.startP2pSupplicant()) {
                         mWifiMonitor.startMonitoring();
                         transitionTo(mP2pEnablingState);
                     } else {
@@ -577,6 +591,7 @@
             mNetworkInfo.setIsAvailable(true);
             //Start listening for new connections
             WifiNative.p2pListen();
+            initializeP2pSettings();
         }
 
         @Override
@@ -637,6 +652,22 @@
                     if (mPeers.clear()) sendP2pPeersChangedBroadcast();
                     transitionTo(mP2pDisabledState);
                     sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
+                    break;
+                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+                    mGroup = (WifiP2pGroup) message.obj;
+                    if (DBG) logd(getName() + " group started");
+                    if (mGroup.isGroupOwner()) {
+                        startDhcpServer(mGroup.getInterface());
+                    } else {
+                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
+                                P2pStateMachine.this, mGroup.getInterface());
+                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
+                        WifiP2pDevice groupOwner = mGroup.getOwner();
+                        updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
+                        sendP2pPeersChangedBroadcast();
+                    }
+                    transitionTo(mGroupCreatedState);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -708,21 +739,6 @@
                     sendP2pPeersChangedBroadcast();
                     transitionTo(mInactiveState);
                     break;
-                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
-                    mGroup = (WifiP2pGroup) message.obj;
-                    if (DBG) logd(getName() + " group started");
-                    if (mGroup.isGroupOwner()) {
-                        startDhcpServer(mGroup.getInterface());
-                    } else {
-                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
-                                P2pStateMachine.this, mGroup.getInterface());
-                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
-                        WifiP2pDevice groupOwner = mGroup.getOwner();
-                        updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
-                        sendP2pPeersChangedBroadcast();
-                    }
-                    transitionTo(mGroupCreatedState);
-                    break;
                 case GROUP_NEGOTIATION_TIMED_OUT:
                     if (mGroupNegotiationTimeoutIndex == message.arg1) {
                         if (DBG) logd("Group negotiation timed out");
@@ -760,25 +776,33 @@
                     //After a GO setup, STA connected event comes with interface address
                     String interfaceAddress = (String) message.obj;
                     String deviceAddress = getDeviceAddress(interfaceAddress);
-                    mGroup.addClient(deviceAddress);
-                    updateDeviceStatus(deviceAddress, Status.CONNECTED);
-                    if (DBG) logd(getName() + " ap sta connected");
-                    sendP2pPeersChangedBroadcast();
+                    if (deviceAddress != null) {
+                        mGroup.addClient(deviceAddress);
+                        updateDeviceStatus(deviceAddress, Status.CONNECTED);
+                        if (DBG) logd(getName() + " ap sta connected");
+                        sendP2pPeersChangedBroadcast();
+                    } else {
+                        loge("Connect on unknown device address : " + interfaceAddress);
+                    }
                     break;
                 case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
                     interfaceAddress = (String) message.obj;
                     deviceAddress = getDeviceAddress(interfaceAddress);
-                    updateDeviceStatus(deviceAddress, Status.AVAILABLE);
-                    if (mGroup.removeClient(deviceAddress)) {
-                        if (DBG) logd("Removed client " + deviceAddress);
-                        sendP2pPeersChangedBroadcast();
-                    } else {
-                        if (DBG) logd("Failed to remove client " + deviceAddress);
-                        for (WifiP2pDevice c : mGroup.getClientList()) {
-                            if (DBG) logd("client " + c.deviceAddress);
+                    if (deviceAddress != null) {
+                        updateDeviceStatus(deviceAddress, Status.AVAILABLE);
+                        if (mGroup.removeClient(deviceAddress)) {
+                            if (DBG) logd("Removed client " + deviceAddress);
+                            sendP2pPeersChangedBroadcast();
+                        } else {
+                            if (DBG) logd("Failed to remove client " + deviceAddress);
+                            for (WifiP2pDevice c : mGroup.getClientList()) {
+                                if (DBG) logd("client " + c.deviceAddress);
+                            }
                         }
+                        if (DBG) loge(getName() + " ap sta disconnected");
+                    } else {
+                        loge("Disconnect on unknown device address : " + interfaceAddress);
                     }
-                    if (DBG) loge(getName() + " ap sta disconnected");
                     break;
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
                     DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
@@ -857,6 +881,9 @@
                 case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
                     notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj);
                     break;
+                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+                    Slog.e(TAG, "Duplicate group creation event notice, ignore");
+                    break;
                 case WifiP2pManager.WPS_PBC:
                     WifiNative.wpsPbc();
                     break;
@@ -1117,6 +1144,12 @@
         return null;
     }
 
+    private void initializeP2pSettings() {
+        WifiNative.setPersistentReconnect(true);
+        WifiNative.setDeviceName(mDeviceName);
+        WifiNative.setDeviceType(mDeviceType);
+    }
+
     //State machine initiated requests can have replyTo set to null indicating
     //there are no recepients, we ignore those reply actions
     private void replyToMessage(Message msg, int what) {