Merge "Fix 6583164: Make navbar slippery when shade is open" into jb-dev
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index cb53422..54b5836 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -1301,7 +1301,6 @@
                 "       am display-size [reset|MxN]\n" +
                 "       am to-uri [INTENT]\n" +
                 "       am to-intent-uri [INTENT]\n" +
-                "       am switch-user <USER_ID>\n" +
                 "\n" +
                 "am start: start an Activity.  Options are:\n" +
                 "    -D: enable debugging\n" +
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index f9ff861..88a025e 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1360,22 +1360,19 @@
         System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
         System.err.println("       pm list features");
         System.err.println("       pm list libraries");
-        System.err.println("       pm list users");
         System.err.println("       pm path PACKAGE");
         System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]");
         System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm clear PACKAGE");
-        System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
-        System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
-        System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
+        System.err.println("       pm enable PACKAGE_OR_COMPONENT");
+        System.err.println("       pm disable PACKAGE_OR_COMPONENT");
+        System.err.println("       pm disable-user PACKAGE_OR_COMPONENT");
         System.err.println("       pm grant PACKAGE PERMISSION");
         System.err.println("       pm revoke PACKAGE PERMISSION");
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
         System.err.println("       pm get-install-location");
         System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
-        System.err.println("       pm create-user USER_NAME");
-        System.err.println("       pm remove-user USER_ID");
         System.err.println("");
         System.err.println("pm list packages: prints all packages, optionally only");
         System.err.println("  those whose package name contains the text in FILTER.  Options:");
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index ad4b58f..079b9bd 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -163,7 +163,8 @@
                 new HashMap<Account, Integer>();
         private final Object cacheLock = new Object();
         /** protected by the {@link #cacheLock} */
-        private final HashMap<String, Account[]> accountCache = new HashMap<String, Account[]>();
+        private final HashMap<String, Account[]> accountCache =
+                new LinkedHashMap<String, Account[]>();
         /** protected by the {@link #cacheLock} */
         private HashMap<Account, HashMap<String, String>> userDataCache =
                 new HashMap<Account, HashMap<String, String>>();
@@ -296,7 +297,7 @@
             try {
                 accounts.accountCache.clear();
                 final HashMap<String, ArrayList<String>> accountNamesByType =
-                        new HashMap<String, ArrayList<String>>();
+                        new LinkedHashMap<String, ArrayList<String>>();
                 while (cursor.moveToNext()) {
                     final long accountId = cursor.getLong(0);
                     final String accountType = cursor.getString(1);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 6058bdc..03ee419 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1568,8 +1568,17 @@
         for (int i=0; i<N; i++) {
             Fragment f = mActive.get(i);
             if (f != null) {
+                if (f.mIndex < 0) {
+                    String msg = "Failure saving state: active " + f
+                            + " has cleared index: " + f.mIndex;
+                    Slog.e(TAG, msg);
+                    dump("  ", null, new PrintWriter(new LogWriter(
+                            Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
+                    throw new IllegalStateException(msg);
+                }
+
                 haveFragments = true;
-                
+
                 FragmentState fs = new FragmentState(f);
                 active[i] = fs;
                 
@@ -1621,6 +1630,14 @@
                 added = new int[N];
                 for (int i=0; i<N; i++) {
                     added[i] = mAdded.get(i).mIndex;
+                    if (added[i] < 0) {
+                        String msg = "Failure saving state: active " + mAdded.get(i)
+                                + " has cleared index: " + added[i];
+                        Slog.e(TAG, msg);
+                        dump("  ", null, new PrintWriter(new LogWriter(
+                                Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
+                        throw new IllegalStateException(msg);
+                    }
                     if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
                             + ": " + mAdded.get(i));
                 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3ced82b..036008b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1379,7 +1379,7 @@
             }
         }
 
-        private RemoteViews applyStandardTemplate(int resId) {
+        private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) {
             RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId);
             boolean showLine3 = false;
             boolean showLine2 = false;
@@ -1432,7 +1432,6 @@
                 contentView.setTextViewText(R.id.text, mSubText);
                 if (mContentText != null) {
                     contentView.setTextViewText(R.id.text2, mContentText);
-                    // need to shrink all the type to make sure everything fits
                     contentView.setViewVisibility(R.id.text2, View.VISIBLE);
                     showLine2 = true;
                 } else {
@@ -1450,10 +1449,13 @@
                 }
             }
             if (showLine2) {
-                final Resources res = mContext.getResources();
-                final float subTextSize = res.getDimensionPixelSize(
-                        R.dimen.notification_subtext_size);
-                contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize);
+                if (fitIn1U) {
+                    // need to shrink all the type to make sure everything fits
+                    final Resources res = mContext.getResources();
+                    final float subTextSize = res.getDimensionPixelSize(
+                            R.dimen.notification_subtext_size);
+                    contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize);
+                }
                 // vertical centering
                 contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
             }
@@ -1470,16 +1472,18 @@
                 }
             }
             contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
+            contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE);
             return contentView;
         }
 
         private RemoteViews applyStandardTemplateWithActions(int layoutId) {
-            RemoteViews big = applyStandardTemplate(layoutId);
+            RemoteViews big = applyStandardTemplate(layoutId, false);
 
             int N = mActions.size();
             if (N > 0) {
                 // Log.d("Notification", "has actions: " + mContentText);
                 big.setViewVisibility(R.id.actions, View.VISIBLE);
+                big.setViewVisibility(R.id.action_divider, View.VISIBLE);
                 if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
                 big.removeAllViews(R.id.actions);
                 for (int i=0; i<N; i++) {
@@ -1495,7 +1499,7 @@
             if (mContentView != null) {
                 return mContentView;
             } else {
-                return applyStandardTemplate(R.layout.notification_template_base); // no more special large_icon flavor
+                return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor
             }
         }
 
@@ -1506,7 +1510,7 @@
                 if (mContentView == null) {
                     return applyStandardTemplate(mLargeIcon == null
                             ? R.layout.status_bar_latest_event_ticker
-                            : R.layout.status_bar_latest_event_ticker_large_icon);
+                            : R.layout.status_bar_latest_event_ticker_large_icon, true);
                 } else {
                     return null;
                 }
@@ -1655,12 +1659,9 @@
                 contentView.setViewVisibility(R.id.line1, View.VISIBLE);
             }
 
+            // The last line defaults to the content text or subtext, but can be replaced by mSummaryText
             if (mSummaryText != null && !mSummaryText.equals("")) {
-                contentView.setViewVisibility(R.id.overflow_title, View.VISIBLE);
-                contentView.setTextViewText(R.id.overflow_title, mSummaryText);
-                contentView.setViewVisibility(R.id.line3, View.GONE);
-            } else {
-                contentView.setViewVisibility(R.id.overflow_title, View.GONE);
+                contentView.setTextViewText(R.id.text, mSummaryText);
                 contentView.setViewVisibility(R.id.line3, View.VISIBLE);
             }
 
@@ -1801,6 +1802,8 @@
         }
 
         private RemoteViews makeBigContentView() {
+            // Remove the content text so line3 disappears entirely
+            mBuilder.mContentText = null;
             RemoteViews contentView = getStandardView(R.layout.notification_template_big_text);
             contentView.setTextViewText(R.id.big_text, mBigText);
             contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ad52e13..e180df4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -935,7 +935,17 @@
                 com.android.internal.R.styleable.AndroidManifest_installLocation,
                 PARSE_DEFAULT_INSTALL_LOCATION);
         pkg.applicationInfo.installLocation = pkg.installLocation;
-        
+
+        /* Set the global "forward lock" flag */
+        if ((flags & PARSE_FORWARD_LOCK) != 0) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
+        }
+
+        /* Set the global "on SD card" flag */
+        if ((flags & PARSE_ON_SDCARD) != 0) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
+        }
+
         // Resource boolean are -1, so 1 means we don't know the value.
         int supportsSmallScreens = 1;
         int supportsNormalScreens = 1;
@@ -1726,14 +1736,6 @@
             }
         }
 
-        if ((flags & PARSE_FORWARD_LOCK) != 0) {
-            ai.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
-        }
-
-        if ((flags & PARSE_ON_SDCARD) != 0) {
-            ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
-        }
-
         if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
                 false)) {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 035a7c6..4d9077f 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -736,8 +736,8 @@
                 return;
 
             case CAMERA_MSG_PREVIEW_FRAME:
-                if (mPreviewCallback != null) {
-                    PreviewCallback cb = mPreviewCallback;
+                PreviewCallback pCb = mPreviewCallback;
+                if (pCb != null) {
                     if (mOneShot) {
                         // Clear the callback variable before the callback
                         // in case the app calls setPreviewCallback from
@@ -749,7 +749,7 @@
                         // Set to oneshot mode again.
                         setHasPreviewCallback(true, false);
                     }
-                    cb.onPreviewFrame((byte[])msg.obj, mCamera);
+                    pCb.onPreviewFrame((byte[])msg.obj, mCamera);
                 }
                 return;
 
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 2782dca..e8f87bb 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -24,6 +24,7 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.CursorEntityIterator;
 import android.content.Entity;
 import android.content.EntityIterator;
@@ -7711,9 +7712,19 @@
          */
         public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode,
                 String[] excludeMimes) {
+            // When launching from an Activiy, we don't want to start a new task, but otherwise
+            // we *must* start a new task.  (Otherwise startActivity() would crash.)
+            Context actualContext = context;
+            while ((actualContext instanceof ContextWrapper)
+                    && !(actualContext instanceof Activity)) {
+                actualContext = ((ContextWrapper) actualContext).getBaseContext();
+            }
+            final int intentFlags = (actualContext instanceof Activity)
+                    ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
+                    : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK;
+
             // Launch pivot dialog through intent for now
-            final Intent intent = new Intent(ACTION_QUICK_CONTACT)
-                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+            final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
 
             intent.setData(lookupUri);
             intent.setSourceBounds(target);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8b7ee0e..8630204 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2886,6 +2886,15 @@
             "enabled_accessibility_services";
 
         /**
+         * List of the accessibility services to which the user has graned
+         * permission to put the device into touch exploration mode.
+         *
+         * @hide
+         */
+        public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES =
+            "touch_exploration_granted_accessibility_services";
+
+        /**
          * Whether to speak passwords while in accessibility mode.
          */
         public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
@@ -4292,6 +4301,7 @@
             ACCESSIBILITY_SCRIPT_INJECTION,
             BACKUP_AUTO_RESTORE,
             ENABLED_ACCESSIBILITY_SERVICES,
+            TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
             TOUCH_EXPLORATION_ENABLED,
             ACCESSIBILITY_ENABLED,
             ACCESSIBILITY_SPEAK_PASSWORD,
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 300bc68..08a99d2 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -33,7 +33,11 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Message;
 import android.os.ParcelUuid;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -65,6 +69,10 @@
     private final BluetoothAdapter mAdapter;
     private int   mTargetA2dpState;
     private BluetoothDevice mPlayingA2dpDevice;
+    private IntentBroadcastHandler mIntentBroadcastHandler;
+    private final WakeLock mWakeLock;
+
+    private static final int MSG_CONNECTION_STATE_CHANGED = 0;
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -131,6 +139,11 @@
     public BluetoothA2dpService(Context context, BluetoothService bluetoothService) {
         mContext = context;
 
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BluetoothA2dpService");
+
+        mIntentBroadcastHandler = new IntentBroadcastHandler();
+
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
 
         mBluetoothService = bluetoothService;
@@ -514,17 +527,15 @@
                 adjustOtherSinkPriorities(device);
             }
 
-            Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
-            intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
+            int delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, state);
 
-            if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
-
-            mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state,
-                                                        prevState);
+            mWakeLock.acquire();
+            mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage(
+                                                            MSG_CONNECTION_STATE_CHANGED,
+                                                            prevState,
+                                                            state,
+                                                            device),
+                                                       delay);
         }
     }
 
@@ -586,6 +597,34 @@
         }
     }
 
+    /** Handles A2DP connection state change intent broadcasts. */
+    private class IntentBroadcastHandler extends Handler {
+
+        private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) {
+            Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
+            intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
+
+            if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
+
+            mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state,
+                                                        prevState);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_CONNECTION_STATE_CHANGED:
+                    onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2);
+                    mWakeLock.release();
+                    break;
+            }
+        }
+    }
+
     @Override
     protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 2ea0360..3bb9c01 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -459,6 +459,18 @@
     }
 
     /**
+     * Returns true if the device is a full keyboard.
+     *
+     * @return True if the device is a full keyboard.
+     *
+     * @hide
+     */
+    public boolean isFullKeyboard() {
+        return (mSources & SOURCE_KEYBOARD) == SOURCE_KEYBOARD
+                && mKeyboardType == KEYBOARD_TYPE_ALPHABETIC;
+    }
+
+    /**
      * Gets the name of this input device.
      * @return The input device name.
      */
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index 78984e0..5ffc2c3 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -437,8 +437,10 @@
 
     public void postVolumeChanged(int streamType, int flags) {
         if (hasMessages(MSG_VOLUME_CHANGED)) return;
-        if (mStreamControls == null) {
-            createSliders();
+        synchronized (this) {
+            if (mStreamControls == null) {
+                createSliders();
+            }
         }
         removeMessages(MSG_FREE_RESOURCES);
         obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();
@@ -450,8 +452,10 @@
 
     public void postMuteChanged(int streamType, int flags) {
         if (hasMessages(MSG_VOLUME_CHANGED)) return;
-        if (mStreamControls == null) {
-            createSliders();
+        synchronized (this) {
+            if (mStreamControls == null) {
+                createSliders();
+            }
         }
         removeMessages(MSG_FREE_RESOURCES);
         obtainMessage(MSG_MUTE_CHANGED, streamType, flags).sendToTarget();
@@ -471,10 +475,12 @@
         if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")");
 
         if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
-            if (mActiveStreamType != streamType) {
-                reorderSliders(streamType);
+            synchronized (this) {
+                if (mActiveStreamType != streamType) {
+                    reorderSliders(streamType);
+                }
+                onShowVolumeChanged(streamType, flags);
             }
-            onShowVolumeChanged(streamType, flags);
         }
 
         if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9abe72b..dae9c6a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2283,14 +2283,10 @@
             final ListAdapter adapter = getAdapter();
 
             if ((position == INVALID_POSITION) || (adapter == null)) {
-                // Cannot perform actions on invalid items.
-                info.setEnabled(false);
                 return;
             }
 
             if (!isEnabled() || !adapter.isEnabled(position)) {
-                // Cannot perform actions on invalid items.
-                info.setEnabled(false);
                 return;
             }
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 16490e8..c29dd58 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1416,6 +1416,7 @@
         }
 
         Layout layout = mTextView.getLayout();
+        Layout hintLayout = mTextView.getHintLayout();
         final int offset = mTextView.getSelectionStart();
         final int line = layout.getLineForOffset(offset);
         final int top = layout.getLineTop(line);
@@ -1429,13 +1430,23 @@
             middle = (top + bottom) >> 1;
         }
 
-        updateCursorPosition(0, top, middle, layout.getPrimaryHorizontal(offset));
+        updateCursorPosition(0, top, middle, getPrimaryHorizontal(layout, hintLayout, offset));
 
         if (mCursorCount == 2) {
             updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset));
         }
     }
 
+    private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset) {
+        if (TextUtils.isEmpty(layout.getText()) &&
+                hintLayout != null &&
+                !TextUtils.isEmpty(hintLayout.getText())) {
+            return hintLayout.getPrimaryHorizontal(offset);
+        } else {
+            return layout.getPrimaryHorizontal(offset);
+        }
+    }
+
     /**
      * @return true if the selection mode was actually started.
      */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3e2d43a..131b075 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1312,6 +1312,14 @@
     }
 
     /**
+     * @return the Layout that is currently being used to display the hint text.
+     * This can be null.
+     */
+    final Layout getHintLayout() {
+        return mHintLayout;
+    }
+
+    /**
      * @return the current key listener for this TextView.
      * This will frequently be null for non-EditText TextViews.
      *
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 234cb71..46478ca 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -673,26 +673,29 @@
 
         if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
                 || fromSystem)) {
-            mTopVisibilityView.setAlpha(0);
-            mTopVisibilityView.setTranslationY(-mTopVisibilityView.getHeight());
+            mTopVisibilityView.setTranslationY(0); // because we're about to ask its window loc
+            float startingY = -mTopVisibilityView.getHeight();
+            if (fromSystem) {
+                int topLeft[] = {0, 0};
+                mTopVisibilityView.getLocationInWindow(topLeft);
+                startingY -= topLeft[1];
+            }
+            mTopVisibilityView.setTranslationY(startingY);
             AnimatorSet anim = new AnimatorSet();
-            AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 1));
-            b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY", 0));
+            AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView,
+                    "translationY", 0));
             if (mContentView != null) {
                 b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
-                        -mTopVisibilityView.getHeight(), 0));
+                        startingY, 0));
             }
             if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
-                mSplitView.setAlpha(0);
                 mSplitView.setTranslationY(mSplitView.getHeight());
                 mSplitView.setVisibility(View.VISIBLE);
-                b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1));
                 b.with(ObjectAnimator.ofFloat(mSplitView, "translationY", 0));
             }
             anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
-                    com.android.internal.R.interpolator.decelerate_quad));
-            anim.setDuration(mContext.getResources().getInteger(
-                    com.android.internal.R.integer.config_mediumAnimTime));
+                    com.android.internal.R.interpolator.decelerate_cubic));
+            anim.setDuration(250);
             // If this is being shown from the system, add a small delay.
             // This is because we will also be animating in the status bar,
             // and these two elements can't be done in lock-step.  So we give
@@ -700,9 +703,6 @@
             // the action bar animates.  (This corresponds to the corresponding
             // case when hiding, where the status bar has a small delay before
             // starting.)
-            if (fromSystem) {
-                anim.setStartDelay(100);
-            }
             anim.addListener(mShowListener);
             mCurrentShowAnim = anim;
             anim.start();
@@ -734,23 +734,26 @@
             mTopVisibilityView.setAlpha(1);
             mContainerView.setTransitioning(true);
             AnimatorSet anim = new AnimatorSet();
-            AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 0));
-            b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY",
-                    -mTopVisibilityView.getHeight()));
+            float endingY = -mTopVisibilityView.getHeight();
+            if (fromSystem) {
+                int topLeft[] = {0, 0};
+                mTopVisibilityView.getLocationInWindow(topLeft);
+                endingY -= topLeft[1];
+            }
+            AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView,
+                    "translationY", endingY));
             if (mContentView != null) {
                 b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
-                        0, -mTopVisibilityView.getHeight()));
+                        0, endingY));
             }
             if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
                 mSplitView.setAlpha(1);
-                b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0));
                 b.with(ObjectAnimator.ofFloat(mSplitView, "translationY",
                         mSplitView.getHeight()));
             }
             anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
-                    com.android.internal.R.interpolator.accelerate_quad));
-            anim.setDuration(mContext.getResources().getInteger(
-                    com.android.internal.R.integer.config_mediumAnimTime));
+                    com.android.internal.R.interpolator.accelerate_cubic));
+            anim.setDuration(250);
             anim.addListener(mHideListener);
             mCurrentShowAnim = anim;
             anim.start();
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index a22395b..b2c3091 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -419,6 +419,7 @@
             "y", 0,
             "onUpdate", mUpdateListener,
             "onComplete", finishListener));
+        mHandleAnimations.start();
     }
 
     /**
@@ -528,7 +529,6 @@
             deactivateHandle(HIDE_ANIMATION_DURATION, HIDE_ANIMATION_DELAY, 1.0f,
                     mResetListenerWithPing);
             hideTargets(true, false);
-            mHandleAnimations.start();
         }
 
         setGrabbedState(OnTriggerListener.NO_HANDLE);
diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp
index 0777ea2..3bbb8bf 100644
--- a/core/jni/android_database_SQLiteConnection.cpp
+++ b/core/jni/android_database_SQLiteConnection.cpp
@@ -41,6 +41,20 @@
 
 namespace android {
 
+/* Busy timeout in milliseconds.
+ * If another connection (possibly in another process) has the database locked for
+ * longer than this amount of time then SQLite will generate a SQLITE_BUSY error.
+ * The SQLITE_BUSY error is then raised as a SQLiteDatabaseLockedException.
+ *
+ * In ordinary usage, busy timeouts are quite rare.  Most databases only ever
+ * have a single open connection at a time unless they are using WAL.  When using
+ * WAL, a timeout could occur if one connection is busy performing an auto-checkpoint
+ * operation.  The busy timeout needs to be long enough to tolerate slow I/O write
+ * operations but not so long as to cause the application to hang indefinitely if
+ * there is a problem acquiring a database lock.
+ */
+static const int BUSY_TIMEOUT_MS = 2500;
+
 static struct {
     jfieldID name;
     jfieldID numArgs;
@@ -127,8 +141,8 @@
         return 0;
     }
 
-    // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY
-    err = sqlite3_busy_timeout(db, 1000 /* ms */);
+    // Set the default busy handler to retry automatically before returning SQLITE_BUSY.
+    err = sqlite3_busy_timeout(db, BUSY_TIMEOUT_MS);
     if (err != SQLITE_OK) {
         throw_sqlite3_exception(env, db, "Could not set busy timeout");
         sqlite3_close(db);
diff --git a/core/res/res/anim/dock_bottom_enter.xml b/core/res/res/anim/dock_bottom_enter.xml
index 74a021b..4f2f753 100644
--- a/core/res/res/anim/dock_bottom_enter.xml
+++ b/core/res/res/anim/dock_bottom_enter.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the bottom of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/decelerate_quad">
+        android:interpolator="@android:interpolator/decelerate_cubic">
     <translate android:fromYDelta="100%" android:toYDelta="0"
-        android:duration="@android:integer/config_mediumAnimTime"/>
+        android:duration="250"/>
 </set>
diff --git a/core/res/res/anim/dock_bottom_exit.xml b/core/res/res/anim/dock_bottom_exit.xml
index 213b3d9..afbe24b 100644
--- a/core/res/res/anim/dock_bottom_exit.xml
+++ b/core/res/res/anim/dock_bottom_exit.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the bottom of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/accelerate_quad">
+        android:interpolator="@android:interpolator/accelerate_cubic">
     <translate android:fromYDelta="0" android:toYDelta="100%"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
+        android:startOffset="100" android:duration="250"/>
 </set>
diff --git a/core/res/res/anim/dock_left_enter.xml b/core/res/res/anim/dock_left_enter.xml
index 4fce35a..7f5dfd5 100644
--- a/core/res/res/anim/dock_left_enter.xml
+++ b/core/res/res/anim/dock_left_enter.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the left of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/decelerate_quad">
+        android:interpolator="@android:interpolator/decelerate_cubic">
     <translate android:fromXDelta="-100%" android:toXDelta="0"
-        android:duration="@android:integer/config_mediumAnimTime"/>
+        android:duration="250"/>
 </set>
diff --git a/core/res/res/anim/dock_left_exit.xml b/core/res/res/anim/dock_left_exit.xml
index bce203d..11cbc0b3 100644
--- a/core/res/res/anim/dock_left_exit.xml
+++ b/core/res/res/anim/dock_left_exit.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the right of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/accelerate_quad">
+        android:interpolator="@android:interpolator/accelerate_cubic">
     <translate android:fromXDelta="0" android:toXDelta="-100%"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
+        android:startOffset="100" android:duration="250"/>
 </set>
diff --git a/core/res/res/anim/dock_right_enter.xml b/core/res/res/anim/dock_right_enter.xml
index 26b8ad6..a92c7d2 100644
--- a/core/res/res/anim/dock_right_enter.xml
+++ b/core/res/res/anim/dock_right_enter.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the right of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/decelerate_quad">
+        android:interpolator="@android:interpolator/decelerate_cubic">
     <translate android:fromXDelta="100%" android:toXDelta="0"
-        android:duration="@android:integer/config_mediumAnimTime"/>
+        android:duration="250"/>
 </set>
diff --git a/core/res/res/anim/dock_right_exit.xml b/core/res/res/anim/dock_right_exit.xml
index 6beda59..80e4dc3 100644
--- a/core/res/res/anim/dock_right_exit.xml
+++ b/core/res/res/anim/dock_right_exit.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the right of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/accelerate_quad">
+        android:interpolator="@android:interpolator/accelerate_cubic">
     <translate android:fromXDelta="0" android:toXDelta="100%"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
+        android:startOffset="100" android:duration="250"/>
 </set>
diff --git a/core/res/res/anim/dock_top_enter.xml b/core/res/res/anim/dock_top_enter.xml
index 594b479..1f74e48 100644
--- a/core/res/res/anim/dock_top_enter.xml
+++ b/core/res/res/anim/dock_top_enter.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the top of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/decelerate_quad">
+        android:interpolator="@android:interpolator/decelerate_cubic">
     <translate android:fromYDelta="-100%" android:toYDelta="0"
-        android:duration="@android:integer/config_mediumAnimTime"/>
+        android:duration="250"/>
 </set>
diff --git a/core/res/res/anim/dock_top_exit.xml b/core/res/res/anim/dock_top_exit.xml
index b9691f6..4d2fea94 100644
--- a/core/res/res/anim/dock_top_exit.xml
+++ b/core/res/res/anim/dock_top_exit.xml
@@ -18,7 +18,7 @@
 
 <!-- Animation for when a dock window at the top of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:interpolator/accelerate_quad">
+        android:interpolator="@android:interpolator/accelerate_cubic">
     <translate android:fromYDelta="0" android:toYDelta="-100%"
-        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
+        android:startOffset="100" android:duration="250"/>
 </set>
diff --git a/core/res/res/layout/notification_action_list.xml b/core/res/res/layout/notification_action_list.xml
index fa0a8c8..591c9ea 100644
--- a/core/res/res/layout/notification_action_list.xml
+++ b/core/res/res/layout/notification_action_list.xml
@@ -23,6 +23,7 @@
     android:visibility="gone"
     android:showDividers="middle"
     android:divider="?android:attr/listDivider"
+    android:dividerPadding="12dp"
     >
     <!-- actions will be added here -->
 </LinearLayout>
diff --git a/core/res/res/layout/notification_template_base.xml b/core/res/res/layout/notification_template_base.xml
index ed680a9..47bbbde 100644
--- a/core/res/res/layout/notification_template_base.xml
+++ b/core/res/res/layout/notification_template_base.xml
@@ -36,8 +36,7 @@
         android:layout_marginLeft="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingLeft="12dp"
-        android:paddingRight="12dp"
+        android:paddingRight="8dp"
         android:paddingTop="2dp"
         android:paddingBottom="2dp"
         android:gravity="top"
@@ -47,6 +46,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingTop="6dp"
+            android:layout_marginLeft="8dp"
             android:orientation="horizontal"
             >
             <TextView android:id="@+id/title"
@@ -81,6 +81,7 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="-2dp"
             android:layout_marginBottom="-2dp"
+            android:layout_marginLeft="8dp"
             android:singleLine="true"
             android:fadingEdge="horizontal"
             android:ellipsize="marquee"
@@ -90,24 +91,17 @@
             android:id="@android:id/progress"
             android:layout_width="match_parent"
             android:layout_height="12dp"
+            android:layout_marginLeft="8dp"
             android:visibility="gone"
             style="?android:attr/progressBarStyleHorizontal"
             />
-        <TextView android:id="@+id/overflow_title"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:fadingEdge="horizontal"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
         <LinearLayout
             android:id="@+id/line3"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:layout_marginLeft="8dp"
             >
             <TextView android:id="@+id/text"
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
@@ -130,14 +124,14 @@
                 android:paddingLeft="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
+                android:layout_marginLeft="8dp"
                 android:scaleType="centerInside"
-                android:paddingLeft="8dp"
                 android:visibility="gone"
-                android:drawableAlpha="180"
+                android:drawableAlpha="153"
                 />
         </LinearLayout>
     </LinearLayout>
diff --git a/core/res/res/layout/notification_template_big_base.xml b/core/res/res/layout/notification_template_big_base.xml
index f2c204f..69f0a24 100644
--- a/core/res/res/layout/notification_template_big_base.xml
+++ b/core/res/res/layout/notification_template_big_base.xml
@@ -33,19 +33,16 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="fill_vertical"
-        android:layout_marginLeft="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingLeft="12dp"
-        android:paddingRight="12dp"
-        android:paddingTop="2dp"
-        android:paddingBottom="2dp"
         android:gravity="top"
         >
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/notification_large_icon_width"
             android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
             android:orientation="vertical"
             >
             <LinearLayout
@@ -53,6 +50,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:paddingTop="6dp"
+                android:layout_marginRight="8dp"
+                android:layout_marginLeft="8dp"
                 android:orientation="horizontal"
                 >
                 <TextView android:id="@+id/title"
@@ -87,6 +86,8 @@
                 android:layout_height="wrap_content"
                 android:layout_marginTop="-2dp"
                 android:layout_marginBottom="-2dp"
+                android:layout_marginLeft="8dp"
+                android:layout_marginRight="8dp"
                 android:singleLine="true"
                 android:fadingEdge="horizontal"
                 android:ellipsize="marquee"
@@ -96,6 +97,8 @@
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginLeft="8dp"
+                android:layout_marginRight="8dp"
                 android:singleLine="false"
                 android:visibility="gone"
                 />
@@ -103,7 +106,10 @@
                 android:id="@+id/line3"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginLeft="8dp"
+                android:layout_marginRight="8dp"
                 android:orientation="horizontal"
+                android:gravity="center_vertical"
                 >
                 <TextView android:id="@+id/text"
                     android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
@@ -126,29 +132,38 @@
                     android:paddingLeft="8dp"
                     />
                 <ImageView android:id="@+id/right_icon"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
+                    android:layout_width="16dp"
+                    android:layout_height="16dp"
                     android:layout_gravity="center"
                     android:layout_weight="0"
+                    android:layout_marginLeft="8dp"
                     android:scaleType="centerInside"
-                    android:paddingLeft="8dp"
                     android:visibility="gone"
-                    android:drawableAlpha="180"
+                    android:drawableAlpha="153"
                     />
             </LinearLayout>
             <ProgressBar
                 android:id="@android:id/progress"
                 android:layout_width="match_parent"
                 android:layout_height="12dp"
+                android:layout_marginBottom="8dp"
+                android:layout_marginLeft="8dp"
+                android:layout_marginRight="8dp"
                 android:visibility="gone"
                 style="?android:attr/progressBarStyleHorizontal"
                 />
         </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1px"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
         <include
             layout="@layout/notification_action_list"
-            android:id="@+id/actions"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/notification_large_icon_width"
             />
     </LinearLayout>
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_big_picture.xml b/core/res/res/layout/notification_template_big_picture.xml
index 077616e..ecb3616 100644
--- a/core/res/res/layout/notification_template_big_picture.xml
+++ b/core/res/res/layout/notification_template_big_picture.xml
@@ -53,7 +53,6 @@
         <include
             layout="@layout/notification_action_list"
             android:id="@+id/actions"
-            android:layout_marginLeft="8dp"
             android:layout_gravity="bottom"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_big_text.xml b/core/res/res/layout/notification_template_big_text.xml
index 304f2b5..b86177e 100644
--- a/core/res/res/layout/notification_template_big_text.xml
+++ b/core/res/res/layout/notification_template_big_text.xml
@@ -34,8 +34,6 @@
         android:layout_gravity="fill_vertical"
         android:layout_marginLeft="@dimen/notification_large_icon_width"
         android:orientation="vertical"
-        android:paddingLeft="12dp"
-        android:paddingRight="12dp"
         android:paddingTop="2dp"
         android:paddingBottom="2dp"
         android:gravity="top"
@@ -44,6 +42,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:layout_weight="1"
             >
             <LinearLayout
@@ -87,6 +87,7 @@
                 android:layout_height="wrap_content"
                 android:layout_marginTop="-2dp"
                 android:layout_marginBottom="-2dp"
+                android:layout_marginRight="8dp"
                 android:singleLine="true"
                 android:fadingEdge="horizontal"
                 android:ellipsize="marquee"
@@ -97,6 +98,8 @@
                 android:id="@android:id/progress"
                 android:layout_width="match_parent"
                 android:layout_height="12dp"
+                android:layout_marginBottom="8dp"
+                android:layout_marginRight="8dp"
                 android:visibility="gone"
                 android:layout_weight="0"
                 style="?android:attr/progressBarStyleHorizontal"
@@ -105,7 +108,8 @@
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
                 android:layout_width="match_parent"
                 android:layout_height="0dp"
-                android:layout_marginBottom="2dp"
+                android:layout_marginBottom="8dp"
+                android:layout_marginRight="8dp"
                 android:singleLine="false"
                 android:visibility="gone"
                 android:maxLines="8"
@@ -113,6 +117,13 @@
                 android:layout_weight="1"
                 />
         </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dip"
+            android:layout_marginTop="-1px"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
         <include
             layout="@layout/notification_action_list"
             android:layout_width="match_parent"
@@ -120,22 +131,23 @@
             android:visibility="gone"
             android:layout_weight="1"
             />
-        <TextView android:id="@+id/overflow_title"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+        <ImageView
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:fadingEdge="horizontal"
-            android:visibility="gone"
-            android:layout_weight="0"
-            />
+            android:layout_height="1px"
+            android:id="@+id/overflow_divider"
+            android:layout_marginBottom="8dp"
+            android:visibility="visible"
+            android:background="?android:attr/dividerHorizontal" />
         <LinearLayout
             android:id="@+id/line3"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginLeft="8dp"
+            android:layout_marginBottom="8dp"
+            android:layout_marginRight="8dp"
             android:orientation="horizontal"
             android:layout_weight="0"
+            android:gravity="center_vertical"
             >
             <TextView android:id="@+id/text"
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
@@ -158,14 +170,14 @@
                 android:paddingLeft="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
+                android:layout_marginLeft="8dp"
                 android:scaleType="centerInside"
-                android:paddingLeft="8dp"
                 android:visibility="gone"
-                android:drawableAlpha="180"
+                android:drawableAlpha="153"
                 />
         </LinearLayout>
     </LinearLayout>
diff --git a/core/res/res/layout/notification_template_inbox.xml b/core/res/res/layout/notification_template_inbox.xml
index 121a81c..e9a3686 100644
--- a/core/res/res/layout/notification_template_inbox.xml
+++ b/core/res/res/layout/notification_template_inbox.xml
@@ -36,8 +36,6 @@
         android:layout_marginLeft="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingLeft="12dp"
-        android:paddingRight="12dp"
         android:paddingTop="2dp"
         android:paddingBottom="2dp"
         android:gravity="top"
@@ -46,6 +44,8 @@
             android:id="@+id/line1"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:paddingTop="6dp"
             android:orientation="horizontal"
             android:layout_weight="0"
@@ -82,6 +82,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="-2dp"
             android:layout_marginBottom="-2dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:fadingEdge="horizontal"
             android:ellipsize="marquee"
@@ -92,6 +94,8 @@
             android:id="@android:id/progress"
             android:layout_width="match_parent"
             android:layout_height="12dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:visibility="gone"
             android:layout_weight="0"
             style="?android:attr/progressBarStyleHorizontal"
@@ -100,6 +104,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -109,6 +115,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -118,6 +126,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -127,6 +137,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -136,6 +148,7 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -145,6 +158,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -154,6 +169,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -163,35 +180,44 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
             android:layout_weight="1"
             android:text="@android:string/ellipsis"
             />
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1px"
+            android:id="@+id/overflow_divider"
+            android:layout_marginTop="8dp"
+            android:visibility="visible"
+            android:background="?android:attr/dividerHorizontal" />
         <include
             layout="@layout/notification_action_list"
-            android:id="@+id/actions"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_weight="0"
             />
-        <TextView android:id="@+id/overflow_title"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+        <ImageView
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:fadingEdge="horizontal"
+            android:layout_height="1px"
+            android:id="@+id/action_divider"
             android:visibility="gone"
-            android:layout_weight="0"
-            />
+            android:background="?android:attr/dividerHorizontal" /><!-- note: divider below actions -->
         <LinearLayout
             android:id="@+id/line3"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginBottom="8dp"
+            android:layout_marginRight="8dp"
             android:orientation="horizontal"
             android:layout_weight="0"
+            android:gravity="center_vertical"
             >
             <TextView android:id="@+id/text"
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
@@ -214,14 +240,14 @@
                 android:paddingLeft="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
+                android:layout_marginLeft="8dp"
                 android:scaleType="centerInside"
-                android:paddingLeft="8dp"
                 android:visibility="gone"
-                android:drawableAlpha="180"
+                android:drawableAlpha="153"
                 />
         </LinearLayout>
     </LinearLayout>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a70394f..bf9fe42 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -120,7 +120,6 @@
   <java-symbol type="id" name="old_app_action" />
   <java-symbol type="id" name="old_app_description" />
   <java-symbol type="id" name="old_app_icon" />
-  <java-symbol type="id" name="overflow_title" />
   <java-symbol type="id" name="package_label" />
   <java-symbol type="id" name="packages_list" />
   <java-symbol type="id" name="pause" />
@@ -210,6 +209,8 @@
   <java-symbol type="id" name="inbox_text6" />
   <java-symbol type="id" name="inbox_more" />
   <java-symbol type="id" name="status_bar_latest_event_content" />
+  <java-symbol type="id" name="action_divider" />
+  <java-symbol type="id" name="overflow_divider" />
 
   <java-symbol type="attr" name="actionModeShareDrawable" />
   <java-symbol type="attr" name="alertDialogCenterButtons" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a54cdf1..223d17a 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -239,7 +239,7 @@
     </style>
     <!-- Notification content styles -->
     <style name="TextAppearance.StatusBar.EventContent">
-        <item name="android:textColor">#808080</item>
+        <item name="android:textColor">#999999</item>
         <item name="android:textSize">@dimen/notification_text_size</item>
     </style>
     <style name="TextAppearance.StatusBar.EventContent.Title">
@@ -253,11 +253,14 @@
     </style>
     <style name="TextAppearance.StatusBar.EventContent.Info">
         <item name="android:textSize">@dimen/notification_subtext_size</item>
-        <item name="android:textColor">#666666</item>
+        <item name="android:textColor">#999999</item>
     </style>
     <style name="TextAppearance.StatusBar.EventContent.Time">
         <item name="android:textSize">@dimen/notification_subtext_size</item>
-        <item name="android:textColor">#666666</item>
+        <item name="android:textColor">#999999</item>
+    </style>
+    <style name="TextAppearance.StatusBar.EventContent.Emphasis">
+        <item name="android:textColor">#CCCCCC</item>
     </style>
 
     <style name="TextAppearance.Small.CalendarViewWeekDayView">
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6c7c160..6b9522b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -19,6 +19,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -2376,6 +2377,42 @@
         }
     }
 
+     /**
+     * Indicate wired accessory connection state change.
+     * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx)
+     * @param state  new connection state: 1 connected, 0 disconnected
+     * @param name   device name
+     * {@hide}
+     */
+    public void setWiredDeviceConnectionState(int device, int state, String name) {
+        IAudioService service = getService();
+        try {
+            service.setWiredDeviceConnectionState(device, state, name);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
+        }
+    }
+
+     /**
+     * Indicate A2DP sink connection state change.
+     * @param device Bluetooth device connected/disconnected
+     * @param state  new connection state (BluetoothProfile.STATE_xxx)
+     * @return a delay in ms that the caller should wait before broadcasting
+     * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
+     * {@hide}
+     */
+    public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) {
+        IAudioService service = getService();
+        int delay = 0;
+        try {
+            delay = service.setBluetoothA2dpDeviceConnectionState(device, state);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e);
+        } finally {
+            return delay;
+        }
+    }
+
     /** {@hide} */
     public IRingtonePlayer getRingtonePlayer() {
         try {
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 5e338ab..84856bf 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -135,6 +135,8 @@
     private static final int MSG_RCDISPLAY_UPDATE = 13;
     private static final int MSG_SET_ALL_VOLUMES = 14;
     private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 15;
+    private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 16;
+    private static final int MSG_SET_A2DP_CONNECTION_STATE = 17;
 
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -442,15 +444,9 @@
 
         // Register for device connection intent broadcasts.
         IntentFilter intentFilter =
-                new IntentFilter(Intent.ACTION_HEADSET_PLUG);
-
-        intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
+                new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
         intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
         intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
-        intentFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
-        intentFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
-        intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
         intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
         intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
         intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
@@ -1961,7 +1957,19 @@
                 deviceList = a2dp.getConnectedDevices();
                 if (deviceList.size() > 0) {
                     btDevice = deviceList.get(0);
-                    handleA2dpConnectionStateChange(btDevice, a2dp.getConnectionState(btDevice));
+                    synchronized (mConnectedDevices) {
+                        int state = a2dp.getConnectionState(btDevice);
+                        int delay = checkSendBecomingNoisyIntent(
+                                                AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                                                (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
+                        sendMsg(mAudioHandler,
+                                MSG_SET_A2DP_CONNECTION_STATE,
+                                SENDMSG_QUEUE,
+                                state,
+                                0,
+                                btDevice,
+                                delay);
+                    }
                 }
                 break;
 
@@ -2262,6 +2270,36 @@
         return device;
     }
 
+    public void setWiredDeviceConnectionState(int device, int state, String name) {
+        synchronized (mConnectedDevices) {
+            int delay = checkSendBecomingNoisyIntent(device, state);
+            sendMsg(mAudioHandler,
+                    MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
+                    SENDMSG_QUEUE,
+                    device,
+                    state,
+                    name,
+                    delay);
+        }
+    }
+
+    public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state)
+    {
+        int delay;
+        synchronized (mConnectedDevices) {
+            delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                                            (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
+            sendMsg(mAudioHandler,
+                    MSG_SET_A2DP_CONNECTION_STATE,
+                    SENDMSG_QUEUE,
+                    state,
+                    0,
+                    device,
+                    delay);
+        }
+        return delay;
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Inner classes
     ///////////////////////////////////////////////////////////////////////////
@@ -2959,6 +2997,14 @@
                 case MSG_BT_HEADSET_CNCT_FAILED:
                     resetBluetoothSco();
                     break;
+
+                case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
+                    onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
+                    break;
+
+                case MSG_SET_A2DP_CONNECTION_STATE:
+                    onSetA2dpConnectionState((BluetoothDevice)msg.obj, msg.arg1);
+                    break;
             }
         }
     }
@@ -3020,7 +3066,6 @@
 
     // must be called synchronized on mConnectedDevices
     private void makeA2dpDeviceUnavailableNow(String address) {
-        sendBecomingNoisyIntent();
         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                 AudioSystem.DEVICE_STATE_UNAVAILABLE,
                 address);
@@ -3050,7 +3095,7 @@
         return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
     }
 
-    private void handleA2dpConnectionStateChange(BluetoothDevice btDevice, int state)
+    private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
     {
         if (btDevice == null) {
             return;
@@ -3116,6 +3161,76 @@
         return false;
     }
 
+    // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
+    // sent if none of these devices is connected.
+    int mBecomingNoisyIntentDevices =
+            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
+            AudioSystem.DEVICE_OUT_ALL_A2DP;
+
+    // must be called before removing the device from mConnectedDevices
+    private int checkSendBecomingNoisyIntent(int device, int state) {
+        int delay = 0;
+        if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
+            int devices = 0;
+            for (int dev : mConnectedDevices.keySet()) {
+                if ((dev & mBecomingNoisyIntentDevices) != 0) {
+                   devices |= dev;
+                }
+            }
+            if (devices == device) {
+                delay = 1000;
+                sendBecomingNoisyIntent();
+            }
+        }
+
+        if (mAudioHandler.hasMessages(MSG_SET_A2DP_CONNECTION_STATE) ||
+                mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
+            delay = 1000;
+        }
+        return delay;
+    }
+
+    private void sendDeviceConnectionIntent(int device, int state, String name)
+    {
+        Intent intent = new Intent();
+
+        intent.putExtra("state", state);
+        intent.putExtra("name", name);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+
+        if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
+            intent.setAction(Intent.ACTION_HEADSET_PLUG);
+            intent.putExtra("microphone", 1);
+        } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) {
+            intent.setAction(Intent.ACTION_HEADSET_PLUG);
+            intent.putExtra("microphone", 0);
+        } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) {
+            intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
+        } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
+            intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
+        } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) {
+            intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG);
+        }
+
+        ActivityManagerNative.broadcastStickyIntent(intent, null);
+    }
+
+    private void onSetWiredDeviceConnectionState(int device, int state, String name)
+    {
+        synchronized (mConnectedDevices) {
+            if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
+                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
+                setBluetoothA2dpOnInt(true);
+            }
+            handleDeviceConnection((state == 1), device, "");
+            if ((state != 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
+                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
+                setBluetoothA2dpOnInt(false);
+            }
+            sendDeviceConnectionIntent(device, state, name);
+        }
+    }
+
     /* cache of the address of the last dock the device was connected to */
     private String mDockAddress;
 
@@ -3151,12 +3266,6 @@
                         config = AudioSystem.FORCE_NONE;
                 }
                 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
-            } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
-                state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
-                                               BluetoothProfile.STATE_DISCONNECTED);
-                BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
-                handleA2dpConnectionStateChange(btDevice, state);
             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
@@ -3197,43 +3306,9 @@
                         }
                     }
                 }
-            } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
-                state = intent.getIntExtra("state", 0);
-                int microphone = intent.getIntExtra("microphone", 0);
-
-                if (microphone != 0) {
-                    device = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
-                } else {
-                    device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
-                }
-                // enable A2DP before notifying headset disconnection to avoid glitches
-                if (state == 0) {
-                    setBluetoothA2dpOnInt(true);
-                }
-                handleDeviceConnection((state == 1), device, "");
-                // disable A2DP after notifying headset connection to avoid glitches
-                if (state != 0) {
-                    setBluetoothA2dpOnInt(false);
-                }
-            } else if (action.equals(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG)) {
-                state = intent.getIntExtra("state", 0);
-                Log.v(TAG, "Broadcast Receiver: Got ACTION_ANALOG_AUDIO_DOCK_PLUG, state = "+state);
-                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, "");
-            } else if (action.equals(Intent.ACTION_HDMI_AUDIO_PLUG)) {
-                state = intent.getIntExtra("state", 0);
-                Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state);
-                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_AUX_DIGITAL, "");
-            } else if (action.equals(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG)) {
-                state = intent.getIntExtra("state", 0);
-                Log.v(TAG,
-                      "Broadcast Receiver Got ACTION_DIGITAL_AUDIO_DOCK_PLUG, state = " + state);
-                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, "");
             } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
                            action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
                 state = intent.getIntExtra("state", 0);
-                if (state == 0) {
-                    sendBecomingNoisyIntent();
-                }
                 int alsaCard = intent.getIntExtra("card", -1);
                 int alsaDevice = intent.getIntExtra("device", -1);
                 String params = (alsaCard == -1 && alsaDevice == -1 ? ""
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 7fbe28c..133f30b 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
 import android.media.IAudioFocusDispatcher;
 import android.media.IRemoteControlClient;
@@ -133,4 +134,7 @@
     void setRingtonePlayer(IRingtonePlayer player);
     IRingtonePlayer getRingtonePlayer();
     int getMasterStreamType();
+
+    void setWiredDeviceConnectionState(int device, int state, String name);
+    int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state);
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index 62462bd..6995c60 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -415,59 +415,61 @@
         output.write("Total number of loops: " + NUMBER_OF_TIME_LAPSE_LOOPS + "\n");
 
         try {
-            output.write("No of loop: ");
-            for (int i = 0; i < NUMBER_OF_TIME_LAPSE_LOOPS; i++) {
-                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
-                Log.v(TAG, filename);
-                runOnLooper(new Runnable() {
-                    @Override
-                    public void run() {
-                        mRecorder = new MediaRecorder();
+            for (int j = 0, n = Camera.getNumberOfCameras(); j < n; j++) {
+                output.write("No of loop: camera " + j);
+                for (int i = 0; i < NUMBER_OF_TIME_LAPSE_LOOPS; i++) {
+                    filename = OUTPUT_FILE + j + "_" + i + OUTPUT_FILE_EXT;
+                    Log.v(TAG, filename);
+                    runOnLooper(new Runnable() {
+                        @Override
+                        public void run() {
+                            mRecorder = new MediaRecorder();
+                        }
+                    });
+
+                    // Set callback
+                    mRecorder.setOnErrorListener(mRecorderErrorCallback);
+
+                    // Set video source
+                    mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+
+                    // Set camcorder profile for time lapse
+                    CamcorderProfile profile =
+                        CamcorderProfile.get(j, CamcorderProfile.QUALITY_TIME_LAPSE_HIGH);
+                    mRecorder.setProfile(profile);
+
+                    // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc.
+                    // http://developer.android.com/guide/topics/media/camera.html#time-lapse-video
+                    mRecorder.setCaptureRate(captureRate);
+
+                    // Set output file
+                    mRecorder.setOutputFile(filename);
+
+                    // Set the preview display
+                    Log.v(TAG, "mediaRecorder setPreviewDisplay");
+                    mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+
+                    mRecorder.prepare();
+                    mRecorder.start();
+                    Thread.sleep(record_duration);
+                    Log.v(TAG, "Before stop");
+                    mRecorder.stop();
+                    mRecorder.release();
+
+                    // Start the playback
+                    MediaPlayer mp = new MediaPlayer();
+                    mp.setDataSource(filename);
+                    mp.setDisplay(mSurfaceHolder);
+                    mp.prepare();
+                    mp.start();
+                    Thread.sleep(TIME_LAPSE_PLAYBACK_WAIT_TIME);
+                    mp.release();
+                    validateRecordedVideo(filename);
+                    if (remove_video) {
+                        removeRecordedVideo(filename);
                     }
-                });
-
-                // Set callback
-                mRecorder.setOnErrorListener(mRecorderErrorCallback);
-
-                // Set video source
-                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
-
-                // Set camcorder profile for time lapse
-                CamcorderProfile profile =
-                        CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH);
-                mRecorder.setProfile(profile);
-
-                // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc.
-                // http://developer.android.com/guide/topics/media/camera.html#time-lapse-video
-                mRecorder.setCaptureRate(captureRate);
-
-                // Set output file
-                mRecorder.setOutputFile(filename);
-
-                // Set the preview display
-                Log.v(TAG, "mediaRecorder setPreviewDisplay");
-                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
-
-                mRecorder.prepare();
-                mRecorder.start();
-                Thread.sleep(record_duration);
-                Log.v(TAG, "Before stop");
-                mRecorder.stop();
-                mRecorder.release();
-
-                // Start the playback
-                MediaPlayer mp = new MediaPlayer();
-                mp.setDataSource(filename);
-                mp.setDisplay(mSurfaceHolder);
-                mp.prepare();
-                mp.start();
-                Thread.sleep(TIME_LAPSE_PLAYBACK_WAIT_TIME);
-                mp.release();
-                validateRecordedVideo(filename);
-                if(remove_video) {
-                  removeRecordedVideo(filename);
+                    output.write(", " + i);
                 }
-                output.write(", " + i);
             }
         }
         catch (IllegalStateException e) {
diff --git a/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png
index 8a0a30f..ff0bd4c 100644
--- a/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png
index 25f15e6..2bbb2c6 100644
--- a/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png
index 2ff93d3..e7caeda 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png
index 430f913..ae07083 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png
index 807241a..8423ef9 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png
index 2ff93d3..0c20ba2 100644
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png
index 430f913..56cd238 100644
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png
index 807241a..3f05767 100644
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png
index 60e7418..932e0ef 100644
--- a/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6433cd3..ca29738 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -145,6 +145,6 @@
     <string name="notifications_off_title" msgid="8936620513608443224">"通知功能已停用"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"点按此处可重新启用通知功能。"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
-    <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕锁定为横向浏览模式。"</string>
-    <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕已锁定为纵向浏览模式。"</string>
+    <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕锁定为横向模式。"</string>
+    <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕锁定为纵向模式。"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
index 1db2a7f..73249b4 100644
--- a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
+++ b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
@@ -58,8 +58,8 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final boolean activateOnDock = 0 != Settings.Secure.getInt(
-                context.getContentResolver(), 
-                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 1);
+                context.getContentResolver(),
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 0);
 
             if (!activateOnDock) return;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 89bf3b6..587bfe8 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -309,7 +309,7 @@
 
             // if there are no apps, either bring up a "No recent apps" message, or just
             // quit early
-            boolean noApps = (mRecentTaskDescriptions.size() == 0);
+            boolean noApps = !mFirstScreenful && (mRecentTaskDescriptions.size() == 0);
             if (mRecentsNoApps != null) {
                 mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 3c71784..f682203 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -101,6 +101,9 @@
             }
 
             final View view = mAdapter.getView(i, old, mLinearLayout);
+            if (view.getParent() != null) {
+                throw new RuntimeException("Recycled child has parent");
+            }
 
             if (mPerformanceHelper != null) {
                 mPerformanceHelper.addViewCallback(view);
@@ -139,6 +142,9 @@
             thumbnailView.setClickable(true);
             thumbnailView.setOnClickListener(launchAppListener);
             thumbnailView.setOnLongClickListener(longClickListener);
+            if (view.getParent() != null) {
+                throw new RuntimeException("Recycled child has parent");
+            }
 
             // We don't want to dismiss recents if a user clicks on the app title
             // (we also don't want to launch the app either, though, because the
@@ -148,6 +154,9 @@
             appTitle.setOnTouchListener(noOpListener);
             final View calloutLine = view.findViewById(R.id.recents_callout_line);
             calloutLine.setOnTouchListener(noOpListener);
+            if (view.getParent() != null) {
+                throw new RuntimeException("Recycled child has parent");
+            }
 
             mLinearLayout.addView(view);
         }
diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
index 737ea47..22b854e 100644
--- a/policy/src/com/android/internal/policy/impl/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
@@ -468,7 +468,8 @@
             if (!mServiceRunning) {
                 Log.d(TAG, "Starting Face Unlock");
                 try {
-                    mService.startUi(windowToken, x, y, w, h, false);
+                    mService.startUi(windowToken, x, y, w, h,
+                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
                 } catch (RemoteException e) {
                     Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
                     return;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index cce55d5..1033296 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2278,7 +2278,12 @@
                 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
                 int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
                 if (mHdmiPlugged) {
-                    if (top > mExternalDisplayHeight) {
+                    // Move the nav bar up if the external display is the same aspect ratio
+                    // but shorter.  This avoids clipping on the external display.
+                    boolean sameAspect = mExternalDisplayHeight > 0 && displayHeight > 0
+                        && ((float) mExternalDisplayWidth / mExternalDisplayHeight > 1)
+                        == ((float) displayWidth / displayHeight > 1);
+                    if (sameAspect && top > mExternalDisplayHeight) {
                         top = mExternalDisplayHeight;
                     }
                 }
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 38e08ae..469b4f1 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2242,7 +2242,9 @@
                     } else {
                         newValue = endValue;
                         mHighestLightSensorValue = endSensorValue;
-                        mInitialAnimation = false;
+                        if (endValue > 0) {
+                            mInitialAnimation = false;
+                        }
                     }
 
                     if (mDebugLightAnimation) {
@@ -2290,7 +2292,7 @@
                 currentMask = mask;
                 duration = (int) (mWindowScaleAnimation * animationDuration);
                 startTimeMillis = SystemClock.elapsedRealtime();
-                mInitialAnimation = currentValue == 0 && target > 0;
+                mInitialAnimation = mInitialAnimation && target > 0;
 
                 if (mDebugLightAnimation) {
                     Slog.v(TAG, "animateTo(target=" + target
@@ -2608,7 +2610,8 @@
         }
     };
 
-    private boolean mInitialAnimation; // used to prevent lightsensor changes while turning on
+    /** used to prevent lightsensor changes while turning on. */
+    private boolean mInitialAnimation = true;
 
     private void dockStateChanged(int state) {
         synchronized (mLocks) {
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index c936ef9..d1f92a7 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -65,7 +65,7 @@
 
     // Enable launching of applications when entering the dock.
     private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
-    private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = false;
+    private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
 
     private static final int MSG_UPDATE_TWILIGHT = 0;
     private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
@@ -120,7 +120,7 @@
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
         return intent;
     }
-    
+
     // The broadcast receiver which receives the result of the ordered broadcast sent when
     // the dock state changes. The original ordered broadcast is sent with an initial result
     // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
@@ -130,7 +130,7 @@
         public void onReceive(Context context, Intent intent) {
             if (getResultCode() != Activity.RESULT_OK) {
                 if (LOG) {
-                    Slog.v(TAG, "Handling broadcast result for action " + intent.getAction() 
+                    Slog.v(TAG, "Handling broadcast result for action " + intent.getAction()
                             + ": canceled: " + getResultCode());
                 }
                 return;
@@ -138,7 +138,7 @@
 
             final int  enableFlags = intent.getIntExtra("enableFlags", 0);
             final int  disableFlags = intent.getIntExtra("disableFlags", 0);
-            
+
             synchronized (mLock) {
                 // Launch a dock activity
                 String category = null;
@@ -166,15 +166,15 @@
 
                 if (LOG) {
                     Slog.v(TAG, String.format(
-                        "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s", 
+                        "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s",
                         intent.getAction(), enableFlags, disableFlags, category));
                 }
-                
+
                 if (category != null) {
                     // This is the new activity that will serve as home while
                     // we are in care mode.
                     Intent homeIntent = buildHomeIntent(category);
-                    
+
                     // Now we are going to be careful about switching the
                     // configuration and starting the activity -- we need to
                     // do this in a specific order under control of the
@@ -479,8 +479,8 @@
         }
 
         if (LOG) {
-            Slog.d(TAG, 
-                "updateConfigurationLocked: mDockState=" + mDockState 
+            Slog.d(TAG,
+                "updateConfigurationLocked: mDockState=" + mDockState
                 + "; mCarMode=" + mCarModeEnabled
                 + "; mNightMode=" + mNightMode
                 + "; uiMode=" + uiMode);
@@ -657,7 +657,7 @@
         boolean mNetworkListenerEnabled;
         boolean mDidFirstInit;
         long mLastNetworkRegisterTime = -MIN_LOCATION_UPDATE_MS;
-        
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -682,12 +682,12 @@
                         // since we last requested an update.
                         return;
                     }
-                    
+
                     // Unregister the current location monitor, so we can
                     // register a new one for it to get an immediate update.
                     mNetworkListenerEnabled = false;
                     mLocationManager.removeUpdates(mEmptyLocationListener);
-                    
+
                     // Fall through to re-register listener.
                 case MSG_ENABLE_LOCATION_UPDATES:
                     // enable network provider to receive at least location updates for a given
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 53d1f0e..96ac493 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -139,11 +139,14 @@
     private final Context mContext;
     private final WakeLock mWakeLock;  // held while there is a pending route change
 
+    private final AudioManager mAudioManager;
+
     public WiredAccessoryObserver(Context context) {
         mContext = context;
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver");
         mWakeLock.setReferenceCounted(false);
+        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
 
         context.registerReceiver(new BootCompletedReceiver(),
             new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
@@ -250,106 +253,65 @@
         mPrevHeadsetState = mHeadsetState;
         mHeadsetState = headsetState;
 
-        if (headsetState == 0) {
-            if (mContext.getResources().getBoolean(
-                    com.android.internal.R.bool.config_sendAudioBecomingNoisy)) {
-                Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
-                mContext.sendBroadcast(intent);
-            }
-
-            // It can take hundreds of ms flush the audio pipeline after
-            // apps pause audio playback, but audio route changes are
-            // immediate, so delay the route change by 1000ms.
-            // This could be improved once the audio sub-system provides an
-            // interface to clear the audio pipeline.
-            delay = 1000;
-        } else {
-            // Insert the same delay for headset connection so that the connection event is not
-            // broadcast before the disconnection event in case of fast removal/insertion
-            if (mHandler.hasMessages(0)) {
-                delay = 1000;
-            }
-        }
         mWakeLock.acquire();
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(0,
-                                                           mHeadsetState,
-                                                           mPrevHeadsetState,
-                                                           mHeadsetName),
-                                    delay);
+        mHandler.sendMessage(mHandler.obtainMessage(0,
+                                                    mHeadsetState,
+                                                    mPrevHeadsetState,
+                                                    mHeadsetName));
     }
 
-    private synchronized final void sendIntents(int headsetState, int prevHeadsetState, String headsetName) {
+    private synchronized final void setDevicesState(int headsetState,
+                                                    int prevHeadsetState,
+                                                    String headsetName) {
         int allHeadsets = SUPPORTED_HEADSETS;
         for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
             if ((curHeadset & allHeadsets) != 0) {
-                sendIntent(curHeadset, headsetState, prevHeadsetState, headsetName);
+                setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName);
                 allHeadsets &= ~curHeadset;
             }
         }
     }
 
-    private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
+    private final void setDeviceState(int headset,
+                                      int headsetState,
+                                      int prevHeadsetState,
+                                      String headsetName) {
         if ((headsetState & headset) != (prevHeadsetState & headset)) {
+            int device;
+            int state;
 
-            int state = 0;
             if ((headsetState & headset) != 0) {
                 state = 1;
+            } else {
+                state = 0;
             }
-            if((headset == BIT_USB_HEADSET_ANLG) || (headset == BIT_USB_HEADSET_DGTL) ||
-               (headset == BIT_HDMI_AUDIO)) {
-                Intent intent;
 
-                //  Pack up the values and broadcast them to everyone
-                if (headset == BIT_USB_HEADSET_ANLG) {
-                    intent = new Intent(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
-                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                    intent.putExtra("state", state);
-                    intent.putExtra("name", headsetName);
-                    ActivityManagerNative.broadcastStickyIntent(intent, null);
-                } else if (headset == BIT_USB_HEADSET_DGTL) {
-                    intent = new Intent(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
-                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                    intent.putExtra("state", state);
-                    intent.putExtra("name", headsetName);
-                    ActivityManagerNative.broadcastStickyIntent(intent, null);
-                } else if (headset == BIT_HDMI_AUDIO) {
-                    intent = new Intent(Intent.ACTION_HDMI_AUDIO_PLUG);
-                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                    intent.putExtra("state", state);
-                    intent.putExtra("name", headsetName);
-                    ActivityManagerNative.broadcastStickyIntent(intent, null);
-                }
-
-                if (LOG) Slog.v(TAG, "Intent.ACTION_USB_HEADSET_PLUG: state: "+state+" name: "+headsetName);
-                // TODO: Should we require a permission?
+            if (headset == BIT_HEADSET) {
+                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
+            } else if (headset == BIT_HEADSET_NO_MIC){
+                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
+            } else if (headset == BIT_USB_HEADSET_ANLG) {
+                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
+            } else if (headset == BIT_USB_HEADSET_DGTL) {
+                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
+            } else if (headset == BIT_HDMI_AUDIO) {
+                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
+            } else {
+                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
+                return;
             }
-            if((headset == BIT_HEADSET) || (headset == BIT_HEADSET_NO_MIC)) {
 
-                //  Pack up the values and broadcast them to everyone
-                Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                //int state = 0;
-                int microphone = 0;
+            if (LOG)
+                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
 
-                if ((headset & HEADSETS_WITH_MIC) != 0) {
-                    microphone = 1;
-                }
-
-                intent.putExtra("state", state);
-                intent.putExtra("name", headsetName);
-                intent.putExtra("microphone", microphone);
-
-                if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone);
-                // TODO: Should we require a permission?
-                ActivityManagerNative.broadcastStickyIntent(intent, null);
-            }
+            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
         }
     }
 
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            sendIntents(msg.arg1, msg.arg2, (String)msg.obj);
+            setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
             mWakeLock.release();
         }
     };
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 039efbd..3e8f512 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -104,10 +104,14 @@
     private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
         "registerUiTestAutomationService";
 
+    private static final char COMPONENT_NAME_SEPARATOR = ':';
+
     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
 
     private static final int MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG = 1;
 
+    private static final int MSG_TOGGLE_TOUCH_EXPLORATION = 2;
+
     private static int sIdCounter = 0;
 
     private static int sNextWindowId;
@@ -127,12 +131,14 @@
 
     private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
 
+    private final Set<ComponentName> mTouchExplorationGrantedServices = new HashSet<ComponentName>();
+
     private final SparseArray<AccessibilityConnectionWrapper> mWindowIdToInteractionConnectionWrapperMap =
         new SparseArray<AccessibilityConnectionWrapper>();
 
     private final SparseArray<IBinder> mWindowIdToWindowTokenMap = new SparseArray<IBinder>();
 
-    private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(':');
+    private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
 
     private final Rect mTempRect = new Rect();
 
@@ -164,6 +170,8 @@
 
     private boolean mTouchExplorationGestureStarted;
 
+    private AlertDialog mEnableTouchExplorationDialog;
+
     /**
      * Creates a new instance.
      *
@@ -208,7 +216,16 @@
                         String compPkg = comp.getPackageName();
                         if (compPkg.equals(packageName)) {
                             it.remove();
-                            updateEnabledAccessibilitySerivcesSettingLocked(mEnabledServices);
+                            // Update the enabled services setting.
+                            persistComponentNamesToSettingLocked(
+                                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                                    mEnabledServices);
+                            // Update the touch exploration granted services setting.
+                            mTouchExplorationGrantedServices.remove(comp);
+                            persistComponentNamesToSettingLocked(
+                                    Settings.Secure.
+                                            TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                                    mEnabledServices);
                             return;
                         }
                     }
@@ -219,7 +236,6 @@
             public boolean onHandleForceStop(Intent intent, String[] packages,
                     int uid, boolean doit) {
                 synchronized (mLock) {
-                    boolean changed = false;
                     Iterator<ComponentName> it = mEnabledServices.iterator();
                     while (it.hasNext()) {
                         ComponentName comp = it.next();
@@ -230,13 +246,12 @@
                                     return true;
                                 }
                                 it.remove();
-                                changed = true;
+                                persistComponentNamesToSettingLocked(
+                                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                                        mEnabledServices);
                             }
                         }
                     }
-                    if (changed) {
-                        updateEnabledAccessibilitySerivcesSettingLocked(mEnabledServices);
-                    }
                     return false;
                 }
             }
@@ -248,33 +263,19 @@
                         // We will update when the automation service dies.
                         if (mUiAutomationService == null) {
                             populateAccessibilityServiceListLocked();
+                            populateEnabledAccessibilityServicesLocked();
+                            populateTouchExplorationGrantedAccessibilityServicesLocked();
                             handleAccessibilityEnabledSettingChangedLocked();
                             handleTouchExplorationEnabledSettingChangedLocked();
                             updateInputFilterLocked();
                             sendStateToClientsLocked();
                         }
                     }
-
                     return;
                 }
 
                 super.onReceive(context, intent);
             }
-
-            private void updateEnabledAccessibilitySerivcesSettingLocked(
-                    Set<ComponentName> enabledServices) {
-                Iterator<ComponentName> it = enabledServices.iterator();
-                StringBuilder str = new StringBuilder();
-                while (it.hasNext()) {
-                    if (str.length() > 0) {
-                        str.append(':');
-                    }
-                    str.append(it.next().flattenToShortString());
-                }
-                Settings.Secure.putString(mContext.getContentResolver(),
-                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                        str.toString());
-            }
         };
 
         // package changes
@@ -338,6 +339,25 @@
                     synchronized (mLock) {
                         // We will update when the automation service dies.
                         if (mUiAutomationService == null) {
+                            populateEnabledAccessibilityServicesLocked();
+                            manageServicesLocked();
+                        }
+                    }
+                }
+            });
+
+        Uri touchExplorationGrantedServicesUri = Settings.Secure.getUriFor(
+                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
+        contentResolver.registerContentObserver(touchExplorationGrantedServicesUri, false,
+            new ContentObserver(new Handler()) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    super.onChange(selfChange);
+                    synchronized (mLock) {
+                        // We will update when the automation service dies.
+                        if (mUiAutomationService == null) {
+                            populateTouchExplorationGrantedAccessibilityServicesLocked();
+                            unbindAllServicesLocked();
                             manageServicesLocked();
                         }
                     }
@@ -647,6 +667,18 @@
         }
     }
 
+    private void populateEnabledAccessibilityServicesLocked() {
+        populateComponentNamesFromSettingLocked(
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                mEnabledServices);
+    }
+
+    private void populateTouchExplorationGrantedAccessibilityServicesLocked() {
+        populateComponentNamesFromSettingLocked(
+                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                mTouchExplorationGrantedServices);
+    }
+
     /**
      * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
      * and denotes the period after the last event before notifying the service.
@@ -689,7 +721,7 @@
             mServices.add(service);
             mComponentNameToServiceMap.put(service.mComponentName, service);
             updateInputFilterLocked();
-            tryEnableTouchExploration(service);
+            tryEnableTouchExplorationLocked(service);
         } catch (RemoteException e) {
             /* do nothing */
         }
@@ -710,7 +742,7 @@
         service.unlinkToOwnDeath();
         service.dispose();
         updateInputFilterLocked();
-        tryDisableTouchExploration(service);
+        tryDisableTouchExplorationLocked(service);
         return removed;
     }
 
@@ -762,7 +794,6 @@
      * Manages services by starting enabled ones and stopping disabled ones.
      */
     private void manageServicesLocked() {
-        populateEnabledServicesLocked(mEnabledServices);
         final int enabledInstalledServicesCount = updateServicesStateLocked(mInstalledServices,
                 mEnabledServices);
         // No enabled installed services => disable accessibility to avoid
@@ -789,20 +820,21 @@
     }
 
     /**
-     * Populates a list with the {@link ComponentName}s of all enabled
-     * {@link AccessibilityService}s.
+     * Populates a set with the {@link ComponentName}s stored in a colon
+     * separated value setting.
      *
-     * @param enabledServices The list.
+     * @param settingName The setting to parse.
+     * @param outComponentNames The output component names.
      */
-    private void populateEnabledServicesLocked(Set<ComponentName> enabledServices) {
-        enabledServices.clear();
+    private void populateComponentNamesFromSettingLocked(String settingName,
+            Set<ComponentName> outComponentNames) {
+        outComponentNames.clear();
 
-        String servicesValue = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+        String settingValue = Settings.Secure.getString(mContext.getContentResolver(), settingName);
 
-        if (servicesValue != null) {
+        if (settingValue != null) {
             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
-            splitter.setString(servicesValue);
+            splitter.setString(settingValue);
             while (splitter.hasNext()) {
                 String str = splitter.next();
                 if (str == null || str.length() <= 0) {
@@ -810,13 +842,32 @@
                 }
                 ComponentName enabledService = ComponentName.unflattenFromString(str);
                 if (enabledService != null) {
-                    enabledServices.add(enabledService);
+                    outComponentNames.add(enabledService);
                 }
             }
         }
     }
 
     /**
+     * Persists the component names in the specified setting in a
+     * colon separated fashion.
+     *
+     * @param settingName The setting name.
+     * @param componentNames The component names.
+     */
+    private void persistComponentNamesToSettingLocked(String settingName,
+            Set<ComponentName> componentNames) {
+        StringBuilder builder = new StringBuilder();
+        for (ComponentName componentName : componentNames) {
+            if (builder.length() > 0) {
+                builder.append(COMPONENT_NAME_SEPARATOR);
+            }
+            builder.append(componentName.flattenToShortString());
+        }
+        Settings.Secure.putString(mContext.getContentResolver(), settingName, builder.toString());
+    }
+
+    /**
      * Updates the state of each service by starting (or keeping running) enabled ones and
      * stopping the rest.
      *
@@ -935,20 +986,21 @@
                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
     }
 
-    private void tryEnableTouchExploration(final Service service) {
+    private void tryEnableTouchExplorationLocked(final Service service) {
         if (!mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) {
-            if (!service.mIsAutomation) {
+            final boolean canToggleTouchExploration = mTouchExplorationGrantedServices.contains(
+                    service.mComponentName);
+            if (!service.mIsAutomation && !canToggleTouchExploration) {
                 mMainHandler.obtainMessage(MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG,
                         service).sendToTarget();
             } else {
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1);
+                mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 1, 0).sendToTarget();
             }
         }
     }
 
-    private void tryDisableTouchExploration(Service service) {
-        if (mIsTouchExplorationEnabled && service.mReqeustTouchExplorationMode) {
+    private void tryDisableTouchExplorationLocked(Service service) {
+        if (mIsTouchExplorationEnabled) {
             synchronized (mLock) {
                 final int serviceCount = mServices.size();
                 for (int i = 0; i < serviceCount; i++) {
@@ -957,8 +1009,7 @@
                         return;
                     }
                 }
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0);
+                mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 0, 0).sendToTarget();
             }
         }
     }
@@ -995,32 +1046,54 @@
         public void handleMessage(Message msg) {
             final int type = msg.what;
             switch (type) {
+                case MSG_TOGGLE_TOUCH_EXPLORATION: {
+                    final int value = msg.arg1;
+                    Settings.Secure.putInt(mContext.getContentResolver(),
+                            Settings.Secure.TOUCH_EXPLORATION_ENABLED, value);
+                } break;
                 case MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG: {
-                    Service service = (Service) msg.obj;
+                    final Service service = (Service) msg.obj;
                     String label = service.mResolveInfo.loadLabel(
                             mContext.getPackageManager()).toString();
-                    final AlertDialog dialog = new AlertDialog.Builder(mContext)
-                        .setIcon(android.R.drawable.ic_dialog_alert)
-                        .setPositiveButton(android.R.string.ok, new OnClickListener() {
-                            @Override
-                            public void onClick(DialogInterface dialog, int which) {
-                                Settings.Secure.putInt(mContext.getContentResolver(),
-                                        Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1);
-                            }
-                        })
-                        .setNegativeButton(android.R.string.cancel, new OnClickListener() {
-                            @Override
-                            public void onClick(DialogInterface dialog, int which) {
-                                dialog.dismiss();
-                            }
-                        })
-                        .setTitle(R.string.enable_explore_by_touch_warning_title)
-                        .setMessage(mContext.getString(
-                            R.string.enable_explore_by_touch_warning_message, label))
-                        .create();
-                    dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
-                    dialog.setCanceledOnTouchOutside(true);
-                    dialog.show();
+                    synchronized (mLock) {
+                        if (mIsTouchExplorationEnabled) {
+                            return;
+                        }
+                        if (mEnableTouchExplorationDialog != null
+                                && mEnableTouchExplorationDialog.isShowing()) {
+                            return;
+                        }
+                        mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
+                            .setIcon(android.R.drawable.ic_dialog_alert)
+                            .setPositiveButton(android.R.string.ok, new OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialog, int which) {
+                                    // The user allowed the service to toggle touch exploration.
+                                    mTouchExplorationGrantedServices.add(service.mComponentName);
+                                    persistComponentNamesToSettingLocked(
+                                            Settings.Secure.
+                                                   TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                                            mTouchExplorationGrantedServices);
+                                    // Enable touch exploration.
+                                    Settings.Secure.putInt(mContext.getContentResolver(),
+                                            Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1);
+                                }
+                            })
+                            .setNegativeButton(android.R.string.cancel, new OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialog, int which) {
+                                    dialog.dismiss();
+                                }
+                            })
+                            .setTitle(R.string.enable_explore_by_touch_warning_title)
+                            .setMessage(mContext.getString(
+                                R.string.enable_explore_by_touch_warning_message, label))
+                            .create();
+                        mEnableTouchExplorationDialog.getWindow().setType(
+                                WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
+                        mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
+                        mEnableTouchExplorationDialog.show();
+                    }
                 }
             }
         }
@@ -1143,8 +1216,16 @@
             mRequestTouchExplorationMode = (info.flags
                     & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
 
+            // If this service is up and running we may have to enable touch
+            // exploration, otherwise this will happen when the service connects.
             synchronized (mLock) {
-                tryAddServiceLocked(this);
+                if (isConfigured()) {
+                    if (mRequestTouchExplorationMode) {
+                        tryEnableTouchExplorationLocked(this);
+                    } else {
+                        tryDisableTouchExplorationLocked(this);
+                    }
+                }
             }
         }
 
@@ -1496,6 +1577,9 @@
                 if (mIsAutomation) {
                     mUiAutomationService = null;
 
+                    populateEnabledAccessibilityServicesLocked();
+                    populateTouchExplorationGrantedAccessibilityServicesLocked();
+
                     handleAccessibilityEnabledSettingChangedLocked();
                     sendStateToClientsLocked();
 
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index b0b2b8d..4c38ab9 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -1532,7 +1532,7 @@
          */
         public ReceivedPointerTracker(Context context) {
             mThresholdActivePointer =
-                ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;
+                ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;//Heie govna
         }
 
         /**
diff --git a/services/java/com/android/server/am/ContentProviderConnection.java b/services/java/com/android/server/am/ContentProviderConnection.java
index 84f8f02..7f69b24 100644
--- a/services/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/java/com/android/server/am/ContentProviderConnection.java
@@ -17,6 +17,8 @@
 package com.android.server.am;
 
 import android.os.Binder;
+import android.os.SystemClock;
+import android.util.TimeUtils;
 
 /**
  * Represents a link between a content provider and client.
@@ -24,6 +26,7 @@
 public class ContentProviderConnection extends Binder {
     public final ContentProviderRecord provider;
     public final ProcessRecord client;
+    public final long createTime;
     public int stableCount;
     public int unstableCount;
     // The client of this connection is currently waiting for the provider to appear.
@@ -39,6 +42,7 @@
     public ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client) {
         provider = _provider;
         client = _client;
+        createTime = SystemClock.elapsedRealtime();
     }
 
     public String toString() {
@@ -83,5 +87,8 @@
         if (dead) {
             sb.append(" DEAD");
         }
+        long nowReal = SystemClock.elapsedRealtime();
+        sb.append(" ");
+        TimeUtils.formatDuration(nowReal-createTime, sb);
     }
 }
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index d85facc..bdd0aa4 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -592,7 +592,7 @@
                 deviceIdAndGeneration[i * 2] = inputDevice.getId();
                 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
 
-                if (isFullKeyboard(inputDevice)) {
+                if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
                     if (!containsInputDeviceWithDescriptor(oldInputDevices,
                             inputDevice.getDescriptor())) {
                         mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice);
@@ -695,12 +695,6 @@
         reloadKeyboardLayouts();
     }
 
-    private static boolean isFullKeyboard(InputDevice inputDevice) {
-        return !inputDevice.isVirtual()
-                && (inputDevice.getSources() & InputDevice.SOURCE_KEYBOARD) != 0
-                && inputDevice.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC;
-    }
-
     private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
             String descriptor) {
         final int numDevices = inputDevices.length;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 4ce8c97..10919f2 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -6466,17 +6466,18 @@
                                     WindowManagerPolicy.PRESENCE_INTERNAL;
 
                     if (mIsTouchDevice) {
-                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) != 0) {
+                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
+                                InputDevice.SOURCE_TOUCHSCREEN) {
                             config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
                         }
                     } else {
                         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
                     }
 
-                    if ((sources & InputDevice.SOURCE_TRACKBALL) != 0) {
+                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
                         config.navigation = Configuration.NAVIGATION_TRACKBALL;
                         navigationPresence |= presenceFlag;
-                    } else if ((sources & InputDevice.SOURCE_DPAD) != 0
+                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
                             && config.navigation == Configuration.NAVIGATION_NONAV) {
                         config.navigation = Configuration.NAVIGATION_DPAD;
                         navigationPresence |= presenceFlag;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 04ec820..9e5e84b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -226,7 +226,7 @@
     ALOGD("nuSensorService thread starting...");
 
     const size_t numEventMax = 16;
-    const size_t minBufferSize = numEventMax * mVirtualSensorList.size();
+    const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size();
     sensors_event_t buffer[minBufferSize];
     sensors_event_t scratch[minBufferSize];
     SensorDevice& device(SensorDevice::getInstance());
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 5220d04..1a42f93 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -263,12 +263,19 @@
                 Context.CONNECTIVITY_SERVICE);
         sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false);
 
-        // Disable for wifi only devices.
-        if (Settings.Secure.getString(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON) == null
-                && sWifiOnly) {
-            log("Disabling watchog for wi-fi only device");
-            putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, false);
+        // Watchdog is always enabled. Poor network detection & walled garden detection
+        // can individually be turned on/off
+        // TODO: Remove this setting & clean up state machine since we always have
+        // watchdog in an enabled state
+        putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true);
+
+        // Disable poor network avoidance, but keep watchdog active for walled garden detection
+        if (sWifiOnly) {
+            log("Disabling poor network avoidance for wi-fi only device");
+            putSettingsBoolean(contentResolver,
+                    Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, false);
         }
+
         WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
         wwsm.start();
         return wwsm;